From 73366c1131f4769db1a46e42347a1d73a93d1a08 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 10 Jun 2022 13:47:46 -0400 Subject: [PATCH 001/283] Add bip340 hash signing subroutine --- bitcoin/signature.c | 21 +++++++++++++++++++++ bitcoin/signature.h | 20 ++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 4e0cda8ada98..f91ef6ec2bcd 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -124,6 +124,27 @@ void sign_hash(const struct privkey *privkey, assert(ok); } +void bip340_sign_hash(const struct privkey *privkey, + const struct sha256_double *hash, + struct bip340sig *sig) +{ + bool ok; + secp256k1_keypair keypair; + + ok = secp256k1_keypair_create(secp256k1_ctx, + &keypair, + privkey->secret.data); + + assert(ok); + + ok = secp256k1_schnorrsig_sign32(secp256k1_ctx, + sig->u8, + hash->sha.u.u8, + &keypair, /* aux_rand32 */ NULL); + + assert(ok); +} + void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, const u8 *script, enum sighash_type sighash_type, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 29d368148430..25f7774e0f9f 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -4,6 +4,7 @@ #include #include #include +#include struct sha256_double; struct sha256_ctx; @@ -19,6 +20,11 @@ enum sighash_type { SIGHASH_ANYONECANPAY = 0x80 }; +/* Schnorr */ +struct bip340sig { + u8 u8[64]; +}; + #define SIGHASH_MASK 0x7F static inline bool sighash_single(enum sighash_type sighash_type) @@ -71,6 +77,16 @@ void sign_hash(const struct privkey *p, const struct sha256_double *h, secp256k1_ecdsa_signature *sig); +/** + * bip340_sigh_hash - produce a raw BIP340 signature + * @privkey: secret key + * @hash: hash to sign. + * @sig: signature to fill and return + */ +void bip340_sign_hash(const struct privkey *privkey, + const struct sha256_double *hash, + struct bip340sig *sig); + /** * check_signed_hash - check a raw secp256k1 signature. * @h: hash which was signed. @@ -132,10 +148,6 @@ void towire_bitcoin_signature(u8 **pptr, const struct bitcoin_signature *sig); void fromwire_bitcoin_signature(const u8 **cursor, size_t *max, struct bitcoin_signature *sig); -/* Schnorr */ -struct bip340sig { - u8 u8[64]; -}; void towire_bip340sig(u8 **pptr, const struct bip340sig *bip340sig); void fromwire_bip340sig(const u8 **cursor, size_t *max, struct bip340sig *bip340sig); From 18220e4a4faf6073f5842f947d71cdbcb97267e8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 10 Jun 2022 15:49:21 -0400 Subject: [PATCH 002/283] small note about updating submodules for custom dev --- doc/INSTALL.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/INSTALL.md b/doc/INSTALL.md index 3b4585b89496..21a198deed55 100644 --- a/doc/INSTALL.md +++ b/doc/INSTALL.md @@ -407,6 +407,17 @@ apk del ca-certificates alpine-sdk autoconf automake git libtool \ gmp-dev sqlite python3 py3-mako net-tools zlib-dev libsodium gettext ``` +Messing with subtrees: +``` +> edit .gitmodule file +git submodule sync --recursive +cd external/ +git fetch +cd ../.. +# Do this any time you have an update ready for the branch +git submodule update --remote external/ +``` + Additional steps -------------------- Go to [README](https://github.com/ElementsProject/lightning/blob/master/README.md) for more information how to create an address, add funds, connect to a node, etc. From 9b8a733cd5684110ce90ff190b3badb48f9a3c9b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 10 Jun 2022 15:49:37 -0400 Subject: [PATCH 003/283] Update libwally to custom branch --- .gitmodules | 3 ++- external/libwally-core | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 095547408073..eb67e470f12c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,8 +9,9 @@ url = https://github.com/ianlancetaylor/libbacktrace.git [submodule "external/libwally-core"] path = external/libwally-core - url = https://github.com/ElementsProject/libwally-core.git + url = https://github.com/instagibbs/libwally-core.git ignore = dirty + branch = taproot [submodule "external/gheap"] path = external/gheap url = https://github.com/valyala/gheap diff --git a/external/libwally-core b/external/libwally-core index f7c0824e56a0..e6ab70fba338 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit f7c0824e56a068c4d9c27cb2e8b26e2a9b8ea3b3 +Subproject commit e6ab70fba3387d39cf5d871e45a8e6d16d90f593 From 31d65a261b83f4aa44f70ca90dc415a917f8b4cc Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 10 Jun 2022 15:57:02 -0400 Subject: [PATCH 004/283] update submodule --- external/libwally-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/libwally-core b/external/libwally-core index e6ab70fba338..b108e98f66eb 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit e6ab70fba3387d39cf5d871e45a8e6d16d90f593 +Subproject commit b108e98f66eb63d95a4670797e7df0dc216e06c0 From 1b8a8e2efcfb03138f9c081e41e60cb283d558b1 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 16 Jun 2022 13:43:20 -0400 Subject: [PATCH 005/283] Bump libwally --- external/libwally-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/libwally-core b/external/libwally-core index b108e98f66eb..e8311e0b2c25 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit b108e98f66eb63d95a4670797e7df0dc216e06c0 +Subproject commit e8311e0b2c25f8f14880d9326d211a854d5f4e90 From 515dad8adbc3508a93c45008cccee9dc309060e3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 16 Jun 2022 15:51:50 -0400 Subject: [PATCH 006/283] add bitcoind_tx_taproot_hash_for_sig --- bitcoin/psbt.c | 12 +++++++ bitcoin/psbt.h | 8 +++++ bitcoin/signature.c | 33 +++++++++++++++++++ bitcoin/signature.h | 15 +++++++++ ...-tx-bitcoin_tx_2of2_input_witness_weight.c | 4 +++ 5 files changed, 72 insertions(+) diff --git a/bitcoin/psbt.c b/bitcoin/psbt.c index 990621104228..a14785028190 100644 --- a/bitcoin/psbt.c +++ b/bitcoin/psbt.c @@ -450,6 +450,18 @@ struct amount_sat psbt_input_get_amount(const struct wally_psbt *psbt, return val; } +const unsigned char *psbt_input_get_scriptpubkey(const struct wally_psbt *psbt, + size_t in) +{ + if (psbt->inputs[in].witness_utxo) { + return psbt->inputs[in].witness_utxo->script; + } else if (psbt->inputs[in].utxo) { + return psbt->inputs[in].utxo->outputs[psbt->tx->inputs[in].index].script; + } else { + abort(); + } +} + struct amount_sat psbt_output_get_amount(const struct wally_psbt *psbt, size_t out) { diff --git a/bitcoin/psbt.h b/bitcoin/psbt.h index 53ff1c4cef29..e1e05449f7f4 100644 --- a/bitcoin/psbt.h +++ b/bitcoin/psbt.h @@ -206,6 +206,14 @@ void psbt_output_set_unknown(const tal_t *ctx, struct amount_sat psbt_input_get_amount(const struct wally_psbt *psbt, size_t in); +/* psbt_input_get_scriptpubkey - Returns pointer to the input's scriptPubKey + * + * @psbt - psbt + * in - index of input whose value script returning + */ +const unsigned char *psbt_input_get_scriptpubkey(const struct wally_psbt *psbt, + size_t in); + /* psbt_output_get_amount - Returns the value of this output * * @psbt - psbt diff --git a/bitcoin/signature.c b/bitcoin/signature.c index f91ef6ec2bcd..54112dcbb00d 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -178,6 +178,39 @@ void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, tal_wally_end(tx->wtx); } +void bitcoind_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, + unsigned int input_index, + enum sighash_type sighash_type, /* FIXME get from PSBT? */ + const unsigned char *tapleaf_script, /* FIXME Get directly from PSBT? */ + struct sha256_double *dest) +{ + int ret, i; + + /* Preparing args for taproot*/ + size_t input_count = tx->wtx->num_inputs; + const unsigned char *input_spks[input_count]; + size_t input_spk_lens[input_count]; + u64 input_val_sats[input_count]; + + for (i=0; i < input_count; ++i) { + input_spks[i] = psbt_input_get_scriptpubkey(tx->psbt, i); + input_spk_lens[i] = tal_bytelen(input_spks[i]); /* FIXME ??? tal_bytelen? */ + input_val_sats[i] = psbt_input_get_amount(tx->psbt, i).satoshis; + } + + /* Wally can allocate here, iff tx doesn't fit on stack */ + tal_wally_start(); + ret = wally_tx_get_btc_taproot_signature_hash( + tx->wtx, sighash_type, input_index, input_spks, input_spk_lens, + input_val_sats, tapleaf_script, tal_bytelen(tapleaf_script), 0x00 /* key_version */, + 0xFFFFFFFF /* codesep_position */, 0 /* flags */, dest->sha.u.u8, + sizeof(*dest)); + + assert(ret == WALLY_OK); + tal_wally_end(tx->wtx); + +} + void sign_tx_input(const struct bitcoin_tx *tx, unsigned int in, const u8 *subscript, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 25f7774e0f9f..45251281c058 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -67,6 +67,21 @@ void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, enum sighash_type sighash_type, struct sha256_double *dest); +/** + * bitcoin_tx_taproot_hash_for_sig - produce hash for a taproot spend + * + * @tx - tx to hash + * @input_index - index that this 'hash' is for + * @sighash_type - sighash_type to hash for + * @tapleaf_script - tapscript leaf for the index that's being 'hashed for', NULL if keyspend + * @dest - hash result + */ +void bitcoind_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, + unsigned int input_index, + enum sighash_type sighash_type, + const unsigned char *tapleaf_script, + struct sha256_double *dest); + /** * sign_hash - produce a raw secp256k1 signature (with low R value). * @p: secret key diff --git a/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c b/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c index d1c6a3c25d98..69d8bf36f685 100644 --- a/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c +++ b/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c @@ -95,6 +95,10 @@ bool psbt_finalize(struct wally_psbt *psbt UNNEEDED) struct amount_sat psbt_input_get_amount(const struct wally_psbt *psbt UNNEEDED, size_t in UNNEEDED) { fprintf(stderr, "psbt_input_get_amount called!\n"); abort(); } +/* Generated stub for psbt_input_get_scriptpubkey */ +const unsigned char *psbt_input_get_scriptpubkey(const struct wally_psbt *psbt UNNEEDED, + size_t in UNNEEDED) +{ fprintf(stderr, "psbt_input_get_scriptpubkey called!\n"); abort(); } /* Generated stub for psbt_input_set_wit_utxo */ void psbt_input_set_wit_utxo(struct wally_psbt *psbt UNNEEDED, size_t in UNNEEDED, const u8 *scriptPubkey UNNEEDED, struct amount_sat amt UNNEEDED) From bbba31204e3c54224d6ee96e740c9e0bec6cc4b2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 17 Jun 2022 10:28:06 -0400 Subject: [PATCH 007/283] sign_tx_taproot_input --- bitcoin/signature.c | 28 +++++++++++++++++++++++++++- bitcoin/signature.h | 18 +++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 54112dcbb00d..0329163806d6 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -178,7 +178,7 @@ void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, tal_wally_end(tx->wtx); } -void bitcoind_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, +void bitcoin_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, unsigned int input_index, enum sighash_type sighash_type, /* FIXME get from PSBT? */ const unsigned char *tapleaf_script, /* FIXME Get directly from PSBT? */ @@ -232,6 +232,32 @@ void sign_tx_input(const struct bitcoin_tx *tx, sign_hash(privkey, &hash, &sig->s); } +void sign_tx_taproot_input(const struct bitcoin_tx *tx, + unsigned int input_index, + enum sighash_type sighash_type, + const u8 *tapleaf_script, + const secp256k1_keypair *key_pair, + struct bip340sig *sig) +{ + struct sha256_double hash; + int ret; + secp256k1_pubkey pubkey; + struct pubkey pk; + struct privkey privkey; + + /* FIXME assert sighashes we actually support assert(sighash_type_valid(sighash_type)); */ + bitcoin_tx_taproot_hash_for_sig(tx, input_index, sighash_type, tapleaf_script, &hash); + + /* TODO just have it take keypair? */ + ret = secp256k1_keypair_pub(secp256k1_ctx, &pubkey, key_pair); + assert(ret); + pk.pubkey = pubkey; + dump_tx("Signing", tx, input_index, tapleaf_script, &pk, &hash); + ret= secp256k1_keypair_sec(secp256k1_ctx, privkey.secret.data, key_pair); + assert(ret); + bip340_sign_hash(&privkey, &hash, sig); +} + bool check_signed_hash(const struct sha256_double *hash, const secp256k1_ecdsa_signature *signature, const struct pubkey *key) diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 45251281c058..c8382a82d3b7 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -76,7 +76,7 @@ void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, * @tapleaf_script - tapscript leaf for the index that's being 'hashed for', NULL if keyspend * @dest - hash result */ -void bitcoind_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, +void bitcoin_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, unsigned int input_index, enum sighash_type sighash_type, const unsigned char *tapleaf_script, @@ -134,6 +134,22 @@ void sign_tx_input(const struct bitcoin_tx *tx, enum sighash_type sighash_type, struct bitcoin_signature *sig); +/** + * sign_tx_taproot_input - produce a bitcoin signature for a taproot transaction input + * @tx: the bitcoin transaction we're signing. + * @input_index: the input number to sign. + * @sighash_type: a valid sighash type. + * @tapleaf_script: tapscript leaf script to hash. + * @key_pair: the BIP340 keypair to use for signing and verification. + * @sig: (in) sighash_type indicates what type of signature make. + */ +void sign_tx_taproot_input(const struct bitcoin_tx *tx, + unsigned int input_index, + enum sighash_type sighash_type, + const u8 *tapleaf_script, + const secp256k1_keypair *key_pair, + struct bip340sig *sig); + /** * check_tx_sig - produce a bitcoin signature for a transaction input * @tx: the bitcoin transaction which has been signed. From cf526813c3f2746ac23d842004b762ce245af048 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 17 Jun 2022 11:15:57 -0400 Subject: [PATCH 008/283] check_signed_bip340_hash --- bitcoin/signature.c | 9 +++++++++ bitcoin/signature.h | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 0329163806d6..b7e292868d58 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -278,6 +278,15 @@ bool check_signed_hash(const struct sha256_double *hash, return ret == 1; } +bool check_signed_bip340_hash(const struct sha256_double *hash, + const struct bip340sig *signature, + const struct point32 *key) +{ + int ret; + ret = secp256k1_schnorrsig_verify(secp256k1_ctx, signature->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &key->pubkey); + return ret == 1; +} + bool check_tx_sig(const struct bitcoin_tx *tx, size_t input_num, const u8 *redeemscript, const u8 *witness_script, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index c8382a82d3b7..c22674311b2e 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -10,6 +10,7 @@ struct sha256_double; struct sha256_ctx; struct bitcoin_tx; struct pubkey; +struct point32; struct privkey; struct bitcoin_tx_output; @@ -115,6 +116,19 @@ bool check_signed_hash(const struct sha256_double *hash, const secp256k1_ecdsa_signature *signature, const struct pubkey *key); +/** + * check_signed_bip340_hash - check a raw BIP340 signature. + * @hash: hash which was signed. + * @signature: BIP340 signature. + * @key: x-only public key corresponding to private key used to sign. + * + * Returns true if the key, hash and signature are correct. Changing any + * one of these will make it fail. + */ +bool check_signed_bip340_hash(const struct sha256_double *hash, + const struct bip340sig *signature, + const struct point32 *key); + /** * sign_tx_input - produce a bitcoin signature for a transaction input * @tx: the bitcoin transaction we're signing. From b859f503513dd70047cee0b90a00a8e8c56314b4 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 17 Jun 2022 13:08:31 -0400 Subject: [PATCH 009/283] check_tx_taproot_sig --- bitcoin/signature.c | 49 +++++++++++++++++++++++++++++++++++++-------- bitcoin/signature.h | 18 +++++++++++++++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index b7e292868d58..2862842130e6 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -31,6 +31,7 @@ static void dump_tx(const char *msg, const struct bitcoin_tx *tx, size_t inputnum, const u8 *script, const struct pubkey *key, + const struct point32 *x_key, const struct sha256_double *h) { size_t i, j; @@ -58,6 +59,11 @@ static void dump_tx(const char *msg, for (i = 0; i < sizeof(key->pubkey); i++) fprintf(stderr, "%02x", ((u8 *)&key->pubkey)[i]); fprintf(stderr, "\n"); + } else if (x_key) { + fprintf(stderr, "\nPubkey: "); + for (i = 0; i < sizeof(x_key->pubkey); i++) + fprintf(stderr, "%02x", ((u8 *)&x_key->pubkey)[i]); + fprintf(stderr, "\n"); } if (h) { fprintf(stderr, "\nHash: "); @@ -71,6 +77,7 @@ static void dump_tx(const char *msg UNUSED, const struct bitcoin_tx *tx UNUSED, size_t inputnum UNUSED, const u8 *script UNUSED, const struct pubkey *key UNUSED, + const struct point32 *x_key, const struct sha256_double *h UNUSED) { } @@ -228,7 +235,7 @@ void sign_tx_input(const struct bitcoin_tx *tx, sig->sighash_type = sighash_type; bitcoin_tx_hash_for_sig(tx, in, script, sighash_type, &hash); - dump_tx("Signing", tx, in, subscript, key, &hash); + dump_tx("Signing", tx, in, subscript, key, NULL /* x_key */, &hash); sign_hash(privkey, &hash, &sig->s); } @@ -241,18 +248,18 @@ void sign_tx_taproot_input(const struct bitcoin_tx *tx, { struct sha256_double hash; int ret; - secp256k1_pubkey pubkey; - struct pubkey pk; + secp256k1_xonly_pubkey pubkey; + struct point32 x_key; struct privkey privkey; /* FIXME assert sighashes we actually support assert(sighash_type_valid(sighash_type)); */ bitcoin_tx_taproot_hash_for_sig(tx, input_index, sighash_type, tapleaf_script, &hash); /* TODO just have it take keypair? */ - ret = secp256k1_keypair_pub(secp256k1_ctx, &pubkey, key_pair); + ret = secp256k1_keypair_xonly_pub(secp256k1_ctx, &pubkey, NULL /* pk_parity */, key_pair); assert(ret); - pk.pubkey = pubkey; - dump_tx("Signing", tx, input_index, tapleaf_script, &pk, &hash); + x_key.pubkey = pubkey; + dump_tx("Signing", tx, input_index, tapleaf_script, NULL /* key */, &x_key, &hash); ret= secp256k1_keypair_sec(secp256k1_ctx, privkey.secret.data, key_pair); assert(ret); bip340_sign_hash(&privkey, &hash, sig); @@ -308,11 +315,37 @@ bool check_tx_sig(const struct bitcoin_tx *tx, size_t input_num, assert(input_num < tx->wtx->num_inputs); bitcoin_tx_hash_for_sig(tx, input_num, script, sig->sighash_type, &hash); - dump_tx("check_tx_sig", tx, input_num, script, key, &hash); + dump_tx("check_tx_sig", tx, input_num, script, key, NULL /* x_key */, &hash); ret = check_signed_hash(&hash, &sig->s, key); if (!ret) - dump_tx("Sig failed", tx, input_num, redeemscript, key, &hash); + dump_tx("Sig failed", tx, input_num, redeemscript, key, NULL /* x_key */, &hash); + return ret; +} + +bool check_tx_taproot_sig(const struct bitcoin_tx *tx, size_t input_num, + const u8 *tapleaf_script, + const struct point32 *x_key, + enum sighash_type sighash_type, + const struct bip340sig *sig) +{ + struct sha256_double hash; + bool ret; + + /* FIXME We only support a limited subset of sighash types. */ + if (sighash_type != SIGHASH_ALL) { + if (sighash_type != (SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) + return false; + } + assert(input_num < tx->wtx->num_inputs); + + bitcoin_tx_taproot_hash_for_sig(tx, input_num, sighash_type, tapleaf_script, &hash); + + dump_tx("check_tx_sig", tx, input_num, tapleaf_script, NULL /* key */, x_key, &hash); + + ret = check_signed_bip340_hash(&hash, sig, x_key); + if (!ret) + dump_tx("Sig failed", tx, input_num, tapleaf_script, NULL /* key */, x_key, &hash); return ret; } diff --git a/bitcoin/signature.h b/bitcoin/signature.h index c22674311b2e..5d2b2e6968eb 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -182,6 +182,24 @@ bool check_tx_sig(const struct bitcoin_tx *tx, size_t input_num, const struct pubkey *key, const struct bitcoin_signature *sig); +/** + * check_tx_taproot_sig - check a bitcoin signature for a transaction input + * @tx: the bitcoin transaction which has been signed. + * @input_num: the input number to which @sig should apply. + * @tapleaf_script: NULL(keyspend) or the tapscript leaf script to hash. + * @key: the x-only public key corresonding to the signature. + * @sighash_type: sighash type for @sig. + * @sig: the signature to check. + * + * Returns true if this signature was created by @privkey and this tx + * and sighash_type, otherwise false. + */ +bool check_tx_taproot_sig(const struct bitcoin_tx *tx, size_t input_num, + const u8 *tapleaf_script, + const struct point32 *x_key, + enum sighash_type sighash_type, + const struct bip340sig *sig); + /* Give DER encoding of signature: returns length used (<= 73). */ size_t signature_to_der(u8 der[73], const struct bitcoin_signature *sig); From 8bf0af1120786c509c548a802ecd8f906cda5f22 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 17 Jun 2022 14:37:50 -0400 Subject: [PATCH 010/283] Enable musig module, make bip340_partial_sign_hash --- bitcoin/signature.c | 26 ++++++++++++++++++++++++++ bitcoin/signature.h | 21 ++++++++++++++++++++- external/Makefile | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 2862842130e6..5d47ef32f125 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -136,6 +136,7 @@ void bip340_sign_hash(const struct privkey *privkey, struct bip340sig *sig) { bool ok; + secp256k1_xonly_pubkey pubkey; secp256k1_keypair keypair; ok = secp256k1_keypair_create(secp256k1_ctx, @@ -149,7 +150,32 @@ void bip340_sign_hash(const struct privkey *privkey, hash->sha.u.u8, &keypair, /* aux_rand32 */ NULL); + + ok = secp256k1_keypair_xonly_pub(secp256k1_ctx, &pubkey, NULL /* pk_parity */, &keypair); assert(ok); + + assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); +} + +void bip340_partial_sign_hash(const struct privkey *privkey, + secp256k1_musig_secnonce *secnonce, + secp256k1_musig_keyagg_cache *cache, + secp256k1_musig_session *session, + const struct sha256_double *hash, + secp256k1_musig_partial_sig *p_sig) +{ + bool ok; + secp256k1_keypair keypair; + + ok = secp256k1_keypair_create(secp256k1_ctx, + &keypair, + privkey->secret.data); + + assert(ok); + + ok = secp256k1_musig_partial_sign(secp256k1_ctx, p_sig, secnonce, &keypair, cache, session); + + assert(ok); } void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 5d2b2e6968eb..803fd6f1e3c3 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -5,6 +5,7 @@ #include #include #include +#include struct sha256_double; struct sha256_ctx; @@ -94,7 +95,7 @@ void sign_hash(const struct privkey *p, secp256k1_ecdsa_signature *sig); /** - * bip340_sigh_hash - produce a raw BIP340 signature + * bip340_sighn_hash - produce a raw BIP340 signature * @privkey: secret key * @hash: hash to sign. * @sig: signature to fill and return @@ -103,6 +104,24 @@ void bip340_sign_hash(const struct privkey *privkey, const struct sha256_double *hash, struct bip340sig *sig); +/** + * bip340_partial_sign_hash - produce a partial BIP340 signature. + * This assumed an already existing session with pubkeys aggregated + * and nonces collected, aggregated, and processed. + * This is called after _____ FIXME. + * @privkey: secret key + * @secnonce: secret nonce used *once* to partially sign + * @session: session information for signing attempt + * @hash: hash to sign. + * @p_sig: partial signature to fill and return + */ +void bip340_partial_sign_hash(const struct privkey *privkey, + secp256k1_musig_secnonce *secnonce, + secp256k1_musig_keyagg_cache *cache, + secp256k1_musig_session *session, + const struct sha256_double *hash, + secp256k1_musig_partial_sig *p_sig); + /** * check_signed_hash - check a raw secp256k1 signature. * @h: hash which was signed. diff --git a/external/Makefile b/external/Makefile index 92e976092a09..6564c0fbd086 100644 --- a/external/Makefile +++ b/external/Makefile @@ -81,6 +81,7 @@ $(TARGET_DIR)/libwally-core-build/src/libwallycore.% $(TARGET_DIR)/libwally-core --enable-module-recovery \ --enable-module-extrakeys \ --enable-module-schnorrsig \ + --enable-module-musig \ --enable-elements \ --enable-shared=no \ --prefix=/ \ From 086ff172f664e2ce3a73cd34afe3102c9af3e69c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 17 Jun 2022 15:38:25 -0400 Subject: [PATCH 011/283] Add bip340_partial_sigs_verify --- bitcoin/signature.c | 23 ++++++++++++++++++++--- bitcoin/signature.h | 21 +++++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 5d47ef32f125..8be39ec5bcf3 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -157,11 +157,10 @@ void bip340_sign_hash(const struct privkey *privkey, assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); } -void bip340_partial_sign_hash(const struct privkey *privkey, +void bip340_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, - const struct sha256_double *hash, secp256k1_musig_partial_sig *p_sig) { bool ok; @@ -178,6 +177,24 @@ void bip340_partial_sign_hash(const struct privkey *privkey, assert(ok); } +bool bip340_partial_sigs_verify(const secp256k1_musig_partial_sig * const *p_sigs, + size_t num_signers, + const secp256k1_xonly_pubkey *agg_pk, + secp256k1_musig_session *session, + const struct sha256_double *hash, + struct bip340sig *sig) +{ + int ret; + + ret = secp256k1_musig_partial_sig_agg(secp256k1_ctx, sig->u8, session, p_sigs, num_signers); + + if (!ret) { + return false; + } + + return secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), agg_pk); +} + void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, const u8 *script, enum sighash_type sighash_type, @@ -286,7 +303,7 @@ void sign_tx_taproot_input(const struct bitcoin_tx *tx, assert(ret); x_key.pubkey = pubkey; dump_tx("Signing", tx, input_index, tapleaf_script, NULL /* key */, &x_key, &hash); - ret= secp256k1_keypair_sec(secp256k1_ctx, privkey.secret.data, key_pair); + ret = secp256k1_keypair_sec(secp256k1_ctx, privkey.secret.data, key_pair); assert(ret); bip340_sign_hash(&privkey, &hash, sig); } diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 803fd6f1e3c3..019cd84daf5a 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -105,23 +105,36 @@ void bip340_sign_hash(const struct privkey *privkey, struct bip340sig *sig); /** - * bip340_partial_sign_hash - produce a partial BIP340 signature. + * bip340_partial_sign - produce a partial BIP340 signature. * This assumed an already existing session with pubkeys aggregated * and nonces collected, aggregated, and processed. * This is called after _____ FIXME. * @privkey: secret key * @secnonce: secret nonce used *once* to partially sign * @session: session information for signing attempt - * @hash: hash to sign. * @p_sig: partial signature to fill and return */ -void bip340_partial_sign_hash(const struct privkey *privkey, +void bip340_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, - const struct sha256_double *hash, secp256k1_musig_partial_sig *p_sig); +/** + * bip340_partial_sigs_verify - combine and verify partial MuSig signatures + * @p_sigs: partial signatures to combine and validate + * @num_signers: number of partial signatures to combine + * @agg_pk: aggregated public key signature is validated against + * @hash: hash to validate signature against + * @sig: final BIP340 signature to output + */ +bool bip340_partial_sigs_verify(const secp256k1_musig_partial_sig * const *p_sigs, + size_t num_signers, + const secp256k1_xonly_pubkey *agg_pk, + secp256k1_musig_session *session, + const struct sha256_double *hash, + struct bip340sig *sig); + /** * check_signed_hash - check a raw secp256k1 signature. * @h: hash which was signed. From 29bb4945a5db6a695f555edce8fa5f6975fa4786 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Jun 2022 09:30:51 -0400 Subject: [PATCH 012/283] rename to bip340_partial_sigs_combine_verify --- bitcoin/signature.c | 2 +- bitcoin/signature.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 8be39ec5bcf3..22d2f70b65fb 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -177,7 +177,7 @@ void bip340_partial_sign(const struct privkey *privkey, assert(ok); } -bool bip340_partial_sigs_verify(const secp256k1_musig_partial_sig * const *p_sigs, +bool bip340_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, size_t num_signers, const secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_session *session, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 019cd84daf5a..4de7682ec7f4 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -121,14 +121,14 @@ void bip340_partial_sign(const struct privkey *privkey, secp256k1_musig_partial_sig *p_sig); /** - * bip340_partial_sigs_verify - combine and verify partial MuSig signatures + * bip340_partial_sigs_combine_verify - combine and verify partial MuSig signatures * @p_sigs: partial signatures to combine and validate * @num_signers: number of partial signatures to combine * @agg_pk: aggregated public key signature is validated against * @hash: hash to validate signature against * @sig: final BIP340 signature to output */ -bool bip340_partial_sigs_verify(const secp256k1_musig_partial_sig * const *p_sigs, +bool bip340_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, size_t num_signers, const secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_session *session, From 6bf5488ecc9c826d15d61d9ff11f2c86702d2552 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Jun 2022 09:37:38 -0400 Subject: [PATCH 013/283] renaming stuff to bipmusig until it's assigned a nuber --- bitcoin/signature.c | 4 ++-- bitcoin/signature.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 22d2f70b65fb..43507cc8d6b9 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -157,7 +157,7 @@ void bip340_sign_hash(const struct privkey *privkey, assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); } -void bip340_partial_sign(const struct privkey *privkey, +void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, @@ -177,7 +177,7 @@ void bip340_partial_sign(const struct privkey *privkey, assert(ok); } -bool bip340_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, +bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, size_t num_signers, const secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_session *session, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 4de7682ec7f4..feed801c52cd 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -95,7 +95,7 @@ void sign_hash(const struct privkey *p, secp256k1_ecdsa_signature *sig); /** - * bip340_sighn_hash - produce a raw BIP340 signature + * bip340_sign_hash - produce a raw BIP340 signature * @privkey: secret key * @hash: hash to sign. * @sig: signature to fill and return @@ -105,7 +105,7 @@ void bip340_sign_hash(const struct privkey *privkey, struct bip340sig *sig); /** - * bip340_partial_sign - produce a partial BIP340 signature. + * bipmusig_partial_sign - produce a partial BIP340 signature. * This assumed an already existing session with pubkeys aggregated * and nonces collected, aggregated, and processed. * This is called after _____ FIXME. @@ -114,21 +114,21 @@ void bip340_sign_hash(const struct privkey *privkey, * @session: session information for signing attempt * @p_sig: partial signature to fill and return */ -void bip340_partial_sign(const struct privkey *privkey, +void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, secp256k1_musig_partial_sig *p_sig); /** - * bip340_partial_sigs_combine_verify - combine and verify partial MuSig signatures + * bipmusig_partial_sigs_combine_verify - combine and verify partial MuSig signatures * @p_sigs: partial signatures to combine and validate * @num_signers: number of partial signatures to combine * @agg_pk: aggregated public key signature is validated against * @hash: hash to validate signature against * @sig: final BIP340 signature to output */ -bool bip340_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, +bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, size_t num_signers, const secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_session *session, From e16338bd5e354bf0a94fa3f7670ba94be3c9d088 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Jun 2022 11:12:10 -0400 Subject: [PATCH 014/283] Add bipmusig_aggregate_keys subroutine --- bitcoin/signature.c | 33 +++++++++++++++++++++++++++++++++ bitcoin/signature.h | 14 ++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 43507cc8d6b9..4b550690f0a3 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -157,6 +157,39 @@ void bip340_sign_hash(const struct privkey *privkey, assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); } +void bipmusig_aggregate_keys(secp256k1_xonly_pubkey *agg_pk, + secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_xonly_pubkey * const* pubkeys, + size_t n_pubkeys) +{ + int i, ok; + assert(n_pubkeys <= 100); + + /* Sorting moves pubkeys themselves, we copy and discard after */ + secp256k1_xonly_pubkey pubkeys_copy[100]; + const secp256k1_xonly_pubkey *pubkeys_ptr[100]; + for (i=0; i < n_pubkeys; ++i) { + memcpy(&pubkeys_copy[i], pubkeys[i], sizeof(secp256k1_xonly_pubkey)); + pubkeys_ptr[i] = &pubkeys_copy[i]; + } + + ok = secp256k1_xonly_sort(secp256k1_ctx, + pubkeys_ptr, + n_pubkeys); + + assert(ok); + + ok = secp256k1_musig_pubkey_agg(secp256k1_ctx, + NULL /* scratch */, + agg_pk, + keyagg_cache, + pubkeys_ptr, + n_pubkeys); + + assert(ok); +} + + void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, secp256k1_musig_keyagg_cache *cache, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index feed801c52cd..8221b20db804 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -104,6 +104,20 @@ void bip340_sign_hash(const struct privkey *privkey, const struct sha256_double *hash, struct bip340sig *sig); +/** + * bipmusig_aggregate_keys - Aggregate keys in lexigraphically + * sorted order, and initializes the cache required for signing + * sessions + * @agg_pk: Aggregated public key to be constructed + * @keyagg_cache: Cache to be used for signing session and validation + * @pubkeys: Array of pubkeys to be aggregated + * @n_pubkeys: Number of public keys in @pubkeys + */ +void bipmusig_aggregate_keys(secp256k1_xonly_pubkey *agg_pk, + secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_xonly_pubkey * const* pubkeys, + size_t n_pubkeys); + /** * bipmusig_partial_sign - produce a partial BIP340 signature. * This assumed an already existing session with pubkeys aggregated From 0c9dc6dae0c948a034e9d116b786131d50138159 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Jun 2022 13:23:41 -0400 Subject: [PATCH 015/283] Make bipmusig_finalize_keys which also tweaks the keys --- bitcoin/signature.c | 25 +++++++++++++++++++++++-- bitcoin/signature.h | 16 ++++++++++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 4b550690f0a3..d4b8424d1945 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -157,12 +157,16 @@ void bip340_sign_hash(const struct privkey *privkey, assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); } -void bipmusig_aggregate_keys(secp256k1_xonly_pubkey *agg_pk, +void bipmusig_finalize_keys(secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_xonly_pubkey * const* pubkeys, - size_t n_pubkeys) + size_t n_pubkeys, + const struct sha256 *tap_merkle_root, + unsigned char *tap_tweak_out) { int i, ok; + unsigned char taptweak_preimage[64]; + secp256k1_pubkey tmp_pk; assert(n_pubkeys <= 100); /* Sorting moves pubkeys themselves, we copy and discard after */ @@ -187,6 +191,23 @@ void bipmusig_aggregate_keys(secp256k1_xonly_pubkey *agg_pk, n_pubkeys); assert(ok); + + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, agg_pk); + + assert(ok); + + if (tap_merkle_root) { + memcpy(taptweak_preimage + 32, tap_merkle_root->u.u8, sizeof(tap_merkle_root->u.u8)); + + ok = wally_tagged_hash(taptweak_preimage, sizeof(taptweak_preimage), "TapTweak", tap_tweak_out); + + assert(ok == WALLY_OK); + + /* Tweak, if script path spend */ + ok = secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_ctx, &tmp_pk, keyagg_cache, tap_tweak_out); + + assert(ok); + } } diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 8221b20db804..d0248b61f4d6 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -7,6 +7,7 @@ #include #include +struct sha256; struct sha256_double; struct sha256_ctx; struct bitcoin_tx; @@ -105,18 +106,25 @@ void bip340_sign_hash(const struct privkey *privkey, struct bip340sig *sig); /** - * bipmusig_aggregate_keys - Aggregate keys in lexigraphically - * sorted order, and initializes the cache required for signing + * bipmusig_finalize_keys - Aggregate keys in lexigraphically + * sorted order, tweaks if required for keyspend, + * and initializes the cache required for signing * sessions * @agg_pk: Aggregated public key to be constructed * @keyagg_cache: Cache to be used for signing session and validation * @pubkeys: Array of pubkeys to be aggregated * @n_pubkeys: Number of public keys in @pubkeys + * @tap_merkle_root: Merkle root for taptree, to be used in tweaking. + * NULL if script path spending is used. + * @tap_tweak_out: Set to `t` in `t = hashTapTweak(p || k_m)` of BIP341. + Must be NULL iff @tap_merkle_root is NULL, 32 bytes otherwise. */ -void bipmusig_aggregate_keys(secp256k1_xonly_pubkey *agg_pk, +void bipmusig_finalize_keys(secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_xonly_pubkey * const* pubkeys, - size_t n_pubkeys); + size_t n_pubkeys, + const struct sha256 *tap_merkle_root, + unsigned char *tap_tweak_out); /** * bipmusig_partial_sign - produce a partial BIP340 signature. From 7a27f309bea25fef9e6a53fe04f96321c2b2fe87 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Jun 2022 14:26:22 -0400 Subject: [PATCH 016/283] Nonce generation wrapper --- bitcoin/signature.c | 17 +++++++++++++++++ bitcoin/signature.h | 16 ++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index d4b8424d1945..962cac130332 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -10,6 +10,7 @@ #include #include #include +#include #undef DEBUG #ifdef DEBUG @@ -210,6 +211,22 @@ void bipmusig_finalize_keys(secp256k1_xonly_pubkey *agg_pk, } } +void bipmusig_gen_nonce(secp256k1_musig_secnonce *secnonce, + secp256k1_musig_pubnonce *pubnonce, + const struct privkey *privkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *msg32) +{ + /* MUST be unique for each signing attempt or SFYL */ + unsigned char session_id[32]; + int ok; + + randombytes_buf(session_id, sizeof(session_id)); + + ok = secp256k1_musig_nonce_gen(secp256k1_ctx, secnonce, pubnonce, session_id, privkey->secret.data, msg32, keyagg_cache, NULL /* extra_input32 */); + + assert(ok); +} void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index d0248b61f4d6..02e00e80e936 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -126,6 +126,22 @@ void bipmusig_finalize_keys(secp256k1_xonly_pubkey *agg_pk, const struct sha256 *tap_merkle_root, unsigned char *tap_tweak_out); +/** + * bipmusig_gen_nonce - Generates session id, private + * and public nonce pair, assuming we already have + * a private and aggregated key. + * @secnonce: secret nonce to be generated. MUST NEVER BE MANUALLY COPIED OR PERSISTED!!! + * @pubnonce: public nonce to be generated + * @privkey: privkey for this signing session + * @keyagg_cache: aggregated key cache + * @msg32: Optional 32 byte message for misuse resistance + */ +void bipmusig_gen_nonce(secp256k1_musig_secnonce *secnonce, + secp256k1_musig_pubnonce *pubnonce, + const struct privkey *privkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *msg32); + /** * bipmusig_partial_sign - produce a partial BIP340 signature. * This assumed an already existing session with pubkeys aggregated From 2f8f212af7ee35ad5ff0a42e8537628319fc058d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Jun 2022 14:45:12 -0400 Subject: [PATCH 017/283] Rework bipmusig_partial_sign to do the nonce aggregation as well --- bitcoin/signature.c | 13 +++++++++++++ bitcoin/signature.h | 10 ++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 962cac130332..4a928e08d1f9 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -230,12 +230,25 @@ void bipmusig_gen_nonce(secp256k1_musig_secnonce *secnonce, void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, + const secp256k1_musig_pubnonce * const *pubnonces, + size_t num_signers, + unsigned char *msg32, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, secp256k1_musig_partial_sig *p_sig) { bool ok; secp256k1_keypair keypair; + secp256k1_musig_aggnonce agg_pubnonce; + + /* Create aggregate nonce and initialize the session */ + ok = secp256k1_musig_nonce_agg(secp256k1_ctx, &agg_pubnonce, pubnonces, num_signers); + + assert(ok); + + ok = secp256k1_musig_nonce_process(secp256k1_ctx, session, &agg_pubnonce, msg32, cache, NULL); + + assert(ok); ok = secp256k1_keypair_create(secp256k1_ctx, &keypair, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 02e00e80e936..adb596a43bdd 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -145,15 +145,21 @@ void bipmusig_gen_nonce(secp256k1_musig_secnonce *secnonce, /** * bipmusig_partial_sign - produce a partial BIP340 signature. * This assumed an already existing session with pubkeys aggregated - * and nonces collected, aggregated, and processed. - * This is called after _____ FIXME. + * and nonces collected but not aggregated and processed. + * This is called after bipmusig_gen_nonce. * @privkey: secret key * @secnonce: secret nonce used *once* to partially sign + * @pubnonces: public nonces collected from all signers, including self + * @num_signers: number of signers + * @msg32: Message hash we are signing * @session: session information for signing attempt * @p_sig: partial signature to fill and return */ void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, + const secp256k1_musig_pubnonce * const *pubnonces, + size_t num_signers, + unsigned char *msg32, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, secp256k1_musig_partial_sig *p_sig); From 9e3bb954865de692b97ad963fa47f8d2d6aab584 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 22 Jun 2022 11:51:33 -0400 Subject: [PATCH 018/283] Update libwally to support APO(AS) sighashes --- external/libwally-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/libwally-core b/external/libwally-core index e8311e0b2c25..dd15feb8bcad 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit e8311e0b2c25f8f14880d9326d211a854d5f4e90 +Subproject commit dd15feb8bcada3f87e960e0a14316d2038e6b7bf From 1aea6c2a1210f4f4b96949a2aebab4d89364a4a0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 29 Jun 2022 10:22:23 -0400 Subject: [PATCH 019/283] Checkin some p2tr stuff --- bitcoin/script.c | 28 ++++++ bitcoin/script.h | 6 ++ bitcoin/signature.c | 41 ++++---- bitcoin/signature.h | 10 +- devtools/.gitignore | 1 + devtools/Makefile | 4 +- devtools/eltoo_mkfunding.c | 190 +++++++++++++++++++++++++++++++++++++ 7 files changed, 256 insertions(+), 24 deletions(-) create mode 100644 devtools/eltoo_mkfunding.c diff --git a/bitcoin/script.c b/bitcoin/script.c index 316388696548..2cea635ba381 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -310,6 +310,34 @@ u8 *scriptpubkey_witness_raw(const tal_t *ctx, u8 version, return script; } +/* Create an output script for a taproot output */ +u8 *scriptpubkey_p2tr(const tal_t *ctx, const struct pubkey *pubkey) +{ + int ok; + secp256k1_xonly_pubkey x_key; + unsigned char x_key_bytes[32]; + //struct sha256 h; + u8 *script = tal_arr(ctx, u8, 0); + + add_op(&script, OP_1); + + + ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, + &x_key, + /* pk_parity */ NULL, + &(pubkey->pubkey)); + assert(ok); + + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, + x_key_bytes, + &x_key); + assert(ok); + + script_push_bytes(&script, x_key_bytes, sizeof(x_key_bytes)); + assert(tal_count(script) == BITCOIN_SCRIPTPUBKEY_P2TR_LEN); + return script; +} + /* BOLT #3: * * #### `to_remote` Output diff --git a/bitcoin/script.h b/bitcoin/script.h index 89f225ae860f..ec824809bf86 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -53,6 +53,9 @@ u8 *p2wpkh_scriptcode(const tal_t *ctx, const struct pubkey *key); /* Create an output script for a 32-byte witness program. */ u8 *scriptpubkey_p2wsh(const tal_t *ctx, const u8 *witnessscript); +/* Create an output script for a taproot output */ +u8 *scriptpubkey_p2tr(const tal_t *ctx, const struct pubkey *pubkey); + /* Create an output script for a 20-byte witness program. */ u8 *scriptpubkey_p2wpkh(const tal_t *ctx, const struct pubkey *key); @@ -177,4 +180,7 @@ void script_push_bytes(u8 **scriptp, const void *mem, size_t len); /* OP_0 + PUSH(32-byte-hash) */ #define BITCOIN_SCRIPTPUBKEY_P2WSH_LEN (1 + 1 + 32) +/* OP_1 + PUSH(32-byte-key) */ +#define BITCOIN_SCRIPTPUBKEY_P2TR_LEN (1 + 1 + 32) + #endif /* LIGHTNING_BITCOIN_SCRIPT_H */ diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 4a928e08d1f9..f00776584964 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -158,55 +158,60 @@ void bip340_sign_hash(const struct privkey *privkey, assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); } -void bipmusig_finalize_keys(secp256k1_xonly_pubkey *agg_pk, +void bipmusig_finalize_keys(struct pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_xonly_pubkey * const* pubkeys, + const struct pubkey * const* pubkeys, size_t n_pubkeys, const struct sha256 *tap_merkle_root, unsigned char *tap_tweak_out) { int i, ok; unsigned char taptweak_preimage[64]; - secp256k1_pubkey tmp_pk; + secp256k1_xonly_pubkey agg_x_key; assert(n_pubkeys <= 100); /* Sorting moves pubkeys themselves, we copy and discard after */ - secp256k1_xonly_pubkey pubkeys_copy[100]; - const secp256k1_xonly_pubkey *pubkeys_ptr[100]; + secp256k1_xonly_pubkey x_keys[100]; + const secp256k1_xonly_pubkey *x_keys_ptr[100]; + for (i=0; i < n_pubkeys; ++i) { - memcpy(&pubkeys_copy[i], pubkeys[i], sizeof(secp256k1_xonly_pubkey)); - pubkeys_ptr[i] = &pubkeys_copy[i]; + ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &x_keys[i], /* pk_parity */ NULL, + &(pubkeys[i]->pubkey)); + assert(ok); + x_keys_ptr[i] = &x_keys[i]; } ok = secp256k1_xonly_sort(secp256k1_ctx, - pubkeys_ptr, + x_keys_ptr, n_pubkeys); assert(ok); ok = secp256k1_musig_pubkey_agg(secp256k1_ctx, NULL /* scratch */, - agg_pk, + &agg_x_key, keyagg_cache, - pubkeys_ptr, + x_keys_ptr, n_pubkeys); assert(ok); - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, agg_pk); + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &agg_x_key); assert(ok); - if (tap_merkle_root) { + if (!tap_merkle_root) { + /* No-tapscript recommended commitment: Q = P + int(hashTapTweak(bytes(P)))G */ + ok = wally_tagged_hash(taptweak_preimage, 32, "TapTweak", tap_tweak_out); + assert(ok == WALLY_OK); + ok = secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_ctx, &(agg_pk->pubkey), keyagg_cache, tap_tweak_out); + assert(ok); + } else { + /* Otherwise: Q = P + int(hashTapTweak(bytes(P)||tap_merkle_root))G */ memcpy(taptweak_preimage + 32, tap_merkle_root->u.u8, sizeof(tap_merkle_root->u.u8)); - ok = wally_tagged_hash(taptweak_preimage, sizeof(taptweak_preimage), "TapTweak", tap_tweak_out); - assert(ok == WALLY_OK); - - /* Tweak, if script path spend */ - ok = secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_ctx, &tmp_pk, keyagg_cache, tap_tweak_out); - + ok = secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_ctx, &(agg_pk->pubkey), keyagg_cache, tap_tweak_out); assert(ok); } } diff --git a/bitcoin/signature.h b/bitcoin/signature.h index adb596a43bdd..88cd0781eae4 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -107,21 +107,21 @@ void bip340_sign_hash(const struct privkey *privkey, /** * bipmusig_finalize_keys - Aggregate keys in lexigraphically - * sorted order, tweaks if required for keyspend, + * sorted order, tweaks required for keyspend, * and initializes the cache required for signing * sessions - * @agg_pk: Aggregated public key to be constructed + * @agg_pk: Aggregated, tweaked public key to be constructed * @keyagg_cache: Cache to be used for signing session and validation * @pubkeys: Array of pubkeys to be aggregated * @n_pubkeys: Number of public keys in @pubkeys * @tap_merkle_root: Merkle root for taptree, to be used in tweaking. * NULL if script path spending is used. * @tap_tweak_out: Set to `t` in `t = hashTapTweak(p || k_m)` of BIP341. - Must be NULL iff @tap_merkle_root is NULL, 32 bytes otherwise. + N.B. if @tap_merkle_root if NULL, k_m is implicitly the empty string. */ -void bipmusig_finalize_keys(secp256k1_xonly_pubkey *agg_pk, +void bipmusig_finalize_keys(struct pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_xonly_pubkey * const* pubkeys, + const struct pubkey * const* pubkeys, size_t n_pubkeys, const struct sha256 *tap_merkle_root, unsigned char *tap_tweak_out); diff --git a/devtools/.gitignore b/devtools/.gitignore index 9f95803ced42..33b1284e52e8 100644 --- a/devtools/.gitignore +++ b/devtools/.gitignore @@ -12,6 +12,7 @@ mkclose mkcommit mkencoded mkfunding +eltoo_mkfunding mkgossip mkquery onion diff --git a/devtools/Makefile b/devtools/Makefile index ba529da0f66f..07d6e85de284 100644 --- a/devtools/Makefile +++ b/devtools/Makefile @@ -1,4 +1,4 @@ -DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route devtools/bolt12-cli devtools/encodeaddr devtools/features devtools/fp16 +DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/eltoo_mkfunding devtools/mkclose devtools/mkgossip devtools/mkencoded devtools/mkquery devtools/lightning-checkmessage devtools/topology devtools/route devtools/bolt12-cli devtools/encodeaddr devtools/features devtools/fp16 ifeq ($(HAVE_SQLITE3),1) DEVTOOLS += devtools/checkchannels endif @@ -78,6 +78,8 @@ devtools/mkcommit: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) common/d devtools/mkfunding: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o common/key_derive.o devtools/mkfunding.o +devtools/eltoo_mkfunding: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o common/key_derive.o devtools/eltoo_mkfunding.o + devtools/mkclose: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/mkclose.o devtools/mkgossip: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o common/utxo.o common/permute_tx.o common/key_derive.o devtools/mkgossip.o diff --git a/devtools/eltoo_mkfunding.c b/devtools/eltoo_mkfunding.c new file mode 100644 index 000000000000..f3c25acbeb5b --- /dev/null +++ b/devtools/eltoo_mkfunding.c @@ -0,0 +1,190 @@ +/* For example, in the spec tests we use the following keys: + * + * lightning/devtools/mkfunding 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b 1 0.01btc 253 76edf0c303b9e692da9cb491abedef46ca5b81d32f102eb4648461b239cb0f99 0000000000000000000000000000000000000000000000000000000000000010 0000000000000000000000000000000000000000000000000000000000000020 + * + * lightning/devtools/mkfunding 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b 0 0.02btc 253 bc2f48a76a6b8815940accaf01981d3b6347a68fbe844f81c50ecbadf27cd179 0000000000000000000000000000000000000000000000000000000000000030 0000000000000000000000000000000000000000000000000000000000000040 + * + * lightning/devtools/mkfunding 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b 3 0.03btc 253 16c5027616e940d1e72b4c172557b3b799a93c0582f924441174ea556aadd01c 0000000000000000000000000000000000000000000000000000000000000050 0000000000000000000000000000000000000000000000000000000000000060 + */ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void status_fmt(enum log_level level, + const struct node_id *node_id, + const char *fmt, ...) +{ +} + +static char *sig_as_hex(const struct bitcoin_signature *sig) +{ + u8 compact_sig[64]; + + secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, + compact_sig, + &sig->s); + return tal_hexstr(NULL, compact_sig, sizeof(compact_sig)); +} + +static struct bitcoin_tx *tx_spending_utxo(const tal_t *ctx, + const struct utxo *utxo, + size_t num_output, + u32 nlocktime, + u32 nsequence) +{ + struct bitcoin_tx *tx = bitcoin_tx(ctx, chainparams, 1, num_output, + nlocktime); + + assert(!utxo->is_p2sh); + bitcoin_tx_add_input(tx, &utxo->outpoint, + nsequence, NULL, utxo->amount, + utxo->scriptPubkey, NULL); + + return tx; +} + +static struct bitcoin_tx *funding_tx_eltoo(const tal_t *ctx, + const struct utxo *utxo, + struct amount_sat funding, + const struct pubkey *local_fundingkey, + const struct pubkey *remote_fundingkey) +{ + u8 *wscript; + struct bitcoin_tx *tx; + struct pubkey agg_pk; + secp256k1_musig_keyagg_cache keyagg_cache; + unsigned char tap_tweak_out[32]; + + const struct pubkey *pubkeys[2]; + pubkeys[0] = local_fundingkey; + pubkeys[1] = remote_fundingkey; + + /* Currently untweaked by a taptree */ + bipmusig_finalize_keys(&agg_pk, + &keyagg_cache, + pubkeys, + sizeof(pubkeys), + /* tap_merkle_root */ NULL, + tap_tweak_out); + + tx = tx_spending_utxo(ctx, utxo, + 1, 0, BITCOIN_TX_DEFAULT_SEQUENCE); + + /* Generate P2TR scriptpubkey */ + /* FIXME taproot PSBT support? */ + bitcoin_tx_add_output(tx, scriptpubkey_p2wsh(tx, wscript), wscript, funding); + tal_free(wscript); + + bitcoin_tx_finalize(tx); + assert(bitcoin_tx_check(tx)); + return tx; +} + + +int main(int argc, char *argv[]) +{ + struct privkey input_privkey; + struct privkey local_funding_privkey, remote_funding_privkey; + struct pubkey funding_localkey, funding_remotekey, inputkey; + struct amount_sat fee, funding_amount; + unsigned int feerate_per_kw; + int argnum; + struct bitcoin_tx *tx; + size_t weight; + struct utxo input; + struct bitcoin_signature sig; + struct bitcoin_txid txid; + u8 **witnesses; + + setup_locale(); + chainparams = chainparams_for_network("bitcoin"); + + secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | + SECP256K1_CONTEXT_SIGN); + + if (argc != 1 + 7) + errx(1, "Usage: mkfunding "); + + input.is_p2sh = false; + input.close_info = NULL; + + argnum = 1; + if (!bitcoin_txid_from_hex(argv[argnum], + strlen(argv[argnum]), &input.outpoint.txid)) + errx(1, "Bad input-txid"); + argnum++; + input.outpoint.n = atoi(argv[argnum++]); + if (!parse_amount_sat(&input.amount, argv[argnum], strlen(argv[argnum]))) + errx(1, "Bad input-amount"); + argnum++; + feerate_per_kw = atoi(argv[argnum++]); + if (!hex_decode(argv[argnum], strlen(argv[argnum]), + &input_privkey, sizeof(input_privkey))) + errx(1, "Parsing input-privkey"); + argnum++; + if (!hex_decode(argv[argnum], strlen(argv[argnum]), + &local_funding_privkey, sizeof(local_funding_privkey))) + errx(1, "Parsing local-funding-privkey"); + argnum++; + if (!hex_decode(argv[argnum], strlen(argv[argnum]), + &remote_funding_privkey, sizeof(remote_funding_privkey))) + errx(1, "Parsing remote-funding-privkey"); + argnum++; + + if (!pubkey_from_privkey(&input_privkey, &inputkey) + || !pubkey_from_privkey(&local_funding_privkey, &funding_localkey) + || !pubkey_from_privkey(&remote_funding_privkey, &funding_remotekey)) + errx(1, "Bad privkeys"); + + /* nVersion, input count, output count, nLocktime */ + weight = 4 * (4 + 1 + 1 + 4); + /* Add segwit fields: marker + flag */ + weight += 1 + 1; + /* Single output: Satoshis, script length, p2tr. */ + weight += 4 * (8 + 1 + BITCOIN_SCRIPTPUBKEY_P2TR_LEN); + /* Single input: txid, index, scriptlen, nSequence */ + weight += 4 * (32 + 4 + 1 + 4); + /* Single witness: witness element count, len[0], sig, len[2], key */ + weight += 1 + (1 + 73 + 1 + 33); + + fee = amount_tx_fee(feerate_per_kw, weight); + if (!amount_sat_sub(&funding_amount, input.amount, fee)) + errx(1, "Input %s can't afford fee %s", + type_to_string(NULL, struct amount_sat, &input.amount), + type_to_string(NULL, struct amount_sat, &fee)); + + /* No change output, so we don't need a bip32 base. */ + tx = funding_tx_eltoo(NULL, &input, funding_amount, + &funding_localkey, &funding_remotekey); + + /* P2WSH of inputkey */ + bitcoin_tx_input_set_script(tx, 0, NULL); + sign_tx_input(tx, 0, NULL, p2wpkh_scriptcode(NULL, &inputkey), + &input_privkey, &inputkey, + SIGHASH_ALL, &sig); + witnesses = bitcoin_witness_p2wpkh(NULL, &sig, &inputkey); + bitcoin_tx_input_set_witness(tx, 0, witnesses); + + printf("# funding sig: %s\n", sig_as_hex(&sig)); + printf("# funding witnesses: [\n"); + for (size_t i = 0; i < tal_count(witnesses); i++) + printf("\t%s\n", tal_hex(NULL, witnesses[i])); + printf("# ]\n"); + printf("# funding amount: %s\n", + type_to_string(NULL, struct amount_sat, &funding_amount)); + + bitcoin_txid(tx, &txid); + printf("# funding txid: %s\n", + type_to_string(NULL, struct bitcoin_txid, &txid)); + + printf("tx: %s\n", tal_hex(NULL, linearize_tx(NULL, tx))); + + return 0; +} From cec994f98b560c08c5639546ed3f8e53d5a2484b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 30 Jun 2022 12:38:19 -0400 Subject: [PATCH 020/283] Compiling --- devtools/eltoo_mkfunding.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/devtools/eltoo_mkfunding.c b/devtools/eltoo_mkfunding.c index f3c25acbeb5b..4e8a66831cb0 100644 --- a/devtools/eltoo_mkfunding.c +++ b/devtools/eltoo_mkfunding.c @@ -56,7 +56,7 @@ static struct bitcoin_tx *funding_tx_eltoo(const tal_t *ctx, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey) { - u8 *wscript; + //u8 *wscript; struct bitcoin_tx *tx; struct pubkey agg_pk; secp256k1_musig_keyagg_cache keyagg_cache; @@ -78,9 +78,9 @@ static struct bitcoin_tx *funding_tx_eltoo(const tal_t *ctx, 1, 0, BITCOIN_TX_DEFAULT_SEQUENCE); /* Generate P2TR scriptpubkey */ - /* FIXME taproot PSBT support? */ - bitcoin_tx_add_output(tx, scriptpubkey_p2wsh(tx, wscript), wscript, funding); - tal_free(wscript); + /* FIXME taproot PSBT support with taproot fields PSBT_OUT_TAP_INTERNAL_KEY PSBT_OUT_TAP_TREE */ + bitcoin_tx_add_output(tx, scriptpubkey_p2tr(tx, &agg_pk), /* wscript */ NULL, funding); + // tal_free(wscript); bitcoin_tx_finalize(tx); assert(bitcoin_tx_check(tx)); From d5f8704647a3590fb0308cc4efeca58dba3632b3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 30 Jun 2022 17:13:04 -0400 Subject: [PATCH 021/283] Checkin --- bitcoin/script.c | 11 +++++++++++ bitcoin/script.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/bitcoin/script.c b/bitcoin/script.c index 2cea635ba381..d0f940db974b 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -914,3 +914,14 @@ bool scripteq(const u8 *s1, const u8 *s2) return false; return memcmp(s1, s2, tal_count(s1)) == 0; } + +u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx) +{ + u8 *script = tal_arr(ctx, u8, 0); + + /* BOLT #3: + * FIXME cite the extension bolts + */ + add_op(&script, OP_TRUE); + return script; +} diff --git a/bitcoin/script.h b/bitcoin/script.h index ec824809bf86..c16998d85771 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -168,6 +168,9 @@ bool scripteq(const u8 *s1, const u8 *s2); /* Raw "push these bytes" accessor. */ void script_push_bytes(u8 **scriptp, const void *mem, size_t len); +/* "anyonecanspend" Ephemeral anchor outputs */ +u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx); + /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) From 817dc1d16ec8a90c8c46db77a22584ff86887732 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 30 Jun 2022 17:13:26 -0400 Subject: [PATCH 022/283] f --- channeld/settlement_tx.c | 433 +++++++++++++++++++++++++++++++++ channeld/settlement_tx.h | 91 +++++++ common/initial_settlement_tx.c | 286 ++++++++++++++++++++++ common/initial_settlement_tx.h | 63 +++++ 4 files changed, 873 insertions(+) create mode 100644 channeld/settlement_tx.c create mode 100644 channeld/settlement_tx.h create mode 100644 common/initial_settlement_tx.c create mode 100644 common/initial_settlement_tx.h diff --git a/channeld/settlement_tx.c b/channeld/settlement_tx.c new file mode 100644 index 000000000000..2fdf0df1ac62 --- /dev/null +++ b/channeld/settlement_tx.c @@ -0,0 +1,433 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + +static bool trim(const struct htlc *htlc, + u32 feerate_per_kw, + struct amount_sat dust_limit, + bool option_anchor_outputs, + enum side side) +{ + return htlc_is_trimmed(htlc_owner(htlc), htlc->amount, + feerate_per_kw, dust_limit, side, + option_anchor_outputs); +} + +size_t commit_tx_num_untrimmed(const struct htlc **htlcs, + u32 feerate_per_kw, + struct amount_sat dust_limit, + bool option_anchor_outputs, + enum side side) +{ + size_t i, n; + + for (i = n = 0; i < tal_count(htlcs); i++) + n += !trim(htlcs[i], feerate_per_kw, dust_limit, + option_anchor_outputs, side); + + return n; +} + +bool commit_tx_amount_trimmed(const struct htlc **htlcs, + u32 feerate_per_kw, + struct amount_sat dust_limit, + bool option_anchor_outputs, + enum side side, + struct amount_msat *amt) +{ + for (size_t i = 0; i < tal_count(htlcs); i++) { + if (trim(htlcs[i], feerate_per_kw, dust_limit, + option_anchor_outputs, side)) + if (!amount_msat_add(amt, *amt, htlcs[i]->amount)) + return false; + } + return true; +} + +static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n, + const struct htlc *htlc, + const struct keyset *keyset, + bool option_anchor_outputs) +{ + struct ripemd160 ripemd; + u8 *wscript, *p2wsh; + struct amount_sat amount = amount_msat_to_sat_round_down(htlc->amount); + + ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); + wscript = htlc_offered_wscript(tx, &ripemd, keyset, + option_anchor_outputs); + p2wsh = scriptpubkey_p2wsh(tx, wscript); + bitcoin_tx_add_output(tx, p2wsh, wscript, amount); + SUPERVERBOSE("# HTLC #%" PRIu64 " offered amount %"PRIu64" wscript %s\n", htlc->id, + amount.satoshis, /* Raw: BOLT 3 output match */ + tal_hex(wscript, wscript)); + tal_free(wscript); +} + +static void add_received_htlc_out(struct bitcoin_tx *tx, size_t n, + const struct htlc *htlc, + const struct keyset *keyset, + bool option_anchor_outputs) +{ + struct ripemd160 ripemd; + u8 *wscript, *p2wsh; + struct amount_sat amount; + + ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); + wscript = htlc_received_wscript(tx, &ripemd, &htlc->expiry, keyset, + option_anchor_outputs); + p2wsh = scriptpubkey_p2wsh(tx, wscript); + amount = amount_msat_to_sat_round_down(htlc->amount); + + bitcoin_tx_add_output(tx, p2wsh, wscript, amount); + + SUPERVERBOSE("# HTLC #%"PRIu64" received amount %"PRIu64" wscript %s\n", + htlc->id, + amount.satoshis, /* Raw: BOLT 3 output match */ + tal_hex(wscript, wscript)); + tal_free(wscript); +} + +struct bitcoin_tx *commit_tx(const tal_t *ctx, + const struct bitcoin_outpoint *funding, + struct amount_sat funding_sats, + const struct pubkey *local_funding_key, + const struct pubkey *remote_funding_key, + enum side opener, + u16 to_self_delay, + u32 lease_expiry, + u32 blockheight, + const struct keyset *keyset, + u32 feerate_per_kw, + struct amount_sat dust_limit, + struct amount_msat self_pay, + struct amount_msat other_pay, + const struct htlc **htlcs, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + u64 obscured_commitment_number, + bool option_anchor_outputs, + enum side side) +{ + struct amount_sat base_fee; + struct amount_msat total_pay; + struct bitcoin_tx *tx; + size_t i, n, untrimmed; + /* Is this the lessor ? */ + enum side lessor = !opener; + u32 *cltvs; + bool to_local, to_remote; + struct htlc *dummy_to_local = (struct htlc *)0x01, + *dummy_to_remote = (struct htlc *)0x02; + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, + local_funding_key, + remote_funding_key); + u32 csv_lock = lease_expiry > blockheight ? + lease_expiry - blockheight : 1; + + if (!amount_msat_add(&total_pay, self_pay, other_pay)) + abort(); + assert(!amount_msat_greater_sat(total_pay, funding_sats)); + + /* BOLT #3: + * + * 1. Calculate which committed HTLCs need to be trimmed (see + * [Trimmed Outputs](#trimmed-outputs)). + */ + untrimmed = commit_tx_num_untrimmed(htlcs, + feerate_per_kw, + dust_limit, + option_anchor_outputs, + side); + + /* BOLT #3: + * + * 2. Calculate the base [commitment transaction + * fee](#fee-calculation). + */ + base_fee = commit_tx_base_fee(feerate_per_kw, untrimmed, + option_anchor_outputs); + + SUPERVERBOSE("# base commitment transaction fee = %"PRIu64"\n", + base_fee.satoshis /* Raw: spec uses raw numbers */); + + /* BOLT #3: + * If `option_anchors` applies to the commitment + * transaction, also subtract two times the fixed anchor size + * of 330 sats from the funder (either `to_local` or + * `to_remote`). + */ + if (option_anchor_outputs + && !amount_sat_add(&base_fee, base_fee, AMOUNT_SAT(660))) + /* Can't overflow: feerate is u32. */ + abort(); + + /* BOLT #3: + * + * 3. Subtract this base fee from the funder (either `to_local` or + * `to_remote`). + */ + try_subtract_fee(opener, side, base_fee, &self_pay, &other_pay); + +#ifdef PRINT_ACTUAL_FEE + { + struct amount_sat out = AMOUNT_SAT(0); + bool ok = true; + for (i = 0; i < tal_count(htlcs); i++) { + if (!trim(htlcs[i], feerate_per_kw, dust_limit, + option_anchor_outputs, side)) + ok &= amount_sat_add(&out, out, amount_msat_to_sat_round_down(htlcs[i]->amount)); + } + if (amount_msat_greater_eq_sat(self_pay, dust_limit)) + ok &= amount_sat_add(&out, out, amount_msat_to_sat_round_down(self_pay)); + if (amount_msat_greater_eq_sat(other_pay, dust_limit)) + ok &= amount_sat_add(&out, out, amount_msat_to_sat_round_down(other_pay)); + assert(ok); + SUPERVERBOSE("# actual commitment transaction fee = %"PRIu64"\n", + funding_sats.satoshis - out.satoshis); /* Raw: test output */ + } +#endif + + /* Worst-case sizing: both to-local and to-remote outputs, and anchors. */ + tx = bitcoin_tx(ctx, chainparams, 1, untrimmed + 2 + 2, 0); + + /* We keep track of which outputs have which HTLCs */ + *htlcmap = tal_arr(tx, const struct htlc *, tx->wtx->outputs_allocation_len); + + /* We keep cltvs for tie-breaking HTLC outputs; we use the same order + * for sending the htlc txs, so it may matter. */ + cltvs = tal_arr(tmpctx, u32, tx->wtx->outputs_allocation_len); + + /* This could be done in a single loop, but we follow the BOLT + * literally to make comments in test vectors clearer. */ + + n = 0; + /* BOLT #3: + * + * 4. For every offered HTLC, if it is not trimmed, add an + * [offered HTLC output](#offered-htlc-outputs). + */ + for (i = 0; i < tal_count(htlcs); i++) { + if (htlc_owner(htlcs[i]) != side) + continue; + if (trim(htlcs[i], feerate_per_kw, dust_limit, + option_anchor_outputs, side)) + continue; + add_offered_htlc_out(tx, n, htlcs[i], keyset, + option_anchor_outputs); + (*htlcmap)[n] = htlcs[i]; + cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry); + n++; + } + + /* BOLT #3: + * + * 5. For every received HTLC, if it is not trimmed, add an + * [received HTLC output](#received-htlc-outputs). + */ + for (i = 0; i < tal_count(htlcs); i++) { + if (htlc_owner(htlcs[i]) == side) + continue; + if (trim(htlcs[i], feerate_per_kw, dust_limit, + option_anchor_outputs, side)) + continue; + add_received_htlc_out(tx, n, htlcs[i], keyset, + option_anchor_outputs); + (*htlcmap)[n] = htlcs[i]; + cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry); + n++; + } + + /* BOLT #3: + * + * 6. If the `to_local` amount is greater or equal to + * `dust_limit_satoshis`, add a [`to_local` + * output](#to_local-output). + */ + if (amount_msat_greater_eq_sat(self_pay, dust_limit)) { + /* BOLT- #3: + * In a leased channel, the `to_local` output that + * pays the `accepter` node is modified so that its + * CSV is equal to the greater of the + * `to_self_delay` or the `lease_end` - `blockheight`. + */ + u8 *wscript = to_self_wscript(tmpctx, + to_self_delay, + side == lessor ? csv_lock : 0, + keyset); + u8 *p2wsh = scriptpubkey_p2wsh(tx, wscript); + struct amount_sat amount = amount_msat_to_sat_round_down(self_pay); + + bitcoin_tx_add_output(tx, p2wsh, wscript, amount); + /* Add a dummy entry to the htlcmap so we can recognize it later */ + (*htlcmap)[n] = direct_outputs ? dummy_to_local : NULL; + /* We don't assign cltvs[n]: if we use it, order doesn't matter. + * However, valgrind will warn us something wierd is happening */ + SUPERVERBOSE("# to_local amount %"PRIu64" wscript %s\n", + amount.satoshis, /* Raw: BOLT 3 output match */ + tal_hex(tmpctx, wscript)); + n++; + to_local = true; + } else + to_local = false; + + /* BOLT #3: + * + * 7. If the `to_remote` amount is greater or equal to + * `dust_limit_satoshis`, add a [`to_remote` + * output](#to_remote-output). + */ + u8 *redeem; + if (amount_msat_greater_eq_sat(other_pay, dust_limit)) { + struct amount_sat amount = amount_msat_to_sat_round_down(other_pay); + u8 *scriptpubkey; + int pos; + + /* BOLT #3: + * + * #### `to_remote` Output + * + * If `option_anchors` applies to the commitment + * transaction, the `to_remote` output is encumbered by a one + * block csv lock. + * OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY + * + *... + * Otherwise, this output is a simple P2WPKH to `remotepubkey`. + */ + if (option_anchor_outputs) { + redeem = anchor_to_remote_redeem(tmpctx, + &keyset->other_payment_key, + (!side) == lessor ? + csv_lock : 1); + /* BOLT- #3: + * ##### Leased channel (`option_will_fund`) + * + * If a `lease` applies to the channel, the + * `to_remote` output of the `initiator` + * ensures the `leasor` funds are not + * spendable until the lease expires. + * + * OP_CHECKSIGVERIFY + * MAX(1, lease_end - blockheight) + * OP_CHECKSEQUENCEVERIFY + */ + scriptpubkey = scriptpubkey_p2wsh(tmpctx, redeem); + } else { + redeem = NULL; + scriptpubkey = scriptpubkey_p2wpkh(tmpctx, + &keyset->other_payment_key); + } + pos = bitcoin_tx_add_output(tx, scriptpubkey, redeem, amount); + assert(pos == n); + (*htlcmap)[n] = direct_outputs ? dummy_to_remote : NULL; + /* We don't assign cltvs[n]: if we use it, order doesn't matter. + * However, valgrind will warn us something wierd is happening */ + SUPERVERBOSE("# to_remote amount %"PRIu64" P2WPKH(%s)\n", + amount.satoshis, /* Raw: BOLT 3 output match */ + type_to_string(tmpctx, struct pubkey, + &keyset->other_payment_key)); + n++; + + to_remote = true; + } else { + to_remote = false; + redeem = NULL; + } + + /* BOLT #3: + * + * 8. If `option_anchors` applies to the commitment transaction: + * * if `to_local` exists or there are untrimmed HTLCs, add a + * [`to_local_anchor` output]... + * * if `to_remote` exists or there are untrimmed HTLCs, add a + * [`to_remote_anchor` output] + */ + if (option_anchor_outputs) { + if (to_local || untrimmed != 0) { + tx_add_anchor_output(tx, local_funding_key); + (*htlcmap)[n] = NULL; + n++; + } + + if (to_remote || untrimmed != 0) { + tx_add_anchor_output(tx, remote_funding_key); + (*htlcmap)[n] = NULL; + n++; + } + } + + /* BOLT #2: + * + * - MUST set `channel_reserve_satoshis` greater than or equal to + * `dust_limit_satoshis`. + */ + /* This means there must be at least one output. */ + assert(n > 0); + + assert(n <= tx->wtx->outputs_allocation_len); + tal_resize(htlcmap, n); + + /* BOLT #3: + * + * 9. Sort the outputs into [BIP 69+CLTV + * order](#transaction-input-and-output-ordering) + */ + permute_outputs(tx, cltvs, (const void **)*htlcmap); + + /* BOLT #3: + * + * ## Commitment Transaction + * + * * version: 2 + */ + assert(tx->wtx->version == 2); + + /* BOLT #3: + * + * * locktime: upper 8 bits are 0x20, lower 24 bits are the lower 24 bits of the obscured commitment number + */ + bitcoin_tx_set_locktime(tx, + (0x20000000 | (obscured_commitment_number & 0xFFFFFF))); + + /* BOLT #3: + * + * * txin count: 1 + * * `txin[0]` outpoint: `txid` and `output_index` from + * `funding_created` message + */ + /* BOLT #3: + * + * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured commitment number + */ + u32 sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF)); + bitcoin_tx_add_input(tx, funding, + sequence, NULL, funding_sats, NULL, funding_wscript); + + /* Identify the direct outputs (to_us, to_them). */ + if (direct_outputs != NULL) { + direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; + for (size_t i = 0; i < tx->wtx->num_outputs; i++) { + if ((*htlcmap)[i] == dummy_to_local) { + (*htlcmap)[i] = NULL; + direct_outputs[LOCAL] = tx->wtx->outputs + i; + } else if ((*htlcmap)[i] == dummy_to_remote) { + (*htlcmap)[i] = NULL; + direct_outputs[REMOTE] = tx->wtx->outputs + i; + } + } + } + + bitcoin_tx_finalize(tx); + assert(bitcoin_tx_check(tx)); + + return tx; +} diff --git a/channeld/settlement_tx.h b/channeld/settlement_tx.h new file mode 100644 index 000000000000..fc2db029de40 --- /dev/null +++ b/channeld/settlement_tx.h @@ -0,0 +1,91 @@ +#ifndef LIGHTNING_CHANNELD_COMMIT_TX_H +#define LIGHTNING_CHANNELD_COMMIT_TX_H +#include "config.h" +#include +#include + +struct keyset; + +/** + * commit_tx_num_untrimmed: how many of these htlc outputs will commit tx have? + * @htlcs: tal_arr of HTLCs + * @feerate_per_kw: feerate to use + * @dust_limit: dust limit below which to trim outputs. + * @option_anchor_outputs: does option_anchor_outputs apply to this channel? + * @side: from which side's point of view + * @option_anchor_outputs: does option_anchor_outputs apply to this channel? + * + * We need @side because HTLC fees are different for offered and + * received HTLCs. + */ +size_t commit_tx_num_untrimmed(const struct htlc **htlcs, + u32 feerate_per_kw, + struct amount_sat dust_limit, + bool option_anchor_outputs, + enum side side); + +/** + * commit_tx_amount_trimmed: what's the sum of trimmed htlc amounts? + * @htlcs: tal_arr of HTLCs + * @feerate_per_kw: feerate to use + * @dust_limit: dust limit below which to trim outputs. + * @option_anchor_outputs: does option_anchor_outputs apply to this channel? + * @side: from which side's point of view + * @amt: returned, total value trimmed from this commitment + * + * We need @side because HTLC fees are different for offered and + * received HTLCs. + * + * Returns false if unable to calculate amount trimmed. + */ +bool commit_tx_amount_trimmed(const struct htlc **htlcs, + u32 feerate_per_kw, + struct amount_sat dust_limit, + bool option_anchor_outputs, + enum side side, + struct amount_msat *amt); +/** + * commit_tx: create (unsigned) commitment tx to spend the funding tx output + * @ctx: context to allocate transaction and @htlc_map from. + * @funding, @funding_sats: funding outpoint and amount + * @local_funding_key, @remote_funding_key: keys for funding input. + * @opener: is the LOCAL or REMOTE paying the fee? + * @keyset: keys derived for this commit tx. + * @feerate_per_kw: feerate to use + * @dust_limit: dust limit below which to trim outputs. + * @self_pay: amount to pay directly to self + * @other_pay: amount to pay directly to the other side + * @htlcs: tal_arr of htlcs committed by transaction (some may be trimmed) + * @htlc_map: outputed map of outnum->HTLC (NULL for direct outputs). + * @obscured_commitment_number: number to encode in commitment transaction + * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). + * @option_anchor_outputs: does option_anchor_outputs apply to this channel? + * @side: side to generate commitment transaction for. + * @option_anchor_outputs: does option_anchor_outputs apply to this channel? + * + * We need to be able to generate the remote side's tx to create signatures, + * but the BOLT is expressed in terms of generating our local commitment + * transaction, so we carefully use the terms "self" and "other" here. + */ +struct bitcoin_tx *commit_tx(const tal_t *ctx, + const struct bitcoin_outpoint *funding, + struct amount_sat funding_sats, + const struct pubkey *local_funding_key, + const struct pubkey *remote_funding_key, + enum side opener, + u16 to_self_delay, + u32 lease_expiry, + u32 blockheight, + const struct keyset *keyset, + u32 feerate_per_kw, + struct amount_sat dust_limit, + struct amount_msat self_pay, + struct amount_msat other_pay, + const struct htlc **htlcs, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + u64 obscured_commitment_number, + bool option_anchor_outputs, + enum side side); + +#endif /* LIGHTNING_CHANNELD_COMMIT_TX_H */ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c new file mode 100644 index 000000000000..39c7e5aad545 --- /dev/null +++ b/common/initial_settlement_tx.c @@ -0,0 +1,286 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + + +void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) +{ + u8 *spk = bitcoin_spk_ephemeral_anchor(tmpctx); + bitcoin_tx_add_output(tx, spk, /* wscript */ NULL, AMOUNT_SAT(0)); +} + +struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, + const struct bitcoin_outpoint *update_output, + struct amount_sat update_output_sats, + const struct pubkey funding_key[NUM_SIDES], + enum side opener, + u16 to_self_delay, + const struct keyset *keyset, + u32 feerate_per_kw, + struct amount_sat dust_limit, + struct amount_msat self_pay, + struct amount_msat other_pay, + struct amount_sat self_reserve, + u64 obscured_commitment_number, + struct wally_tx_output *direct_outputs[NUM_SIDES], + enum side side, + u32 csv_lock, + bool option_anchor_outputs, + char** err_reason) +{ + struct amount_sat base_fee; + struct bitcoin_tx *tx; + size_t n, untrimmed; + bool to_local, to_remote; + struct amount_msat total_pay; + struct amount_sat amount; + enum side lessor = !opener; + u32 sequence; + void *dummy_local = (void *)LOCAL, *dummy_remote = (void *)REMOTE; + /* There is a direct, and possibly an anchor output for each side. */ + const void *output_order[2 * NUM_SIDES]; + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, + &funding_key[LOCAL], + &funding_key[REMOTE]); + + if (!amount_msat_add(&total_pay, self_pay, other_pay)) + abort(); + assert(!amount_msat_greater_sat(total_pay, funding_sats)); + + /* BOLT #3: + * + * 1. Calculate which committed HTLCs need to be trimmed (see + * [Trimmed Outputs](#trimmed-outputs)). + */ + untrimmed = 0; + + /* BOLT #3: + * + * 2. Calculate the base [commitment transaction + * fee](#fee-calculation). + */ + base_fee = commit_tx_base_fee(feerate_per_kw, untrimmed, + option_anchor_outputs); + + /* BOLT: + * If `option_anchor_outputs` applies to the commitment + * transaction, also subtract two times the fixed anchor size + * of 330 sats from the funder (either `to_local` or + * `to_remote`). + */ + if (option_anchor_outputs + && !amount_sat_add(&base_fee, base_fee, AMOUNT_SAT(660))) { + *err_reason = "Funder cannot afford anchor outputs"; + return NULL; + } + + /* BOLT #3: + * + * 3. Subtract this base fee from the funder (either `to_local` or + * `to_remote`). + * If `option_anchors` applies to the commitment transaction, + * also subtract two times the fixed anchor size of 330 sats from the + * funder (either `to_local` or `to_remote`). + */ + if (!try_subtract_fee(opener, side, base_fee, &self_pay, &other_pay)) { + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - it considers `feerate_per_kw` too small for timely + * processing or unreasonably large. + */ + *err_reason = "Funder cannot afford fee on initial commitment transaction"; + status_unusual("Funder cannot afford fee" + " on initial commitment transaction"); + return NULL; + } + + /* FIXME, should be in #2: + * + * The receiving node MUST fail the channel if: + *... + * - both `to_local` and `to_remote` amounts for the initial + * commitment transaction are less than or equal to + * `channel_reserve_satoshis`. + */ + if (!amount_msat_greater_sat(self_pay, self_reserve) + && !amount_msat_greater_sat(other_pay, self_reserve)) { + *err_reason = "Neither self amount nor other amount exceed reserve on " + "initial commitment transaction"; + status_unusual("Neither self amount %s" + " nor other amount %s" + " exceed reserve %s" + " on initial commitment transaction", + type_to_string(tmpctx, struct amount_msat, + &self_pay), + type_to_string(tmpctx, struct amount_msat, + &other_pay), + type_to_string(tmpctx, struct amount_sat, + &self_reserve)); + return NULL; + } + + + /* Worst-case sizing: both to-local and to-remote outputs + anchors. */ + tx = bitcoin_tx(ctx, chainparams, 1, untrimmed + 4, 0); + + /* This could be done in a single loop, but we follow the BOLT + * literally to make comments in test vectors clearer. */ + + n = 0; + /* BOLT #3: + * + * 4. For every offered HTLC, if it is not trimmed, add an + * [offered HTLC output](#offered-htlc-outputs). + */ + + /* BOLT #3: + * + * 5. For every received HTLC, if it is not trimmed, add an + * [received HTLC output](#received-htlc-outputs). + */ + + /* BOLT #3: + * + * 6. If the `to_local` amount is greater or equal to + * `dust_limit_satoshis`, add a [`to_local` + * output](#to_local-output). + */ + if (amount_msat_greater_eq_sat(self_pay, dust_limit)) { + /* FIXME to_self_wscript doesn't exist */ + u8 *wscript = to_self_wscript(tmpctx, + to_self_delay, + side == lessor ? csv_lock : 0, + keyset); + amount = amount_msat_to_sat_round_down(self_pay); + int pos = bitcoin_tx_add_output( + tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); + assert(pos == n); + output_order[n] = dummy_local; + n++; + to_local = true; + } else + to_local = false; + + /* BOLT #3: + * + * 7. If the `to_remote` amount is greater or equal to + * `dust_limit_satoshis`, add a [`to_remote` + * output](#to_remote-output). + */ + if (amount_msat_greater_eq_sat(other_pay, dust_limit)) { + /* BOLT #3: + * + * If `option_anchors` applies to the commitment + * transaction, the `to_remote` output is encumbered by a one + * block csv lock. + * OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY + * + *... + * Otherwise, this output is a simple P2WPKH to `remotepubkey`. + */ + u8 *scriptpubkey; + int pos; + u8 *redeem; + + amount = amount_msat_to_sat_round_down(other_pay); + if (option_anchor_outputs) { + redeem = anchor_to_remote_redeem(tmpctx, + &keyset->other_payment_key, + (!side) == lessor ? csv_lock : 1); + scriptpubkey = scriptpubkey_p2wsh(tmpctx, redeem); + } else { + redeem = NULL; + scriptpubkey = scriptpubkey_p2wpkh(tmpctx, + &keyset->other_payment_key); + } + pos = bitcoin_tx_add_output(tx, scriptpubkey, redeem, amount); + assert(pos == n); + output_order[n] = dummy_remote; + n++; + to_remote = true; + } else + to_remote = false; + + /* BOLT #3: + * 8. If `option_anchors` applies to the commitment transaction: + * * if `to_local` exists or there are untrimmed HTLCs, add a + * [`to_local_anchor` output]... + * * if `to_remote` exists or there are untrimmed HTLCs, add a + * [`to_remote_anchor` output] + */ + if (option_anchor_outputs) { + if (to_local || untrimmed != 0) { + tx_add_anchor_output(tx, &funding_key[side]); + output_order[n] = NULL; + n++; + } + + if (to_remote || untrimmed != 0) { + tx_add_anchor_output(tx, &funding_key[!side]); + output_order[n] = NULL; + n++; + } + } + + assert(n <= tx->wtx->num_outputs); + assert(n <= ARRAY_SIZE(output_order)); + + /* BOLT #3: + * + * 9. Sort the outputs into [BIP 69+CLTV + * order](#transaction-input-and-output-ordering) + */ + permute_outputs(tx, NULL, output_order); + + /* BOLT #3: + * + * ## Commitment Transaction + * + * * version: 2 + */ + assert(tx->wtx->version == 2); + + /* BOLT #3: + * + * * locktime: upper 8 bits are 0x20, lower 24 bits are the + * lower 24 bits of the obscured commitment number + */ + bitcoin_tx_set_locktime(tx, + (0x20000000 | (obscured_commitment_number & 0xFFFFFF))); + + /* BOLT #3: + * + * * txin count: 1 + * * `txin[0]` outpoint: `txid` and `output_index` from + * `funding_created` message + * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured commitment number + * * `txin[0]` script bytes: 0 + */ + sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF)); + bitcoin_tx_add_input(tx, funding, sequence, + NULL, funding_sats, NULL, funding_wscript); + + if (direct_outputs != NULL) { + direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; + for (size_t i = 0; i < tx->wtx->num_outputs; i++) { + if (output_order[i] == dummy_local) + direct_outputs[LOCAL] = &tx->wtx->outputs[i]; + else if (output_order[i] == dummy_remote) + direct_outputs[REMOTE] = &tx->wtx->outputs[i]; + } + } + + /* This doesn't reorder outputs, so we can do this after mapping outputs. */ + bitcoin_tx_finalize(tx); + + assert(bitcoin_tx_check(tx)); + + return tx; +} diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h new file mode 100644 index 000000000000..6eeb760188a0 --- /dev/null +++ b/common/initial_settlement_tx.h @@ -0,0 +1,63 @@ +/* Commit tx without HTLC support; needed for openingd. */ +#ifndef LIGHTNING_COMMON_INITIAL_SETTLEMENT_TX_H +#define LIGHTNING_COMMON_INITIAL_SETTLEMENT_TX_H +#include "config.h" +#include +#include +#include +#include +#include + +struct bitcoin_outpoint; +struct keyset; +struct wally_tx_output; + +/** + * initial_settlement_tx: create (unsigned) commitment tx to spend the first update tx + * @ctx: context to allocate transaction and @htlc_map from. + * @funding, @funding_sats: funding outpoint and amount + * @funding_wscript: scriptPubkey of the funding output + * @funding_keys: funding bitcoin keys + * @opener: is the LOCAL or REMOTE paying the fee? + * @keyset: keys derived for this commit tx. + * @feerate_per_kw: feerate to use + * @dust_limit: dust limit below which to trim outputs. + * @self_pay: amount to pay directly to self + * @other_pay: amount to pay directly to the other side + * @self_reserve: reserve the other side insisted we have + * @obscured_commitment_number: number to encode in commitment transaction + * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). + * @side: side to generate commitment transaction for. + * @option_anchor_outputs: does option_anchor_outputs apply to this channel? + * @err_reason: When NULL is returned, this will point to a human readable reason. + * + * We need to be able to generate the remote side's tx to create signatures, + * but the BOLT is expressed in terms of generating our local commitment + * transaction, so we carefully use the terms "self" and "other" here. + */ +struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, + const struct bitcoin_outpoint *funding, + struct amount_sat funding_sats, + const struct pubkey funding_key[NUM_SIDES], + enum side opener, + u16 to_self_delay, + const struct keyset *keyset, + u32 feerate_per_kw, + struct amount_sat dust_limit, + struct amount_msat self_pay, + struct amount_msat other_pay, + struct amount_sat self_reserve, + u64 obscured_commitment_number, + struct wally_tx_output *direct_outputs[NUM_SIDES], + enum side side, + u32 csv_lock, + bool option_anchor_outputs, + char** err_reason); + + +/* To-other is simply: scriptpubkey_p2wpkh(tx, keyset->other_payment_key) */ + +/* We always add a single ephemeral anchor output to settlement transactions */ +void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx); + +#endif /* LIGHTNING_COMMON_INITIAL_SETTLEMENT_TX_H */ From 3dd0b268655164786936e87ace066811721ba073 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 1 Jul 2022 15:55:48 -0400 Subject: [PATCH 023/283] Not at all complete initial settlement tx construction --- bitcoin/script.c | 32 +++++++ bitcoin/script.h | 3 + common/initial_settlement_tx.c | 168 ++++++++++++--------------------- common/initial_settlement_tx.h | 23 ++--- common/keyset.h | 6 ++ 5 files changed, 108 insertions(+), 124 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index d0f940db974b..3a3eedc361ee 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -925,3 +925,35 @@ u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx) add_op(&script, OP_TRUE); return script; } + +u8 *bitcoin_tapscript_to_node(const struct pubkey *settlement_pubkey) +{ + u8 *script = tal_arr(ctx, u8, 0); + + /* BOLT #?? + * `tr(aggregated_key, EXPR_BALANCE)` + * + * where EXPR_BALANCE = + * + * 1 OP_CHECKSEQUENCEVERIFY settlement_pubkey OP_CHECKSIGVERIFY + */ + add_number(&script, 1); + add_op(&script, OP_CHECKSEQUENCEVERIFY); + add_push_key(&script, settlement_pubkey); + add_op(&script, OP_CHECKSIGVERIFY); + return script; +} + +void compute_taptree_merkle_root(struct *sha256, u8 **scripts, size_t num_scripts) +{ + int ok; + unsigned char tap_version = 0xc0; + + /* Only what's required for eltoo et al for now, sue me */ + assert(num_scripts <= 2); + if (num_scripts == 1) { + /* Let k0 = hashTapLeaf(v || compact_size(size of s) || s); also call it the tapleaf hash. */ + ok = wally_tagged_hash((unsigned char*)scripts[0], tal_count(scripts[0]), "TapBranch", tap_tweak_out); + assert(ok); + } +} diff --git a/bitcoin/script.h b/bitcoin/script.h index c16998d85771..6e9ffbf526bf 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -171,6 +171,9 @@ void script_push_bytes(u8 **scriptp, const void *mem, size_t len); /* "anyonecanspend" Ephemeral anchor outputs */ u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx); +/* to_node balance output script with anti-pinning 1 block CSV */ +u8 *bitcoin_tapscript_to_node(const struct pubkey *settlement_pubkey); + /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 39c7e5aad545..567cd52b9041 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -14,43 +14,52 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) bitcoin_tx_add_output(tx, spk, /* wscript */ NULL, AMOUNT_SAT(0)); } +u8 *to_self_eltoo_wscript(const tal_t *ctx, + const struct keyset *keyset) +{ + return bitcoin_wscript_to_local(ctx, to_self_delay, csv, + &keyset->self_revocation_key, + &keyset->self_delayed_payment_key); +} + struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct bitcoin_outpoint *update_output, struct amount_sat update_output_sats, const struct pubkey funding_key[NUM_SIDES], - enum side opener, - u16 to_self_delay, + u32 shared_delay, const struct keyset *keyset, u32 feerate_per_kw, struct amount_sat dust_limit, struct amount_msat self_pay, struct amount_msat other_pay, struct amount_sat self_reserve, - u64 obscured_commitment_number, + u32 obscured_update_number, struct wally_tx_output *direct_outputs[NUM_SIDES], - enum side side, - u32 csv_lock, - bool option_anchor_outputs, char** err_reason) { - struct amount_sat base_fee; + struct amount_sat base_fee; struct bitcoin_tx *tx; size_t n, untrimmed; bool to_local, to_remote; struct amount_msat total_pay; struct amount_sat amount; enum side lessor = !opener; - u32 sequence; void *dummy_local = (void *)LOCAL, *dummy_remote = (void *)REMOTE; /* There is a direct, and possibly an anchor output for each side. */ const void *output_order[2 * NUM_SIDES]; + struct pubkey *pubkey_ptrs[2]; + const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, &funding_key[LOCAL], &funding_key[REMOTE]); + /* For MuSig aggregation for outputs */ + pubkey_ptrs[0] = &funding_key[0]; + pubkey_ptrs[1] = &funding_key[1]; + if (!amount_msat_add(&total_pay, self_pay, other_pay)) abort(); - assert(!amount_msat_greater_sat(total_pay, funding_sats)); + assert(!amount_msat_greater_sat(total_pay, update_output_sats)); /* BOLT #3: * @@ -59,48 +68,6 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, */ untrimmed = 0; - /* BOLT #3: - * - * 2. Calculate the base [commitment transaction - * fee](#fee-calculation). - */ - base_fee = commit_tx_base_fee(feerate_per_kw, untrimmed, - option_anchor_outputs); - - /* BOLT: - * If `option_anchor_outputs` applies to the commitment - * transaction, also subtract two times the fixed anchor size - * of 330 sats from the funder (either `to_local` or - * `to_remote`). - */ - if (option_anchor_outputs - && !amount_sat_add(&base_fee, base_fee, AMOUNT_SAT(660))) { - *err_reason = "Funder cannot afford anchor outputs"; - return NULL; - } - - /* BOLT #3: - * - * 3. Subtract this base fee from the funder (either `to_local` or - * `to_remote`). - * If `option_anchors` applies to the commitment transaction, - * also subtract two times the fixed anchor size of 330 sats from the - * funder (either `to_local` or `to_remote`). - */ - if (!try_subtract_fee(opener, side, base_fee, &self_pay, &other_pay)) { - /* BOLT #2: - * - * The receiving node MUST fail the channel if: - *... - * - it considers `feerate_per_kw` too small for timely - * processing or unreasonably large. - */ - *err_reason = "Funder cannot afford fee on initial commitment transaction"; - status_unusual("Funder cannot afford fee" - " on initial commitment transaction"); - return NULL; - } - /* FIXME, should be in #2: * * The receiving node MUST fail the channel if: @@ -127,8 +94,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, } - /* Worst-case sizing: both to-local and to-remote outputs + anchors. */ - tx = bitcoin_tx(ctx, chainparams, 1, untrimmed + 4, 0); + /* Worst-case sizing: both to-local and to-remote outputs + single anchor. */ + tx = bitcoin_tx(ctx, chainparams, 1, untrimmed + NUM_SIDES + 1, 0); /* This could be done in a single loop, but we follow the BOLT * literally to make comments in test vectors clearer. */ @@ -148,16 +115,21 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* BOLT #3: * - * 6. If the `to_local` amount is greater or equal to - * `dust_limit_satoshis`, add a [`to_local` - * output](#to_local-output). + * 6. If the `to_node` amount is greater or equal to + * `dust_limit_satoshis`, add a [`to_node` + * output](#to_node-output). */ if (amount_msat_greater_eq_sat(self_pay, dust_limit)) { - /* FIXME to_self_wscript doesn't exist */ - u8 *wscript = to_self_wscript(tmpctx, - to_self_delay, - side == lessor ? csv_lock : 0, - keyset); + struct pubkey agg_pk; + secp256k1_musig_keyagg_cache keyagg_cache; + struct sha256 tap_merkle_root; + unsigned char tap_tweak_out[32]; + + u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.self_payment_key); + /* FIXME compute taptree merkle root */ + bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ sizeof(pubkey_ptrs), + &tap_merkle_root, tap_tweak_out) + amount = amount_msat_to_sat_round_down(self_pay); int pos = bitcoin_tx_add_output( tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); @@ -175,32 +147,27 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * output](#to_remote-output). */ if (amount_msat_greater_eq_sat(other_pay, dust_limit)) { - /* BOLT #3: + /* BOLT #???: * * If `option_anchors` applies to the commitment * transaction, the `to_remote` output is encumbered by a one * block csv lock. * OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY * - *... - * Otherwise, this output is a simple P2WPKH to `remotepubkey`. */ - u8 *scriptpubkey; - int pos; - u8 *redeem; + struct pubkey agg_pk; + secp256k1_musig_keyagg_cache keyagg_cache; + struct sha256 tap_merkle_root; + unsigned char tap_tweak_out[32]; - amount = amount_msat_to_sat_round_down(other_pay); - if (option_anchor_outputs) { - redeem = anchor_to_remote_redeem(tmpctx, - &keyset->other_payment_key, - (!side) == lessor ? csv_lock : 1); - scriptpubkey = scriptpubkey_p2wsh(tmpctx, redeem); - } else { - redeem = NULL; - scriptpubkey = scriptpubkey_p2wpkh(tmpctx, - &keyset->other_payment_key); - } - pos = bitcoin_tx_add_output(tx, scriptpubkey, redeem, amount); + u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.other_payment_key); + /* FIXME compute taptree merkle root */ + bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ sizeof(pubkey_ptrs), + &tap_merkle_root, tap_tweak_out) + + amount = amount_msat_to_sat_round_down(self_pay); + int pos = bitcoin_tx_add_output( + tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); assert(pos == n); output_order[n] = dummy_remote; n++; @@ -208,38 +175,26 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, } else to_remote = false; - /* BOLT #3: - * 8. If `option_anchors` applies to the commitment transaction: - * * if `to_local` exists or there are untrimmed HTLCs, add a - * [`to_local_anchor` output]... - * * if `to_remote` exists or there are untrimmed HTLCs, add a - * [`to_remote_anchor` output] + /* BOLT #???: */ - if (option_anchor_outputs) { - if (to_local || untrimmed != 0) { - tx_add_anchor_output(tx, &funding_key[side]); - output_order[n] = NULL; - n++; - } - - if (to_remote || untrimmed != 0) { - tx_add_anchor_output(tx, &funding_key[!side]); - output_order[n] = NULL; - n++; - } - } + if (untrimmed != 0) { + tx_add_ephemeral_anchor_output(tx, &funding_key[side]); + output_order[n] = NULL; + n++; + } assert(n <= tx->wtx->num_outputs); assert(n <= ARRAY_SIZE(output_order)); - /* BOLT #3: + /* BOLT #???: * * 9. Sort the outputs into [BIP 69+CLTV * order](#transaction-input-and-output-ordering) */ + /* FIXME? */ permute_outputs(tx, NULL, output_order); - /* BOLT #3: + /* BOLT #???: * * ## Commitment Transaction * @@ -247,15 +202,15 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, */ assert(tx->wtx->version == 2); - /* BOLT #3: + /* BOLT #???: * * * locktime: upper 8 bits are 0x20, lower 24 bits are the * lower 24 bits of the obscured commitment number */ bitcoin_tx_set_locktime(tx, - (0x20000000 | (obscured_commitment_number & 0xFFFFFF))); + obscured_update_number); - /* BOLT #3: + /* BOLT #???: * * * txin count: 1 * * `txin[0]` outpoint: `txid` and `output_index` from @@ -263,9 +218,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured commitment number * * `txin[0]` script bytes: 0 */ - sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF)); - bitcoin_tx_add_input(tx, funding, sequence, - NULL, funding_sats, NULL, funding_wscript); + bitcoin_tx_add_input(tx, update_output, shared_delay, + /* scriptSig */ NULL, update_output_sats, /* scriptPubKey */ NULL, /* input_wscript */ /* FIXME */); if (direct_outputs != NULL) { direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; @@ -280,7 +234,5 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* This doesn't reorder outputs, so we can do this after mapping outputs. */ bitcoin_tx_finalize(tx); - assert(bitcoin_tx_check(tx)); - return tx; } diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 6eeb760188a0..9538d3326c32 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -16,19 +16,15 @@ struct wally_tx_output; * initial_settlement_tx: create (unsigned) commitment tx to spend the first update tx * @ctx: context to allocate transaction and @htlc_map from. * @funding, @funding_sats: funding outpoint and amount - * @funding_wscript: scriptPubkey of the funding output - * @funding_keys: funding bitcoin keys - * @opener: is the LOCAL or REMOTE paying the fee? - * @keyset: keys derived for this commit tx. - * @feerate_per_kw: feerate to use + * @funding_keys: funding bitcoin keys to rederive funding output script + * @shared_delay: delay before this settlement transaction can be included in a block + * @eltoo_keyset: keys for the settlement outputs. * @dust_limit: dust limit below which to trim outputs. * @self_pay: amount to pay directly to self * @other_pay: amount to pay directly to the other side * @self_reserve: reserve the other side insisted we have - * @obscured_commitment_number: number to encode in commitment transaction + * @obscured_update_number: number to encode in update transaction as nlocktime * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). - * @side: side to generate commitment transaction for. - * @option_anchor_outputs: does option_anchor_outputs apply to this channel? * @err_reason: When NULL is returned, this will point to a human readable reason. * * We need to be able to generate the remote side's tx to create signatures, @@ -39,19 +35,14 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct bitcoin_outpoint *funding, struct amount_sat funding_sats, const struct pubkey funding_key[NUM_SIDES], - enum side opener, - u16 to_self_delay, - const struct keyset *keyset, - u32 feerate_per_kw, + u16 shared_delay, + const struct eltoo_keyset *eltoo_keyset, struct amount_sat dust_limit, struct amount_msat self_pay, struct amount_msat other_pay, struct amount_sat self_reserve, - u64 obscured_commitment_number, + u64 obscured_update_number, struct wally_tx_output *direct_outputs[NUM_SIDES], - enum side side, - u32 csv_lock, - bool option_anchor_outputs, char** err_reason); diff --git a/common/keyset.h b/common/keyset.h index ba74ceeb024f..b310a338f14a 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -13,6 +13,12 @@ struct keyset { struct pubkey self_payment_key, other_payment_key; }; +/* Keys needed to derive a particular settlement tx. */ +struct eltoo_keyset { + struct pubkey self_htlc_key, other_htlc_key; + struct pubkey self_payment_key, other_payment_key; +}; + /* Self == owner of commitment tx, other == non-owner. */ bool derive_keyset(const struct pubkey *per_commitment_point, const struct basepoints *self, From 5059d435da51e992dcfb5facd78f498c3b092c52 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 09:46:59 -0400 Subject: [PATCH 024/283] more fixups --- common/initial_settlement_tx.c | 8 -------- common/initial_settlement_tx.h | 7 +------ 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 567cd52b9041..591abd88ec8d 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -14,14 +14,6 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) bitcoin_tx_add_output(tx, spk, /* wscript */ NULL, AMOUNT_SAT(0)); } -u8 *to_self_eltoo_wscript(const tal_t *ctx, - const struct keyset *keyset) -{ - return bitcoin_wscript_to_local(ctx, to_self_delay, csv, - &keyset->self_revocation_key, - &keyset->self_delayed_payment_key); -} - struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct bitcoin_outpoint *update_output, struct amount_sat update_output_sats, diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 9538d3326c32..413b19bdcd92 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -13,7 +13,7 @@ struct keyset; struct wally_tx_output; /** - * initial_settlement_tx: create (unsigned) commitment tx to spend the first update tx + * initial_settlement_tx: create (unsigned) update tx to spend the first update tx * @ctx: context to allocate transaction and @htlc_map from. * @funding, @funding_sats: funding outpoint and amount * @funding_keys: funding bitcoin keys to rederive funding output script @@ -27,9 +27,6 @@ struct wally_tx_output; * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). * @err_reason: When NULL is returned, this will point to a human readable reason. * - * We need to be able to generate the remote side's tx to create signatures, - * but the BOLT is expressed in terms of generating our local commitment - * transaction, so we carefully use the terms "self" and "other" here. */ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct bitcoin_outpoint *funding, @@ -46,8 +43,6 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, char** err_reason); -/* To-other is simply: scriptpubkey_p2wpkh(tx, keyset->other_payment_key) */ - /* We always add a single ephemeral anchor output to settlement transactions */ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx); From 731fc97eddf1cb9ae121c932c42fd9a7b5e3831b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 09:48:50 -0400 Subject: [PATCH 025/283] f --- common/initial_settlement_tx.c | 3 +-- common/initial_settlement_tx.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 591abd88ec8d..74c114178cee 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -19,8 +19,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct amount_sat update_output_sats, const struct pubkey funding_key[NUM_SIDES], u32 shared_delay, - const struct keyset *keyset, - u32 feerate_per_kw, + const struct eltoo_keyset *eltoo_keyset, struct amount_sat dust_limit, struct amount_msat self_pay, struct amount_msat other_pay, diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 413b19bdcd92..fd0ace2f265a 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -29,8 +29,8 @@ struct wally_tx_output; * */ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, - const struct bitcoin_outpoint *funding, - struct amount_sat funding_sats, + const struct bitcoin_outpoint *update_output, + struct amount_sat udpate_output_sats, const struct pubkey funding_key[NUM_SIDES], u16 shared_delay, const struct eltoo_keyset *eltoo_keyset, From 7e5f6dd09adcb5111fac6a8c0e3efb5d328d4390 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 10:34:50 -0400 Subject: [PATCH 026/283] f --- common/initial_settlement_tx.c | 42 +++++++++++++++------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 74c114178cee..776e081519d4 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -28,23 +28,17 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct wally_tx_output *direct_outputs[NUM_SIDES], char** err_reason) { - struct amount_sat base_fee; struct bitcoin_tx *tx; - size_t n, untrimmed; + size_t output_index, num_untrimmed; bool to_local, to_remote; struct amount_msat total_pay; struct amount_sat amount; - enum side lessor = !opener; void *dummy_local = (void *)LOCAL, *dummy_remote = (void *)REMOTE; - /* There is a direct, and possibly an anchor output for each side. */ - const void *output_order[2 * NUM_SIDES]; + /* There is a direct output and possibly a shared anchor output */ + const void *output_order[NUM_SIDES + 1]; struct pubkey *pubkey_ptrs[2]; - const u8 *funding_wscript = bitcoin_redeem_2of2(tmpctx, - &funding_key[LOCAL], - &funding_key[REMOTE]); - - /* For MuSig aggregation for outputs */ + /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &funding_key[0]; pubkey_ptrs[1] = &funding_key[1]; @@ -57,7 +51,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * 1. Calculate which committed HTLCs need to be trimmed (see * [Trimmed Outputs](#trimmed-outputs)). */ - untrimmed = 0; + num_untrimmed = 0; /* FIXME, should be in #2: * @@ -86,12 +80,12 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* Worst-case sizing: both to-local and to-remote outputs + single anchor. */ - tx = bitcoin_tx(ctx, chainparams, 1, untrimmed + NUM_SIDES + 1, 0); + tx = bitcoin_tx(ctx, chainparams, 1, num_untrimmed + NUM_SIDES + 1, 0); /* This could be done in a single loop, but we follow the BOLT * literally to make comments in test vectors clearer. */ - n = 0; + output_index = 0; /* BOLT #3: * * 4. For every offered HTLC, if it is not trimmed, add an @@ -118,15 +112,15 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.self_payment_key); /* FIXME compute taptree merkle root */ - bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ sizeof(pubkey_ptrs), + bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out) amount = amount_msat_to_sat_round_down(self_pay); int pos = bitcoin_tx_add_output( tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); - assert(pos == n); - output_order[n] = dummy_local; - n++; + assert(pos == output_index); + output_order[output_index] = dummy_local; + output_index++; to_local = true; } else to_local = false; @@ -153,7 +147,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.other_payment_key); /* FIXME compute taptree merkle root */ - bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ sizeof(pubkey_ptrs), + bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out) amount = amount_msat_to_sat_round_down(self_pay); @@ -168,14 +162,14 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* BOLT #???: */ - if (untrimmed != 0) { - tx_add_ephemeral_anchor_output(tx, &funding_key[side]); - output_order[n] = NULL; - n++; + if (to_local || to_remote || num_untrimmed != 0) { + tx_add_ephemeral_anchor_output(tx); + output_order[output_index] = NULL; + output_index++; } - assert(n <= tx->wtx->num_outputs); - assert(n <= ARRAY_SIZE(output_order)); + assert(output_index <= tx->wtx->num_outputs); + assert(output_index <= ARRAY_SIZE(output_order)); /* BOLT #???: * From ba107e8ead52c5c23af269a22c43290b2b40de17 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 13:07:27 -0400 Subject: [PATCH 027/283] touchups --- common/initial_settlement_tx.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 776e081519d4..ee3d204509b0 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -108,12 +108,12 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct pubkey agg_pk; secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; - unsigned char tap_tweak_out[32]; + struct sha256 tap_tweak_out[32]; u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.self_payment_key); /* FIXME compute taptree merkle root */ bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out) + &tap_merkle_root, tap_tweak_out.u.u8) amount = amount_msat_to_sat_round_down(self_pay); int pos = bitcoin_tx_add_output( @@ -143,12 +143,12 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct pubkey agg_pk; secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; - unsigned char tap_tweak_out[32]; + struct sha256 tap_tweak_out[32]; u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.other_payment_key); /* FIXME compute taptree merkle root */ bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out) + &tap_merkle_root, tap_tweak_out.u.u8) amount = amount_msat_to_sat_round_down(self_pay); int pos = bitcoin_tx_add_output( @@ -206,6 +206,9 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, bitcoin_tx_add_input(tx, update_output, shared_delay, /* scriptSig */ NULL, update_output_sats, /* scriptPubKey */ NULL, /* input_wscript */ /* FIXME */); + /* Now the the transaction itself is determined, we must compute the APO sighash to inject it + into the inputs' tapscript, then attach the information to the PSBT */ + if (direct_outputs != NULL) { direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; for (size_t i = 0; i < tx->wtx->num_outputs; i++) { From 4804f9b53fb9f4c0610189201f87f9b009c37afa Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 14:16:03 -0400 Subject: [PATCH 028/283] Work towards tap merkle root --- bitcoin/script.c | 12 ++++++++---- bitcoin/script.h | 5 ++++- bitcoin/tx.c | 8 ++++++-- bitcoin/tx.h | 4 +++- channeld/commit_tx.c | 2 +- channeld/watchtower.c | 2 +- common/close_tx.c | 2 +- common/htlc_tx.c | 2 +- common/initial_commit_tx.c | 2 +- common/initial_settlement_tx.c | 4 ++-- devtools/eltoo_mkfunding.c | 2 +- devtools/mkclose.c | 2 +- devtools/mkfunding.c | 2 +- onchaind/onchaind.c | 4 ++-- 14 files changed, 33 insertions(+), 20 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 3a3eedc361ee..d12d2ecea41e 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -926,7 +926,7 @@ u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx) return script; } -u8 *bitcoin_tapscript_to_node(const struct pubkey *settlement_pubkey) +u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_pubkey) { u8 *script = tal_arr(ctx, u8, 0); @@ -944,16 +944,20 @@ u8 *bitcoin_tapscript_to_node(const struct pubkey *settlement_pubkey) return script; } -void compute_taptree_merkle_root(struct *sha256, u8 **scripts, size_t num_scripts) +void compute_taptree_merkle_root(struct sha256 *hash_out, u8 *tap_tree, size_t num_scripts) { int ok; - unsigned char tap_version = 0xc0; + //unsigned char tap_version = 0xc0; + unsigned char scripts[1]; /* FIXME we need to extract info directly from psbt tap_tree structure */ + unsigned char tap_tweak_out[1]; /* FIXME this is junk */ + scripts[0] = 0; + /* Only what's required for eltoo et al for now, sue me */ assert(num_scripts <= 2); if (num_scripts == 1) { /* Let k0 = hashTapLeaf(v || compact_size(size of s) || s); also call it the tapleaf hash. */ - ok = wally_tagged_hash((unsigned char*)scripts[0], tal_count(scripts[0]), "TapBranch", tap_tweak_out); + ok = wally_tagged_hash(scripts, 1, "TapBranch", tap_tweak_out); assert(ok); } } diff --git a/bitcoin/script.h b/bitcoin/script.h index 6e9ffbf526bf..f908a5a301ff 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -172,7 +172,10 @@ void script_push_bytes(u8 **scriptp, const void *mem, size_t len); u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx); /* to_node balance output script with anti-pinning 1 block CSV */ -u8 *bitcoin_tapscript_to_node(const struct pubkey *settlement_pubkey); +u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_pubkey); + +/* Computes taproot merkle root from PSBT-formatted taptree */ +void compute_taptree_merkle_root(struct sha256 *hash_out, u8 *tap_tree, size_t num_scripts); /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 29d0ed8ab0f7..929122d29851 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -187,7 +187,8 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *outpoint, u32 sequence, const u8 *scriptSig, struct amount_sat amount, const u8 *scriptPubkey, - const u8 *input_wscript) + const u8 *input_wscript, const struct pubkey *inner_pubkey, + const u8 *tap_tree) { int wally_err; int input_num = tx->wtx->num_inputs; @@ -198,7 +199,10 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, if (input_wscript) { scriptPubkey = scriptpubkey_p2wsh(tmpctx, input_wscript); - } + } else if (tap_tree) { + /* FIXME Compute tap merkle root */ + scriptPubkey = NULL; + } assert(scriptPubkey); psbt_input_set_wit_utxo(tx->psbt, input_num, diff --git a/bitcoin/tx.h b/bitcoin/tx.h index cb0903ccf40d..be01d66f8525 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -2,6 +2,7 @@ #define LIGHTNING_BITCOIN_TX_H #include "config.h" #include +#include #include #include #include @@ -106,6 +107,7 @@ void bitcoin_tx_set_locktime(struct bitcoin_tx *tx, u32 locktime); /* Add a new input to a bitcoin tx. * * For P2WSH inputs, we'll also store the wscript and/or scriptPubkey + * For P2TR inputs, we'll store the control block and/or scriptPubkey * Passing in just the {input_wscript}, we'll generate the scriptPubkey for you. * In some cases we may not have the wscript, in which case the scriptPubkey * should be provided. We'll check that it's P2WSH before saving it */ @@ -113,7 +115,7 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *outpoint, u32 sequence, const u8 *scriptSig, struct amount_sat amount, const u8 *scriptPubkey, - const u8 *input_wscript); + const u8 *input_wscript, const struct pubkey *inner_pubkey, const u8 * tap_tree); /* This is useful because wally uses a raw byte array for txids */ bool wally_tx_input_spends(const struct wally_tx_input *input, diff --git a/channeld/commit_tx.c b/channeld/commit_tx.c index 2fdf0df1ac62..3cbae5e95c31 100644 --- a/channeld/commit_tx.c +++ b/channeld/commit_tx.c @@ -410,7 +410,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, */ u32 sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF)); bitcoin_tx_add_input(tx, funding, - sequence, NULL, funding_sats, NULL, funding_wscript); + sequence, NULL, funding_sats, NULL, funding_wscript, NULL, NULL); /* Identify the direct outputs (to_us, to_them). */ if (direct_outputs != NULL) { diff --git a/channeld/watchtower.c b/channeld/watchtower.c index 269b4f405ad0..53e5de58d642 100644 --- a/channeld/watchtower.c +++ b/channeld/watchtower.c @@ -76,7 +76,7 @@ penalty_tx_create(const tal_t *ctx, tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); bitcoin_tx_add_input(tx, &outpoint, 0xFFFFFFFF, - NULL, to_them_sats, NULL, wscript); + NULL, to_them_sats, NULL, wscript, NULL, NULL); bitcoin_tx_add_output(tx, final_scriptpubkey, NULL, to_them_sats); assert((final_index == NULL) == (final_ext_key == NULL)); diff --git a/common/close_tx.c b/common/close_tx.c index 48e54d1e9c02..1b02e8f5eaaf 100644 --- a/common/close_tx.c +++ b/common/close_tx.c @@ -43,7 +43,7 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx, /* Our input spends the anchor tx output. */ bitcoin_tx_add_input(tx, funding, BITCOIN_TX_DEFAULT_SEQUENCE, NULL, - funding_sats, NULL, funding_wscript); + funding_sats, NULL, funding_wscript, NULL, NULL); if (amount_sat_greater_eq(to_us, dust_limit)) { script = tal_dup_talarr(tx, u8, our_script); diff --git a/common/htlc_tx.c b/common/htlc_tx.c index e80ea1375813..679ebad05d97 100644 --- a/common/htlc_tx.c +++ b/common/htlc_tx.c @@ -48,7 +48,7 @@ static struct bitcoin_tx *htlc_tx(const tal_t *ctx, amount = amount_msat_to_sat_round_down(msat); bitcoin_tx_add_input(tx, commit, option_anchor_outputs ? 1 : 0, - NULL, amount, NULL, commit_wscript); + NULL, amount, NULL, commit_wscript, NULL, NULL); /* BOLT #3: * * txout count: 1 diff --git a/common/initial_commit_tx.c b/common/initial_commit_tx.c index 44203f7f4bd6..89b030255756 100644 --- a/common/initial_commit_tx.c +++ b/common/initial_commit_tx.c @@ -321,7 +321,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, */ sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF)); bitcoin_tx_add_input(tx, funding, sequence, - NULL, funding_sats, NULL, funding_wscript); + NULL, funding_sats, NULL, funding_wscript, NULL, NULL); if (direct_outputs != NULL) { direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index ee3d204509b0..58d0c0f89f1a 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -110,7 +110,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct sha256 tap_merkle_root; struct sha256 tap_tweak_out[32]; - u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.self_payment_key); + u8 *tapleaf_script = bitcoin_tapscript_to_node(ctx, eltoo_keyset.self_payment_key); /* FIXME compute taptree merkle root */ bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8) @@ -145,7 +145,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct sha256 tap_merkle_root; struct sha256 tap_tweak_out[32]; - u8 *tapleaf_script = bitcoin_tapscript_to_node(eltoo_keyset.other_payment_key); + u8 *tapleaf_script = bitcoin_tapscript_to_node(ctx, eltoo_keyset.other_payment_key); /* FIXME compute taptree merkle root */ bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8) diff --git a/devtools/eltoo_mkfunding.c b/devtools/eltoo_mkfunding.c index 4e8a66831cb0..d4cfe2c17c45 100644 --- a/devtools/eltoo_mkfunding.c +++ b/devtools/eltoo_mkfunding.c @@ -45,7 +45,7 @@ static struct bitcoin_tx *tx_spending_utxo(const tal_t *ctx, assert(!utxo->is_p2sh); bitcoin_tx_add_input(tx, &utxo->outpoint, nsequence, NULL, utxo->amount, - utxo->scriptPubkey, NULL); + utxo->scriptPubkey, NULL, NULL, NULL); return tx; } diff --git a/devtools/mkclose.c b/devtools/mkclose.c index f60b6175fe07..d29d71ff95ea 100644 --- a/devtools/mkclose.c +++ b/devtools/mkclose.c @@ -167,7 +167,7 @@ int main(int argc, char *argv[]) /* Our input spends the anchor tx output. */ bitcoin_tx_add_input(tx, &funding, BITCOIN_TX_DEFAULT_SEQUENCE, NULL, - funding_amount, NULL, funding_wscript); + funding_amount, NULL, funding_wscript, NULL, NULL); sign_tx_input(tx, 0, NULL, funding_wscript, &funding_privkey[LOCAL], diff --git a/devtools/mkfunding.c b/devtools/mkfunding.c index 878212de086a..82d8748248e5 100644 --- a/devtools/mkfunding.c +++ b/devtools/mkfunding.c @@ -45,7 +45,7 @@ static struct bitcoin_tx *tx_spending_utxo(const tal_t *ctx, assert(!utxo->is_p2sh); bitcoin_tx_add_input(tx, &utxo->outpoint, nsequence, NULL, utxo->amount, - utxo->scriptPubkey, NULL); + utxo->scriptPubkey, NULL, NULL, NULL); return tx; } diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 7d10e36a4b5c..83c0b059a658 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -618,7 +618,7 @@ static struct bitcoin_tx *tx_to_us(const tal_t *ctx, tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); bitcoin_tx_add_input(tx, &out->outpoint, to_self_delay, - NULL, out->sat, NULL, wscript); + NULL, out->sat, NULL, wscript, NULL, NULL); bitcoin_tx_add_output( tx, scriptpubkey_p2wpkh(tmpctx, &our_wallet_pubkey), NULL, out->sat); @@ -741,7 +741,7 @@ replace_penalty_tx_to_us(const tal_t *ctx, /* Reconstruct the input. */ bitcoin_tx_add_input(tx, &input_outpoint, BITCOIN_TX_RBF_SEQUENCE, - NULL, input_amount, NULL, input_wscript); + NULL, input_amount, NULL, input_wscript, NULL, NULL); /* Reconstruct the output with a smaller amount. */ if (amount_sat_greater(*output_amount, dust_limit)) { bitcoin_tx_add_output(tx, From e90aa1482fc6510c4389d10f7fae0b80c5abb79e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 15:34:09 -0400 Subject: [PATCH 029/283] possibly working taptree root computation --- bitcoin/script.c | 44 +++++++++++++++++++++++++++++++++++++------- bitcoin/script.h | 2 +- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index d12d2ecea41e..c73b51936669 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -944,20 +944,50 @@ u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_ return script; } -void compute_taptree_merkle_root(struct sha256 *hash_out, u8 *tap_tree, size_t num_scripts) +void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts) { int ok; - //unsigned char tap_version = 0xc0; - unsigned char scripts[1]; /* FIXME we need to extract info directly from psbt tap_tree structure */ - unsigned char tap_tweak_out[1]; /* FIXME this is junk */ - - scripts[0] = 0; + unsigned char leaf_version = 0xc0; + unsigned char tag_hash_buf[1000]; /* Needs to be large enough for HTLC scripts */ + unsigned char tap_hashes[64]; /* To store the leaves for comparison */ /* Only what's required for eltoo et al for now, sue me */ assert(num_scripts <= 2); if (num_scripts == 1) { + size_t script_len = tal_count(scripts[0]); + unsigned char *p = tag_hash_buf; /* Let k0 = hashTapLeaf(v || compact_size(size of s) || s); also call it the tapleaf hash. */ - ok = wally_tagged_hash(scripts, 1, "TapBranch", tap_tweak_out); + p[0] = leaf_version; + p++; + p += varint_put(p, script_len); + memcpy(p, scripts[0], script_len); + p += script_len; + + /* k0 == km, this is the merkle root so we directly write it out */ + ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", hash_out->u.u8); + assert(ok); + } else if (num_scripts == 2) { + int i; + for (i=0; i= 0) { + memcpy(tag_hash_buf, tap_hashes, 32); + memcpy(tap_hashes, tap_hashes + 32, 32); + memcpy(tap_hashes + 32, tag_hash_buf, 32); + } + ok = wally_tagged_hash(tap_hashes, sizeof(tap_hashes), "TapBranch", hash_out->u.u8); assert(ok); } } diff --git a/bitcoin/script.h b/bitcoin/script.h index f908a5a301ff..9be0f2b5aa7b 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -175,7 +175,7 @@ u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx); u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_pubkey); /* Computes taproot merkle root from PSBT-formatted taptree */ -void compute_taptree_merkle_root(struct sha256 *hash_out, u8 *tap_tree, size_t num_scripts); +void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts); /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) From f98a9b75039e9e9c08dfad8ab706dd92e066a412 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 15:36:35 -0400 Subject: [PATCH 030/283] fixup --- common/initial_settlement_tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 58d0c0f89f1a..c557a9707d58 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -108,7 +108,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct pubkey agg_pk; secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; - struct sha256 tap_tweak_out[32]; + struct sha256 tap_tweak_out; u8 *tapleaf_script = bitcoin_tapscript_to_node(ctx, eltoo_keyset.self_payment_key); /* FIXME compute taptree merkle root */ @@ -143,7 +143,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct pubkey agg_pk; secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; - struct sha256 tap_tweak_out[32]; + struct sha256 tap_tweak_out; u8 *tapleaf_script = bitcoin_tapscript_to_node(ctx, eltoo_keyset.other_payment_key); /* FIXME compute taptree merkle root */ From f58d89e1a15ccc6aaeb701e5eea206069c8b28d9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 15:41:28 -0400 Subject: [PATCH 031/283] Compute tap merkle root for balance outputs --- common/initial_settlement_tx.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index c557a9707d58..f4379c68b39c 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -109,9 +109,10 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; struct sha256 tap_tweak_out; + u8 **tapleaf_scripts[1]; - u8 *tapleaf_script = bitcoin_tapscript_to_node(ctx, eltoo_keyset.self_payment_key); - /* FIXME compute taptree merkle root */ + tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, eltoo_keyset.self_payment_key); + compute_taptree_merkle_root(&tap_merkle_root, scripts, /* num_scripts */ 1) bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8) @@ -144,9 +145,11 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; struct sha256 tap_tweak_out; + u8 **tapleaf_scripts[1]; + + tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, eltoo_keyset.other_payment_key); + compute_taptree_merkle_root(&tap_merkle_root, scripts, /* num_scripts */ 1) - u8 *tapleaf_script = bitcoin_tapscript_to_node(ctx, eltoo_keyset.other_payment_key); - /* FIXME compute taptree merkle root */ bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8) From 4f463cdc620b11da837829b7e1ff38b3cc91683a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 5 Jul 2022 16:26:56 -0400 Subject: [PATCH 032/283] huh? compiles? --- common/initial_settlement_tx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index f4379c68b39c..58678f5d46b5 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -156,9 +156,9 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, amount = amount_msat_to_sat_round_down(self_pay); int pos = bitcoin_tx_add_output( tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); - assert(pos == n); - output_order[n] = dummy_remote; - n++; + assert(pos == output_index); + output_order[output_index] = dummy_remote; + output_index++; to_remote = true; } else to_remote = false; From 7bf94e3eb5ff2839758b16eae69173eb639fc609 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 6 Jul 2022 10:16:24 -0400 Subject: [PATCH 033/283] fix compilation --- channeld/Makefile | 1 + channeld/commit_tx.h | 2 ++ common/Makefile | 1 + common/initial_settlement_tx.c | 24 ++++++++++++------------ common/initial_settlement_tx.h | 6 +++--- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/channeld/Makefile b/channeld/Makefile index bdab8ffa0c13..739d2091f58a 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -60,6 +60,7 @@ CHANNELD_COMMON_OBJS := \ common/htlc_wire.o \ common/initial_channel.o \ common/initial_commit_tx.o \ + common/initial_settlement_tx.o \ common/keyset.o \ common/key_derive.o \ common/memleak.o \ diff --git a/channeld/commit_tx.h b/channeld/commit_tx.h index fc2db029de40..d6f389ec24a7 100644 --- a/channeld/commit_tx.h +++ b/channeld/commit_tx.h @@ -4,6 +4,8 @@ #include #include +#include + struct keyset; /** diff --git a/common/Makefile b/common/Makefile index 86f1588b421b..ec5503fe457d 100644 --- a/common/Makefile +++ b/common/Makefile @@ -46,6 +46,7 @@ COMMON_SRC_NOGEN := \ common/htlc_wire.c \ common/initial_channel.c \ common/initial_commit_tx.c \ + common/initial_settlement_tx.c \ common/iso4217.c \ common/json.c \ common/json_helpers.c \ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 58678f5d46b5..5d414bd3b34d 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -36,7 +36,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, void *dummy_local = (void *)LOCAL, *dummy_remote = (void *)REMOTE; /* There is a direct output and possibly a shared anchor output */ const void *output_order[NUM_SIDES + 1]; - struct pubkey *pubkey_ptrs[2]; + const struct pubkey *pubkey_ptrs[2]; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &funding_key[0]; @@ -109,16 +109,16 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; struct sha256 tap_tweak_out; - u8 **tapleaf_scripts[1]; + u8 *tapleaf_scripts[1]; - tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, eltoo_keyset.self_payment_key); - compute_taptree_merkle_root(&tap_merkle_root, scripts, /* num_scripts */ 1) + tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->self_payment_key); + compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out.u.u8) + &tap_merkle_root, tap_tweak_out.u.u8); amount = amount_msat_to_sat_round_down(self_pay); int pos = bitcoin_tx_add_output( - tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); + tx, scriptpubkey_p2tr(ctx, &agg_pk), /* wscript */ NULL, amount /* FIXME pass in psbt fields for tap outputs */); assert(pos == output_index); output_order[output_index] = dummy_local; output_index++; @@ -145,17 +145,17 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, secp256k1_musig_keyagg_cache keyagg_cache; struct sha256 tap_merkle_root; struct sha256 tap_tweak_out; - u8 **tapleaf_scripts[1]; + u8 *tapleaf_scripts[1]; - tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, eltoo_keyset.other_payment_key); - compute_taptree_merkle_root(&tap_merkle_root, scripts, /* num_scripts */ 1) + tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->other_payment_key); + compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out.u.u8) + &tap_merkle_root, tap_tweak_out.u.u8); amount = amount_msat_to_sat_round_down(self_pay); int pos = bitcoin_tx_add_output( - tx, scriptpubkey_p2wsh(tx, wscript), wscript, amount); + tx, scriptpubkey_p2tr(ctx, &agg_pk), /* wscript */ NULL, amount /* FIXME PSBT tap output fields*/); assert(pos == output_index); output_order[output_index] = dummy_remote; output_index++; @@ -207,7 +207,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * * `txin[0]` script bytes: 0 */ bitcoin_tx_add_input(tx, update_output, shared_delay, - /* scriptSig */ NULL, update_output_sats, /* scriptPubKey */ NULL, /* input_wscript */ /* FIXME */); + /* scriptSig */ NULL, update_output_sats, /* scriptPubKey */ NULL, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); /* Now the the transaction itself is determined, we must compute the APO sighash to inject it into the inputs' tapscript, then attach the information to the PSBT */ diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index fd0ace2f265a..7bf9cb1715b5 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -9,7 +9,7 @@ #include struct bitcoin_outpoint; -struct keyset; +struct eltoo_keyset; struct wally_tx_output; /** @@ -32,13 +32,13 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct bitcoin_outpoint *update_output, struct amount_sat udpate_output_sats, const struct pubkey funding_key[NUM_SIDES], - u16 shared_delay, + u32 shared_delay, const struct eltoo_keyset *eltoo_keyset, struct amount_sat dust_limit, struct amount_msat self_pay, struct amount_msat other_pay, struct amount_sat self_reserve, - u64 obscured_update_number, + u32 obscured_update_number, struct wally_tx_output *direct_outputs[NUM_SIDES], char** err_reason); From 08c0f54a1058b985fd0792d5d1a13c5934905e1a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 6 Jul 2022 12:11:48 -0400 Subject: [PATCH 034/283] Compute and pass in inner pubkeys --- bitcoin/signature.c | 34 ++++++++++++++++++++++++++++++++++ bitcoin/signature.h | 11 +++++++++++ bitcoin/tx.c | 8 +++----- bitcoin/tx.h | 2 +- common/initial_settlement_tx.c | 19 ++++++++++++++++--- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index f00776584964..d430474a32e0 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -158,6 +158,40 @@ void bip340_sign_hash(const struct privkey *privkey, assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); } +void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, + const struct pubkey * const* pubkeys, + size_t n_pubkeys) +{ + int i, ok; + assert(n_pubkeys <= 100); + + /* Sorting moves pubkeys themselves, we copy and discard after */ + secp256k1_xonly_pubkey x_keys[100]; + const secp256k1_xonly_pubkey *x_keys_ptr[100]; + + for (i=0; i < n_pubkeys; ++i) { + ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &x_keys[i], /* pk_parity */ NULL, + &(pubkeys[i]->pubkey)); + assert(ok); + x_keys_ptr[i] = &x_keys[i]; + } + + ok = secp256k1_xonly_sort(secp256k1_ctx, + x_keys_ptr, + n_pubkeys); + + assert(ok); + + ok = secp256k1_musig_pubkey_agg(secp256k1_ctx, + NULL /* scratch */, + inner_pubkey, + /* keyagg_cache */ NULL, + x_keys_ptr, + n_pubkeys); + + assert(ok); +} + void bipmusig_finalize_keys(struct pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const struct pubkey * const* pubkeys, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 88cd0781eae4..d7d1f9d6fef5 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -105,6 +105,17 @@ void bip340_sign_hash(const struct privkey *privkey, const struct sha256_double *hash, struct bip340sig *sig); +/** + * bipmusig_inner_pubkey - produce the sorted taproot inner pubkey. + * Does not create a signing session. + * @inner_pubkey: resulting aggregated(untweaked) x-only pubkey + * @pubkeys: array of public keys to aggregate + * @n_pubkeys: number of pubkeys in @pubkeys array + */ +void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, + const struct pubkey * const* pubkeys, + size_t n_pubkeys); + /** * bipmusig_finalize_keys - Aggregate keys in lexigraphically * sorted order, tweaks required for keyspend, diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 929122d29851..cadcff0b2a8c 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -187,9 +187,10 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *outpoint, u32 sequence, const u8 *scriptSig, struct amount_sat amount, const u8 *scriptPubkey, - const u8 *input_wscript, const struct pubkey *inner_pubkey, + const u8 *input_wscript, const secp256k1_xonly_pubkey *inner_pubkey, const u8 *tap_tree) { + /* FIXME use inner_pubkey and tap_tree */ int wally_err; int input_num = tx->wtx->num_inputs; @@ -199,10 +200,7 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, if (input_wscript) { scriptPubkey = scriptpubkey_p2wsh(tmpctx, input_wscript); - } else if (tap_tree) { - /* FIXME Compute tap merkle root */ - scriptPubkey = NULL; - } + } assert(scriptPubkey); psbt_input_set_wit_utxo(tx->psbt, input_num, diff --git a/bitcoin/tx.h b/bitcoin/tx.h index be01d66f8525..5134da85e295 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -115,7 +115,7 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *outpoint, u32 sequence, const u8 *scriptSig, struct amount_sat amount, const u8 *scriptPubkey, - const u8 *input_wscript, const struct pubkey *inner_pubkey, const u8 * tap_tree); + const u8 *input_wscript, const secp256k1_xonly_pubkey *inner_pubkey, const u8 * tap_tree); /* This is useful because wally uses a raw byte array for txids */ bool wally_tx_input_spends(const struct wally_tx_input *input, diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 5d414bd3b34d..4dd3025bd41b 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -37,11 +37,18 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* There is a direct output and possibly a shared anchor output */ const void *output_order[NUM_SIDES + 1]; const struct pubkey *pubkey_ptrs[2]; + int input_num; + secp256k1_xonly_pubkey inner_pubkey; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &funding_key[0]; pubkey_ptrs[1] = &funding_key[1]; + /* Channel-wide inner public key computed here */ + bipmusig_inner_pubkey(&inner_pubkey, + pubkey_ptrs, + /* n_pubkeys */ 2); + if (!amount_msat_add(&total_pay, self_pay, other_pay)) abort(); assert(!amount_msat_greater_sat(total_pay, update_output_sats)); @@ -206,11 +213,17 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured commitment number * * `txin[0]` script bytes: 0 */ - bitcoin_tx_add_input(tx, update_output, shared_delay, - /* scriptSig */ NULL, update_output_sats, /* scriptPubKey */ NULL, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); - + /* + * We do not know what scriptPubKey, tap_tree look like yet because we're computing + * a sighash to then put into the input sciript. We pass in dummies + * where necessary for now. + */ + input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, + /* scriptSig */ NULL, update_output_sats, /* scriptPubKey */ NULL, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); + assert(input_num >= 0); /* Now the the transaction itself is determined, we must compute the APO sighash to inject it into the inputs' tapscript, then attach the information to the PSBT */ + /* bitcoin_tx_rebind_input(tx, input_num);*/ if (direct_outputs != NULL) { direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; From f850dc42e7b9f29813528efc9c50872b683597de Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 6 Jul 2022 12:48:03 -0400 Subject: [PATCH 035/283] fix to_node script --- bitcoin/script.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index c73b51936669..b3cf316c074b 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -937,10 +937,10 @@ u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_ * * 1 OP_CHECKSEQUENCEVERIFY settlement_pubkey OP_CHECKSIGVERIFY */ - add_number(&script, 1); - add_op(&script, OP_CHECKSEQUENCEVERIFY); add_push_key(&script, settlement_pubkey); add_op(&script, OP_CHECKSIGVERIFY); + add_number(&script, 1); + add_op(&script, OP_CHECKSEQUENCEVERIFY); return script; } From 5eba4fce20c2f742784fe803ff632c9961fd1c5c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 6 Jul 2022 16:50:40 -0400 Subject: [PATCH 036/283] Checkin --- bitcoin/script.c | 95 ++++++++++++++++++++++++++++++++++ bitcoin/script.h | 16 +++++- bitcoin/signature.c | 15 ++++++ bitcoin/signature.h | 6 ++- common/initial_settlement_tx.c | 9 +++- 5 files changed, 137 insertions(+), 4 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index b3cf316c074b..b073061d589c 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -991,3 +992,97 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n assert(ok); } } + +void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit) +{ + int ok; + u8 *control_block_cursor = control_block; + unsigned char leaf_version = 0xc0; + unsigned char tag_hash_buf[1000]; /* Needs to be large enough for HTLC scripts */ + + /* Only what's required for eltoo et al for now, 2 leaves max, sue me */ + assert(control_block_size && *control_block_size >= 33 + 32); + + assert(parity_bit == 0 || parity_bit == 1); + control_block_cursor[0] = leaf_version | parity_bit; + control_block_cursor++; + + ok = secp256k1_xonly_pubkey_serialize( + secp256k1_ctx, + control_block_cursor, + inner_pubkey); + assert(ok); + control_block_cursor += 32; + + /* Need tapleaf hash of the other script of the 2 */ + if (other_script) { + size_t script_len = tal_count(other_script); + unsigned char *p = tag_hash_buf; + /* Let k0 = hashTapLeaf(v || compact_size(size of s) || s); also call it the tapleaf hash. */ + p[0] = leaf_version; + p++; + p += varint_put(p, script_len); + memcpy(p, other_script, script_len); + p += script_len; + + ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", control_block_cursor); + assert(ok); + control_block_cursor += 32; + } + *control_block_size = control_block_cursor - control_block; +} + +u8 *make_apoas_cov_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index) +{ + int ok; + enum sighash_type sh_type = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_ALL; + u8 *script = tal_arr(ctx, u8, 0); + struct sha256_double sighash; + struct bip340sig sig; + secp256k1_keypair G_pair; + secp256k1_xonly_pubkey G; + struct privkey g; + unsigned char one_G_bytes[33]; + + /* We use tapleaf_script as a switch for doing BIP342 hash + * We really shouldn't, but for now we pass in dummy + * since APOAS sighash doesn't cover it. + */ + bitcoin_tx_taproot_hash_for_sig(tx, + input_index, + sh_type, + script, + &sighash); + + /* Should directly take keypair instead of extracting but... */ + create_keypair_of_one(&G_pair); + ok = secp256k1_keypair_sec( + secp256k1_ctx, + g.secret.data, + &G_pair); + assert(ok); + + bip340_sign_hash(&g, + &sighash, + &sig); + + /* 0x01-prefixed G for APOAS pubkey */ + ok = secp256k1_keypair_xonly_pub( + secp256k1_ctx, + &G, + /* pk_parity */ NULL, + &G_pair); + assert(ok); + one_G_bytes[0] = 0x01; + ok = secp256k1_xonly_pubkey_serialize( + secp256k1_ctx, + one_G_bytes+1, + &G); + + /* Build the script */ + script_push_bytes(&script, sig.u8, sizeof(sig.u8)); + script_push_bytes(&script, one_G_bytes, sizeof(one_G_bytes)); + add_op(&script, OP_CHECKSIG); + return script; +} + diff --git a/bitcoin/script.h b/bitcoin/script.h index 9be0f2b5aa7b..f26a8d034555 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -174,9 +174,23 @@ u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx); /* to_node balance output script with anti-pinning 1 block CSV */ u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_pubkey); -/* Computes taproot merkle root from PSBT-formatted taptree */ +/* Computes taproot merkle root from list of up to two scripts in depth 1 tree, in order */ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts); +/* Computes control block for a spend from a taptree of size two, depth of 1, tops. other_script is NULL if only one script is committed. + * @control_block: BIP341 serialized control block + * @control_block_size: (in/out) Size of required buffer, and written for size of control block + * @inner_pubkey: Inner pubkey for taproot control block + * @parity_bit: Parity of outer taproot pubkey + */ +void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit); + +/* Creates tapscript that makes a sig-in-script ANYPREVOUTANYSCRIPT covenant + * which commits to the tx argument: + * CovSig(n) 1_G OP_CHECKSIG + */ +u8 *make_apoas_cov_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index); + /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index d430474a32e0..31e70ecc4d20 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -703,3 +703,18 @@ void bip340_sighash_init(struct sha256_ctx *sctx, sha256_update(sctx, &taghash, sizeof(taghash)); } +void create_keypair_of_one(secp256k1_keypair *G_pair) +{ + int ok; + unsigned char g[32]; + + /* Privkey of exactly 1, so the pubkey is the generator G */ + memset(g, 0x00, sizeof(g)); + g[sizeof(g)-1] = 0x01; + + ok = secp256k1_keypair_create( + secp256k1_ctx, + G_pair, + g); + assert(ok); +} diff --git a/bitcoin/signature.h b/bitcoin/signature.h index d7d1f9d6fef5..2eecd1e83384 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -20,7 +20,8 @@ enum sighash_type { SIGHASH_ALL = 1, SIGHASH_NONE = 2, SIGHASH_SINGLE = 3, - SIGHASH_ANYONECANPAY = 0x80 + SIGHASH_ANYONECANPAY = 0x80, + SIGHASH_ANYPREVOUTANYSCRIPT = 0xC0, }; /* Schnorr */ @@ -312,4 +313,7 @@ void bip340_sighash_init(struct sha256_ctx *sctx, const char *tag2, const char *tag3); +/* Used for APO style covenant signatures */ +void create_keypair_of_one(secp256k1_keypair *G_pair); + #endif /* LIGHTNING_BITCOIN_SIGNATURE_H */ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 4dd3025bd41b..4295a9ed9ece 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -39,6 +39,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct pubkey *pubkey_ptrs[2]; int input_num; secp256k1_xonly_pubkey inner_pubkey; + u8 *script_pubkey; + u8 dummy_script; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &funding_key[0]; @@ -219,11 +221,14 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * where necessary for now. */ input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, - /* scriptSig */ NULL, update_output_sats, /* scriptPubKey */ NULL, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); + /* scriptSig */ NULL, update_output_sats, &dummy_script, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); assert(input_num >= 0); /* Now the the transaction itself is determined, we must compute the APO sighash to inject it into the inputs' tapscript, then attach the information to the PSBT */ - /* bitcoin_tx_rebind_input(tx, input_num);*/ + script_pubkey = make_apoas_cov_script(tmpctx, tx, input_num); + assert(script_pubkey); + // We need to calc control block compute_taptree_merkle_root(tap_merkle_root, u8 **scripts, /* num_scripts */ 2); + //bitcoin_tx_rebind_input(tx, input_num, update_output, script_pubkey, /* tap_tree FIXME */ NULL); if (direct_outputs != NULL) { direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; From 19439a76306bb9d830f6d51de7349765affdcbea Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 11:09:26 -0400 Subject: [PATCH 037/283] initial settlement tx compiling --- bitcoin/script.c | 17 +++++- bitcoin/script.h | 5 +- ...-tx-bitcoin_tx_2of2_input_witness_weight.c | 4 ++ bitcoin/tx.c | 12 +++++ bitcoin/tx.h | 4 ++ common/initial_settlement_tx.c | 53 ++++++++++++++++--- 6 files changed, 86 insertions(+), 9 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index b073061d589c..7b26440fca10 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1032,7 +1032,7 @@ void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *ot *control_block_size = control_block_cursor - control_block; } -u8 *make_apoas_cov_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index) +u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index) { int ok; enum sighash_type sh_type = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_ALL; @@ -1046,7 +1046,7 @@ u8 *make_apoas_cov_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t /* We use tapleaf_script as a switch for doing BIP342 hash * We really shouldn't, but for now we pass in dummy - * since APOAS sighash doesn't cover it. + * since APOAS sighash doesn't cover it anyways. */ bitcoin_tx_taproot_hash_for_sig(tx, input_index, @@ -1086,3 +1086,16 @@ u8 *make_apoas_cov_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t return script; } +u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num) +{ + /* where EXPR_UPDATE(n) = + * + *`OP_1 OP_CHECKSIGVERIFY OP_CLTV` + */ + u8 *script = tal_arr(ctx, u8, 0); + add_op(&script, OP_1); + add_op(&script, OP_CHECKSIGVERIFY); + add_number(&script, update_num); + add_op(&script, OP_CHECKSEQUENCEVERIFY); + return script; +} diff --git a/bitcoin/script.h b/bitcoin/script.h index f26a8d034555..386e6ff2b983 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -189,7 +189,10 @@ void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *ot * which commits to the tx argument: * CovSig(n) 1_G OP_CHECKSIG */ -u8 *make_apoas_cov_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index); +u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index); + +/* Creates the update path tapscript for eltoo, which commits to the masked update number */ +u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) diff --git a/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c b/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c index 69d8bf36f685..f0f0d6e3b0a6 100644 --- a/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c +++ b/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c @@ -103,6 +103,10 @@ const unsigned char *psbt_input_get_scriptpubkey(const struct wally_psbt *psbt U void psbt_input_set_wit_utxo(struct wally_psbt *psbt UNNEEDED, size_t in UNNEEDED, const u8 *scriptPubkey UNNEEDED, struct amount_sat amt UNNEEDED) { fprintf(stderr, "psbt_input_set_wit_utxo called!\n"); abort(); } +/* Generated stub for psbt_rm_input */ +void psbt_rm_input(struct wally_psbt *psbt UNNEEDED, + size_t remove_at UNNEEDED) +{ fprintf(stderr, "psbt_rm_input called!\n"); abort(); } /* Generated stub for towire */ void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) { fprintf(stderr, "towire called!\n"); abort(); } diff --git a/bitcoin/tx.c b/bitcoin/tx.c index cadcff0b2a8c..8a5028761b26 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -227,6 +227,18 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, return input_num; } +void bitcoin_tx_remove_input(struct bitcoin_tx *tx, + size_t index_num) +{ + int ok; + ok = wally_tx_remove_input( + tx->wtx, + index_num); + assert(ok == WALLY_OK); + + psbt_rm_input(tx->psbt, index_num); +} + bool bitcoin_tx_check(const struct bitcoin_tx *tx) { u8 *newtx; diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 5134da85e295..75d210803254 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -117,6 +117,10 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, struct amount_sat amount, const u8 *scriptPubkey, const u8 *input_wscript, const secp256k1_xonly_pubkey *inner_pubkey, const u8 * tap_tree); +/* Removes specified input from bitcoin tx */ +void bitcoin_tx_remove_input(struct bitcoin_tx *tx, + size_t index_num); + /* This is useful because wally uses a raw byte array for txids */ bool wally_tx_input_spends(const struct wally_tx_input *input, const struct bitcoin_outpoint *outpoint); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 4295a9ed9ece..723f7e936498 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -38,9 +38,18 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const void *output_order[NUM_SIDES + 1]; const struct pubkey *pubkey_ptrs[2]; int input_num; - secp256k1_xonly_pubkey inner_pubkey; + secp256k1_xonly_pubkey inner_pubkey, output_pubkey; + u8 *settle_and_update_tapscripts[2]; u8 *script_pubkey; u8 dummy_script; + u8 control_block[33+32]; + u8 *witness[2]; /* settle_and_update_tapscripts[0] script and control_block */ + size_t control_block_size = sizeof(control_block); + struct sha256 update_merkle_root; + struct pubkey update_agg_pk; + secp256k1_musig_keyagg_cache update_keyagg_cache; + unsigned char update_tap_tweak[32]; + int parity_bit, ok; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &funding_key[0]; @@ -222,13 +231,45 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, */ input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, /* scriptSig */ NULL, update_output_sats, &dummy_script, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); - assert(input_num >= 0); + assert(input_num == 0); + /* Now the the transaction itself is determined, we must compute the APO sighash to inject it into the inputs' tapscript, then attach the information to the PSBT */ - script_pubkey = make_apoas_cov_script(tmpctx, tx, input_num); - assert(script_pubkey); - // We need to calc control block compute_taptree_merkle_root(tap_merkle_root, u8 **scripts, /* num_scripts */ 2); - //bitcoin_tx_rebind_input(tx, input_num, update_output, script_pubkey, /* tap_tree FIXME */ NULL); + settle_and_update_tapscripts[0] = make_eltoo_settle_script(tmpctx, tx, input_num); + settle_and_update_tapscripts[1] = make_eltoo_update_script(tmpctx, obscured_update_number); + assert(settle_and_update_tapscripts[0]); + assert(settle_and_update_tapscripts[1]); + + /* We need to calculate the merkle root to figure the parity bit */ + compute_taptree_merkle_root(&update_merkle_root, settle_and_update_tapscripts, /* num_scripts */ 2); + bipmusig_finalize_keys(&update_agg_pk, + &update_keyagg_cache, + pubkey_ptrs, + /* n_pubkeys */ 2, + &update_merkle_root, + update_tap_tweak); + + /* Convert to x-only, grab parity bit of the output pubkey */ + ok = secp256k1_xonly_pubkey_from_pubkey(ctx, &output_pubkey, &parity_bit, &(update_agg_pk.pubkey)); + assert(ok); + compute_control_block(control_block, &control_block_size, settle_and_update_tapscripts[1], &inner_pubkey, parity_bit); + script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); + + /* Remove and re-add with updated information */ + bitcoin_tx_remove_input(tx, input_num); + input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, + /* scriptSig */ NULL, update_output_sats, script_pubkey, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); + assert(input_num == 0); + + /* We have the complete witness for this transaction already, just add it + * the second-to-last stack element s, the script. + * last stack element is called the control block + */ + witness[0] = settle_and_update_tapscripts[0]; + witness[1] = control_block; + bitcoin_tx_input_set_witness(tx, input_num, witness); + + /* Transaction is now ready for broadcast! */ if (direct_outputs != NULL) { direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; From 3f274c1b81d9b3a8c603e7fbee7bd07c43d108a0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 12:24:18 -0400 Subject: [PATCH 038/283] Add initial settlement tx testing stub --- channeld/test/Makefile | 1 + channeld/test/run-settle_tx.c | 128 ++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 channeld/test/run-settle_tx.c diff --git a/channeld/test/Makefile b/channeld/test/Makefile index 77ea655abbf2..bf24a656c845 100644 --- a/channeld/test/Makefile +++ b/channeld/test/Makefile @@ -17,6 +17,7 @@ CHANNELD_TEST_COMMON_OBJS := \ common/htlc_trim.o \ common/htlc_tx.o \ common/initial_commit_tx.o \ + common/initial_settlement_tx.o \ common/key_derive.o \ common/msg_queue.o \ common/permute_tx.o \ diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c new file mode 100644 index 000000000000..654a9f810b65 --- /dev/null +++ b/channeld/test/run-settle_tx.c @@ -0,0 +1,128 @@ +#include "config.h" +#include +#include +#include +static bool print_superverbose; +#define SUPERVERBOSE(...) \ + do { if (print_superverbose) printf(__VA_ARGS__); } while(0) +#define PRINT_ACTUAL_FEE +#include "../commit_tx.c" +#include +#include +#include +#include +#include +#include +#include +#include + +/* Turn this on to brute-force fee values */ +/*#define DEBUG */ + +/* AUTOGENERATED MOCKS START */ +/* Generated stub for fromwire_bigsize */ +bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } +/* Generated stub for fromwire_channel_id */ +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } +/* Generated stub for fromwire_node_id */ +void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED) +{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); } +/* Generated stub for fromwire_wireaddr */ +bool fromwire_wireaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct wireaddr *addr UNNEEDED) +{ fprintf(stderr, "fromwire_wireaddr called!\n"); abort(); } +/* Generated stub for status_fmt */ +void status_fmt(enum log_level level UNNEEDED, + const struct node_id *peer UNNEEDED, + const char *fmt UNNEEDED, ...) + +{ fprintf(stderr, "status_fmt called!\n"); abort(); } +/* Generated stub for towire_bigsize */ +void towire_bigsize(u8 **pptr UNNEEDED, const bigsize_t val UNNEEDED) +{ fprintf(stderr, "towire_bigsize called!\n"); abort(); } +/* Generated stub for towire_channel_id */ +void towire_channel_id(u8 **pptr UNNEEDED, const struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "towire_channel_id called!\n"); abort(); } +/* Generated stub for towire_node_id */ +void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "towire_node_id called!\n"); abort(); } +/* Generated stub for towire_wireaddr */ +void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) +{ fprintf(stderr, "towire_wireaddr called!\n"); abort(); } +/* AUTOGENERATED MOCKS END */ + +/* bitcoind loves its backwards txids! */ +static struct bitcoin_txid txid_from_hex(const char *hex) +{ + struct bitcoin_txid txid; + + if (!bitcoin_txid_from_hex(hex, strlen(hex), &txid)) + abort(); + return txid; +} + +static struct secret secret_from_hex(const char *hex) +{ + struct secret s; + size_t len; + if (strstarts(hex, "0x")) + hex += 2; + len = strlen(hex); + /* BOLT #3: + * + * - Private keys are displayed as 32 bytes plus a trailing 1 + * (Bitcoin's convention for "compressed" private keys, i.e. keys + * for which the public key is compressed). + */ + if (len == 66 && strends(hex, "01")) + len -= 2; + if (!hex_decode(hex, len, &s, sizeof(s))) + abort(); + return s; +} + +static void tx_must_be_eq(const struct bitcoin_tx *a, + const struct bitcoin_tx *b) +{ + u8 *lina, *linb; + size_t i; + + lina = linearize_tx(tmpctx, a); + linb = linearize_tx(tmpctx, b); + + for (i = 0; i < tal_count(lina); i++) { + if (i >= tal_count(linb)) + errx(1, "Second tx is truncated:\n" + "%s\n" + "%s", + tal_hex(tmpctx, lina), + tal_hex(tmpctx, linb)); + if (lina[i] != linb[i]) + errx(1, "tx differ at offset %zu:\n" + "%s\n" + "%s", + i, + tal_hex(tmpctx, lina), + tal_hex(tmpctx, linb)); + } + if (i != tal_count(linb)) + errx(1, "First tx is truncated:\n" + "%s\n" + "%s", + tal_hex(tmpctx, lina), + tal_hex(tmpctx, linb)); +} + +int main(int argc, const char *argv[]) +{ + common_setup(argv[0]); + tx_must_be_eq(NULL, NULL); + secret_from_hex(NULL); + txid_from_hex(NULL); + common_shutdown(); + + /* FIXME: Do BOLT comparison! */ + return 0; +} From f8400811568d6fbf435f88fa31d5789f0ab6a3ff Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 13:57:38 -0400 Subject: [PATCH 039/283] update libwally --- external/libwally-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/libwally-core b/external/libwally-core index dd15feb8bcad..f09f95c3116c 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit dd15feb8bcada3f87e960e0a14316d2038e6b7bf +Subproject commit f09f95c3116c61e4a594002d9006777f879316ed From a99151b06b8ff359ce1fb3c733a34b3846a52b36 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 14:15:51 -0400 Subject: [PATCH 040/283] Revert "update libwally" This reverts commit f8400811568d6fbf435f88fa31d5789f0ab6a3ff. --- external/libwally-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/libwally-core b/external/libwally-core index f09f95c3116c..dd15feb8bcad 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit f09f95c3116c61e4a594002d9006777f879316ed +Subproject commit dd15feb8bcada3f87e960e0a14316d2038e6b7bf From 6af563663f75e9b725ca943c0a29889e9284b81b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 14:21:24 -0400 Subject: [PATCH 041/283] update libwally --- external/libwally-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/libwally-core b/external/libwally-core index dd15feb8bcad..1f2cb9f89180 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit dd15feb8bcada3f87e960e0a14316d2038e6b7bf +Subproject commit 1f2cb9f89180f1aac6f873d5e72cc4e68608c138 From 74fac28323c0f7f424c68ba093b371b3a90a19d6 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 14:23:07 -0400 Subject: [PATCH 042/283] test compiling --- bitcoin/script.c | 8 ++-- bitcoin/signature.c | 2 +- channeld/test/run-settle_tx.c | 84 ++++++++++++++++++++++++++++++++-- common/initial_settlement_tx.c | 9 ++-- common/keyset.h | 2 +- 5 files changed, 91 insertions(+), 14 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 7b26440fca10..c235e7bd63af 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -966,7 +966,7 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n /* k0 == km, this is the merkle root so we directly write it out */ ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", hash_out->u.u8); - assert(ok); + assert(ok == WALLY_OK); } else if (num_scripts == 2) { int i; for (i=0; i= 0) { @@ -989,7 +989,7 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n memcpy(tap_hashes + 32, tag_hash_buf, 32); } ok = wally_tagged_hash(tap_hashes, sizeof(tap_hashes), "TapBranch", hash_out->u.u8); - assert(ok); + assert(ok == WALLY_OK); } } @@ -1026,7 +1026,7 @@ void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *ot p += script_len; ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", control_block_cursor); - assert(ok); + assert(ok == WALLY_OK); control_block_cursor += 32; } *control_block_size = control_block_cursor - control_block; diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 31e70ecc4d20..08357d701a73 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -375,7 +375,7 @@ void bitcoin_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, tal_wally_start(); ret = wally_tx_get_btc_taproot_signature_hash( tx->wtx, sighash_type, input_index, input_spks, input_spk_lens, - input_val_sats, tapleaf_script, tal_bytelen(tapleaf_script), 0x00 /* key_version */, + input_val_sats, tapleaf_script, tal_bytelen(tapleaf_script), (sighash_type & SIGHASH_ANYPREVOUTANYSCRIPT) == SIGHASH_ANYPREVOUTANYSCRIPT ? 0x01 : 0x00 /* key_version */, 0xFFFFFFFF /* codesep_position */, 0 /* flags */, dest->sha.u.u8, sizeof(*dest)); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 654a9f810b65..5338324cf472 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -7,7 +7,7 @@ static bool print_superverbose; do { if (print_superverbose) printf(__VA_ARGS__); } while(0) #define PRINT_ACTUAL_FEE #include "../commit_tx.c" -#include +#include #include #include #include @@ -15,6 +15,7 @@ static bool print_superverbose; #include #include #include +#include /* Turn this on to brute-force fee values */ /*#define DEBUG */ @@ -115,12 +116,87 @@ static void tx_must_be_eq(const struct bitcoin_tx *a, tal_hex(tmpctx, linb)); } +static struct pubkey pubkey_from_hex(const char *hex) +{ + struct pubkey pubkey; + + if (strstarts(hex, "0x")) + hex += 2; + if (!pubkey_from_hexstr(hex, strlen(hex), &pubkey)) + abort(); + return pubkey; +} + int main(int argc, const char *argv[]) { + struct bitcoin_outpoint update_output; + struct amount_sat update_output_sats; + struct pubkey funding_key[NUM_SIDES]; + u32 shared_delay; + struct eltoo_keyset eltoo_keyset; + struct amount_sat dust_limit; + struct amount_msat self_pay; + struct amount_msat other_pay; + struct amount_sat self_reserve; + u32 obscured_update_number; + /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ + char* err_reason; + struct bitcoin_tx *tx; + struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; + int ok; + common_setup(argv[0]); - tx_must_be_eq(NULL, NULL); - secret_from_hex(NULL); - txid_from_hex(NULL); + + chainparams = chainparams_for_network("bitcoin"); + + /* Test initial settlement tx */ + + update_output.txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); + update_output.n = 0; + update_output_sats.satoshis = 69420; + funding_key[0] = pubkey_from_hex("02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f"); + + alice_funding_privkey.secret = secret_from_hex("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901"); + bob_funding_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); + + ok = pubkey_from_privkey(&alice_funding_privkey, + &funding_key[0]); + ok = pubkey_from_privkey(&bob_funding_privkey, + &funding_key[1]); + + shared_delay = 42; + + alice_settle_privkey.secret = secret_from_hex("1111111111111111111111111111111111111111111111111111111111111111"); + bob_settle_privkey.secret = secret_from_hex("2222222222222222222222222222222222222222222222222222222222222222"); + + ok = pubkey_from_privkey(&alice_settle_privkey, + &eltoo_keyset.self_settle_key); + ok = pubkey_from_privkey(&bob_settle_privkey, + &eltoo_keyset.other_settle_key); + assert(ok); + + dust_limit.satoshis = 294; + self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; + other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; + self_reserve.satoshis = 0; /* not testing this yet since it's really layer violation here */ + obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ + + tx = initial_settlement_tx(tmpctx, + &update_output, + update_output_sats, + funding_key, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + self_reserve, + obscured_update_number, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + &err_reason); + + tx_must_be_eq(tx, tx); + common_shutdown(); /* FIXME: Do BOLT comparison! */ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 723f7e936498..ad6f4a7b3531 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -41,7 +41,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, secp256k1_xonly_pubkey inner_pubkey, output_pubkey; u8 *settle_and_update_tapscripts[2]; u8 *script_pubkey; - u8 dummy_script; + u8 *dummy_script; u8 control_block[33+32]; u8 *witness[2]; /* settle_and_update_tapscripts[0] script and control_block */ size_t control_block_size = sizeof(control_block); @@ -129,7 +129,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct sha256 tap_tweak_out; u8 *tapleaf_scripts[1]; - tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->self_payment_key); + tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->self_settle_key); compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8); @@ -165,7 +165,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct sha256 tap_tweak_out; u8 *tapleaf_scripts[1]; - tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->other_payment_key); + tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->other_settle_key); compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, @@ -229,8 +229,9 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * a sighash to then put into the input sciript. We pass in dummies * where necessary for now. */ + dummy_script = bitcoin_spk_ephemeral_anchor(tmpctx); input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, - /* scriptSig */ NULL, update_output_sats, &dummy_script, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); + /* scriptSig */ NULL, update_output_sats, dummy_script, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); assert(input_num == 0); /* Now the the transaction itself is determined, we must compute the APO sighash to inject it diff --git a/common/keyset.h b/common/keyset.h index b310a338f14a..8d0b0ccc9ad1 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -16,7 +16,7 @@ struct keyset { /* Keys needed to derive a particular settlement tx. */ struct eltoo_keyset { struct pubkey self_htlc_key, other_htlc_key; - struct pubkey self_payment_key, other_payment_key; + struct pubkey self_settle_key, other_settle_key; }; /* Self == owner of commitment tx, other == non-owner. */ From 2ec21efa88eb0a805990d9e5741c133e07a8aed6 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 15:02:20 -0400 Subject: [PATCH 043/283] No crashes on test --- bitcoin/script.c | 11 +++++++---- bitcoin/script.h | 6 +++--- common/initial_settlement_tx.c | 8 ++++---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index c235e7bd63af..ee557beebff2 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -993,15 +993,18 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n } } -void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit) +u8 *compute_control_block(const tal_t *ctx, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit) { int ok; - u8 *control_block_cursor = control_block; + u8 *control_block_cursor; + u8 *control_block = tal_arr(ctx, u8, other_script ? 33 + 32 : 33); + + control_block_cursor = control_block; + unsigned char leaf_version = 0xc0; unsigned char tag_hash_buf[1000]; /* Needs to be large enough for HTLC scripts */ /* Only what's required for eltoo et al for now, 2 leaves max, sue me */ - assert(control_block_size && *control_block_size >= 33 + 32); assert(parity_bit == 0 || parity_bit == 1); control_block_cursor[0] = leaf_version | parity_bit; @@ -1029,7 +1032,7 @@ void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *ot assert(ok == WALLY_OK); control_block_cursor += 32; } - *control_block_size = control_block_cursor - control_block; + return control_block; } u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index) diff --git a/bitcoin/script.h b/bitcoin/script.h index 386e6ff2b983..b30dd1b1d2d5 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -178,12 +178,12 @@ u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts); /* Computes control block for a spend from a taptree of size two, depth of 1, tops. other_script is NULL if only one script is committed. - * @control_block: BIP341 serialized control block - * @control_block_size: (in/out) Size of required buffer, and written for size of control block + * Returns the control block array. + * @other_script: The script that needs to be hashed and put in control block * @inner_pubkey: Inner pubkey for taproot control block * @parity_bit: Parity of outer taproot pubkey */ -void compute_control_block(u8 *control_block, size_t *control_block_size, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit); +u8 *compute_control_block(const tal_t *ctx, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit); /* Creates tapscript that makes a sig-in-script ANYPREVOUTANYSCRIPT covenant * which commits to the tx argument: diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index ad6f4a7b3531..82c89e629484 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -42,9 +42,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, u8 *settle_and_update_tapscripts[2]; u8 *script_pubkey; u8 *dummy_script; - u8 control_block[33+32]; - u8 *witness[2]; /* settle_and_update_tapscripts[0] script and control_block */ - size_t control_block_size = sizeof(control_block); + u8 *control_block; + u8 **witness; /* settle_and_update_tapscripts[0] script and control_block */ struct sha256 update_merkle_root; struct pubkey update_agg_pk; secp256k1_musig_keyagg_cache update_keyagg_cache; @@ -253,7 +252,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* Convert to x-only, grab parity bit of the output pubkey */ ok = secp256k1_xonly_pubkey_from_pubkey(ctx, &output_pubkey, &parity_bit, &(update_agg_pk.pubkey)); assert(ok); - compute_control_block(control_block, &control_block_size, settle_and_update_tapscripts[1], &inner_pubkey, parity_bit); + control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], &inner_pubkey, parity_bit); script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); /* Remove and re-add with updated information */ @@ -266,6 +265,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * the second-to-last stack element s, the script. * last stack element is called the control block */ + witness = tal_arr(tmpctx, u8 *, 2); witness[0] = settle_and_update_tapscripts[0]; witness[1] = control_block; bitcoin_tx_input_set_witness(tx, input_num, witness); From 877dd5c05506b14bfe80b0a228d4138f9fe5e6a7 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 15:24:13 -0400 Subject: [PATCH 044/283] fixup the pay amounts --- channeld/test/run-settle_tx.c | 12 ++++++++++++ common/initial_settlement_tx.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 5338324cf472..eee20da4f4ee 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -54,6 +54,14 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ +static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) +{ + u8 *lin = linearize_tx(ctx, tx); + char *s = tal_hex(ctx, lin); + tal_free(lin); + return s; +} + /* bitcoind loves its backwards txids! */ static struct bitcoin_txid txid_from_hex(const char *hex) { @@ -144,6 +152,7 @@ int main(int argc, const char *argv[]) struct bitcoin_tx *tx; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; + char *tx_hex; common_setup(argv[0]); @@ -197,6 +206,9 @@ int main(int argc, const char *argv[]) tx_must_be_eq(tx, tx); + tx_hex = fmt_bitcoin_tx(tmpctx, tx); + printf("Settlement tx: %s\n", tx_hex); + common_shutdown(); /* FIXME: Do BOLT comparison! */ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 82c89e629484..5346f9252330 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -170,7 +170,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8); - amount = amount_msat_to_sat_round_down(self_pay); + amount = amount_msat_to_sat_round_down(other_pay); int pos = bitcoin_tx_add_output( tx, scriptpubkey_p2tr(ctx, &agg_pk), /* wscript */ NULL, amount /* FIXME PSBT tap output fields*/); assert(pos == output_index); From 87932e52ddda2abcebac2c0cb734c4d399830946 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 7 Jul 2022 15:45:52 -0400 Subject: [PATCH 045/283] Add regression vector that may be wrong --- channeld/test/run-settle_tx.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index eee20da4f4ee..cfa1e81ac204 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -54,6 +54,8 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ +char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120f943c7f1a74a813d2b58a6da3a3335a0cbae49ee2a27be8451b4a4561acbf4681ce800000000000022512071a5325fea5db11f3ff887aa52cfe54143f85c8e1f5cb163d985f13f4baaee040264409ee21e6da38282d769fd3224651e4415c6e95cb5b03436c9b30fddb75c7a7cbdc3b674f8f199bf5f71267fdc101ca59f7612e883540bbf32af31072e915bb351210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a46eb09cb3c07a74993a0c294cfa0b87d5aa9d979f8c4b0e02be2fa561b416d33300000000"; + static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { u8 *lin = linearize_tx(ctx, tx); @@ -149,7 +151,7 @@ int main(int argc, const char *argv[]) u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ char* err_reason; - struct bitcoin_tx *tx; + struct bitcoin_tx *tx, *tx_cmp; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; char *tx_hex; @@ -204,11 +206,13 @@ int main(int argc, const char *argv[]) /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, &err_reason); - tx_must_be_eq(tx, tx); - tx_hex = fmt_bitcoin_tx(tmpctx, tx); printf("Settlement tx: %s\n", tx_hex); + /* Regression test vector for now */ + tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); + tx_must_be_eq(tx, tx_cmp); + common_shutdown(); /* FIXME: Do BOLT comparison! */ From 505ac0d1b83c6db936fd5e023eaa835e3d143723 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 8 Jul 2022 15:54:25 -0400 Subject: [PATCH 046/283] Forgot to tack on sighash flag for APO sig --- bitcoin/script.c | 20 +++++++++++++++++++- channeld/test/run-settle_tx.c | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index ee557beebff2..a2f6475b432c 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -11,6 +11,8 @@ #include #include +#include + /* To push 0-75 bytes onto stack. */ #define OP_PUSHBYTES(val) (val) @@ -1042,10 +1044,12 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size u8 *script = tal_arr(ctx, u8, 0); struct sha256_double sighash; struct bip340sig sig; + unsigned char sig_with_flag[65]; secp256k1_keypair G_pair; secp256k1_xonly_pubkey G; struct privkey g; unsigned char one_G_bytes[33]; +// u8 *sighash_data; /* We use tapleaf_script as a switch for doing BIP342 hash * We really shouldn't, but for now we pass in dummy @@ -1057,6 +1061,12 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size script, &sighash); + printf("SIGHASH: %s\n", tal_hexstr(tmpctx, sighash.sha.u.u32, 32));//\n", sighash.sha.u.u32); + // Core is reporting this 3824125aa2a552b201262e7a01dabad67f95e2a7f62831c0a43957509af121c0 +// sighash_data = tal_hexdata(tmpctx, "3824125aa2a552b201262e7a01dabad67f95e2a7f62831c0a43957509af121c0", strlen("3824125aa2a552b201262e7a01dabad67f95e2a7f62831c0a43957509af121c0")); +// memcpy(sighash.sha.u.u32, sighash_data, 32); +// printf("SIGHASH MOD: %s\n", tal_hexstr(tmpctx, sighash.sha.u.u32, 32)); + /* Should directly take keypair instead of extracting but... */ create_keypair_of_one(&G_pair); ok = secp256k1_keypair_sec( @@ -1082,8 +1092,11 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size one_G_bytes+1, &G); + memcpy(sig_with_flag, sig.u8, sizeof(sig.u8)); + sig_with_flag[64] = sh_type; + /* Build the script */ - script_push_bytes(&script, sig.u8, sizeof(sig.u8)); + script_push_bytes(&script, sig_with_flag, sizeof(sig_with_flag)); script_push_bytes(&script, one_G_bytes, sizeof(one_G_bytes)); add_op(&script, OP_CHECKSIG); return script; @@ -1102,3 +1115,8 @@ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num) add_op(&script, OP_CHECKSEQUENCEVERIFY); return script; } + +//u8 *make_eltoo_htlc_success_script() +//{ + +//} diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index cfa1e81ac204..0be208015146 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -8,6 +8,7 @@ static bool print_superverbose; #define PRINT_ACTUAL_FEE #include "../commit_tx.c" #include +#include #include #include #include @@ -155,6 +156,7 @@ int main(int argc, const char *argv[]) struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; char *tx_hex; + char *psbt_b64; common_setup(argv[0]); @@ -208,6 +210,8 @@ int main(int argc, const char *argv[]) tx_hex = fmt_bitcoin_tx(tmpctx, tx); printf("Settlement tx: %s\n", tx_hex); + psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); + printf("Settlement psbt: %s\n", psbt_b64); /* Regression test vector for now */ tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); From a9a60fb16479e6adaa53c3655d99f54f1e72049b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 8 Jul 2022 16:50:05 -0400 Subject: [PATCH 047/283] Logging... fixed this? --- bitcoin/script.c | 1 + common/initial_settlement_tx.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/bitcoin/script.c b/bitcoin/script.c index a2f6475b432c..0a6fcad81b68 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -983,6 +983,7 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", tap_hashes + (i*32)); assert(ok == WALLY_OK); + printf("TAPLEAF HASHES: %s\n", tal_hexstr(tmpctx, tap_hashes + (i*32), 32)); } /* If kj ≥ ej: kj+1 = hashTapBranch(ej || kj), swap them*/ if (memcmp(tap_hashes, tap_hashes + 32, 32) >= 0) { diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 5346f9252330..0e5462f6bfee 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -6,6 +6,7 @@ #include #include #include +#include void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) @@ -39,6 +40,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct pubkey *pubkey_ptrs[2]; int input_num; secp256k1_xonly_pubkey inner_pubkey, output_pubkey; + unsigned char output_pubkey_bytes[32]; u8 *settle_and_update_tapscripts[2]; u8 *script_pubkey; u8 *dummy_script; @@ -242,6 +244,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* We need to calculate the merkle root to figure the parity bit */ compute_taptree_merkle_root(&update_merkle_root, settle_and_update_tapscripts, /* num_scripts */ 2); + printf("TAP MERK ROOT: %s\n", tal_hexstr(tmpctx, update_merkle_root.u.u32, 32)); bipmusig_finalize_keys(&update_agg_pk, &update_keyagg_cache, pubkey_ptrs, @@ -249,12 +252,21 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, &update_merkle_root, update_tap_tweak); + printf("TAPTWEAK: %s\n", tal_hexstr(tmpctx, update_tap_tweak, 32)); /* Convert to x-only, grab parity bit of the output pubkey */ ok = secp256k1_xonly_pubkey_from_pubkey(ctx, &output_pubkey, &parity_bit, &(update_agg_pk.pubkey)); + printf("PARITY BIT: %d\n", parity_bit); assert(ok); control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], &inner_pubkey, parity_bit); + printf("CBLOCK: %s\n", tal_hexstr(tmpctx, control_block, tal_count(control_block))); script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output_pubkey_bytes, &output_pubkey); + assert(ok); + printf("OUTER PUBKEY: %s\n", tal_hexstr(tmpctx, output_pubkey_bytes, 32)); + + assert(secp256k1_xonly_pubkey_tweak_add_check(secp256k1_ctx, output_pubkey_bytes, parity_bit, &inner_pubkey, update_tap_tweak)); + /* Remove and re-add with updated information */ bitcoin_tx_remove_input(tx, input_num); input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, From 4af08d57535e54506ad14e37c40026e15a17dbc9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 11 Jul 2022 11:59:54 -0400 Subject: [PATCH 048/283] Fix balance outputs, was pushing compressed pubkey... --- bitcoin/script.c | 17 ++++++++++++++++- channeld/test/run-settle_tx.c | 2 +- common/initial_settlement_tx.c | 6 ++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 0a6fcad81b68..b72c173dfca0 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -89,6 +89,20 @@ static void add_push_key(u8 **scriptp, const struct pubkey *key) script_push_bytes(scriptp, der, sizeof(der)); } +static void add_push_xonly_key(u8 **scriptp, const struct pubkey *key) +{ + int ok; + unsigned char xonly_bytes[32]; + secp256k1_xonly_pubkey xonly; + + ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &xonly, /* parity_bit */ NULL, &(key->pubkey)); + assert(ok); + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, xonly_bytes, &xonly); + assert(ok); + + script_push_bytes(scriptp, xonly_bytes, sizeof(xonly_bytes)); +} + static void add_push_sig(u8 **scriptp, const struct bitcoin_signature *sig) { u8 der[73]; @@ -940,7 +954,7 @@ u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_ * * 1 OP_CHECKSEQUENCEVERIFY settlement_pubkey OP_CHECKSIGVERIFY */ - add_push_key(&script, settlement_pubkey); + add_push_xonly_key(&script, settlement_pubkey); add_op(&script, OP_CHECKSIGVERIFY); add_number(&script, 1); add_op(&script, OP_CHECKSEQUENCEVERIFY); @@ -969,6 +983,7 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n /* k0 == km, this is the merkle root so we directly write it out */ ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", hash_out->u.u8); assert(ok == WALLY_OK); + printf("TAPLEAF HASH(1 branch): %s\n", tal_hexstr(tmpctx, hash_out->u.u8, 32)); } else if (num_scripts == 2) { int i; for (i=0; iself_settle_key); + printf("SELF TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8); @@ -167,6 +169,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, u8 *tapleaf_scripts[1]; tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->other_settle_key); + printf("OTHER TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, @@ -261,6 +264,9 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, printf("CBLOCK: %s\n", tal_hexstr(tmpctx, control_block, tal_count(control_block))); script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, &inner_pubkey); + assert(ok); + printf("INNER PUBKEY: %s\n", tal_hexstr(tmpctx, inner_pubkey_bytes, 32)); ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output_pubkey_bytes, &output_pubkey); assert(ok); printf("OUTER PUBKEY: %s\n", tal_hexstr(tmpctx, output_pubkey_bytes, 32)); From 8ce6f95c2e02900f4403a745b10cce267b602c01 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 11 Jul 2022 12:52:56 -0400 Subject: [PATCH 049/283] add htlc success script for eltoo --- bitcoin/script.c | 29 ++++++++++++++++++++--------- bitcoin/script.h | 3 +++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index b72c173dfca0..f23e19d8cc46 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1065,7 +1065,6 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size secp256k1_xonly_pubkey G; struct privkey g; unsigned char one_G_bytes[33]; -// u8 *sighash_data; /* We use tapleaf_script as a switch for doing BIP342 hash * We really shouldn't, but for now we pass in dummy @@ -1078,10 +1077,6 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size &sighash); printf("SIGHASH: %s\n", tal_hexstr(tmpctx, sighash.sha.u.u32, 32));//\n", sighash.sha.u.u32); - // Core is reporting this 3824125aa2a552b201262e7a01dabad67f95e2a7f62831c0a43957509af121c0 -// sighash_data = tal_hexdata(tmpctx, "3824125aa2a552b201262e7a01dabad67f95e2a7f62831c0a43957509af121c0", strlen("3824125aa2a552b201262e7a01dabad67f95e2a7f62831c0a43957509af121c0")); -// memcpy(sighash.sha.u.u32, sighash_data, 32); -// printf("SIGHASH MOD: %s\n", tal_hexstr(tmpctx, sighash.sha.u.u32, 32)); /* Should directly take keypair instead of extracting but... */ create_keypair_of_one(&G_pair); @@ -1132,7 +1127,23 @@ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num) return script; } -//u8 *make_eltoo_htlc_success_script() -//{ - -//} +u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u8 *invoice_hash) +{ + /* where EXPR_SUCCESS = + * + * ` OP_CHECKSIGVERIFY OP_SIZE <32> OP_EQUALVERIFY OP_HASH160 + * OP_EQUALVERIFY 1 OP_CHECKSEQUENCEVERIFY` + */ + u8 *script = tal_arr(ctx, u8, 0); + add_push_xonly_key(&script, settlement_pubkey); + add_op(&script, OP_CHECKSIGVERIFY); + add_op(&script, OP_SIZE); + add_number(&script, 32); + add_op(&script, OP_EQUALVERIFY); + add_op(&script, OP_HASH160); + add(&script, invoice_hash, 32); + add_op(&script, OP_EQUALVERIFY); + add_number(&script, 1); + add_op(&script, OP_CHECKSEQUENCEVERIFY); + return script; +} diff --git a/bitcoin/script.h b/bitcoin/script.h index b30dd1b1d2d5..dc77cb16b51d 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -194,6 +194,9 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size /* Creates the update path tapscript for eltoo, which commits to the masked update number */ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); +/* Creates eltoo HTLC success script, with invoice hash lock */ +u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u8 *invoice_hash); + /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) From ff3477231c4af02ef5c36aea0634914bce96715b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 11 Jul 2022 13:02:28 -0400 Subject: [PATCH 050/283] Add eltoo HTLC timeout tapscript creation --- bitcoin/script.c | 17 +++++++++++++++++ bitcoin/script.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/bitcoin/script.c b/bitcoin/script.c index f23e19d8cc46..c6c64e901a67 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1147,3 +1147,20 @@ u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settle add_op(&script, OP_CHECKSEQUENCEVERIFY); return script; } + +u8 *make_eltoo_htlc_timeout_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u32 htlc_timeout) +{ + /* and EXPR_TIMEOUT = + * + *` OP_CHECKLOCKTIMEVERIFY OP_VERIFY OP_CHECKSIGVERIFY 1 + * OP_CHECKSEQUENCEVERIFY` + */ + u8 *script = tal_arr(ctx, u8, 0); + add_number(&script, htlc_timeout); + add_op(&script, OP_VERIFY); + add_push_xonly_key(&script, settlement_pubkey); + add_op(&script, OP_CHECKSIGVERIFY); + add_number(&script, 1); + add_op(&script, OP_CHECKSEQUENCEVERIFY); + return script; +} diff --git a/bitcoin/script.h b/bitcoin/script.h index dc77cb16b51d..3ae47da30627 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -197,6 +197,9 @@ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); /* Creates eltoo HTLC success script, with invoice hash lock */ u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u8 *invoice_hash); +/* Creates eltoo HTLC timeout script, with timeout value */ +u8 *make_eltoo_htlc_timeout_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u32 htlc_timeout); + /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) From b69a34ce4cedbb6079780c2c564c296dd3f7a501 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 11 Jul 2022 13:36:05 -0400 Subject: [PATCH 051/283] compartmentalise settlement tx test --- channeld/test/run-settle_tx.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index d4d94d5d04df..ab4464f5bc64 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -138,7 +138,7 @@ static struct pubkey pubkey_from_hex(const char *hex) return pubkey; } -int main(int argc, const char *argv[]) +static int test_initial_settlement_tx(void) { struct bitcoin_outpoint update_output; struct amount_sat update_output_sats; @@ -158,10 +158,6 @@ int main(int argc, const char *argv[]) char *tx_hex; char *psbt_b64; - common_setup(argv[0]); - - chainparams = chainparams_for_network("bitcoin"); - /* Test initial settlement tx */ update_output.txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); @@ -217,8 +213,23 @@ int main(int argc, const char *argv[]) tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); tx_must_be_eq(tx, tx_cmp); - common_shutdown(); - /* FIXME: Do BOLT comparison! */ return 0; } + +int main(int argc, const char *argv[]) +{ + int err = 0; + + common_setup(argv[0]); + + chainparams = chainparams_for_network("bitcoin"); + + err |= test_initial_settlement_tx(); + assert(!err); + + common_shutdown(); + + return err; +} + From d6346ea505d2eee465187499459320436755ab8a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 11 Jul 2022 14:51:31 -0400 Subject: [PATCH 052/283] Add basic HTLC test cross-reffed with scriptwiz results --- bitcoin/script.c | 3 +- channeld/test/run-settle_tx.c | 58 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index c6c64e901a67..76f9f5b6c60b 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1141,7 +1141,7 @@ u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settle add_number(&script, 32); add_op(&script, OP_EQUALVERIFY); add_op(&script, OP_HASH160); - add(&script, invoice_hash, 32); + script_push_bytes(&script, invoice_hash, 20); add_op(&script, OP_EQUALVERIFY); add_number(&script, 1); add_op(&script, OP_CHECKSEQUENCEVERIFY); @@ -1157,6 +1157,7 @@ u8 *make_eltoo_htlc_timeout_script(const tal_t *ctx, const struct pubkey *settle */ u8 *script = tal_arr(ctx, u8, 0); add_number(&script, htlc_timeout); + add_op(&script, OP_CHECKLOCKTIMEVERIFY); add_op(&script, OP_VERIFY); add_push_xonly_key(&script, settlement_pubkey); add_op(&script, OP_CHECKSIGVERIFY); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index ab4464f5bc64..6e95a6eb1c54 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -217,6 +217,62 @@ static int test_initial_settlement_tx(void) return 0; } +static int test_htlc_output_creation(void) +{ + struct privkey settlement_privkey; + struct pubkey settlement_pubkey, agg_pubkey; + const struct pubkey * pubkey_ptrs[1]; + u8 *htlc_success_script; + u8 *htlc_timeout_script; + u8 *tapleaf_scripts[2]; + u8 *taproot_script; + /* 0-value hash image */ + unsigned char *invoice_hash = tal_arr(tmpctx, u8, 20); + struct sha256 tap_merkle_root; + secp256k1_xonly_pubkey inner_pubkey; + unsigned char inner_pubkey_bytes[32]; + secp256k1_musig_keyagg_cache keyagg_cache; + unsigned char tap_tweak_out[32]; + int ok; + char *tap_hex; + char hex_script[] = "51201886a9f50222b126b010a811bb156cbd6572ba92282808f384e9af4a0849028d"; + + settlement_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); + + ok = pubkey_from_privkey(&settlement_privkey, + &settlement_pubkey); + assert(ok); + + pubkey_ptrs[0] = &settlement_pubkey; + + /* Calculate inner pubkey */ + bipmusig_inner_pubkey(&inner_pubkey, + pubkey_ptrs, + /* n_pubkeys */ 1); + + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, &inner_pubkey); + assert(ok); + printf("INNER PUBKEY: %s\n", tal_hexstr(tmpctx, inner_pubkey_bytes, 32)); + + htlc_success_script = make_eltoo_htlc_success_script(tmpctx, &settlement_pubkey, invoice_hash); + printf("HTLC Success script: %s\n", tal_hexstr(tmpctx, htlc_success_script, tal_count(htlc_success_script))); + htlc_timeout_script = make_eltoo_htlc_timeout_script(tmpctx, &settlement_pubkey, 420); + printf("HTLC Timeout script: %s\n", tal_hexstr(tmpctx, htlc_timeout_script, tal_count(htlc_timeout_script))); + tapleaf_scripts[0] = htlc_success_script; + tapleaf_scripts[1] = htlc_timeout_script; + compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 2); + bipmusig_finalize_keys(&agg_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 1, + &tap_merkle_root, tap_tweak_out); + taproot_script = scriptpubkey_p2tr(tmpctx, &agg_pubkey); + /* Size of OP_1 script in hex output*/ + assert(tal_count(taproot_script) == 1+1+32); + tap_hex = tal_hexstr(tmpctx, taproot_script, tal_count(taproot_script)); + printf("Taproot script: %s\n", tap_hex); + assert(tal_count(tap_hex) == (1+1+32)*2 + 1); + assert(!memcmp(tap_hex, hex_script, tal_count(tap_hex))); + return 0; +} + int main(int argc, const char *argv[]) { int err = 0; @@ -228,6 +284,8 @@ int main(int argc, const char *argv[]) err |= test_initial_settlement_tx(); assert(!err); + err |= test_htlc_output_creation(); + common_shutdown(); return err; From 2f459c5db91795254a58d982b90eccf01e0aba90 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 11 Jul 2022 14:53:15 -0400 Subject: [PATCH 053/283] f --- channeld/test/run-settle_tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 6e95a6eb1c54..033a95bbae32 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -235,6 +235,7 @@ static int test_htlc_output_creation(void) unsigned char tap_tweak_out[32]; int ok; char *tap_hex; + /* Ground truth generated elsewhere */ char hex_script[] = "51201886a9f50222b126b010a811bb156cbd6572ba92282808f384e9af4a0849028d"; settlement_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); From 3dcfba60868d32bcf8fb2b56992b69fffb8754b0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 12 Jul 2022 15:07:41 -0400 Subject: [PATCH 054/283] simplify key storage with eltoo_keyset --- channeld/test/run-settle_tx.c | 18 ++---------------- common/initial_settlement_tx.c | 19 +++++++++---------- common/initial_settlement_tx.h | 6 ++---- common/keyset.h | 1 + 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 033a95bbae32..811b159cd11f 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -127,22 +127,10 @@ static void tx_must_be_eq(const struct bitcoin_tx *a, tal_hex(tmpctx, linb)); } -static struct pubkey pubkey_from_hex(const char *hex) -{ - struct pubkey pubkey; - - if (strstarts(hex, "0x")) - hex += 2; - if (!pubkey_from_hexstr(hex, strlen(hex), &pubkey)) - abort(); - return pubkey; -} - static int test_initial_settlement_tx(void) { struct bitcoin_outpoint update_output; struct amount_sat update_output_sats; - struct pubkey funding_key[NUM_SIDES]; u32 shared_delay; struct eltoo_keyset eltoo_keyset; struct amount_sat dust_limit; @@ -163,15 +151,14 @@ static int test_initial_settlement_tx(void) update_output.txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); update_output.n = 0; update_output_sats.satoshis = 69420; - funding_key[0] = pubkey_from_hex("02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f"); alice_funding_privkey.secret = secret_from_hex("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901"); bob_funding_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); ok = pubkey_from_privkey(&alice_funding_privkey, - &funding_key[0]); + &eltoo_keyset.self_funding_key); ok = pubkey_from_privkey(&bob_funding_privkey, - &funding_key[1]); + &eltoo_keyset.other_funding_key); shared_delay = 42; @@ -193,7 +180,6 @@ static int test_initial_settlement_tx(void) tx = initial_settlement_tx(tmpctx, &update_output, update_output_sats, - funding_key, shared_delay, &eltoo_keyset, dust_limit, diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 84166cd0a670..9b3a1d4f3a0b 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -16,9 +16,8 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) } struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, - const struct bitcoin_outpoint *update_output, - struct amount_sat update_output_sats, - const struct pubkey funding_key[NUM_SIDES], + const struct bitcoin_outpoint *update_outpoint, + struct amount_sat update_outpoint_sats, u32 shared_delay, const struct eltoo_keyset *eltoo_keyset, struct amount_sat dust_limit, @@ -54,8 +53,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, int parity_bit, ok; /* For MuSig aggregation for outputs */ - pubkey_ptrs[0] = &funding_key[0]; - pubkey_ptrs[1] = &funding_key[1]; + pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); + pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, @@ -64,7 +63,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, if (!amount_msat_add(&total_pay, self_pay, other_pay)) abort(); - assert(!amount_msat_greater_sat(total_pay, update_output_sats)); + assert(!amount_msat_greater_sat(total_pay, update_outpoint_sats)); /* BOLT #3: * @@ -234,8 +233,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * where necessary for now. */ dummy_script = bitcoin_spk_ephemeral_anchor(tmpctx); - input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, - /* scriptSig */ NULL, update_output_sats, dummy_script, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); + input_num = bitcoin_tx_add_input(tx, update_outpoint, shared_delay, + /* scriptSig */ NULL, update_outpoint_sats, dummy_script, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); assert(input_num == 0); /* Now the the transaction itself is determined, we must compute the APO sighash to inject it @@ -275,8 +274,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* Remove and re-add with updated information */ bitcoin_tx_remove_input(tx, input_num); - input_num = bitcoin_tx_add_input(tx, update_output, shared_delay, - /* scriptSig */ NULL, update_output_sats, script_pubkey, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); + input_num = bitcoin_tx_add_input(tx, update_outpoint, shared_delay, + /* scriptSig */ NULL, update_outpoint_sats, script_pubkey, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); assert(input_num == 0); /* We have the complete witness for this transaction already, just add it diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 7bf9cb1715b5..674aede389cb 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -16,9 +16,8 @@ struct wally_tx_output; * initial_settlement_tx: create (unsigned) update tx to spend the first update tx * @ctx: context to allocate transaction and @htlc_map from. * @funding, @funding_sats: funding outpoint and amount - * @funding_keys: funding bitcoin keys to rederive funding output script * @shared_delay: delay before this settlement transaction can be included in a block - * @eltoo_keyset: keys for the settlement outputs. + * @eltoo_keyset: keys for the update and settlement outputs. * @dust_limit: dust limit below which to trim outputs. * @self_pay: amount to pay directly to self * @other_pay: amount to pay directly to the other side @@ -30,8 +29,7 @@ struct wally_tx_output; */ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct bitcoin_outpoint *update_output, - struct amount_sat udpate_output_sats, - const struct pubkey funding_key[NUM_SIDES], + struct amount_sat update_output_sats, u32 shared_delay, const struct eltoo_keyset *eltoo_keyset, struct amount_sat dust_limit, diff --git a/common/keyset.h b/common/keyset.h index 8d0b0ccc9ad1..1fb85a54697b 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -17,6 +17,7 @@ struct keyset { struct eltoo_keyset { struct pubkey self_htlc_key, other_htlc_key; struct pubkey self_settle_key, other_settle_key; + struct pubkey self_funding_key, other_funding_key; }; /* Self == owner of commitment tx, other == non-owner. */ From 36b31a61e48bbfd26f62bb40b92f0338ef29f10e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 13 Jul 2022 11:12:05 -0400 Subject: [PATCH 055/283] refactor out tx_add_to_node_output --- common/initial_settlement_tx.c | 72 +++++++++++++++------------------- common/initial_settlement_tx.h | 3 ++ 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 9b3a1d4f3a0b..d0949002e48d 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -8,6 +8,36 @@ #include #include +int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *eltoo_keyset, struct amount_msat pay, enum side receiver) +{ + struct pubkey taproot_pk; + secp256k1_musig_keyagg_cache keyagg_cache; + struct sha256 tap_merkle_root; + struct sha256 tap_tweak_out; + u8 *tapleaf_scripts[1]; + struct pubkey const *receiver_pubkey; + struct pubkey const *pubkey_ptrs[2]; + struct amount_sat amount; + + if (receiver == LOCAL) { + receiver_pubkey = &eltoo_keyset->self_settle_key; + } else { + receiver_pubkey = &eltoo_keyset->other_settle_key; + } + + pubkey_ptrs[0] = &eltoo_keyset->self_funding_key; + pubkey_ptrs[1] = &eltoo_keyset->other_funding_key; + + tapleaf_scripts[0] = bitcoin_tapscript_to_node(tmpctx, receiver_pubkey); + printf("SELF TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); + compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); + bipmusig_finalize_keys(&taproot_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, + &tap_merkle_root, tap_tweak_out.u.u8); + + amount = amount_msat_to_sat_round_down(pay); + return bitcoin_tx_add_output( + tx, scriptpubkey_p2tr(tmpctx, &taproot_pk), /* wscript */ NULL, amount /* FIXME pass in psbt fields for tap outputs */); +} void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) { @@ -32,7 +62,6 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, size_t output_index, num_untrimmed; bool to_local, to_remote; struct amount_msat total_pay; - struct amount_sat amount; void *dummy_local = (void *)LOCAL, *dummy_remote = (void *)REMOTE; /* There is a direct output and possibly a shared anchor output */ const void *output_order[NUM_SIDES + 1]; @@ -124,21 +153,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * output](#to_node-output). */ if (amount_msat_greater_eq_sat(self_pay, dust_limit)) { - struct pubkey agg_pk; - secp256k1_musig_keyagg_cache keyagg_cache; - struct sha256 tap_merkle_root; - struct sha256 tap_tweak_out; - u8 *tapleaf_scripts[1]; - - tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->self_settle_key); - printf("SELF TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); - compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); - bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out.u.u8); - - amount = amount_msat_to_sat_round_down(self_pay); - int pos = bitcoin_tx_add_output( - tx, scriptpubkey_p2tr(ctx, &agg_pk), /* wscript */ NULL, amount /* FIXME pass in psbt fields for tap outputs */); + int pos = tx_add_to_node_output(tx, eltoo_keyset, self_pay, LOCAL); assert(pos == output_index); output_order[output_index] = dummy_local; output_index++; @@ -153,30 +168,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * output](#to_remote-output). */ if (amount_msat_greater_eq_sat(other_pay, dust_limit)) { - /* BOLT #???: - * - * If `option_anchors` applies to the commitment - * transaction, the `to_remote` output is encumbered by a one - * block csv lock. - * OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY - * - */ - struct pubkey agg_pk; - secp256k1_musig_keyagg_cache keyagg_cache; - struct sha256 tap_merkle_root; - struct sha256 tap_tweak_out; - u8 *tapleaf_scripts[1]; - - tapleaf_scripts[0] = bitcoin_tapscript_to_node(ctx, &eltoo_keyset->other_settle_key); - printf("OTHER TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); - compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); - - bipmusig_finalize_keys(&agg_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out.u.u8); - - amount = amount_msat_to_sat_round_down(other_pay); - int pos = bitcoin_tx_add_output( - tx, scriptpubkey_p2tr(ctx, &agg_pk), /* wscript */ NULL, amount /* FIXME PSBT tap output fields*/); + int pos = tx_add_to_node_output(tx, eltoo_keyset, other_pay, REMOTE); assert(pos == output_index); output_order[output_index] = dummy_remote; output_index++; diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 674aede389cb..d7edbf0a1e91 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -12,6 +12,7 @@ struct bitcoin_outpoint; struct eltoo_keyset; struct wally_tx_output; + /** * initial_settlement_tx: create (unsigned) update tx to spend the first update tx * @ctx: context to allocate transaction and @htlc_map from. @@ -44,4 +45,6 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* We always add a single ephemeral anchor output to settlement transactions */ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx); +int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *eltoo_keyset, struct amount_msat pay, enum side receiver); + #endif /* LIGHTNING_COMMON_INITIAL_SETTLEMENT_TX_H */ From a61824791d197fe8858cc99c1b8b3e5c3d3e0f82 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 15 Jul 2022 13:37:02 -0400 Subject: [PATCH 056/283] Refactor out settlement transaction input creation --- common/initial_settlement_tx.c | 160 ++++++++++++++++++--------------- common/initial_settlement_tx.h | 2 + 2 files changed, 89 insertions(+), 73 deletions(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index d0949002e48d..93aa36a6504c 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -8,6 +8,10 @@ #include #include +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *eltoo_keyset, struct amount_msat pay, enum side receiver) { struct pubkey taproot_pk; @@ -29,7 +33,7 @@ int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *elto pubkey_ptrs[1] = &eltoo_keyset->other_funding_key; tapleaf_scripts[0] = bitcoin_tapscript_to_node(tmpctx, receiver_pubkey); - printf("SELF TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); + SUPERVERBOSE("SELF TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&taproot_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8); @@ -45,6 +49,86 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) bitcoin_tx_add_output(tx, spk, /* wscript */ NULL, AMOUNT_SAT(0)); } +void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *update_outpoint, + struct amount_sat update_outpoint_sats, u32 shared_delay, secp256k1_xonly_pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]) +{ + u8 *dummy_script; + int input_num; + u8 *settle_and_update_tapscripts[2]; + struct sha256 update_merkle_root; + struct pubkey update_agg_pk; + secp256k1_musig_keyagg_cache update_keyagg_cache; + unsigned char update_tap_tweak[32]; + secp256k1_xonly_pubkey output_pubkey; + int parity_bit, ok; + u8 *control_block; + u8 *script_pubkey; + u8 **witness; /* settle_and_update_tapscripts[0] script and control_block */ + unsigned char inner_pubkey_bytes[32]; + unsigned char output_pubkey_bytes[32]; + + /* + * We do not know what scriptPubKey, tap_tree look like yet because we're computing + * a sighash to then put into the input sciript. We pass in dummies + * where necessary for now. + */ + dummy_script = bitcoin_spk_ephemeral_anchor(tmpctx); + input_num = bitcoin_tx_add_input(tx, update_outpoint, shared_delay, + /* scriptSig */ NULL, update_outpoint_sats, dummy_script, /* input_wscript */ NULL, inner_pubkey, /* tap_tree */ NULL); + assert(input_num == 0); + + /* Now the the transaction itself is determined, we must compute the APO sighash to inject it + into the inputs' tapscript, then attach the information to the PSBT */ + settle_and_update_tapscripts[0] = make_eltoo_settle_script(tmpctx, tx, input_num); + settle_and_update_tapscripts[1] = make_eltoo_update_script(tmpctx, obscured_update_number); + assert(settle_and_update_tapscripts[0]); + assert(settle_and_update_tapscripts[1]); + + /* We need to calculate the merkle root to figure the parity bit */ + compute_taptree_merkle_root(&update_merkle_root, settle_and_update_tapscripts, /* num_scripts */ 2); + printf("TAP MERK ROOT: %s\n", tal_hexstr(tmpctx, update_merkle_root.u.u32, 32)); + bipmusig_finalize_keys(&update_agg_pk, + &update_keyagg_cache, + pubkey_ptrs, + /* n_pubkeys */ 2, + &update_merkle_root, + update_tap_tweak); + + printf("TAPTWEAK: %s\n", tal_hexstr(tmpctx, update_tap_tweak, 32)); + /* Convert to x-only, grab parity bit of the output pubkey */ + ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &output_pubkey, &parity_bit, &(update_agg_pk.pubkey)); + printf("PARITY BIT: %d\n", parity_bit); + assert(ok); + control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], inner_pubkey, parity_bit); + printf("CBLOCK: %s\n", tal_hexstr(tmpctx, control_block, tal_count(control_block))); + script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); + + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, inner_pubkey); + assert(ok); + printf("INNER PUBKEY: %s\n", tal_hexstr(tmpctx, inner_pubkey_bytes, 32)); + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output_pubkey_bytes, &output_pubkey); + assert(ok); + printf("OUTER PUBKEY: %s\n", tal_hexstr(tmpctx, output_pubkey_bytes, 32)); + + assert(secp256k1_xonly_pubkey_tweak_add_check(secp256k1_ctx, output_pubkey_bytes, parity_bit, inner_pubkey, update_tap_tweak)); + + /* Remove and re-add with updated information */ + bitcoin_tx_remove_input(tx, input_num); + input_num = bitcoin_tx_add_input(tx, update_outpoint, shared_delay, + /* scriptSig */ NULL, update_outpoint_sats, script_pubkey, /* input_wscript */ NULL, inner_pubkey, /* tap_tree */ NULL); + assert(input_num == 0); + + /* We have the complete witness for this transaction already, just add it + * the second-to-last stack element s, the script. + * last stack element is called the control block + */ + witness = tal_arr(tmpctx, u8 *, 2); + witness[0] = settle_and_update_tapscripts[0]; + witness[1] = control_block; + bitcoin_tx_input_set_witness(tx, input_num, witness); +} + + struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, @@ -66,20 +150,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* There is a direct output and possibly a shared anchor output */ const void *output_order[NUM_SIDES + 1]; const struct pubkey *pubkey_ptrs[2]; - int input_num; - secp256k1_xonly_pubkey inner_pubkey, output_pubkey; - unsigned char inner_pubkey_bytes[32]; - unsigned char output_pubkey_bytes[32]; - u8 *settle_and_update_tapscripts[2]; - u8 *script_pubkey; - u8 *dummy_script; - u8 *control_block; - u8 **witness; /* settle_and_update_tapscripts[0] script and control_block */ - struct sha256 update_merkle_root; - struct pubkey update_agg_pk; - secp256k1_musig_keyagg_cache update_keyagg_cache; - unsigned char update_tap_tweak[32]; - int parity_bit, ok; + secp256k1_xonly_pubkey inner_pubkey; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); @@ -219,65 +290,8 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured commitment number * * `txin[0]` script bytes: 0 */ - /* - * We do not know what scriptPubKey, tap_tree look like yet because we're computing - * a sighash to then put into the input sciript. We pass in dummies - * where necessary for now. - */ - dummy_script = bitcoin_spk_ephemeral_anchor(tmpctx); - input_num = bitcoin_tx_add_input(tx, update_outpoint, shared_delay, - /* scriptSig */ NULL, update_outpoint_sats, dummy_script, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); - assert(input_num == 0); - - /* Now the the transaction itself is determined, we must compute the APO sighash to inject it - into the inputs' tapscript, then attach the information to the PSBT */ - settle_and_update_tapscripts[0] = make_eltoo_settle_script(tmpctx, tx, input_num); - settle_and_update_tapscripts[1] = make_eltoo_update_script(tmpctx, obscured_update_number); - assert(settle_and_update_tapscripts[0]); - assert(settle_and_update_tapscripts[1]); - - /* We need to calculate the merkle root to figure the parity bit */ - compute_taptree_merkle_root(&update_merkle_root, settle_and_update_tapscripts, /* num_scripts */ 2); - printf("TAP MERK ROOT: %s\n", tal_hexstr(tmpctx, update_merkle_root.u.u32, 32)); - bipmusig_finalize_keys(&update_agg_pk, - &update_keyagg_cache, - pubkey_ptrs, - /* n_pubkeys */ 2, - &update_merkle_root, - update_tap_tweak); - - printf("TAPTWEAK: %s\n", tal_hexstr(tmpctx, update_tap_tweak, 32)); - /* Convert to x-only, grab parity bit of the output pubkey */ - ok = secp256k1_xonly_pubkey_from_pubkey(ctx, &output_pubkey, &parity_bit, &(update_agg_pk.pubkey)); - printf("PARITY BIT: %d\n", parity_bit); - assert(ok); - control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], &inner_pubkey, parity_bit); - printf("CBLOCK: %s\n", tal_hexstr(tmpctx, control_block, tal_count(control_block))); - script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); - - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, &inner_pubkey); - assert(ok); - printf("INNER PUBKEY: %s\n", tal_hexstr(tmpctx, inner_pubkey_bytes, 32)); - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output_pubkey_bytes, &output_pubkey); - assert(ok); - printf("OUTER PUBKEY: %s\n", tal_hexstr(tmpctx, output_pubkey_bytes, 32)); - - assert(secp256k1_xonly_pubkey_tweak_add_check(secp256k1_ctx, output_pubkey_bytes, parity_bit, &inner_pubkey, update_tap_tweak)); - - /* Remove and re-add with updated information */ - bitcoin_tx_remove_input(tx, input_num); - input_num = bitcoin_tx_add_input(tx, update_outpoint, shared_delay, - /* scriptSig */ NULL, update_outpoint_sats, script_pubkey, /* input_wscript */ NULL, &inner_pubkey, /* tap_tree */ NULL); - assert(input_num == 0); - /* We have the complete witness for this transaction already, just add it - * the second-to-last stack element s, the script. - * last stack element is called the control block - */ - witness = tal_arr(tmpctx, u8 *, 2); - witness[0] = settle_and_update_tapscripts[0]; - witness[1] = control_block; - bitcoin_tx_input_set_witness(tx, input_num, witness); + add_settlement_input(tx, update_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); /* Transaction is now ready for broadcast! */ diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index d7edbf0a1e91..bae939f8a814 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -47,4 +47,6 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx); int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *eltoo_keyset, struct amount_msat pay, enum side receiver); +void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, u32 shared_delay, secp256k1_xonly_pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]); + #endif /* LIGHTNING_COMMON_INITIAL_SETTLEMENT_TX_H */ From ce92a0224e51d8fae743c838aaffc0fdfa9ad193 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 15 Jul 2022 15:35:59 -0400 Subject: [PATCH 057/283] Add non-initial settlement tx creation plus test without htlcs --- bitcoin/script.c | 2 +- bitcoin/script.h | 2 +- channeld/Makefile | 2 + channeld/settle_tx.c | 268 ++++++++++++++++++++++++++++++++++ channeld/settle_tx.h | 67 +++++++++ channeld/test/run-settle_tx.c | 198 ++++++++++++++++++++++++- 6 files changed, 536 insertions(+), 3 deletions(-) create mode 100644 channeld/settle_tx.c create mode 100644 channeld/settle_tx.h diff --git a/bitcoin/script.c b/bitcoin/script.c index 76f9f5b6c60b..088fadbc0bb9 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1127,7 +1127,7 @@ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num) return script; } -u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u8 *invoice_hash) +u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const u8 *invoice_hash) { /* where EXPR_SUCCESS = * diff --git a/bitcoin/script.h b/bitcoin/script.h index 3ae47da30627..0d6667120519 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -195,7 +195,7 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); /* Creates eltoo HTLC success script, with invoice hash lock */ -u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u8 *invoice_hash); +u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const u8 *invoice_hash); /* Creates eltoo HTLC timeout script, with timeout value */ u8 *make_eltoo_htlc_timeout_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u32 htlc_timeout); diff --git a/channeld/Makefile b/channeld/Makefile index 739d2091f58a..ccaf8bb97c45 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -8,12 +8,14 @@ CHANNELD_HEADERS := \ channeld/commit_tx.h \ channeld/full_channel.h \ channeld/full_channel_error.h \ + channeld/settle_tx.h \ channeld/watchtower.h CHANNELD_SRC := channeld/channeld.c \ channeld/commit_tx.c \ channeld/full_channel.c \ channeld/channeld_wiregen.c \ + channeld/settle_tx.c \ channeld/watchtower.c CHANNELD_OBJS := $(CHANNELD_SRC:.c=.o) diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c new file mode 100644 index 000000000000..b07cb4138d76 --- /dev/null +++ b/channeld/settle_tx.c @@ -0,0 +1,268 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + +/* These are 0-fee, require anchors, so we override useless options */ +static bool trim(const struct htlc *htlc, + struct amount_sat dust_limit) +{ + return htlc_is_trimmed(htlc_owner(htlc), htlc->amount, + /* feerate_per_kw */ 0, dust_limit, /* side */ LOCAL, + /* option_anchor_outputs */ true); +} + +size_t settle_tx_num_untrimmed(const struct htlc **htlcs, + struct amount_sat dust_limit) +{ + size_t i, n; + + for (i = n = 0; i < tal_count(htlcs); i++) + n += !trim(htlcs[i], dust_limit); + + return n; +} + +bool settle_tx_amount_trimmed(const struct htlc **htlcs, + struct amount_sat dust_limit, + struct amount_msat *amt) +{ + for (size_t i = 0; i < tal_count(htlcs); i++) { + if (trim(htlcs[i], dust_limit)) + if (!amount_msat_add(amt, *amt, htlcs[i]->amount)) + return false; + } + return true; +} + +static void add_eltoo_htlc_out(struct bitcoin_tx *tx, + const struct htlc *htlc, + const struct eltoo_keyset *eltoo_keyset, + enum side receiver_side) +{ + struct ripemd160 ripemd; + u8 *htlc_scripts[2]; + u8 *taproot_script; + struct sha256 tap_merkle_root; + const struct pubkey *sender_pubkey, *receiver_pubkey; + const struct pubkey *pubkey_ptrs[2]; + struct amount_sat amount; + secp256k1_musig_keyagg_cache keyagg_cache; + struct pubkey taproot_pubkey; + unsigned char tap_tweak_out[32]; + + if (receiver_side == LOCAL) { + receiver_pubkey = &(eltoo_keyset->self_settle_key); + sender_pubkey = &(eltoo_keyset->other_settle_key); + } else { + receiver_pubkey = &(eltoo_keyset->other_settle_key); + sender_pubkey = &(eltoo_keyset->self_settle_key); + } + + pubkey_ptrs[0] = receiver_pubkey; + pubkey_ptrs[1] = sender_pubkey; + + ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); + + htlc_scripts[0] = make_eltoo_htlc_success_script(tx, receiver_pubkey, htlc->rhash.u.u8); + htlc_scripts[1] = make_eltoo_htlc_timeout_script(tx, sender_pubkey, htlc->expiry.locktime); + compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); + bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 1, + &tap_merkle_root, tap_tweak_out); + taproot_script = scriptpubkey_p2tr(tx, &taproot_pubkey); + + amount = amount_msat_to_sat_round_down(htlc->amount); + + bitcoin_tx_add_output(tx, taproot_script, /* wscript */ NULL, amount); + + SUPERVERBOSE("# HTLC #%"PRIu64" received amount %"PRIu64" success_script %s timeout_script %s\n", + htlc->id, + amount.satoshis, /* Raw: BOLT 3 output match */ + tal_hex(htlc_scripts[0], htlc_scripts[0]), + tal_hex(htlc_scripts[1], htlc_scripts[1])); + + tal_free(htlc_scripts[0]); + tal_free(htlc_scripts[1]); +} + +struct bitcoin_tx *settle_tx(const tal_t *ctx, + const struct bitcoin_outpoint *update_outpoint, + struct amount_sat update_outpoint_sats, + u16 shared_delay, + const struct eltoo_keyset *eltoo_keyset, + struct amount_sat dust_limit, + struct amount_msat self_pay, + struct amount_msat other_pay, + const struct htlc **htlcs, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + u64 obscured_update_number) +{ + struct amount_msat total_pay; + struct bitcoin_tx *tx; + size_t i, n, num_untrimmed; + u32 *cltvs; + bool to_local, to_remote; + struct htlc *dummy_to_local = (struct htlc *)0x01, + *dummy_to_remote = (struct htlc *)0x02; + secp256k1_xonly_pubkey inner_pubkey; + const struct pubkey *pubkey_ptrs[2]; + + /* For MuSig aggregation for outputs */ + pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); + pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); + + /* Channel-wide inner public key computed here */ + bipmusig_inner_pubkey(&inner_pubkey, + pubkey_ptrs, + /* n_pubkeys */ 2); + + + if (!amount_msat_add(&total_pay, self_pay, other_pay)) + abort(); + assert(!amount_msat_greater_sat(total_pay, update_outpoint_sats)); + + /* BOLT #3: + * + * 1. Calculate which settleted HTLCs need to be trimmed (see + * [Trimmed Outputs](#trimmed-outputs)). + */ + num_untrimmed = settle_tx_num_untrimmed(htlcs, + dust_limit); + + + /* Worst-case sizing: both to-local and to-remote outputs, and single anchor. */ + tx = bitcoin_tx(ctx, chainparams, 1, num_untrimmed + NUM_SIDES + 1, 0); + + /* We keep track of which outputs have which HTLCs */ + *htlcmap = tal_arr(tx, const struct htlc *, tx->wtx->outputs_allocation_len); + + /* We keep cltvs for tie-breaking HTLC outputs; we use the same order + * for sending the htlc txs, so it may matter. */ + cltvs = tal_arr(tmpctx, u32, tx->wtx->outputs_allocation_len); + + /* This could be done in a single loop, but we follow the BOLT + * literally to make comments in test vectors clearer. */ + + n = 0; + /* BOLT #??: + * + * 4. For every HTLC, if it is not trimmed, add an + * [HTLC output](#htlc-outputs). + */ + for (i = 0; i < tal_count(htlcs); i++) { + if (trim(htlcs[i], dust_limit)) + continue; + add_eltoo_htlc_out(tx, htlcs[i], eltoo_keyset, + htlc_owner(htlcs[i])); + (*htlcmap)[n] = htlcs[i]; + cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry); + n++; + } + + /* BOLT #3: + * + * 6. If the `to_local` amount is greater or equal to + * `dust_limit_satoshis`, add a [`to_local` + * output](#to_local-output). + */ + if (amount_msat_greater_eq_sat(self_pay, dust_limit)) { + int pos = tx_add_to_node_output(tx, eltoo_keyset, self_pay, LOCAL); + assert(pos == n); + /* Add a dummy entry to the htlcmap so we can recognize it later */ + (*htlcmap)[n] = direct_outputs ? dummy_to_local : NULL; + n++; + to_local = true; + } else + to_local = false; + + /* BOLT #3: + * + * 7. If the `to_remote` amount is greater or equal to + * `dust_limit_satoshis`, add a [`to_remote` + * output](#to_remote-output). + */ + if (amount_msat_greater_eq_sat(other_pay, dust_limit)) { + int pos = tx_add_to_node_output(tx, eltoo_keyset, other_pay, REMOTE); + assert(pos == n); + (*htlcmap)[n] = direct_outputs ? dummy_to_remote : NULL; + n++; + + to_remote = true; + } else { + to_remote = false; + } + + if (to_local || to_remote || num_untrimmed != 0) { + tx_add_ephemeral_anchor_output(tx); + (*htlcmap)[n] = NULL; + n++; + } + + /* BOLT #2: + * + * - MUST set `channel_reserve_satoshis` greater than or equal to + * `dust_limit_satoshis`. + */ + /* This means there must be at least one output. */ + assert(n > 0); + + assert(n <= tx->wtx->outputs_allocation_len); + tal_resize(htlcmap, n); + + /* BOLT #3: + * + * 9. Sort the outputs into [BIP 69+CLTV + * order](#transaction-input-and-output-ordering) + */ + permute_outputs(tx, cltvs, (const void **)*htlcmap); + + /* BOLT #3: + * + * ## Commitment Transaction + * + * * version: 2 + */ + assert(tx->wtx->version == 2); + + bitcoin_tx_set_locktime(tx, obscured_update_number); + + /* BOLT #3: + * + * * txin count: 1 + * * `txin[0]` outpoint: `txid` and `output_index` from + * `funding_created` message + */ + /* BOLT #3: + * + * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured settlement number + */ + add_settlement_input(tx, update_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); + + /* Identify the direct outputs (to_us, to_them). */ + if (direct_outputs != NULL) { + direct_outputs[LOCAL] = direct_outputs[REMOTE] = NULL; + for (size_t i = 0; i < tx->wtx->num_outputs; i++) { + if ((*htlcmap)[i] == dummy_to_local) { + (*htlcmap)[i] = NULL; + direct_outputs[LOCAL] = tx->wtx->outputs + i; + } else if ((*htlcmap)[i] == dummy_to_remote) { + (*htlcmap)[i] = NULL; + direct_outputs[REMOTE] = tx->wtx->outputs + i; + } + } + } + + bitcoin_tx_finalize(tx); + assert(bitcoin_tx_check(tx)); + + return tx; +} diff --git a/channeld/settle_tx.h b/channeld/settle_tx.h new file mode 100644 index 000000000000..864059a47ec9 --- /dev/null +++ b/channeld/settle_tx.h @@ -0,0 +1,67 @@ +#ifndef LIGHTNING_CHANNELD_COMMIT_TX_H +#define LIGHTNING_CHANNELD_COMMIT_TX_H +#include "config.h" +#include +#include + +struct keyset; + +/** + * settle_tx_num_untrimmed: how many of these htlc outputs will settle tx have? + * @htlcs: tal_arr of HTLCs + * @dust_limit: dust limit below which to trim outputs. + * + */ +size_t settle_tx_num_untrimmed(const struct htlc **htlcs, + struct amount_sat dust_limit); + +/** + * settle_tx_amount_trimmed: what's the sum of trimmed htlc amounts? + * @htlcs: tal_arr of HTLCs + * @dust_limit: dust limit below which to trim outputs. + * @amt: returned, total value trimmed from this settlement + * + * We need @side because HTLC fees are different for offered and + * received HTLCs. + * + * Returns false if unable to calculate amount trimmed. + */ +bool settle_tx_amount_trimmed(const struct htlc **htlcs, + struct amount_sat dust_limit, + struct amount_msat *amt); + +static void add_eltoo_htlc_out(struct bitcoin_tx *tx, + const struct htlc *htlc, + const struct eltoo_keyset *eltoo_keyset, + enum side receiver_side); + +/** + * settle_tx: create (unsigned) settlement tx to spend the funding tx output + * @ctx: context to allocate transaction and @htlc_map from. + * @update_outpoint, @update_outpoint_sats: funding outpoint and amount + * @shared_delay: delay before this settlement transaction can be included in a block + * @eltoo_keyset: keys derived for this settle tx. + * @dust_limit: dust limit below which to trim outputs. + * @self_pay: amount to pay directly to self + * @other_pay: amount to pay directly to the other side + * @htlcs: tal_arr of htlcs settleted by transaction (some may be trimmed) + * @htlc_map: outputed map of outnum->HTLC (NULL for direct outputs). + * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). + * @obscured_settlement_number: number to encode in settlement transaction + * + * This does not support liquidity ads (yet) + */ +struct bitcoin_tx *settle_tx(const tal_t *ctx, + const struct bitcoin_outpoint *update_outpoint, + struct amount_sat update_outpoint_sats, + u16 to_shared_delay, + const struct eltoo_keyset *eltoo_keyset, + struct amount_sat dust_limit, + struct amount_msat self_pay, + struct amount_msat other_pay, + const struct htlc **htlcs, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + u64 obscured_update_number); + +#endif /* LIGHTNING_CHANNELD_COMMIT_TX_H */ diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 811b159cd11f..2e225c71aa0e 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -6,8 +6,9 @@ static bool print_superverbose; #define SUPERVERBOSE(...) \ do { if (print_superverbose) printf(__VA_ARGS__); } while(0) #define PRINT_ACTUAL_FEE -#include "../commit_tx.c" +#include "../settle_tx.c" #include +#include #include #include #include @@ -127,6 +128,198 @@ static void tx_must_be_eq(const struct bitcoin_tx *a, tal_hex(tmpctx, linb)); } +/* BOLT #3: + * + * htlc 0 direction: remote->local + * htlc 0 amount_msat: 1000000 + * htlc 0 expiry: 500 + * htlc 0 payment_preimage: 0000000000000000000000000000000000000000000000000000000000000000 + * htlc 1 direction: remote->local + * htlc 1 amount_msat: 2000000 + * htlc 1 expiry: 501 + * htlc 1 payment_preimage: 0101010101010101010101010101010101010101010101010101010101010101 + * htlc 2 direction: local->remote + * htlc 2 amount_msat: 2000000 + * htlc 2 expiry: 502 + * htlc 2 payment_preimage: 0202020202020202020202020202020202020202020202020202020202020202 + * htlc 3 direction: local->remote + * htlc 3 amount_msat: 3000000 + * htlc 3 expiry: 503 + * htlc 3 payment_preimage: 0303030303030303030303030303030303030303030303030303030303030303 + * htlc 4 direction: remote->local + * htlc 4 amount_msat: 4000000 + * htlc 4 expiry: 504 + * htlc 4 payment_preimage: 0404040404040404040404040404040404040404040404040404040404040404 + */ +static const struct htlc **setup_htlcs_0_to_4(const tal_t *ctx) +{ + const struct htlc **htlcs = tal_arr(ctx, const struct htlc *, 5); + int i; + + for (i = 0; i < 5; i++) { + struct htlc *htlc = tal(htlcs, struct htlc); + + htlc->id = i; + switch (i) { + case 0: + htlc->state = RCVD_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(1000000); + break; + case 1: + htlc->state = RCVD_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(2000000); + break; + case 2: + htlc->state = SENT_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(2000000); + break; + case 3: + htlc->state = SENT_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(3000000); + break; + case 4: + htlc->state = RCVD_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(4000000); + break; + } + + htlc->expiry.locktime = 500 + i; + htlc->r = tal(htlc, struct preimage); + memset(htlc->r, i, sizeof(*htlc->r)); + sha256(&htlc->rhash, htlc->r, sizeof(*htlc->r)); + htlcs[i] = htlc; + } + return htlcs; +} + +/* BOLT #3: + * htlc 5 direction: local->remote + * htlc 5 amount_msat: 5000000 + * htlc 5 expiry: 506 + * htlc 5 payment_preimage: 0505050505050505050505050505050505050505050505050505050505050505 + * htlc 6 direction: local->remote + * htlc 6 amount_msat: 5000001 + * htlc 6 expiry: 505 + * htlc 6 payment_preimage: 0505050505050505050505050505050505050505050505050505050505050505 +*/ +static const struct htlc **setup_htlcs_1_5_and_6(const tal_t *ctx) +{ + const struct htlc **htlcs = tal_arr(ctx, const struct htlc *, 3); + int i; + const u64 htlc_ids[] = {1, 5, 6}; + + for (i = 0; i < 3; i++) { + struct htlc *htlc = tal(htlcs, struct htlc); + + htlc->r = tal(htlc, struct preimage); + htlc->id = htlc_ids[i]; + switch (htlc->id) { + case 1: + htlc->state = RCVD_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(2000000); + htlc->expiry.locktime = 501; + memset(htlc->r, 1, sizeof(*htlc->r)); + break; + case 5: + htlc->state = SENT_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(5000000); + htlc->expiry.locktime = 505; + memset(htlc->r, 5, sizeof(*htlc->r)); + break; + case 6: + htlc->state = SENT_ADD_ACK_REVOCATION; + htlc->amount = AMOUNT_MSAT(5000001); + htlc->expiry.locktime = 506; + memset(htlc->r, 5, sizeof(*htlc->r)); + break; + } + sha256(&htlc->rhash, htlc->r, sizeof(*htlc->r)); + htlcs[i] = htlc; + } + return htlcs; +} + + +static int test_settlement_tx(void) +{ + struct bitcoin_outpoint update_output; + struct amount_sat update_output_sats; + u32 shared_delay; + struct eltoo_keyset eltoo_keyset; + struct amount_sat dust_limit; + struct amount_msat self_pay; + struct amount_msat other_pay; + u32 obscured_update_number; + /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ + struct bitcoin_tx *tx, *tx_cmp; + struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; + int ok; + char *tx_hex; + char *psbt_b64; + const struct htlc **htlc_map; + + /* Test settlement tx with no HTLCs */ + const struct htlc **htlcs = tal_arr(tmpctx, const struct htlc *, 3); + + + update_output.txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); + update_output.n = 0; + update_output_sats.satoshis = 69420; + + alice_funding_privkey.secret = secret_from_hex("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901"); + bob_funding_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); + + ok = pubkey_from_privkey(&alice_funding_privkey, + &eltoo_keyset.self_funding_key); + ok = pubkey_from_privkey(&bob_funding_privkey, + &eltoo_keyset.other_funding_key); + + shared_delay = 42; + + alice_settle_privkey.secret = secret_from_hex("1111111111111111111111111111111111111111111111111111111111111111"); + bob_settle_privkey.secret = secret_from_hex("2222222222222222222222222222222222222222222222222222222222222222"); + + ok = pubkey_from_privkey(&alice_settle_privkey, + &eltoo_keyset.self_settle_key); + ok = pubkey_from_privkey(&bob_settle_privkey, + &eltoo_keyset.other_settle_key); + assert(ok); + + dust_limit.satoshis = 294; + self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; + other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; + obscured_update_number = 0; + + tx = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + /* htlcs */ NULL, + &htlc_map, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + + tx_hex = fmt_bitcoin_tx(tmpctx, tx); + printf("Settlement tx: %s\n", tx_hex); + psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); + printf("Settlement psbt: %s\n", psbt_b64); + + /* Regression test vector for now */ + tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); + tx_must_be_eq(tx, tx_cmp); + + /* Next we test with htlcs */ + htlcs = setup_htlcs_0_to_4(tmpctx); + htlcs = setup_htlcs_1_5_and_6(tmpctx); + assert(htlcs); + + return 0; +} + static int test_initial_settlement_tx(void) { struct bitcoin_outpoint update_output; @@ -272,6 +465,9 @@ int main(int argc, const char *argv[]) assert(!err); err |= test_htlc_output_creation(); + assert(!err); + + err |= test_settlement_tx(); common_shutdown(); From 9a7431b83da51be4199a7264c308f0c2b95baeec Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 15 Jul 2022 15:42:29 -0400 Subject: [PATCH 058/283] Add very basic update number test --- channeld/test/run-settle_tx.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 2e225c71aa0e..2c87a8d41b51 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -317,6 +317,26 @@ static int test_settlement_tx(void) htlcs = setup_htlcs_1_5_and_6(tmpctx); assert(htlcs); + assert(tx->wtx->locktime == obscured_update_number); + + obscured_update_number = 1234; + + tal_free(tx); + tx = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + /* htlcs */ NULL, + &htlc_map, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + + assert(tx->wtx->locktime == obscured_update_number); + return 0; } From c147c4e86b607b2da07d78c89af67a3d758d94a5 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 15 Jul 2022 16:05:26 -0400 Subject: [PATCH 059/283] some more settlement tx with htlc testing --- channeld/test/run-settle_tx.c | 102 ++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 5 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 2c87a8d41b51..b8ca2294138b 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -288,6 +288,7 @@ static int test_settlement_tx(void) dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; + assert(other_pay.millisatoshis < self_pay.millisatoshis); obscured_update_number = 0; tx = settle_tx(tmpctx, @@ -312,11 +313,6 @@ static int test_settlement_tx(void) tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); tx_must_be_eq(tx, tx_cmp); - /* Next we test with htlcs */ - htlcs = setup_htlcs_0_to_4(tmpctx); - htlcs = setup_htlcs_1_5_and_6(tmpctx); - assert(htlcs); - assert(tx->wtx->locktime == obscured_update_number); obscured_update_number = 1234; @@ -336,6 +332,102 @@ static int test_settlement_tx(void) obscured_update_number); assert(tx->wtx->locktime == obscured_update_number); + assert(tx->wtx->num_outputs == 3); + + /* Just above trimming level */ + dust_limit.satoshis = (other_pay.millisatoshis/1000); + tal_free(tx); + tx = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + /* htlcs */ NULL, + &htlc_map, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + + assert(tx->wtx->num_outputs == 3); + + /* Smallest should be trimmed */ + dust_limit.satoshis = (other_pay.millisatoshis/1000) + 1; + tal_free(tx); + tx = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + /* htlcs */ NULL, + &htlc_map, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + assert(tx->wtx->num_outputs == 2); + + /* Next we test with htlcs */ + dust_limit.satoshis = 0; + htlcs = setup_htlcs_0_to_4(tmpctx); + + tal_free(tx); + tx = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + htlcs, + &htlc_map, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + + assert(tx->wtx->num_outputs == 3 + tal_count(htlcs)); + + /* All outputs survive */ + dust_limit.satoshis = htlcs[0]->amount.millisatoshis/1000; + tal_free(tx); + tx = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + htlcs, + &htlc_map, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + + assert(tx->wtx->num_outputs == 3 + tal_count(htlcs)); + + /* Smallest HTLC trimmed */ + dust_limit.satoshis = (htlcs[0]->amount.millisatoshis/1000)+1; + tal_free(tx); + tx = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + htlcs, + &htlc_map, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + + assert(tx->wtx->num_outputs == 3 + tal_count(htlcs) - 1); + + /* Do some more interesting testing */ + htlcs = setup_htlcs_1_5_and_6(tmpctx); + assert(htlcs); return 0; } From 25d126b7460f24d8a5a4893571673b67df6ab26c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 15 Jul 2022 16:39:17 -0400 Subject: [PATCH 060/283] Set proper nlocktime, redefine obscured update number --- channeld/settle_tx.c | 2 +- channeld/settle_tx.h | 2 +- channeld/test/run-settle_tx.c | 6 +++--- common/initial_settlement_tx.c | 2 +- common/initial_settlement_tx.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index b07cb4138d76..92b9d0ef5da3 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -233,7 +233,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, */ assert(tx->wtx->version == 2); - bitcoin_tx_set_locktime(tx, obscured_update_number); + bitcoin_tx_set_locktime(tx, obscured_update_number + 500000000); /* BOLT #3: * diff --git a/channeld/settle_tx.h b/channeld/settle_tx.h index 864059a47ec9..8a6a767fa5c5 100644 --- a/channeld/settle_tx.h +++ b/channeld/settle_tx.h @@ -47,7 +47,7 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, * @htlcs: tal_arr of htlcs settleted by transaction (some may be trimmed) * @htlc_map: outputed map of outnum->HTLC (NULL for direct outputs). * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). - * @obscured_settlement_number: number to encode in settlement transaction + * @obscured_settlement_number: number to encode in settlement transaction for update number * * This does not support liquidity ads (yet) */ diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index b8ca2294138b..766e341a3304 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -56,7 +56,7 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541d7a72a6c1aac9118078c1855278391dea91c9380a125e71416be15e0573b7eceef11cbdaf40d01c84639e4d1766fa3faa1eb9f4049abe764dc75e62e0b5075e5c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a46eb09cb3c07a74993a0c294cfa0b87d5aa9d979f8c4b0e02be2fa561b416d33300000000"; +char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a46eb09cb3c07a74993a0c294cfa0b87d5aa9d979f8c4b0e02be2fa561b416d3330065cd1d"; static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { @@ -313,7 +313,7 @@ static int test_settlement_tx(void) tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); tx_must_be_eq(tx, tx_cmp); - assert(tx->wtx->locktime == obscured_update_number); + assert(tx->wtx->locktime == obscured_update_number + 500000000); obscured_update_number = 1234; @@ -331,7 +331,7 @@ static int test_settlement_tx(void) /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, obscured_update_number); - assert(tx->wtx->locktime == obscured_update_number); + assert(tx->wtx->locktime == obscured_update_number + 500000000); assert(tx->wtx->num_outputs == 3); /* Just above trimming level */ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 93aa36a6504c..7b31d2f0f2fd 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -280,7 +280,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * lower 24 bits of the obscured commitment number */ bitcoin_tx_set_locktime(tx, - obscured_update_number); + obscured_update_number + 500000000); /* BOLT #???: * diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index bae939f8a814..3a78cebf0e8a 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -23,7 +23,7 @@ struct wally_tx_output; * @self_pay: amount to pay directly to self * @other_pay: amount to pay directly to the other side * @self_reserve: reserve the other side insisted we have - * @obscured_update_number: number to encode in update transaction as nlocktime + * @obscured_update_number: obscured update number "o+k" * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). * @err_reason: When NULL is returned, this will point to a human readable reason. * From 9c4b35bee5b2fa8f41538f7ba9ee2b73dd4ace20 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 18 Jul 2022 11:41:19 -0400 Subject: [PATCH 061/283] fixup eltoo update script constant to become time --- bitcoin/script.c | 19 ++++++++++++++++--- bitcoin/script.h | 3 +++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 088fadbc0bb9..a04fd5151b9f 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1114,16 +1114,29 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size } u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num) +{ + /* TL(n) = `500000000+o+n` + * where EXPR_UPDATE(n) = + * + *`<1> OP_CHECKSIGVERIFY OP_CHECKLOCKTIMEVERIFY` if `n > 0` + */ + u8 *script = tal_arr(ctx, u8, 0); + add_op(&script, OP_1); + add_op(&script, OP_CHECKSIGVERIFY); + add_number(&script, 500000000 + update_num); + add_op(&script, OP_CHECKSEQUENCEVERIFY); + return script; +} + +u8 *make_eltoo_funding_update_script(const tal_t *ctx) { /* where EXPR_UPDATE(n) = * - *`OP_1 OP_CHECKSIGVERIFY OP_CLTV` + *`<1> OP_CHECKSIGVERIFY`, in the case of `n == 0` */ u8 *script = tal_arr(ctx, u8, 0); add_op(&script, OP_1); add_op(&script, OP_CHECKSIGVERIFY); - add_number(&script, update_num); - add_op(&script, OP_CHECKSEQUENCEVERIFY); return script; } diff --git a/bitcoin/script.h b/bitcoin/script.h index 0d6667120519..1bca8e6e7783 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -194,6 +194,9 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size /* Creates the update path tapscript for eltoo, which commits to the masked update number */ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); +/* Creates the update path tapscript for the special case of a funding output being spent, which is ~4 WU smaller */ +u8 *make_eltoo_funding_update_script(const tal_t *ctx); + /* Creates eltoo HTLC success script, with invoice hash lock */ u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const u8 *invoice_hash); From 9e8a400a621861b961bc91ee5912d4be2fb057d8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 18 Jul 2022 11:42:41 -0400 Subject: [PATCH 062/283] f --- bitcoin/script.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bitcoin/script.h b/bitcoin/script.h index 1bca8e6e7783..58c7b1673b0c 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -194,7 +194,9 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size /* Creates the update path tapscript for eltoo, which commits to the masked update number */ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); -/* Creates the update path tapscript for the special case of a funding output being spent, which is ~4 WU smaller */ +/* Creates the update path tapscript for the special case of a funding output being spent, which is ~4 WU smaller for + * the average non-adversarial unilateral close + */ u8 *make_eltoo_funding_update_script(const tal_t *ctx); /* Creates eltoo HTLC success script, with invoice hash lock */ From f9b7efc57094f12d58490861c49f44b92e7c2e08 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 18 Jul 2022 13:47:27 -0400 Subject: [PATCH 063/283] Update script in settlement input is one larger than settlement locktime --- common/initial_settlement_tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 7b31d2f0f2fd..9634e8f27e5a 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -80,7 +80,10 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * /* Now the the transaction itself is determined, we must compute the APO sighash to inject it into the inputs' tapscript, then attach the information to the PSBT */ settle_and_update_tapscripts[0] = make_eltoo_settle_script(tmpctx, tx, input_num); - settle_and_update_tapscripts[1] = make_eltoo_update_script(tmpctx, obscured_update_number); + printf("SETTLE: %s\n", tal_hexstr(tmpctx, settle_and_update_tapscripts[0], tal_count(settle_and_update_tapscripts[0]))); + /* update number is one more for the update path, which isn't being taken */ + settle_and_update_tapscripts[1] = make_eltoo_update_script(tmpctx, obscured_update_number + 1); + printf("UPDATE: %s\n", tal_hexstr(tmpctx, settle_and_update_tapscripts[1], tal_count(settle_and_update_tapscripts[1]))); assert(settle_and_update_tapscripts[0]); assert(settle_and_update_tapscripts[1]); From ba076f2ac3d4b5b934597ceddfc10bfbb49a4375 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 18 Jul 2022 13:52:35 -0400 Subject: [PATCH 064/283] Update settlement hex --- channeld/test/run-settle_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 766e341a3304..a103517e5154 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -56,7 +56,7 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a46eb09cb3c07a74993a0c294cfa0b87d5aa9d979f8c4b0e02be2fa561b416d3330065cd1d"; +char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4a2229690aa611abee255baf9c628da8e0fab458573e5745585718ed0e0b4f3740065cd1d"; static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { From 67aeb34c8c9ae22ad0d1a04785aa269669e082ab Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 18 Jul 2022 15:00:21 -0400 Subject: [PATCH 065/283] Add initial update tx creation code --- channeld/Makefile | 1 + channeld/test/Makefile | 1 + channeld/test/run-settle_tx.c | 13 +++- common/Makefile | 1 + common/initial_update_tx.c | 111 ++++++++++++++++++++++++++++++++++ common/initial_update_tx.h | 40 ++++++++++++ 6 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 common/initial_update_tx.c create mode 100644 common/initial_update_tx.h diff --git a/channeld/Makefile b/channeld/Makefile index ccaf8bb97c45..3d9f9e853235 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -63,6 +63,7 @@ CHANNELD_COMMON_OBJS := \ common/initial_channel.o \ common/initial_commit_tx.o \ common/initial_settlement_tx.o \ + common/initial_update_tx.o \ common/keyset.o \ common/key_derive.o \ common/memleak.o \ diff --git a/channeld/test/Makefile b/channeld/test/Makefile index bf24a656c845..3dc23747e14e 100644 --- a/channeld/test/Makefile +++ b/channeld/test/Makefile @@ -18,6 +18,7 @@ CHANNELD_TEST_COMMON_OBJS := \ common/htlc_tx.o \ common/initial_commit_tx.o \ common/initial_settlement_tx.o \ + common/initial_update_tx.o \ common/key_derive.o \ common/msg_queue.o \ common/permute_tx.o \ diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index a103517e5154..7f3efc5cc015 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -18,6 +18,7 @@ static bool print_superverbose; #include #include #include +#include /* Turn this on to brute-force fee values */ /*#define DEBUG */ @@ -445,7 +446,7 @@ static int test_initial_settlement_tx(void) u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ char* err_reason; - struct bitcoin_tx *tx, *tx_cmp; + struct bitcoin_tx *tx, *tx_cmp, *update_tx; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; char *tx_hex; @@ -504,6 +505,16 @@ static int test_initial_settlement_tx(void) tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); tx_must_be_eq(tx, tx_cmp); + /* We rebind the outpoint later anyways, so just reuse the outpoint */ + update_tx = initial_update_tx(tmpctx, + tx, + &update_output, + update_output_sats, + &eltoo_keyset, + &err_reason); + + psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); + printf("Update psbt: %s\n", psbt_b64); return 0; } diff --git a/common/Makefile b/common/Makefile index ec5503fe457d..8cbb1f345e09 100644 --- a/common/Makefile +++ b/common/Makefile @@ -47,6 +47,7 @@ COMMON_SRC_NOGEN := \ common/initial_channel.c \ common/initial_commit_tx.c \ common/initial_settlement_tx.c \ + common/initial_update_tx.c \ common/iso4217.c \ common/json.c \ common/json_helpers.c \ diff --git a/common/initial_update_tx.c b/common/initial_update_tx.c new file mode 100644 index 000000000000..94588fc5a13e --- /dev/null +++ b/common/initial_update_tx.c @@ -0,0 +1,111 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + +struct wally_psbt; + +int tx_add_settlement_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx) +{ + struct amount_sat amount; + amount.satoshis = settle_tx->psbt->inputs[0].witness_utxo->satoshi; + return bitcoin_tx_add_output( + update_tx, settle_tx->psbt->inputs[0].witness_utxo->script, /* wscript */ NULL, amount /* FIXME pass in psbt fields for tap outputs */); +} + +u8 *make_eltoo_annex(const tal_t *ctx, u8 *settle_tapscript) +{ + int ok; + struct sha256 result; + /* Enough space for annex flag plus the one hash we want published */ + u8 *annex = tal_arr(ctx, u8, 1 + sizeof(result)); + + ok = wally_tagged_hash(settle_tapscript, tal_count(settle_tapscript), "TapLeaf", result.u.u8); + assert(ok == WALLY_OK); + + annex[0] = 0x50; /* annex flag */ + memcpy(annex + 1, result.u.u8, sizeof(result)); + return annex; +} + +void tx_add_funding_input(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, struct amount_sat funding_outpoint_sats, const struct eltoo_keyset *eltoo_keyset) +{ + int input_num; + const struct pubkey *pubkey_ptrs[2]; + u8 *update_tapscript[1]; + /* For committing to the output's settle path tapleaf hash inside the annex itself */ + u8 *output_settle_tapscript; + u8 *script_pubkey; + struct sha256 update_merkle_root; + struct pubkey update_agg_pk; + secp256k1_musig_keyagg_cache update_keyagg_cache; + unsigned char update_tap_tweak[32]; + u8 **witness; + + /* For MuSig aggregation for outputs */ + pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); + pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); + + update_tapscript[0] = make_eltoo_funding_update_script(tmpctx); + + compute_taptree_merkle_root(&update_merkle_root, update_tapscript, /* num_scripts */ 1); + bipmusig_finalize_keys(&update_agg_pk, + &update_keyagg_cache, + pubkey_ptrs, + /* n_pubkeys */ 2, + &update_merkle_root, + update_tap_tweak); + + script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); + + input_num = bitcoin_tx_add_input(update_tx, funding_outpoint, /* sequence */ 0xFFFFFFFD, + /* scriptSig */ NULL, funding_outpoint_sats, script_pubkey, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); + assert(input_num == 0); + + /* Annex commitment of *settlement script* for corresponding output set here as well (annex field for PSBT doesn't exist?) */ + output_settle_tapscript = make_eltoo_settle_script(tmpctx, settle_tx, input_num); + witness = tal_arr(tmpctx, u8 *, 1); + witness[0] = make_eltoo_annex(tmpctx, output_settle_tapscript); + bitcoin_tx_input_set_witness(update_tx, input_num, witness); +} + +struct bitcoin_tx *initial_update_tx(const tal_t *ctx, + const struct bitcoin_tx *settle_tx, + const struct bitcoin_outpoint *funding_outpoint, + struct amount_sat funding_outpoint_sats, + const struct eltoo_keyset *eltoo_keyset, + char** err_reason) +{ + struct bitcoin_tx *update_tx; + int pos; + + /* 1 input 1 output tx */ + update_tx = bitcoin_tx(ctx, chainparams, 1, 1, 0); + + /* Add output */ + pos = tx_add_settlement_output(update_tx, settle_tx); + assert(pos == 0); + + /* Add unsigned funding input (but includes annex commitment!) */ + tx_add_funding_input(update_tx, settle_tx, funding_outpoint, funding_outpoint_sats, eltoo_keyset); + + /* Set global fields */ + assert(update_tx->wtx->version == 2); + bitcoin_tx_set_locktime(update_tx, + settle_tx->wtx->locktime); + + bitcoin_tx_finalize(update_tx); + + return update_tx; +} diff --git a/common/initial_update_tx.h b/common/initial_update_tx.h new file mode 100644 index 000000000000..e1da3a1500c1 --- /dev/null +++ b/common/initial_update_tx.h @@ -0,0 +1,40 @@ +/* Commit tx without HTLC support; needed for openingd. */ +#ifndef LIGHTNING_COMMON_INITIAL_UPDATE_TX_H +#define LIGHTNING_COMMON_INITIAL_UPDATE_TX_H +#include "config.h" +#include +#include +#include +#include +#include +#include + +struct bitcoin_outpoint; + +int tx_add_settlement_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx); + +u8 *make_eltoo_annex(const tal_t *ctx, u8 *settle_tapscript); + +void tx_add_funding_input(struct bitcoin_tx *update_tx, + const struct bitcoin_tx *settle_tx, + const struct bitcoin_outpoint *funding_outpoint, + struct amount_sat funding_outpoint_sats, + const struct eltoo_keyset *eltoo_keyset); + +/** + * initial_update_tx: create (unsigned) update tx to spend the funding output + * @ctx: context to allocate transaction and @htlc_map from. + * @settlement_tx: initial settlement tx created via `initial_settlement_tx` + * @funding_outpoint, @funding_outpoint_sats: funding outpoint and amount + * @eltoo_keyset: set of keys for deriving inner public key + * @err_reason: When NULL is returned, this will point to a human readable reason. + * + */ +struct bitcoin_tx *initial_update_tx(const tal_t *ctx, + const struct bitcoin_tx *settle_tx, + const struct bitcoin_outpoint *funding_outpoint, + struct amount_sat funding_outpoint_sats, + const struct eltoo_keyset *eltoo_keyset, + char** err_reason); + +#endif /* LIGHTNING_COMMON_INITIAL_UPDATE_TX_H */ From 3195f2576faa4f3ba8a68cd0a8cc5a2a524c2b09 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 18 Jul 2022 15:43:28 -0400 Subject: [PATCH 066/283] Fix annex creation --- bitcoin/script.c | 4 ++++ common/initial_update_tx.c | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index a04fd5151b9f..e59d0d9e3deb 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -983,6 +983,8 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n /* k0 == km, this is the merkle root so we directly write it out */ ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", hash_out->u.u8); assert(ok == WALLY_OK); + printf("SCRIPT(1 branch): %s\n", tal_hexstr(tmpctx, scripts[0], tal_count(scripts[0]))); + printf("***TAPLEAF PREIMAGE***: %s\n", tal_hexstr(tmpctx, tag_hash_buf, p - tag_hash_buf)); printf("TAPLEAF HASH(1 branch): %s\n", tal_hexstr(tmpctx, hash_out->u.u8, 32)); } else if (num_scripts == 2) { int i; @@ -998,6 +1000,8 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", tap_hashes + (i*32)); assert(ok == WALLY_OK); + printf("SCRIPT(2 branches): %s\n", tal_hexstr(tmpctx, scripts[i], tal_count(scripts[i]))); + printf("***TAPLEAF PREIMAGE***: %s\n", tal_hexstr(tmpctx, tag_hash_buf, p - tag_hash_buf)); printf("TAPLEAF HASHES: %s\n", tal_hexstr(tmpctx, tap_hashes + (i*32), 32)); } /* If kj ≥ ej: kj+1 = hashTapBranch(ej || kj), swap them*/ diff --git a/common/initial_update_tx.c b/common/initial_update_tx.c index 94588fc5a13e..9182ce58757d 100644 --- a/common/initial_update_tx.c +++ b/common/initial_update_tx.c @@ -28,11 +28,24 @@ u8 *make_eltoo_annex(const tal_t *ctx, u8 *settle_tapscript) { int ok; struct sha256 result; + u8 *preimage_cursor; + u64 tapscript_len = tal_count(settle_tapscript); + u8 *tapleaf_preimage = tal_arr(ctx, u8, 1 + varint_size(tapscript_len) + tapscript_len); /* Enough space for annex flag plus the one hash we want published */ - u8 *annex = tal_arr(ctx, u8, 1 + sizeof(result)); - - ok = wally_tagged_hash(settle_tapscript, tal_count(settle_tapscript), "TapLeaf", result.u.u8); + u8 *annex = tal_arr(ctx, u8, 1 + sizeof(result.u.u8)); + + preimage_cursor = tapleaf_preimage; + preimage_cursor[0] = 0xC0; + preimage_cursor++; + preimage_cursor += varint_put(preimage_cursor, tapscript_len); + memcpy(preimage_cursor, settle_tapscript, tapscript_len); + preimage_cursor += tapscript_len; + + assert(tal_count(tapleaf_preimage) == preimage_cursor - tapleaf_preimage); + printf("***ANNEX PREIMAGE***: %s\n", tal_hexstr(tmpctx, tapleaf_preimage, tal_count(tapleaf_preimage))); + ok = wally_tagged_hash(tapleaf_preimage, tal_count(tapleaf_preimage), "TapLeaf", result.u.u8); assert(ok == WALLY_OK); + printf("TAPLEAF HASH(annex): %s\n", tal_hexstr(tmpctx, result.u.u8, 32)); annex[0] = 0x50; /* annex flag */ memcpy(annex + 1, result.u.u8, sizeof(result)); From 7992f64468ed0ec8fe2e1242d61507c055e06f09 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 19 Jul 2022 13:23:27 -0400 Subject: [PATCH 067/283] updating libwally --- bitcoin/signature.c | 2 +- external/libwally-core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 08357d701a73..cb20c247d835 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -376,7 +376,7 @@ void bitcoin_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, ret = wally_tx_get_btc_taproot_signature_hash( tx->wtx, sighash_type, input_index, input_spks, input_spk_lens, input_val_sats, tapleaf_script, tal_bytelen(tapleaf_script), (sighash_type & SIGHASH_ANYPREVOUTANYSCRIPT) == SIGHASH_ANYPREVOUTANYSCRIPT ? 0x01 : 0x00 /* key_version */, - 0xFFFFFFFF /* codesep_position */, 0 /* flags */, dest->sha.u.u8, + 0xFFFFFFFF /* codesep_position */, NULL /* annex */, 0 /* annex_len */, 0 /* flags */, dest->sha.u.u8, sizeof(*dest)); assert(ret == WALLY_OK); diff --git a/external/libwally-core b/external/libwally-core index 1f2cb9f89180..c1b04b273664 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit 1f2cb9f89180f1aac6f873d5e72cc4e68608c138 +Subproject commit c1b04b27366459020af19f218b7d283d05d05956 From ff02df6921ab2d72dc6f70215626f094110661d5 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 19 Jul 2022 13:38:01 -0400 Subject: [PATCH 068/283] Thread annex through to sign_tx_taproot_input --- bitcoin/script.c | 1 + bitcoin/signature.c | 7 ++++--- bitcoin/signature.h | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index e59d0d9e3deb..a97e01ab2127 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1078,6 +1078,7 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size input_index, sh_type, script, + /* annex */ NULL, &sighash); printf("SIGHASH: %s\n", tal_hexstr(tmpctx, sighash.sha.u.u32, 32));//\n", sighash.sha.u.u32); diff --git a/bitcoin/signature.c b/bitcoin/signature.c index cb20c247d835..25d59734f7d8 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -355,6 +355,7 @@ void bitcoin_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, unsigned int input_index, enum sighash_type sighash_type, /* FIXME get from PSBT? */ const unsigned char *tapleaf_script, /* FIXME Get directly from PSBT? */ + u8 *annex, struct sha256_double *dest) { int ret, i; @@ -376,7 +377,7 @@ void bitcoin_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, ret = wally_tx_get_btc_taproot_signature_hash( tx->wtx, sighash_type, input_index, input_spks, input_spk_lens, input_val_sats, tapleaf_script, tal_bytelen(tapleaf_script), (sighash_type & SIGHASH_ANYPREVOUTANYSCRIPT) == SIGHASH_ANYPREVOUTANYSCRIPT ? 0x01 : 0x00 /* key_version */, - 0xFFFFFFFF /* codesep_position */, NULL /* annex */, 0 /* annex_len */, 0 /* flags */, dest->sha.u.u8, + 0xFFFFFFFF /* codesep_position */, annex, tal_count(annex), 0 /* flags */, dest->sha.u.u8, sizeof(*dest)); assert(ret == WALLY_OK); @@ -419,7 +420,7 @@ void sign_tx_taproot_input(const struct bitcoin_tx *tx, struct privkey privkey; /* FIXME assert sighashes we actually support assert(sighash_type_valid(sighash_type)); */ - bitcoin_tx_taproot_hash_for_sig(tx, input_index, sighash_type, tapleaf_script, &hash); + bitcoin_tx_taproot_hash_for_sig(tx, input_index, sighash_type, tapleaf_script, NULL /* annex */, &hash); /* TODO just have it take keypair? */ ret = secp256k1_keypair_xonly_pub(secp256k1_ctx, &pubkey, NULL /* pk_parity */, key_pair); @@ -505,7 +506,7 @@ bool check_tx_taproot_sig(const struct bitcoin_tx *tx, size_t input_num, } assert(input_num < tx->wtx->num_inputs); - bitcoin_tx_taproot_hash_for_sig(tx, input_num, sighash_type, tapleaf_script, &hash); + bitcoin_tx_taproot_hash_for_sig(tx, input_num, sighash_type, tapleaf_script, /* annex */ NULL, &hash); dump_tx("check_tx_sig", tx, input_num, tapleaf_script, NULL /* key */, x_key, &hash); diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 2eecd1e83384..08057e06df3b 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -78,12 +78,14 @@ void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, * @input_index - index that this 'hash' is for * @sighash_type - sighash_type to hash for * @tapleaf_script - tapscript leaf for the index that's being 'hashed for', NULL if keyspend + * @annex - annex to commit to, NULL if none * @dest - hash result */ void bitcoin_tx_taproot_hash_for_sig(const struct bitcoin_tx *tx, unsigned int input_index, enum sighash_type sighash_type, const unsigned char *tapleaf_script, + u8 *annex, struct sha256_double *dest); /** From d54d35c1f037a2d9f51d49fc562b872612d5c2ea Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 19 Jul 2022 14:06:58 -0400 Subject: [PATCH 069/283] Don't crudely embed annex witness data in PSBT --- common/initial_update_tx.c | 12 +++--------- common/initial_update_tx.h | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/common/initial_update_tx.c b/common/initial_update_tx.c index 9182ce58757d..29d3a93ecf29 100644 --- a/common/initial_update_tx.c +++ b/common/initial_update_tx.c @@ -24,11 +24,12 @@ int tx_add_settlement_output(struct bitcoin_tx *update_tx, const struct bitcoin_ update_tx, settle_tx->psbt->inputs[0].witness_utxo->script, /* wscript */ NULL, amount /* FIXME pass in psbt fields for tap outputs */); } -u8 *make_eltoo_annex(const tal_t *ctx, u8 *settle_tapscript) +u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) { int ok; struct sha256 result; u8 *preimage_cursor; + u8 *settle_tapscript = make_eltoo_settle_script(tmpctx, settle_tx, /* input_num */ 0); u64 tapscript_len = tal_count(settle_tapscript); u8 *tapleaf_preimage = tal_arr(ctx, u8, 1 + varint_size(tapscript_len) + tapscript_len); /* Enough space for annex flag plus the one hash we want published */ @@ -58,13 +59,11 @@ void tx_add_funding_input(struct bitcoin_tx *update_tx, const struct bitcoin_tx const struct pubkey *pubkey_ptrs[2]; u8 *update_tapscript[1]; /* For committing to the output's settle path tapleaf hash inside the annex itself */ - u8 *output_settle_tapscript; u8 *script_pubkey; struct sha256 update_merkle_root; struct pubkey update_agg_pk; secp256k1_musig_keyagg_cache update_keyagg_cache; unsigned char update_tap_tweak[32]; - u8 **witness; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); @@ -85,14 +84,9 @@ void tx_add_funding_input(struct bitcoin_tx *update_tx, const struct bitcoin_tx input_num = bitcoin_tx_add_input(update_tx, funding_outpoint, /* sequence */ 0xFFFFFFFD, /* scriptSig */ NULL, funding_outpoint_sats, script_pubkey, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); assert(input_num == 0); - - /* Annex commitment of *settlement script* for corresponding output set here as well (annex field for PSBT doesn't exist?) */ - output_settle_tapscript = make_eltoo_settle_script(tmpctx, settle_tx, input_num); - witness = tal_arr(tmpctx, u8 *, 1); - witness[0] = make_eltoo_annex(tmpctx, output_settle_tapscript); - bitcoin_tx_input_set_witness(update_tx, input_num, witness); } + struct bitcoin_tx *initial_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, diff --git a/common/initial_update_tx.h b/common/initial_update_tx.h index e1da3a1500c1..d40c79df9a9c 100644 --- a/common/initial_update_tx.h +++ b/common/initial_update_tx.h @@ -13,7 +13,7 @@ struct bitcoin_outpoint; int tx_add_settlement_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx); -u8 *make_eltoo_annex(const tal_t *ctx, u8 *settle_tapscript); +u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx); void tx_add_funding_input(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx, From 9a9dd491a00461edfaeb1973b895658ff23fed2c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 20 Jul 2022 10:58:34 -0400 Subject: [PATCH 070/283] Complete MuSig signing example in update tx test --- channeld/test/run-settle_tx.c | 77 +++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 7f3efc5cc015..c813bf3e6c08 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -452,6 +452,27 @@ static int test_initial_settlement_tx(void) char *tx_hex; char *psbt_b64; + /* Aggregation stuff */ + struct pubkey taproot_pubkey; + secp256k1_musig_keyagg_cache keyagg_cache[2]; + const struct pubkey *pubkey_ptrs[2]; + const struct sha256 tap_merkle_root; + unsigned char tap_tweak_out[32]; + int i; + secp256k1_xonly_pubkey xonly_pubkey; + + /* MuSig signing stuff */ + secp256k1_musig_secnonce secnonce[2]; + const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; + secp256k1_musig_pubnonce pubnonces[2]; + struct sha256_double msg_out; + const secp256k1_musig_partial_sig *p_sig_ptrs[2]; + secp256k1_musig_partial_sig p_sigs[2]; + u8 *tapleaf_script; + struct bip340sig sig; + u8 *annex; + secp256k1_musig_session session[2]; + /* Test initial settlement tx */ update_output.txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); @@ -477,6 +498,9 @@ static int test_initial_settlement_tx(void) &eltoo_keyset.other_settle_key); assert(ok); + pubkey_ptrs[0] = &eltoo_keyset.self_funding_key; + pubkey_ptrs[1] = &eltoo_keyset.other_funding_key; + dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; @@ -516,6 +540,59 @@ static int test_initial_settlement_tx(void) psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); printf("Update psbt: %s\n", psbt_b64); + /* Generate signing session for "both sides" */ + for (i=0; i<2; ++i){ + bipmusig_finalize_keys(&taproot_pubkey, + &keyagg_cache[i], + pubkey_ptrs, + /* n_pubkeys */ 2, + &tap_merkle_root, + tap_tweak_out); + + /* FIXME we should just accept compressed pubkey whole way */ + ok = secp256k1_xonly_pubkey_from_pubkey( + secp256k1_ctx, + &xonly_pubkey, + /* pk_parity */ NULL, + &(taproot_pubkey.pubkey)); + assert(ok); + + /* "Presharing" nonces here */ + bipmusig_gen_nonce(&secnonce[i], + &pubnonces[i], + (i == 0) ? &alice_funding_privkey : &bob_funding_privkey, + &keyagg_cache[i], + /* msg32 */ NULL); + pubnonce_ptrs[i] = &pubnonces[i]; + } + + /* This should be stored in bitcoin_tx->psbt... */ + tapleaf_script = make_eltoo_funding_update_script(tmpctx); + annex = make_eltoo_annex(tmpctx, tx); + for (i=0; i<2; ++i){ + bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, tapleaf_script, annex, &msg_out); + bipmusig_partial_sign((i == 0) ? &alice_funding_privkey : &bob_funding_privkey, + &secnonce[i], + pubnonce_ptrs, + 2, + msg_out.sha.u.u8, /* FIXME harmonize this to sha256_double */ + &keyagg_cache[i], + &session[i], + &p_sigs[i]); + p_sig_ptrs[i] = &p_sigs[i]; + } + + /* Finally, combine sig */ + for (i=0; i<2; ++i){ + ok = bipmusig_partial_sigs_combine_verify(p_sig_ptrs, + 2, + &xonly_pubkey, + &session[i], + &msg_out, + &sig); + assert(ok); + } + return 0; } From 37b576655d56b008e9a8540a534cdbe64a4475c3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 20 Jul 2022 12:38:27 -0400 Subject: [PATCH 071/283] Maybe signed update tx in test --- channeld/test/run-settle_tx.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index c813bf3e6c08..caff655ce81b 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -458,10 +458,11 @@ static int test_initial_settlement_tx(void) const struct pubkey *pubkey_ptrs[2]; const struct sha256 tap_merkle_root; unsigned char tap_tweak_out[32]; - int i; + int i, pk_parity; secp256k1_xonly_pubkey xonly_pubkey; /* MuSig signing stuff */ + secp256k1_xonly_pubkey inner_pubkey; secp256k1_musig_secnonce secnonce[2]; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; secp256k1_musig_pubnonce pubnonces[2]; @@ -470,8 +471,10 @@ static int test_initial_settlement_tx(void) secp256k1_musig_partial_sig p_sigs[2]; u8 *tapleaf_script; struct bip340sig sig; - u8 *annex; secp256k1_musig_session session[2]; + u8 *annex; + u8 **update_witness; + u8 *final_sig; /* Test initial settlement tx */ @@ -501,6 +504,11 @@ static int test_initial_settlement_tx(void) pubkey_ptrs[0] = &eltoo_keyset.self_funding_key; pubkey_ptrs[1] = &eltoo_keyset.other_funding_key; + /* Calculate inner pubkey */ + bipmusig_inner_pubkey(&inner_pubkey, + pubkey_ptrs, + /* n_pubkeys */ 1); + dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; @@ -523,7 +531,7 @@ static int test_initial_settlement_tx(void) tx_hex = fmt_bitcoin_tx(tmpctx, tx); printf("Settlement tx: %s\n", tx_hex); psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); - printf("Settlement psbt: %s\n", psbt_b64); + printf("Initial Settlement psbt: %s\n", psbt_b64); /* Regression test vector for now */ tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); @@ -553,7 +561,7 @@ static int test_initial_settlement_tx(void) ok = secp256k1_xonly_pubkey_from_pubkey( secp256k1_ctx, &xonly_pubkey, - /* pk_parity */ NULL, + &pk_parity, &(taproot_pubkey.pubkey)); assert(ok); @@ -568,6 +576,7 @@ static int test_initial_settlement_tx(void) /* This should be stored in bitcoin_tx->psbt... */ tapleaf_script = make_eltoo_funding_update_script(tmpctx); + annex = make_eltoo_annex(tmpctx, tx); for (i=0; i<2; ++i){ bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, tapleaf_script, annex, &msg_out); @@ -593,6 +602,21 @@ static int test_initial_settlement_tx(void) assert(ok); } + final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); + memcpy(final_sig, sig.u8, sizeof(sig.u8)); + final_sig[sizeof(final_sig) - 1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; + + /* Witness stack, bottom to top: MuSig2 sig + tapscript + control block + Annex data */ + update_witness = tal_arr(tmpctx, u8 *, 4); + update_witness[0] = final_sig; + update_witness[1] = make_eltoo_funding_update_script(tmpctx); + update_witness[2] = compute_control_block(tmpctx, update_witness[1], &inner_pubkey, pk_parity); + update_witness[3] = annex; + bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); + + psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); + printf("Initial update psbt with finalized witness for input: %s\n", psbt_b64); + return 0; } From d0a375b5fd1a425480402b8fa207b74f71ebbfe7 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 21 Jul 2022 09:50:00 -0400 Subject: [PATCH 072/283] Funding output only has one script --- channeld/test/run-settle_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index caff655ce81b..66028d6b4e22 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -610,7 +610,7 @@ static int test_initial_settlement_tx(void) update_witness = tal_arr(tmpctx, u8 *, 4); update_witness[0] = final_sig; update_witness[1] = make_eltoo_funding_update_script(tmpctx); - update_witness[2] = compute_control_block(tmpctx, update_witness[1], &inner_pubkey, pk_parity); + update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, &inner_pubkey, pk_parity); update_witness[3] = annex; bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); From 79fb637eabab132f4267475cd895d0a45dc46949 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 21 Jul 2022 10:10:30 -0400 Subject: [PATCH 073/283] actually populate the tap merkle root for update funding spend --- channeld/test/run-settle_tx.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 66028d6b4e22..2e89b5f373c1 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -456,7 +456,7 @@ static int test_initial_settlement_tx(void) struct pubkey taproot_pubkey; secp256k1_musig_keyagg_cache keyagg_cache[2]; const struct pubkey *pubkey_ptrs[2]; - const struct sha256 tap_merkle_root; + struct sha256 funding_tap_merkle_root; unsigned char tap_tweak_out[32]; int i, pk_parity; secp256k1_xonly_pubkey xonly_pubkey; @@ -469,7 +469,7 @@ static int test_initial_settlement_tx(void) struct sha256_double msg_out; const secp256k1_musig_partial_sig *p_sig_ptrs[2]; secp256k1_musig_partial_sig p_sigs[2]; - u8 *tapleaf_script; + u8 *funding_tapleaf_script[1]; struct bip340sig sig; secp256k1_musig_session session[2]; u8 *annex; @@ -548,13 +548,19 @@ static int test_initial_settlement_tx(void) psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); printf("Update psbt: %s\n", psbt_b64); + /* This should be stored in bitcoin_tx->psbt... */ + funding_tapleaf_script[0] = make_eltoo_funding_update_script(tmpctx); + + /* FIXME This as well as inner key will be in PSBT so no need to recompute again */ + compute_taptree_merkle_root(&funding_tap_merkle_root, funding_tapleaf_script, /* num_scripts */ 1); + /* Generate signing session for "both sides" */ for (i=0; i<2; ++i){ bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache[i], pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, + &funding_tap_merkle_root, tap_tweak_out); /* FIXME we should just accept compressed pubkey whole way */ @@ -574,12 +580,9 @@ static int test_initial_settlement_tx(void) pubnonce_ptrs[i] = &pubnonces[i]; } - /* This should be stored in bitcoin_tx->psbt... */ - tapleaf_script = make_eltoo_funding_update_script(tmpctx); - annex = make_eltoo_annex(tmpctx, tx); for (i=0; i<2; ++i){ - bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, tapleaf_script, annex, &msg_out); + bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, funding_tapleaf_script[0], annex, &msg_out); bipmusig_partial_sign((i == 0) ? &alice_funding_privkey : &bob_funding_privkey, &secnonce[i], pubnonce_ptrs, From bfaa3c8f05946c7eef93b19d3a4bb5c0a6fa059e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 21 Jul 2022 10:41:41 -0400 Subject: [PATCH 074/283] Fix control block for funding update --- channeld/test/run-settle_tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 2e89b5f373c1..704a93331206 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -505,9 +505,10 @@ static int test_initial_settlement_tx(void) pubkey_ptrs[1] = &eltoo_keyset.other_funding_key; /* Calculate inner pubkey */ + printf("INNER PUBKEY INITIAL UPDATE\n"); bipmusig_inner_pubkey(&inner_pubkey, pubkey_ptrs, - /* n_pubkeys */ 1); + /* n_pubkeys */ 2); dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; @@ -553,6 +554,7 @@ static int test_initial_settlement_tx(void) /* FIXME This as well as inner key will be in PSBT so no need to recompute again */ compute_taptree_merkle_root(&funding_tap_merkle_root, funding_tapleaf_script, /* num_scripts */ 1); + printf("UPDATE FUNDING MERKLE ROOT: %s\n", tal_hexstr(tmpctx, funding_tap_merkle_root.u.u8, 32)); /* Generate signing session for "both sides" */ for (i=0; i<2; ++i){ @@ -562,6 +564,7 @@ static int test_initial_settlement_tx(void) /* n_pubkeys */ 2, &funding_tap_merkle_root, tap_tweak_out); + printf("UPDATE FUNDING TAPTWEAK: %s\n", tal_hexstr(tmpctx, tap_tweak_out, 32)); /* FIXME we should just accept compressed pubkey whole way */ ok = secp256k1_xonly_pubkey_from_pubkey( From 8d075321b42c295931f00b6ac9b5da9b98c79ffd Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 21 Jul 2022 11:13:31 -0400 Subject: [PATCH 075/283] Fixup signatures a bit for update tx --- channeld/test/run-settle_tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 704a93331206..c58912e781b7 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -586,6 +586,7 @@ static int test_initial_settlement_tx(void) annex = make_eltoo_annex(tmpctx, tx); for (i=0; i<2; ++i){ bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, funding_tapleaf_script[0], annex, &msg_out); + printf("UPDATE FUNDING SIGHASH: %s\n", tal_hexstr(tmpctx, msg_out.sha.u.u8, 32)); bipmusig_partial_sign((i == 0) ? &alice_funding_privkey : &bob_funding_privkey, &secnonce[i], pubnonce_ptrs, @@ -610,7 +611,7 @@ static int test_initial_settlement_tx(void) final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); memcpy(final_sig, sig.u8, sizeof(sig.u8)); - final_sig[sizeof(final_sig) - 1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; + final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; /* Witness stack, bottom to top: MuSig2 sig + tapscript + control block + Annex data */ update_witness = tal_arr(tmpctx, u8 *, 4); From fe703985c337ba7cb549411f7b08703838b1ec5b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 21 Jul 2022 11:14:37 -0400 Subject: [PATCH 076/283] update libwally for annex update --- external/libwally-core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/libwally-core b/external/libwally-core index c1b04b273664..339dbc6ec12b 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit c1b04b27366459020af19f218b7d283d05d05956 +Subproject commit 339dbc6ec12b7e5509197ee4f85020a4787b35db From 92104e1467a41b15d7f058830afeae5ddf6ed6ab Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 21 Jul 2022 12:18:32 -0400 Subject: [PATCH 077/283] Incorrect miniscript... --- bitcoin/script.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index a97e01ab2127..790f4202c4a1 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1137,11 +1137,11 @@ u8 *make_eltoo_funding_update_script(const tal_t *ctx) { /* where EXPR_UPDATE(n) = * - *`<1> OP_CHECKSIGVERIFY`, in the case of `n == 0` + *`<1> OP_CHECKSIG`, in the case of `n == 0` */ u8 *script = tal_arr(ctx, u8, 0); add_op(&script, OP_1); - add_op(&script, OP_CHECKSIGVERIFY); + add_op(&script, OP_CHECKSIG); return script; } From b1db6e86c8dc14675b56919823cb841c3ba054f2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 21 Jul 2022 12:19:49 -0400 Subject: [PATCH 078/283] Fix test signing of update tx --- bitcoin/signature.c | 3 +- bitcoin/signature.h | 6 ++-- channeld/settle_tx.c | 1 + channeld/test/run-settle_tx.c | 56 +++++++++++++++++++--------------- common/initial_settlement_tx.c | 1 + 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 25d59734f7d8..2658863b2f25 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -159,6 +159,7 @@ void bip340_sign_hash(const struct privkey *privkey, } void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, const struct pubkey * const* pubkeys, size_t n_pubkeys) { @@ -185,7 +186,7 @@ void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, ok = secp256k1_musig_pubkey_agg(secp256k1_ctx, NULL /* scratch */, inner_pubkey, - /* keyagg_cache */ NULL, + keyagg_cache, x_keys_ptr, n_pubkeys); diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 08057e06df3b..cda31c399dc2 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -109,13 +109,15 @@ void bip340_sign_hash(const struct privkey *privkey, struct bip340sig *sig); /** - * bipmusig_inner_pubkey - produce the sorted taproot inner pubkey. - * Does not create a signing session. + * bipmusig_inner_pubkey - produce the sorted taproot inner pubkey using sort order. + * Can be used for signing for internal pubkey if keyagg_cache is non-NULL. * @inner_pubkey: resulting aggregated(untweaked) x-only pubkey + * @keyagg_cache: cache for signing session for tapscript usage * @pubkeys: array of public keys to aggregate * @n_pubkeys: number of pubkeys in @pubkeys array */ void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, const struct pubkey * const* pubkeys, size_t n_pubkeys); diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 92b9d0ef5da3..2329601793b7 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -122,6 +122,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, + /* keyagg_cache */ NULL, pubkey_ptrs, /* n_pubkeys */ 2); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index c58912e781b7..11801629cbc5 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -453,16 +453,17 @@ static int test_initial_settlement_tx(void) char *psbt_b64; /* Aggregation stuff */ - struct pubkey taproot_pubkey; secp256k1_musig_keyagg_cache keyagg_cache[2]; const struct pubkey *pubkey_ptrs[2]; struct sha256 funding_tap_merkle_root; unsigned char tap_tweak_out[32]; int i, pk_parity; - secp256k1_xonly_pubkey xonly_pubkey; + secp256k1_xonly_pubkey dummy_xonly_pubkey; + struct pubkey taproot_pubkey; + secp256k1_musig_keyagg_cache dummy_cache; /* MuSig signing stuff */ - secp256k1_xonly_pubkey inner_pubkey; + secp256k1_xonly_pubkey xo_inner_pubkey; secp256k1_musig_secnonce secnonce[2]; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; secp256k1_musig_pubnonce pubnonces[2]; @@ -504,11 +505,14 @@ static int test_initial_settlement_tx(void) pubkey_ptrs[0] = &eltoo_keyset.self_funding_key; pubkey_ptrs[1] = &eltoo_keyset.other_funding_key; - /* Calculate inner pubkey */ + /* Calculate inner pubkey, cache reused at end for tapscript signing */ printf("INNER PUBKEY INITIAL UPDATE\n"); - bipmusig_inner_pubkey(&inner_pubkey, - pubkey_ptrs, - /* n_pubkeys */ 2); + for (i=0; i<2; ++i) { + bipmusig_inner_pubkey(&xo_inner_pubkey, + &keyagg_cache[i], + pubkey_ptrs, + /* n_pubkeys */ 2); + } dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; @@ -552,27 +556,30 @@ static int test_initial_settlement_tx(void) /* This should be stored in bitcoin_tx->psbt... */ funding_tapleaf_script[0] = make_eltoo_funding_update_script(tmpctx); + /* FIXME Next three blocks only needed for parity bit to make witness... refactor this */ + /* FIXME This as well as inner key will be in PSBT so no need to recompute again */ compute_taptree_merkle_root(&funding_tap_merkle_root, funding_tapleaf_script, /* num_scripts */ 1); printf("UPDATE FUNDING MERKLE ROOT: %s\n", tal_hexstr(tmpctx, funding_tap_merkle_root.u.u8, 32)); + bipmusig_finalize_keys(&taproot_pubkey, + &dummy_cache, + pubkey_ptrs, + /* n_pubkeys */ 2, + &funding_tap_merkle_root, + tap_tweak_out); + printf("UPDATE FUNDING TAPTWEAK: %s\n", tal_hexstr(tmpctx, tap_tweak_out, 32)); + + /* FIXME we should just accept compressed pubkey whole way */ + ok = secp256k1_xonly_pubkey_from_pubkey( + secp256k1_ctx, + &dummy_xonly_pubkey, + &pk_parity, + &(taproot_pubkey.pubkey)); + assert(ok); + /* Generate signing session for "both sides" */ for (i=0; i<2; ++i){ - bipmusig_finalize_keys(&taproot_pubkey, - &keyagg_cache[i], - pubkey_ptrs, - /* n_pubkeys */ 2, - &funding_tap_merkle_root, - tap_tweak_out); - printf("UPDATE FUNDING TAPTWEAK: %s\n", tal_hexstr(tmpctx, tap_tweak_out, 32)); - - /* FIXME we should just accept compressed pubkey whole way */ - ok = secp256k1_xonly_pubkey_from_pubkey( - secp256k1_ctx, - &xonly_pubkey, - &pk_parity, - &(taproot_pubkey.pubkey)); - assert(ok); /* "Presharing" nonces here */ bipmusig_gen_nonce(&secnonce[i], @@ -602,7 +609,7 @@ static int test_initial_settlement_tx(void) for (i=0; i<2; ++i){ ok = bipmusig_partial_sigs_combine_verify(p_sig_ptrs, 2, - &xonly_pubkey, + &xo_inner_pubkey, &session[i], &msg_out, &sig); @@ -617,7 +624,7 @@ static int test_initial_settlement_tx(void) update_witness = tal_arr(tmpctx, u8 *, 4); update_witness[0] = final_sig; update_witness[1] = make_eltoo_funding_update_script(tmpctx); - update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, &inner_pubkey, pk_parity); + update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, &xo_inner_pubkey, pk_parity); update_witness[3] = annex; bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); @@ -658,6 +665,7 @@ static int test_htlc_output_creation(void) /* Calculate inner pubkey */ bipmusig_inner_pubkey(&inner_pubkey, + /* keyagg_cache */ NULL, pubkey_ptrs, /* n_pubkeys */ 1); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 9634e8f27e5a..99f5a5168132 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -161,6 +161,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, + /* keyagg_cache */ NULL, pubkey_ptrs, /* n_pubkeys */ 2); From f916e8f54632fb9006f5b43c193ae6a8bb88fe49 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 25 Jul 2022 15:28:42 -0400 Subject: [PATCH 079/283] Refactor update transaction flow to follow actual rebinding flow --- bitcoin/script.c | 19 +++++++++ bitcoin/script.h | 6 +++ bitcoin/tx.c | 42 ++++++++++++++++++ bitcoin/tx.h | 11 +++++ channeld/test/run-settle_tx.c | 80 ++++++++++++----------------------- common/initial_update_tx.c | 80 +++++++++++++++++++++++++++-------- common/initial_update_tx.h | 55 +++++++++++++++++++----- 7 files changed, 211 insertions(+), 82 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 790f4202c4a1..56ad4689ba4e 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -327,6 +327,20 @@ u8 *scriptpubkey_witness_raw(const tal_t *ctx, u8 version, return script; } +int pubkey_parity(const struct pubkey *pubkey) +{ + int ok, pk_parity; + secp256k1_xonly_pubkey x_key; + + ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, + &x_key, + &pk_parity, + &(pubkey->pubkey)); + assert(ok); + + return pk_parity; +} + /* Create an output script for a taproot output */ u8 *scriptpubkey_p2tr(const tal_t *ctx, const struct pubkey *pubkey) { @@ -1015,6 +1029,11 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n } } +void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, u8 *update_tapscript, u8 *invalidated_annex_hint) +{ + +} + u8 *compute_control_block(const tal_t *ctx, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit) { int ok; diff --git a/bitcoin/script.h b/bitcoin/script.h index 58c7b1673b0c..d0fa70978cae 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -53,6 +53,9 @@ u8 *p2wpkh_scriptcode(const tal_t *ctx, const struct pubkey *key); /* Create an output script for a 32-byte witness program. */ u8 *scriptpubkey_p2wsh(const tal_t *ctx, const u8 *witnessscript); +/* Retrieve x-only parity bit from pubkey */ +int pubkey_parity(const struct pubkey *pubkey); + /* Create an output script for a taproot output */ u8 *scriptpubkey_p2tr(const tal_t *ctx, const struct pubkey *pubkey); @@ -177,6 +180,9 @@ u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_ /* Computes taproot merkle root from list of up to two scripts in depth 1 tree, in order */ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts); +/* FIXME implement */ +void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, u8 *update_tapscript, u8 *invalidated_annex_hint); + /* Computes control block for a spend from a taptree of size two, depth of 1, tops. other_script is NULL if only one script is committed. * Returns the control block array. * @other_script: The script that needs to be hashed and put in control block diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 8a5028761b26..444e15694c18 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -183,6 +183,48 @@ void bitcoin_tx_set_locktime(struct bitcoin_tx *tx, u32 locktime) tx->psbt->tx->locktime = locktime; } +int bitcoin_tx_add_unbound_input(struct bitcoin_tx *tx, + u32 sequence, + struct amount_sat amount, + const secp256k1_xonly_pubkey *inner_pubkey) +{ + int wally_err; + int input_num = tx->wtx->num_inputs; + /* PSBTs insist that a utxo is "real", insert garbage so we have value later */ + struct bitcoin_outpoint fake_outpoint; + u8 *fake_script_pubkey = tal_arr(tx, u8, 1); + + memset(fake_outpoint.txid.shad.sha.u.u8, 0x00, sizeof(fake_outpoint.txid.shad.sha.u.u8)); + fake_outpoint.n = 0; + + /* FIXME Put in PSBT */ + assert(inner_pubkey); + + psbt_append_input(tx->psbt, &fake_outpoint, + sequence, /* scriptSig */ NULL, + /* input_wscript */ NULL, /* redeemScript */ NULL); + + psbt_input_set_wit_utxo(tx->psbt, input_num, + fake_script_pubkey, amount); + + tal_wally_start(); + wally_err = wally_tx_add_input(tx->wtx, + &tx->psbt->tx->inputs[input_num]); + assert(wally_err == WALLY_OK); + + tal_wally_end(tx->wtx); + + if (is_elements(chainparams)) { + struct amount_asset asset; + /* FIXME: persist asset tags */ + asset = amount_sat_to_asset(&amount, + chainparams->fee_asset_tag); + /* FIXME: persist nonces */ + psbt_elements_input_set_asset(tx->psbt, input_num, &asset); + } + return input_num; +} + int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *outpoint, u32 sequence, const u8 *scriptSig, diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 75d210803254..ffc133817024 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -104,6 +104,17 @@ int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script, /* Set the locktime for a transaction */ void bitcoin_tx_set_locktime(struct bitcoin_tx *tx, u32 locktime); +/* Add a new input to a bitcoin tx that will be signed + * using ANYPREVOUT(ANYSCRIPT). + * Since at signing time we do not know what the outpoint + * will be, or the script being signed for at all, + * we ommitt all those values. + */ +int bitcoin_tx_add_unbound_input(struct bitcoin_tx *tx, + u32 sequence, + struct amount_sat amount, + const secp256k1_xonly_pubkey *inner_pubkey); + /* Add a new input to a bitcoin tx. * * For P2WSH inputs, we'll also store the wscript and/or scriptPubkey diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 11801629cbc5..d40f0ae149e7 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -455,12 +455,7 @@ static int test_initial_settlement_tx(void) /* Aggregation stuff */ secp256k1_musig_keyagg_cache keyagg_cache[2]; const struct pubkey *pubkey_ptrs[2]; - struct sha256 funding_tap_merkle_root; - unsigned char tap_tweak_out[32]; - int i, pk_parity; - secp256k1_xonly_pubkey dummy_xonly_pubkey; - struct pubkey taproot_pubkey; - secp256k1_musig_keyagg_cache dummy_cache; + int i; /* MuSig signing stuff */ secp256k1_xonly_pubkey xo_inner_pubkey; @@ -470,11 +465,9 @@ static int test_initial_settlement_tx(void) struct sha256_double msg_out; const secp256k1_musig_partial_sig *p_sig_ptrs[2]; secp256k1_musig_partial_sig p_sigs[2]; - u8 *funding_tapleaf_script[1]; struct bip340sig sig; secp256k1_musig_session session[2]; u8 *annex; - u8 **update_witness; u8 *final_sig; /* Test initial settlement tx */ @@ -505,15 +498,6 @@ static int test_initial_settlement_tx(void) pubkey_ptrs[0] = &eltoo_keyset.self_funding_key; pubkey_ptrs[1] = &eltoo_keyset.other_funding_key; - /* Calculate inner pubkey, cache reused at end for tapscript signing */ - printf("INNER PUBKEY INITIAL UPDATE\n"); - for (i=0; i<2; ++i) { - bipmusig_inner_pubkey(&xo_inner_pubkey, - &keyagg_cache[i], - pubkey_ptrs, - /* n_pubkeys */ 2); - } - dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; @@ -542,41 +526,26 @@ static int test_initial_settlement_tx(void) tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); tx_must_be_eq(tx, tx_cmp); - /* We rebind the outpoint later anyways, so just reuse the outpoint */ - update_tx = initial_update_tx(tmpctx, + /* Calculate inner pubkey, caches reused at end for tapscript signing */ + printf("INNER PUBKEY INITIAL UPDATE\n"); + for (i=0; i<2; ++i) { + bipmusig_inner_pubkey(&xo_inner_pubkey, + &keyagg_cache[i], + pubkey_ptrs, + /* n_pubkeys */ 2); + } + + /* Will be bound later */ + update_tx = unbound_update_tx(tmpctx, tx, - &update_output, update_output_sats, - &eltoo_keyset, + &xo_inner_pubkey, &err_reason); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); - printf("Update psbt: %s\n", psbt_b64); + printf("Unbound update psbt: %s\n", psbt_b64); - /* This should be stored in bitcoin_tx->psbt... */ - funding_tapleaf_script[0] = make_eltoo_funding_update_script(tmpctx); - - /* FIXME Next three blocks only needed for parity bit to make witness... refactor this */ - - /* FIXME This as well as inner key will be in PSBT so no need to recompute again */ - compute_taptree_merkle_root(&funding_tap_merkle_root, funding_tapleaf_script, /* num_scripts */ 1); - printf("UPDATE FUNDING MERKLE ROOT: %s\n", tal_hexstr(tmpctx, funding_tap_merkle_root.u.u8, 32)); - - bipmusig_finalize_keys(&taproot_pubkey, - &dummy_cache, - pubkey_ptrs, - /* n_pubkeys */ 2, - &funding_tap_merkle_root, - tap_tweak_out); - printf("UPDATE FUNDING TAPTWEAK: %s\n", tal_hexstr(tmpctx, tap_tweak_out, 32)); - - /* FIXME we should just accept compressed pubkey whole way */ - ok = secp256k1_xonly_pubkey_from_pubkey( - secp256k1_ctx, - &dummy_xonly_pubkey, - &pk_parity, - &(taproot_pubkey.pubkey)); - assert(ok); + /* Signing happens next */ /* Generate signing session for "both sides" */ for (i=0; i<2; ++i){ @@ -592,7 +561,7 @@ static int test_initial_settlement_tx(void) annex = make_eltoo_annex(tmpctx, tx); for (i=0; i<2; ++i){ - bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, funding_tapleaf_script[0], annex, &msg_out); + bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &msg_out); printf("UPDATE FUNDING SIGHASH: %s\n", tal_hexstr(tmpctx, msg_out.sha.u.u8, 32)); bipmusig_partial_sign((i == 0) ? &alice_funding_privkey : &bob_funding_privkey, &secnonce[i], @@ -618,15 +587,18 @@ static int test_initial_settlement_tx(void) final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); memcpy(final_sig, sig.u8, sizeof(sig.u8)); + /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; - /* Witness stack, bottom to top: MuSig2 sig + tapscript + control block + Annex data */ - update_witness = tal_arr(tmpctx, u8 *, 4); - update_witness[0] = final_sig; - update_witness[1] = make_eltoo_funding_update_script(tmpctx); - update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, &xo_inner_pubkey, pk_parity); - update_witness[3] = annex; - bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); + /* We want to close the channel without cooperation... time to rebind and finalize */ + + /* Re-bind, add final script/tapscript info into PSBT */ + bind_update_tx_to_funding_outpoint(update_tx, + tx, + &update_output, + &eltoo_keyset, + &xo_inner_pubkey, + final_sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); printf("Initial update psbt with finalized witness for input: %s\n", psbt_b64); diff --git a/common/initial_update_tx.c b/common/initial_update_tx.c index 29d3a93ecf29..1feaeb456029 100644 --- a/common/initial_update_tx.c +++ b/common/initial_update_tx.c @@ -53,45 +53,89 @@ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) return annex; } -void tx_add_funding_input(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, struct amount_sat funding_outpoint_sats, const struct eltoo_keyset *eltoo_keyset) +void tx_add_unbound_input(struct bitcoin_tx *update_tx, struct amount_sat funding_sats, const secp256k1_xonly_pubkey *inner_pubkey) { int input_num; + + /* FIXME this field needs to be stored in PSBT via bitcoin_tx_add_unbound_input */ + assert(inner_pubkey); + + input_num = bitcoin_tx_add_unbound_input(update_tx, /* sequence */ 0xFFFFFFFD, funding_sats, inner_pubkey); + assert(input_num == 0); +} + +void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, + const struct bitcoin_tx *settle_tx, + const struct bitcoin_outpoint *funding_outpoint, + const struct eltoo_keyset *eltoo_keyset, + secp256k1_xonly_pubkey *psbt_inner_pubkey, + u8 *final_sig) +{ const struct pubkey *pubkey_ptrs[2]; u8 *update_tapscript[1]; + int input_num; /* For committing to the output's settle path tapleaf hash inside the annex itself */ u8 *script_pubkey; - struct sha256 update_merkle_root; - struct pubkey update_agg_pk; - secp256k1_musig_keyagg_cache update_keyagg_cache; - unsigned char update_tap_tweak[32]; + struct pubkey taproot_pk; + secp256k1_musig_keyagg_cache unused_coop_cache; + u8 **update_witness; + struct amount_sat funding_sats; + + /* Stuff that should go in PSBT eventually */ + struct sha256 psbt_tap_merkle_root; + unsigned char psbt_tap_tweak[32]; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); + /* FIXME embed this in PSBT as well... */ update_tapscript[0] = make_eltoo_funding_update_script(tmpctx); - compute_taptree_merkle_root(&update_merkle_root, update_tapscript, /* num_scripts */ 1); - bipmusig_finalize_keys(&update_agg_pk, - &update_keyagg_cache, + compute_taptree_merkle_root(&psbt_tap_merkle_root, update_tapscript, /* num_scripts */ 1); + + bipmusig_finalize_keys(&taproot_pk, + &unused_coop_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &update_merkle_root, - update_tap_tweak); + &psbt_tap_merkle_root, + psbt_tap_tweak); - script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); + script_pubkey = scriptpubkey_p2tr(tmpctx, &taproot_pk); + /* Remove existing input since we're over-writing all details */ + funding_sats.satoshis = update_tx->psbt->inputs[0].witness_utxo->satoshi; + bitcoin_tx_remove_input(update_tx, /* input_num */ 0); + + /* FIXME carry inner pubkey and tapscript/taptree info in PSBT, even though not needed to complete this tx per se */ input_num = bitcoin_tx_add_input(update_tx, funding_outpoint, /* sequence */ 0xFFFFFFFD, - /* scriptSig */ NULL, funding_outpoint_sats, script_pubkey, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); + /* scriptSig */ NULL, funding_sats, script_pubkey, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); assert(input_num == 0); + + /* FIXME we can now rebind settle_tx's prevout */ + + /* Witness stack, bottom to top: MuSig2 sig + tapscript + control block + Annex data */ + update_witness = tal_arr(tmpctx, u8 *, 4); + update_witness[0] = final_sig; + update_witness[1] = update_tapscript[0]; + update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, psbt_inner_pubkey, pubkey_parity(&taproot_pk)); + update_witness[3] = make_eltoo_annex(tmpctx, settle_tx);; + bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } +void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, + const struct bitcoin_outpoint *funding_outpoint, + const struct eltoo_keyset *eltoo_keyset, + const u8 *invalidated_annex_hint, + u32 invalidated_update_number) +{ + // FIXME +} -struct bitcoin_tx *initial_update_tx(const tal_t *ctx, +struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, - const struct bitcoin_outpoint *funding_outpoint, - struct amount_sat funding_outpoint_sats, - const struct eltoo_keyset *eltoo_keyset, + struct amount_sat funding_sats, + const secp256k1_xonly_pubkey *inner_pubkey, char** err_reason) { struct bitcoin_tx *update_tx; @@ -104,8 +148,8 @@ struct bitcoin_tx *initial_update_tx(const tal_t *ctx, pos = tx_add_settlement_output(update_tx, settle_tx); assert(pos == 0); - /* Add unsigned funding input (but includes annex commitment!) */ - tx_add_funding_input(update_tx, settle_tx, funding_outpoint, funding_outpoint_sats, eltoo_keyset); + /* Add unsigned, un-bound funding input */ + tx_add_unbound_input(update_tx, funding_sats, inner_pubkey); /* Set global fields */ assert(update_tx->wtx->version == 2); diff --git a/common/initial_update_tx.h b/common/initial_update_tx.h index d40c79df9a9c..9b2668c65323 100644 --- a/common/initial_update_tx.h +++ b/common/initial_update_tx.h @@ -15,26 +15,61 @@ int tx_add_settlement_output(struct bitcoin_tx *update_tx, const struct bitcoin_ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx); -void tx_add_funding_input(struct bitcoin_tx *update_tx, +/* Appends a tx input to the update transaction, without + * binding it to a particular outpoint or script */ +void tx_add_unbound_input(struct bitcoin_tx *update_tx, + struct amount_sat funding_sats, + const secp256k1_xonly_pubkey *inner_pubkey); + +/* Used to bind the update transaction to the funding outpoint + * of the eltoo contract. This is the expected (non-malicious) + * failure mode of a channel. Also finalizes the witness data. + * @update_tx: The transaction being re-binded + * @settle_tx: The corresponding settlement transaction, also re-binded + * @funding_outpoint: The outpoint to be spend on chain + * @eltoo_keyset: Set of keys to derive inner public key + * @psbt_inner_pubkey: Inner pubkey for the state input + * @final_sig: Raw 65-bytes of signature to be put into witness + */ +void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, - struct amount_sat funding_outpoint_sats, - const struct eltoo_keyset *eltoo_keyset); + const struct eltoo_keyset *eltoo_keyset, + secp256k1_xonly_pubkey *psbt_inner_pubkey, + u8 *final_sig); + +/* Used to bind the update transaction to the non-funding outpoints + * of the eltoo contract. This only occurs if invalidated update + * transactions are published, e.g. faulty watchtower, or malicious + * counter-party. + * @update_tx: The transaction being re-binded + * @funding_outpoint: The outpoint to be spend on chain + * @eltoo_keyset: Set of keys to derive inner public key + * @invalidated_annex_hint: The annex data of the update transaction + * which is having its outpoint spent by @update_tx + * @invalidated_update_number: The locktime of the update transaction + * which is having its outpoint spent by @update_tx + */ +void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, + const struct bitcoin_outpoint *funding_outpoint, + const struct eltoo_keyset *eltoo_keyset, + const u8 *invalidated_annex_hint, + u32 invalidated_update_number); /** - * initial_update_tx: create (unsigned) update tx to spend the funding output + * unbound_update_tx: create (unsigned) update tx to spend a yet-to-decided ouutpoint * @ctx: context to allocate transaction and @htlc_map from. * @settlement_tx: initial settlement tx created via `initial_settlement_tx` - * @funding_outpoint, @funding_outpoint_sats: funding outpoint and amount - * @eltoo_keyset: set of keys for deriving inner public key + * @funding_sats: funding amount + * @inner_pubkey: inner public key for the eltoo channel * @err_reason: When NULL is returned, this will point to a human readable reason. * */ -struct bitcoin_tx *initial_update_tx(const tal_t *ctx, +struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, - const struct bitcoin_outpoint *funding_outpoint, - struct amount_sat funding_outpoint_sats, - const struct eltoo_keyset *eltoo_keyset, + struct amount_sat funding_sats, + const secp256k1_xonly_pubkey *inner_pubkey, char** err_reason); + #endif /* LIGHTNING_COMMON_INITIAL_UPDATE_TX_H */ From 058f9747ee43a27b3fbf7094b1eba09a2efd2dd9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 25 Jul 2022 17:00:00 -0400 Subject: [PATCH 080/283] Implement annex hint stuff for update to update tx --- bitcoin/script.c | 47 +++++++++++++++++++++++--- bitcoin/script.h | 9 ++--- common/initial_settlement_tx.c | 5 ++- common/initial_update_tx.c | 60 +++++++++++++++++++++++++++++++--- common/initial_update_tx.h | 11 +++++-- 5 files changed, 114 insertions(+), 18 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 56ad4689ba4e..9f6944da410c 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1029,16 +1029,48 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n } } -void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, u8 *update_tapscript, u8 *invalidated_annex_hint) +void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, const u8 *update_tapscript, const u8 *invalidated_annex_hint) { + int ok; + unsigned char leaf_version = 0xc0; + unsigned char tag_hash_buf[1000]; /* Needs to be large enough for HTLC scripts */ + unsigned char tap_hashes[64]; /* To store the leaves for comparison */ + + size_t script_len = tal_count(update_tapscript); + unsigned char *p = tag_hash_buf; + + assert(tal_count(invalidated_annex_hint) == 32 && invalidated_annex_hint[0] == 0x50); + /* Let k0 = hashTapLeaf(v || compact_size(size of s) || s); also call it the tapleaf hash. */ + p[0] = leaf_version; + p++; + p += varint_put(p, script_len); + memcpy(p, update_tapscript, script_len); + p += script_len; + + ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", tap_hashes); + assert(ok == WALLY_OK); + + /* Put invalidated hint in place as a tapleaf hash directly */ + memcpy(tap_hashes + 32, invalidated_annex_hint + 1, 32); + + /* If kj ≥ ej: kj+1 = hashTapBranch(ej || kj), swap them*/ + if (memcmp(tap_hashes, tap_hashes + 32, 32) >= 0) { + memcpy(tag_hash_buf, tap_hashes, 32); + memcpy(tap_hashes, tap_hashes + 32, 32); + memcpy(tap_hashes + 32, tag_hash_buf, 32); + } + ok = wally_tagged_hash(tap_hashes, sizeof(tap_hashes), "TapBranch", update_merkle_root->u.u8); + assert(ok == WALLY_OK); } -u8 *compute_control_block(const tal_t *ctx, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit) +u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *annex_hint, const secp256k1_xonly_pubkey *inner_pubkey, int parity_bit) { int ok; u8 *control_block_cursor; - u8 *control_block = tal_arr(ctx, u8, other_script ? 33 + 32 : 33); + u8 *control_block = tal_arr(ctx, u8, (!!other_script | !!annex_hint) ? 33 + 32 : 33); + + assert(other_script != annex_hint); control_block_cursor = control_block; @@ -1072,11 +1104,16 @@ u8 *compute_control_block(const tal_t *ctx, u8 *other_script, secp256k1_xonly_pu ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", control_block_cursor); assert(ok == WALLY_OK); control_block_cursor += 32; + } else if (annex_hint) { + assert(tal_count(annex_hint) == 33); + assert(annex_hint[0] == 0x50); + memcpy(control_block_cursor, annex_hint + 1, 32); + control_block_cursor += 32; } return control_block; } -u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index) +u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *settle_tx, size_t input_index) { int ok; enum sighash_type sh_type = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_ALL; @@ -1093,7 +1130,7 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size * We really shouldn't, but for now we pass in dummy * since APOAS sighash doesn't cover it anyways. */ - bitcoin_tx_taproot_hash_for_sig(tx, + bitcoin_tx_taproot_hash_for_sig(settle_tx, input_index, sh_type, script, diff --git a/bitcoin/script.h b/bitcoin/script.h index d0fa70978cae..5922d8ebcdeb 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -180,22 +180,23 @@ u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_ /* Computes taproot merkle root from list of up to two scripts in depth 1 tree, in order */ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts); -/* FIXME implement */ -void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, u8 *update_tapscript, u8 *invalidated_annex_hint); +/* Compute merkle root via annex hint from invalidated update tx */ +void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, const u8 *update_tapscript, const u8 *invalidated_annex_hint); /* Computes control block for a spend from a taptree of size two, depth of 1, tops. other_script is NULL if only one script is committed. * Returns the control block array. * @other_script: The script that needs to be hashed and put in control block + * @annex_hint: ... or if @other_script is NULL, must supply annex hint from the posted update tx * @inner_pubkey: Inner pubkey for taproot control block * @parity_bit: Parity of outer taproot pubkey */ -u8 *compute_control_block(const tal_t *ctx, u8 *other_script, secp256k1_xonly_pubkey *inner_pubkey, int parity_bit); +u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *annex_hint, const secp256k1_xonly_pubkey *inner_pubkey, int parity_bit); /* Creates tapscript that makes a sig-in-script ANYPREVOUTANYSCRIPT covenant * which commits to the tx argument: * CovSig(n) 1_G OP_CHECKSIG */ -u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *tx, size_t input_index); +u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *settle_tx, size_t input_index); /* Creates the update path tapscript for eltoo, which commits to the masked update number */ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 99f5a5168132..607e9f4824b4 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -98,11 +98,10 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * update_tap_tweak); printf("TAPTWEAK: %s\n", tal_hexstr(tmpctx, update_tap_tweak, 32)); - /* Convert to x-only, grab parity bit of the output pubkey */ - ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &output_pubkey, &parity_bit, &(update_agg_pk.pubkey)); + parity_bit = pubkey_parity(&update_agg_pk); printf("PARITY BIT: %d\n", parity_bit); assert(ok); - control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], inner_pubkey, parity_bit); + control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], /* annex_hint */ NULL, inner_pubkey, parity_bit); printf("CBLOCK: %s\n", tal_hexstr(tmpctx, control_block, tal_count(control_block))); script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); diff --git a/common/initial_update_tx.c b/common/initial_update_tx.c index 1feaeb456029..eed2eb46e96c 100644 --- a/common/initial_update_tx.c +++ b/common/initial_update_tx.c @@ -118,18 +118,70 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, update_witness = tal_arr(tmpctx, u8 *, 4); update_witness[0] = final_sig; update_witness[1] = update_tapscript[0]; - update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, psbt_inner_pubkey, pubkey_parity(&taproot_pk)); + update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, /* annex_hint */ NULL, psbt_inner_pubkey, pubkey_parity(&taproot_pk)); update_witness[3] = make_eltoo_annex(tmpctx, settle_tx);; bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, - const struct bitcoin_outpoint *funding_outpoint, + struct bitcoin_tx *settle_tx, + const struct bitcoin_outpoint *outpoint, const struct eltoo_keyset *eltoo_keyset, const u8 *invalidated_annex_hint, - u32 invalidated_update_number) + u32 invalidated_update_number, + secp256k1_xonly_pubkey *psbt_inner_pubkey, + u8 *final_sig) { - // FIXME + const struct pubkey *pubkey_ptrs[2]; + u8 *update_tapscript; + int input_num; + /* For committing to the output's settle path tapleaf hash inside the annex itself */ + u8 *script_pubkey; + struct pubkey taproot_pk; + secp256k1_musig_keyagg_cache unused_coop_cache; + u8 **update_witness; + struct amount_sat funding_sats; + + /* Stuff that should go in PSBT eventually */ + struct sha256 psbt_tap_merkle_root; + unsigned char psbt_tap_tweak[32]; + + /* For MuSig aggregation for outputs */ + pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); + pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); + + /* FIXME embed this in PSBT as well... */ + update_tapscript = make_eltoo_update_script(tmpctx, invalidated_update_number); + + compute_taptree_merkle_root_with_hint(&psbt_tap_merkle_root, update_tapscript, invalidated_annex_hint); + + bipmusig_finalize_keys(&taproot_pk, + &unused_coop_cache, + pubkey_ptrs, + /* n_pubkeys */ 2, + &psbt_tap_merkle_root, + psbt_tap_tweak); + + script_pubkey = scriptpubkey_p2tr(tmpctx, &taproot_pk); + + /* Remove existing input since we're over-writing all details */ + funding_sats.satoshis = update_tx->psbt->inputs[0].witness_utxo->satoshi; + bitcoin_tx_remove_input(update_tx, /* input_num */ 0); + + /* FIXME carry inner pubkey and tapscript/taptree info in PSBT, even though not needed to complete this tx per se */ + input_num = bitcoin_tx_add_input(update_tx, outpoint, /* sequence */ 0xFFFFFFFD, + /* scriptSig */ NULL, funding_sats, script_pubkey, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); + assert(input_num == 0); + + /* FIXME we can now rebind settle_tx's prevout */ + + /* Witness stack, bottom to top: MuSig2 sig + tapscript + control block + Annex data */ + update_witness = tal_arr(tmpctx, u8 *, 4); + update_witness[0] = final_sig; + update_witness[1] = update_tapscript; + update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, invalidated_annex_hint, psbt_inner_pubkey, pubkey_parity(&taproot_pk)); + update_witness[3] = make_eltoo_annex(tmpctx, settle_tx); + bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, diff --git a/common/initial_update_tx.h b/common/initial_update_tx.h index 9b2668c65323..9ab6cbe611b3 100644 --- a/common/initial_update_tx.h +++ b/common/initial_update_tx.h @@ -43,21 +43,28 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, * transactions are published, e.g. faulty watchtower, or malicious * counter-party. * @update_tx: The transaction being re-binded + * @settle_tx: The corresponding settlement transaction, also re-binded * @funding_outpoint: The outpoint to be spend on chain * @eltoo_keyset: Set of keys to derive inner public key * @invalidated_annex_hint: The annex data of the update transaction * which is having its outpoint spent by @update_tx * @invalidated_update_number: The locktime of the update transaction * which is having its outpoint spent by @update_tx + * @psbt_inner_pubkey: Inner pubkey for the state input + * @final_sig: Raw 65-bytes of signature to put into witness */ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, - const struct bitcoin_outpoint *funding_outpoint, + struct bitcoin_tx *settle_tx, + const struct bitcoin_outpoint *outpoint, const struct eltoo_keyset *eltoo_keyset, const u8 *invalidated_annex_hint, - u32 invalidated_update_number); + u32 invalidated_update_number, + secp256k1_xonly_pubkey *psbt_inner_pubkey, + u8 *final_sig); /** * unbound_update_tx: create (unsigned) update tx to spend a yet-to-decided ouutpoint + * FIXME return annex here too(or include as proprietary field in PSBT?) * @ctx: context to allocate transaction and @htlc_map from. * @settlement_tx: initial settlement tx created via `initial_settlement_tx` * @funding_sats: funding amount From 6ab9f1a3775a026a654acd95c9dfeded904213b8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 26 Jul 2022 12:35:18 -0400 Subject: [PATCH 081/283] Rename initial_update_tx to update_tx since it's not just initial --- bitcoin/script.c | 5 +++-- channeld/Makefile | 2 +- channeld/test/Makefile | 2 +- channeld/test/run-settle_tx.c | 4 ++-- common/Makefile | 2 +- common/initial_settlement_tx.c | 15 +-------------- common/{initial_update_tx.c => update_tx.c} | 8 +++----- common/{initial_update_tx.h => update_tx.h} | 10 +++++----- 8 files changed, 17 insertions(+), 31 deletions(-) rename common/{initial_update_tx.c => update_tx.c} (95%) rename common/{initial_update_tx.h => update_tx.h} (92%) diff --git a/bitcoin/script.c b/bitcoin/script.c index 9f6944da410c..66a6aa927a59 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1068,9 +1068,10 @@ u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *an { int ok; u8 *control_block_cursor; - u8 *control_block = tal_arr(ctx, u8, (!!other_script | !!annex_hint) ? 33 + 32 : 33); + u8 *control_block = tal_arr(ctx, u8, (other_script || annex_hint) ? 33 + 32 : 33); - assert(other_script != annex_hint); + /* other_script and annex_hint are mutually exclusive args */ + assert(!(other_script && annex_hint)); control_block_cursor = control_block; diff --git a/channeld/Makefile b/channeld/Makefile index 3d9f9e853235..295fef246838 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -63,7 +63,6 @@ CHANNELD_COMMON_OBJS := \ common/initial_channel.o \ common/initial_commit_tx.o \ common/initial_settlement_tx.o \ - common/initial_update_tx.o \ common/keyset.o \ common/key_derive.o \ common/memleak.o \ @@ -89,6 +88,7 @@ CHANNELD_COMMON_OBJS := \ common/subdaemon.o \ common/timeout.o \ common/type_to_string.o \ + common/update_tx.o \ common/utils.o \ common/utxo.o \ common/version.o \ diff --git a/channeld/test/Makefile b/channeld/test/Makefile index 3dc23747e14e..ff98e7e1b128 100644 --- a/channeld/test/Makefile +++ b/channeld/test/Makefile @@ -18,13 +18,13 @@ CHANNELD_TEST_COMMON_OBJS := \ common/htlc_tx.o \ common/initial_commit_tx.o \ common/initial_settlement_tx.o \ - common/initial_update_tx.o \ common/key_derive.o \ common/msg_queue.o \ common/permute_tx.o \ common/pseudorand.o \ common/setup.o \ common/type_to_string.o \ + common/update_tx.o \ common/utils.o $(CHANNELD_TEST_PROGRAMS): $(CCAN_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CHANNELD_TEST_COMMON_OBJS) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index d40f0ae149e7..a6a3f43c9f90 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -14,11 +14,11 @@ static bool print_superverbose; #include #include #include +#include #include #include #include -#include -#include +#include /* Turn this on to brute-force fee values */ /*#define DEBUG */ diff --git a/common/Makefile b/common/Makefile index 8cbb1f345e09..d35eb7303895 100644 --- a/common/Makefile +++ b/common/Makefile @@ -47,7 +47,6 @@ COMMON_SRC_NOGEN := \ common/initial_channel.c \ common/initial_commit_tx.c \ common/initial_settlement_tx.c \ - common/initial_update_tx.c \ common/iso4217.c \ common/json.c \ common/json_helpers.c \ @@ -86,6 +85,7 @@ COMMON_SRC_NOGEN := \ common/subdaemon.c \ common/timeout.c \ common/type_to_string.c \ + common/update_tx.c \ common/utils.c \ common/utxo.c \ common/version.c \ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 607e9f4824b4..1f559fe29ccb 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -59,13 +59,10 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * struct pubkey update_agg_pk; secp256k1_musig_keyagg_cache update_keyagg_cache; unsigned char update_tap_tweak[32]; - secp256k1_xonly_pubkey output_pubkey; - int parity_bit, ok; + int parity_bit; u8 *control_block; u8 *script_pubkey; u8 **witness; /* settle_and_update_tapscripts[0] script and control_block */ - unsigned char inner_pubkey_bytes[32]; - unsigned char output_pubkey_bytes[32]; /* * We do not know what scriptPubKey, tap_tree look like yet because we're computing @@ -100,20 +97,10 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * printf("TAPTWEAK: %s\n", tal_hexstr(tmpctx, update_tap_tweak, 32)); parity_bit = pubkey_parity(&update_agg_pk); printf("PARITY BIT: %d\n", parity_bit); - assert(ok); control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], /* annex_hint */ NULL, inner_pubkey, parity_bit); printf("CBLOCK: %s\n", tal_hexstr(tmpctx, control_block, tal_count(control_block))); script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, inner_pubkey); - assert(ok); - printf("INNER PUBKEY: %s\n", tal_hexstr(tmpctx, inner_pubkey_bytes, 32)); - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, output_pubkey_bytes, &output_pubkey); - assert(ok); - printf("OUTER PUBKEY: %s\n", tal_hexstr(tmpctx, output_pubkey_bytes, 32)); - - assert(secp256k1_xonly_pubkey_tweak_add_check(secp256k1_ctx, output_pubkey_bytes, parity_bit, inner_pubkey, update_tap_tweak)); - /* Remove and re-add with updated information */ bitcoin_tx_remove_input(tx, input_num); input_num = bitcoin_tx_add_input(tx, update_outpoint, shared_delay, diff --git a/common/initial_update_tx.c b/common/update_tx.c similarity index 95% rename from common/initial_update_tx.c rename to common/update_tx.c index eed2eb46e96c..b7e6059b5741 100644 --- a/common/initial_update_tx.c +++ b/common/update_tx.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -16,7 +16,7 @@ struct wally_psbt; -int tx_add_settlement_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx) +int tx_add_state_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx) { struct amount_sat amount; amount.satoshis = settle_tx->psbt->inputs[0].witness_utxo->satoshi; @@ -74,7 +74,6 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, const struct pubkey *pubkey_ptrs[2]; u8 *update_tapscript[1]; int input_num; - /* For committing to the output's settle path tapleaf hash inside the annex itself */ u8 *script_pubkey; struct pubkey taproot_pk; secp256k1_musig_keyagg_cache unused_coop_cache; @@ -135,7 +134,6 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, const struct pubkey *pubkey_ptrs[2]; u8 *update_tapscript; int input_num; - /* For committing to the output's settle path tapleaf hash inside the annex itself */ u8 *script_pubkey; struct pubkey taproot_pk; secp256k1_musig_keyagg_cache unused_coop_cache; @@ -197,7 +195,7 @@ struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, update_tx = bitcoin_tx(ctx, chainparams, 1, 1, 0); /* Add output */ - pos = tx_add_settlement_output(update_tx, settle_tx); + pos = tx_add_state_output(update_tx, settle_tx); assert(pos == 0); /* Add unsigned, un-bound funding input */ diff --git a/common/initial_update_tx.h b/common/update_tx.h similarity index 92% rename from common/initial_update_tx.h rename to common/update_tx.h index 9ab6cbe611b3..d32f9dc33b61 100644 --- a/common/initial_update_tx.h +++ b/common/update_tx.h @@ -1,6 +1,5 @@ -/* Commit tx without HTLC support; needed for openingd. */ -#ifndef LIGHTNING_COMMON_INITIAL_UPDATE_TX_H -#define LIGHTNING_COMMON_INITIAL_UPDATE_TX_H +#ifndef LIGHTNING_COMMON_UPDATE_TX_H +#define LIGHTNING_COMMON_UPDATE_TX_H #include "config.h" #include #include @@ -11,7 +10,8 @@ struct bitcoin_outpoint; -int tx_add_settlement_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx); +/* Generates the "state" output for eltoo update transaction, based on the settlement tx */ +int tx_add_state_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx); u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx); @@ -79,4 +79,4 @@ struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, char** err_reason); -#endif /* LIGHTNING_COMMON_INITIAL_UPDATE_TX_H */ +#endif /* LIGHTNING_COMMON_UPDATE_TX_H */ From fb36456b4d04d12de7ba5de28e3c1c99782ff3f3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 26 Jul 2022 14:35:46 -0400 Subject: [PATCH 082/283] Delete the copious amount of printing for debugging --- bitcoin/script.c | 7 ------- channeld/test/run-settle_tx.c | 9 --------- common/initial_settlement_tx.c | 8 ++------ common/update_tx.c | 2 -- 4 files changed, 2 insertions(+), 24 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 66a6aa927a59..186b922f9b78 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -997,9 +997,6 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n /* k0 == km, this is the merkle root so we directly write it out */ ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", hash_out->u.u8); assert(ok == WALLY_OK); - printf("SCRIPT(1 branch): %s\n", tal_hexstr(tmpctx, scripts[0], tal_count(scripts[0]))); - printf("***TAPLEAF PREIMAGE***: %s\n", tal_hexstr(tmpctx, tag_hash_buf, p - tag_hash_buf)); - printf("TAPLEAF HASH(1 branch): %s\n", tal_hexstr(tmpctx, hash_out->u.u8, 32)); } else if (num_scripts == 2) { int i; for (i=0; i= 0) { @@ -1138,7 +1132,6 @@ u8 *make_eltoo_settle_script(const tal_t *ctx, const struct bitcoin_tx *settle_t /* annex */ NULL, &sighash); - printf("SIGHASH: %s\n", tal_hexstr(tmpctx, sighash.sha.u.u32, 32));//\n", sighash.sha.u.u32); /* Should directly take keypair instead of extracting but... */ create_keypair_of_one(&G_pair); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index a6a3f43c9f90..aedbe16f58a0 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -449,7 +449,6 @@ static int test_initial_settlement_tx(void) struct bitcoin_tx *tx, *tx_cmp, *update_tx; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; - char *tx_hex; char *psbt_b64; /* Aggregation stuff */ @@ -517,8 +516,6 @@ static int test_initial_settlement_tx(void) /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, &err_reason); - tx_hex = fmt_bitcoin_tx(tmpctx, tx); - printf("Settlement tx: %s\n", tx_hex); psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); printf("Initial Settlement psbt: %s\n", psbt_b64); @@ -527,7 +524,6 @@ static int test_initial_settlement_tx(void) tx_must_be_eq(tx, tx_cmp); /* Calculate inner pubkey, caches reused at end for tapscript signing */ - printf("INNER PUBKEY INITIAL UPDATE\n"); for (i=0; i<2; ++i) { bipmusig_inner_pubkey(&xo_inner_pubkey, &keyagg_cache[i], @@ -562,7 +558,6 @@ static int test_initial_settlement_tx(void) annex = make_eltoo_annex(tmpctx, tx); for (i=0; i<2; ++i){ bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &msg_out); - printf("UPDATE FUNDING SIGHASH: %s\n", tal_hexstr(tmpctx, msg_out.sha.u.u8, 32)); bipmusig_partial_sign((i == 0) ? &alice_funding_privkey : &bob_funding_privkey, &secnonce[i], pubnonce_ptrs, @@ -643,12 +638,9 @@ static int test_htlc_output_creation(void) ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, &inner_pubkey); assert(ok); - printf("INNER PUBKEY: %s\n", tal_hexstr(tmpctx, inner_pubkey_bytes, 32)); htlc_success_script = make_eltoo_htlc_success_script(tmpctx, &settlement_pubkey, invoice_hash); - printf("HTLC Success script: %s\n", tal_hexstr(tmpctx, htlc_success_script, tal_count(htlc_success_script))); htlc_timeout_script = make_eltoo_htlc_timeout_script(tmpctx, &settlement_pubkey, 420); - printf("HTLC Timeout script: %s\n", tal_hexstr(tmpctx, htlc_timeout_script, tal_count(htlc_timeout_script))); tapleaf_scripts[0] = htlc_success_script; tapleaf_scripts[1] = htlc_timeout_script; compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 2); @@ -658,7 +650,6 @@ static int test_htlc_output_creation(void) /* Size of OP_1 script in hex output*/ assert(tal_count(taproot_script) == 1+1+32); tap_hex = tal_hexstr(tmpctx, taproot_script, tal_count(taproot_script)); - printf("Taproot script: %s\n", tap_hex); assert(tal_count(tap_hex) == (1+1+32)*2 + 1); assert(!memcmp(tap_hex, hex_script, tal_count(tap_hex))); return 0; diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 1f559fe29ccb..5e201f377b44 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -77,16 +77,15 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * /* Now the the transaction itself is determined, we must compute the APO sighash to inject it into the inputs' tapscript, then attach the information to the PSBT */ settle_and_update_tapscripts[0] = make_eltoo_settle_script(tmpctx, tx, input_num); - printf("SETTLE: %s\n", tal_hexstr(tmpctx, settle_and_update_tapscripts[0], tal_count(settle_and_update_tapscripts[0]))); + /* update number is one more for the update path, which isn't being taken */ settle_and_update_tapscripts[1] = make_eltoo_update_script(tmpctx, obscured_update_number + 1); - printf("UPDATE: %s\n", tal_hexstr(tmpctx, settle_and_update_tapscripts[1], tal_count(settle_and_update_tapscripts[1]))); + assert(settle_and_update_tapscripts[0]); assert(settle_and_update_tapscripts[1]); /* We need to calculate the merkle root to figure the parity bit */ compute_taptree_merkle_root(&update_merkle_root, settle_and_update_tapscripts, /* num_scripts */ 2); - printf("TAP MERK ROOT: %s\n", tal_hexstr(tmpctx, update_merkle_root.u.u32, 32)); bipmusig_finalize_keys(&update_agg_pk, &update_keyagg_cache, pubkey_ptrs, @@ -94,11 +93,8 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * &update_merkle_root, update_tap_tweak); - printf("TAPTWEAK: %s\n", tal_hexstr(tmpctx, update_tap_tweak, 32)); parity_bit = pubkey_parity(&update_agg_pk); - printf("PARITY BIT: %d\n", parity_bit); control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], /* annex_hint */ NULL, inner_pubkey, parity_bit); - printf("CBLOCK: %s\n", tal_hexstr(tmpctx, control_block, tal_count(control_block))); script_pubkey = scriptpubkey_p2tr(tmpctx, &update_agg_pk); /* Remove and re-add with updated information */ diff --git a/common/update_tx.c b/common/update_tx.c index b7e6059b5741..2df0e51d031a 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -43,10 +43,8 @@ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) preimage_cursor += tapscript_len; assert(tal_count(tapleaf_preimage) == preimage_cursor - tapleaf_preimage); - printf("***ANNEX PREIMAGE***: %s\n", tal_hexstr(tmpctx, tapleaf_preimage, tal_count(tapleaf_preimage))); ok = wally_tagged_hash(tapleaf_preimage, tal_count(tapleaf_preimage), "TapLeaf", result.u.u8); assert(ok == WALLY_OK); - printf("TAPLEAF HASH(annex): %s\n", tal_hexstr(tmpctx, result.u.u8, 32)); annex[0] = 0x50; /* annex flag */ memcpy(annex + 1, result.u.u8, sizeof(result)); From c880d710454f003155dd8bbd5a7c0d5a11ae25a7 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 26 Jul 2022 15:32:49 -0400 Subject: [PATCH 083/283] Outpoint doesnt make sense to set for non-initial settlement tx --- channeld/settle_tx.c | 11 +++++++++-- channeld/settle_tx.h | 1 - channeld/test/run-settle_tx.c | 2 +- common/initial_settlement_tx.c | 2 +- common/initial_settlement_tx.h | 6 +++--- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 2329601793b7..7f848369578d 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -94,7 +94,7 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, } struct bitcoin_tx *settle_tx(const tal_t *ctx, - const struct bitcoin_outpoint *update_outpoint, + const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, u16 shared_delay, const struct eltoo_keyset *eltoo_keyset, @@ -115,6 +115,13 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, *dummy_to_remote = (struct htlc *)0x02; secp256k1_xonly_pubkey inner_pubkey; const struct pubkey *pubkey_ptrs[2]; + /* For non-initial settlement tx, we cannot safely + * predict prevout, we will rebind this last second, + * so just put something in to satisfy PSBT et al + */ + struct bitcoin_outpoint dummy_update_outpoint; + memset(dummy_update_outpoint.txid.shad.sha.u.u8, 0, 32); + dummy_update_outpoint.n = 0; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); @@ -246,7 +253,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, * * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured settlement number */ - add_settlement_input(tx, update_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); + add_settlement_input(tx, &dummy_update_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); /* Identify the direct outputs (to_us, to_them). */ if (direct_outputs != NULL) { diff --git a/channeld/settle_tx.h b/channeld/settle_tx.h index 8a6a767fa5c5..228b84648b94 100644 --- a/channeld/settle_tx.h +++ b/channeld/settle_tx.h @@ -38,7 +38,6 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, /** * settle_tx: create (unsigned) settlement tx to spend the funding tx output * @ctx: context to allocate transaction and @htlc_map from. - * @update_outpoint, @update_outpoint_sats: funding outpoint and amount * @shared_delay: delay before this settlement transaction can be included in a block * @eltoo_keyset: keys derived for this settle tx. * @dust_limit: dust limit below which to trim outputs. diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index aedbe16f58a0..4079e5c87b9e 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -57,7 +57,7 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4a2229690aa611abee255baf9c628da8e0fab458573e5745585718ed0e0b4f3740065cd1d"; +char regression_tx_hex[] = "02000000000101000000000000000000000000000000000000000000000000000000000000000000000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4a2229690aa611abee255baf9c628da8e0fab458573e5745585718ed0e0b4f3740065cd1d"; static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 5e201f377b44..593ded659b17 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -66,7 +66,7 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * /* * We do not know what scriptPubKey, tap_tree look like yet because we're computing - * a sighash to then put into the input sciript. We pass in dummies + * a sighash to then put into the input script. We pass in dummies * where necessary for now. */ dummy_script = bitcoin_spk_ephemeral_anchor(tmpctx); diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 3a78cebf0e8a..b552cd06712b 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -16,7 +16,7 @@ struct wally_tx_output; /** * initial_settlement_tx: create (unsigned) update tx to spend the first update tx * @ctx: context to allocate transaction and @htlc_map from. - * @funding, @funding_sats: funding outpoint and amount + * @update_outpoint, @update_outpoint_sats: funding outpoint and amount * @shared_delay: delay before this settlement transaction can be included in a block * @eltoo_keyset: keys for the update and settlement outputs. * @dust_limit: dust limit below which to trim outputs. @@ -29,8 +29,8 @@ struct wally_tx_output; * */ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, - const struct bitcoin_outpoint *update_output, - struct amount_sat update_output_sats, + const struct bitcoin_outpoint *update_outpoint, + struct amount_sat update_outpoint_sats, u32 shared_delay, const struct eltoo_keyset *eltoo_keyset, struct amount_sat dust_limit, From c3e3a773323491989ab48ee97ce8e2885103b114 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 26 Jul 2022 16:40:26 -0400 Subject: [PATCH 084/283] Checkin --- channeld/test/run-settle_tx.c | 287 ++++++++++++++++++++++++++++------ 1 file changed, 238 insertions(+), 49 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 4079e5c87b9e..90d52bd46e2f 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -97,6 +97,63 @@ static struct secret secret_from_hex(const char *hex) return s; } +static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *alice_privkey, struct privkey *bob_privkey, secp256k1_xonly_pubkey *xo_inner_pubkey) +{ + u8 *final_sig; + secp256k1_musig_keyagg_cache keyagg_cache[2]; + const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; + struct sha256_double msg_out; + secp256k1_musig_session session[2]; + const secp256k1_musig_partial_sig *p_sig_ptrs[2]; + secp256k1_musig_partial_sig p_sigs[2]; + struct bip340sig sig; + int i; + bool ok; + secp256k1_musig_secnonce secnonce[2]; + secp256k1_musig_pubnonce pubnonces[2]; + + for (i=0; i<2; ++i){ + + /* "Presharing" nonces here */ + bipmusig_gen_nonce(&secnonce[i], + &pubnonces[i], + (i == 0) ? alice_privkey : bob_privkey, + &keyagg_cache[i], + /* msg32 */ NULL); + pubnonce_ptrs[i] = &pubnonces[i]; + } + + for (i=0; i<2; ++i){ + bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &msg_out); + bipmusig_partial_sign((i == 0) ? alice_privkey : bob_privkey, + &secnonce[i], + pubnonce_ptrs, + 2, + msg_out.sha.u.u8, /* FIXME harmonize this to sha256_double */ + &keyagg_cache[i], + &session[i], + &p_sigs[i]); + p_sig_ptrs[i] = &p_sigs[i]; + } + + /* Finally, combine sig */ + for (i=0; i<2; ++i){ + ok = bipmusig_partial_sigs_combine_verify(p_sig_ptrs, + 2, + xo_inner_pubkey, + &session[i], + &msg_out, + &sig); + assert(ok); + } + + final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); + memcpy(final_sig, sig.u8, sizeof(sig.u8)); + /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ + final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; + return final_sig; +} + static void tx_must_be_eq(const struct bitcoin_tx *a, const struct bitcoin_tx *b) { @@ -433,8 +490,13 @@ static int test_settlement_tx(void) return 0; } -static int test_initial_settlement_tx(void) +static int test_invalid_update_tx(void) { + /* Exercise the code when >1 state + * update is authorized, and an invalidated + * update tx is posted. + */ + struct bitcoin_outpoint update_output; struct amount_sat update_output_sats; u32 shared_delay; @@ -446,7 +508,7 @@ static int test_initial_settlement_tx(void) u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ char* err_reason; - struct bitcoin_tx *tx, *tx_cmp, *update_tx; + struct bitcoin_tx *tx, *tx_cmp, *update_tx, *settle_tx_1, *update_tx_1_A; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; char *psbt_b64; @@ -458,15 +520,7 @@ static int test_initial_settlement_tx(void) /* MuSig signing stuff */ secp256k1_xonly_pubkey xo_inner_pubkey; - secp256k1_musig_secnonce secnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; - secp256k1_musig_pubnonce pubnonces[2]; - struct sha256_double msg_out; - const secp256k1_musig_partial_sig *p_sig_ptrs[2]; - secp256k1_musig_partial_sig p_sigs[2]; - struct bip340sig sig; - secp256k1_musig_session session[2]; - u8 *annex; + u8 *annex_0, *annex_1; u8 *final_sig; /* Test initial settlement tx */ @@ -517,7 +571,7 @@ static int test_initial_settlement_tx(void) &err_reason); psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); - printf("Initial Settlement psbt: %s\n", psbt_b64); + printf("Settlement psbt 0: %s\n", psbt_b64); /* Regression test vector for now */ tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); @@ -538,52 +592,183 @@ static int test_initial_settlement_tx(void) &xo_inner_pubkey, &err_reason); + /* Signing happens next */ + annex_0 = make_eltoo_annex(tmpctx, tx); + final_sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey); + + /* Re-bind, add final script/tapscript info into PSBT */ + bind_update_tx_to_funding_outpoint(update_tx, + tx, + &update_output, + &eltoo_keyset, + &xo_inner_pubkey, + final_sig); + psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); - printf("Unbound update psbt: %s\n", psbt_b64); + printf("Update transaction 0: %s\n", psbt_b64); - /* Signing happens next */ + /* Go to second update, Bob gets paid */ + obscured_update_number++; + self_pay.millisatoshis -= 1000; + other_pay.millisatoshis += 1000; - /* Generate signing session for "both sides" */ - for (i=0; i<2; ++i){ + settle_tx_1 = settle_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + /* htlcs */ NULL, + /* htlc_map */ NULL, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); - /* "Presharing" nonces here */ - bipmusig_gen_nonce(&secnonce[i], - &pubnonces[i], - (i == 0) ? &alice_funding_privkey : &bob_funding_privkey, - &keyagg_cache[i], - /* msg32 */ NULL); - pubnonce_ptrs[i] = &pubnonces[i]; - } + assert(settle_tx_1); - annex = make_eltoo_annex(tmpctx, tx); - for (i=0; i<2; ++i){ - bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &msg_out); - bipmusig_partial_sign((i == 0) ? &alice_funding_privkey : &bob_funding_privkey, - &secnonce[i], - pubnonce_ptrs, - 2, - msg_out.sha.u.u8, /* FIXME harmonize this to sha256_double */ + /* Will be bound to funding output */ + update_tx_1_A = unbound_update_tx(tmpctx, + settle_tx_1, + update_output_sats, + &xo_inner_pubkey, + &err_reason); + + /* Authorize this next state update */ + annex_1 = make_eltoo_annex(tmpctx, settle_tx_1); + final_sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey); + + /* This can RBF the first update tx */ + bind_update_tx_to_funding_outpoint(update_tx_1_A, + settle_tx_1, + &update_output, + &eltoo_keyset, + &xo_inner_pubkey, + final_sig); + + psbt_b64 = psbt_to_b64(tmpctx, update_tx_1_A->psbt); + printf("Update transaction 1A(funding output): %s\n", psbt_b64); + + /* Re-bind same transaction and signature to non-funding output? */ + bind_update_tx_to_update_outpoint(update_tx_1_A, + settle_tx_1, + &update_output, /* FIXME should be update_tx's first output */ + &eltoo_keyset, + annex_0, /* annex you see on chain */ + obscured_update_number - 1, /* locktime you see on old update tx */ + &xo_inner_pubkey, + final_sig); + + psbt_b64 = psbt_to_b64(tmpctx, update_tx_1_A->psbt); + printf("Update transaction 1B(update output): %s\n", psbt_b64); + + return 0; +} + + +static int test_initial_settlement_tx(void) +{ + struct bitcoin_outpoint update_output; + struct amount_sat update_output_sats; + u32 shared_delay; + struct eltoo_keyset eltoo_keyset; + struct amount_sat dust_limit; + struct amount_msat self_pay; + struct amount_msat other_pay; + struct amount_sat self_reserve; + u32 obscured_update_number; + /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ + char* err_reason; + struct bitcoin_tx *tx, *tx_cmp, *update_tx; + struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; + int ok; + char *psbt_b64; + + /* Aggregation stuff */ + secp256k1_musig_keyagg_cache keyagg_cache[2]; + const struct pubkey *pubkey_ptrs[2]; + int i; + + /* MuSig signing stuff */ + secp256k1_xonly_pubkey xo_inner_pubkey; + u8 *annex; + u8 *final_sig; + + /* Test initial settlement tx */ + + update_output.txid = txid_from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be"); + update_output.n = 0; + update_output_sats.satoshis = 69420; + + alice_funding_privkey.secret = secret_from_hex("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901"); + bob_funding_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); + + ok = pubkey_from_privkey(&alice_funding_privkey, + &eltoo_keyset.self_funding_key); + ok = pubkey_from_privkey(&bob_funding_privkey, + &eltoo_keyset.other_funding_key); + + shared_delay = 42; + + alice_settle_privkey.secret = secret_from_hex("1111111111111111111111111111111111111111111111111111111111111111"); + bob_settle_privkey.secret = secret_from_hex("2222222222222222222222222222222222222222222222222222222222222222"); + + ok = pubkey_from_privkey(&alice_settle_privkey, + &eltoo_keyset.self_settle_key); + ok = pubkey_from_privkey(&bob_settle_privkey, + &eltoo_keyset.other_settle_key); + assert(ok); + + pubkey_ptrs[0] = &eltoo_keyset.self_funding_key; + pubkey_ptrs[1] = &eltoo_keyset.other_funding_key; + + dust_limit.satoshis = 294; + self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; + other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; + self_reserve.satoshis = 0; /* not testing this yet since it's really layer violation here */ + obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ + + tx = initial_settlement_tx(tmpctx, + &update_output, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + self_reserve, + obscured_update_number, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + &err_reason); + + psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); + printf("Initial Settlement psbt: %s\n", psbt_b64); + + /* Regression test vector for now */ + tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); + tx_must_be_eq(tx, tx_cmp); + + /* Calculate inner pubkey, caches reused at end for tapscript signing */ + for (i=0; i<2; ++i) { + bipmusig_inner_pubkey(&xo_inner_pubkey, &keyagg_cache[i], - &session[i], - &p_sigs[i]); - p_sig_ptrs[i] = &p_sigs[i]; + pubkey_ptrs, + /* n_pubkeys */ 2); } - /* Finally, combine sig */ - for (i=0; i<2; ++i){ - ok = bipmusig_partial_sigs_combine_verify(p_sig_ptrs, - 2, - &xo_inner_pubkey, - &session[i], - &msg_out, - &sig); - assert(ok); - } + /* Will be bound later */ + update_tx = unbound_update_tx(tmpctx, + tx, + update_output_sats, + &xo_inner_pubkey, + &err_reason); - final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); - memcpy(final_sig, sig.u8, sizeof(sig.u8)); - /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ - final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; + psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); + printf("Unbound update psbt: %s\n", psbt_b64); + + /* Signing happens next */ + annex = make_eltoo_annex(tmpctx, tx); + final_sig = musig_sign(update_tx, annex, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey); /* We want to close the channel without cooperation... time to rebind and finalize */ @@ -670,6 +855,10 @@ int main(int argc, const char *argv[]) assert(!err); err |= test_settlement_tx(); + assert(!err); + + err |= test_invalid_update_tx(); + assert(!err); common_shutdown(); From 84f79b5fd106418d42ca2b826ae1e0eab6b67de9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 26 Jul 2022 16:56:43 -0400 Subject: [PATCH 085/283] Compiling through --- bitcoin/script.c | 2 +- channeld/test/run-settle_tx.c | 20 ++++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 186b922f9b78..f6eb94ff290b 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1033,7 +1033,7 @@ void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, co size_t script_len = tal_count(update_tapscript); unsigned char *p = tag_hash_buf; - assert(tal_count(invalidated_annex_hint) == 32 && invalidated_annex_hint[0] == 0x50); + assert(tal_count(invalidated_annex_hint) == 33 && invalidated_annex_hint[0] == 0x50); /* Let k0 = hashTapLeaf(v || compact_size(size of s) || s); also call it the tapleaf hash. */ p[0] = leaf_version; diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 90d52bd46e2f..52307d7fe422 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -57,7 +57,7 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -char regression_tx_hex[] = "02000000000101000000000000000000000000000000000000000000000000000000000000000000000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4a2229690aa611abee255baf9c628da8e0fab458573e5745585718ed0e0b4f3740065cd1d"; +char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4a2229690aa611abee255baf9c628da8e0fab458573e5745585718ed0e0b4f3740065cd1d"; static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { @@ -97,10 +97,9 @@ static struct secret secret_from_hex(const char *hex) return s; } -static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *alice_privkey, struct privkey *bob_privkey, secp256k1_xonly_pubkey *xo_inner_pubkey) +static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *alice_privkey, struct privkey *bob_privkey, secp256k1_xonly_pubkey *xo_inner_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache) { u8 *final_sig; - secp256k1_musig_keyagg_cache keyagg_cache[2]; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; struct sha256_double msg_out; secp256k1_musig_session session[2]; @@ -309,7 +308,7 @@ static int test_settlement_tx(void) struct amount_msat other_pay; u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ - struct bitcoin_tx *tx, *tx_cmp; + struct bitcoin_tx *tx; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; char *tx_hex; @@ -367,10 +366,6 @@ static int test_settlement_tx(void) psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); printf("Settlement psbt: %s\n", psbt_b64); - /* Regression test vector for now */ - tx_cmp = bitcoin_tx_from_hex(tmpctx, regression_tx_hex, sizeof(regression_tx_hex)-1); - tx_must_be_eq(tx, tx_cmp); - assert(tx->wtx->locktime == obscured_update_number + 500000000); obscured_update_number = 1234; @@ -512,6 +507,7 @@ static int test_invalid_update_tx(void) struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; char *psbt_b64; + const struct htlc **htlc_map; /* Aggregation stuff */ secp256k1_musig_keyagg_cache keyagg_cache[2]; @@ -594,7 +590,7 @@ static int test_invalid_update_tx(void) /* Signing happens next */ annex_0 = make_eltoo_annex(tmpctx, tx); - final_sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey); + final_sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey, keyagg_cache); /* Re-bind, add final script/tapscript info into PSBT */ bind_update_tx_to_funding_outpoint(update_tx, @@ -621,7 +617,7 @@ static int test_invalid_update_tx(void) self_pay, other_pay, /* htlcs */ NULL, - /* htlc_map */ NULL, + &htlc_map, /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, obscured_update_number); @@ -636,7 +632,7 @@ static int test_invalid_update_tx(void) /* Authorize this next state update */ annex_1 = make_eltoo_annex(tmpctx, settle_tx_1); - final_sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey); + final_sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey, keyagg_cache); /* This can RBF the first update tx */ bind_update_tx_to_funding_outpoint(update_tx_1_A, @@ -768,7 +764,7 @@ static int test_initial_settlement_tx(void) /* Signing happens next */ annex = make_eltoo_annex(tmpctx, tx); - final_sig = musig_sign(update_tx, annex, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey); + final_sig = musig_sign(update_tx, annex, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey, keyagg_cache); /* We want to close the channel without cooperation... time to rebind and finalize */ From e454e0c017945118348c2ff23bec0294a3fee47d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 27 Jul 2022 09:28:28 -0400 Subject: [PATCH 086/283] Print out 2nd settlement tx --- channeld/test/run-settle_tx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 52307d7fe422..aea9a701c769 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -623,6 +623,9 @@ static int test_invalid_update_tx(void) assert(settle_tx_1); + psbt_b64 = psbt_to_b64(tmpctx, settle_tx_1->psbt); + printf("Settlement psbt 1: %s\n", psbt_b64); + /* Will be bound to funding output */ update_tx_1_A = unbound_update_tx(tmpctx, settle_tx_1, From 1fd630f90fc50ff09d917bd9e0ffa6c87ed16e73 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 27 Jul 2022 11:14:10 -0400 Subject: [PATCH 087/283] Spec wrong, and me being wrong... --- bitcoin/script.c | 2 +- common/update_tx.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index f6eb94ff290b..8d595b363855 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1179,7 +1179,7 @@ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num) add_op(&script, OP_1); add_op(&script, OP_CHECKSIGVERIFY); add_number(&script, 500000000 + update_num); - add_op(&script, OP_CHECKSEQUENCEVERIFY); + add_op(&script, OP_CHECKLOCKTIMEVERIFY); return script; } diff --git a/common/update_tx.c b/common/update_tx.c index 2df0e51d031a..fc8220faad5f 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -147,7 +147,12 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); /* FIXME embed this in PSBT as well... */ - update_tapscript = make_eltoo_update_script(tmpctx, invalidated_update_number); + /* We are regenerating the the witness stack for the latest published state + * which locks coins to that state + 1 + * + * * tapscript: EXPR_UPDATE(m+1) + */ + update_tapscript = make_eltoo_update_script(tmpctx, invalidated_update_number + 1); compute_taptree_merkle_root_with_hint(&psbt_tap_merkle_root, update_tapscript, invalidated_annex_hint); From 6dda4cd160c45d2081ed0c2bbbee9b6195770f1e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 27 Jul 2022 11:15:48 -0400 Subject: [PATCH 088/283] F --- channeld/test/run-settle_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index aea9a701c769..30fb6c3867c4 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -57,7 +57,7 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c0442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4a2229690aa611abee255baf9c628da8e0fab458573e5745585718ed0e0b4f3740065cd1d"; +char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4b4d868d7231ff3d15775dbd01acf0051b86eccd1f1139772222152b32986c4df0065cd1d"; static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { From 6b8f0427a0a07a333bb3d360a6f39d444db7a069 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 2 Aug 2022 11:17:39 -0400 Subject: [PATCH 089/283] Check in work --- common/channel_config.c | 23 ++++++ common/channel_config.h | 55 ++++++++++++++ common/initial_eltoo_channel.c | 130 +++++++++++++++++++++++++++++++++ common/initial_eltoo_channel.h | 130 +++++++++++++++++++++++++++++++++ common/keyset.h | 3 +- 5 files changed, 339 insertions(+), 2 deletions(-) create mode 100644 common/initial_eltoo_channel.c create mode 100644 common/initial_eltoo_channel.h diff --git a/common/channel_config.c b/common/channel_config.c index 55e32ae6dc66..865ff916530a 100644 --- a/common/channel_config.c +++ b/common/channel_config.c @@ -24,3 +24,26 @@ void fromwire_channel_config(const u8 **ptr, size_t *max, config->max_accepted_htlcs = fromwire_u16(ptr, max); config->max_dust_htlc_exposure_msat = fromwire_amount_msat(ptr, max); } + +void towire_eltoo_channel_config(u8 **pptr, const struct eltoo_channel_config *config) +{ + towire_amount_sat(pptr, config->dust_limit); + towire_amount_msat(pptr, config->max_htlc_value_in_flight); + towire_amount_sat(pptr, config->channel_reserve); + towire_amount_msat(pptr, config->htlc_minimum); + towire_u16(pptr, config->shared_delay); + towire_u16(pptr, config->max_accepted_htlcs); + towire_amount_msat(pptr, config->max_dust_htlc_exposure_msat); +} + +void fromwire_eltoo_channel_config(const u8 **ptr, size_t *max, + struct eltoo_channel_config *config) +{ + config->dust_limit = fromwire_amount_sat(ptr, max); + config->max_htlc_value_in_flight = fromwire_amount_msat(ptr, max); + config->channel_reserve = fromwire_amount_sat(ptr, max); + config->htlc_minimum = fromwire_amount_msat(ptr, max); + config->shared_delay = fromwire_u16(ptr, max); + config->max_accepted_htlcs = fromwire_u16(ptr, max); + config->max_dust_htlc_exposure_msat = fromwire_amount_msat(ptr, max); +} diff --git a/common/channel_config.h b/common/channel_config.h index fb74a4998c01..42e96afd2325 100644 --- a/common/channel_config.h +++ b/common/channel_config.h @@ -82,4 +82,59 @@ struct channel_config { void towire_channel_config(u8 **pptr, const struct channel_config *config); void fromwire_channel_config(const u8 **ptr, size_t *max, struct channel_config *config); + +struct eltoo_channel_config { + /* Database ID */ + u64 id; + /* BOLT #2: + * + * `dust_limit_satoshis` is the threshold below which outputs should + * not be generated for this node's commitment or HTLC transaction + */ + struct amount_sat dust_limit; + + /* BOLT #2: + * + * `max_htlc_value_in_flight_msat` is a cap on total value of + * outstanding HTLCs, which allows a node to limit its exposure to + * HTLCs */ + struct amount_msat max_htlc_value_in_flight; + + /* BOLT #2: + * + * `channel_reserve_satoshis` is the minimum amount that the other + * node is to keep as a direct payment. */ + struct amount_sat channel_reserve; + + /* BOLT #2: + * + * `htlc_minimum_msat` indicates the smallest value HTLC this node + * will accept. + */ + struct amount_msat htlc_minimum; + + /* BOLT #2: + * + * `to_self_delay` is replaced with a symmetrical `shared_delay` which + * must be agreed upon by nodes. This is currently set by the opener. + */ + u16 shared_delay; + + /* BOLT #2: + * + * similarly, `max_accepted_htlcs` limits the number of outstanding + * HTLCs the other node can offer. */ + u16 max_accepted_htlcs; + + /* BOLT-TBD #X + * + * maximum dust exposure allowed for this channel + */ + struct amount_msat max_dust_htlc_exposure_msat; +}; + +void towire_eltoo_channel_config(u8 **pptr, const struct eltoo_channel_config *config); +void fromwire_eltoo_channel_config(const u8 **ptr, size_t *max, + struct eltoo_channel_config *config); + #endif /* LIGHTNING_COMMON_CHANNEL_CONFIG_H */ diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c new file mode 100644 index 000000000000..99e5eac5b47d --- /dev/null +++ b/common/initial_eltoo_channel.c @@ -0,0 +1,130 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct channel *new_initial_eltoo_channel(const tal_t *ctx, + const struct channel_id *cid, + const struct bitcoin_outpoint *funding, + u32 minimum_depth, + const struct height_states *height_states TAKES, + struct amount_sat funding_sats, + struct amount_msat local_msatoshi, + const struct channel_config *local, + const struct channel_config *remote, + const struct pubkey *local_funding_pubkey, + const struct pubkey *remote_funding_pubkey, + const struct pubkey *local_settle_pubkey, + const struct pubkey *remote_settle_pubkey, + const struct channel_type *type TAKES, + bool option_wumbo, + enum side opener) +{ + struct eltoo_channel *channel = tal(ctx, struct channel); + struct amount_msat remote_msatoshi; + + channel->cid = *cid; + channel->funding = *funding; + channel->funding_sats = funding_sats; + channel->minimum_depth = minimum_depth; + if (!amount_sat_sub_msat(&remote_msatoshi, + channel->funding_sats, local_msatoshi)) + return tal_free(channel); + + channel->opener = opener; + channel->config[LOCAL] = *local; + channel->config[REMOTE] = *remote; + channel->eltoo_keyset->self_funding_key = *local_funding_pubkey; + channel->eltoo_keyset->other_funding_key = *remote_funding_pubkey; + channel->eltoo_keyset->self_settle_key = *local_settle_pubkey; + channel->eltoo_keyset->other_settle_key = *remote_settle_pubkey; + channel->htlcs = NULL; + + channel->view[LOCAL].owed[LOCAL] + = channel->view[REMOTE].owed[LOCAL] + = local_msatoshi; + channel->view[REMOTE].owed[REMOTE] + = channel->view[LOCAL].owed[REMOTE] + = remote_msatoshi; + + channel->update_number_obscurer + = 0; + + channel->option_wumbo = option_wumbo; + /* takes() if necessary */ + channel->type = tal_dup(channel, struct channel_type, type); + + return channel; +} + +struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, + const struct eltoo_channel *channel, + struct wally_tx_output *direct_outputs[NUM_SIDES], + char** err_reason) +{ + struct bitcoin_tx *init_settle_tx; + + /* This assumes no HTLCs! */ + assert(!channel->htlcs); + + init_settle_tx = initial_settlement_tx(ctx, + &channel->funding, + channel->funding_sats, + channel->config.shared_delay, + channel->eltoo_keyset, + channel->config.dust_limit, + channel->view.owed[LOCAL], + channel->view.owed[REMOTE], + channel->config.channel_reserve, + 0 ^ channel->commitment_number_obscurer, + direct_outputs, + err_reason); + + if (init_settle_tx) { + psbt_input_add_pubkey(init_settle_tx->psbt, 0, + &channel->eltoo_keyset->self_funding_key); + psbt_input_add_pubkey(init_settle_tx->psbt, 0, + &channel->eltoo_keyset->other_funding_key); + } + + return init_settle_tx; +} + +struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, + const struct bitcoin_tx *settle_tx, + const struct eltoo_channel *channel, + char** err_reason) +{ + struct bitcoin_tx *init_update_tx; + /* This should be gathered from settle_tx PSBT when stored there, + * it's generated in initial_settlement_tx. This is unused otherwise. + */ + secp256k1_xonly_pubkey dummy_inner_pubkey; + + /* This assumes no HTLCs! */ + assert(!channel->htlcs); + + init_update_tx = unbound_update_tx(ctx, + settle_tx, + channel->funding_sats, + &dummy_inner_pubkey, + err_reason); + + if (init_update_tx) { + psbt_input_add_pubkey(init_update_tx->psbt, 0, + &channel->eltoo_keyset->self_funding_key); + psbt_input_add_pubkey(init_update_tx->psbt, 0, + &channel->eltoo_keyset->other_funding_key); + } + + return init_update_tx; +} +/* Magic comment. */ +REGISTER_TYPE_TO_STRING(channel, fmt_channel); diff --git a/common/initial_eltoo_channel.h b/common/initial_eltoo_channel.h new file mode 100644 index 000000000000..fdd53d956b8f --- /dev/null +++ b/common/initial_eltoo_channel.h @@ -0,0 +1,130 @@ +/* This represents a channel with no HTLCs: all that's required for openingd. */ +#ifndef LIGHTNING_COMMON_INITIAL_CHANNEL_H +#define LIGHTNING_COMMON_INITIAL_CHANNEL_H +#include "config.h" + +#include +#include +#include +#include +#include + +struct signature; +struct added_htlc; +struct failed_htlc; +struct fulfilled_htlc; + +/* View from each side */ +struct channel_view { + /* How much is owed to each side (includes pending changes) */ + struct amount_msat owed[NUM_SIDES]; +}; + +struct eltoo_channel { + + /* The id for this channel */ + struct channel_id cid; + + /* Funding txid and output. */ + struct bitcoin_outpoint funding; + + /* Keys used for the lifetime of the channel */ + struct eltoo_keyset; + + /* satoshis in from commitment tx */ + struct amount_sat funding_sats; + + /* confirmations needed for locking funding */ + u32 minimum_depth; + + /* Who is paying fees. */ + enum side opener; + + /* Limits and settings on this channel. */ + struct channel_config config; + + /* Mask for obscuring the encoding of the update number. */ + u32 update_number_obscurer; + + /* All live HTLCs for this channel */ + struct htlc_map *htlcs; + + /* What it looks like to nodes. */ + struct channel_view view; + + /* Features which apply to this channel. */ + struct channel_type *type; + + /* Are we using big channels? */ + bool option_wumbo; + +}; + +/** + * new_initial_channel: Given initial funding, what is initial state? + * @ctx: tal context to allocate return value from. + * @cid: The channel's id. + * @funding: The commitment transaction id/outnum + * @minimum_depth: The minimum confirmations needed for funding transaction. + * @funding_sats: The commitment transaction amount. + * @local_msatoshi: The amount for the local side (remainder goes to remote) + * @local: local channel configuration + * @remote: remote channel configuration + * @local_funding_pubkey: local funding key + * @remote_funding_pubkey: remote funding key + * @local_settle_pubkey: local settlement key + * @remote_settle_key: remote settlement key + * @type: type for this channel + * @option_wumbo: has peer currently negotiated wumbo? + * @opener: which side initiated it. + * + * Returns channel, or NULL if malformed. + */ +struct channel *new_initial_eltoo_channel(const tal_t *ctx, + const struct channel_id *cid, + const struct bitcoin_outpoint *funding, + u32 minimum_depth, + struct amount_sat funding_sats, + struct amount_msat local_msatoshi, + const struct channel_config *local, + const struct channel_config *remote, + const struct pubkey *local_funding_pubkey, + const struct pubkey *remote_funding_pubkey, + const struct pubkey *local_settle_pubkey, + const struct pubkey *remote_settle_pubkey, + const struct channel_type *type TAKES, + bool option_wumbo, + enum side opener); + +/** + * initial_settle_channel_tx: Get the current settlement tx for the *empty* channel. + * @ctx: tal context to allocate return value from. + * @channel: The channel to evaluate + * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). + * @err_reason: When NULL is returned, this will point to a human readable reason. + * + * Returns the fully signed settlement transaction, or NULL + * if the channel size was insufficient to cover reserves. + */ +struct bitcoin_tx *initial_eltoo_channel_tx(const tal_t *ctx, + const struct eltoo_channel *channel, + struct wally_tx_output *direct_outputs[NUM_SIDES], + char** err_reason); + +/** + * initial_update_channel_tx: Get the current update tx for the *empty* channel. Must be called + * *after* initial_eltoo_channel_tx. + * @ctx: tal context to allocate return value from. + * @settle_tx: The settlement transaction to commit to + * @channel: The channel to evaluate + * @err_reason: When NULL is returned, this will point to a human readable reason. + * + * Returns the fully signed settlement transaction, or NULL + * if the channel size was insufficient to cover reserves. + */ +struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, + const struct bitcoin_tx *settle_tx, + const struct eltoo_channel *channel, + char** err_reason); + +#endif /* LIGHTNING_COMMON_INITIAL_CHANNEL_H */ diff --git a/common/keyset.h b/common/keyset.h index 1fb85a54697b..4d16f0d96eb1 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -13,9 +13,8 @@ struct keyset { struct pubkey self_payment_key, other_payment_key; }; -/* Keys needed to derive a particular settlement tx. */ +/* Keys needed to derive a particular update/settlement tx pair. */ struct eltoo_keyset { - struct pubkey self_htlc_key, other_htlc_key; struct pubkey self_settle_key, other_settle_key; struct pubkey self_funding_key, other_funding_key; }; From b99ae7ea287ce2d22ba72ecde06d60d4e207e12e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 2 Aug 2022 22:21:17 -0400 Subject: [PATCH 090/283] openingd_eltoo messages compiling --- Makefile | 1 + common/initial_eltoo_channel.c | 47 +++++++------- common/initial_eltoo_channel.h | 17 ++--- lightningd/.gitignore | 1 + openingd/Makefile | 25 ++++++-- openingd/eltoo_openingd_wire.csv | 103 +++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 37 deletions(-) create mode 100644 openingd/eltoo_openingd_wire.csv diff --git a/Makefile b/Makefile index 8eea1ec2aeab..79024a17133b 100644 --- a/Makefile +++ b/Makefile @@ -392,6 +392,7 @@ PKGLIBEXEC_PROGRAMS = \ lightningd/lightning_hsmd \ lightningd/lightning_onchaind \ lightningd/lightning_openingd \ + lightningd/lightning_eltoo_openingd \ lightningd/lightning_websocketd # Don't delete these intermediaries. diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index 99e5eac5b47d..b4e678c7a261 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -5,20 +5,20 @@ #include #include #include -#include -#include +#include +#include #include #include +#include -struct channel *new_initial_eltoo_channel(const tal_t *ctx, +struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, - const struct height_states *height_states TAKES, struct amount_sat funding_sats, struct amount_msat local_msatoshi, - const struct channel_config *local, - const struct channel_config *remote, + const struct eltoo_channel_config *local, + const struct eltoo_channel_config *remote, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, @@ -27,7 +27,7 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, bool option_wumbo, enum side opener) { - struct eltoo_channel *channel = tal(ctx, struct channel); + struct eltoo_channel *channel = tal(ctx, struct eltoo_channel); struct amount_msat remote_msatoshi; channel->cid = *cid; @@ -41,10 +41,10 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, channel->opener = opener; channel->config[LOCAL] = *local; channel->config[REMOTE] = *remote; - channel->eltoo_keyset->self_funding_key = *local_funding_pubkey; - channel->eltoo_keyset->other_funding_key = *remote_funding_pubkey; - channel->eltoo_keyset->self_settle_key = *local_settle_pubkey; - channel->eltoo_keyset->other_settle_key = *remote_settle_pubkey; + channel->eltoo_keyset.self_funding_key = *local_funding_pubkey; + channel->eltoo_keyset.other_funding_key = *remote_funding_pubkey; + channel->eltoo_keyset.self_settle_key = *local_settle_pubkey; + channel->eltoo_keyset.other_settle_key = *remote_settle_pubkey; channel->htlcs = NULL; channel->view[LOCAL].owed[LOCAL] @@ -77,21 +77,21 @@ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, init_settle_tx = initial_settlement_tx(ctx, &channel->funding, channel->funding_sats, - channel->config.shared_delay, - channel->eltoo_keyset, - channel->config.dust_limit, - channel->view.owed[LOCAL], - channel->view.owed[REMOTE], - channel->config.channel_reserve, - 0 ^ channel->commitment_number_obscurer, + channel->config->shared_delay, + &channel->eltoo_keyset, + channel->config->dust_limit, + channel->view->owed[LOCAL], + channel->view->owed[REMOTE], + channel->config->channel_reserve, + 0 ^ channel->update_number_obscurer, direct_outputs, err_reason); if (init_settle_tx) { psbt_input_add_pubkey(init_settle_tx->psbt, 0, - &channel->eltoo_keyset->self_funding_key); + &channel->eltoo_keyset.self_funding_key); psbt_input_add_pubkey(init_settle_tx->psbt, 0, - &channel->eltoo_keyset->other_funding_key); + &channel->eltoo_keyset.other_funding_key); } return init_settle_tx; @@ -107,6 +107,7 @@ struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, * it's generated in initial_settlement_tx. This is unused otherwise. */ secp256k1_xonly_pubkey dummy_inner_pubkey; + memset(dummy_inner_pubkey.data, 0, sizeof(dummy_inner_pubkey.data)); /* This assumes no HTLCs! */ assert(!channel->htlcs); @@ -119,12 +120,10 @@ struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, if (init_update_tx) { psbt_input_add_pubkey(init_update_tx->psbt, 0, - &channel->eltoo_keyset->self_funding_key); + &channel->eltoo_keyset.self_funding_key); psbt_input_add_pubkey(init_update_tx->psbt, 0, - &channel->eltoo_keyset->other_funding_key); + &channel->eltoo_keyset.other_funding_key); } return init_update_tx; } -/* Magic comment. */ -REGISTER_TYPE_TO_STRING(channel, fmt_channel); diff --git a/common/initial_eltoo_channel.h b/common/initial_eltoo_channel.h index fdd53d956b8f..7abcbec6d8f4 100644 --- a/common/initial_eltoo_channel.h +++ b/common/initial_eltoo_channel.h @@ -8,6 +8,7 @@ #include #include #include +#include struct signature; struct added_htlc; @@ -29,7 +30,7 @@ struct eltoo_channel { struct bitcoin_outpoint funding; /* Keys used for the lifetime of the channel */ - struct eltoo_keyset; + struct eltoo_keyset eltoo_keyset; /* satoshis in from commitment tx */ struct amount_sat funding_sats; @@ -41,7 +42,7 @@ struct eltoo_channel { enum side opener; /* Limits and settings on this channel. */ - struct channel_config config; + struct eltoo_channel_config config[NUM_SIDES]; /* Mask for obscuring the encoding of the update number. */ u32 update_number_obscurer; @@ -50,7 +51,7 @@ struct eltoo_channel { struct htlc_map *htlcs; /* What it looks like to nodes. */ - struct channel_view view; + struct channel_view view[NUM_SIDES]; /* Features which apply to this channel. */ struct channel_type *type; @@ -80,14 +81,14 @@ struct eltoo_channel { * * Returns channel, or NULL if malformed. */ -struct channel *new_initial_eltoo_channel(const tal_t *ctx, +struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, struct amount_sat funding_sats, struct amount_msat local_msatoshi, - const struct channel_config *local, - const struct channel_config *remote, + const struct eltoo_channel_config *local, + const struct eltoo_channel_config *remote, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, @@ -106,14 +107,14 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, * Returns the fully signed settlement transaction, or NULL * if the channel size was insufficient to cover reserves. */ -struct bitcoin_tx *initial_eltoo_channel_tx(const tal_t *ctx, +struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, const struct eltoo_channel *channel, struct wally_tx_output *direct_outputs[NUM_SIDES], char** err_reason); /** * initial_update_channel_tx: Get the current update tx for the *empty* channel. Must be called - * *after* initial_eltoo_channel_tx. + * *after* initial_settle_channel_tx. * @ctx: tal context to allocate return value from. * @settle_tx: The settlement transaction to commit to * @channel: The channel to evaluate diff --git a/lightningd/.gitignore b/lightningd/.gitignore index 4ba7a1a9cec2..e926781cefca 100644 --- a/lightningd/.gitignore +++ b/lightningd/.gitignore @@ -8,3 +8,4 @@ lightning_hsmd lightning_onchaind lightning_openingd lightning_websocketd +lightning_eltoo_openingd diff --git a/openingd/Makefile b/openingd/Makefile index 608268399655..401f501e70ec 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -4,6 +4,10 @@ OPENINGD_HEADERS := \ openingd/common.h \ openingd/openingd_wiregen.h +OPENINGD_ELTOO_HEADERS := \ + openingd/common.h \ + openingd/eltoo_openingd_wiregen.h + DUALOPEND_HEADERS := \ openingd/common.h \ openingd/dualopend_wiregen.h @@ -11,23 +15,29 @@ DUALOPEND_HEADERS := \ OPENINGD_SRC := openingd/openingd.c \ $(OPENINGD_HEADERS:.h=.c) +OPENINGD_ELTOO_SRC := openingd/eltoo_openingd.c \ + $(OPENINGD_ELTOO_HEADERS:.h=.c) + DUALOPEND_SRC := openingd/dualopend.c \ $(DUALOPEND_HEADERS:.h=.c) OPENINGD_OBJS := $(OPENINGD_SRC:.c=.o) $(OPENINGD_OBJS): $(OPENINGD_HEADERS) +OPENINGD_ELTOO_OBJS := $(OPENINGD_ELTOO_SRC:.c=.o) +$(OPENINGD_ELTOO_OBJS): $(OPENINGD_ELTOO_HEADERS) + DUALOPEND_OBJS := $(DUALOPEND_SRC:.c=.o) $(DUALOPEND_OBJS): $(DUALOPEND_HEADERS) # Make sure these depend on everything. -ALL_C_SOURCES += $(OPENINGD_SRC) $(DUALOPEND_SRC) -ALL_C_HEADERS += $(OPENINGD_HEADERS) $(DUALOPEND_HEADERS) -ALL_PROGRAMS += lightningd/lightning_openingd lightningd/lightning_dualopend +ALL_C_SOURCES += $(OPENINGD_SRC) $(OPENINGD_ELTOO_SRC) $(DUALOPEND_SRC) +ALL_C_HEADERS += $(OPENINGD_HEADERS) $(OPENINGD_ELTOO_HEADERS) $(DUALOPEND_HEADERS) +ALL_PROGRAMS += lightningd/lightning_openingd lightningd/lightning_eltoo_openingd lightningd/lightning_dualopend # Here's what lightningd depends on -LIGHTNINGD_CONTROL_HEADERS += openingd/openingd_wiregen.h openingd/dualopend_wiregen.h -LIGHTNINGD_CONTROL_OBJS += openingd/openingd_wiregen.o openingd/dualopend_wiregen.o +LIGHTNINGD_CONTROL_HEADERS += openingd/openingd_wiregen.h openingd/eltoo_openingd_wiregen.h openingd/dualopend_wiregen.h +LIGHTNINGD_CONTROL_OBJS += openingd/openingd_wiregen.o openingd/eltoo_openingd_wiregen.o openingd/dualopend_wiregen.o # Common source we use. OPENINGD_COMMON_OBJS := \ @@ -53,6 +63,8 @@ OPENINGD_COMMON_OBJS := \ common/htlc_wire.o \ common/initial_channel.o \ common/initial_commit_tx.o \ + common/initial_eltoo_channel.o \ + common/initial_settlement_tx.o \ common/key_derive.o \ common/keyset.o \ common/lease_rates.o \ @@ -79,6 +91,7 @@ OPENINGD_COMMON_OBJS := \ common/status_wiregen.o \ common/subdaemon.o \ common/type_to_string.o \ + common/update_tx.o \ common/utils.o \ common/utxo.o \ common/version.o \ @@ -89,6 +102,8 @@ OPENINGD_COMMON_OBJS := \ lightningd/lightning_openingd: $(OPENINGD_OBJS) $(OPENINGD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS) +lightningd/lightning_eltoo_openingd: $(OPENINGD_ELTOO_OBJS) $(OPENINGD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS) + lightningd/lightning_dualopend: $(DUALOPEND_OBJS) $(OPENINGD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS) -include openingd/test/Makefile diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv new file mode 100644 index 000000000000..9eb6526d4957 --- /dev/null +++ b/openingd/eltoo_openingd_wire.csv @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include + +# Eltoo variant +msgtype,openingd_eltoo_init,6500 +# Which network are we configured for? +msgdata,openingd_eltoo_init,chainparams,chainparams, +msgdata,openingd_eltoo_init,our_features,feature_set, +msgdata,openingd_eltoo_init,their_init_features_len,u16, +msgdata,openingd_eltoo_init,their_init_features,u8,their_init_features_len +# Base configuration we'll offer (channel reserve will vary with amount) +msgdata,openingd_eltoo_init,our_config,eltoo_channel_config, +# Minimum/maximum configuration values we'll accept +msgdata,openingd_eltoo_init,max_shared_delay,u32, +msgdata,openingd_eltoo_init,min_effective_htlc_capacity_msat,amount_msat, +msgdata,openingd_eltoo_init,our_funding_pubkey,pubkey, +msgdata,openingd_eltoo_init,our_settle_pubkey,pubkey, +# Constraints in case the other end tries to open a channel. +msgdata,openingd_eltoo_init,minimum_depth,u32, +msgdata,openingd_eltoo_init,min_feerate,u32, +msgdata,openingd_eltoo_init,max_feerate,u32, +msgdata,openingd_eltoo_init,dev_temporary_channel_id,?byte,32 + +#include +# Openingd->master: we've successfully offered channel. +# This gives their psig, means we can broadcast tx: we're done. +msgtype,openingd_eltoo_funder_reply,6601 +msgdata,openingd_eltoo_funder_reply,their_config,eltoo_channel_config, +msgdata,openingd_eltoo_funder_reply,first_commit,bitcoin_tx, +msgdata,openingd_eltoo_funder_reply,first_update_psig,bitcoin_signature, +msgdata,openingd_eltoo_funder_reply,minimum_depth,u32, +msgdata,openingd_eltoo_funder_reply,remote_funding_key,pubkey, +msgdata,openingd_eltoo_funder_reply,remote_settlement_key,pubkey, +msgdata,openingd_eltoo_funder_reply,funding,bitcoin_outpoint, +msgdata,openingd_eltoo_funder_reply,our_channel_reserve_satoshis,amount_sat, +msgdata,openingd_eltoo_funder_reply,shutdown_len,u16, +msgdata,openingd_eltoo_funder_reply,shutdown_scriptpubkey,u8,shutdown_len +msgdata,openingd_eltoo_funder_reply,channel_type,channel_type, + +# master->openingd: start channel establishment for a funding tx +msgtype,openingd_eltoo_funder_start,6502 +msgdata,openingd_eltoo_funder_start,funding_satoshis,amount_sat, +msgdata,openingd_eltoo_funder_start,push_msat,amount_msat, +msgdata,openingd_eltoo_funder_start,len_upfront,u16, +msgdata,openingd_eltoo_funder_start,upfront_shutdown_script,u8,len_upfront +msgdata,openingd_eltoo_funder_start,upfront_shutdown_wallet_index,?u32, +msgdata,openingd_eltoo_funder_start,feerate_per_kw,u32, +msgdata,openingd_eltoo_funder_start,temporary_channel_id,channel_id, +msgdata,openingd_eltoo_funder_start,channel_flags,u8, + +# openingd->master: send back output script for 2-of-2 funding output +msgtype,openingd_eltoo_funder_start_reply,6602 +msgdata,openingd_eltoo_funder_start_reply,script_len,u8, +msgdata,openingd_eltoo_funder_start_reply,scriptpubkey,u8,script_len +msgdata,openingd_eltoo_funder_start_reply,upfront_shutdown_negotiated,bool, +msgdata,openingd_eltoo_funder_start_reply,channel_type,channel_type, + +# master->openingd: complete channel establishment for a funding +# tx that will be paid for by an external wallet +# response to this is a normal `openingd_eltoo_funder_reply` ?? +msgtype,openingd_eltoo_funder_complete,6512 +msgdata,openingd_eltoo_funder_complete,funding_txid,bitcoin_txid, +msgdata,openingd_eltoo_funder_complete,funding_txout,u16, +msgdata,openingd_eltoo_funder_complete,channel_type,channel_type, + +#master->openingd: cancel channel establishment for a funding +msgtype,openingd_eltoo_funder_cancel,6513 + +# Openingd->master: we failed to negotiation channel +msgtype,openingd_eltoo_failed,6504 +msgdata,openingd_eltoo_failed,reason,wirestring, + +# Openingd->master: they offered channel. +# This gives their txid and info, means we can send funding_signed: we're done. +msgtype,openingd_eltoo_fundee,6503 +msgdata,openingd_eltoo_fundee,their_config,eltoo_channel_config, +msgdata,openingd_eltoo_fundee,first_settlement,bitcoin_tx, +msgdata,openingd_eltoo_fundee,first_update_sig,bitcoin_signature, +msgdata,openingd_eltoo_fundee,remote_fundingkey,pubkey, +msgdata,openingd_eltoo_fundee,funding,bitcoin_outpoint, +msgdata,openingd_eltoo_fundee,funding_satoshis,amount_sat, +msgdata,openingd_eltoo_fundee,push_msat,amount_msat, +msgdata,openingd_eltoo_fundee,channel_flags,u8, +# The funding signed message: send this and we're committed. +msgdata,openingd_eltoo_fundee,msglen,u16, +msgdata,openingd_eltoo_fundee,funding_signed_eltoo_msg,u8,msglen +msgdata,openingd_eltoo_fundee,our_channel_reserve_satoshis,amount_sat, +msgdata,openingd_eltoo_fundee,local_shutdown_len,u16, +msgdata,openingd_eltoo_fundee,local_shutdown_scriptpubkey,u8,local_shutdown_len +msgdata,openingd_eltoo_fundee,remote_shutdown_len,u16, +msgdata,openingd_eltoo_fundee,remote_shutdown_scriptpubkey,u8,remote_shutdown_len +msgdata,openingd_eltoo_fundee,channel_type,channel_type, + +# master -> openingd: do you have a memleak? +msgtype,openingd_eltoo_dev_memleak,6533 + +msgtype,openingd_eltoo_dev_memleak_reply,6133 +msgdata,openingd_eltoo_dev_memleak_reply,leak,bool, From b902edd117af711096353f590476827d1d559f3c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 2 Aug 2022 22:30:21 -0400 Subject: [PATCH 091/283] Delete reserve requirements from eltoo --- channeld/settle_tx.c | 5 ----- channeld/test/run-settle_tx.c | 6 ------ common/initial_settlement_tx.c | 27 --------------------------- common/initial_settlement_tx.h | 2 -- 4 files changed, 40 deletions(-) diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 7f848369578d..0cbc00ab63df 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -215,11 +215,6 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, n++; } - /* BOLT #2: - * - * - MUST set `channel_reserve_satoshis` greater than or equal to - * `dust_limit_satoshis`. - */ /* This means there must be at least one output. */ assert(n > 0); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 30fb6c3867c4..558177579851 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -499,7 +499,6 @@ static int test_invalid_update_tx(void) struct amount_sat dust_limit; struct amount_msat self_pay; struct amount_msat other_pay; - struct amount_sat self_reserve; u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ char* err_reason; @@ -550,7 +549,6 @@ static int test_invalid_update_tx(void) dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; - self_reserve.satoshis = 0; /* not testing this yet since it's really layer violation here */ obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ tx = initial_settlement_tx(tmpctx, @@ -561,7 +559,6 @@ static int test_invalid_update_tx(void) dust_limit, self_pay, other_pay, - self_reserve, obscured_update_number, /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, &err_reason); @@ -674,7 +671,6 @@ static int test_initial_settlement_tx(void) struct amount_sat dust_limit; struct amount_msat self_pay; struct amount_msat other_pay; - struct amount_sat self_reserve; u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ char* err_reason; @@ -724,7 +720,6 @@ static int test_initial_settlement_tx(void) dust_limit.satoshis = 294; self_pay.millisatoshis = (update_output_sats.satoshis - 10000)*1000; other_pay.millisatoshis = (update_output_sats.satoshis*1000) - self_pay.millisatoshis; - self_reserve.satoshis = 0; /* not testing this yet since it's really layer violation here */ obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ tx = initial_settlement_tx(tmpctx, @@ -735,7 +730,6 @@ static int test_initial_settlement_tx(void) dust_limit, self_pay, other_pay, - self_reserve, obscured_update_number, /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, &err_reason); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 593ded659b17..23314ed735fb 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -122,7 +122,6 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct amount_sat dust_limit, struct amount_msat self_pay, struct amount_msat other_pay, - struct amount_sat self_reserve, u32 obscured_update_number, struct wally_tx_output *direct_outputs[NUM_SIDES], char** err_reason) @@ -158,32 +157,6 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, */ num_untrimmed = 0; - /* FIXME, should be in #2: - * - * The receiving node MUST fail the channel if: - *... - * - both `to_local` and `to_remote` amounts for the initial - * commitment transaction are less than or equal to - * `channel_reserve_satoshis`. - */ - if (!amount_msat_greater_sat(self_pay, self_reserve) - && !amount_msat_greater_sat(other_pay, self_reserve)) { - *err_reason = "Neither self amount nor other amount exceed reserve on " - "initial commitment transaction"; - status_unusual("Neither self amount %s" - " nor other amount %s" - " exceed reserve %s" - " on initial commitment transaction", - type_to_string(tmpctx, struct amount_msat, - &self_pay), - type_to_string(tmpctx, struct amount_msat, - &other_pay), - type_to_string(tmpctx, struct amount_sat, - &self_reserve)); - return NULL; - } - - /* Worst-case sizing: both to-local and to-remote outputs + single anchor. */ tx = bitcoin_tx(ctx, chainparams, 1, num_untrimmed + NUM_SIDES + 1, 0); diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index b552cd06712b..262cfb382efd 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -22,7 +22,6 @@ struct wally_tx_output; * @dust_limit: dust limit below which to trim outputs. * @self_pay: amount to pay directly to self * @other_pay: amount to pay directly to the other side - * @self_reserve: reserve the other side insisted we have * @obscured_update_number: obscured update number "o+k" * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). * @err_reason: When NULL is returned, this will point to a human readable reason. @@ -36,7 +35,6 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct amount_sat dust_limit, struct amount_msat self_pay, struct amount_msat other_pay, - struct amount_sat self_reserve, u32 obscured_update_number, struct wally_tx_output *direct_outputs[NUM_SIDES], char** err_reason); From d14f35a96431748950173dad344f899ecda5be5c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 14:56:32 -0400 Subject: [PATCH 092/283] Add new files --- openingd/eltoo_openingd.c | 1410 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1410 insertions(+) create mode 100644 openingd/eltoo_openingd.c diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c new file mode 100644 index 000000000000..752e78e82606 --- /dev/null +++ b/openingd/eltoo_openingd.c @@ -0,0 +1,1410 @@ +/*~ Welcome to the opening daemon: gateway to channels! + * + * This daemon handles a single peer. It's happy to trade gossip with the + * peer until either lightningd asks it to fund a channel, or the peer itself + * asks to fund a channel. Then it goes through with the channel opening + * negotiations. It's important to note that until this negotiation is complete, + * there's nothing permanent about the channel: lightningd will only have to + * commit to the database once openingd succeeds. + */ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* stdin == lightningd, 3 == peer, 4 = hsmd */ +#define REQ_FD STDIN_FILENO +#define HSM_FD 4 + +#if DEVELOPER +/* If --dev-force-tmp-channel-id is set, it ends up here */ +static struct channel_id *dev_force_tmp_channel_id; +#endif /* DEVELOPER */ + +/* Global state structure. This is only for the one specific peer and channel */ +struct eltoo_state { + struct per_peer_state *pps; + + /* Features they offered */ + u8 *their_features; + + /* Constraints on a channel they open. */ + u32 minimum_depth; + u32 min_feerate, max_feerate; + struct amount_msat min_effective_htlc_capacity; + + /* Limits on what remote config we accept. */ + u32 max_shared_delay; + + /* These are the points lightningd told us to use when accepting or + * opening a channel. */ + struct pubkey our_funding_pubkey; + struct pubkey our_settlement_pubkey; + + /* Information we need between funding_start and funding_complete */ + struct pubkey their_funding_pubkey; + struct pubkey their_settlement_pubkey; + + /* Initially temporary, then final channel id. */ + struct channel_id channel_id; + + /* Funding and feerate: set by opening peer. */ + struct amount_sat funding_sats; + struct amount_msat push_msat; + /* u32 feerate_per_kw; pretty sure this is commit tx feerate? */ + struct bitcoin_outpoint funding; + + /* If non-NULL, this is the scriptpubkey we/they *must* close with */ + u8 *upfront_shutdown_script[NUM_SIDES]; + + /* If non-NULL, the wallet index for the LOCAL script */ + u32 *local_upfront_shutdown_wallet_index; + + /* This is a cluster of fields in open_channel and accept_channel which + * indicate the restrictions each side places on the channel. + * FIXME do we need just the one? + */ + struct eltoo_channel_config localconf, remoteconf; + + /* The channel structure, as defined in common/initial_channel.h. While + * the structure has room for HTLCs, those routines are channeld-specific + * as initial channels never have HTLCs. */ + struct eltoo_channel *channel; + + /* Channel type we agreed on (even before channel populated) */ + struct channel_type *channel_type; + + struct feature_set *our_features; +}; + +/*~ If we can't agree on parameters, we fail to open the channel. + * Tell lightningd why. */ +static void NORETURN negotiation_aborted(struct eltoo_state *state, const char *why) +{ + status_debug("aborted opening negotiation: %s", why); + /*~ The "billboard" (exposed as "status" in the JSON listpeers RPC + * call) is a transient per-channel area which indicates important + * information about what is happening. It has a "permanent" area for + * each state, which can be used to indicate what went wrong in that + * state (such as here), and a single transient area for current + * status. */ + peer_billboard(true, why); + + /* Tell master that funding failed. */ + wire_sync_write(REQ_FD, take(towire_openingd_eltoo_failed(NULL, why))); + exit(0); +} + +/*~ For negotiation failures: we tell them the parameter we didn't like. */ +static void NORETURN negotiation_failed(struct eltoo_state *state, + const char *fmt, ...) +{ + va_list ap; + const char *errmsg; + u8 *msg; + + va_start(ap, fmt); + errmsg = tal_vfmt(tmpctx, fmt, ap); + va_end(ap); + + msg = towire_errorfmt(NULL, &state->channel_id, + "You gave bad parameters: %s", errmsg); + peer_write(state->pps, take(msg)); + + negotiation_aborted(state, errmsg); +} + +/* We always set channel_reserve_satoshis to 1%, rounded down. */ +static void set_reserve(struct eltoo_state *state, const struct amount_sat dust_limit) +{ + state->localconf.channel_reserve + = amount_sat_div(state->funding_sats, 100); + + /* BOLT #2: + * + * The sending node: + *... + * - MUST set `channel_reserve_satoshis` greater than or equal to + * `dust_limit_satoshis` from the `open_channel` message. + */ + if (amount_sat_greater(dust_limit, + state->localconf.channel_reserve)) + state->localconf.channel_reserve + = dust_limit; +} + +/*~ Handle random messages we might get during opening negotiation, (eg. gossip) + * returning the first non-handled one, or NULL if we aborted negotiation. */ +static u8 *opening_negotiate_msg(const tal_t *ctx, struct eltoo_state *state, + const struct channel_id *alternate) +{ + /* This is an event loop of its own. That's generally considered poor + * form, but we use it in a very limited way. */ + for (;;) { + u8 *msg; + char *err; + bool warning; + struct channel_id actual; + + /* The event loop is responsible for freeing tmpctx, so our + * temporary allocations don't grow unbounded. */ + clean_tmpctx(); + + /* This helper routine polls both the peer and gossipd. */ + msg = peer_read(ctx, state->pps); + + /* BOLT #1: + * + * A receiving node: + * - upon receiving a message of _odd_, unknown type: + * - MUST ignore the received message. + */ + if (is_unknown_msg_discardable(msg)) + continue; + + /* A helper which decodes an error. */ + if (is_peer_error(tmpctx, msg, &state->channel_id, + &err, &warning)) { + /* BOLT #1: + * + * - if no existing channel is referred to by `channel_id`: + * - MUST ignore the message. + */ + /* In this case, is_peer_error returns true, but sets + * err to NULL */ + if (!err) { + tal_free(msg); + continue; + } + negotiation_aborted(state, + tal_fmt(tmpctx, "They sent %s", + err)); + /* Return NULL so caller knows to stop negotiating. */ + return NULL; + } + + /*~ We do not support multiple "live" channels, though the + * protocol has a "channel_id" field in all non-gossip messages + * so it's possible. Our one-process-one-channel mechanism + * keeps things simple: if we wanted to change this, we would + * probably be best with another daemon to de-multiplex them; + * this could be connectd itself, in fact. */ + if (is_wrong_channel(msg, &state->channel_id, &actual) + && is_wrong_channel(msg, alternate, &actual)) { + status_debug("Rejecting %s for unknown channel_id %s", + peer_wire_name(fromwire_peektype(msg)), + type_to_string(tmpctx, struct channel_id, + &actual)); + peer_write(state->pps, + take(towire_errorfmt(NULL, &actual, + "Multiple channels" + " unsupported"))); + tal_free(msg); + continue; + } + + /* If we get here, it's an interesting message. */ + return msg; + } +} + +static bool setup_channel_funder(struct eltoo_state *state) +{ + /*~ For symmetry, we calculate our own reserve even though lightningd + * could do it for the we-are-funding case. */ + set_reserve(state, state->localconf.dust_limit); + +#if DEVELOPER + /* --dev-force-tmp-channel-id specified */ + if (dev_force_tmp_channel_id) + state->channel_id = *dev_force_tmp_channel_id; +#endif + /* BOLT #2: + * + * The sending node: + *... + * - if both nodes advertised `option_support_large_channel`: + * - MAY set `funding_satoshis` greater than or equal to 2^24 satoshi. + * - otherwise: + * - MUST set `funding_satoshis` to less than 2^24 satoshi. + */ + if (!feature_negotiated(state->our_features, + state->their_features, OPT_LARGE_CHANNELS) + && amount_sat_greater(state->funding_sats, + chainparams->max_funding)) { + status_failed(STATUS_FAIL_MASTER_IO, + "funding_satoshis must be < %s, not %s", + type_to_string(tmpctx, struct amount_sat, + &chainparams->max_funding), + type_to_string(tmpctx, struct amount_sat, + &state->funding_sats)); + return false; + } + + return true; +} + +static void set_remote_upfront_shutdown(struct eltoo_state *state, + u8 *shutdown_scriptpubkey STEALS) +{ + bool anysegwit = feature_negotiated(state->our_features, + state->their_features, + OPT_SHUTDOWN_ANYSEGWIT); + bool anchors = feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS) + || feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHORS_ZERO_FEE_HTLC_TX); + + /* BOLT #2: + * + * - MUST include `upfront_shutdown_script` with either a valid + * `shutdown_scriptpubkey` as required by `shutdown` `scriptpubkey`, + * or a zero-length `shutdown_scriptpubkey` (ie. `0x0000`). + */ + /* We turn empty into NULL. */ + if (tal_bytelen(shutdown_scriptpubkey) == 0) + shutdown_scriptpubkey = tal_free(shutdown_scriptpubkey); + + state->upfront_shutdown_script[REMOTE] + = tal_steal(state, shutdown_scriptpubkey); + + if (shutdown_scriptpubkey + && !valid_shutdown_scriptpubkey(shutdown_scriptpubkey, anysegwit, anchors)) + peer_failed_err(state->pps, + &state->channel_id, + "Unacceptable upfront_shutdown_script %s", + tal_hex(tmpctx, shutdown_scriptpubkey)); +} + +/* We start the 'open a channel' negotation with the supplied peer, but + * stop when we get to the part where we need the funding txid */ +static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) +{ + u8 *msg = NULL; /* FIXME make sure initialized otherwise */ + u8 *funding_output_script = NULL; /* FIXME make sure initialized otherwise */ + struct channel_id id_in; + struct tlv_open_channel_tlvs *open_tlvs = NULL; /* FIXME make sure initialized otherwise */ + struct tlv_accept_channel_tlvs *accept_tlvs = NULL; /* FIXME make sure initialized otherwise */ + + status_debug("funder_channel_start"); + if (!setup_channel_funder(state)) + return NULL; + + if (!state->upfront_shutdown_script[LOCAL]) + state->upfront_shutdown_script[LOCAL] + = no_upfront_shutdown_script(state, + state->our_features, + state->their_features); + + state->channel_type = default_channel_type(state, + state->our_features, + state->their_features); + + open_tlvs = tlv_open_channel_tlvs_new(tmpctx); + open_tlvs->upfront_shutdown_script + = state->upfront_shutdown_script[LOCAL]; + + /* BOLT #2: + * - if it includes `channel_type`: + * - MUST set it to a defined type representing the type it wants. + * - MUST use the smallest bitmap possible to represent the channel + * type. + * - SHOULD NOT set it to a type containing a feature which was not + * negotiated. + */ + open_tlvs->channel_type = state->channel_type->features; + + /* FIXME generate BOLT message for open_channel_eltoo + msg = towire_open_channel_eltoo(NULL, + &chainparams->genesis_blockhash, + &state->channel_id, + state->funding_sats, + state->push_msat, + state->localconf.dust_limit, + state->localconf.max_htlc_value_in_flight, + state->localconf.channel_reserve, + state->localconf.htlc_minimum, + state->localconf.shared_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, + &state->first_per_commitment_point[LOCAL], + channel_flags, + open_tlvs); + */ + peer_write(state->pps, take(msg)); + + /* This is usually a very transient state... */ + peer_billboard(false, + "Funding channel start: offered, now waiting for accept_channel"); + + /* ... since their reply should be immediate. */ + msg = opening_negotiate_msg(tmpctx, state, NULL); + if (!msg) + return NULL; + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - `funding_pubkey`, `revocation_basepoint`, `htlc_basepoint`, + * `payment_basepoint`, or `delayed_payment_basepoint` are not + * valid secp256k1 pubkeys in compressed format. + */ + /* FIXME generate BOLT message for accept_channel_eltoo + if (!fromwire_accept_channel(tmpctx, msg, &id_in, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.channel_reserve, + &state->remoteconf.htlc_minimum, + &state->minimum_depth, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &state->their_funding_pubkey, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.delayed_payment, + &state->their_points.htlc, + &state->first_per_commitment_point[REMOTE], + &accept_tlvs)) { + peer_failed_err(state->pps, + &state->channel_id, + "Parsing accept_channel %s", tal_hex(msg, msg)); + } + */ + set_remote_upfront_shutdown(state, accept_tlvs->upfront_shutdown_script); + + /* BOLT #2: + * - if `channel_type` is set, and `channel_type` was set in + * `open_channel`, and they are not equal types: + * - MUST reject the channel. + */ + if (accept_tlvs->channel_type + && !featurebits_eq(accept_tlvs->channel_type, + state->channel_type->features)) { + negotiation_failed(state, + "Return unoffered channel_type: %s", + fmt_featurebits(tmpctx, + accept_tlvs->channel_type)); + return NULL; + } + + /* BOLT #2: + * + * The `temporary_channel_id` MUST be the same as the + * `temporary_channel_id` in the `open_channel` message. */ + if (!channel_id_eq(&id_in, &state->channel_id)) + /* In this case we exit, since we don't know what's going on. */ + peer_failed_err(state->pps, &id_in, + "accept_channel ids don't match: sent %s got %s", + type_to_string(msg, struct channel_id, &id_in), + type_to_string(msg, struct channel_id, + &state->channel_id)); + + if (amount_sat_greater(state->remoteconf.dust_limit, + state->localconf.channel_reserve)) { + negotiation_failed(state, + "dust limit %s" + " would be above our reserve %s", + type_to_string(tmpctx, struct amount_sat, + &state->remoteconf.dust_limit), + type_to_string(tmpctx, struct amount_sat, + &state->localconf.channel_reserve)); + return NULL; + } + + /* FIXME implement eltoo bounds checking + if (!check_config_bounds(tmpctx, state->funding_sats, + state->feerate_per_kw, + state->max_to_self_delay, + state->min_effective_htlc_capacity, + &state->remoteconf, + &state->localconf, + true, + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + &err_reason)) { + negotiation_failed(state, "%s", err_reason); + return NULL; + } + */ + + /* FIXME compute the scriptpubkey of funding transaction output + funding_output_script = + scriptpubkey_p2wsh(tmpctx, + bitcoin_redeem_2of2(tmpctx, + &state->our_funding_pubkey, + &state->their_funding_pubkey)); + */ + + /* Update the billboard with our infos */ + peer_billboard(false, + "Funding channel start: awaiting funding_txid with output to %s", + tal_hex(tmpctx, funding_output_script)); + + return towire_openingd_eltoo_funder_start_reply(state, + funding_output_script, + feature_negotiated( + state->our_features, + state->their_features, + OPT_UPFRONT_SHUTDOWN_SCRIPT), + state->channel_type); +} + +static bool funder_finalize_channel_setup(struct eltoo_state *state, + struct amount_msat local_msat, + struct bitcoin_signature *sig, + struct bitcoin_tx **update_tx) +{ + u8 *msg; + struct channel_id id_in; + struct channel_id cid; + char *err_reason; + struct wally_tx_output *direct_outputs[NUM_SIDES]; + struct bitcoin_tx *settle_tx; + + /*~ Channel is ready; Report the channel parameters to the signer. */ + /* FIXME hsmd messages need implementing. + msg = towire_hsmd_ready_channel(NULL, + true, + state->funding_sats, + state->push_msat, + &state->funding.txid, + state->funding.n, + state->localconf.shared_delay, + state->upfront_shutdown_script[LOCAL], + state->local_upfront_shutdown_wallet_index, + &state->their_points, + &state->their_funding_pubkey, + state->remoteconf.to_self_delay, + state->upfront_shutdown_script[REMOTE], + state->channel_type); + wire_sync_write(HSM_FD, take(msg)); + */ + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_ready_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + tal_hex(tmpctx, msg)); + + /*~ Now we can initialize the `struct channel`. This represents + * the current channel state and is how we can generate the current + * commitment transaction. + * + * The routines to support `struct channel` are split into a common + * part (common/initial_channel) which doesn't support HTLCs and is + * enough for us here, and the complete channel support required by + * `channeld` which lives in channeld/full_channel. */ + derive_channel_id(&cid, &state->funding); + + state->channel = new_initial_eltoo_channel(state, + &cid, + &state->funding, + state->minimum_depth, + state->funding_sats, + local_msat, + &state->localconf, + &state->remoteconf, + &state->our_funding_pubkey, + &state->their_funding_pubkey, + &state->our_settlement_pubkey, + &state->their_settlement_pubkey, + state->channel_type, + feature_offered(state->their_features, + OPT_LARGE_CHANNELS), + /* Opener is local */ + LOCAL); + /* We were supposed to do enough checks above, but just in case, + * new_initial_channel will fail to create absurd channels */ + if (!state->channel) + peer_failed_err(state->pps, + &state->channel_id, + "could not create channel with given config"); + + /* BOLT #2: + * + * ### The `funding_created` Message + * + * This message describes the outpoint which the funder has created + * for the initial commitment transactions. After receiving the + * peer's signature, via `funding_signed`, it will broadcast the funding + * transaction. + */ + settle_tx = initial_settle_channel_tx(tmpctx, state->channel, + direct_outputs, &err_reason); + if (!settle_tx) { + /* This should not happen: we should never create channels we + * can't afford the fees for after reserve. */ + negotiation_failed(state, + "Could not meet their reserve: %s", err_reason); + goto fail; + } + + *update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel, &err_reason); + + if (!*update_tx) { + /* This should not happen: we should never create channels we + * can't afford the fees for after reserve. */ + negotiation_failed(state, + "Could not meet their reserve: %s", err_reason); + goto fail; + } + + /* We ask the HSM to sign their commitment transaction for us: it knows + * our funding key, it just needs the remote funding key to create the + * witness script. It also needs the amount of the funding output, + * as segwit signatures commit to that as well, even though it doesn't + * explicitly appear in the transaction itself. */ + /* FIXME implement HSM signing message + struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); + u32 feerate = 0; // unused since there are no htlcs + u64 commit_num = 0; + msg = towire_hsmd_sign_update_tx(NULL, + update_tx, + &state->channel->funding_pubkey[REMOTE], + &state->first_per_commitment_point[REMOTE], + channel_has(state->channel, + OPT_STATIC_REMOTEKEY), + commit_num, + (const struct simple_htlc **) htlcs, + feerate); + */ + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_sign_tx_reply(msg, sig)) + status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", + tal_hex(tmpctx, msg)); + + /* You can tell this has been a problem before, since there's a debug + * message here: */ + status_debug("signature %s on tx %s using key %s", + type_to_string(tmpctx, struct bitcoin_signature, sig), + type_to_string(tmpctx, struct bitcoin_tx, *update_tx), + type_to_string(tmpctx, struct pubkey, + &state->our_funding_pubkey)); + + /* Now we give our peer the signature for their first commitment + * transaction. */ + msg = towire_funding_created(state, &state->channel_id, + &state->funding.txid, + state->funding.n, + &sig->s); + peer_write(state->pps, msg); + + /* BOLT #2: + * + * ### The `funding_signed` Message + * + * This message gives the funder the signature it needs for the first + * commitment transaction, so it can broadcast the transaction knowing + * that funds can be redeemed, if need be. + */ + peer_billboard(false, + "Funding channel: create first tx, now waiting for their signature"); + + /* Now they send us their signature for that first commitment + * transaction. Note that errors may refer to the temporary channel + * id (state->channel_id), but success should refer to the new + * "cid" */ + msg = opening_negotiate_msg(tmpctx, state, &cid); + if (!msg) + goto fail; + + sig->sighash_type = SIGHASH_ALL; + if (!fromwire_funding_signed(msg, &id_in, &sig->s)) + peer_failed_err(state->pps, &state->channel_id, + "Parsing funding_signed: %s", tal_hex(msg, msg)); + /* BOLT #2: + * + * This message introduces the `channel_id` to identify the channel. + * It's derived from the funding transaction by combining the + * `funding_txid` and the `funding_output_index`, using big-endian + * exclusive-OR (i.e. `funding_output_index` alters the last 2 + * bytes). + */ + + /*~ Back in Milan, we chose to allow multiple channels between peers in + * the protocol. I insisted that we multiplex these over the same + * socket, and (even though I didn't plan on implementing it anytime + * soon) that we put it into the first version of the protocol + * because it would be painful to add in later. + * + * My logic seemed sound: we treat new connections as an implication + * that the old connection has disconnected, which happens more often + * than you'd hope on modern networks. However, supporting multiple + * channels via multiple connections would be far easier for us to + * support with our (introduced-since) separate daemon model. + * + * Let this be a lesson: beware premature specification, even if you + * suspect "we'll need it later!". */ + state->channel_id = cid; + + if (!channel_id_eq(&id_in, &state->channel_id)) + peer_failed_err(state->pps, &id_in, + "funding_signed ids don't match: expected %s got %s", + type_to_string(msg, struct channel_id, + &state->channel_id), + type_to_string(msg, struct channel_id, &id_in)); + + /* BOLT #2: + * + * The recipient: + * - if `signature` is incorrect OR non-compliant with LOW-S-standard rule...: + * - MUST fail the channel + */ + /* So we create *our* initial commitment transaction, and check the + * signature they sent against that. */ + validate_initial_commitment_signature(HSM_FD, *update_tx, sig); + + /* FIXME check psig + if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) { + peer_failed_err(state->pps, &state->channel_id, + "Bad signature %s on tx %s using key %s (channel_type=%s)", + type_to_string(tmpctx, struct bitcoin_signature, + sig), + type_to_string(tmpctx, struct bitcoin_tx, *tx), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + fmt_featurebits(tmpctx, + state->channel->type->features)); + }*/ + + /* We save their sig to our first commitment tx */ + /* FIXME as a partial sig... how is this stored? + if (!psbt_input_set_signature((*update_tx)->psbt, 0, + &state->their_funding_pubkey, + sig)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Unable to set signature internally"); + */ + peer_billboard(false, "Funding channel: opening negotiation succeeded"); + + return true; + +fail: + /* FIXME free whatever we allocate + tal_free(wscript); + */ + return false; +} + +static u8 *funder_channel_complete(struct eltoo_state *state) +{ + /* Remote commitment tx */ + struct bitcoin_tx *tx; + struct bitcoin_signature sig; + struct amount_msat local_msat; + + /* Update the billboard about what we're doing*/ + peer_billboard(false, + "Funding channel con't: continuing with funding_txid %s", + type_to_string(tmpctx, struct bitcoin_txid, &state->funding.txid)); + + /* We recalculate the local_msat from cached values; should + * succeed because we checked it earlier */ + if (!amount_sat_sub_msat(&local_msat, state->funding_sats, state->push_msat)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "push_msat %s > funding %s?", + type_to_string(tmpctx, struct amount_msat, + &state->push_msat), + type_to_string(tmpctx, struct amount_sat, + &state->funding_sats)); + + if (!funder_finalize_channel_setup(state, local_msat, &sig, &tx)) + return NULL; + + return towire_openingd_eltoo_funder_reply(state, + &state->remoteconf, + tx, + &sig, + state->minimum_depth, + &state->their_funding_pubkey, + &state->their_settlement_pubkey, + &state->funding, + state->localconf.channel_reserve, + state->upfront_shutdown_script[REMOTE], + state->channel_type); +} + +/*~ The peer sent us an `open_channel`, that means we're the fundee. */ +static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) +{ + struct channel_id id_in; + /* FIXME Can't these just be read into eltoo_keyset? */ + struct pubkey their_funding_pubkey; + struct pubkey their_settlement_pubkey; + struct bitcoin_signature theirsig, sig; + struct bitcoin_tx *settle_tx, *update_tx; + struct bitcoin_blkid chain_hash; + u8 *msg = NULL; /* FIXME properly intiialize this */ + const u8 *wscript = NULL; /* FIXME get rid of this*/ + u8 channel_flags = 0; /* FIXME properly intiialize this */ + u16 funding_txout; + char* err_reason; + struct tlv_accept_channel_tlvs *accept_tlvs; + struct tlv_open_channel_tlvs *open_tlvs = NULL; /* FIXME get this initialized */ + struct wally_tx_output *direct_outputs[NUM_SIDES]; + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - `funding_pubkey`, `revocation_basepoint`, `htlc_basepoint`, + * `payment_basepoint`, or `delayed_payment_basepoint` are not valid + * secp256k1 pubkeys in compressed format. + */ + /* FIXME implement open_channel_eltoo message + if (!fromwire_open_channel(tmpctx, open_channel_msg, &chain_hash, + &state->channel_id, + &state->funding_sats, + &state->push_msat, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.channel_reserve, + &state->remoteconf.htlc_minimum, + &state->feerate_per_kw, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &their_funding_pubkey, + &theirs.revocation, + &theirs.payment, + &theirs.delayed_payment, + &theirs.htlc, + &state->first_per_commitment_point[REMOTE], + &channel_flags, + &open_tlvs)) + peer_failed_err(state->pps, + &state->channel_id, + "Parsing open_channel %s", tal_hex(tmpctx, open_channel_msg)); + */ + set_remote_upfront_shutdown(state, open_tlvs->upfront_shutdown_script); + + /* BOLT #2: + * The receiving node MUST fail the channel if: + *... + * - It supports `channel_type`, `channel_type` was set, and the + * `type` is not suitable. + */ + if (open_tlvs->channel_type) { + state->channel_type = + channel_type_accept(state, + open_tlvs->channel_type, + state->our_features, + state->their_features); + if (!state->channel_type) { + negotiation_failed(state, + "Did not support channel_type %s", + fmt_featurebits(tmpctx, + open_tlvs->channel_type)); + return NULL; + } + } else + state->channel_type + = default_channel_type(state, + state->our_features, + state->their_features); + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + * - the `chain_hash` value is set to a hash of a chain + * that is unknown to the receiver. + */ + if (!bitcoin_blkid_eq(&chain_hash, &chainparams->genesis_blockhash)) { + negotiation_failed(state, + "Unknown chain-hash %s", + type_to_string(tmpctx, + struct bitcoin_blkid, + &chain_hash)); + return NULL; + } + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - `funding_satoshis` is greater than or equal to 2^24 and the receiver does not support + * `option_support_large_channel`. */ + /* We choose to require *negotiation*, not just support! */ + if (!feature_negotiated(state->our_features, state->their_features, + OPT_LARGE_CHANNELS) + && amount_sat_greater(state->funding_sats, chainparams->max_funding)) { + negotiation_failed(state, + "funding_satoshis %s too large", + type_to_string(tmpctx, struct amount_sat, + &state->funding_sats)); + return NULL; + } + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + * ... + * - `push_msat` is greater than `funding_satoshis` * 1000. + */ + if (amount_msat_greater_sat(state->push_msat, state->funding_sats)) { + peer_failed_err(state->pps, &state->channel_id, + "Their push_msat %s" + " would be too large for funding_satoshis %s", + type_to_string(tmpctx, struct amount_msat, + &state->push_msat), + type_to_string(tmpctx, struct amount_sat, + &state->funding_sats)); + return NULL; + } + + /* This reserves 1% of the channel (rounded up) */ + set_reserve(state, state->remoteconf.dust_limit); + + /* BOLT #2: + * + * The sender: + *... + * - MUST set `channel_reserve_satoshis` greater than or equal to + * `dust_limit_satoshis` from the `open_channel` message. + * - MUST set `dust_limit_satoshis` less than or equal to + * `channel_reserve_satoshis` from the `open_channel` message. + */ + if (amount_sat_greater(state->remoteconf.dust_limit, + state->localconf.channel_reserve)) { + negotiation_failed(state, + "Our channel reserve %s" + " would be below their dust %s", + type_to_string(tmpctx, struct amount_sat, + &state->localconf.channel_reserve), + type_to_string(tmpctx, struct amount_sat, + &state->remoteconf.dust_limit)); + return NULL; + } + if (amount_sat_greater(state->localconf.dust_limit, + state->remoteconf.channel_reserve)) { + negotiation_failed(state, + "Our dust limit %s" + " would be above their reserve %s", + type_to_string(tmpctx, struct amount_sat, + &state->localconf.dust_limit), + type_to_string(tmpctx, struct amount_sat, + &state->remoteconf.channel_reserve)); + return NULL; + } + + /* These checks are the same whether we're opener or accepter... */ + /* FIXME implement bounds checking for eltoo + if (!check_config_bounds(tmpctx, state->funding_sats, + state->feerate_per_kw, + state->max_to_self_delay, + state->min_effective_htlc_capacity, + &state->remoteconf, + &state->localconf, + false, + feature_negotiated(state->our_features, + state->their_features, + OPT_ANCHOR_OUTPUTS), + &err_reason)) { + negotiation_failed(state, "%s", err_reason); + return NULL; + } + */ + + /* If they give us a reason to reject, do so. */ + if (err_reason) { + negotiation_failed(state, "%s", err_reason); + tal_free(err_reason); + return NULL; + } + + if (!state->upfront_shutdown_script[LOCAL]) + state->upfront_shutdown_script[LOCAL] + = no_upfront_shutdown_script(state, + state->our_features, + state->their_features); + + /* OK, we accept! */ + accept_tlvs = tlv_accept_channel_tlvs_new(tmpctx); + accept_tlvs->upfront_shutdown_script + = state->upfront_shutdown_script[LOCAL]; + /* BOLT #2: + * - if it sets `channel_type`: + * - MUST set it to the `channel_type` from `open_channel` + */ + accept_tlvs->channel_type = state->channel_type->features; + + /* FIXME implement eltoo channel msgs + msg = towire_accept_channel_eltoo(NULL, &state->channel_id, + state->localconf.dust_limit, + state->localconf.max_htlc_value_in_flight, + state->localconf.channel_reserve, + state->localconf.htlc_minimum, + state->minimum_depth, + state->localconf.to_self_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, + &state->first_per_commitment_point[LOCAL], + accept_tlvs); + */ + peer_write(state->pps, take(msg)); + + peer_billboard(false, + "Incoming channel: accepted, now waiting for them to create funding tx"); + + /* This is a loop which handles gossip until we get a non-gossip msg */ + msg = opening_negotiate_msg(tmpctx, state, NULL); + if (!msg) + return NULL; + + /* The message should be "funding_created" which tells us what funding + * tx they generated; the sighash type is implied, so we set it here. */ + theirsig.sighash_type = SIGHASH_ALL; + if (!fromwire_funding_created(msg, &id_in, + &state->funding.txid, + &funding_txout, + &theirsig.s)) + peer_failed_err(state->pps, &state->channel_id, + "Parsing funding_created"); + /* We only allow 16 bits for this on the wire. */ + state->funding.n = funding_txout; + + /* BOLT #2: + * + * The `temporary_channel_id` MUST be the same as the + * `temporary_channel_id` in the `open_channel` message. + */ + if (!channel_id_eq(&id_in, &state->channel_id)) + peer_failed_err(state->pps, &id_in, + "funding_created ids don't match: sent %s got %s", + type_to_string(msg, struct channel_id, + &state->channel_id), + type_to_string(msg, struct channel_id, &id_in)); + + /*~ Channel is ready; Report the channel parameters to the signer. */ + /* FIXME implement HSM messages + msg = towire_hsmd_ready_channel(NULL, + false, + state->funding_sats, + state->push_msat, + &state->funding.txid, + state->funding.n, + state->localconf.to_self_delay, + state->upfront_shutdown_script[LOCAL], + state->local_upfront_shutdown_wallet_index, + &theirs, + &their_funding_pubkey, + state->remoteconf.to_self_delay, + state->upfront_shutdown_script[REMOTE], + state->channel_type); + */ + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_ready_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + tal_hex(tmpctx, msg)); + + /* Now we can create the channel structure. */ + state->channel = new_initial_eltoo_channel(state, + &state->channel_id, + &state->funding, + state->minimum_depth, + state->funding_sats, + state->push_msat, + &state->localconf, + &state->remoteconf, + &state->our_funding_pubkey, + &their_funding_pubkey, + &state->our_settlement_pubkey, + &their_settlement_pubkey, + state->channel_type, + feature_offered(state->their_features, + OPT_LARGE_CHANNELS), + REMOTE); + /* We don't expect this to fail, but it does do some additional + * internal sanity checks. */ + if (!state->channel) + peer_failed_err(state->pps, &state->channel_id, + "We could not create channel with given config"); + + /* BOLT #2: + * + * The recipient: + * - if `signature` is incorrect OR non-compliant with LOW-S-standard + * rule...: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + settle_tx = initial_settle_channel_tx(tmpctx, state->channel, + direct_outputs, &err_reason); + /* This shouldn't happen either, AFAICT. */ + if (!settle_tx) { + negotiation_failed(state, + "Could not meet our reserve: %s", err_reason); + return NULL; + } + + update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel, &err_reason); + /* Nor this */ + if (!update_tx) { + negotiation_failed(state, + "Failed to make update tx: %s", err_reason); + return NULL; + } + + /* FIXME bind update tx to funding output, then check partial sig */ + + validate_initial_commitment_signature(HSM_FD, update_tx, &theirsig); + + if (!check_tx_sig(update_tx, 0, NULL, wscript, &their_funding_pubkey, + &theirsig)) { + /* BOLT #1: + * + * ### The `error` and `warning` Messages + *... + * - when failure was caused by an invalid signature check: + * - SHOULD include the raw, hex-encoded transaction in reply + * to a `funding_created`, `funding_signed`, + * `closing_signed`, or `commitment_signed` message. + */ + /*~ This verbosity is not only useful for our own testing, but + * a courtesy to other implementaters whose brains may be so + * twisted by coding in Go, Scala and Rust that they can no + * longer read C code. */ + peer_failed_err(state->pps, &state->channel_id, + "Bad signature %s on tx %s using key %s", + type_to_string(tmpctx, struct bitcoin_signature, + &theirsig), + type_to_string(tmpctx, struct bitcoin_tx, update_tx), + type_to_string(tmpctx, struct pubkey, + &their_funding_pubkey)); + } + + /* BOLT #2: + * + * This message introduces the `channel_id` to identify the + * channel. It's derived from the funding transaction by combining the + * `funding_txid` and the `funding_output_index`, using big-endian + * exclusive-OR (i.e. `funding_output_index` alters the last 2 bytes). + */ + derive_channel_id(&state->channel_id, &state->funding); + + /*~ We generate the `funding_signed` message here, since we have all + * the data and it's only applicable in the fundee case. + * + * FIXME: Perhaps we should have channeld generate this, so we + * can't possibly send before channel committed to disk? + */ + + /* BOLT #2: + * + * ### The `funding_signed` Message + * + * This message gives the funder the signature it needs for the first + * commitment transaction, so it can broadcast the transaction knowing + * that funds can be redeemed, if need be. + */ + /* FIXME this is the 2nd commitment tx being signed, unnneeded? + remote_commit = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[REMOTE], + REMOTE, direct_outputs, &err_reason); + */ + + /* Make HSM sign it */ + /* FIXME implement HSM signing message + struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); + u32 feerate = 0; // unused since there are no htlcs + u64 commit_num = 0; + msg = towire_hsmd_sign_remote_commitment_tx(NULL, + remote_commit, + &state->channel->funding_pubkey[REMOTE], + &state->first_per_commitment_point[REMOTE], + channel_has(state->channel, + OPT_STATIC_REMOTEKEY), + commit_num, + (const struct simple_htlc **) htlcs, + feerate); + */ + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_sign_tx_reply(msg, &sig)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); + + /* We don't send this ourselves: channeld does, because master needs + * to save state to disk before doing so. */ + assert(sig.sighash_type == SIGHASH_ALL); + msg = towire_funding_signed(state, &state->channel_id, &sig.s); + + return towire_openingd_eltoo_fundee(state, + &state->remoteconf, + update_tx, + &theirsig, + &their_funding_pubkey, + &state->funding, + state->funding_sats, + state->push_msat, + channel_flags, + msg, + state->localconf.channel_reserve, + state->upfront_shutdown_script[LOCAL], + state->upfront_shutdown_script[REMOTE], + state->channel_type); +} + +/*~ Standard "peer sent a message, handle it" demuxer. Though it really only + * handles one message, we use the standard form as principle of least + * surprise. */ +static u8 *handle_peer_in(struct eltoo_state *state) +{ + u8 *msg = peer_read(tmpctx, state->pps); + enum peer_wire t = fromwire_peektype(msg); + struct channel_id channel_id; + bool extracted; + + if (t == WIRE_OPEN_CHANNEL) + return fundee_channel(state, msg); + + /* Handles error cases. */ + if (handle_peer_error(state->pps, &state->channel_id, msg)) + return NULL; + + extracted = extract_channel_id(msg, &channel_id); + + peer_write(state->pps, + take(towire_warningfmt(NULL, + extracted ? &channel_id : NULL, + "Unexpected message %s: %s", + peer_wire_name(t), + tal_hex(tmpctx, msg)))); + + /* FIXME: We don't actually want master to try to send an + * error, since peer is transient. This is a hack. + */ + status_broken("Unexpected message %s", peer_wire_name(t)); + peer_failed_connection_lost(); +} + +/* Memory leak detection is DEVELOPER-only because we go to great lengths to + * record the backtrace when allocations occur: without that, the leak + * detection tends to be useless for diagnosing where the leak came from, but + * it has significant overhead. */ +#if DEVELOPER +static void handle_dev_memleak(struct eltoo_state *state, const u8 *msg) +{ + struct htable *memtable; + bool found_leak; + + /* Populate a hash table with all our allocations (except msg, which + * is in use right now). */ + memtable = memleak_find_allocations(tmpctx, msg, msg); + + /* Now delete state and things it has pointers to. */ + memleak_remove_region(memtable, state, sizeof(*state)); + + /* If there's anything left, dump it to logs, and return true. */ + found_leak = dump_memleak(memtable, memleak_status_broken); + wire_sync_write(REQ_FD, + take(towire_openingd_eltoo_dev_memleak_reply(NULL, + found_leak))); +} +#endif /* DEVELOPER */ + +/* Standard lightningd-fd-is-ready-to-read demux code. Again, we could hang + * here, but if we can't trust our parent, who can we trust? */ +static u8 *handle_master_in(struct eltoo_state *state) +{ + u8 *msg = wire_sync_read(tmpctx, REQ_FD); + enum eltoo_openingd_wire t = fromwire_peektype(msg); + u8 channel_flags = 0; /* FIXME intiailize properly */ + /* FIXME + struct bitcoin_txid funding_txid; + u16 funding_txout;*/ + + switch (t) { + case WIRE_OPENINGD_ELTOO_FUNDER_START: + /* FIXME + if (!fromwire_openingd_funder_start(state, msg, + &state->funding_sats, + &state->push_msat, + &state->upfront_shutdown_script[LOCAL], + &state->local_upfront_shutdown_wallet_index, + &state->feerate_per_kw, + &state->channel_id, + &channel_flags)) + master_badmsg(WIRE_OPENINGD_FUNDER_START, msg); + + */ + msg = funder_channel_start(state, channel_flags); + /* We want to keep openingd alive, since we're not done yet */ + if (msg) + wire_sync_write(REQ_FD, take(msg)); + return NULL; + case WIRE_OPENINGD_ELTOO_FUNDER_COMPLETE: + /* FIXME + if (!fromwire_openingd_funder_complete(state, msg, + &funding_txid, + &funding_txout, + &state->channel_type)) + master_badmsg(WIRE_OPENINGD_FUNDER_COMPLETE, msg); + state->funding.txid = funding_txid; + state->funding.n = funding_txout; + */ + return funder_channel_complete(state); + case WIRE_OPENINGD_ELTOO_FUNDER_CANCEL: + /* We're aborting this, simple */ + if (!fromwire_openingd_eltoo_funder_cancel(msg)) + master_badmsg(WIRE_OPENINGD_ELTOO_FUNDER_CANCEL, msg); + + msg = towire_errorfmt(NULL, &state->channel_id, "Channel open canceled by us"); + peer_write(state->pps, take(msg)); + negotiation_aborted(state, "Channel open canceled by RPC"); + return NULL; + case WIRE_OPENINGD_ELTOO_DEV_MEMLEAK: +#if DEVELOPER + handle_dev_memleak(state, msg); + return NULL; +#endif + case WIRE_OPENINGD_ELTOO_DEV_MEMLEAK_REPLY: + case WIRE_OPENINGD_ELTOO_INIT: + case WIRE_OPENINGD_ELTOO_FUNDER_REPLY: + case WIRE_OPENINGD_ELTOO_FUNDER_START_REPLY: + case WIRE_OPENINGD_ELTOO_FUNDEE: + case WIRE_OPENINGD_ELTOO_FAILED: + break; + } + + status_failed(STATUS_FAIL_MASTER_IO, + "Unknown msg %s", tal_hex(tmpctx, msg)); +} + +int main(int argc, char *argv[]) +{ + setup_locale(); + + u8 *msg; + struct pollfd pollfd[2]; + struct eltoo_state *state = tal(NULL, struct eltoo_state); + struct channel_id *force_tmp_channel_id; + + subdaemon_setup(argc, argv); + + /*~ This makes status_failed, status_debug etc work synchronously by + * writing to REQ_FD */ + status_setup_sync(REQ_FD); + + /*~ The very first thing we read from lightningd is our init msg */ + msg = wire_sync_read(tmpctx, REQ_FD); + if (!fromwire_openingd_eltoo_init(state, msg, + &chainparams, + &state->our_features, + &state->their_features, + &state->localconf, + &state->max_shared_delay, + &state->min_effective_htlc_capacity, + &state->our_funding_pubkey, + &state->our_settlement_pubkey, + &state->minimum_depth, + &state->min_feerate, &state->max_feerate, + &force_tmp_channel_id)) + master_badmsg(WIRE_OPENINGD_ELTOO_INIT, msg); + +#if DEVELOPER + dev_force_tmp_channel_id = force_tmp_channel_id; +#endif + + /* 3 == peer, 4 = hsmd */ + state->pps = new_per_peer_state(state); + per_peer_state_set_fd(state->pps, 3); + + /*~ Initially we're not associated with a channel, but + * handle_peer_gossip_or_error compares this. */ + memset(&state->channel_id, 0, sizeof(state->channel_id)); + state->channel = NULL; + + /* Default this to zero, we only ever look at the local */ + state->remoteconf.max_dust_htlc_exposure_msat = AMOUNT_MSAT(0); + + /*~ We set these to NULL, meaning no requirements on shutdown */ + state->upfront_shutdown_script[LOCAL] + = state->upfront_shutdown_script[REMOTE] + = NULL; + + /*~ We manually run a little poll() loop here. With only three fds */ + pollfd[0].fd = REQ_FD; + pollfd[0].events = POLLIN; + pollfd[1].fd = state->pps->peer_fd; + pollfd[1].events = POLLIN; + + /* We exit when we get a conclusion to write to lightningd: either + * opening_funder_reply or opening_fundee. */ + msg = NULL; + while (!msg) { + /*~ If we get a signal which aborts the poll() call, valgrind + * complains about revents being uninitialized. I'm not sure + * that's correct, but it's easy to be sure. */ + pollfd[0].revents = pollfd[1].revents = 0; + + poll(pollfd, ARRAY_SIZE(pollfd), -1); + /* Subtle: handle_master_in can do its own poll loop, so + * don't try to service more than one fd per loop. */ + /* First priority: messages from lightningd. */ + if (pollfd[0].revents & POLLIN) + msg = handle_master_in(state); + /* Second priority: messages from peer. */ + else if (pollfd[1].revents & POLLIN) + msg = handle_peer_in(state); + + /* Since we're the top-level event loop, we clean up */ + clean_tmpctx(); + } + + /*~ Write message and hand back the peer fd. This also means that if + * the peer wrote us any messages we didn't read yet, it will simply + * be read by the next daemon. */ + wire_sync_write(REQ_FD, msg); + per_peer_state_fdpass_send(REQ_FD, state->pps); + status_debug("Sent %s with fd", + eltoo_openingd_wire_name(fromwire_peektype(msg))); + + /* This frees the entire tal tree. */ + tal_free(state); + + /* This frees up everything else. */ + daemon_shutdown(); + return 0; +} + +/*~ Note that there are no other source files in openingd: it really is a fairly + * straight-line daemon. + * + * From here the channel is established: lightningd hands the peer off to + * channeld/channeld.c which runs the normal channel routine for this peer. + */ From abdc3d102407cfcafdc83d09779c560d0613be9d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 14:59:50 -0400 Subject: [PATCH 093/283] Remove rest of reserve requirement stuff for eltoo --- openingd/eltoo_openingd.c | 81 ++------------------------------ openingd/eltoo_openingd_wire.csv | 3 -- 2 files changed, 3 insertions(+), 81 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 752e78e82606..569612c25bae 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -137,25 +137,6 @@ static void NORETURN negotiation_failed(struct eltoo_state *state, negotiation_aborted(state, errmsg); } -/* We always set channel_reserve_satoshis to 1%, rounded down. */ -static void set_reserve(struct eltoo_state *state, const struct amount_sat dust_limit) -{ - state->localconf.channel_reserve - = amount_sat_div(state->funding_sats, 100); - - /* BOLT #2: - * - * The sending node: - *... - * - MUST set `channel_reserve_satoshis` greater than or equal to - * `dust_limit_satoshis` from the `open_channel` message. - */ - if (amount_sat_greater(dust_limit, - state->localconf.channel_reserve)) - state->localconf.channel_reserve - = dust_limit; -} - /*~ Handle random messages we might get during opening negotiation, (eg. gossip) * returning the first non-handled one, or NULL if we aborted negotiation. */ static u8 *opening_negotiate_msg(const tal_t *ctx, struct eltoo_state *state, @@ -233,9 +214,6 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct eltoo_state *state, static bool setup_channel_funder(struct eltoo_state *state) { - /*~ For symmetry, we calculate our own reserve even though lightningd - * could do it for the we-are-funding case. */ - set_reserve(state, state->localconf.dust_limit); #if DEVELOPER /* --dev-force-tmp-channel-id specified */ @@ -429,18 +407,6 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) type_to_string(msg, struct channel_id, &state->channel_id)); - if (amount_sat_greater(state->remoteconf.dust_limit, - state->localconf.channel_reserve)) { - negotiation_failed(state, - "dust limit %s" - " would be above our reserve %s", - type_to_string(tmpctx, struct amount_sat, - &state->remoteconf.dust_limit), - type_to_string(tmpctx, struct amount_sat, - &state->localconf.channel_reserve)); - return NULL; - } - /* FIXME implement eltoo bounds checking if (!check_config_bounds(tmpctx, state->funding_sats, state->feerate_per_kw, @@ -561,20 +527,16 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, settle_tx = initial_settle_channel_tx(tmpctx, state->channel, direct_outputs, &err_reason); if (!settle_tx) { - /* This should not happen: we should never create channels we - * can't afford the fees for after reserve. */ negotiation_failed(state, - "Could not meet their reserve: %s", err_reason); + "Could not make settle tx: %s", err_reason); goto fail; } *update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel, &err_reason); if (!*update_tx) { - /* This should not happen: we should never create channels we - * can't afford the fees for after reserve. */ negotiation_failed(state, - "Could not meet their reserve: %s", err_reason); + "Could not make update tx: %s", err_reason); goto fail; } @@ -749,7 +711,6 @@ static u8 *funder_channel_complete(struct eltoo_state *state) &state->their_funding_pubkey, &state->their_settlement_pubkey, &state->funding, - state->localconf.channel_reserve, state->upfront_shutdown_script[REMOTE], state->channel_type); } @@ -881,41 +842,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) return NULL; } - /* This reserves 1% of the channel (rounded up) */ - set_reserve(state, state->remoteconf.dust_limit); - - /* BOLT #2: - * - * The sender: - *... - * - MUST set `channel_reserve_satoshis` greater than or equal to - * `dust_limit_satoshis` from the `open_channel` message. - * - MUST set `dust_limit_satoshis` less than or equal to - * `channel_reserve_satoshis` from the `open_channel` message. - */ - if (amount_sat_greater(state->remoteconf.dust_limit, - state->localconf.channel_reserve)) { - negotiation_failed(state, - "Our channel reserve %s" - " would be below their dust %s", - type_to_string(tmpctx, struct amount_sat, - &state->localconf.channel_reserve), - type_to_string(tmpctx, struct amount_sat, - &state->remoteconf.dust_limit)); - return NULL; - } - if (amount_sat_greater(state->localconf.dust_limit, - state->remoteconf.channel_reserve)) { - negotiation_failed(state, - "Our dust limit %s" - " would be above their reserve %s", - type_to_string(tmpctx, struct amount_sat, - &state->localconf.dust_limit), - type_to_string(tmpctx, struct amount_sat, - &state->remoteconf.channel_reserve)); - return NULL; - } - /* These checks are the same whether we're opener or accepter... */ /* FIXME implement bounds checking for eltoo if (!check_config_bounds(tmpctx, state->funding_sats, @@ -1067,7 +993,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* This shouldn't happen either, AFAICT. */ if (!settle_tx) { negotiation_failed(state, - "Could not meet our reserve: %s", err_reason); + "Failed to make settle tx: %s", err_reason); return NULL; } @@ -1173,7 +1099,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->push_msat, channel_flags, msg, - state->localconf.channel_reserve, state->upfront_shutdown_script[LOCAL], state->upfront_shutdown_script[REMOTE], state->channel_type); diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index 9eb6526d4957..1c0b2c2c5226 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -13,7 +13,6 @@ msgdata,openingd_eltoo_init,chainparams,chainparams, msgdata,openingd_eltoo_init,our_features,feature_set, msgdata,openingd_eltoo_init,their_init_features_len,u16, msgdata,openingd_eltoo_init,their_init_features,u8,their_init_features_len -# Base configuration we'll offer (channel reserve will vary with amount) msgdata,openingd_eltoo_init,our_config,eltoo_channel_config, # Minimum/maximum configuration values we'll accept msgdata,openingd_eltoo_init,max_shared_delay,u32, @@ -37,7 +36,6 @@ msgdata,openingd_eltoo_funder_reply,minimum_depth,u32, msgdata,openingd_eltoo_funder_reply,remote_funding_key,pubkey, msgdata,openingd_eltoo_funder_reply,remote_settlement_key,pubkey, msgdata,openingd_eltoo_funder_reply,funding,bitcoin_outpoint, -msgdata,openingd_eltoo_funder_reply,our_channel_reserve_satoshis,amount_sat, msgdata,openingd_eltoo_funder_reply,shutdown_len,u16, msgdata,openingd_eltoo_funder_reply,shutdown_scriptpubkey,u8,shutdown_len msgdata,openingd_eltoo_funder_reply,channel_type,channel_type, @@ -89,7 +87,6 @@ msgdata,openingd_eltoo_fundee,channel_flags,u8, # The funding signed message: send this and we're committed. msgdata,openingd_eltoo_fundee,msglen,u16, msgdata,openingd_eltoo_fundee,funding_signed_eltoo_msg,u8,msglen -msgdata,openingd_eltoo_fundee,our_channel_reserve_satoshis,amount_sat, msgdata,openingd_eltoo_fundee,local_shutdown_len,u16, msgdata,openingd_eltoo_fundee,local_shutdown_scriptpubkey,u8,local_shutdown_len msgdata,openingd_eltoo_fundee,remote_shutdown_len,u16, From a387627fea4d035db3b9c7de122ab41f9b52112c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 15:06:04 -0400 Subject: [PATCH 094/283] more reserve removing --- common/channel_config.c | 2 -- common/channel_config.h | 6 ------ 2 files changed, 8 deletions(-) diff --git a/common/channel_config.c b/common/channel_config.c index 865ff916530a..5f25b846cadb 100644 --- a/common/channel_config.c +++ b/common/channel_config.c @@ -29,7 +29,6 @@ void towire_eltoo_channel_config(u8 **pptr, const struct eltoo_channel_config *c { towire_amount_sat(pptr, config->dust_limit); towire_amount_msat(pptr, config->max_htlc_value_in_flight); - towire_amount_sat(pptr, config->channel_reserve); towire_amount_msat(pptr, config->htlc_minimum); towire_u16(pptr, config->shared_delay); towire_u16(pptr, config->max_accepted_htlcs); @@ -41,7 +40,6 @@ void fromwire_eltoo_channel_config(const u8 **ptr, size_t *max, { config->dust_limit = fromwire_amount_sat(ptr, max); config->max_htlc_value_in_flight = fromwire_amount_msat(ptr, max); - config->channel_reserve = fromwire_amount_sat(ptr, max); config->htlc_minimum = fromwire_amount_msat(ptr, max); config->shared_delay = fromwire_u16(ptr, max); config->max_accepted_htlcs = fromwire_u16(ptr, max); diff --git a/common/channel_config.h b/common/channel_config.h index 42e96afd2325..79891185647f 100644 --- a/common/channel_config.h +++ b/common/channel_config.h @@ -100,12 +100,6 @@ struct eltoo_channel_config { * HTLCs */ struct amount_msat max_htlc_value_in_flight; - /* BOLT #2: - * - * `channel_reserve_satoshis` is the minimum amount that the other - * node is to keep as a direct payment. */ - struct amount_sat channel_reserve; - /* BOLT #2: * * `htlc_minimum_msat` indicates the smallest value HTLC this node From 573e34ac0beddf41f2fe8e7aee36202ff74976bd Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 16:23:40 -0400 Subject: [PATCH 095/283] add check_eltoo_config_bounds --- openingd/common.c | 92 +++++++++++++++++++++++++++++++++++++++ openingd/common.h | 7 +++ openingd/eltoo_openingd.c | 23 +++------- 3 files changed, 104 insertions(+), 18 deletions(-) diff --git a/openingd/common.c b/openingd/common.c index c31bb7774d72..1541e5ec7304 100644 --- a/openingd/common.c +++ b/openingd/common.c @@ -9,6 +9,98 @@ #include #include +bool check_eltoo_config_bounds(const tal_t *ctx, + struct amount_sat funding, + u32 max_shared_delay, + struct amount_msat min_effective_htlc_capacity, + const struct eltoo_channel_config *remoteconf, + const struct eltoo_channel_config *localconf, + char **err_reason) +{ + /* For eltoo, funding is capacity always */ + struct amount_sat capacity = funding; + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - `to_self_delay` is unreasonably large. + */ + if (remoteconf->shared_delay > max_shared_delay) { + *err_reason = tal_fmt(ctx, + "shared_delay %u larger than %u", + remoteconf->shared_delay, + max_shared_delay); + return false; + } + + /* If they set the max HTLC value to less than that number, it caps + * the channel capacity. */ + if (amount_sat_greater(capacity, + amount_msat_to_sat_round_down(remoteconf->max_htlc_value_in_flight))) + capacity = amount_msat_to_sat_round_down(remoteconf->max_htlc_value_in_flight); + + /* If the minimum htlc is greater than the capacity, the channel is + * useless. */ + if (amount_msat_greater_sat(remoteconf->htlc_minimum, capacity)) { + *err_reason = tal_fmt(ctx, "htlc_minimum_msat %s" + " too large for funding %s" + " capacity_msat %s", + type_to_string(ctx, struct amount_msat, + &remoteconf->htlc_minimum), + type_to_string(ctx, struct amount_sat, + &funding), + type_to_string(ctx, struct amount_sat, + &capacity)); + return false; + } + + /* If the resulting channel doesn't meet our minimum "effective capacity" + * set by lightningd, don't bother opening it. */ + if (amount_msat_greater_sat(min_effective_htlc_capacity, + capacity)) { + struct amount_sat min_effective_htlc_capacity_sat = + amount_msat_to_sat_round_down(min_effective_htlc_capacity); + + *err_reason = tal_fmt(ctx, + "channel capacity with funding %s," + " max_htlc_value_in_flight_msat is %s," + " channel capacity is %s, which is below %s", + type_to_string(ctx, struct amount_sat, + &funding), + type_to_string(ctx, struct amount_msat, + &remoteconf->max_htlc_value_in_flight), + type_to_string(ctx, struct amount_sat, + &capacity), + type_to_string(ctx, struct amount_sat, + &min_effective_htlc_capacity_sat)); + return false; + } + + /* We don't worry about how many HTLCs they accept, as long as > 0! */ + if (remoteconf->max_accepted_htlcs == 0) { + *err_reason = tal_fmt(ctx, + "max_accepted_htlcs %u invalid", + remoteconf->max_accepted_htlcs); + return false; + } + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - `max_accepted_htlcs` is greater than 483. + */ + if (remoteconf->max_accepted_htlcs > 483) { + *err_reason = tal_fmt(ctx, + "max_accepted_htlcs %u too large", + remoteconf->max_accepted_htlcs); + return false; + } + + return true; +} + /*~ This is the key function that checks that their configuration is reasonable: * it applied for both the case where they're trying to open a channel, and when * they've accepted our open. */ diff --git a/openingd/common.h b/openingd/common.h index 838321867dda..61571cf6cf20 100644 --- a/openingd/common.h +++ b/openingd/common.h @@ -8,6 +8,13 @@ struct bitcoin_tx; struct bitcoin_signature; struct channel_config; +bool check_eltoo_config_bounds(const tal_t *ctx, + struct amount_sat funding, + u32 max_shared_delay, + struct amount_msat min_effective_htlc_capacity, + const struct eltoo_channel_config *remoteconf, + const struct eltoo_channel_config *localconf, + char **err_reason); bool check_config_bounds(const tal_t *ctx, struct amount_sat funding, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 569612c25bae..6be5ee9e4e53 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -288,6 +288,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) struct channel_id id_in; struct tlv_open_channel_tlvs *open_tlvs = NULL; /* FIXME make sure initialized otherwise */ struct tlv_accept_channel_tlvs *accept_tlvs = NULL; /* FIXME make sure initialized otherwise */ + char *err_reason; status_debug("funder_channel_start"); if (!setup_channel_funder(state)) @@ -407,22 +408,15 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) type_to_string(msg, struct channel_id, &state->channel_id)); - /* FIXME implement eltoo bounds checking - if (!check_config_bounds(tmpctx, state->funding_sats, - state->feerate_per_kw, - state->max_to_self_delay, + if (!check_eltoo_config_bounds(tmpctx, state->funding_sats, + state->max_shared_delay, state->min_effective_htlc_capacity, &state->remoteconf, &state->localconf, - true, - feature_negotiated(state->our_features, - state->their_features, - OPT_ANCHOR_OUTPUTS), &err_reason)) { negotiation_failed(state, "%s", err_reason); return NULL; } - */ /* FIXME compute the scriptpubkey of funding transaction output funding_output_script = @@ -843,22 +837,15 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) } /* These checks are the same whether we're opener or accepter... */ - /* FIXME implement bounds checking for eltoo - if (!check_config_bounds(tmpctx, state->funding_sats, - state->feerate_per_kw, - state->max_to_self_delay, + if (!check_eltoo_config_bounds(tmpctx, state->funding_sats, + state->max_shared_delay, state->min_effective_htlc_capacity, &state->remoteconf, &state->localconf, - false, - feature_negotiated(state->our_features, - state->their_features, - OPT_ANCHOR_OUTPUTS), &err_reason)) { negotiation_failed(state, "%s", err_reason); return NULL; } - */ /* If they give us a reason to reject, do so. */ if (err_reason) { From c2efb3c896c066a331cae21898d2ac8a928a434b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 16:46:30 -0400 Subject: [PATCH 096/283] Create funding script helper, use in funder_channel_start --- bitcoin/signature.c | 26 ++++++++++++++++++++++++++ bitcoin/signature.h | 3 +++ openingd/eltoo_openingd.c | 12 ++++-------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 2658863b2f25..44dc04fb576a 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -720,3 +720,29 @@ void create_keypair_of_one(secp256k1_keypair *G_pair) g); assert(ok); } + +u8 *scriptpubkey_eltoo_funding(const tal_t *ctx, const struct pubkey *pubkey1, const struct pubkey *pubkey2) +{ + struct pubkey taproot_pubkey; + secp256k1_musig_keyagg_cache keyagg_cache; + const struct pubkey *pk_ptrs[2]; + struct sha256 tap_merkle_root; + unsigned char tap_tweak_out[32]; + u8 *update_tapscript[1]; + + pk_ptrs[0] = pubkey1; + pk_ptrs[1] = pubkey2; + + update_tapscript[0] = make_eltoo_funding_update_script(tmpctx); + + compute_taptree_merkle_root(&tap_merkle_root, update_tapscript, /* num_scripts */ 1); + + bipmusig_finalize_keys(&taproot_pubkey, + &keyagg_cache, + pk_ptrs, + /* n_pubkeys */ 2, + &tap_merkle_root, + tap_tweak_out); + + return scriptpubkey_p2tr(ctx, &taproot_pubkey); +} diff --git a/bitcoin/signature.h b/bitcoin/signature.h index cda31c399dc2..203e53273f58 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -320,4 +320,7 @@ void bip340_sighash_init(struct sha256_ctx *sctx, /* Used for APO style covenant signatures */ void create_keypair_of_one(secp256k1_keypair *G_pair); +/* Compute an output script for funding output */ +u8 *scriptpubkey_eltoo_funding(const tal_t *ctx, const struct pubkey *pubkey1, const struct pubkey *pubkey2); + #endif /* LIGHTNING_BITCOIN_SIGNATURE_H */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 6be5ee9e4e53..245c8a39c1af 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -284,7 +284,7 @@ static void set_remote_upfront_shutdown(struct eltoo_state *state, static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) { u8 *msg = NULL; /* FIXME make sure initialized otherwise */ - u8 *funding_output_script = NULL; /* FIXME make sure initialized otherwise */ + u8 *funding_output_script; struct channel_id id_in; struct tlv_open_channel_tlvs *open_tlvs = NULL; /* FIXME make sure initialized otherwise */ struct tlv_accept_channel_tlvs *accept_tlvs = NULL; /* FIXME make sure initialized otherwise */ @@ -418,13 +418,9 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) return NULL; } - /* FIXME compute the scriptpubkey of funding transaction output - funding_output_script = - scriptpubkey_p2wsh(tmpctx, - bitcoin_redeem_2of2(tmpctx, - &state->our_funding_pubkey, - &state->their_funding_pubkey)); - */ + funding_output_script = scriptpubkey_eltoo_funding(tmpctx, + &state->our_funding_pubkey, + &state->their_funding_pubkey); /* Update the billboard with our infos */ peer_billboard(false, From 07a10d6b2b9c7716daa23b44e62a6b2da9a2276e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 22:59:43 -0400 Subject: [PATCH 097/283] More openingd compiling --- hsmd/Makefile | 4 +- hsmd/hsmd_eltoo_wire.csv | 44 +++++++++++++++++++++ openingd/common.c | 29 ++++++++++++++ openingd/common.h | 5 +++ openingd/eltoo_openingd.c | 66 ++++++++++++++------------------ openingd/eltoo_openingd_wire.csv | 5 ++- 6 files changed, 112 insertions(+), 41 deletions(-) create mode 100644 hsmd/hsmd_eltoo_wire.csv diff --git a/hsmd/Makefile b/hsmd/Makefile index 6fd4dac59704..b6c7b300e3af 100644 --- a/hsmd/Makefile +++ b/hsmd/Makefile @@ -2,9 +2,10 @@ HSMD_SRC := hsmd/hsmd.c \ hsmd/hsmd_wiregen.c \ + hsmd/hsmd_eltoo_wiregen.c \ hsmd/libhsmd.c -HSMD_HEADERS := hsmd/hsmd_wiregen.h +HSMD_HEADERS := hsmd/hsmd_wiregen.h hsmd/hsmd_eltoo_wiregen.h HSMD_OBJS := $(HSMD_SRC:.c=.o) $(HSMD_OBJS): $(HSMD_HEADERS) @@ -12,6 +13,7 @@ $(HSMD_OBJS): $(HSMD_HEADERS) # Other programs which use the hsm need this. HSMD_CLIENT_OBJS := \ hsmd/hsmd_wiregen.o \ + hsmd/hsmd_eltoo_wiregen.o \ common/htlc_wire.o # Make sure these depend on everything. diff --git a/hsmd/hsmd_eltoo_wire.csv b/hsmd/hsmd_eltoo_wire.csv new file mode 100644 index 000000000000..748db5981c95 --- /dev/null +++ b/hsmd/hsmd_eltoo_wire.csv @@ -0,0 +1,44 @@ +#include +#include +#include +# Provide channel parameters. +msgtype,hsmd_ready_eltoo_channel,81 +msgdata,hsmd_ready_eltoo_channel,is_outbound,bool, +msgdata,hsmd_ready_eltoo_channel,channel_value,amount_sat, +msgdata,hsmd_ready_eltoo_channel,push_value,amount_msat, +msgdata,hsmd_ready_eltoo_channel,funding_txid,bitcoin_txid, +msgdata,hsmd_ready_eltoo_channel,funding_txout,u16, +msgdata,hsmd_ready_eltoo_channel,shared_delay,u16, +msgdata,hsmd_ready_eltoo_channel,local_shutdown_script_len,u16, +msgdata,hsmd_ready_eltoo_channel,local_shutdown_script,u8,local_shutdown_script_len +msgdata,hsmd_ready_eltoo_channel,local_shutdown_wallet_index,?u32, +msgdata,hsmd_ready_eltoo_channel,remote_funding_pubkey,pubkey, +msgdata,hsmd_ready_eltoo_channel,remote_settle_pubkey,pubkey, +msgdata,hsmd_ready_eltoo_channel,remote_shutdown_script_len,u16, +msgdata,hsmd_ready_eltoo_channel,remote_shutdown_script,u8,remote_shutdown_script_len +msgdata,hsmd_ready_eltoo_channel,channel_type,channel_type, + +# No value returned. +msgtype,hsmd_ready_eltoo_channel_reply,181 + +# Reply for all the above requests. +msgtype,hsmd_sign_update_tx_reply,162 +msgdata,hsmd_sign_update_tx_reply,sig,bip340sig, + +# Openingd/channeld asks HSM to sign the shared update tx. +#include +msgtype,hsmd_sign_update_tx,69 +msgdata,hsmd_sign_update_tx,update_tx,bitcoin_tx, +msgdata,hsmd_sign_update_tx,remote_funding_key,pubkey, +msgdata,hsmd_sign_update_tx,update_num,u64, +msgdata,hsmd_sign_update_tx,num_htlcs,u16, +msgdata,hsmd_sign_update_tx,htlcs,simple_htlc,num_htlcs + +msgtype,hsmd_validate_update_tx,95 +msgdata,hsmd_validate_update_tx,tx,bitcoin_tx, +msgdata,hsmd_validate_update_tx,num_htlcs,u16, +msgdata,hsmd_validate_update_tx,htlcs,simple_htlc,num_htlcs +msgdata,hsmd_validate_update_tx,update_num,u64, +msgdata,hsmd_validate_update_tx,sig,bip340sig, + +msgtype,hsmd_validate_update_tx_reply,195 diff --git a/openingd/common.c b/openingd/common.c index 1541e5ec7304..207732816442 100644 --- a/openingd/common.c +++ b/openingd/common.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -355,3 +356,31 @@ void validate_initial_commitment_signature(int hsm_fd, tal_hex(tmpctx, msg)); } +void validate_initial_update_signature(int hsm_fd, + struct bitcoin_tx *update_tx, + struct bip340sig *sig) +{ + struct existing_htlc **htlcs; + struct bitcoin_signature *htlc_sigs; + u64 update_num; + const u8 *msg; + + /* Validate the counterparty's signature. */ + htlcs = tal_arr(NULL, struct existing_htlc *, 0); + htlc_sigs = tal_arr(NULL, struct bitcoin_signature, 0); + update_num = 0; + msg = towire_hsmd_validate_update_tx(NULL, + update_tx, + (const struct simple_htlc **) htlcs, + update_num, + sig); + tal_free(htlc_sigs); + tal_free(htlcs); + wire_sync_write(hsm_fd, take(msg)); + msg = wire_sync_read(tmpctx, hsm_fd); + if (!fromwire_hsmd_validate_update_tx_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, + "Reading validate_commitment_tx reply: %s", + tal_hex(tmpctx, msg)); +} + diff --git a/openingd/common.h b/openingd/common.h index 61571cf6cf20..31eed31d5b3f 100644 --- a/openingd/common.h +++ b/openingd/common.h @@ -4,6 +4,7 @@ #include "config.h" struct amount_sat; +struct bip340sig; struct bitcoin_tx; struct bitcoin_signature; struct channel_config; @@ -34,4 +35,8 @@ u8 *no_upfront_shutdown_script(const tal_t *ctx, void validate_initial_commitment_signature(int hsm_fd, struct bitcoin_tx *tx, struct bitcoin_signature *sig); + +void validate_initial_update_signature(int hsm_fd, + struct bitcoin_tx *update_tx, + struct bip340sig *sig); #endif /* LIGHTNING_OPENINGD_COMMON_H */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 245c8a39c1af..16b918faa465 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -438,7 +438,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) static bool funder_finalize_channel_setup(struct eltoo_state *state, struct amount_msat local_msat, - struct bitcoin_signature *sig, + struct bip340sig *sig, struct bitcoin_tx **update_tx) { u8 *msg; @@ -450,7 +450,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /*~ Channel is ready; Report the channel parameters to the signer. */ /* FIXME hsmd messages need implementing. - msg = towire_hsmd_ready_channel(NULL, + msg = towire_hsmd_ready_eltoo_channel(NULL, true, state->funding_sats, state->push_msat, @@ -467,7 +467,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, wire_sync_write(HSM_FD, take(msg)); */ msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_ready_channel_reply(msg)) + if (!fromwire_hsmd_ready_eltoo_channel_reply(msg)) status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", tal_hex(tmpctx, msg)); @@ -551,24 +551,25 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, */ wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_tx_reply(msg, sig)) + if (!fromwire_hsmd_sign_update_tx_reply(msg, sig)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* You can tell this has been a problem before, since there's a debug * message here: */ status_debug("signature %s on tx %s using key %s", - type_to_string(tmpctx, struct bitcoin_signature, sig), + type_to_string(tmpctx, struct bip340sig, sig), type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey)); /* Now we give our peer the signature for their first commitment * transaction. */ + /* FIXME implement funding_created message msg = towire_funding_created(state, &state->channel_id, &state->funding.txid, state->funding.n, - &sig->s); + &sig->s);*/ peer_write(state->pps, msg); /* BOLT #2: @@ -590,10 +591,12 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!msg) goto fail; + /* FIXME implement funding_signed message sig->sighash_type = SIGHASH_ALL; if (!fromwire_funding_signed(msg, &id_in, &sig->s)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed: %s", tal_hex(msg, msg)); + */ /* BOLT #2: * * This message introduces the `channel_id` to identify the channel. @@ -632,9 +635,9 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * - if `signature` is incorrect OR non-compliant with LOW-S-standard rule...: * - MUST fail the channel */ - /* So we create *our* initial commitment transaction, and check the + /* So we create the initial update transaction, and check the * signature they sent against that. */ - validate_initial_commitment_signature(HSM_FD, *update_tx, sig); + validate_initial_update_signature(HSM_FD, *update_tx, sig); /* FIXME check psig if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) { @@ -672,7 +675,7 @@ static u8 *funder_channel_complete(struct eltoo_state *state) { /* Remote commitment tx */ struct bitcoin_tx *tx; - struct bitcoin_signature sig; + struct bip340sig sig; struct amount_msat local_msat; /* Update the billboard about what we're doing*/ @@ -712,13 +715,12 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* FIXME Can't these just be read into eltoo_keyset? */ struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; - struct bitcoin_signature theirsig, sig; + struct bip340sig theirsig, sig; struct bitcoin_tx *settle_tx, *update_tx; struct bitcoin_blkid chain_hash; u8 *msg = NULL; /* FIXME properly intiialize this */ - const u8 *wscript = NULL; /* FIXME get rid of this*/ u8 channel_flags = 0; /* FIXME properly intiialize this */ - u16 funding_txout; + u16 funding_txout = 0; /* FIXME actually initialize this */ char* err_reason; struct tlv_accept_channel_tlvs *accept_tlvs; struct tlv_open_channel_tlvs *open_tlvs = NULL; /* FIXME get this initialized */ @@ -895,6 +897,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* The message should be "funding_created" which tells us what funding * tx they generated; the sighash type is implied, so we set it here. */ + /* FIXME implement funding_created message theirsig.sighash_type = SIGHASH_ALL; if (!fromwire_funding_created(msg, &id_in, &state->funding.txid, @@ -902,6 +905,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &theirsig.s)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); + */ /* We only allow 16 bits for this on the wire. */ state->funding.n = funding_txout; @@ -918,25 +922,22 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) type_to_string(msg, struct channel_id, &id_in)); /*~ Channel is ready; Report the channel parameters to the signer. */ - /* FIXME implement HSM messages - msg = towire_hsmd_ready_channel(NULL, - false, + msg = towire_hsmd_ready_eltoo_channel(NULL, + /* is_outbound */ false, state->funding_sats, state->push_msat, &state->funding.txid, state->funding.n, - state->localconf.to_self_delay, + state->localconf.shared_delay, state->upfront_shutdown_script[LOCAL], state->local_upfront_shutdown_wallet_index, - &theirs, &their_funding_pubkey, - state->remoteconf.to_self_delay, + &their_settlement_pubkey, state->upfront_shutdown_script[REMOTE], state->channel_type); - */ wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_ready_channel_reply(msg)) + if (!fromwire_hsmd_ready_eltoo_channel_reply(msg)) status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", tal_hex(tmpctx, msg)); @@ -990,23 +991,10 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* FIXME bind update tx to funding output, then check partial sig */ - validate_initial_commitment_signature(HSM_FD, update_tx, &theirsig); - + validate_initial_update_signature(HSM_FD, update_tx, &theirsig); + /* FIXME check psig? if (!check_tx_sig(update_tx, 0, NULL, wscript, &their_funding_pubkey, &theirsig)) { - /* BOLT #1: - * - * ### The `error` and `warning` Messages - *... - * - when failure was caused by an invalid signature check: - * - SHOULD include the raw, hex-encoded transaction in reply - * to a `funding_created`, `funding_signed`, - * `closing_signed`, or `commitment_signed` message. - */ - /*~ This verbosity is not only useful for our own testing, but - * a courtesy to other implementaters whose brains may be so - * twisted by coding in Go, Scala and Rust that they can no - * longer read C code. */ peer_failed_err(state->pps, &state->channel_id, "Bad signature %s on tx %s using key %s", type_to_string(tmpctx, struct bitcoin_signature, @@ -1015,7 +1003,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) type_to_string(tmpctx, struct pubkey, &their_funding_pubkey)); } - + */ /* BOLT #2: * * This message introduces the `channel_id` to identify the @@ -1063,15 +1051,17 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) */ wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_tx_reply(msg, &sig)) + if (!fromwire_hsmd_sign_update_tx_reply(msg, &sig)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ + /* FIXME funding_signed logic assert(sig.sighash_type == SIGHASH_ALL); msg = towire_funding_signed(state, &state->channel_id, &sig.s); + */ return towire_openingd_eltoo_fundee(state, &state->remoteconf, update_tx, diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index 1c0b2c2c5226..abac5dcf3af7 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -31,7 +32,7 @@ msgdata,openingd_eltoo_init,dev_temporary_channel_id,?byte,32 msgtype,openingd_eltoo_funder_reply,6601 msgdata,openingd_eltoo_funder_reply,their_config,eltoo_channel_config, msgdata,openingd_eltoo_funder_reply,first_commit,bitcoin_tx, -msgdata,openingd_eltoo_funder_reply,first_update_psig,bitcoin_signature, +msgdata,openingd_eltoo_funder_reply,first_update_psig,bip340sig, msgdata,openingd_eltoo_funder_reply,minimum_depth,u32, msgdata,openingd_eltoo_funder_reply,remote_funding_key,pubkey, msgdata,openingd_eltoo_funder_reply,remote_settlement_key,pubkey, @@ -78,7 +79,7 @@ msgdata,openingd_eltoo_failed,reason,wirestring, msgtype,openingd_eltoo_fundee,6503 msgdata,openingd_eltoo_fundee,their_config,eltoo_channel_config, msgdata,openingd_eltoo_fundee,first_settlement,bitcoin_tx, -msgdata,openingd_eltoo_fundee,first_update_sig,bitcoin_signature, +msgdata,openingd_eltoo_fundee,first_update_sig,bip340sig, msgdata,openingd_eltoo_fundee,remote_fundingkey,pubkey, msgdata,openingd_eltoo_fundee,funding,bitcoin_outpoint, msgdata,openingd_eltoo_fundee,funding_satoshis,amount_sat, From 8e438fbe5e7058f0b55daf23ee101dbb52add709 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 23:04:42 -0400 Subject: [PATCH 098/283] Fixup fromwire_openingd_eltoo_funder_start --- openingd/eltoo_openingd.c | 8 ++------ openingd/eltoo_openingd_wire.csv | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 16b918faa465..2f1a4a96b61c 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -1148,18 +1148,14 @@ static u8 *handle_master_in(struct eltoo_state *state) switch (t) { case WIRE_OPENINGD_ELTOO_FUNDER_START: - /* FIXME - if (!fromwire_openingd_funder_start(state, msg, + if (!fromwire_openingd_eltoo_funder_start(state, msg, &state->funding_sats, &state->push_msat, &state->upfront_shutdown_script[LOCAL], &state->local_upfront_shutdown_wallet_index, - &state->feerate_per_kw, &state->channel_id, &channel_flags)) - master_badmsg(WIRE_OPENINGD_FUNDER_START, msg); - - */ + master_badmsg(WIRE_OPENINGD_ELTOO_FUNDER_START, msg); msg = funder_channel_start(state, channel_flags); /* We want to keep openingd alive, since we're not done yet */ if (msg) diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index abac5dcf3af7..a74a2e3890f4 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -48,7 +48,6 @@ msgdata,openingd_eltoo_funder_start,push_msat,amount_msat, msgdata,openingd_eltoo_funder_start,len_upfront,u16, msgdata,openingd_eltoo_funder_start,upfront_shutdown_script,u8,len_upfront msgdata,openingd_eltoo_funder_start,upfront_shutdown_wallet_index,?u32, -msgdata,openingd_eltoo_funder_start,feerate_per_kw,u32, msgdata,openingd_eltoo_funder_start,temporary_channel_id,channel_id, msgdata,openingd_eltoo_funder_start,channel_flags,u8, From e312b81fb2abc7898590d31bbf1c1f15847ef0f7 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 23:06:37 -0400 Subject: [PATCH 099/283] finish up handle_master_in --- openingd/eltoo_openingd.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 2f1a4a96b61c..c46967fe5627 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -1141,10 +1141,9 @@ static u8 *handle_master_in(struct eltoo_state *state) { u8 *msg = wire_sync_read(tmpctx, REQ_FD); enum eltoo_openingd_wire t = fromwire_peektype(msg); - u8 channel_flags = 0; /* FIXME intiailize properly */ - /* FIXME + u8 channel_flags; struct bitcoin_txid funding_txid; - u16 funding_txout;*/ + u16 funding_txout; switch (t) { case WIRE_OPENINGD_ELTOO_FUNDER_START: @@ -1162,15 +1161,13 @@ static u8 *handle_master_in(struct eltoo_state *state) wire_sync_write(REQ_FD, take(msg)); return NULL; case WIRE_OPENINGD_ELTOO_FUNDER_COMPLETE: - /* FIXME - if (!fromwire_openingd_funder_complete(state, msg, + if (!fromwire_openingd_eltoo_funder_complete(state, msg, &funding_txid, &funding_txout, &state->channel_type)) - master_badmsg(WIRE_OPENINGD_FUNDER_COMPLETE, msg); + master_badmsg(WIRE_OPENINGD_ELTOO_FUNDER_COMPLETE, msg); state->funding.txid = funding_txid; state->funding.n = funding_txout; - */ return funder_channel_complete(state); case WIRE_OPENINGD_ELTOO_FUNDER_CANCEL: /* We're aborting this, simple */ From 4e2d4e40a12b9a5bf149440f4a05261aa0e35c20 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 3 Aug 2022 23:20:53 -0400 Subject: [PATCH 100/283] All FIXMEs except p2p messages done --- openingd/eltoo_openingd.c | 59 ++++++++++----------------------------- 1 file changed, 15 insertions(+), 44 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index c46967fe5627..4f5878cfce82 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -449,9 +449,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, struct bitcoin_tx *settle_tx; /*~ Channel is ready; Report the channel parameters to the signer. */ - /* FIXME hsmd messages need implementing. msg = towire_hsmd_ready_eltoo_channel(NULL, - true, + /* is_outbound */ true, state->funding_sats, state->push_msat, &state->funding.txid, @@ -459,13 +458,11 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, state->localconf.shared_delay, state->upfront_shutdown_script[LOCAL], state->local_upfront_shutdown_wallet_index, - &state->their_points, &state->their_funding_pubkey, - state->remoteconf.to_self_delay, + &state->their_settlement_pubkey, state->upfront_shutdown_script[REMOTE], state->channel_type); wire_sync_write(HSM_FD, take(msg)); - */ msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_ready_eltoo_channel_reply(msg)) status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", @@ -519,7 +516,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!settle_tx) { negotiation_failed(state, "Could not make settle tx: %s", err_reason); - goto fail; + return false; } *update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel, &err_reason); @@ -527,7 +524,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!*update_tx) { negotiation_failed(state, "Could not make update tx: %s", err_reason); - goto fail; + return false; } /* We ask the HSM to sign their commitment transaction for us: it knows @@ -535,20 +532,13 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * witness script. It also needs the amount of the funding output, * as segwit signatures commit to that as well, even though it doesn't * explicitly appear in the transaction itself. */ - /* FIXME implement HSM signing message struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); - u32 feerate = 0; // unused since there are no htlcs - u64 commit_num = 0; + u64 update_num = 0; msg = towire_hsmd_sign_update_tx(NULL, - update_tx, - &state->channel->funding_pubkey[REMOTE], - &state->first_per_commitment_point[REMOTE], - channel_has(state->channel, - OPT_STATIC_REMOTEKEY), - commit_num, - (const struct simple_htlc **) htlcs, - feerate); - */ + *update_tx, + &state->channel->eltoo_keyset.other_funding_key, + update_num, + (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_sign_update_tx_reply(msg, sig)) @@ -589,7 +579,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * "cid" */ msg = opening_negotiate_msg(tmpctx, state, &cid); if (!msg) - goto fail; + return false; /* FIXME implement funding_signed message sig->sighash_type = SIGHASH_ALL; @@ -663,12 +653,6 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, peer_billboard(false, "Funding channel: opening negotiation succeeded"); return true; - -fail: - /* FIXME free whatever we allocate - tal_free(wscript); - */ - return false; } static u8 *funder_channel_complete(struct eltoo_state *state) @@ -1028,27 +1012,14 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) * commitment transaction, so it can broadcast the transaction knowing * that funds can be redeemed, if need be. */ - /* FIXME this is the 2nd commitment tx being signed, unnneeded? - remote_commit = initial_channel_tx(state, &wscript, state->channel, - &state->first_per_commitment_point[REMOTE], - REMOTE, direct_outputs, &err_reason); - */ /* Make HSM sign it */ - /* FIXME implement HSM signing message struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); - u32 feerate = 0; // unused since there are no htlcs - u64 commit_num = 0; - msg = towire_hsmd_sign_remote_commitment_tx(NULL, - remote_commit, - &state->channel->funding_pubkey[REMOTE], - &state->first_per_commitment_point[REMOTE], - channel_has(state->channel, - OPT_STATIC_REMOTEKEY), - commit_num, - (const struct simple_htlc **) htlcs, - feerate); - */ + msg = towire_hsmd_sign_update_tx(NULL, + update_tx, + &state->channel->eltoo_keyset.other_funding_key, + /* update_num */ 0, + (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_sign_update_tx_reply(msg, &sig)) From fc4b5c7b66a6bc8e6d7358f3eb051b2e305e4ad6 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 4 Aug 2022 11:02:57 -0400 Subject: [PATCH 101/283] Add eltoo peer wire changes --- wire/Makefile | 12 +++++++-- wire/eltoo_wire.csv | 60 +++++++++++++++++++++++++++++++++++++++++++++ wire/peer_wire.csv | 4 +++ 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 wire/eltoo_wire.csv diff --git a/wire/Makefile b/wire/Makefile index d6f1bf5f593b..94a6d53122b0 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -63,6 +63,7 @@ WIRE_BOLT_DEPS := $(BOLT_DEPS) tools/gen/impl_template tools/gen/header_template ALL_PEER_PATCHES := $(sort $(wildcard wire/extracted_peer*.patch)) ALL_ONION_PATCHES := $(sort $(wildcard wire/extracted_onion*.patch)) ALL_BOLT12_PATCHES := $(sort $(wildcard wire/extracted_bolt12*.patch)) +ALL_ELTOO_PATCHES := $(sort $(wildcard wire/extracted_eltoo*.patch)) # These are applied to the non-exp csvs to make the exp csvs. PEER_EXP_PATCHES := $(sort $(wildcard wire/extracted_peer_exp*.patch)) @@ -73,11 +74,12 @@ BOLT12_EXP_PATCHES := $(sort $(wildcard wire/extracted_bolt12_exp*.patch)) PEER_PATCHES := $(filter-out $(PEER_EXP_PATCHES),$(ALL_PEER_PATCHES)) ONION_PATCHES := $(filter-out $(ONION_EXP_PATCHES),$(ALL_ONION_PATCHES)) BOLT12_PATCHES := $(filter-out $(BOLT12_EXP_PATCHES),$(ALL_BOLT12_PATCHES)) +ELTOO_PATCHES := $(filter-out $(BOLT12_EXP_PATCHES),$(ALL_ELTOO_PATCHES)) # Explicit command to re-extract CSV from BOLTs and patch. # This is not a normal make depencency, since we don't want this # called implicitly. -# Note: You will need to run extract-bolt12-csv manually! +# Note: You will need to run extract-bolt12-csv and extract-eltoo-csv manually! extract-bolt-csv: extract-peer-csv extract-onion-csv extract-peer-csv: wire/peer_wire.csv.raw @@ -89,6 +91,9 @@ extract-onion-csv: wire/onion_wire.csv.raw extract-bolt12-csv: wire/bolt12_wire.csv.raw @set -e; T=wire/bolt12_wire.csv; trap "rm -f $$T.$$$$" 0; cp $< $$T.$$$$; for p in $(BOLT12_PATCHES); do echo APPLY $$p; patch $$T.$$$$ $$p; done; mv $$T.$$$$ $$T +extract-eltoo-csv: wire/eltoo_wire.csv.raw + @set -e; T=wire/eltoo_wire.csv; trap "rm -f $$T.$$$$" 0; cp $< $$T.$$$$; for p in $(ELTOO_PATCHES); do echo APPLY $$p; patch $$T.$$$$ $$p; done; mv $$T.$$$$ $$T + wire/peer_wire.csv.raw: bolt-precheck @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/0[127]*.md > $@ @@ -98,6 +103,9 @@ wire/onion_wire.csv.raw: bolt-precheck wire/bolt12_wire.csv.raw: bolt-precheck @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/12*.md > $@ +wire/eltoo_wire.csv.raw: bolt-precheck + @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/XX*.md > $@ + # How to make the exp versions from non-exp versions: wire/peer_exp_wire.csv: wire/peer_wire.csv $(PEER_EXP_PATCHES) @set -e; T=$@; trap "rm -f $$T.$$$$" 0; cp $< $$T.$$$$; for p in $(PEER_EXP_PATCHES); do echo APPLY $$p; patch $$T.$$$$ $$p; done; mv $$T.$$$$ $$T @@ -109,7 +117,7 @@ wire/bolt12_exp_wire.csv: wire/bolt12_wire.csv $(BOLT12_EXP_PATCHES) @set -e; T=$@; trap "rm -f $$T.$$$$" 0; cp $< $$T.$$$$; for p in $(BOLT12_EXP_PATCHES); do echo APPLY $$p; patch $$T.$$$$ $$p; done; mv $$T.$$$$ $$T # These can be deleted. -.INTERMEDIATE: wire/peer_wire.csv.raw wire/onion_wire.csv.raw wire/bolt12_wire.csv.raw +.INTERMEDIATE: wire/peer_wire.csv.raw wire/onion_wire.csv.raw wire/bolt12_wire.csv.raw wire/eltoo_wire.csv.raw # Explicit command to add patchfile for BOLT CSV's against current one. generate-bolt-csv-patch: bolt-precheck diff --git a/wire/eltoo_wire.csv b/wire/eltoo_wire.csv new file mode 100644 index 000000000000..fab1d797bfe4 --- /dev/null +++ b/wire/eltoo_wire.csv @@ -0,0 +1,60 @@ +msgtype,open_channel_eltoo,32768 +tlvtype,open_channel_tlvs,upfront_shutdown_script,0 +tlvdata,open_channel_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... +tlvtype,open_channel_tlvs,channel_type,1 +tlvdata,open_channel_tlvs,channel_type,type,byte,... +msgtype,accept_channel_eltoo,32769 +msgdata,accept_channel_eltoo,temporary_channel_id,byte,32 +msgdata,accept_channel_eltoo,dust_limit_satoshis,u64, +msgdata,accept_channel_eltoo,max_htlc_value_in_flight_msat,u64, +msgdata,accept_channel_eltoo,htlc_minimum_msat,u64, +msgdata,accept_channel_eltoo,minimum_depth,u32, +msgdata,accept_channel_eltoo,shared_delay,u16, +msgdata,accept_channel_eltoo,max_accepted_htlcs,u16, +msgdata,accept_channel_eltoo,funding_pubkey,point, +msgdata,accept_channel_eltoo,settlement_pubkey,point, +msgdata,accept_channel_eltoo,tlvs,accept_channel_tlvs, +tlvtype,accept_channel_tlvs,upfront_shutdown_script,0 +tlvdata,accept_channel_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... +tlvtype,accept_channel_tlvs,channel_type,1 +tlvdata,accept_channel_tlvs,channel_type,type,byte,... +msgtype,funding_created_eltoo,32770 +msgdata,funding_created_eltoo,temporary_channel_id,byte,32 +msgdata,funding_created_eltoo,funding_txid,sha256, +msgdata,funding_created_eltoo,funding_output_index,u16, +msgdata,funding_created_eltoo,update_psig,partial_sig, +msgdata,funding_created_eltoo,next_nonce,nonce, +msgtype,funding_signed_eltoo,32771 +msgdata,funding_signed_eltoo,channel_id,channel_id, +msgdata,funding_signed_eltoo,update_psig,partial_sig, +msgdata,funding_signed_eltoo,next_nonce,nonce, +msgtype,funding_locked_eltoo,36 +msgdata,funding_locked_eltoo,channel_id,channel_id, +msgtype,shutdown_eltoo,38 +msgdata,shutdown_eltoo,channel_id,channel_id, +msgdata,shutdown_eltoo,len,u16, +msgdata,shutdown_eltoo,scriptpubkey,byte,len +msgtype,closing_signed_eltoo,39 +msgdata,closing_signed_eltoo,channel_id,channel_id, +msgdata,closing_signed_eltoo,fee_satoshis,u64, +msgdata,closing_signed_eltoo,tlvs,closing_signed_eltoo_tlvs, +tlvtype,closing_signed_eltoo_tlvs,fee_range,1 +tlvdata,closing_signed_eltoo_tlvs,fee_range,min_fee_satoshis,u64, +tlvdata,closing_signed_eltoo_tlvs,fee_range,max_fee_satoshis,u64, +tlvtype,closing_signed_eltoo_tlvs,nonces,2 +tlvdata,closing_signed_eltoo_tlvs,nonces,nonce,nonce, +tlvtype,closing_signed_eltoo_tlvs,partial_sig,3 +tlvdata,closing_signed_eltoo_tlvs,partial_sig,partial_sig,partial_sig, +msgtype,update_signed,32772 +msgdata,update_signed,channel_id,channel_id, +msgdata,update_signed,update_psig,partial_sig, +msgdata,update_signed,next_nonce,nonce, +msgtype,update_signed_ack,32773 +msgdata,update_signed_ack,channel_id,channel_id, +msgdata,update_signed_ack,update_psig,partial_sig, +msgdata,update_signed_ack,next_nonce,nonce, +msgtype,channel_reestablish_eltoo,32773 +msgdata,channel_reestablish_eltoo,channel_id,channel_id, +msgdata,channel_reestablish_eltoo,last_update_number,u64, +msgdata,channel_reestablish_eltoo,update_psig,partial_sig, +msgdata,channel_reestablish_eltoo,next_nonce,nonce, diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index a028ddc66d92..3b36748bfe45 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -204,6 +204,10 @@ msgdata,closing_signed,tlvs,closing_signed_tlvs, tlvtype,closing_signed_tlvs,fee_range,1 tlvdata,closing_signed_tlvs,fee_range,min_fee_satoshis,u64, tlvdata,closing_signed_tlvs,fee_range,max_fee_satoshis,u64, +msgtype,update_noop,129,option_simplified_update +msgdata,update_noop,channel_id,channel_id, +msgtype,yield,138,option_simplified_update +msgdata,yield,channel_id,channel_id, msgtype,update_add_htlc,128 msgdata,update_add_htlc,channel_id,channel_id, msgdata,update_add_htlc,id,u64, From a2501b617eaf3c9de3d0d44a6a19c06bb4fb089f Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 4 Aug 2022 11:11:24 -0400 Subject: [PATCH 102/283] fixup --- channeld/channeld.c | 4 ++++ connectd/multiplex.c | 2 ++ gossipd/gossipd.c | 2 ++ openingd/dualopend.c | 6 ++++++ wire/peer_wire.c | 10 ++++++++++ 5 files changed, 24 insertions(+) diff --git a/channeld/channeld.c b/channeld/channeld.c index 72cd437bfdd2..8844388f3f29 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2240,6 +2240,10 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_SHUTDOWN: handle_peer_shutdown(peer, msg); return; + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: + /* FIXME handle these messages */ + return; #if EXPERIMENTAL_FEATURES case WIRE_STFU: diff --git a/connectd/multiplex.c b/connectd/multiplex.c index 54740a7b3c4f..ad5ee4a1edf2 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -291,6 +291,8 @@ static bool is_urgent(enum peer_wire type) case WIRE_PONG: case WIRE_COMMITMENT_SIGNED: case WIRE_REVOKE_AND_ACK: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: return true; }; diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index a776d294f457..5cda13e49c68 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -555,6 +555,8 @@ static void handle_recv_gossip(struct daemon *daemon, const u8 *outermsg) case WIRE_ACK_RBF: case WIRE_OBS2_ONION_MESSAGE: case WIRE_ONION_MESSAGE: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 2afcc4993586..5daa14b4c610 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -1295,6 +1295,8 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) case WIRE_WARNING: case WIRE_PING: case WIRE_PONG: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -1638,6 +1640,8 @@ static bool run_tx_interactive(struct state *state, case WIRE_REPLY_SHORT_CHANNEL_IDS_END: case WIRE_PING: case WIRE_PONG: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -3762,6 +3766,8 @@ static u8 *handle_peer_in(struct state *state) case WIRE_WARNING: case WIRE_PING: case WIRE_PONG: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 35089e48f1d7..7b886bf30be5 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -47,6 +47,8 @@ static bool unknown_type(enum peer_wire t) case WIRE_ACCEPT_CHANNEL2: case WIRE_INIT_RBF: case WIRE_ACK_RBF: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -101,6 +103,8 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_ACK_RBF: case WIRE_OBS2_ONION_MESSAGE: case WIRE_ONION_MESSAGE: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -155,6 +159,8 @@ bool is_msg_gossip_broadcast(const u8 *cursor) case WIRE_ACCEPT_CHANNEL2: case WIRE_INIT_RBF: case WIRE_ACK_RBF: + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -392,6 +398,10 @@ bool extract_channel_id(const u8 *in_pkt, struct channel_id *channel_id) * 2. data: * * [`channel_id`:`channel_id`] */ + case WIRE_UPDATE_NOOP: + /* FIXME add BOLT text here */ + case WIRE_YIELD: + /* FIXME add BOLT text here */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: /* BOLT-quiescent #2: From 5a59fe6cc6d56829e01434dfadfa6a78bc2dbe2a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 4 Aug 2022 12:18:28 -0400 Subject: [PATCH 103/283] working through compilation.... --- openingd/eltoo_openingd.c | 18 ++++++------------ wire/Makefile | 8 ++++++-- wire/eltoo_wire.csv | 38 ++++++++++++++++++++++++++++---------- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 4f5878cfce82..867203e4f476 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -286,8 +287,8 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) u8 *msg = NULL; /* FIXME make sure initialized otherwise */ u8 *funding_output_script; struct channel_id id_in; - struct tlv_open_channel_tlvs *open_tlvs = NULL; /* FIXME make sure initialized otherwise */ - struct tlv_accept_channel_tlvs *accept_tlvs = NULL; /* FIXME make sure initialized otherwise */ + struct tlv_open_channel_eltoo_tlvs *open_tlvs = NULL; /* FIXME make sure initialized otherwise */ + struct tlv_accept_channel_eltoo_tlvs *accept_tlvs = NULL; /* FIXME make sure initialized otherwise */ char *err_reason; status_debug("funder_channel_start"); @@ -304,7 +305,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) state->our_features, state->their_features); - open_tlvs = tlv_open_channel_tlvs_new(tmpctx); + open_tlvs = tlv_open_channel_eltoo_tlvs_new(tmpctx); open_tlvs->upfront_shutdown_script = state->upfront_shutdown_script[LOCAL]; @@ -318,7 +319,6 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) */ open_tlvs->channel_type = state->channel_type->features; - /* FIXME generate BOLT message for open_channel_eltoo msg = towire_open_channel_eltoo(NULL, &chainparams->genesis_blockhash, &state->channel_id, @@ -326,19 +326,13 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) state->push_msat, state->localconf.dust_limit, state->localconf.max_htlc_value_in_flight, - state->localconf.channel_reserve, state->localconf.htlc_minimum, state->localconf.shared_delay, state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, - &state->our_points.revocation, - &state->our_points.payment, - &state->our_points.delayed_payment, - &state->our_points.htlc, - &state->first_per_commitment_point[LOCAL], + &state->our_settlement_pubkey, channel_flags, open_tlvs); - */ peer_write(state->pps, take(msg)); /* This is usually a very transient state... */ @@ -707,7 +701,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) u16 funding_txout = 0; /* FIXME actually initialize this */ char* err_reason; struct tlv_accept_channel_tlvs *accept_tlvs; - struct tlv_open_channel_tlvs *open_tlvs = NULL; /* FIXME get this initialized */ + struct tlv_open_channel_eltoo_tlvs *open_tlvs = NULL; /* FIXME get this initialized */ struct wally_tx_output *direct_outputs[NUM_SIDES]; /* BOLT #2: diff --git a/wire/Makefile b/wire/Makefile index 94a6d53122b0..428422dddde4 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -13,7 +13,8 @@ WIRE_HEADERS := wire/onion_defs.h \ wire/channel_type_wiregen.h \ wire/bolt12$(EXP)_printgen.h \ wire/peer$(EXP)_printgen.h \ - wire/onion$(EXP)_printgen.h + wire/onion$(EXP)_printgen.h \ + wire/eltoo_wiregen.h # We don't include peer_printgen/onion_printgen here since most don't need it. WIRE_SRC := wire/wire_sync.c \ @@ -25,7 +26,8 @@ WIRE_SRC := wire/wire_sync.c \ wire/bolt12$(EXP)_wiregen.c \ wire/peer$(EXP)_wiregen.c \ wire/channel_type_wiregen.c \ - wire/onion$(EXP)_wiregen.c + wire/onion$(EXP)_wiregen.c \ + wire/eltoo_wiregen.c WIRE_PRINT_SRC := \ wire/onion$(EXP)_printgen.c \ @@ -40,11 +42,13 @@ $(WIRE_OBJS) $(WIRE_PRINT_OBJS): $(WIRE_HEADERS) # Make sure these depend on everything: in case we're experimental, # include non-experimental ones here so they get rebuilt. WIRE_NONEXP_SRC := wire/bolt12_wiregen.c \ + wire/eltoo_wiregen.c \ wire/peer_wiregen.c \ wire/onion_wiregen.c \ wire/onion_printgen.c \ wire/peer_printgen.c WIRE_NONEXP_HEADERS := wire/peer_wiregen.h \ + wire/eltoo_wiregen.h \ wire/onion_wiregen.h \ wire/bolt12_wiregen.h \ wire/peer_printgen.h \ diff --git a/wire/eltoo_wire.csv b/wire/eltoo_wire.csv index fab1d797bfe4..d27ab6c2afaa 100644 --- a/wire/eltoo_wire.csv +++ b/wire/eltoo_wire.csv @@ -1,8 +1,26 @@ +#include +#include +#include +#include + msgtype,open_channel_eltoo,32768 -tlvtype,open_channel_tlvs,upfront_shutdown_script,0 -tlvdata,open_channel_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... -tlvtype,open_channel_tlvs,channel_type,1 -tlvdata,open_channel_tlvs,channel_type,type,byte,... +msgdata,open_channel_eltoo,chain_hash,chain_hash, +msgdata,open_channel_eltoo,temporary_channel_id,byte,32 +msgdata,open_channel_eltoo,funding_satoshis,u64, +msgdata,open_channel_eltoo,push_msat,u64, +msgdata,open_channel_eltoo,dust_limit_satoshis,u64, +msgdata,open_channel_eltoo,max_htlc_value_in_flight_msat,u64, +msgdata,open_channel_eltoo,htlc_minimum_msat,u64, +msgdata,open_channel_eltoo,shared_delay,u16, +msgdata,open_channel_eltoo,max_accepted_htlcs,u16, +msgdata,open_channel_eltoo,funding_pubkey,point, +msgdata,open_channel_eltoo,settlement_pubkey,point, +msgdata,open_channel_eltoo,channel_flags,byte, +msgdata,open_channel_eltoo,tlvs,open_channel_eltoo_tlvs, +tlvtype,open_channel_eltoo_tlvs,upfront_shutdown_script,0 +tlvdata,open_channel_eltoo_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... +tlvtype,open_channel_eltoo_tlvs,channel_type,1 +tlvdata,open_channel_eltoo_tlvs,channel_type,type,byte,... msgtype,accept_channel_eltoo,32769 msgdata,accept_channel_eltoo,temporary_channel_id,byte,32 msgdata,accept_channel_eltoo,dust_limit_satoshis,u64, @@ -13,11 +31,11 @@ msgdata,accept_channel_eltoo,shared_delay,u16, msgdata,accept_channel_eltoo,max_accepted_htlcs,u16, msgdata,accept_channel_eltoo,funding_pubkey,point, msgdata,accept_channel_eltoo,settlement_pubkey,point, -msgdata,accept_channel_eltoo,tlvs,accept_channel_tlvs, -tlvtype,accept_channel_tlvs,upfront_shutdown_script,0 -tlvdata,accept_channel_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... -tlvtype,accept_channel_tlvs,channel_type,1 -tlvdata,accept_channel_tlvs,channel_type,type,byte,... +msgdata,accept_channel_eltoo,tlvs,accept_channel_eltoo_tlvs, +tlvtype,accept_channel_eltoo_tlvs,upfront_shutdown_script,0 +tlvdata,accept_channel_eltoo_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... +tlvtype,accept_channel_eltoo_tlvs,channel_type,1 +tlvdata,accept_channel_eltoo_tlvs,channel_type,type,byte,... msgtype,funding_created_eltoo,32770 msgdata,funding_created_eltoo,temporary_channel_id,byte,32 msgdata,funding_created_eltoo,funding_txid,sha256, @@ -53,7 +71,7 @@ msgtype,update_signed_ack,32773 msgdata,update_signed_ack,channel_id,channel_id, msgdata,update_signed_ack,update_psig,partial_sig, msgdata,update_signed_ack,next_nonce,nonce, -msgtype,channel_reestablish_eltoo,32773 +msgtype,channel_reestablish_eltoo,32774 msgdata,channel_reestablish_eltoo,channel_id,channel_id, msgdata,channel_reestablish_eltoo,last_update_number,u64, msgdata,channel_reestablish_eltoo,update_psig,partial_sig, From 9fd7208afa4a90eadbfdb5e9ae36cde8cee91120 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 4 Aug 2022 13:21:31 -0400 Subject: [PATCH 104/283] Partial sig stuff compiling --- bitcoin/pubkey.c | 26 ++++++++++++++++++++++++++ bitcoin/pubkey.h | 9 +++++++++ bitcoin/signature.c | 24 ++++++++++++++++++++++++ bitcoin/signature.h | 8 ++++++++ wire/eltoo_wire.csv | 1 + 5 files changed, 68 insertions(+) diff --git a/bitcoin/pubkey.c b/bitcoin/pubkey.c index 00ce2f1398ab..e5dd11333641 100644 --- a/bitcoin/pubkey.c +++ b/bitcoin/pubkey.c @@ -150,6 +150,32 @@ void towire_point32(u8 **pptr, const struct point32 *point32) towire(pptr, output, sizeof(output)); } +void fromwire_nonce(const u8 **cursor, size_t *max, struct nonce *nonce) +{ + u8 raw[66]; + + if (!fromwire(cursor, max, raw, sizeof(raw))) + return; + + if (!secp256k1_musig_pubnonce_parse(secp256k1_ctx, + &nonce->nonce, + raw)) { + SUPERVERBOSE("not a valid musig nonce"); + fromwire_fail(cursor, max); + } +} + +void towire_nonce(u8 **pptr, const struct nonce *nonce) +{ + u8 nonce_output[66]; + + secp256k1_musig_pubnonce_serialize(secp256k1_ctx, + nonce_output, + &nonce->nonce); + + towire(pptr, nonce_output, sizeof(nonce_output)); +} + static char *point32_to_hexstr(const tal_t *ctx, const struct point32 *point32) { u8 output[32]; diff --git a/bitcoin/pubkey.h b/bitcoin/pubkey.h index 3eb52add0645..47f32a09f0b9 100644 --- a/bitcoin/pubkey.h +++ b/bitcoin/pubkey.h @@ -6,6 +6,7 @@ #include #include #include +#include struct privkey; struct secret; @@ -26,6 +27,11 @@ struct point32 { /* Define pubkey_eq (no padding) */ STRUCTEQ_DEF(point32, 0, pubkey.data); +struct nonce { + /* Un-aggregated public nonce for MuSig2 */ + secp256k1_musig_pubnonce nonce; +}; + /* Convert from hex string of DER (scriptPubKey from validateaddress) */ bool pubkey_from_hexstr(const char *derstr, size_t derlen, struct pubkey *key); @@ -72,4 +78,7 @@ void fromwire_pubkey(const u8 **cursor, size_t *max, struct pubkey *pubkey); void towire_point32(u8 **pptr, const struct point32 *pubkey); void fromwire_point32(const u8 **cursor, size_t *max, struct point32 *pubkey); +void towire_nonce(u8 **pptr, const struct nonce *nonce); +void fromwire_nonce(const u8 **cursor, size_t *max, struct nonce *nonce); + #endif /* LIGHTNING_BITCOIN_PUBKEY_H */ diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 44dc04fb576a..d7d989e3fe8a 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -12,6 +12,10 @@ #include #include +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + #undef DEBUG #ifdef DEBUG # include @@ -668,6 +672,26 @@ void fromwire_bip340sig(const u8 **cursor, size_t *max, fromwire_u8_array(cursor, max, bip340sig->u8, sizeof(bip340sig->u8)); } +void towire_partial_sig(u8 **pptr, const struct partial_sig *p_sig) +{ + secp256k1_musig_partial_sig_serialize(secp256k1_ctx, *pptr, &p_sig->p_sig); +} + +void fromwire_partial_sig(const u8 **cursor, size_t *max, + struct partial_sig *p_sig) +{ + u8 raw[32]; + + + if (!fromwire(cursor, max, raw, sizeof(raw))) + return; + + if (!secp256k1_musig_partial_sig_parse(secp256k1_ctx, &p_sig->p_sig, raw)) { + SUPERVERBOSE("not a valid musig partial sig"); + fromwire_fail(cursor, max); + } +} + char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig) { return tal_hexstr(ctx, bip340sig->u8, sizeof(bip340sig->u8)); diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 203e53273f58..5e01adf03e72 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -29,6 +29,10 @@ struct bip340sig { u8 u8[64]; }; +struct partial_sig { + secp256k1_musig_partial_sig p_sig; +}; + #define SIGHASH_MASK 0x7F static inline bool sighash_single(enum sighash_type sighash_type) @@ -307,6 +311,10 @@ void towire_bip340sig(u8 **pptr, const struct bip340sig *bip340sig); void fromwire_bip340sig(const u8 **cursor, size_t *max, struct bip340sig *bip340sig); +void towire_partial_sig(u8 **pptr, const struct partial_sig *p_sig); +void fromwire_partial_sig(const u8 **cursor, size_t *max, + struct partial_sig *p_sig); + /* Get a hex string sig */ char *fmt_signature(const tal_t *ctx, const secp256k1_ecdsa_signature *sig); char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig); diff --git a/wire/eltoo_wire.csv b/wire/eltoo_wire.csv index d27ab6c2afaa..31bd10fad807 100644 --- a/wire/eltoo_wire.csv +++ b/wire/eltoo_wire.csv @@ -1,5 +1,6 @@ #include #include +#include #include #include From 6c81a1706a0bd2ae2584386e4ac4ebc1f670323a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 4 Aug 2022 13:52:38 -0400 Subject: [PATCH 105/283] All wire messages implemented for openingd eltoo --- hsmd/hsmd_eltoo_wire.csv | 3 +- openingd/common.c | 3 -- openingd/eltoo_openingd.c | 100 +++++++++++++++----------------------- 3 files changed, 42 insertions(+), 64 deletions(-) diff --git a/hsmd/hsmd_eltoo_wire.csv b/hsmd/hsmd_eltoo_wire.csv index 748db5981c95..dc2888a6e5b0 100644 --- a/hsmd/hsmd_eltoo_wire.csv +++ b/hsmd/hsmd_eltoo_wire.csv @@ -23,7 +23,8 @@ msgtype,hsmd_ready_eltoo_channel_reply,181 # Reply for all the above requests. msgtype,hsmd_sign_update_tx_reply,162 -msgdata,hsmd_sign_update_tx_reply,sig,bip340sig, +msgdata,hsmd_sign_update_tx_reply,p_sig,partial_sig, +msgdata,hsmd_sign_update_tx_reply,nonce,nonce, # Openingd/channeld asks HSM to sign the shared update tx. #include diff --git a/openingd/common.c b/openingd/common.c index 207732816442..ef858fd37575 100644 --- a/openingd/common.c +++ b/openingd/common.c @@ -361,20 +361,17 @@ void validate_initial_update_signature(int hsm_fd, struct bip340sig *sig) { struct existing_htlc **htlcs; - struct bitcoin_signature *htlc_sigs; u64 update_num; const u8 *msg; /* Validate the counterparty's signature. */ htlcs = tal_arr(NULL, struct existing_htlc *, 0); - htlc_sigs = tal_arr(NULL, struct bitcoin_signature, 0); update_num = 0; msg = towire_hsmd_validate_update_tx(NULL, update_tx, (const struct simple_htlc **) htlcs, update_num, sig); - tal_free(htlc_sigs); tal_free(htlcs); wire_sync_write(hsm_fd, take(msg)); msg = wire_sync_read(tmpctx, hsm_fd); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 867203e4f476..90882954f188 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -284,11 +284,11 @@ static void set_remote_upfront_shutdown(struct eltoo_state *state, * stop when we get to the part where we need the funding txid */ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) { - u8 *msg = NULL; /* FIXME make sure initialized otherwise */ + u8 *msg; u8 *funding_output_script; struct channel_id id_in; - struct tlv_open_channel_eltoo_tlvs *open_tlvs = NULL; /* FIXME make sure initialized otherwise */ - struct tlv_accept_channel_eltoo_tlvs *accept_tlvs = NULL; /* FIXME make sure initialized otherwise */ + struct tlv_open_channel_eltoo_tlvs *open_tlvs; + struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; char *err_reason; status_debug("funder_channel_start"); @@ -352,27 +352,20 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) * `payment_basepoint`, or `delayed_payment_basepoint` are not * valid secp256k1 pubkeys in compressed format. */ - /* FIXME generate BOLT message for accept_channel_eltoo - if (!fromwire_accept_channel(tmpctx, msg, &id_in, + if (!fromwire_accept_channel_eltoo(tmpctx, msg, &id_in, &state->remoteconf.dust_limit, &state->remoteconf.max_htlc_value_in_flight, - &state->remoteconf.channel_reserve, &state->remoteconf.htlc_minimum, &state->minimum_depth, - &state->remoteconf.to_self_delay, + &state->remoteconf.shared_delay, &state->remoteconf.max_accepted_htlcs, &state->their_funding_pubkey, - &state->their_points.revocation, - &state->their_points.payment, - &state->their_points.delayed_payment, - &state->their_points.htlc, - &state->first_per_commitment_point[REMOTE], + &state->their_settlement_pubkey, &accept_tlvs)) { peer_failed_err(state->pps, &state->channel_id, "Parsing accept_channel %s", tal_hex(msg, msg)); } - */ set_remote_upfront_shutdown(state, accept_tlvs->upfront_shutdown_script); /* BOLT #2: @@ -441,6 +434,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, char *err_reason; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct bitcoin_tx *settle_tx; + struct partial_sig update_psig; + struct nonce next_nonce; /*~ Channel is ready; Report the channel parameters to the signer. */ msg = towire_hsmd_ready_eltoo_channel(NULL, @@ -535,7 +530,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_update_tx_reply(msg, sig)) + if (!fromwire_hsmd_sign_update_tx_reply(msg, &update_psig, &next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -547,13 +542,13 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey)); - /* Now we give our peer the signature for their first commitment + /* Now we give our peer the partial signature for the first update * transaction. */ - /* FIXME implement funding_created message - msg = towire_funding_created(state, &state->channel_id, + msg = towire_funding_created_eltoo(state, &state->channel_id, &state->funding.txid, state->funding.n, - &sig->s);*/ + &update_psig, + &next_nonce); peer_write(state->pps, msg); /* BOLT #2: @@ -575,12 +570,10 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!msg) return false; - /* FIXME implement funding_signed message - sig->sighash_type = SIGHASH_ALL; - if (!fromwire_funding_signed(msg, &id_in, &sig->s)) + // FIXME ? sig->sighash_type = SIGHASH_ALL; + if (!fromwire_funding_signed_eltoo(msg, &id_in, &update_psig, &next_nonce)) peer_failed_err(state->pps, &state->channel_id, - "Parsing funding_signed: %s", tal_hex(msg, msg)); - */ + "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); /* BOLT #2: * * This message introduces the `channel_id` to identify the channel. @@ -621,6 +614,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, */ /* So we create the initial update transaction, and check the * signature they sent against that. */ + + /* FIXME we don't have full sig here... sign then check? */ validate_initial_update_signature(HSM_FD, *update_tx, sig); /* FIXME check psig @@ -693,16 +688,19 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* FIXME Can't these just be read into eltoo_keyset? */ struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; - struct bip340sig theirsig, sig; + struct bip340sig theirsig; struct bitcoin_tx *settle_tx, *update_tx; struct bitcoin_blkid chain_hash; - u8 *msg = NULL; /* FIXME properly intiialize this */ - u8 channel_flags = 0; /* FIXME properly intiialize this */ - u16 funding_txout = 0; /* FIXME actually initialize this */ + u8 *msg; + u8 channel_flags; + u16 funding_txout; char* err_reason; - struct tlv_accept_channel_tlvs *accept_tlvs; - struct tlv_open_channel_eltoo_tlvs *open_tlvs = NULL; /* FIXME get this initialized */ + struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; + struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; + /* FIXME split these up to their/ours tuple, or send over full sig in response? */ + struct partial_sig update_psig; + struct nonce next_nonce; /* BOLT #2: * @@ -712,30 +710,22 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) * `payment_basepoint`, or `delayed_payment_basepoint` are not valid * secp256k1 pubkeys in compressed format. */ - /* FIXME implement open_channel_eltoo message - if (!fromwire_open_channel(tmpctx, open_channel_msg, &chain_hash, + if (!fromwire_open_channel_eltoo(tmpctx, open_channel_msg, &chain_hash, &state->channel_id, &state->funding_sats, &state->push_msat, &state->remoteconf.dust_limit, &state->remoteconf.max_htlc_value_in_flight, - &state->remoteconf.channel_reserve, &state->remoteconf.htlc_minimum, - &state->feerate_per_kw, - &state->remoteconf.to_self_delay, + &state->remoteconf.shared_delay, &state->remoteconf.max_accepted_htlcs, &their_funding_pubkey, - &theirs.revocation, - &theirs.payment, - &theirs.delayed_payment, - &theirs.htlc, - &state->first_per_commitment_point[REMOTE], + &their_settlement_pubkey, &channel_flags, &open_tlvs)) peer_failed_err(state->pps, &state->channel_id, "Parsing open_channel %s", tal_hex(tmpctx, open_channel_msg)); - */ set_remote_upfront_shutdown(state, open_tlvs->upfront_shutdown_script); /* BOLT #2: @@ -837,7 +827,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->their_features); /* OK, we accept! */ - accept_tlvs = tlv_accept_channel_tlvs_new(tmpctx); + accept_tlvs = tlv_accept_channel_eltoo_tlvs_new(tmpctx); accept_tlvs->upfront_shutdown_script = state->upfront_shutdown_script[LOCAL]; /* BOLT #2: @@ -846,23 +836,16 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) */ accept_tlvs->channel_type = state->channel_type->features; - /* FIXME implement eltoo channel msgs msg = towire_accept_channel_eltoo(NULL, &state->channel_id, state->localconf.dust_limit, state->localconf.max_htlc_value_in_flight, - state->localconf.channel_reserve, state->localconf.htlc_minimum, state->minimum_depth, - state->localconf.to_self_delay, + state->localconf.shared_delay, state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, - &state->our_points.revocation, - &state->our_points.payment, - &state->our_points.delayed_payment, - &state->our_points.htlc, - &state->first_per_commitment_point[LOCAL], + &state->our_settlement_pubkey, accept_tlvs); - */ peer_write(state->pps, take(msg)); peer_billboard(false, @@ -875,15 +858,14 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* The message should be "funding_created" which tells us what funding * tx they generated; the sighash type is implied, so we set it here. */ - /* FIXME implement funding_created message - theirsig.sighash_type = SIGHASH_ALL; - if (!fromwire_funding_created(msg, &id_in, + // FIXME ? theirsig.sighash_type = SIGHASH_ALL; + if (!fromwire_funding_created_eltoo(msg, &id_in, &state->funding.txid, &funding_txout, - &theirsig.s)) + &update_psig, + &next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); - */ /* We only allow 16 bits for this on the wire. */ state->funding.n = funding_txout; @@ -1016,17 +998,15 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_update_tx_reply(msg, &sig)) + if (!fromwire_hsmd_sign_update_tx_reply(msg, &update_psig, &next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ - /* FIXME funding_signed logic - assert(sig.sighash_type == SIGHASH_ALL); - msg = towire_funding_signed(state, &state->channel_id, &sig.s); + // FIXME ? assert(sig.sighash_type == SIGHASH_ALL); + msg = towire_funding_signed_eltoo(state, &state->channel_id, &update_psig, &next_nonce); - */ return towire_openingd_eltoo_fundee(state, &state->remoteconf, update_tx, From 4aad440c315be035c1d6790f2f3c6df2e9e85af2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 4 Aug 2022 14:36:12 -0400 Subject: [PATCH 106/283] Validation wire --- hsmd/hsmd_eltoo_wire.csv | 2 +- openingd/common.c | 6 +++--- openingd/common.h | 2 +- openingd/eltoo_openingd.c | 30 +++++++++++++++--------------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/hsmd/hsmd_eltoo_wire.csv b/hsmd/hsmd_eltoo_wire.csv index dc2888a6e5b0..45dc82ef4ec3 100644 --- a/hsmd/hsmd_eltoo_wire.csv +++ b/hsmd/hsmd_eltoo_wire.csv @@ -40,6 +40,6 @@ msgdata,hsmd_validate_update_tx,tx,bitcoin_tx, msgdata,hsmd_validate_update_tx,num_htlcs,u16, msgdata,hsmd_validate_update_tx,htlcs,simple_htlc,num_htlcs msgdata,hsmd_validate_update_tx,update_num,u64, -msgdata,hsmd_validate_update_tx,sig,bip340sig, +msgdata,hsmd_validate_update_tx,p_sig,partial_sig, msgtype,hsmd_validate_update_tx_reply,195 diff --git a/openingd/common.c b/openingd/common.c index ef858fd37575..ba4d281bb560 100644 --- a/openingd/common.c +++ b/openingd/common.c @@ -358,20 +358,20 @@ void validate_initial_commitment_signature(int hsm_fd, void validate_initial_update_signature(int hsm_fd, struct bitcoin_tx *update_tx, - struct bip340sig *sig) + struct partial_sig *p_sig) { struct existing_htlc **htlcs; u64 update_num; const u8 *msg; - /* Validate the counterparty's signature. */ + /* Validate the counterparty's partial signature. */ htlcs = tal_arr(NULL, struct existing_htlc *, 0); update_num = 0; msg = towire_hsmd_validate_update_tx(NULL, update_tx, (const struct simple_htlc **) htlcs, update_num, - sig); + p_sig); tal_free(htlcs); wire_sync_write(hsm_fd, take(msg)); msg = wire_sync_read(tmpctx, hsm_fd); diff --git a/openingd/common.h b/openingd/common.h index 31eed31d5b3f..8e74b1b31319 100644 --- a/openingd/common.h +++ b/openingd/common.h @@ -38,5 +38,5 @@ void validate_initial_commitment_signature(int hsm_fd, void validate_initial_update_signature(int hsm_fd, struct bitcoin_tx *update_tx, - struct bip340sig *sig); + struct partial_sig *p_sig); #endif /* LIGHTNING_OPENINGD_COMMON_H */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 90882954f188..b6a94d66496c 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -434,8 +434,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, char *err_reason; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct bitcoin_tx *settle_tx; - struct partial_sig update_psig; - struct nonce next_nonce; + struct partial_sig our_update_psig, their_update_psig; + struct nonce our_next_nonce, their_next_nonce; /*~ Channel is ready; Report the channel parameters to the signer. */ msg = towire_hsmd_ready_eltoo_channel(NULL, @@ -530,7 +530,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_update_tx_reply(msg, &update_psig, &next_nonce)) + if (!fromwire_hsmd_sign_update_tx_reply(msg, &our_update_psig, &our_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -547,8 +547,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, msg = towire_funding_created_eltoo(state, &state->channel_id, &state->funding.txid, state->funding.n, - &update_psig, - &next_nonce); + &our_update_psig, + &our_next_nonce); peer_write(state->pps, msg); /* BOLT #2: @@ -571,7 +571,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, return false; // FIXME ? sig->sighash_type = SIGHASH_ALL; - if (!fromwire_funding_signed_eltoo(msg, &id_in, &update_psig, &next_nonce)) + if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &their_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); /* BOLT #2: @@ -615,8 +615,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /* So we create the initial update transaction, and check the * signature they sent against that. */ - /* FIXME we don't have full sig here... sign then check? */ - validate_initial_update_signature(HSM_FD, *update_tx, sig); + /* VLS type checks can go here... */ + validate_initial_update_signature(HSM_FD, *update_tx, &their_update_psig); /* FIXME check psig if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) { @@ -699,8 +699,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; /* FIXME split these up to their/ours tuple, or send over full sig in response? */ - struct partial_sig update_psig; - struct nonce next_nonce; + struct partial_sig our_update_psig, their_update_psig; + struct nonce our_next_nonce, their_next_nonce; /* BOLT #2: * @@ -862,8 +862,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) if (!fromwire_funding_created_eltoo(msg, &id_in, &state->funding.txid, &funding_txout, - &update_psig, - &next_nonce)) + &their_update_psig, + &their_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); /* We only allow 16 bits for this on the wire. */ @@ -951,7 +951,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* FIXME bind update tx to funding output, then check partial sig */ - validate_initial_update_signature(HSM_FD, update_tx, &theirsig); + validate_initial_update_signature(HSM_FD, update_tx, &their_update_psig); /* FIXME check psig? if (!check_tx_sig(update_tx, 0, NULL, wscript, &their_funding_pubkey, &theirsig)) { @@ -998,14 +998,14 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_update_tx_reply(msg, &update_psig, &next_nonce)) + if (!fromwire_hsmd_sign_update_tx_reply(msg, &our_update_psig, &our_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ // FIXME ? assert(sig.sighash_type == SIGHASH_ALL); - msg = towire_funding_signed_eltoo(state, &state->channel_id, &update_psig, &next_nonce); + msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &our_next_nonce); return towire_openingd_eltoo_fundee(state, &state->remoteconf, From 7a137c55d8a1540c6c8652beb32237a5d6898874 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 4 Aug 2022 15:41:16 -0400 Subject: [PATCH 107/283] Make eltoo BOLT processing more narrow --- wire/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/Makefile b/wire/Makefile index 428422dddde4..fc234db30f4b 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -108,7 +108,7 @@ wire/bolt12_wire.csv.raw: bolt-precheck @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/12*.md > $@ wire/eltoo_wire.csv.raw: bolt-precheck - @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/XX*.md > $@ + @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/XX-eltoo*.md > $@ # How to make the exp versions from non-exp versions: wire/peer_exp_wire.csv: wire/peer_wire.csv $(PEER_EXP_PATCHES) From af02f2334d26dd5884fe73ed16aff85fcf053ba8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 5 Aug 2022 09:46:12 -0400 Subject: [PATCH 108/283] Synchonize sighash usage --- bitcoin/signature.c | 4 ++-- bitcoin/signature.h | 2 +- channeld/test/run-settle_tx.c | 2 +- openingd/eltoo_openingd.c | 3 +-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index d7d989e3fe8a..6fb475c51c44 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -276,7 +276,7 @@ void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, const secp256k1_musig_pubnonce * const *pubnonces, size_t num_signers, - unsigned char *msg32, + struct sha256_double *msg32, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, secp256k1_musig_partial_sig *p_sig) @@ -290,7 +290,7 @@ void bipmusig_partial_sign(const struct privkey *privkey, assert(ok); - ok = secp256k1_musig_nonce_process(secp256k1_ctx, session, &agg_pubnonce, msg32, cache, NULL); + ok = secp256k1_musig_nonce_process(secp256k1_ctx, session, &agg_pubnonce, msg32->sha.u.u8, cache, NULL); assert(ok); diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 5e01adf03e72..a5df8b52c854 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -179,7 +179,7 @@ void bipmusig_partial_sign(const struct privkey *privkey, secp256k1_musig_secnonce *secnonce, const secp256k1_musig_pubnonce * const *pubnonces, size_t num_signers, - unsigned char *msg32, + struct sha256_double *msg32, secp256k1_musig_keyagg_cache *cache, secp256k1_musig_session *session, secp256k1_musig_partial_sig *p_sig); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 558177579851..2610159537a6 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -128,7 +128,7 @@ static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *a &secnonce[i], pubnonce_ptrs, 2, - msg_out.sha.u.u8, /* FIXME harmonize this to sha256_double */ + &msg_out, &keyagg_cache[i], &session[i], &p_sigs[i]); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index b6a94d66496c..670a1384c4c8 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -698,7 +698,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; - /* FIXME split these up to their/ours tuple, or send over full sig in response? */ struct partial_sig our_update_psig, their_update_psig; struct nonce our_next_nonce, their_next_nonce; @@ -949,7 +948,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) return NULL; } - /* FIXME bind update tx to funding output, then check partial sig */ + /* FIXME Sign and bind update tx */ validate_initial_update_signature(HSM_FD, update_tx, &their_update_psig); /* FIXME check psig? From a4ac5a84c14629ca4182a342a1fdeb056a79a1d2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 5 Aug 2022 12:41:56 -0400 Subject: [PATCH 109/283] compiling --- bitcoin/signature.h | 9 +++--- hsmd/hsmd_eltoo_wire.csv | 40 +++++++++++++++++------ hsmd/libhsmd.c | 10 ++++++ openingd/eltoo_openingd.c | 67 ++++++++++++++++++++++++++------------- wire/eltoo_wire.csv | 2 ++ 5 files changed, 92 insertions(+), 36 deletions(-) diff --git a/bitcoin/signature.h b/bitcoin/signature.h index a5df8b52c854..4595661615cb 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -148,13 +148,12 @@ void bipmusig_finalize_keys(struct pubkey *agg_pk, /** * bipmusig_gen_nonce - Generates session id, private - * and public nonce pair, assuming we already have - * a private and aggregated key. + * and public nonce pair * @secnonce: secret nonce to be generated. MUST NEVER BE MANUALLY COPIED OR PERSISTED!!! * @pubnonce: public nonce to be generated - * @privkey: privkey for this signing session - * @keyagg_cache: aggregated key cache - * @msg32: Optional 32 byte message for misuse resistance + * @privkey: privkey for this signing session (can be NULL) + * @keyagg_cache: aggregated key cache (can be NULL) + * @msg32: Optional 32 byte message for misuse resistance (can be NULL) */ void bipmusig_gen_nonce(secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, diff --git a/hsmd/hsmd_eltoo_wire.csv b/hsmd/hsmd_eltoo_wire.csv index 45dc82ef4ec3..8a0275e530d2 100644 --- a/hsmd/hsmd_eltoo_wire.csv +++ b/hsmd/hsmd_eltoo_wire.csv @@ -1,6 +1,8 @@ #include #include +#include #include + # Provide channel parameters. msgtype,hsmd_ready_eltoo_channel,81 msgdata,hsmd_ready_eltoo_channel,is_outbound,bool, @@ -22,18 +24,30 @@ msgdata,hsmd_ready_eltoo_channel,channel_type,channel_type, msgtype,hsmd_ready_eltoo_channel_reply,181 # Reply for all the above requests. -msgtype,hsmd_sign_update_tx_reply,162 -msgdata,hsmd_sign_update_tx_reply,p_sig,partial_sig, -msgdata,hsmd_sign_update_tx_reply,nonce,nonce, +msgtype,hsmd_psign_update_tx_reply,162 +msgdata,hsmd_psign_update_tx_reply,p_sig,partial_sig, +msgdata,hsmd_psign_update_tx_reply,nonce,nonce, # Openingd/channeld asks HSM to sign the shared update tx. #include -msgtype,hsmd_sign_update_tx,69 -msgdata,hsmd_sign_update_tx,update_tx,bitcoin_tx, -msgdata,hsmd_sign_update_tx,remote_funding_key,pubkey, -msgdata,hsmd_sign_update_tx,update_num,u64, -msgdata,hsmd_sign_update_tx,num_htlcs,u16, -msgdata,hsmd_sign_update_tx,htlcs,simple_htlc,num_htlcs +msgtype,hsmd_psign_update_tx,69 +# sus: we don't know channel id for opening? +msgdata,hsmd_psign_update_tx,channel_id,channel_id, +msgdata,hsmd_psign_update_tx,update_tx,bitcoin_tx, +msgdata,hsmd_psign_update_tx,settlement_tx,bitcoin_tx, +msgdata,hsmd_psign_update_tx,remote_funding_key,pubkey, +msgdata,hsmd_psign_update_tx,num_htlcs,u16, +msgdata,hsmd_psign_update_tx,htlcs,simple_htlc,num_htlcs + +msgtype,hsmd_combine_psig,92 +# sus: we don't know channel id for opening? +msgdata,hsmd_combine_psig,channel_id,channel_id, +msgdata,hsmd_combine_psig,p_sig_1,partial_sig, +msgdata,hsmd_combine_psig,p_sig_2,partial_sig, +msgdata,hsmd_combine_psig,update_tx,bitcoin_tx, + +msgtype,hsmd_combine_psig_reply,192 +msgdata,hsmd_combine_psig_reply,sig,bip340sig, msgtype,hsmd_validate_update_tx,95 msgdata,hsmd_validate_update_tx,tx,bitcoin_tx, @@ -43,3 +57,11 @@ msgdata,hsmd_validate_update_tx,update_num,u64, msgdata,hsmd_validate_update_tx,p_sig,partial_sig, msgtype,hsmd_validate_update_tx_reply,195 + +# Get musig public nonce for channel... FIXME channel_id completely +# ignored for now until storage model is figured +msgtype,hsmd_get_nonce,96 +msgdata,hsmd_get_nonce,channel_id,channel_id, + +msgtype,hsmd_get_nonce_reply,196 +msgdata,hsmd_get_nonce_reply,pubnonce,nonce, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 84f78de344d7..5c3f041e50a2 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,15 @@ struct { struct secret hsm_secret; struct ext_key bip32; secp256k1_keypair bolt12; + /* + * FIXME HACK: We only support on eltoo channel, to avoid unbounded state. + * What's the best architecture to support unbounded numbers of channels? + * We're just going to blindly assume this is the nonce for the eltoo channel + * signature operation.... + */ + struct channel_id musig_channel; + secp256k1_musig_secnonce sec_nonce; + secp256k1_musig_session session; } secretstuff; /* Have we initialized the secretstuff? */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 670a1384c4c8..ca5bd98c4da5 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -99,6 +99,10 @@ struct eltoo_state { struct channel_type *channel_type; struct feature_set *our_features; + + /* Nonces used for the next signing operation */ + struct nonce our_next_nonce; + struct nonce their_next_nonce; }; /*~ If we can't agree on parameters, we fail to open the channel. @@ -319,6 +323,17 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) */ open_tlvs->channel_type = state->channel_type->features; + /* Fetch MuSig nonce */ + msg = towire_hsmd_get_nonce(NULL, &state->channel_id); + peer_write(state->pps, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_get_nonce_reply(msg, &state->our_next_nonce)) { + peer_failed_err(state->pps, + &state->channel_id, + "Failed to get nonce for channel: %s", tal_hex(msg, msg)); + } + msg = towire_open_channel_eltoo(NULL, &chainparams->genesis_blockhash, &state->channel_id, @@ -332,6 +347,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->our_funding_pubkey, &state->our_settlement_pubkey, channel_flags, + &state->our_next_nonce, open_tlvs); peer_write(state->pps, take(msg)); @@ -361,6 +377,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->remoteconf.max_accepted_htlcs, &state->their_funding_pubkey, &state->their_settlement_pubkey, + &state->their_next_nonce, &accept_tlvs)) { peer_failed_err(state->pps, &state->channel_id, @@ -435,7 +452,6 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, struct wally_tx_output *direct_outputs[NUM_SIDES]; struct bitcoin_tx *settle_tx; struct partial_sig our_update_psig, their_update_psig; - struct nonce our_next_nonce, their_next_nonce; /*~ Channel is ready; Report the channel parameters to the signer. */ msg = towire_hsmd_ready_eltoo_channel(NULL, @@ -516,31 +532,31 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, return false; } - /* We ask the HSM to sign their commitment transaction for us: it knows + /* We ask the HSM to sign the update transaction for us: it knows * our funding key, it just needs the remote funding key to create the - * witness script. It also needs the amount of the funding output, - * as segwit signatures commit to that as well, even though it doesn't - * explicitly appear in the transaction itself. */ + * tapscripts. */ struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); - u64 update_num = 0; - msg = towire_hsmd_sign_update_tx(NULL, + msg = towire_hsmd_psign_update_tx(NULL, + &state->channel_id, *update_tx, + settle_tx, &state->channel->eltoo_keyset.other_funding_key, - update_num, (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_update_tx_reply(msg, &our_update_psig, &our_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* You can tell this has been a problem before, since there's a debug * message here: */ + /* FIXME stringify partial sigs status_debug("signature %s on tx %s using key %s", - type_to_string(tmpctx, struct bip340sig, sig), + type_to_string(tmpctx, struct partial_sig, sig), type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey)); + */ /* Now we give our peer the partial signature for the first update * transaction. */ @@ -548,15 +564,15 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->funding.txid, state->funding.n, &our_update_psig, - &our_next_nonce); + &state->our_next_nonce); peer_write(state->pps, msg); /* BOLT #2: * - * ### The `funding_signed` Message + * ### The `funding_signed_eltoo` Message * - * This message gives the funder the signature it needs for the first - * commitment transaction, so it can broadcast the transaction knowing + * This message gives the funder the partial signature it needs for the first + * update transaction, so it can broadcast the transaction knowing * that funds can be redeemed, if need be. */ peer_billboard(false, @@ -571,7 +587,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, return false; // FIXME ? sig->sighash_type = SIGHASH_ALL; - if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &their_next_nonce)) + if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &state->their_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); /* BOLT #2: @@ -616,7 +632,9 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * signature they sent against that. */ /* VLS type checks can go here... */ - validate_initial_update_signature(HSM_FD, *update_tx, &their_update_psig); + // validate_initial_update_signature(HSM_FD, *update_tx, &their_update_psig, &our_update_psig); + + /* Combine psigs and validate here */ /* FIXME check psig if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) { @@ -699,7 +717,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct partial_sig our_update_psig, their_update_psig; - struct nonce our_next_nonce, their_next_nonce; /* BOLT #2: * @@ -721,6 +738,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &their_funding_pubkey, &their_settlement_pubkey, &channel_flags, + &state->their_next_nonce, &open_tlvs)) peer_failed_err(state->pps, &state->channel_id, @@ -835,6 +853,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) */ accept_tlvs->channel_type = state->channel_type->features; + /* FIXME Fetch our first public nonce */ + + /* FIXME we can't actually know channel_id ??? */ msg = towire_accept_channel_eltoo(NULL, &state->channel_id, state->localconf.dust_limit, state->localconf.max_htlc_value_in_flight, @@ -844,6 +865,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, &state->our_settlement_pubkey, + &state->our_next_nonce, accept_tlvs); peer_write(state->pps, take(msg)); @@ -862,7 +884,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->funding.txid, &funding_txout, &their_update_psig, - &their_next_nonce)) + &state->their_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); /* We only allow 16 bits for this on the wire. */ @@ -990,21 +1012,22 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* Make HSM sign it */ struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); - msg = towire_hsmd_sign_update_tx(NULL, + msg = towire_hsmd_psign_update_tx(NULL, + &state->channel_id, update_tx, + settle_tx, &state->channel->eltoo_keyset.other_funding_key, - /* update_num */ 0, (const struct simple_htlc **) htlcs); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_sign_update_tx_reply(msg, &our_update_psig, &our_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ // FIXME ? assert(sig.sighash_type == SIGHASH_ALL); - msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &our_next_nonce); + msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &state->our_next_nonce); return towire_openingd_eltoo_fundee(state, &state->remoteconf, diff --git a/wire/eltoo_wire.csv b/wire/eltoo_wire.csv index 31bd10fad807..418381f99164 100644 --- a/wire/eltoo_wire.csv +++ b/wire/eltoo_wire.csv @@ -17,6 +17,7 @@ msgdata,open_channel_eltoo,max_accepted_htlcs,u16, msgdata,open_channel_eltoo,funding_pubkey,point, msgdata,open_channel_eltoo,settlement_pubkey,point, msgdata,open_channel_eltoo,channel_flags,byte, +msgdata,open_channel_eltoo,next_nonce,nonce, msgdata,open_channel_eltoo,tlvs,open_channel_eltoo_tlvs, tlvtype,open_channel_eltoo_tlvs,upfront_shutdown_script,0 tlvdata,open_channel_eltoo_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... @@ -32,6 +33,7 @@ msgdata,accept_channel_eltoo,shared_delay,u16, msgdata,accept_channel_eltoo,max_accepted_htlcs,u16, msgdata,accept_channel_eltoo,funding_pubkey,point, msgdata,accept_channel_eltoo,settlement_pubkey,point, +msgdata,accept_channel_eltoo,next_nonce,nonce, msgdata,accept_channel_eltoo,tlvs,accept_channel_eltoo_tlvs, tlvtype,accept_channel_eltoo_tlvs,upfront_shutdown_script,0 tlvdata,accept_channel_eltoo_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... From bf6263f1512db4d9a41c41b4ad19b144b641ea44 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 5 Aug 2022 13:35:53 -0400 Subject: [PATCH 110/283] both funding paths done? --- openingd/eltoo_openingd.c | 64 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index ca5bd98c4da5..6f862fe59d70 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -442,7 +442,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) static bool funder_finalize_channel_setup(struct eltoo_state *state, struct amount_msat local_msat, - struct bip340sig *sig, + struct bip340sig *update_sig, struct bitcoin_tx **update_tx) { u8 *msg; @@ -635,22 +635,22 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, // validate_initial_update_signature(HSM_FD, *update_tx, &their_update_psig, &our_update_psig); /* Combine psigs and validate here */ + /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ + msg = towire_hsmd_combine_psig(NULL, + &state->channel_id, + &our_update_psig, + &their_update_psig, + *update_tx); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_combine_psig_reply(msg, update_sig)) { + status_failed(STATUS_FAIL_HSM_IO, + "Bad combine_psig_reply_reply %s", tal_hex(tmpctx, msg)); + } - /* FIXME check psig - if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) { - peer_failed_err(state->pps, &state->channel_id, - "Bad signature %s on tx %s using key %s (channel_type=%s)", - type_to_string(tmpctx, struct bitcoin_signature, - sig), - type_to_string(tmpctx, struct bitcoin_tx, *tx), - type_to_string(tmpctx, struct pubkey, - &state->their_funding_pubkey), - fmt_featurebits(tmpctx, - state->channel->type->features)); - }*/ - - /* We save their sig to our first commitment tx */ - /* FIXME as a partial sig... how is this stored? + /* We save their sig to our first update tx */ + /* FIXME Store as taproot signature in PSBT once updated + or should we just sneak it in same way for now? if (!psbt_input_set_signature((*update_tx)->psbt, 0, &state->their_funding_pubkey, sig)) @@ -706,7 +706,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* FIXME Can't these just be read into eltoo_keyset? */ struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; - struct bip340sig theirsig; + struct bip340sig update_sig; struct bitcoin_tx *settle_tx, *update_tx; struct bitcoin_blkid chain_hash; u8 *msg; @@ -970,21 +970,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) return NULL; } - /* FIXME Sign and bind update tx */ - - validate_initial_update_signature(HSM_FD, update_tx, &their_update_psig); - /* FIXME check psig? - if (!check_tx_sig(update_tx, 0, NULL, wscript, &their_funding_pubkey, - &theirsig)) { - peer_failed_err(state->pps, &state->channel_id, - "Bad signature %s on tx %s using key %s", - type_to_string(tmpctx, struct bitcoin_signature, - &theirsig), - type_to_string(tmpctx, struct bitcoin_tx, update_tx), - type_to_string(tmpctx, struct pubkey, - &their_funding_pubkey)); - } - */ /* BOLT #2: * * This message introduces the `channel_id` to identify the @@ -1024,6 +1009,19 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); + /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ + msg = towire_hsmd_combine_psig(NULL, + &state->channel_id, + &our_update_psig, + &their_update_psig, + update_tx); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { + status_failed(STATUS_FAIL_HSM_IO, + "Bad combine_psig_reply_reply %s", tal_hex(tmpctx, msg)); + } + /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ // FIXME ? assert(sig.sighash_type == SIGHASH_ALL); @@ -1032,7 +1030,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) return towire_openingd_eltoo_fundee(state, &state->remoteconf, update_tx, - &theirsig, + &update_sig, &their_funding_pubkey, &state->funding, state->funding_sats, From f8fc3cf7e7da96c4f2ef2c1dabf519da17b5e580 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 09:26:35 -0400 Subject: [PATCH 111/283] Add nonce to shutdown_eltoo message Ran: make extract-bolt-csv BOLTDIR=../bolts BOLTVERSION=0c16c1fd19f03e4a5115c81f84ccd5afbff1695c --- bitcoin/signature.c | 3 ++- wire/eltoo_wire.csv | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 6fb475c51c44..b0231e580ac5 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -262,6 +262,7 @@ void bipmusig_gen_nonce(secp256k1_musig_secnonce *secnonce, const unsigned char *msg32) { /* MUST be unique for each signing attempt or SFYL */ + /* FIXME Does it help at all to get 32 more bytes of randomness? */ unsigned char session_id[32]; int ok; @@ -290,7 +291,7 @@ void bipmusig_partial_sign(const struct privkey *privkey, assert(ok); - ok = secp256k1_musig_nonce_process(secp256k1_ctx, session, &agg_pubnonce, msg32->sha.u.u8, cache, NULL); + ok = secp256k1_musig_nonce_process(secp256k1_ctx, session, &agg_pubnonce, msg32->sha.u.u8, cache, /* adaptor */ NULL); assert(ok); diff --git a/wire/eltoo_wire.csv b/wire/eltoo_wire.csv index 418381f99164..253415f98a90 100644 --- a/wire/eltoo_wire.csv +++ b/wire/eltoo_wire.csv @@ -55,6 +55,7 @@ msgtype,shutdown_eltoo,38 msgdata,shutdown_eltoo,channel_id,channel_id, msgdata,shutdown_eltoo,len,u16, msgdata,shutdown_eltoo,scriptpubkey,byte,len +msgdata,shutdown_eltoo,nonce,nonce, msgtype,closing_signed_eltoo,39 msgdata,closing_signed_eltoo,channel_id,channel_id, msgdata,closing_signed_eltoo,fee_satoshis,u64, From b9852f73fdb675f4e11e76ebce6771f0fcdaa2a0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 09:38:30 -0400 Subject: [PATCH 112/283] Update HSM signing protocol --- hsmd/hsmd_eltoo_wire.csv | 22 +++++++++------------- openingd/eltoo_openingd.c | 10 ++-------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/hsmd/hsmd_eltoo_wire.csv b/hsmd/hsmd_eltoo_wire.csv index 8a0275e530d2..7ce2ad2987e0 100644 --- a/hsmd/hsmd_eltoo_wire.csv +++ b/hsmd/hsmd_eltoo_wire.csv @@ -23,25 +23,21 @@ msgdata,hsmd_ready_eltoo_channel,channel_type,channel_type, # No value returned. msgtype,hsmd_ready_eltoo_channel_reply,181 -# Reply for all the above requests. -msgtype,hsmd_psign_update_tx_reply,162 -msgdata,hsmd_psign_update_tx_reply,p_sig,partial_sig, -msgdata,hsmd_psign_update_tx_reply,nonce,nonce, - -# Openingd/channeld asks HSM to sign the shared update tx. #include +# Dumb blind signer protocol for now, only send what's required +# to sign msgtype,hsmd_psign_update_tx,69 -# sus: we don't know channel id for opening? -msgdata,hsmd_psign_update_tx,channel_id,channel_id, +msgdata,hsmd_psign_update_tx,temp_channel_id,channel_id, msgdata,hsmd_psign_update_tx,update_tx,bitcoin_tx, -msgdata,hsmd_psign_update_tx,settlement_tx,bitcoin_tx, msgdata,hsmd_psign_update_tx,remote_funding_key,pubkey, -msgdata,hsmd_psign_update_tx,num_htlcs,u16, -msgdata,hsmd_psign_update_tx,htlcs,simple_htlc,num_htlcs +msgtype,hsmd_psign_update_tx_reply,162 +msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, +msgdata,hsmd_psign_update_tx_reply,next_nonce,nonce, + +# hsmd holds all signing state, send incomplete sig stuff msgtype,hsmd_combine_psig,92 -# sus: we don't know channel id for opening? -msgdata,hsmd_combine_psig,channel_id,channel_id, +msgdata,hsmd_combine_psig,temp_channel_id,channel_id, msgdata,hsmd_combine_psig,p_sig_1,partial_sig, msgdata,hsmd_combine_psig,p_sig_2,partial_sig, msgdata,hsmd_combine_psig,update_tx,bitcoin_tx, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 6f862fe59d70..30c6c26deebe 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -535,13 +535,10 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /* We ask the HSM to sign the update transaction for us: it knows * our funding key, it just needs the remote funding key to create the * tapscripts. */ - struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); msg = towire_hsmd_psign_update_tx(NULL, &state->channel_id, *update_tx, - settle_tx, - &state->channel->eltoo_keyset.other_funding_key, - (const struct simple_htlc **) htlcs); + &state->channel->eltoo_keyset.other_funding_key); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) @@ -996,13 +993,10 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) */ /* Make HSM sign it */ - struct simple_htlc **htlcs = tal_arr(tmpctx, struct simple_htlc *, 0); msg = towire_hsmd_psign_update_tx(NULL, &state->channel_id, update_tx, - settle_tx, - &state->channel->eltoo_keyset.other_funding_key, - (const struct simple_htlc **) htlcs); + &state->channel->eltoo_keyset.other_funding_key); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) From 24ba7bcac35e0b58b95b5ce5e4a651de992d5317 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 10:14:51 -0400 Subject: [PATCH 113/283] Checking --- hsmd/Makefile | 4 +-- hsmd/hsmd.c | 11 +++++++ hsmd/hsmd_eltoo_wire.csv | 63 --------------------------------------- hsmd/hsmd_wire.csv | 57 +++++++++++++++++++++++++++++++++++ hsmd/libhsmd.c | 25 ++++++++++++++++ openingd/common.c | 44 +++++++++++++-------------- openingd/common.h | 3 +- openingd/eltoo_openingd.c | 2 +- 8 files changed, 117 insertions(+), 92 deletions(-) delete mode 100644 hsmd/hsmd_eltoo_wire.csv diff --git a/hsmd/Makefile b/hsmd/Makefile index b6c7b300e3af..6fd4dac59704 100644 --- a/hsmd/Makefile +++ b/hsmd/Makefile @@ -2,10 +2,9 @@ HSMD_SRC := hsmd/hsmd.c \ hsmd/hsmd_wiregen.c \ - hsmd/hsmd_eltoo_wiregen.c \ hsmd/libhsmd.c -HSMD_HEADERS := hsmd/hsmd_wiregen.h hsmd/hsmd_eltoo_wiregen.h +HSMD_HEADERS := hsmd/hsmd_wiregen.h HSMD_OBJS := $(HSMD_SRC:.c=.o) $(HSMD_OBJS): $(HSMD_HEADERS) @@ -13,7 +12,6 @@ $(HSMD_OBJS): $(HSMD_HEADERS) # Other programs which use the hsm need this. HSMD_CLIENT_OBJS := \ hsmd/hsmd_wiregen.o \ - hsmd/hsmd_eltoo_wiregen.o \ common/htlc_wire.o # Make sure these depend on everything. diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 4ea0805c84aa..d1d9640d9b6a 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -666,6 +666,17 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_SIGN_LOCAL_HTLC_TX: case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US: case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: + /* Eltoo stuff here FIXME enable reacting to the messages*/ + case WIRE_HSMD_READY_ELTOO_CHANNEL: + case WIRE_HSMD_PSIGN_UPDATE_TX: + case WIRE_HSMD_COMBINE_PSIG: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: + + case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: + case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: + case WIRE_HSMD_COMBINE_PSIG_REPLY: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, take(hsmd_handle_client_message( diff --git a/hsmd/hsmd_eltoo_wire.csv b/hsmd/hsmd_eltoo_wire.csv deleted file mode 100644 index 7ce2ad2987e0..000000000000 --- a/hsmd/hsmd_eltoo_wire.csv +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#include - -# Provide channel parameters. -msgtype,hsmd_ready_eltoo_channel,81 -msgdata,hsmd_ready_eltoo_channel,is_outbound,bool, -msgdata,hsmd_ready_eltoo_channel,channel_value,amount_sat, -msgdata,hsmd_ready_eltoo_channel,push_value,amount_msat, -msgdata,hsmd_ready_eltoo_channel,funding_txid,bitcoin_txid, -msgdata,hsmd_ready_eltoo_channel,funding_txout,u16, -msgdata,hsmd_ready_eltoo_channel,shared_delay,u16, -msgdata,hsmd_ready_eltoo_channel,local_shutdown_script_len,u16, -msgdata,hsmd_ready_eltoo_channel,local_shutdown_script,u8,local_shutdown_script_len -msgdata,hsmd_ready_eltoo_channel,local_shutdown_wallet_index,?u32, -msgdata,hsmd_ready_eltoo_channel,remote_funding_pubkey,pubkey, -msgdata,hsmd_ready_eltoo_channel,remote_settle_pubkey,pubkey, -msgdata,hsmd_ready_eltoo_channel,remote_shutdown_script_len,u16, -msgdata,hsmd_ready_eltoo_channel,remote_shutdown_script,u8,remote_shutdown_script_len -msgdata,hsmd_ready_eltoo_channel,channel_type,channel_type, - -# No value returned. -msgtype,hsmd_ready_eltoo_channel_reply,181 - -#include -# Dumb blind signer protocol for now, only send what's required -# to sign -msgtype,hsmd_psign_update_tx,69 -msgdata,hsmd_psign_update_tx,temp_channel_id,channel_id, -msgdata,hsmd_psign_update_tx,update_tx,bitcoin_tx, -msgdata,hsmd_psign_update_tx,remote_funding_key,pubkey, - -msgtype,hsmd_psign_update_tx_reply,162 -msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, -msgdata,hsmd_psign_update_tx_reply,next_nonce,nonce, - -# hsmd holds all signing state, send incomplete sig stuff -msgtype,hsmd_combine_psig,92 -msgdata,hsmd_combine_psig,temp_channel_id,channel_id, -msgdata,hsmd_combine_psig,p_sig_1,partial_sig, -msgdata,hsmd_combine_psig,p_sig_2,partial_sig, -msgdata,hsmd_combine_psig,update_tx,bitcoin_tx, - -msgtype,hsmd_combine_psig_reply,192 -msgdata,hsmd_combine_psig_reply,sig,bip340sig, - -msgtype,hsmd_validate_update_tx,95 -msgdata,hsmd_validate_update_tx,tx,bitcoin_tx, -msgdata,hsmd_validate_update_tx,num_htlcs,u16, -msgdata,hsmd_validate_update_tx,htlcs,simple_htlc,num_htlcs -msgdata,hsmd_validate_update_tx,update_num,u64, -msgdata,hsmd_validate_update_tx,p_sig,partial_sig, - -msgtype,hsmd_validate_update_tx_reply,195 - -# Get musig public nonce for channel... FIXME channel_id completely -# ignored for now until storage model is figured -msgtype,hsmd_get_nonce,96 -msgdata,hsmd_get_nonce,channel_id,channel_id, - -msgtype,hsmd_get_nonce_reply,196 -msgdata,hsmd_get_nonce_reply,pubnonce,nonce, diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index a62edce8c520..150454da8be4 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -281,3 +281,60 @@ msgdata,hsmd_sign_option_will_fund_offer,channel_fee_proportional_basis_max,u16, msgtype,hsmd_sign_option_will_fund_offer_reply,126 msgdata,hsmd_sign_option_will_fund_offer_reply,rsig,secp256k1_ecdsa_signature, + +# ELTOO STUFF BELOW + +#include +#include +#include +#include + +# Provide channel parameters. +msgtype,hsmd_ready_eltoo_channel,81 +msgdata,hsmd_ready_eltoo_channel,is_outbound,bool, +msgdata,hsmd_ready_eltoo_channel,channel_value,amount_sat, +msgdata,hsmd_ready_eltoo_channel,push_value,amount_msat, +msgdata,hsmd_ready_eltoo_channel,funding_txid,bitcoin_txid, +msgdata,hsmd_ready_eltoo_channel,funding_txout,u16, +msgdata,hsmd_ready_eltoo_channel,shared_delay,u16, +msgdata,hsmd_ready_eltoo_channel,local_shutdown_script_len,u16, +msgdata,hsmd_ready_eltoo_channel,local_shutdown_script,u8,local_shutdown_script_len +msgdata,hsmd_ready_eltoo_channel,local_shutdown_wallet_index,?u32, +msgdata,hsmd_ready_eltoo_channel,remote_funding_pubkey,pubkey, +msgdata,hsmd_ready_eltoo_channel,remote_settle_pubkey,pubkey, +msgdata,hsmd_ready_eltoo_channel,remote_shutdown_script_len,u16, +msgdata,hsmd_ready_eltoo_channel,remote_shutdown_script,u8,remote_shutdown_script_len +msgdata,hsmd_ready_eltoo_channel,channel_type,channel_type, + +# No value returned. +msgtype,hsmd_ready_eltoo_channel_reply,181 + +#include +# Dumb blind signer protocol for now, only send what's required +# to sign +msgtype,hsmd_psign_update_tx,69 +msgdata,hsmd_psign_update_tx,channel_id,channel_id, +msgdata,hsmd_psign_update_tx,update_tx,bitcoin_tx, +msgdata,hsmd_psign_update_tx,remote_funding_key,pubkey, + +msgtype,hsmd_psign_update_tx_reply,162 +msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, +msgdata,hsmd_psign_update_tx_reply,next_nonce,nonce, + +msgtype,hsmd_validate_update_tx_psig,163 +msgdata,hsmd_validate_update_tx_psig,channel_id,channel_id, +msgdata,hsmd_validate_update_tx_psig,update_tx,bitcoin_tx, +msgdata,hsmd_validate_update_tx_psig,update_psig,partial_sig, + +# No payload +msgtype,hsmd_validate_update_tx_psig_reply,164 + +# hsmd holds all signing state, send incomplete sig stuff +msgtype,hsmd_combine_psig,92 +msgdata,hsmd_combine_psig,channel_id,channel_id, +msgdata,hsmd_combine_psig,p_sig_1,partial_sig, +msgdata,hsmd_combine_psig,p_sig_2,partial_sig, +msgdata,hsmd_combine_psig,update_tx,bitcoin_tx, + +msgtype,hsmd_combine_psig_reply,192 +msgdata,hsmd_combine_psig_reply,sig,bip340sig, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 5c3f041e50a2..543fdab044e9 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -129,6 +129,19 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_BOLT12: return (client->capabilities & HSM_CAP_MASTER) != 0; + /* Eltoo stuff here FIXME enable reacting to the messages*/ + case WIRE_HSMD_READY_ELTOO_CHANNEL: + case WIRE_HSMD_PSIGN_UPDATE_TX: + case WIRE_HSMD_COMBINE_PSIG: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: + + case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: + case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: + case WIRE_HSMD_COMBINE_PSIG_REPLY: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + break; + /* Eltoo stuff ends */ + /*~ These are messages sent by the HSM so we should never receive them. */ /* FIXME: Since we autogenerate these, we should really generate separate * enums for replies to avoid this kind of clutter! */ @@ -1603,6 +1616,18 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, return handle_sign_remote_htlc_to_us(client, msg); case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: return handle_sign_delayed_payment_to_us(client, msg); + /* Eltoo stuff here FIXME enable reacting to the messages*/ + case WIRE_HSMD_READY_ELTOO_CHANNEL: + case WIRE_HSMD_PSIGN_UPDATE_TX: + case WIRE_HSMD_COMBINE_PSIG: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: + + case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: + case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: + case WIRE_HSMD_COMBINE_PSIG_REPLY: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + break; + /* Eltoo stuff ends */ case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: diff --git a/openingd/common.c b/openingd/common.c index ba4d281bb560..2be6fe5d8652 100644 --- a/openingd/common.c +++ b/openingd/common.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -356,28 +355,25 @@ void validate_initial_commitment_signature(int hsm_fd, tal_hex(tmpctx, msg)); } -void validate_initial_update_signature(int hsm_fd, - struct bitcoin_tx *update_tx, - struct partial_sig *p_sig) +void validate_initial_update_psig(int hsm_fd, + struct channel_id *channel_id, + struct bitcoin_tx *update_tx, + struct partial_sig *p_sig) { - struct existing_htlc **htlcs; - u64 update_num; - const u8 *msg; - - /* Validate the counterparty's partial signature. */ - htlcs = tal_arr(NULL, struct existing_htlc *, 0); - update_num = 0; - msg = towire_hsmd_validate_update_tx(NULL, - update_tx, - (const struct simple_htlc **) htlcs, - update_num, - p_sig); - tal_free(htlcs); - wire_sync_write(hsm_fd, take(msg)); - msg = wire_sync_read(tmpctx, hsm_fd); - if (!fromwire_hsmd_validate_update_tx_reply(msg)) - status_failed(STATUS_FAIL_HSM_IO, - "Reading validate_commitment_tx reply: %s", - tal_hex(tmpctx, msg)); + struct existing_htlc **htlcs; + const u8 *msg; + + /* Validate the counterparty's partial signature. */ + htlcs = tal_arr(NULL, struct existing_htlc *, 0); + msg = towire_hsmd_validate_update_tx_psig(NULL, + channel_id, + update_tx, + p_sig); + tal_free(htlcs); + wire_sync_write(hsm_fd, take(msg)); + msg = wire_sync_read(tmpctx, hsm_fd); + if (!fromwire_hsmd_validate_update_tx_psig_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, + "Reading hsmd_validate_update_tx_psig reply: %s", + tal_hex(tmpctx, msg)); } - diff --git a/openingd/common.h b/openingd/common.h index 8e74b1b31319..c7394b4755f8 100644 --- a/openingd/common.h +++ b/openingd/common.h @@ -36,7 +36,8 @@ void validate_initial_commitment_signature(int hsm_fd, struct bitcoin_tx *tx, struct bitcoin_signature *sig); -void validate_initial_update_signature(int hsm_fd, +void validate_initial_update_psig(int hsm_fd, + struct channel_id *channel_id, struct bitcoin_tx *update_tx, struct partial_sig *p_sig); #endif /* LIGHTNING_OPENINGD_COMMON_H */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 30c6c26deebe..4cf56d20b461 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include From 30ee7383fc2b312bd2ba23680ce5a62098b9db28 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 10:16:47 -0400 Subject: [PATCH 114/283] fixup --- hsmd/hsmd.c | 2 ++ hsmd/hsmd_wire.csv | 8 ++++++++ hsmd/libhsmd.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index d1d9640d9b6a..2f569b3b107d 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -671,11 +671,13 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: + case WIRE_HSMD_GET_NONCE: case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + case WIRE_HSMD_GET_NONCE_REPLY: /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 150454da8be4..62692c686265 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -338,3 +338,11 @@ msgdata,hsmd_combine_psig,update_tx,bitcoin_tx, msgtype,hsmd_combine_psig_reply,192 msgdata,hsmd_combine_psig_reply,sig,bip340sig, + +# Get musig public nonce for channel... FIXME channel_id completely +# ignored for now until storage model is figured +msgtype,hsmd_get_nonce,96 +msgdata,hsmd_get_nonce,channel_id,channel_id, + +msgtype,hsmd_get_nonce_reply,196 +msgdata,hsmd_get_nonce_reply,pubnonce,nonce, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 543fdab044e9..1b84c4304f8d 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -134,11 +134,13 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: + case WIRE_HSMD_GET_NONCE: case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + case WIRE_HSMD_GET_NONCE_REPLY: break; /* Eltoo stuff ends */ @@ -1621,11 +1623,13 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: + case WIRE_HSMD_GET_NONCE: case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + case WIRE_HSMD_GET_NONCE_REPLY: break; /* Eltoo stuff ends */ From 7c68d97127397431721914213d1d788f0e6ab3b7 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 10:27:07 -0400 Subject: [PATCH 115/283] Implement hsm eltoo channel ready msg --- hsmd/hsmd.c | 11 +++++------ hsmd/libhsmd.c | 52 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 2f569b3b107d..0bc45482f8e3 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -672,12 +672,6 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: case WIRE_HSMD_GET_NONCE: - - case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: - case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: - case WIRE_HSMD_COMBINE_PSIG_REPLY: - case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: - case WIRE_HSMD_GET_NONCE_REPLY: /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, @@ -707,6 +701,11 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_SIGN_MESSAGE_REPLY: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: case WIRE_HSMD_SIGN_BOLT12_REPLY: + case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: + case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: + case WIRE_HSMD_COMBINE_PSIG_REPLY: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + case WIRE_HSMD_GET_NONCE_REPLY: return bad_req_fmt(conn, c, c->msg_in, "Received an incoming message of type %s, " "which is not a request", diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 1b84c4304f8d..f5988f1ee4ed 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -378,6 +378,46 @@ static u8 *handle_ready_channel(struct hsmd_client *c, const u8 *msg_in) return towire_hsmd_ready_channel_reply(NULL); } +/* ~This stub implementation is overriden by fully validating signers + * that need the unchanging channel parameters. */ +static u8 *handle_ready_eltoo_channel(struct hsmd_client *c, const u8 *msg_in) +{ + bool is_outbound; + struct amount_sat channel_value; + struct amount_msat push_value; + struct bitcoin_txid funding_txid; + u16 funding_txout; + u16 shared_delay; + u8 *local_shutdown_script; + u32 *local_shutdown_wallet_index; + struct pubkey remote_funding_pubkey, remote_settle_pubkey; + u8 *remote_shutdown_script; + struct amount_msat value_msat; + struct channel_type *channel_type; + + if (!fromwire_hsmd_ready_eltoo_channel(tmpctx, msg_in, &is_outbound, + &channel_value, &push_value, &funding_txid, + &funding_txout, &shared_delay, + &local_shutdown_script, + &local_shutdown_wallet_index, + &remote_funding_pubkey, + &remote_settle_pubkey, + &remote_shutdown_script, + &channel_type)) + return hsmd_status_malformed_request(c, msg_in); + + /* Stub implementation */ + + /* Fail fast if any values are uninitialized or obviously wrong. */ + assert(amount_sat_greater(channel_value, AMOUNT_SAT(0))); + assert(amount_sat_to_msat(&value_msat, channel_value)); + assert(amount_msat_less_eq(push_value, value_msat)); + assert(!mem_is_zero(&funding_txid, sizeof(funding_txid))); + assert(shared_delay > 0); + + return towire_hsmd_ready_eltoo_channel_reply(NULL); +} + /*~ For almost every wallet tx we use the BIP32 seed, but not for onchain * unilateral closes from a peer: they (may) have an output to us using a * public key based on the channel basepoints. It's a bit spammy to spend @@ -1620,16 +1660,11 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, return handle_sign_delayed_payment_to_us(client, msg); /* Eltoo stuff here FIXME enable reacting to the messages*/ case WIRE_HSMD_READY_ELTOO_CHANNEL: + return handle_ready_eltoo_channel(client, msg); case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: case WIRE_HSMD_GET_NONCE: - - case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: - case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: - case WIRE_HSMD_COMBINE_PSIG_REPLY: - case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: - case WIRE_HSMD_GET_NONCE_REPLY: break; /* Eltoo stuff ends */ @@ -1657,6 +1692,11 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_SIGN_MESSAGE_REPLY: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: case WIRE_HSMD_SIGN_BOLT12_REPLY: + case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: + case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: + case WIRE_HSMD_COMBINE_PSIG_REPLY: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + case WIRE_HSMD_GET_NONCE_REPLY: break; } return hsmd_status_bad_request(client, msg, "Unknown request"); From 711353a43cc87e89b9a09d3831ea29b8e5f5f207 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 10:29:35 -0400 Subject: [PATCH 116/283] Set hsmd eltoo capabilitiy to HSM_CAP_MASTER --- hsmd/libhsmd.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index f5988f1ee4ed..b06ace1cd36d 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -127,22 +127,12 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_MESSAGE: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: case WIRE_HSMD_SIGN_BOLT12: - return (client->capabilities & HSM_CAP_MASTER) != 0; - - /* Eltoo stuff here FIXME enable reacting to the messages*/ case WIRE_HSMD_READY_ELTOO_CHANNEL: case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: case WIRE_HSMD_GET_NONCE: - - case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: - case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: - case WIRE_HSMD_COMBINE_PSIG_REPLY: - case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: - case WIRE_HSMD_GET_NONCE_REPLY: - break; - /* Eltoo stuff ends */ + return (client->capabilities & HSM_CAP_MASTER) != 0; /*~ These are messages sent by the HSM so we should never receive them. */ /* FIXME: Since we autogenerate these, we should really generate separate @@ -170,6 +160,11 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_MESSAGE_REPLY: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: case WIRE_HSMD_SIGN_BOLT12_REPLY: + case WIRE_HSMD_READY_ELTOO_CHANNEL_REPLY: + case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: + case WIRE_HSMD_COMBINE_PSIG_REPLY: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: + case WIRE_HSMD_GET_NONCE_REPLY: break; } return false; From 370327da5ce7344ef224fa9e27c148d40deff358 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 12:56:34 -0400 Subject: [PATCH 117/283] Start implementing partial signature for update tx in hsmd --- hsmd/Makefile | 1 + hsmd/hsmd.c | 2 +- hsmd/hsmd_wire.csv | 4 ++ hsmd/libhsmd.c | 89 +++++++++++++++++++++++++++++++++++++++ openingd/eltoo_openingd.c | 12 +++++- 5 files changed, 105 insertions(+), 3 deletions(-) diff --git a/hsmd/Makefile b/hsmd/Makefile index 6fd4dac59704..01511802707c 100644 --- a/hsmd/Makefile +++ b/hsmd/Makefile @@ -49,6 +49,7 @@ HSMD_COMMON_OBJS := \ common/status_wiregen.o \ common/subdaemon.o \ common/type_to_string.o \ + common/update_tx.o \ common/utils.o \ common/utxo.o \ common/version.o \ diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 0bc45482f8e3..ed8d54bc7608 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -666,7 +666,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_SIGN_LOCAL_HTLC_TX: case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US: case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: - /* Eltoo stuff here FIXME enable reacting to the messages*/ + /* Eltoo stuff here */ case WIRE_HSMD_READY_ELTOO_CHANNEL: case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 62692c686265..a314b7b0686f 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -314,8 +314,12 @@ msgtype,hsmd_ready_eltoo_channel_reply,181 # to sign msgtype,hsmd_psign_update_tx,69 msgdata,hsmd_psign_update_tx,channel_id,channel_id, +msgdata,hsmd_psign_update_tx,id,node_id, +msgdata,hsmd_psign_update_tx,dbid,u64, msgdata,hsmd_psign_update_tx,update_tx,bitcoin_tx, +msgdata,hsmd_psign_update_tx,settle_tx,bitcoin_tx, msgdata,hsmd_psign_update_tx,remote_funding_key,pubkey, +msgdata,hsmd_psign_update_tx,remote_nonce,nonce, msgtype,hsmd_psign_update_tx_reply,162 msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index b06ace1cd36d..dcc9a04e7122 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,7 @@ struct { */ struct channel_id musig_channel; secp256k1_musig_secnonce sec_nonce; + struct nonce pub_nonce; secp256k1_musig_session session; } secretstuff; @@ -1345,6 +1347,92 @@ static u8 *handle_sign_penalty_to_us(struct hsmd_client *c, const u8 *msg_in) SIGHASH_ALL); } +/*~ This is another lightningd-only interface; signing a update transaction. + * We sign every single update transaction, so there's no danger here + * aside from signing bad state. + */ +static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) +{ + struct pubkey remote_funding_pubkey, local_funding_pubkey; + struct node_id peer_id; + u64 dbid; + struct secret channel_seed; + struct bitcoin_tx *update_tx, *settle_tx; + struct partial_sig p_sig; + struct secrets secrets; + struct nonce remote_nonce; + struct channel_id channel_id; + + /* MuSug stuff */ + secp256k1_xonly_pubkey xo_inner_pubkey; + secp256k1_musig_keyagg_cache keyagg_cache; + const struct pubkey *pubkey_ptrs[2]; + const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; + u8 *annex; + struct sha256_double hash_out; + + if (!fromwire_hsmd_psign_update_tx(tmpctx, msg_in, + &channel_id, + &peer_id, &dbid, + &update_tx, + &settle_tx, + &remote_funding_pubkey, + &remote_nonce)) + return hsmd_status_malformed_request(c, msg_in); + + update_tx->chainparams = c->chainparams; + settle_tx->chainparams = c->chainparams; + + /* Basic sanity checks. */ + if (update_tx->wtx->num_inputs != 1) + return hsmd_status_bad_request(c, msg_in, + "update tx must have 1 input"); + + if (update_tx->wtx->num_outputs != 1) + return hsmd_status_bad_request_fmt(c, msg_in, + "update tx must have 1 output"); + + get_channel_seed(&peer_id, dbid, &channel_seed); + derive_basepoints(&channel_seed, + &local_funding_pubkey, NULL, &secrets, NULL); + + /* Now that we have both public keys, we can derive the MuSig session */ + + annex = make_eltoo_annex(tmpctx, settle_tx); + pubkey_ptrs[0] = &remote_funding_pubkey; + pubkey_ptrs[1] = &local_funding_pubkey; + bipmusig_inner_pubkey(&xo_inner_pubkey, + &keyagg_cache, + pubkey_ptrs, + /* n_pubkeys */ 2); + + bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &hash_out); + + pubnonce_ptrs[0] = &remote_nonce.nonce; + pubnonce_ptrs[1] = &secretstuff.pub_nonce.nonce; + + /* FIXME assert we have secnonce already... though if we don't this call will already crash... */ + + bipmusig_partial_sign(&secrets.funding_privkey, + &secretstuff.sec_nonce, + pubnonce_ptrs, + /* num_signers */ 2, + &hash_out, + &keyagg_cache, + &secretstuff.session, + &p_sig.p_sig); + + /* Refill and return own next_nonce, using RNG+extra stuff for more security */ + bipmusig_gen_nonce(&secretstuff.sec_nonce, + &secretstuff.pub_nonce.nonce, + &secrets.funding_privkey, + &keyagg_cache, + hash_out.sha.u.u8); + + return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &secretstuff.pub_nonce); +} + + /*~ This is another lightningd-only interface; signing a commit transaction. * This is dangerous, since if we sign a revoked commitment tx we'll lose * funds, thus it's only available to lightningd. @@ -1657,6 +1745,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_READY_ELTOO_CHANNEL: return handle_ready_eltoo_channel(client, msg); case WIRE_HSMD_PSIGN_UPDATE_TX: + return handle_psign_update_tx(client, msg); case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: case WIRE_HSMD_GET_NONCE: diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 4cf56d20b461..d355677f8176 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -537,8 +537,12 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * tapscripts. */ msg = towire_hsmd_psign_update_tx(NULL, &state->channel_id, + NULL, // FIXME &state->channel->peer->id, + 0, // FIXME &state->channel->dbid, *update_tx, - &state->channel->eltoo_keyset.other_funding_key); + settle_tx, + &state->channel->eltoo_keyset.other_funding_key, + &state->their_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) @@ -995,8 +999,12 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* Make HSM sign it */ msg = towire_hsmd_psign_update_tx(NULL, &state->channel_id, + NULL, // FIXME &state->channel->peer->id, + 0, // FIXME &state->channel->dbid, update_tx, - &state->channel->eltoo_keyset.other_funding_key); + settle_tx, + &state->channel->eltoo_keyset.other_funding_key, + &state->their_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) From d9d0e51d0797b160f6cdcf2203245e8a349114bc Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 14:07:12 -0400 Subject: [PATCH 118/283] Merge the two peer BOLTs into one CSV --- channeld/channeld.c | 13 +++++++ common/type_to_string.h | 2 ++ connectd/multiplex.c | 13 +++++++ devtools/print_wire.c | 2 ++ devtools/print_wire.h | 2 ++ gossipd/gossipd.c | 12 +++++++ openingd/dualopend.c | 36 +++++++++++++++++++ openingd/eltoo_openingd.c | 1 - wire/Makefile | 8 +---- wire/eltoo_wire.csv | 20 ++++------- wire/peer_wire.c | 49 +++++++++++++++++++++++++ wire/peer_wire.csv | 76 +++++++++++++++++++++++++++++++++++++++ 12 files changed, 213 insertions(+), 21 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 8844388f3f29..8c64f190e91c 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2289,6 +2289,19 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_ERROR: case WIRE_OBS2_ONION_MESSAGE: case WIRE_ONION_MESSAGE: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ + abort(); } diff --git a/common/type_to_string.h b/common/type_to_string.h index 171ac476a843..e1e6f686808f 100644 --- a/common/type_to_string.h +++ b/common/type_to_string.h @@ -30,6 +30,8 @@ union printable_types { const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature; const struct bitcoin_signature *bitcoin_signature; const struct bip340sig *bip340sig; + const struct nonce *nonce; + const struct partial_sig *partial_sig; const struct channel *channel; const struct amount_msat *amount_msat; const struct amount_sat *amount_sat; diff --git a/connectd/multiplex.c b/connectd/multiplex.c index ad5ee4a1edf2..876d24ac039b 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -281,6 +281,17 @@ static bool is_urgent(enum peer_wire type) case WIRE_GOSSIP_TIMESTAMP_FILTER: case WIRE_OBS2_ONION_MESSAGE: case WIRE_ONION_MESSAGE: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ + #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -293,6 +304,8 @@ static bool is_urgent(enum peer_wire type) case WIRE_REVOKE_AND_ACK: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: return true; }; diff --git a/devtools/print_wire.c b/devtools/print_wire.c index f8b4acc1feaa..61f669c607ef 100644 --- a/devtools/print_wire.c +++ b/devtools/print_wire.c @@ -316,6 +316,8 @@ bool printwire_tlvs(const char *fieldname, const u8 **cursor, size_t *plen, #define PRINTWIRE_STRUCT_TYPE_TO_STRING(T) \ PRINTWIRE_TYPE_TO_STRING(struct T, T) +PRINTWIRE_STRUCT_TYPE_TO_STRING(partial_sig) +PRINTWIRE_STRUCT_TYPE_TO_STRING(nonce) PRINTWIRE_STRUCT_TYPE_TO_STRING(bip340sig) PRINTWIRE_STRUCT_TYPE_TO_STRING(bitcoin_blkid) PRINTWIRE_STRUCT_TYPE_TO_STRING(bitcoin_txid) diff --git a/devtools/print_wire.h b/devtools/print_wire.h index 3165e0e03abc..328ddecfa5d1 100644 --- a/devtools/print_wire.h +++ b/devtools/print_wire.h @@ -28,6 +28,8 @@ bool printwire_utf8_array(const char *fieldname, const u8 **cursor, size_t *plen bool printwire_tlvs(const char *tlv_name, const u8 **cursor, size_t *plen, const struct tlv_print_record_type types[], size_t num_types); +bool printwire_partial_sig(const char *fieldname, const u8 **cursor, size_t *plen); +bool printwire_nonce(const char *fieldname, const u8 **cursor, size_t *plen); bool printwire_bip340sig(const char *fieldname, const u8 **cursor, size_t *plen); bool printwire_bitcoin_blkid(const char *fieldname, const u8 **cursor, size_t *plen); bool printwire_wireaddr(const char *fieldname, const u8 **cursor, size_t *plen); diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 5cda13e49c68..3d9800c79611 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -557,6 +557,18 @@ static void handle_recv_gossip(struct daemon *daemon, const u8 *outermsg) case WIRE_ONION_MESSAGE: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 5daa14b4c610..d4efa7e5494a 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -1297,6 +1297,18 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) case WIRE_PONG: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -1642,6 +1654,18 @@ static bool run_tx_interactive(struct state *state, case WIRE_PONG: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -3768,6 +3792,18 @@ static u8 *handle_peer_in(struct state *state) case WIRE_PONG: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index d355677f8176..d534bbaa960d 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/wire/Makefile b/wire/Makefile index fc234db30f4b..c328a02f5da5 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -14,7 +14,6 @@ WIRE_HEADERS := wire/onion_defs.h \ wire/bolt12$(EXP)_printgen.h \ wire/peer$(EXP)_printgen.h \ wire/onion$(EXP)_printgen.h \ - wire/eltoo_wiregen.h # We don't include peer_printgen/onion_printgen here since most don't need it. WIRE_SRC := wire/wire_sync.c \ @@ -27,7 +26,6 @@ WIRE_SRC := wire/wire_sync.c \ wire/peer$(EXP)_wiregen.c \ wire/channel_type_wiregen.c \ wire/onion$(EXP)_wiregen.c \ - wire/eltoo_wiregen.c WIRE_PRINT_SRC := \ wire/onion$(EXP)_printgen.c \ @@ -42,13 +40,11 @@ $(WIRE_OBJS) $(WIRE_PRINT_OBJS): $(WIRE_HEADERS) # Make sure these depend on everything: in case we're experimental, # include non-experimental ones here so they get rebuilt. WIRE_NONEXP_SRC := wire/bolt12_wiregen.c \ - wire/eltoo_wiregen.c \ wire/peer_wiregen.c \ wire/onion_wiregen.c \ wire/onion_printgen.c \ wire/peer_printgen.c WIRE_NONEXP_HEADERS := wire/peer_wiregen.h \ - wire/eltoo_wiregen.h \ wire/onion_wiregen.h \ wire/bolt12_wiregen.h \ wire/peer_printgen.h \ @@ -67,7 +63,6 @@ WIRE_BOLT_DEPS := $(BOLT_DEPS) tools/gen/impl_template tools/gen/header_template ALL_PEER_PATCHES := $(sort $(wildcard wire/extracted_peer*.patch)) ALL_ONION_PATCHES := $(sort $(wildcard wire/extracted_onion*.patch)) ALL_BOLT12_PATCHES := $(sort $(wildcard wire/extracted_bolt12*.patch)) -ALL_ELTOO_PATCHES := $(sort $(wildcard wire/extracted_eltoo*.patch)) # These are applied to the non-exp csvs to make the exp csvs. PEER_EXP_PATCHES := $(sort $(wildcard wire/extracted_peer_exp*.patch)) @@ -78,7 +73,6 @@ BOLT12_EXP_PATCHES := $(sort $(wildcard wire/extracted_bolt12_exp*.patch)) PEER_PATCHES := $(filter-out $(PEER_EXP_PATCHES),$(ALL_PEER_PATCHES)) ONION_PATCHES := $(filter-out $(ONION_EXP_PATCHES),$(ALL_ONION_PATCHES)) BOLT12_PATCHES := $(filter-out $(BOLT12_EXP_PATCHES),$(ALL_BOLT12_PATCHES)) -ELTOO_PATCHES := $(filter-out $(BOLT12_EXP_PATCHES),$(ALL_ELTOO_PATCHES)) # Explicit command to re-extract CSV from BOLTs and patch. # This is not a normal make depencency, since we don't want this @@ -96,7 +90,7 @@ extract-bolt12-csv: wire/bolt12_wire.csv.raw @set -e; T=wire/bolt12_wire.csv; trap "rm -f $$T.$$$$" 0; cp $< $$T.$$$$; for p in $(BOLT12_PATCHES); do echo APPLY $$p; patch $$T.$$$$ $$p; done; mv $$T.$$$$ $$T extract-eltoo-csv: wire/eltoo_wire.csv.raw - @set -e; T=wire/eltoo_wire.csv; trap "rm -f $$T.$$$$" 0; cp $< $$T.$$$$; for p in $(ELTOO_PATCHES); do echo APPLY $$p; patch $$T.$$$$ $$p; done; mv $$T.$$$$ $$T + @set -e; T=wire/eltoo_wire.csv; trap "rm -f $$T.$$$$" 0; cp $< $$T.$$$$; for p in $(ELTOO_PATCHES); do echo APPLY $$p; patch $$T.$$$$ $$p; done; mv $$T.$$$$ $$T; cat wire/eltoo_wire.csv >> wire/peer_wire.csv wire/peer_wire.csv.raw: bolt-precheck @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/0[127]*.md > $@ diff --git a/wire/eltoo_wire.csv b/wire/eltoo_wire.csv index 253415f98a90..1ec067e13819 100644 --- a/wire/eltoo_wire.csv +++ b/wire/eltoo_wire.csv @@ -1,10 +1,4 @@ -#include -#include -#include -#include -#include - -msgtype,open_channel_eltoo,32768 +msgtype,open_channel_eltoo,32778 msgdata,open_channel_eltoo,chain_hash,chain_hash, msgdata,open_channel_eltoo,temporary_channel_id,byte,32 msgdata,open_channel_eltoo,funding_satoshis,u64, @@ -49,14 +43,14 @@ msgtype,funding_signed_eltoo,32771 msgdata,funding_signed_eltoo,channel_id,channel_id, msgdata,funding_signed_eltoo,update_psig,partial_sig, msgdata,funding_signed_eltoo,next_nonce,nonce, -msgtype,funding_locked_eltoo,36 +msgtype,funding_locked_eltoo,32772 msgdata,funding_locked_eltoo,channel_id,channel_id, -msgtype,shutdown_eltoo,38 +msgtype,shutdown_eltoo,32773 msgdata,shutdown_eltoo,channel_id,channel_id, msgdata,shutdown_eltoo,len,u16, msgdata,shutdown_eltoo,scriptpubkey,byte,len msgdata,shutdown_eltoo,nonce,nonce, -msgtype,closing_signed_eltoo,39 +msgtype,closing_signed_eltoo,32774 msgdata,closing_signed_eltoo,channel_id,channel_id, msgdata,closing_signed_eltoo,fee_satoshis,u64, msgdata,closing_signed_eltoo,tlvs,closing_signed_eltoo_tlvs, @@ -67,15 +61,15 @@ tlvtype,closing_signed_eltoo_tlvs,nonces,2 tlvdata,closing_signed_eltoo_tlvs,nonces,nonce,nonce, tlvtype,closing_signed_eltoo_tlvs,partial_sig,3 tlvdata,closing_signed_eltoo_tlvs,partial_sig,partial_sig,partial_sig, -msgtype,update_signed,32772 +msgtype,update_signed,32775 msgdata,update_signed,channel_id,channel_id, msgdata,update_signed,update_psig,partial_sig, msgdata,update_signed,next_nonce,nonce, -msgtype,update_signed_ack,32773 +msgtype,update_signed_ack,32776 msgdata,update_signed_ack,channel_id,channel_id, msgdata,update_signed_ack,update_psig,partial_sig, msgdata,update_signed_ack,next_nonce,nonce, -msgtype,channel_reestablish_eltoo,32774 +msgtype,channel_reestablish_eltoo,32777 msgdata,channel_reestablish_eltoo,channel_id,channel_id, msgdata,channel_reestablish_eltoo,last_update_number,u64, msgdata,channel_reestablish_eltoo,update_psig,partial_sig, diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 7b886bf30be5..507a041fd088 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -49,6 +49,18 @@ static bool unknown_type(enum peer_wire t) case WIRE_ACK_RBF: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -105,6 +117,18 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_ONION_MESSAGE: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -161,6 +185,18 @@ bool is_msg_gossip_broadcast(const u8 *cursor) case WIRE_ACK_RBF: case WIRE_UPDATE_NOOP: case WIRE_YIELD: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif @@ -402,6 +438,19 @@ bool extract_channel_id(const u8 *in_pkt, struct channel_id *channel_id) /* FIXME add BOLT text here */ case WIRE_YIELD: /* FIXME add BOLT text here */ + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_LOCKED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ + #if EXPERIMENTAL_FEATURES case WIRE_STFU: /* BOLT-quiescent #2: diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 3b36748bfe45..34057ee9cc41 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -342,3 +342,79 @@ msgtype,onion_message,513,option_onion_messages msgdata,onion_message,blinding,point, msgdata,onion_message,len,u16, msgdata,onion_message,onionmsg,byte,len +msgtype,open_channel_eltoo,32778 +msgdata,open_channel_eltoo,chain_hash,chain_hash, +msgdata,open_channel_eltoo,temporary_channel_id,byte,32 +msgdata,open_channel_eltoo,funding_satoshis,u64, +msgdata,open_channel_eltoo,push_msat,u64, +msgdata,open_channel_eltoo,dust_limit_satoshis,u64, +msgdata,open_channel_eltoo,max_htlc_value_in_flight_msat,u64, +msgdata,open_channel_eltoo,htlc_minimum_msat,u64, +msgdata,open_channel_eltoo,shared_delay,u16, +msgdata,open_channel_eltoo,max_accepted_htlcs,u16, +msgdata,open_channel_eltoo,funding_pubkey,point, +msgdata,open_channel_eltoo,settlement_pubkey,point, +msgdata,open_channel_eltoo,channel_flags,byte, +msgdata,open_channel_eltoo,next_nonce,nonce, +msgdata,open_channel_eltoo,tlvs,open_channel_eltoo_tlvs, +tlvtype,open_channel_eltoo_tlvs,upfront_shutdown_script,0 +tlvdata,open_channel_eltoo_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... +tlvtype,open_channel_eltoo_tlvs,channel_type,1 +tlvdata,open_channel_eltoo_tlvs,channel_type,type,byte,... +msgtype,accept_channel_eltoo,32769 +msgdata,accept_channel_eltoo,temporary_channel_id,byte,32 +msgdata,accept_channel_eltoo,dust_limit_satoshis,u64, +msgdata,accept_channel_eltoo,max_htlc_value_in_flight_msat,u64, +msgdata,accept_channel_eltoo,htlc_minimum_msat,u64, +msgdata,accept_channel_eltoo,minimum_depth,u32, +msgdata,accept_channel_eltoo,shared_delay,u16, +msgdata,accept_channel_eltoo,max_accepted_htlcs,u16, +msgdata,accept_channel_eltoo,funding_pubkey,point, +msgdata,accept_channel_eltoo,settlement_pubkey,point, +msgdata,accept_channel_eltoo,next_nonce,nonce, +msgdata,accept_channel_eltoo,tlvs,accept_channel_eltoo_tlvs, +tlvtype,accept_channel_eltoo_tlvs,upfront_shutdown_script,0 +tlvdata,accept_channel_eltoo_tlvs,upfront_shutdown_script,shutdown_scriptpubkey,byte,... +tlvtype,accept_channel_eltoo_tlvs,channel_type,1 +tlvdata,accept_channel_eltoo_tlvs,channel_type,type,byte,... +msgtype,funding_created_eltoo,32770 +msgdata,funding_created_eltoo,temporary_channel_id,byte,32 +msgdata,funding_created_eltoo,funding_txid,sha256, +msgdata,funding_created_eltoo,funding_output_index,u16, +msgdata,funding_created_eltoo,update_psig,partial_sig, +msgdata,funding_created_eltoo,next_nonce,nonce, +msgtype,funding_signed_eltoo,32771 +msgdata,funding_signed_eltoo,channel_id,channel_id, +msgdata,funding_signed_eltoo,update_psig,partial_sig, +msgdata,funding_signed_eltoo,next_nonce,nonce, +msgtype,funding_locked_eltoo,32772 +msgdata,funding_locked_eltoo,channel_id,channel_id, +msgtype,shutdown_eltoo,32773 +msgdata,shutdown_eltoo,channel_id,channel_id, +msgdata,shutdown_eltoo,len,u16, +msgdata,shutdown_eltoo,scriptpubkey,byte,len +msgdata,shutdown_eltoo,nonce,nonce, +msgtype,closing_signed_eltoo,32774 +msgdata,closing_signed_eltoo,channel_id,channel_id, +msgdata,closing_signed_eltoo,fee_satoshis,u64, +msgdata,closing_signed_eltoo,tlvs,closing_signed_eltoo_tlvs, +tlvtype,closing_signed_eltoo_tlvs,fee_range,1 +tlvdata,closing_signed_eltoo_tlvs,fee_range,min_fee_satoshis,u64, +tlvdata,closing_signed_eltoo_tlvs,fee_range,max_fee_satoshis,u64, +tlvtype,closing_signed_eltoo_tlvs,nonces,2 +tlvdata,closing_signed_eltoo_tlvs,nonces,nonce,nonce, +tlvtype,closing_signed_eltoo_tlvs,partial_sig,3 +tlvdata,closing_signed_eltoo_tlvs,partial_sig,partial_sig,partial_sig, +msgtype,update_signed,32775 +msgdata,update_signed,channel_id,channel_id, +msgdata,update_signed,update_psig,partial_sig, +msgdata,update_signed,next_nonce,nonce, +msgtype,update_signed_ack,32776 +msgdata,update_signed_ack,channel_id,channel_id, +msgdata,update_signed_ack,update_psig,partial_sig, +msgdata,update_signed_ack,next_nonce,nonce, +msgtype,channel_reestablish_eltoo,32777 +msgdata,channel_reestablish_eltoo,channel_id,channel_id, +msgdata,channel_reestablish_eltoo,last_update_number,u64, +msgdata,channel_reestablish_eltoo,update_psig,partial_sig, +msgdata,channel_reestablish_eltoo,next_nonce,nonce, From 3d5e2b98d4365e50ff85dbb1b1404646e942f97e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 9 Aug 2022 15:05:05 -0400 Subject: [PATCH 119/283] Look for ELTOO opener --- openingd/eltoo_openingd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index d534bbaa960d..fca59cca7055 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -1053,7 +1053,7 @@ static u8 *handle_peer_in(struct eltoo_state *state) struct channel_id channel_id; bool extracted; - if (t == WIRE_OPEN_CHANNEL) + if (t == WIRE_OPEN_CHANNEL_ELTOO) return fundee_channel(state, msg); /* Handles error cases. */ From 61064deae4f1a586b0ff9a6da0834e2c3cd0e3cc Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 09:37:17 -0400 Subject: [PATCH 120/283] Refactor everything to use compressed pubkeys except JIT blockchain usage --- bitcoin/script.c | 13 ++++++-- bitcoin/script.h | 2 +- bitcoin/signature.c | 24 ++++++++++++--- bitcoin/signature.h | 7 ++--- bitcoin/tx.c | 4 +-- bitcoin/tx.h | 4 +-- channeld/settle_tx.c | 2 +- channeld/test/run-settle_tx.c | 42 ++++++++++++++------------ common/initial_settlement_tx.c | 4 +-- common/initial_settlement_tx.h | 2 +- common/update_tx.c | 8 ++--- common/update_tx.h | 8 ++--- hsmd/hsmd_wire.csv | 2 ++ hsmd/libhsmd.c | 47 +++++++++++++++++++++++++++-- openingd/eltoo_openingd.c | 54 ++++++++++++++++++++++++---------- 15 files changed, 160 insertions(+), 63 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 8d595b363855..055e6c41af69 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1058,11 +1058,20 @@ void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, co assert(ok == WALLY_OK); } -u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *annex_hint, const secp256k1_xonly_pubkey *inner_pubkey, int parity_bit) +u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *annex_hint, const struct pubkey *inner_pubkey, int parity_bit) { int ok; u8 *control_block_cursor; u8 *control_block = tal_arr(ctx, u8, (other_script || annex_hint) ? 33 + 32 : 33); + secp256k1_xonly_pubkey xonly_inner_pubkey; + + ok = secp256k1_xonly_pubkey_from_pubkey( + secp256k1_ctx, + &xonly_inner_pubkey, + NULL /* pk_parity (this is parity bit from inner key, do not want */, + &inner_pubkey->pubkey); + + assert(ok); /* other_script and annex_hint are mutually exclusive args */ assert(!(other_script && annex_hint)); @@ -1081,7 +1090,7 @@ u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *an ok = secp256k1_xonly_pubkey_serialize( secp256k1_ctx, control_block_cursor, - inner_pubkey); + &xonly_inner_pubkey); assert(ok); control_block_cursor += 32; diff --git a/bitcoin/script.h b/bitcoin/script.h index 5922d8ebcdeb..956f532750a6 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -190,7 +190,7 @@ void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, co * @inner_pubkey: Inner pubkey for taproot control block * @parity_bit: Parity of outer taproot pubkey */ -u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *annex_hint, const secp256k1_xonly_pubkey *inner_pubkey, int parity_bit); +u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *annex_hint, const struct pubkey *inner_pubkey, int parity_bit); /* Creates tapscript that makes a sig-in-script ANYPREVOUTANYSCRIPT covenant * which commits to the tx argument: diff --git a/bitcoin/signature.c b/bitcoin/signature.c index b0231e580ac5..5073c245cf19 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -162,7 +162,7 @@ void bip340_sign_hash(const struct privkey *privkey, assert(secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &pubkey)); } -void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, +void bipmusig_inner_pubkey(struct pubkey *inner_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const struct pubkey * const* pubkeys, size_t n_pubkeys) @@ -189,12 +189,18 @@ void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, ok = secp256k1_musig_pubkey_agg(secp256k1_ctx, NULL /* scratch */, - inner_pubkey, + NULL /* agg_pk */, keyagg_cache, x_keys_ptr, n_pubkeys); assert(ok); + + ok = secp256k1_musig_pubkey_get(secp256k1_ctx, + &inner_pubkey->pubkey, + keyagg_cache); + + assert(ok); } void bipmusig_finalize_keys(struct pubkey *agg_pk, @@ -308,12 +314,22 @@ void bipmusig_partial_sign(const struct privkey *privkey, bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, size_t num_signers, - const secp256k1_xonly_pubkey *agg_pk, + const struct pubkey *agg_pk, secp256k1_musig_session *session, const struct sha256_double *hash, struct bip340sig *sig) { int ret; + secp256k1_xonly_pubkey xonly_inner_pubkey; + + ret = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, + &xonly_inner_pubkey, + NULL /* pk_parity */, + &agg_pk->pubkey); + + if (!ret) { + return false; + } ret = secp256k1_musig_partial_sig_agg(secp256k1_ctx, sig->u8, session, p_sigs, num_signers); @@ -321,7 +337,7 @@ bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * co return false; } - return secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), agg_pk); + return secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &xonly_inner_pubkey); } void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 4595661615cb..cb471b357017 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -114,13 +114,12 @@ void bip340_sign_hash(const struct privkey *privkey, /** * bipmusig_inner_pubkey - produce the sorted taproot inner pubkey using sort order. - * Can be used for signing for internal pubkey if keyagg_cache is non-NULL. - * @inner_pubkey: resulting aggregated(untweaked) x-only pubkey + * @inner_pubkey: resulting aggregated(untweaked) compressed pubkey * @keyagg_cache: cache for signing session for tapscript usage * @pubkeys: array of public keys to aggregate * @n_pubkeys: number of pubkeys in @pubkeys array */ -void bipmusig_inner_pubkey(secp256k1_xonly_pubkey *inner_pubkey, +void bipmusig_inner_pubkey(struct pubkey *inner_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const struct pubkey * const* pubkeys, size_t n_pubkeys); @@ -193,7 +192,7 @@ void bipmusig_partial_sign(const struct privkey *privkey, */ bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, size_t num_signers, - const secp256k1_xonly_pubkey *agg_pk, + const struct pubkey *agg_pk, secp256k1_musig_session *session, const struct sha256_double *hash, struct bip340sig *sig); diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 444e15694c18..d915f8ffa38f 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -186,7 +186,7 @@ void bitcoin_tx_set_locktime(struct bitcoin_tx *tx, u32 locktime) int bitcoin_tx_add_unbound_input(struct bitcoin_tx *tx, u32 sequence, struct amount_sat amount, - const secp256k1_xonly_pubkey *inner_pubkey) + const struct pubkey *inner_pubkey) { int wally_err; int input_num = tx->wtx->num_inputs; @@ -229,7 +229,7 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *outpoint, u32 sequence, const u8 *scriptSig, struct amount_sat amount, const u8 *scriptPubkey, - const u8 *input_wscript, const secp256k1_xonly_pubkey *inner_pubkey, + const u8 *input_wscript, const struct pubkey *inner_pubkey, const u8 *tap_tree) { /* FIXME use inner_pubkey and tap_tree */ diff --git a/bitcoin/tx.h b/bitcoin/tx.h index ffc133817024..b4a1cb0a1989 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -113,7 +113,7 @@ void bitcoin_tx_set_locktime(struct bitcoin_tx *tx, u32 locktime); int bitcoin_tx_add_unbound_input(struct bitcoin_tx *tx, u32 sequence, struct amount_sat amount, - const secp256k1_xonly_pubkey *inner_pubkey); + const struct pubkey *inner_pubkey); /* Add a new input to a bitcoin tx. * @@ -126,7 +126,7 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *outpoint, u32 sequence, const u8 *scriptSig, struct amount_sat amount, const u8 *scriptPubkey, - const u8 *input_wscript, const secp256k1_xonly_pubkey *inner_pubkey, const u8 * tap_tree); + const u8 *input_wscript, const struct pubkey *inner_pubkey, const u8 * tap_tree); /* Removes specified input from bitcoin tx */ void bitcoin_tx_remove_input(struct bitcoin_tx *tx, diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 0cbc00ab63df..65b4f1c684f2 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -113,7 +113,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, bool to_local, to_remote; struct htlc *dummy_to_local = (struct htlc *)0x01, *dummy_to_remote = (struct htlc *)0x02; - secp256k1_xonly_pubkey inner_pubkey; + struct pubkey inner_pubkey; const struct pubkey *pubkey_ptrs[2]; /* For non-initial settlement tx, we cannot safely * predict prevout, we will rebind this last second, diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 2610159537a6..690399343bd7 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -97,7 +97,7 @@ static struct secret secret_from_hex(const char *hex) return s; } -static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *alice_privkey, struct privkey *bob_privkey, secp256k1_xonly_pubkey *xo_inner_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache) +static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *alice_privkey, struct privkey *bob_privkey, struct pubkey *inner_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache) { u8 *final_sig; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; @@ -139,7 +139,7 @@ static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *a for (i=0; i<2; ++i){ ok = bipmusig_partial_sigs_combine_verify(p_sig_ptrs, 2, - xo_inner_pubkey, + inner_pubkey, &session[i], &msg_out, &sig); @@ -510,11 +510,11 @@ static int test_invalid_update_tx(void) /* Aggregation stuff */ secp256k1_musig_keyagg_cache keyagg_cache[2]; + struct pubkey inner_pubkey; const struct pubkey *pubkey_ptrs[2]; int i; /* MuSig signing stuff */ - secp256k1_xonly_pubkey xo_inner_pubkey; u8 *annex_0, *annex_1; u8 *final_sig; @@ -572,7 +572,7 @@ static int test_invalid_update_tx(void) /* Calculate inner pubkey, caches reused at end for tapscript signing */ for (i=0; i<2; ++i) { - bipmusig_inner_pubkey(&xo_inner_pubkey, + bipmusig_inner_pubkey(&inner_pubkey, &keyagg_cache[i], pubkey_ptrs, /* n_pubkeys */ 2); @@ -582,19 +582,19 @@ static int test_invalid_update_tx(void) update_tx = unbound_update_tx(tmpctx, tx, update_output_sats, - &xo_inner_pubkey, + &inner_pubkey, &err_reason); /* Signing happens next */ annex_0 = make_eltoo_annex(tmpctx, tx); - final_sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey, keyagg_cache); + final_sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* Re-bind, add final script/tapscript info into PSBT */ bind_update_tx_to_funding_outpoint(update_tx, tx, &update_output, &eltoo_keyset, - &xo_inner_pubkey, + &inner_pubkey, final_sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); @@ -627,19 +627,19 @@ static int test_invalid_update_tx(void) update_tx_1_A = unbound_update_tx(tmpctx, settle_tx_1, update_output_sats, - &xo_inner_pubkey, + &inner_pubkey, &err_reason); /* Authorize this next state update */ annex_1 = make_eltoo_annex(tmpctx, settle_tx_1); - final_sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey, keyagg_cache); + final_sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* This can RBF the first update tx */ bind_update_tx_to_funding_outpoint(update_tx_1_A, settle_tx_1, &update_output, &eltoo_keyset, - &xo_inner_pubkey, + &inner_pubkey, final_sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx_1_A->psbt); @@ -652,7 +652,7 @@ static int test_invalid_update_tx(void) &eltoo_keyset, annex_0, /* annex you see on chain */ obscured_update_number - 1, /* locktime you see on old update tx */ - &xo_inner_pubkey, + &inner_pubkey, final_sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx_1_A->psbt); @@ -685,7 +685,7 @@ static int test_initial_settlement_tx(void) int i; /* MuSig signing stuff */ - secp256k1_xonly_pubkey xo_inner_pubkey; + struct pubkey inner_pubkey; u8 *annex; u8 *final_sig; @@ -743,7 +743,7 @@ static int test_initial_settlement_tx(void) /* Calculate inner pubkey, caches reused at end for tapscript signing */ for (i=0; i<2; ++i) { - bipmusig_inner_pubkey(&xo_inner_pubkey, + bipmusig_inner_pubkey(&inner_pubkey, &keyagg_cache[i], pubkey_ptrs, /* n_pubkeys */ 2); @@ -753,7 +753,7 @@ static int test_initial_settlement_tx(void) update_tx = unbound_update_tx(tmpctx, tx, update_output_sats, - &xo_inner_pubkey, + &inner_pubkey, &err_reason); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); @@ -761,7 +761,7 @@ static int test_initial_settlement_tx(void) /* Signing happens next */ annex = make_eltoo_annex(tmpctx, tx); - final_sig = musig_sign(update_tx, annex, &alice_funding_privkey, &bob_funding_privkey, &xo_inner_pubkey, keyagg_cache); + final_sig = musig_sign(update_tx, annex, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* We want to close the channel without cooperation... time to rebind and finalize */ @@ -770,7 +770,7 @@ static int test_initial_settlement_tx(void) tx, &update_output, &eltoo_keyset, - &xo_inner_pubkey, + &inner_pubkey, final_sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); @@ -791,7 +791,8 @@ static int test_htlc_output_creation(void) /* 0-value hash image */ unsigned char *invoice_hash = tal_arr(tmpctx, u8, 20); struct sha256 tap_merkle_root; - secp256k1_xonly_pubkey inner_pubkey; + struct pubkey inner_pubkey; + secp256k1_xonly_pubkey xonly_inner_pubkey; unsigned char inner_pubkey_bytes[32]; secp256k1_musig_keyagg_cache keyagg_cache; unsigned char tap_tweak_out[32]; @@ -814,7 +815,12 @@ static int test_htlc_output_creation(void) pubkey_ptrs, /* n_pubkeys */ 1); - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, &inner_pubkey); + ok = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, + &xonly_inner_pubkey, + NULL /* pk_parity */, + &inner_pubkey.pubkey); + + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, &xonly_inner_pubkey); assert(ok); htlc_success_script = make_eltoo_htlc_success_script(tmpctx, &settlement_pubkey, invoice_hash); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 23314ed735fb..da6b2f338263 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -50,7 +50,7 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) } void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *update_outpoint, - struct amount_sat update_outpoint_sats, u32 shared_delay, secp256k1_xonly_pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]) + struct amount_sat update_outpoint_sats, u32 shared_delay, const struct pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]) { u8 *dummy_script; int input_num; @@ -134,7 +134,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* There is a direct output and possibly a shared anchor output */ const void *output_order[NUM_SIDES + 1]; const struct pubkey *pubkey_ptrs[2]; - secp256k1_xonly_pubkey inner_pubkey; + struct pubkey inner_pubkey; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 262cfb382efd..73b8007bffbb 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -45,6 +45,6 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx); int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *eltoo_keyset, struct amount_msat pay, enum side receiver); -void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, u32 shared_delay, secp256k1_xonly_pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]); +void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, u32 shared_delay, const struct pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]); #endif /* LIGHTNING_COMMON_INITIAL_SETTLEMENT_TX_H */ diff --git a/common/update_tx.c b/common/update_tx.c index fc8220faad5f..5ac7b4372678 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -51,7 +51,7 @@ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) return annex; } -void tx_add_unbound_input(struct bitcoin_tx *update_tx, struct amount_sat funding_sats, const secp256k1_xonly_pubkey *inner_pubkey) +void tx_add_unbound_input(struct bitcoin_tx *update_tx, struct amount_sat funding_sats, const struct pubkey *inner_pubkey) { int input_num; @@ -66,7 +66,7 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, const struct eltoo_keyset *eltoo_keyset, - secp256k1_xonly_pubkey *psbt_inner_pubkey, + const struct pubkey *psbt_inner_pubkey, u8 *final_sig) { const struct pubkey *pubkey_ptrs[2]; @@ -126,7 +126,7 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, const struct eltoo_keyset *eltoo_keyset, const u8 *invalidated_annex_hint, u32 invalidated_update_number, - secp256k1_xonly_pubkey *psbt_inner_pubkey, + struct pubkey *psbt_inner_pubkey, u8 *final_sig) { const struct pubkey *pubkey_ptrs[2]; @@ -188,7 +188,7 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, struct amount_sat funding_sats, - const secp256k1_xonly_pubkey *inner_pubkey, + const struct pubkey *inner_pubkey, char** err_reason) { struct bitcoin_tx *update_tx; diff --git a/common/update_tx.h b/common/update_tx.h index d32f9dc33b61..085f9df32d2f 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -19,7 +19,7 @@ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx); * binding it to a particular outpoint or script */ void tx_add_unbound_input(struct bitcoin_tx *update_tx, struct amount_sat funding_sats, - const secp256k1_xonly_pubkey *inner_pubkey); + const struct pubkey *inner_pubkey); /* Used to bind the update transaction to the funding outpoint * of the eltoo contract. This is the expected (non-malicious) @@ -35,7 +35,7 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, const struct eltoo_keyset *eltoo_keyset, - secp256k1_xonly_pubkey *psbt_inner_pubkey, + const struct pubkey *psbt_inner_pubkey, u8 *final_sig); /* Used to bind the update transaction to the non-funding outpoints @@ -59,7 +59,7 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, const struct eltoo_keyset *eltoo_keyset, const u8 *invalidated_annex_hint, u32 invalidated_update_number, - secp256k1_xonly_pubkey *psbt_inner_pubkey, + struct pubkey *psbt_inner_pubkey, u8 *final_sig); /** @@ -75,7 +75,7 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, struct amount_sat funding_sats, - const secp256k1_xonly_pubkey *inner_pubkey, + const struct pubkey *inner_pubkey, char** err_reason); diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index a314b7b0686f..bf0024a9d704 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -339,6 +339,8 @@ msgdata,hsmd_combine_psig,channel_id,channel_id, msgdata,hsmd_combine_psig,p_sig_1,partial_sig, msgdata,hsmd_combine_psig,p_sig_2,partial_sig, msgdata,hsmd_combine_psig,update_tx,bitcoin_tx, +msgdata,hsmd_combine_psig,settle_tx,bitcoin_tx, +msgdata,hsmd_combine_psig,inner_pubkey,pubkey, msgtype,hsmd_combine_psig_reply,192 msgdata,hsmd_combine_psig_reply,sig,bip340sig, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index dcc9a04e7122..ea8955768030 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1347,6 +1347,46 @@ static u8 *handle_sign_penalty_to_us(struct hsmd_client *c, const u8 *msg_in) SIGHASH_ALL); } +static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) +{ + struct channel_id channel_id; + struct bitcoin_tx *update_tx, *settle_tx; + struct partial_sig p_sig_1, p_sig_2; + struct sha256_double hash_out; + u8 *annex; + struct bip340sig sig; + struct pubkey inner_pubkey; + const secp256k1_musig_partial_sig *p_sig_ptrs[2]; + + if (!fromwire_hsmd_combine_psig(tmpctx, msg_in, + &channel_id, + &p_sig_1, + &p_sig_2, + &update_tx, + &settle_tx, + &inner_pubkey)) { + return hsmd_status_malformed_request(c, msg_in); + } + + p_sig_ptrs[0] = &p_sig_1.p_sig; + p_sig_ptrs[1] = &p_sig_2.p_sig; + + annex = make_eltoo_annex(tmpctx, settle_tx); + bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &hash_out); + + if (!bipmusig_partial_sigs_combine_verify(p_sig_ptrs, + /* num_signers */ 2, + &inner_pubkey, + &secretstuff.session, + &hash_out, + &sig)) { + /* FIXME better complaint from hsmd */ + return hsmd_status_malformed_request(c, msg_in); + } + + return towire_hsmd_combine_psig_reply(NULL, &sig); +} + /*~ This is another lightningd-only interface; signing a update transaction. * We sign every single update transaction, so there's no danger here * aside from signing bad state. @@ -1363,8 +1403,8 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) struct nonce remote_nonce; struct channel_id channel_id; - /* MuSug stuff */ - secp256k1_xonly_pubkey xo_inner_pubkey; + /* MuSig stuff */ + struct pubkey dummy_inner_pubkey; /* only cache needed for signing */ secp256k1_musig_keyagg_cache keyagg_cache; const struct pubkey *pubkey_ptrs[2]; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; @@ -1401,7 +1441,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) annex = make_eltoo_annex(tmpctx, settle_tx); pubkey_ptrs[0] = &remote_funding_pubkey; pubkey_ptrs[1] = &local_funding_pubkey; - bipmusig_inner_pubkey(&xo_inner_pubkey, + bipmusig_inner_pubkey(&dummy_inner_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2); @@ -1747,6 +1787,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX: return handle_psign_update_tx(client, msg); case WIRE_HSMD_COMBINE_PSIG: + return handle_combine_psig(client, msg); case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: case WIRE_HSMD_GET_NONCE: break; diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index fca59cca7055..6da2c02bc982 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -68,6 +68,9 @@ struct eltoo_state { struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; + /* Inner pubkey for lifetime of channel */ + struct pubkey inner_pubkey; + /* Initially temporary, then final channel id. */ struct channel_id channel_id; @@ -293,6 +296,8 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; char *err_reason; + const struct pubkey *pubkey_ptrs[2]; + secp256k1_musig_keyagg_cache keyagg_cache; status_debug("funder_channel_start"); if (!setup_channel_funder(state)) @@ -384,6 +389,15 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) } set_remote_upfront_shutdown(state, accept_tlvs->upfront_shutdown_script); + /* Both pubkeys should be initialized, generated Taproot inner pubkey */ + pubkey_ptrs[0] = &state->our_funding_pubkey; + pubkey_ptrs[1] = &state->their_funding_pubkey; + + bipmusig_inner_pubkey(&state->inner_pubkey, + &keyagg_cache, + pubkey_ptrs, + 2 /* n_pubkeys */); + /* BOLT #2: * - if `channel_type` is set, and `channel_type` was set in * `open_channel`, and they are not equal types: @@ -586,7 +600,6 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!msg) return false; - // FIXME ? sig->sighash_type = SIGHASH_ALL; if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &state->their_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); @@ -631,16 +644,15 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /* So we create the initial update transaction, and check the * signature they sent against that. */ - /* VLS type checks can go here... */ - // validate_initial_update_signature(HSM_FD, *update_tx, &their_update_psig, &our_update_psig); - /* Combine psigs and validate here */ /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ msg = towire_hsmd_combine_psig(NULL, &state->channel_id, &our_update_psig, &their_update_psig, - *update_tx); + *update_tx, + settle_tx, + &state->inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, update_sig)) { @@ -704,8 +716,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) { struct channel_id id_in; /* FIXME Can't these just be read into eltoo_keyset? */ - struct pubkey their_funding_pubkey; - struct pubkey their_settlement_pubkey; struct bip340sig update_sig; struct bitcoin_tx *settle_tx, *update_tx; struct bitcoin_blkid chain_hash; @@ -717,6 +727,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct partial_sig our_update_psig, their_update_psig; + const struct pubkey *pubkey_ptrs[2]; + secp256k1_musig_keyagg_cache keyagg_cache; /* BOLT #2: * @@ -735,8 +747,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->remoteconf.htlc_minimum, &state->remoteconf.shared_delay, &state->remoteconf.max_accepted_htlcs, - &their_funding_pubkey, - &their_settlement_pubkey, + &state->their_funding_pubkey, + &state->their_settlement_pubkey, &channel_flags, &state->their_next_nonce, &open_tlvs)) @@ -872,6 +884,16 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) peer_billboard(false, "Incoming channel: accepted, now waiting for them to create funding tx"); + /* Make Taproot inner key now that we have both keys in state */ + pubkey_ptrs[0] = &state->our_funding_pubkey; + pubkey_ptrs[1] = &state->their_funding_pubkey; + + bipmusig_inner_pubkey(&state->inner_pubkey, + &keyagg_cache, + pubkey_ptrs, + 2 /* n_pubkeys */); + + /* This is a loop which handles gossip until we get a non-gossip msg */ msg = opening_negotiate_msg(tmpctx, state, NULL); if (!msg) @@ -912,8 +934,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->localconf.shared_delay, state->upfront_shutdown_script[LOCAL], state->local_upfront_shutdown_wallet_index, - &their_funding_pubkey, - &their_settlement_pubkey, + &state->their_funding_pubkey, + &state->their_settlement_pubkey, state->upfront_shutdown_script[REMOTE], state->channel_type); wire_sync_write(HSM_FD, take(msg)); @@ -932,9 +954,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->localconf, &state->remoteconf, &state->our_funding_pubkey, - &their_funding_pubkey, + &state->their_funding_pubkey, &state->our_settlement_pubkey, - &their_settlement_pubkey, + &state->their_settlement_pubkey, state->channel_type, feature_offered(state->their_features, OPT_LARGE_CHANNELS), @@ -1015,7 +1037,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->channel_id, &our_update_psig, &their_update_psig, - update_tx); + update_tx, + settle_tx, + &state->inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { @@ -1032,7 +1056,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->remoteconf, update_tx, &update_sig, - &their_funding_pubkey, + &state->their_funding_pubkey, &state->funding, state->funding_sats, state->push_msat, From 31470f904a46580a70ac32b94db810cd6910889c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 09:40:49 -0400 Subject: [PATCH 121/283] replyreply --- openingd/eltoo_openingd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 6da2c02bc982..573d4a475170 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -1044,7 +1044,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { status_failed(STATUS_FAIL_HSM_IO, - "Bad combine_psig_reply_reply %s", tal_hex(tmpctx, msg)); + "Bad combine_psig_reply %s", tal_hex(tmpctx, msg)); } /* We don't send this ourselves: channeld does, because master needs From 3aa742a41f6b63823ac6987d0c479beb0350b85b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 10:26:10 -0400 Subject: [PATCH 122/283] fixup null ptrs for keyagg_cache --- channeld/settle_tx.c | 3 ++- channeld/test/run-settle_tx.c | 2 +- common/initial_settlement_tx.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 65b4f1c684f2..2ffb778dd5cb 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -115,6 +115,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, *dummy_to_remote = (struct htlc *)0x02; struct pubkey inner_pubkey; const struct pubkey *pubkey_ptrs[2]; + secp256k1_musig_keyagg_cache keyagg_cache; /* For non-initial settlement tx, we cannot safely * predict prevout, we will rebind this last second, * so just put something in to satisfy PSBT et al @@ -129,7 +130,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, - /* keyagg_cache */ NULL, + &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 690399343bd7..d59dc2827aef 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -811,7 +811,7 @@ static int test_htlc_output_creation(void) /* Calculate inner pubkey */ bipmusig_inner_pubkey(&inner_pubkey, - /* keyagg_cache */ NULL, + &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 1); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index da6b2f338263..a3cb6a8cf494 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -135,6 +135,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, const void *output_order[NUM_SIDES + 1]; const struct pubkey *pubkey_ptrs[2]; struct pubkey inner_pubkey; + secp256k1_musig_keyagg_cache keyagg_cache; /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); @@ -142,7 +143,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, - /* keyagg_cache */ NULL, + &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2); From 753042eec341e487dbbae527272ac063b4a2def9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 10:30:28 -0400 Subject: [PATCH 123/283] Psigs have stringified --- openingd/eltoo_openingd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 573d4a475170..23384890f582 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -564,13 +564,11 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /* You can tell this has been a problem before, since there's a debug * message here: */ - /* FIXME stringify partial sigs status_debug("signature %s on tx %s using key %s", - type_to_string(tmpctx, struct partial_sig, sig), + type_to_string(tmpctx, struct partial_sig, &our_update_psig), type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey)); - */ /* Now we give our peer the partial signature for the first update * transaction. */ From ded1ef3e6a90798b93cbe0a4951d276132655972 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 10:42:05 -0400 Subject: [PATCH 124/283] Don't use eltoo_keyset in openenind, yet --- openingd/eltoo_openingd.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 23384890f582..fd3f39a54076 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -554,7 +554,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, 0, // FIXME &state->channel->dbid, *update_tx, settle_tx, - &state->channel->eltoo_keyset.other_funding_key, + &state->their_funding_pubkey, &state->their_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); @@ -713,7 +713,6 @@ static u8 *funder_channel_complete(struct eltoo_state *state) static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) { struct channel_id id_in; - /* FIXME Can't these just be read into eltoo_keyset? */ struct bip340sig update_sig; struct bitcoin_tx *settle_tx, *update_tx; struct bitcoin_blkid chain_hash; @@ -899,7 +898,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* The message should be "funding_created" which tells us what funding * tx they generated; the sighash type is implied, so we set it here. */ - // FIXME ? theirsig.sighash_type = SIGHASH_ALL; if (!fromwire_funding_created_eltoo(msg, &id_in, &state->funding.txid, &funding_txout, @@ -1022,7 +1020,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) 0, // FIXME &state->channel->dbid, update_tx, settle_tx, - &state->channel->eltoo_keyset.other_funding_key, + &state->their_funding_pubkey, &state->their_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); @@ -1047,7 +1045,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ - // FIXME ? assert(sig.sighash_type == SIGHASH_ALL); msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &state->our_next_nonce); return towire_openingd_eltoo_fundee(state, From 1e26cda12d016b65d9751b981fb1b64e58d486a5 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 11:05:11 -0400 Subject: [PATCH 125/283] Fixups, why didn't channel reserve stop working long ago.... --- common/initial_eltoo_channel.c | 14 +++++++++++--- common/keyset.h | 2 ++ openingd/eltoo_openingd.c | 35 +++++----------------------------- 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index b4e678c7a261..c2883cf8e2e5 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -29,6 +29,8 @@ struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, { struct eltoo_channel *channel = tal(ctx, struct eltoo_channel); struct amount_msat remote_msatoshi; + const struct pubkey *pubkey_ptrs[2]; + secp256k1_musig_keyagg_cache keyagg_cache; channel->cid = *cid; channel->funding = *funding; @@ -47,6 +49,13 @@ struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, channel->eltoo_keyset.other_settle_key = *remote_settle_pubkey; channel->htlcs = NULL; + pubkey_ptrs[0] = local_funding_pubkey; + pubkey_ptrs[1] = remote_funding_pubkey; + bipmusig_inner_pubkey(&channel->eltoo_keyset.inner_pubkey, + &keyagg_cache, + pubkey_ptrs, + 2 /* n_pubkeys */); + channel->view[LOCAL].owed[LOCAL] = channel->view[REMOTE].owed[LOCAL] = local_msatoshi; @@ -82,7 +91,6 @@ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, channel->config->dust_limit, channel->view->owed[LOCAL], channel->view->owed[REMOTE], - channel->config->channel_reserve, 0 ^ channel->update_number_obscurer, direct_outputs, err_reason); @@ -106,8 +114,8 @@ struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, /* This should be gathered from settle_tx PSBT when stored there, * it's generated in initial_settlement_tx. This is unused otherwise. */ - secp256k1_xonly_pubkey dummy_inner_pubkey; - memset(dummy_inner_pubkey.data, 0, sizeof(dummy_inner_pubkey.data)); + struct pubkey dummy_inner_pubkey; + memset(dummy_inner_pubkey.pubkey.data, 0, sizeof(dummy_inner_pubkey.pubkey.data)); /* This assumes no HTLCs! */ assert(!channel->htlcs); diff --git a/common/keyset.h b/common/keyset.h index 4d16f0d96eb1..4bcfdc9c0744 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -17,6 +17,8 @@ struct keyset { struct eltoo_keyset { struct pubkey self_settle_key, other_settle_key; struct pubkey self_funding_key, other_funding_key; + /* MuSig2 key using funding keys as input */ + struct pubkey inner_pubkey; }; /* Self == owner of commitment tx, other == non-owner. */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index fd3f39a54076..ebfbb38feecc 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -60,17 +60,15 @@ struct eltoo_state { u32 max_shared_delay; /* These are the points lightningd told us to use when accepting or - * opening a channel. */ + * opening a channel. Copied into channel.eltoo_keyset */ struct pubkey our_funding_pubkey; struct pubkey our_settlement_pubkey; - /* Information we need between funding_start and funding_complete */ + /* Information we need between funding_start and funding_complete + * Copied into channel.eltoo_keyset */ struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; - /* Inner pubkey for lifetime of channel */ - struct pubkey inner_pubkey; - /* Initially temporary, then final channel id. */ struct channel_id channel_id; @@ -296,8 +294,6 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; char *err_reason; - const struct pubkey *pubkey_ptrs[2]; - secp256k1_musig_keyagg_cache keyagg_cache; status_debug("funder_channel_start"); if (!setup_channel_funder(state)) @@ -389,15 +385,6 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) } set_remote_upfront_shutdown(state, accept_tlvs->upfront_shutdown_script); - /* Both pubkeys should be initialized, generated Taproot inner pubkey */ - pubkey_ptrs[0] = &state->our_funding_pubkey; - pubkey_ptrs[1] = &state->their_funding_pubkey; - - bipmusig_inner_pubkey(&state->inner_pubkey, - &keyagg_cache, - pubkey_ptrs, - 2 /* n_pubkeys */); - /* BOLT #2: * - if `channel_type` is set, and `channel_type` was set in * `open_channel`, and they are not equal types: @@ -650,7 +637,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &their_update_psig, *update_tx, settle_tx, - &state->inner_pubkey); + &state->channel->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, update_sig)) { @@ -724,8 +711,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct partial_sig our_update_psig, their_update_psig; - const struct pubkey *pubkey_ptrs[2]; - secp256k1_musig_keyagg_cache keyagg_cache; /* BOLT #2: * @@ -881,16 +866,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) peer_billboard(false, "Incoming channel: accepted, now waiting for them to create funding tx"); - /* Make Taproot inner key now that we have both keys in state */ - pubkey_ptrs[0] = &state->our_funding_pubkey; - pubkey_ptrs[1] = &state->their_funding_pubkey; - - bipmusig_inner_pubkey(&state->inner_pubkey, - &keyagg_cache, - pubkey_ptrs, - 2 /* n_pubkeys */); - - /* This is a loop which handles gossip until we get a non-gossip msg */ msg = opening_negotiate_msg(tmpctx, state, NULL); if (!msg) @@ -1035,7 +1010,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &their_update_psig, update_tx, settle_tx, - &state->inner_pubkey); + &state->channel->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { From d8841ff3ee993c5d211288a3175bde103c17c8ba Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 11:34:29 -0400 Subject: [PATCH 126/283] Generate nonce for channel --- hsmd/hsmd.c | 4 ++-- hsmd/hsmd_wire.csv | 8 ++++---- hsmd/libhsmd.c | 38 +++++++++++++++++++++++++++++++++----- openingd/eltoo_openingd.c | 16 ++++++++++++---- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index ed8d54bc7608..985c53617221 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -671,7 +671,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: - case WIRE_HSMD_GET_NONCE: + case WIRE_HSMD_GEN_NONCE: /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, @@ -705,7 +705,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: - case WIRE_HSMD_GET_NONCE_REPLY: + case WIRE_HSMD_GEN_NONCE_REPLY: return bad_req_fmt(conn, c, c->msg_in, "Received an incoming message of type %s, " "which is not a request", diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index bf0024a9d704..09a04de451b5 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -347,8 +347,8 @@ msgdata,hsmd_combine_psig_reply,sig,bip340sig, # Get musig public nonce for channel... FIXME channel_id completely # ignored for now until storage model is figured -msgtype,hsmd_get_nonce,96 -msgdata,hsmd_get_nonce,channel_id,channel_id, +msgtype,hsmd_gen_nonce,96 +msgdata,hsmd_gen_nonce,channel_id,channel_id, -msgtype,hsmd_get_nonce_reply,196 -msgdata,hsmd_get_nonce_reply,pubnonce,nonce, +msgtype,hsmd_gen_nonce_reply,196 +msgdata,hsmd_gen_nonce_reply,pubnonce,nonce, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index ea8955768030..fe62060efbdf 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -133,7 +133,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: - case WIRE_HSMD_GET_NONCE: + case WIRE_HSMD_GEN_NONCE: return (client->capabilities & HSM_CAP_MASTER) != 0; /*~ These are messages sent by the HSM so we should never receive them. */ @@ -166,7 +166,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: - case WIRE_HSMD_GET_NONCE_REPLY: + case WIRE_HSMD_GEN_NONCE_REPLY: break; } return false; @@ -795,6 +795,32 @@ static u8 *handle_get_channel_basepoints(struct hsmd_client *c, &funding_pubkey); } +static u8 *handle_gen_nonce(struct hsmd_client *c, + const u8 *msg_in) +{ + struct channel_id channel_id; + struct nonce nonce; + struct secret channel_seed; + struct secrets secrets; + + if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) + return hsmd_status_malformed_request(c, msg_in); + + /* Generate privkey for additional nonce entropy */ + get_channel_seed(&c->id, c->dbid, &channel_seed); + derive_basepoints(&channel_seed, + NULL, NULL, &secrets, NULL); + + /* Fill and return own next_nonce FIXME add in more entropy */ + bipmusig_gen_nonce(&secretstuff.sec_nonce, + &secretstuff.pub_nonce.nonce, + &secrets.funding_privkey, + NULL /* keyagg_cache */, + NULL /* msg32 */); + + return towire_hsmd_gen_nonce_reply(NULL, &nonce); +} + /*~ The client has asked us to extract the shared secret from an EC Diffie * Hellman token. This doesn't leak any information, but requires the private * key, so the hsmd performs it. It's used to set up an encryption key for the @@ -1789,10 +1815,12 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_COMBINE_PSIG: return handle_combine_psig(client, msg); case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: - case WIRE_HSMD_GET_NONCE: + /* We immediately sign ourselves and check via handle_combine_psig... + Unneeded? */ break; + case WIRE_HSMD_GEN_NONCE: + return handle_gen_nonce(client, msg); /* Eltoo stuff ends */ - case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: case WIRE_HSMD_CANNOUNCEMENT_SIG_REPLY: @@ -1821,7 +1849,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX_REPLY: case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: - case WIRE_HSMD_GET_NONCE_REPLY: + case WIRE_HSMD_GEN_NONCE_REPLY: break; } return hsmd_status_bad_request(client, msg, "Unknown request"); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index ebfbb38feecc..c6fb9bb8ee5f 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -324,11 +324,11 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) open_tlvs->channel_type = state->channel_type->features; /* Fetch MuSig nonce */ - msg = towire_hsmd_get_nonce(NULL, &state->channel_id); + msg = towire_hsmd_gen_nonce(NULL, &state->channel_id); peer_write(state->pps, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_get_nonce_reply(msg, &state->our_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->our_next_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -847,9 +847,17 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) */ accept_tlvs->channel_type = state->channel_type->features; - /* FIXME Fetch our first public nonce */ + /* Fetch MuSig nonce for channel since we have none yet */ + msg = towire_hsmd_gen_nonce(NULL, &state->channel_id); + peer_write(state->pps, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->our_next_nonce)) { + peer_failed_err(state->pps, + &state->channel_id, + "Failed to get nonce for channel: %s", tal_hex(msg, msg)); + } - /* FIXME we can't actually know channel_id ??? */ msg = towire_accept_channel_eltoo(NULL, &state->channel_id, state->localconf.dust_limit, state->localconf.max_htlc_value_in_flight, From 1c4488559b62ead5212f4780cb33fe3e4fe48479 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 10 Aug 2022 13:21:00 -0400 Subject: [PATCH 127/283] Get peer_ir and dbid from hsm_client...? --- hsmd/hsmd_wire.csv | 2 -- hsmd/libhsmd.c | 5 +---- openingd/eltoo_openingd.c | 4 ---- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 09a04de451b5..73e9207692c2 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -314,8 +314,6 @@ msgtype,hsmd_ready_eltoo_channel_reply,181 # to sign msgtype,hsmd_psign_update_tx,69 msgdata,hsmd_psign_update_tx,channel_id,channel_id, -msgdata,hsmd_psign_update_tx,id,node_id, -msgdata,hsmd_psign_update_tx,dbid,u64, msgdata,hsmd_psign_update_tx,update_tx,bitcoin_tx, msgdata,hsmd_psign_update_tx,settle_tx,bitcoin_tx, msgdata,hsmd_psign_update_tx,remote_funding_key,pubkey, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index fe62060efbdf..fbc7d9bf9d85 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1420,8 +1420,6 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) { struct pubkey remote_funding_pubkey, local_funding_pubkey; - struct node_id peer_id; - u64 dbid; struct secret channel_seed; struct bitcoin_tx *update_tx, *settle_tx; struct partial_sig p_sig; @@ -1439,7 +1437,6 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) if (!fromwire_hsmd_psign_update_tx(tmpctx, msg_in, &channel_id, - &peer_id, &dbid, &update_tx, &settle_tx, &remote_funding_pubkey, @@ -1458,7 +1455,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) return hsmd_status_bad_request_fmt(c, msg_in, "update tx must have 1 output"); - get_channel_seed(&peer_id, dbid, &channel_seed); + get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, &local_funding_pubkey, NULL, &secrets, NULL); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index c6fb9bb8ee5f..265c501edc78 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -537,8 +537,6 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * tapscripts. */ msg = towire_hsmd_psign_update_tx(NULL, &state->channel_id, - NULL, // FIXME &state->channel->peer->id, - 0, // FIXME &state->channel->dbid, *update_tx, settle_tx, &state->their_funding_pubkey, @@ -999,8 +997,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* Make HSM sign it */ msg = towire_hsmd_psign_update_tx(NULL, &state->channel_id, - NULL, // FIXME &state->channel->peer->id, - 0, // FIXME &state->channel->dbid, update_tx, settle_tx, &state->their_funding_pubkey, From 9cd573d9a778d872004bd28f6ee89c17cd4441b9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 11 Aug 2022 10:24:51 -0400 Subject: [PATCH 128/283] Start adding eltoo channeld stuff --- channeld/channeld.c | 1 + channeld/channeld_wire.csv | 5 + channeld/eltoo_channeld.c | 4079 +++++++++++++++++++++++++++++++++ channeld/eltoo_channeld.h | 10 + channeld/eltoo_full_channel.c | 1585 +++++++++++++ channeld/eltoo_full_channel.h | 295 +++ lightningd/channel_control.c | 3 + 7 files changed, 5978 insertions(+) create mode 100644 channeld/eltoo_channeld.c create mode 100644 channeld/eltoo_channeld.h create mode 100644 channeld/eltoo_full_channel.c create mode 100644 channeld/eltoo_full_channel.h diff --git a/channeld/channeld.c b/channeld/channeld.c index 8c64f190e91c..e5996829d725 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3738,6 +3738,7 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_LOCAL_CHANNEL_UPDATE: case WIRE_CHANNELD_LOCAL_CHANNEL_ANNOUNCEMENT: case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: + case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: break; } master_badmsg(-1, msg); diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index b2179908b0d4..b781c10d1ac1 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -275,3 +275,8 @@ msgdata,channeld_upgraded,new_type,channel_type, # Tell peer about our latest and greatest blockheight. msgtype,channeld_blockheight,1012 msgdata,channeld_blockheight,blockheight,u32, + +# ELTOO STUFF + +# When we receive funding_locked. +msgtype,channeld_got_funding_locked_eltoo,1079 diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c new file mode 100644 index 000000000000..0a75cd0645a5 --- /dev/null +++ b/channeld/eltoo_channeld.c @@ -0,0 +1,4079 @@ +/* Main channel operation daemon: runs from funding_locked to shutdown_complete. + * + * We're fairly synchronous: our main loop looks for master or + * peer requests and services them synchronously. + * + * The exceptions are: + * 1. When we've asked the master something: in that case, we queue + * non-response packets for later processing while we await the reply. + * 2. We queue and send non-blocking responses to peers: if both peers were + * reading and writing synchronously we could deadlock if we hit buffer + * limits, unlikely as that is. + */ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* stdin == requests, 3 == peer, 4 = HSM */ +#define MASTER_FD STDIN_FILENO +#define HSM_FD 4 + +struct peer { + struct per_peer_state *pps; + bool funding_locked[NUM_SIDES]; + u64 next_index[NUM_SIDES]; + + /* Features peer supports. */ + u8 *their_features; + + /* Features we support. */ + struct feature_set *our_features; + + /* Tolerable amounts for feerate (only relevant for fundee). */ + u32 feerate_min, feerate_max; + + /* Feerate to be used when creating penalty transactions. */ + u32 feerate_penalty; + + /* Local next per-commit point. */ + struct pubkey next_local_per_commit; + + /* Remote's current per-commit point. */ + struct pubkey remote_per_commit; + + /* Remotes's last per-commitment point: we keep this to check + * revoke_and_ack's `per_commitment_secret` is correct. */ + struct pubkey old_remote_per_commit; + + /* Their sig for current commit. */ + struct bitcoin_signature their_commit_sig; + + /* BOLT #2: + * + * A sending node: + *... + * - for the first HTLC it offers: + * - MUST set `id` to 0. + */ + u64 htlc_id; + + struct channel_id channel_id; + struct channel *channel; + + /* Messages from master: we queue them since we might be + * waiting for a specific reply. */ + struct msg_queue *from_master; + + struct timers timers; + struct oneshot *commit_timer; + u64 commit_timer_attempts; + u32 commit_msec; + + /* The feerate we want. */ + u32 desired_feerate; + + /* Current blockheight */ + u32 our_blockheight; + + /* Announcement related information */ + struct node_id node_ids[NUM_SIDES]; + struct short_channel_id short_channel_ids[NUM_SIDES]; + secp256k1_ecdsa_signature announcement_node_sigs[NUM_SIDES]; + secp256k1_ecdsa_signature announcement_bitcoin_sigs[NUM_SIDES]; + bool have_sigs[NUM_SIDES]; + + /* Which direction of the channel do we control? */ + u16 channel_direction; + + /* CLTV delta to announce to peers */ + u16 cltv_delta; + + /* We only really know these because we're the ones who create + * the channel_updates. */ + u32 fee_base; + u32 fee_per_satoshi; + /* Note: the real min constraint is channel->config[REMOTE].htlc_minimum: + * they could kill the channel if we violate that! */ + struct amount_msat htlc_minimum_msat, htlc_maximum_msat; + + /* The scriptpubkey to use for shutting down. */ + u32 *final_index; + struct ext_key *final_ext_key; + u8 *final_scriptpubkey; + + /* If master told us to shut down */ + bool send_shutdown; + /* Has shutdown been sent by each side? */ + bool shutdown_sent[NUM_SIDES]; + /* If master told us to send wrong_funding */ + struct bitcoin_outpoint *shutdown_wrong_funding; + +#if EXPERIMENTAL_FEATURES + /* Do we want quiescence? */ + bool stfu; + /* Which side is considered the initiator? */ + enum side stfu_initiator; + /* Has stfu been sent by each side? */ + bool stfu_sent[NUM_SIDES]; + /* Updates master asked, which we've deferred while quiescing */ + struct msg_queue *update_queue; +#endif + +#if DEVELOPER + /* If set, don't fire commit counter when this hits 0 */ + u32 *dev_disable_commit; + + /* If set, send channel_announcement after 1 second, not 30 */ + bool dev_fast_gossip; +#endif + /* Information used for reestablishment. */ + bool last_was_revoke; + struct changed_htlc *last_sent_commit; + u64 revocations_received; + u8 channel_flags; + + bool announce_depth_reached; + bool channel_local_active; + + /* Make sure timestamps move forward. */ + u32 last_update_timestamp; + + /* Additional confirmations need for local lockin. */ + u32 depth_togo; + + /* Non-empty if they specified a fixed shutdown script */ + u8 *remote_upfront_shutdown_script; + + /* Empty commitments. Spec violation, but a minor one. */ + u64 last_empty_commitment; + + /* Penalty bases for this channel / peer. */ + struct penalty_base **pbases; + + /* We allow a 'tx-sigs' message between reconnect + funding_locked */ + bool tx_sigs_allowed; + + /* Most recent channel_update message. */ + u8 *channel_update; +}; + +static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer); +static void start_commit_timer(struct peer *peer); + +static void billboard_update(const struct peer *peer) +{ + const char *update = billboard_message(tmpctx, peer->funding_locked, + peer->have_sigs, + peer->shutdown_sent, + peer->depth_togo, + num_channel_htlcs(peer->channel)); + + peer_billboard(false, update); +} + +const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES) +{ + u8 *msg; + + /* hsmd goes away at shutdown. That's OK. */ + if (!wire_sync_write(HSM_FD, req)) + exit(0); + + msg = wire_sync_read(ctx, HSM_FD); + if (!msg) + exit(0); + + return msg; +} + +#if EXPERIMENTAL_FEATURES +static void maybe_send_stfu(struct peer *peer) +{ + if (!peer->stfu) + return; + + if (!peer->stfu_sent[LOCAL] && !pending_updates(peer->channel, LOCAL, false)) { + u8 *msg = towire_stfu(NULL, &peer->channel_id, + peer->stfu_initiator == LOCAL); + peer_write(peer->pps, take(msg)); + peer->stfu_sent[LOCAL] = true; + } + + if (peer->stfu_sent[LOCAL] && peer->stfu_sent[REMOTE]) { + status_unusual("STFU complete: we are quiescent"); + wire_sync_write(MASTER_FD, + towire_channeld_dev_quiesce_reply(tmpctx)); + } +} + +static void handle_stfu(struct peer *peer, const u8 *stfu) +{ + struct channel_id channel_id; + u8 remote_initiated; + + if (!fromwire_stfu(stfu, &channel_id, &remote_initiated)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad stfu %s", tal_hex(peer, stfu)); + + if (!channel_id_eq(&channel_id, &peer->channel_id)) { + peer_failed_err(peer->pps, &channel_id, + "Wrong stfu channel_id: expected %s, got %s", + type_to_string(tmpctx, struct channel_id, + &peer->channel_id), + type_to_string(tmpctx, struct channel_id, + &channel_id)); + } + + /* Sanity check */ + if (pending_updates(peer->channel, REMOTE, false)) + peer_failed_warn(peer->pps, &peer->channel_id, + "STFU but you still have updates pending?"); + + if (!peer->stfu) { + peer->stfu = true; + if (!remote_initiated) + peer_failed_warn(peer->pps, &peer->channel_id, + "Unsolicited STFU but you said" + " you didn't initiate?"); + peer->stfu_initiator = REMOTE; + } else { + /* BOLT-quiescent #2: + * + * If both sides send `stfu` simultaneously, they will both + * set `initiator` to `1`, in which case the "initiator" is + * arbitrarily considered to be the channel funder (the sender + * of `open_channel`). + */ + if (remote_initiated) + peer->stfu_initiator = peer->channel->opener; + } + + /* BOLT-quiescent #2: + * The receiver of `stfu`: + * - if it has sent `stfu` then: + * - MUST now consider the channel to be quiescent + * - otherwise: + * - SHOULD NOT send any more update messages. + * - MUST reply with `stfu` once it can do so. + */ + peer->stfu_sent[REMOTE] = true; + + maybe_send_stfu(peer); +} + +/* Returns true if we queued this for later handling (steals if true) */ +static bool handle_master_request_later(struct peer *peer, const u8 *msg) +{ + if (peer->stfu) { + msg_enqueue(peer->update_queue, take(msg)); + return true; + } + return false; +} + +/* Compare, with false if either is NULL */ +static bool match_type(const u8 *t1, const u8 *t2) +{ + /* Missing fields are possible. */ + if (!t1 || !t2) + return false; + + return featurebits_eq(t1, t2); +} + +static void set_channel_type(struct channel *channel, const u8 *type) +{ + const struct channel_type *cur = channel->type; + + if (featurebits_eq(cur->features, type)) + return; + + /* We only allow one upgrade at the moment, so that's it. */ + assert(!channel_has(channel, OPT_STATIC_REMOTEKEY)); + assert(feature_offered(type, OPT_STATIC_REMOTEKEY)); + + /* Do upgrade, tell master. */ + tal_free(channel->type); + channel->type = channel_type_from(channel, type); + status_unusual("Upgraded channel to [%s]", + fmt_featurebits(tmpctx, type)); + wire_sync_write(MASTER_FD, + take(towire_channeld_upgraded(NULL, channel->type))); +} +#else /* !EXPERIMENTAL_FEATURES */ +static bool handle_master_request_later(struct peer *peer, const u8 *msg) +{ + return false; +} + +static void maybe_send_stfu(struct peer *peer) +{ +} +#endif + +/* Tell gossipd to create channel_update (then it goes into + * gossip_store, then streams out to peers, or sends it directly if + * it's a private channel) */ +static void send_channel_update(struct peer *peer, int disable_flag) +{ + u8 *msg; + + assert(disable_flag == 0 || disable_flag == ROUTING_FLAGS_DISABLED); + + /* Only send an update if we told gossipd */ + if (!peer->channel_local_active) + return; + + assert(peer->short_channel_ids[LOCAL].u64); + + msg = towire_channeld_local_channel_update(NULL, + &peer->short_channel_ids[LOCAL], + disable_flag + == ROUTING_FLAGS_DISABLED, + peer->cltv_delta, + peer->htlc_minimum_msat, + peer->fee_base, + peer->fee_per_satoshi, + peer->htlc_maximum_msat); + wire_sync_write(MASTER_FD, take(msg)); +} + +/* Tell gossipd and the other side what parameters we expect should + * they route through us */ +static void send_channel_initial_update(struct peer *peer) +{ + send_channel_update(peer, 0); +} + +/** + * Add a channel locally and send a channel update to the peer + * + * Send a local_add_channel message to gossipd in order to make the channel + * usable locally, and also tell our peer about our parameters via a + * channel_update message. The peer may accept the update and use the contained + * information to route incoming payments through the channel. The + * channel_update is not preceeded by a channel_announcement and won't make much + * sense to other nodes, so we don't tell gossipd about it. + */ +static void make_channel_local_active(struct peer *peer) +{ + u8 *msg; + const u8 *annfeatures = get_agreed_channelfeatures(tmpctx, + peer->our_features, + peer->their_features); + + /* Tell lightningd to tell gossipd about local channel. */ + msg = towire_channeld_local_private_channel(NULL, + peer->channel->funding_sats, + annfeatures); + wire_sync_write(MASTER_FD, take(msg)); + + /* Under CI, because blocks come so fast, we often find that the + * peer sends its first channel_update before the above message has + * reached it. */ + notleak(new_reltimer(&peer->timers, peer, + time_from_sec(5), + send_channel_initial_update, peer)); +} + +static void send_announcement_signatures(struct peer *peer) +{ + /* First 2 + 256 byte are the signatures and msg type, skip them */ + size_t offset = 258; + struct sha256_double hash; + const u8 *msg, *ca, *req; + struct pubkey mykey; + + status_debug("Exchanging announcement signatures."); + ca = create_channel_announcement(tmpctx, peer); + req = towire_hsmd_cannouncement_sig_req(tmpctx, ca); + + msg = hsm_req(tmpctx, req); + if (!fromwire_hsmd_cannouncement_sig_reply(msg, + &peer->announcement_node_sigs[LOCAL], + &peer->announcement_bitcoin_sigs[LOCAL])) + status_failed(STATUS_FAIL_HSM_IO, + "Reading cannouncement_sig_resp: %s", + strerror(errno)); + + /* Double-check that HSM gave valid signatures. */ + sha256_double(&hash, ca + offset, tal_count(ca) - offset); + if (!pubkey_from_node_id(&mykey, &peer->node_ids[LOCAL])) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not convert my id '%s' to pubkey", + type_to_string(tmpctx, struct node_id, + &peer->node_ids[LOCAL])); + if (!check_signed_hash(&hash, &peer->announcement_node_sigs[LOCAL], + &mykey)) { + /* It's ok to fail here, the channel announcement is + * unique, unlike the channel update which may have + * been replaced in the meantime. */ + status_failed(STATUS_FAIL_HSM_IO, + "HSM returned an invalid node signature"); + } + + if (!check_signed_hash(&hash, &peer->announcement_bitcoin_sigs[LOCAL], + &peer->channel->funding_pubkey[LOCAL])) { + /* It's ok to fail here, the channel announcement is + * unique, unlike the channel update which may have + * been replaced in the meantime. */ + status_failed(STATUS_FAIL_HSM_IO, + "HSM returned an invalid bitcoin signature"); + } + + msg = towire_announcement_signatures( + NULL, &peer->channel_id, &peer->short_channel_ids[LOCAL], + &peer->announcement_node_sigs[LOCAL], + &peer->announcement_bitcoin_sigs[LOCAL]); + peer_write(peer->pps, take(msg)); +} + +/* Tentatively create a channel_announcement, possibly with invalid + * signatures. The signatures need to be collected first, by asking + * the HSM and by exchanging announcement_signature messages. */ +static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer) +{ + int first, second; + u8 *cannounce, *features + = get_agreed_channelfeatures(tmpctx, peer->our_features, + peer->their_features); + + if (peer->channel_direction == 0) { + first = LOCAL; + second = REMOTE; + } else { + first = REMOTE; + second = LOCAL; + } + + cannounce = towire_channel_announcement( + ctx, &peer->announcement_node_sigs[first], + &peer->announcement_node_sigs[second], + &peer->announcement_bitcoin_sigs[first], + &peer->announcement_bitcoin_sigs[second], + features, + &chainparams->genesis_blockhash, + &peer->short_channel_ids[LOCAL], + &peer->node_ids[first], + &peer->node_ids[second], + &peer->channel->funding_pubkey[first], + &peer->channel->funding_pubkey[second]); + return cannounce; +} + +/* Once we have both, we'd better make sure we agree what they are! */ +static void check_short_ids_match(struct peer *peer) +{ + assert(peer->have_sigs[LOCAL]); + assert(peer->have_sigs[REMOTE]); + + if (!short_channel_id_eq(&peer->short_channel_ids[LOCAL], + &peer->short_channel_ids[REMOTE])) + peer_failed_warn(peer->pps, &peer->channel_id, + "We disagree on short_channel_ids:" + " I have %s, you say %s", + type_to_string(peer, struct short_channel_id, + &peer->short_channel_ids[LOCAL]), + type_to_string(peer, struct short_channel_id, + &peer->short_channel_ids[REMOTE])); +} + +static void announce_channel(struct peer *peer) +{ + u8 *cannounce; + + cannounce = create_channel_announcement(tmpctx, peer); + + wire_sync_write(MASTER_FD, + take(towire_channeld_local_channel_announcement(NULL, + cannounce))); + send_channel_update(peer, 0); +} + +static void channel_announcement_negotiate(struct peer *peer) +{ + /* Don't do any announcement work if we're shutting down */ + if (peer->shutdown_sent[LOCAL]) + return; + + /* Can't do anything until funding is locked. */ + if (!peer->funding_locked[LOCAL] || !peer->funding_locked[REMOTE]) + return; + + if (!peer->channel_local_active) { + peer->channel_local_active = true; + make_channel_local_active(peer); + } + + /* BOLT #7: + * + * A node: + * - if the `open_channel` message has the `announce_channel` bit set AND a `shutdown` message has not been sent: + * - MUST send the `announcement_signatures` message. + * - MUST NOT send `announcement_signatures` messages until `funding_locked` + * has been sent and received AND the funding transaction has at least six confirmations. + * - otherwise: + * - MUST NOT send the `announcement_signatures` message. + */ + if (!(peer->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)) + return; + + /* BOLT #7: + * + * - MUST NOT send `announcement_signatures` messages until `funding_locked` + * has been sent and received AND the funding transaction has at least six confirmations. + */ + if (peer->announce_depth_reached && !peer->have_sigs[LOCAL]) { + /* When we reenable the channel, we will also send the announcement to remote peer, and + * receive the remote announcement reply. But we will rebuild the channel with announcement + * from the DB directly, other than waiting for the remote announcement reply. + */ + send_announcement_signatures(peer); + peer->have_sigs[LOCAL] = true; + billboard_update(peer); + } + + /* If we've completed the signature exchange, we can send a real + * announcement, otherwise we send a temporary one */ + if (peer->have_sigs[LOCAL] && peer->have_sigs[REMOTE]) { + check_short_ids_match(peer); + + /* After making sure short_channel_ids match, we can send remote + * announcement to MASTER. */ + wire_sync_write(MASTER_FD, + take(towire_channeld_got_announcement(NULL, + &peer->announcement_node_sigs[REMOTE], + &peer->announcement_bitcoin_sigs[REMOTE]))); + + /* Give other nodes time to notice new block. */ + notleak(new_reltimer(&peer->timers, peer, + time_from_sec(GOSSIP_ANNOUNCE_DELAY(peer->dev_fast_gossip)), + announce_channel, peer)); + } +} + +static void handle_peer_funding_locked_eltoo(struct peer *peer, const u8 *msg) +{ + struct channel_id chanid; + + /* BOLT #2: + * + * A node: + *... + * - upon reconnection: + * - MUST ignore any redundant `funding_locked` it receives. + */ + if (peer->funding_locked[REMOTE]) + return; + + /* Too late, we're shutting down! */ + if (peer->shutdown_sent[LOCAL]) + return; + + peer->old_remote_per_commit = peer->remote_per_commit; + if (!fromwire_funding_locked(msg, &chanid, + &peer->remote_per_commit)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad funding_locked %s", tal_hex(msg, msg)); + + if (!channel_id_eq(&chanid, &peer->channel_id)) + peer_failed_err(peer->pps, &chanid, + "Wrong channel id in %s (expected %s)", + tal_hex(tmpctx, msg), + type_to_string(msg, struct channel_id, + &peer->channel_id)); + + peer->tx_sigs_allowed = false; + peer->funding_locked[REMOTE] = true; + wire_sync_write(MASTER_FD, + take(towire_channeld_got_funding_locked_eltoo(NULL, + &peer->remote_per_commit))); + + channel_announcement_negotiate(peer); + billboard_update(peer); +} + +static void handle_peer_announcement_signatures(struct peer *peer, const u8 *msg) +{ + struct channel_id chanid; + + if (!fromwire_announcement_signatures(msg, + &chanid, + &peer->short_channel_ids[REMOTE], + &peer->announcement_node_sigs[REMOTE], + &peer->announcement_bitcoin_sigs[REMOTE])) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad announcement_signatures %s", + tal_hex(msg, msg)); + + /* Make sure we agree on the channel ids */ + if (!channel_id_eq(&chanid, &peer->channel_id)) { + peer_failed_err(peer->pps, &chanid, + "Wrong channel_id: expected %s, got %s", + type_to_string(tmpctx, struct channel_id, + &peer->channel_id), + type_to_string(tmpctx, struct channel_id, &chanid)); + } + + peer->have_sigs[REMOTE] = true; + billboard_update(peer); + + channel_announcement_negotiate(peer); +} + +static void handle_peer_add_htlc(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u64 id; + struct amount_msat amount; + u32 cltv_expiry; + struct sha256 payment_hash; + u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; + enum channel_add_err add_err; + struct htlc *htlc; +#if EXPERIMENTAL_FEATURES + struct tlv_update_add_tlvs *tlvs; +#endif + struct pubkey *blinding = NULL; + + if (!fromwire_update_add_htlc +#if EXPERIMENTAL_FEATURES + (msg, msg, &channel_id, &id, &amount, + &payment_hash, &cltv_expiry, + onion_routing_packet, &tlvs) +#else + (msg, &channel_id, &id, &amount, + &payment_hash, &cltv_expiry, + onion_routing_packet) +#endif + ) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad peer_add_htlc %s", tal_hex(msg, msg)); + +#if EXPERIMENTAL_FEATURES + blinding = tlvs->blinding; +#endif + add_err = channel_add_htlc(peer->channel, REMOTE, id, amount, + cltv_expiry, &payment_hash, + onion_routing_packet, blinding, &htlc, NULL, + /* We don't immediately fail incoming htlcs, + * instead we wait and fail them after + * they've been committed */ + false); + if (add_err != CHANNEL_ERR_ADD_OK) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad peer_add_htlc: %s", + channel_add_err_name(add_err)); +} + +/* We don't get upset if they're outside the range, as long as they're + * improving (or at least, not getting worse!). */ +static bool feerate_same_or_better(const struct channel *channel, + u32 feerate, u32 feerate_min, u32 feerate_max) +{ + u32 current = channel_feerate(channel, LOCAL); + + /* Too low? But is it going upwards? */ + if (feerate < feerate_min) + return feerate >= current; + if (feerate > feerate_max) + return feerate <= current; + return true; +} + +static void handle_peer_feechange(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u32 feerate; + + if (!fromwire_update_fee(msg, &channel_id, &feerate)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fee %s", tal_hex(msg, msg)); + } + + /* BOLT #2: + * + * A receiving node: + *... + * - if the sender is not responsible for paying the Bitcoin fee: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (peer->channel->opener != REMOTE) + peer_failed_warn(peer->pps, &peer->channel_id, + "update_fee from non-opener?"); + + status_debug("update_fee %u, range %u-%u", + feerate, peer->feerate_min, peer->feerate_max); + + /* BOLT #2: + * + * A receiving node: + * - if the `update_fee` is too low for timely processing, OR is + * unreasonably large: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (!feerate_same_or_better(peer->channel, feerate, + peer->feerate_min, peer->feerate_max)) + peer_failed_warn(peer->pps, &peer->channel_id, + "update_fee %u outside range %u-%u" + " (currently %u)", + feerate, + peer->feerate_min, peer->feerate_max, + channel_feerate(peer->channel, LOCAL)); + + /* BOLT #2: + * + * - if the sender cannot afford the new fee rate on the receiving + * node's current commitment transaction: + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + * - but MAY delay this check until the `update_fee` is committed. + */ + if (!channel_update_feerate(peer->channel, feerate)) + peer_failed_warn(peer->pps, &peer->channel_id, + "update_fee %u unaffordable", + feerate); + + status_debug("peer updated fee to %u", feerate); +} + +static void handle_peer_blockheight_change(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u32 blockheight, current; + + if (!fromwire_update_blockheight(msg, &channel_id, &blockheight)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_blockheight %s", + tal_hex(msg, msg)); + + /* BOLT- #2: + * A receiving node: + * ... + * - if the sender is not the initiator: + * - MUST fail the channel. + */ + if (peer->channel->opener != REMOTE) + peer_failed_warn(peer->pps, &peer->channel_id, + "update_blockheight from non-opener?"); + + current = get_blockheight(peer->channel->blockheight_states, + peer->channel->opener, LOCAL); + + status_debug("update_blockheight %u. last update height %u," + " our current height %u", + blockheight, current, peer->our_blockheight); + + /* BOLT- #2: + * A receiving node: + * - if the `update_blockheight` is less than the last + * received `blockheight`: + * - SHOULD fail the channel. + * ... + * - if `blockheight` is more than 1008 blocks behind + * the current blockheight: + * - SHOULD fail the channel + */ + /* Overflow check */ + if (blockheight + 1008 < blockheight) + peer_failed_warn(peer->pps, &peer->channel_id, + "blockheight + 1008 overflow (%u)", + blockheight); + + /* If they're behind the last one they sent, we just warn and + * reconnect, as they might be catching up */ + /* FIXME: track for how long they send backwards blockheight? */ + if (blockheight < current) + peer_failed_warn(peer->pps, &peer->channel_id, + "update_blockheight %u older than previous %u", + blockheight, current); + + /* BOLT- #2: + * A receiving node: + * ... + * - if `blockheight` is more than 1008 blocks behind + * the current blockheight: + * - SHOULD fail the channel + */ + assert(blockheight < blockheight + 1008); + if (blockheight + 1008 < peer->our_blockheight) + peer_failed_err(peer->pps, &peer->channel_id, + "update_blockheight %u outside" + " permissible range", blockheight); + + channel_update_blockheight(peer->channel, blockheight); + + status_debug("peer updated blockheight to %u", blockheight); +} + +static struct changed_htlc *changed_htlc_arr(const tal_t *ctx, + const struct htlc **changed_htlcs) +{ + struct changed_htlc *changed; + size_t i; + + changed = tal_arr(ctx, struct changed_htlc, tal_count(changed_htlcs)); + for (i = 0; i < tal_count(changed_htlcs); i++) { + changed[i].id = changed_htlcs[i]->id; + changed[i].newstate = changed_htlcs[i]->state; + } + return changed; +} + +static u8 *sending_commitsig_msg(const tal_t *ctx, + u64 remote_commit_index, + struct penalty_base *pbase, + const struct fee_states *fee_states, + const struct height_states *blockheight_states, + const struct htlc **changed_htlcs, + const struct bitcoin_signature *commit_sig, + const struct bitcoin_signature *htlc_sigs) +{ + struct changed_htlc *changed; + u8 *msg; + + /* We tell master what (of our) HTLCs peer will now be + * committed to. */ + changed = changed_htlc_arr(tmpctx, changed_htlcs); + msg = towire_channeld_sending_commitsig(ctx, remote_commit_index, + pbase, fee_states, + blockheight_states, changed, + commit_sig, htlc_sigs); + return msg; +} + +static bool shutdown_complete(const struct peer *peer) +{ + return peer->shutdown_sent[LOCAL] + && peer->shutdown_sent[REMOTE] + && num_channel_htlcs(peer->channel) == 0 + /* We could be awaiting revoke-and-ack for a feechange */ + && peer->revocations_received == peer->next_index[REMOTE] - 1; + +} + +/* BOLT #2: + * + * A sending node: + *... + * - if there are updates pending on the receiving node's commitment + * transaction: + * - MUST NOT send a `shutdown`. + */ +/* So we only call this after reestablish or immediately after sending commit */ +static void maybe_send_shutdown(struct peer *peer) +{ + u8 *msg; + struct tlv_shutdown_tlvs *tlvs; + + if (!peer->send_shutdown) + return; + + /* Send a disable channel_update so others don't try to route + * over us */ + send_channel_update(peer, ROUTING_FLAGS_DISABLED); + + if (peer->shutdown_wrong_funding) { + tlvs = tlv_shutdown_tlvs_new(tmpctx); + tlvs->wrong_funding + = tal(tlvs, struct tlv_shutdown_tlvs_wrong_funding); + tlvs->wrong_funding->txid = peer->shutdown_wrong_funding->txid; + tlvs->wrong_funding->outnum = peer->shutdown_wrong_funding->n; + } else + tlvs = NULL; + + msg = towire_shutdown(NULL, &peer->channel_id, peer->final_scriptpubkey, + tlvs); + peer_write(peer->pps, take(msg)); + peer->send_shutdown = false; + peer->shutdown_sent[LOCAL] = true; + billboard_update(peer); +} + +static void send_shutdown_complete(struct peer *peer) +{ + /* Now we can tell master shutdown is complete. */ + wire_sync_write(MASTER_FD, + take(towire_channeld_shutdown_complete(NULL))); + per_peer_state_fdpass_send(MASTER_FD, peer->pps); + close(MASTER_FD); +} + +/* This queues other traffic from the fd until we get reply. */ +static u8 *master_wait_sync_reply(const tal_t *ctx, + struct peer *peer, + const u8 *msg, + int replytype) +{ + u8 *reply; + + status_debug("Sending master %u", fromwire_peektype(msg)); + + if (!wire_sync_write(MASTER_FD, msg)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not set sync write to master: %s", + strerror(errno)); + + status_debug("... , awaiting %u", replytype); + + for (;;) { + int type; + + reply = wire_sync_read(ctx, MASTER_FD); + if (!reply) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not set sync read from master: %s", + strerror(errno)); + type = fromwire_peektype(reply); + if (type == replytype) { + status_debug("Got it!"); + break; + } + + status_debug("Nope, got %u instead", type); + msg_enqueue(peer->from_master, take(reply)); + } + + return reply; +} + +/* Collect the htlcs for call to hsmd. */ +static struct simple_htlc **collect_htlcs(const tal_t *ctx, const struct htlc **htlc_map) +{ + struct simple_htlc **htlcs; + + htlcs = tal_arr(ctx, struct simple_htlc *, 0); + size_t num_entries = tal_count(htlc_map); + for (size_t ndx = 0; ndx < num_entries; ++ndx) { + struct htlc const *hh = htlc_map[ndx]; + if (hh) { + struct simple_htlc *simple = + new_simple_htlc(htlcs, + htlc_state_owner(hh->state), + hh->amount, + &hh->rhash, + hh->expiry.locktime); + tal_arr_expand(&htlcs, simple); + } + } + return htlcs; +} + +/* Returns HTLC sigs, sets commit_sig */ +static struct bitcoin_signature *calc_commitsigs(const tal_t *ctx, + const struct peer *peer, + struct bitcoin_tx **txs, + const u8 *funding_wscript, + const struct htlc **htlc_map, + u64 commit_index, + struct bitcoin_signature *commit_sig) +{ + struct simple_htlc **htlcs; + size_t i; + struct pubkey local_htlckey; + const u8 *msg; + struct bitcoin_signature *htlc_sigs; + + htlcs = collect_htlcs(tmpctx, htlc_map); + msg = towire_hsmd_sign_remote_commitment_tx(NULL, txs[0], + &peer->channel->funding_pubkey[REMOTE], + &peer->remote_per_commit, + channel_has(peer->channel, + OPT_STATIC_REMOTEKEY), + commit_index, + (const struct simple_htlc **) htlcs, + channel_feerate(peer->channel, REMOTE)); + + msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_sign_tx_reply(msg, commit_sig)) + status_failed(STATUS_FAIL_HSM_IO, + "Reading sign_remote_commitment_tx reply: %s", + tal_hex(tmpctx, msg)); + + status_debug("Creating commit_sig signature %"PRIu64" %s for tx %s wscript %s key %s", + commit_index, + type_to_string(tmpctx, struct bitcoin_signature, + commit_sig), + type_to_string(tmpctx, struct bitcoin_tx, txs[0]), + tal_hex(tmpctx, funding_wscript), + type_to_string(tmpctx, struct pubkey, + &peer->channel->funding_pubkey[LOCAL])); + dump_htlcs(peer->channel, "Sending commit_sig"); + + if (!derive_simple_key(&peer->channel->basepoints[LOCAL].htlc, + &peer->remote_per_commit, + &local_htlckey)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Deriving local_htlckey"); + + /* BOLT #2: + * + * A sending node: + *... + * - MUST include one `htlc_signature` for every HTLC transaction + * corresponding to the ordering of the commitment transaction + */ + htlc_sigs = tal_arr(ctx, struct bitcoin_signature, tal_count(txs) - 1); + + for (i = 0; i < tal_count(htlc_sigs); i++) { + u8 *wscript; + + wscript = bitcoin_tx_output_get_witscript(tmpctx, txs[0], + txs[i+1]->wtx->inputs[0].index); + msg = towire_hsmd_sign_remote_htlc_tx(NULL, txs[i + 1], wscript, + &peer->remote_per_commit, + channel_has(peer->channel, + OPT_ANCHOR_OUTPUTS)); + + msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_sign_tx_reply(msg, &htlc_sigs[i])) + status_failed(STATUS_FAIL_HSM_IO, + "Bad sign_remote_htlc_tx reply: %s", + tal_hex(tmpctx, msg)); + + status_debug("Creating HTLC signature %s for tx %s wscript %s key %s", + type_to_string(tmpctx, struct bitcoin_signature, + &htlc_sigs[i]), + type_to_string(tmpctx, struct bitcoin_tx, txs[1+i]), + tal_hex(tmpctx, wscript), + type_to_string(tmpctx, struct pubkey, + &local_htlckey)); + assert(check_tx_sig(txs[1+i], 0, NULL, wscript, + &local_htlckey, + &htlc_sigs[i])); + } + + return htlc_sigs; +} + +/* Peer protocol doesn't want sighash flags. */ +static secp256k1_ecdsa_signature *raw_sigs(const tal_t *ctx, + const struct bitcoin_signature *sigs) +{ + secp256k1_ecdsa_signature *raw; + + raw = tal_arr(ctx, secp256k1_ecdsa_signature, tal_count(sigs)); + for (size_t i = 0; i < tal_count(sigs); i++) + raw[i] = sigs[i].s; + return raw; +} + +static struct bitcoin_signature *unraw_sigs(const tal_t *ctx, + const secp256k1_ecdsa_signature *raw, + bool option_anchor_outputs) +{ + struct bitcoin_signature *sigs; + + sigs = tal_arr(ctx, struct bitcoin_signature, tal_count(raw)); + for (size_t i = 0; i < tal_count(raw); i++) { + sigs[i].s = raw[i]; + + /* BOLT #3: + * ## HTLC-Timeout and HTLC-Success Transactions + *... + * * if `option_anchors` applies to this commitment + * transaction, `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is + * used as described in [BOLT #5] + */ + if (option_anchor_outputs) + sigs[i].sighash_type = SIGHASH_SINGLE|SIGHASH_ANYONECANPAY; + else + sigs[i].sighash_type = SIGHASH_ALL; + } + return sigs; +} + +/* Do we want to update fees? */ +static bool want_fee_update(const struct peer *peer, u32 *target) +{ + u32 current, val; + + if (peer->channel->opener != LOCAL) + return false; + +#if EXPERIMENTAL_FEATURES + /* No fee update while quiescing! */ + if (peer->stfu) + return false; +#endif + current = channel_feerate(peer->channel, REMOTE); + + /* max is *approximate*: only take it into account if we're + * trying to increase feerate. */ + if (peer->desired_feerate > current) { + /* FIXME: We should avoid adding HTLCs until we can meet this + * feerate! */ + u32 max = approx_max_feerate(peer->channel); + + val = peer->desired_feerate; + /* Respect max, but don't let us *decrease* us */ + if (val > max) + val = max; + if (val < current) + val = current; + } else + val = peer->desired_feerate; + + if (target) + *target = val; + + return val != current; +} + +/* Do we want to update blockheight? */ +static bool want_blockheight_update(const struct peer *peer, u32 *height) +{ + u32 last; + + if (peer->channel->opener != LOCAL) + return false; + + if (peer->channel->lease_expiry == 0) + return false; + +#if EXPERIMENTAL_FEATURES + /* No fee update while quiescing! */ + if (peer->stfu) + return false; +#endif + /* What's the current blockheight */ + last = get_blockheight(peer->channel->blockheight_states, + peer->channel->opener, LOCAL); + + if (peer->our_blockheight < last) { + status_broken("current blockheight %u less than last %u", + peer->our_blockheight, last); + return false; + } + + if (peer->our_blockheight == last) + return false; + + if (height) + *height = peer->our_blockheight; + + return true; +} + +static void send_commit(struct peer *peer) +{ + u8 *msg; + const struct htlc **changed_htlcs; + struct bitcoin_signature commit_sig, *htlc_sigs; + struct bitcoin_tx **txs; + const u8 *funding_wscript; + const struct htlc **htlc_map; + struct wally_tx_output *direct_outputs[NUM_SIDES]; + struct penalty_base *pbase; + u32 our_blockheight; + u32 feerate_target; + +#if DEVELOPER + if (peer->dev_disable_commit && !*peer->dev_disable_commit) { + peer->commit_timer = NULL; + return; + } +#endif + + /* FIXME: Document this requirement in BOLT 2! */ + /* We can't send two commits in a row. */ + if (peer->revocations_received != peer->next_index[REMOTE] - 1) { + assert(peer->revocations_received + == peer->next_index[REMOTE] - 2); + peer->commit_timer_attempts++; + /* Only report this in extreme cases */ + if (peer->commit_timer_attempts % 100 == 0) + status_debug("Can't send commit:" + " waiting for revoke_and_ack with %" + PRIu64" attempts", + peer->commit_timer_attempts); + /* Mark this as done and try again. */ + peer->commit_timer = NULL; + start_commit_timer(peer); + return; + } + + /* BOLT #2: + * + * - if no HTLCs remain in either commitment transaction: + * - MUST NOT send any `update` message after a `shutdown`. + */ + if (peer->shutdown_sent[LOCAL] && !num_channel_htlcs(peer->channel)) { + status_debug("Can't send commit: final shutdown phase"); + + peer->commit_timer = NULL; + return; + } + + /* If we wanted to update fees, do it now. */ + if (want_fee_update(peer, &feerate_target)) { + /* FIXME: We occasionally desynchronize with LND here, so + * don't stress things by having more than one feerate change + * in-flight! */ + if (feerate_changes_done(peer->channel->fee_states, false)) { + u8 *msg; + + /* BOLT-919 #2: + * + * A sending node: + * - if the `dust_balance_on_counterparty_tx` at the + * new `dust_buffer_feerate` is superior to + * `max_dust_htlc_exposure_msat`: + * - MAY NOT send `update_fee` + * - MAY fail the channel + * - if the `dust_balance_on_holder_tx` at the + * new `dust_buffer_feerate` is superior to + * the `max_dust_htlc_exposure_msat`: + * - MAY NOT send `update_fee` + * - MAY fail the channel + */ + /* Is this feerate update going to push the committed + * htlcs over our allowed dust limits? */ + if (!htlc_dust_ok(peer->channel, feerate_target, REMOTE) + || !htlc_dust_ok(peer->channel, feerate_target, LOCAL)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Too much dust to update fee (Desired" + " feerate update %d)", feerate_target); + + if (!channel_update_feerate(peer->channel, feerate_target)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not afford feerate %u" + " (vs max %u)", + feerate_target, approx_max_feerate(peer->channel)); + + msg = towire_update_fee(NULL, &peer->channel_id, + feerate_target); + peer_write(peer->pps, take(msg)); + } + } + + if (want_blockheight_update(peer, &our_blockheight)) { + if (blockheight_changes_done(peer->channel->blockheight_states, + false)) { + u8 *msg; + + channel_update_blockheight(peer->channel, + our_blockheight); + + msg = towire_update_blockheight(NULL, + &peer->channel_id, + our_blockheight); + + peer_write(peer->pps, take(msg)); + } + } + + /* BOLT #2: + * + * A sending node: + * - MUST NOT send a `commitment_signed` message that does not include + * any updates. + */ + changed_htlcs = tal_arr(tmpctx, const struct htlc *, 0); + if (!channel_sending_commit(peer->channel, &changed_htlcs)) { + status_debug("Can't send commit: nothing to send," + " feechange %s (%s)" + " blockheight %s (%s)", + want_fee_update(peer, NULL) ? "wanted": "not wanted", + type_to_string(tmpctx, struct fee_states, peer->channel->fee_states), + want_blockheight_update(peer, NULL) ? "wanted" : "not wanted", + type_to_string(tmpctx, struct height_states, peer->channel->blockheight_states)); + + /* Covers the case where we've just been told to shutdown. */ + maybe_send_shutdown(peer); + + peer->commit_timer = NULL; + return; + } + + txs = channel_txs(tmpctx, &htlc_map, direct_outputs, + &funding_wscript, peer->channel, &peer->remote_per_commit, + peer->next_index[REMOTE], REMOTE); + + htlc_sigs = + calc_commitsigs(tmpctx, peer, txs, funding_wscript, htlc_map, + peer->next_index[REMOTE], &commit_sig); + + if (direct_outputs[LOCAL] != NULL) { + pbase = penalty_base_new(tmpctx, peer->next_index[REMOTE], + txs[0], direct_outputs[LOCAL]); + + /* Add the penalty_base to our in-memory list as well, so we + * can find it again later. */ + tal_arr_expand(&peer->pbases, tal_steal(peer, pbase)); + } else + pbase = NULL; + +#if DEVELOPER + if (peer->dev_disable_commit) { + (*peer->dev_disable_commit)--; + if (*peer->dev_disable_commit == 0) + status_unusual("dev-disable-commit-after: disabling"); + } +#endif + + status_debug("Telling master we're about to commit..."); + /* Tell master to save this next commit to database, then wait. */ + msg = sending_commitsig_msg(NULL, peer->next_index[REMOTE], + pbase, + peer->channel->fee_states, + peer->channel->blockheight_states, + changed_htlcs, + &commit_sig, + htlc_sigs); + /* Message is empty; receiving it is the point. */ + master_wait_sync_reply(tmpctx, peer, take(msg), + WIRE_CHANNELD_SENDING_COMMITSIG_REPLY); + + status_debug("Sending commit_sig with %zu htlc sigs", + tal_count(htlc_sigs)); + + peer->next_index[REMOTE]++; + + msg = towire_commitment_signed(NULL, &peer->channel_id, + &commit_sig.s, + raw_sigs(tmpctx, htlc_sigs)); + peer_write(peer->pps, take(msg)); + + maybe_send_shutdown(peer); + + /* Timer now considered expired, you can add a new one. */ + peer->commit_timer = NULL; + start_commit_timer(peer); +} + +static void start_commit_timer(struct peer *peer) +{ + /* Already armed? */ + if (peer->commit_timer) + return; + + peer->commit_timer_attempts = 0; + peer->commit_timer = new_reltimer(&peer->timers, peer, + time_from_msec(peer->commit_msec), + send_commit, peer); +} + +/* If old_secret is NULL, we don't care, otherwise it is filled in. */ +static void get_per_commitment_point(u64 index, struct pubkey *point, + struct secret *old_secret) +{ + struct secret *s; + const u8 *msg; + + msg = hsm_req(tmpctx, + take(towire_hsmd_get_per_commitment_point(NULL, index))); + + if (!fromwire_hsmd_get_per_commitment_point_reply(tmpctx, msg, + point, + &s)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad per_commitment_point reply %s", + tal_hex(tmpctx, msg)); + + if (old_secret) { + if (!s) + status_failed(STATUS_FAIL_HSM_IO, + "No secret in per_commitment_point_reply %" + PRIu64, + index); + *old_secret = *s; + } +} + +/* revoke_index == current index - 1 (usually; not for retransmission) */ +static u8 *make_revocation_msg(const struct peer *peer, u64 revoke_index, + struct pubkey *point) +{ + struct secret old_commit_secret; + + get_per_commitment_point(revoke_index+2, point, &old_commit_secret); + + return towire_revoke_and_ack(peer, &peer->channel_id, &old_commit_secret, + point); +} + +static u8 *make_revocation_msg_from_secret(const struct peer *peer, + u64 revoke_index, + struct pubkey *point, + const struct secret *old_commit_secret, + const struct pubkey *next_point) +{ + *point = *next_point; + return towire_revoke_and_ack(peer, &peer->channel_id, + old_commit_secret, next_point); +} + +/* Convert changed htlcs into parts which lightningd expects. */ +static void marshall_htlc_info(const tal_t *ctx, + const struct htlc **changed_htlcs, + struct changed_htlc **changed, + struct fulfilled_htlc **fulfilled, + const struct failed_htlc ***failed, + struct added_htlc **added) +{ + *changed = tal_arr(ctx, struct changed_htlc, 0); + *added = tal_arr(ctx, struct added_htlc, 0); + *failed = tal_arr(ctx, const struct failed_htlc *, 0); + *fulfilled = tal_arr(ctx, struct fulfilled_htlc, 0); + + for (size_t i = 0; i < tal_count(changed_htlcs); i++) { + const struct htlc *htlc = changed_htlcs[i]; + if (htlc->state == RCVD_ADD_COMMIT) { + struct added_htlc a; + + a.id = htlc->id; + a.amount = htlc->amount; + a.payment_hash = htlc->rhash; + a.cltv_expiry = abs_locktime_to_blocks(&htlc->expiry); + memcpy(a.onion_routing_packet, + htlc->routing, + sizeof(a.onion_routing_packet)); + if (htlc->blinding) { + a.blinding = htlc->blinding; + ecdh(a.blinding, &a.blinding_ss); + } else + a.blinding = NULL; + a.fail_immediate = htlc->fail_immediate; + tal_arr_expand(added, a); + } else if (htlc->state == RCVD_REMOVE_COMMIT) { + if (htlc->r) { + struct fulfilled_htlc f; + assert(!htlc->failed); + f.id = htlc->id; + f.payment_preimage = *htlc->r; + tal_arr_expand(fulfilled, f); + } else { + assert(!htlc->r); + tal_arr_expand(failed, htlc->failed); + } + } else { + struct changed_htlc c; + assert(htlc->state == RCVD_REMOVE_ACK_COMMIT + || htlc->state == RCVD_ADD_ACK_COMMIT); + + c.id = htlc->id; + c.newstate = htlc->state; + tal_arr_expand(changed, c); + } + } +} + +static void send_revocation(struct peer *peer, + const struct bitcoin_signature *commit_sig, + const struct bitcoin_signature *htlc_sigs, + const struct htlc **changed_htlcs, + const struct bitcoin_tx *committx, + const struct secret *old_secret, + const struct pubkey *next_point) +{ + struct changed_htlc *changed; + struct fulfilled_htlc *fulfilled; + const struct failed_htlc **failed; + struct added_htlc *added; + const u8 *msg; + const u8 *msg_for_master; + + /* Marshall it now before channel_sending_revoke_and_ack changes htlcs */ + /* FIXME: Make infrastructure handle state post-revoke_and_ack! */ + marshall_htlc_info(tmpctx, + changed_htlcs, + &changed, + &fulfilled, + &failed, + &added); + + /* Revoke previous commit, get new point. */ + msg = make_revocation_msg_from_secret(peer, peer->next_index[LOCAL]-1, + &peer->next_local_per_commit, + old_secret, next_point); + + /* From now on we apply changes to the next commitment */ + peer->next_index[LOCAL]++; + + /* If this queues more changes on the other end, send commit. */ + if (channel_sending_revoke_and_ack(peer->channel)) { + status_debug("revoke_and_ack made pending: commit timer"); + start_commit_timer(peer); + } + + /* Tell master daemon about commitsig (and by implication, that we're + * sending revoke_and_ack), then wait for it to ack. */ + /* We had to do this after channel_sending_revoke_and_ack, since we + * want it to save the fee_states produced there. */ + msg_for_master + = towire_channeld_got_commitsig(NULL, + peer->next_index[LOCAL] - 1, + peer->channel->fee_states, + peer->channel->blockheight_states, + commit_sig, htlc_sigs, + added, + fulfilled, + failed, + changed, + committx); + master_wait_sync_reply(tmpctx, peer, take(msg_for_master), + WIRE_CHANNELD_GOT_COMMITSIG_REPLY); + + /* Now we can finally send revoke_and_ack to peer */ + peer_write(peer->pps, take(msg)); +} + +static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + struct bitcoin_signature commit_sig; + secp256k1_ecdsa_signature *raw_sigs; + struct bitcoin_signature *htlc_sigs; + struct pubkey remote_htlckey; + struct bitcoin_tx **txs; + const struct htlc **htlc_map, **changed_htlcs; + const u8 *funding_wscript; + size_t i; + struct simple_htlc **htlcs; + const u8 * msg2; + + changed_htlcs = tal_arr(msg, const struct htlc *, 0); + if (!channel_rcvd_commit(peer->channel, &changed_htlcs)) { + /* BOLT #2: + * + * A sending node: + * - MUST NOT send a `commitment_signed` message that does not + * include any updates. + */ + status_debug("Oh hi LND! Empty commitment at #%"PRIu64, + peer->next_index[LOCAL]); + if (peer->last_empty_commitment == peer->next_index[LOCAL] - 1) + peer_failed_warn(peer->pps, &peer->channel_id, + "commit_sig with no changes (again!)"); + peer->last_empty_commitment = peer->next_index[LOCAL]; + } + + /* We were supposed to check this was affordable as we go. */ + if (peer->channel->opener == REMOTE) { + status_debug("Feerates are %u/%u", + channel_feerate(peer->channel, LOCAL), + channel_feerate(peer->channel, REMOTE)); + assert(can_opener_afford_feerate(peer->channel, + channel_feerate(peer->channel, + LOCAL))); + } + + if (!fromwire_commitment_signed(tmpctx, msg, + &channel_id, &commit_sig.s, &raw_sigs)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad commit_sig %s", tal_hex(msg, msg)); + /* SIGHASH_ALL is implied. */ + commit_sig.sighash_type = SIGHASH_ALL; + htlc_sigs = unraw_sigs(tmpctx, raw_sigs, + channel_has(peer->channel, OPT_ANCHOR_OUTPUTS)); + + txs = + channel_txs(tmpctx, &htlc_map, NULL, + &funding_wscript, peer->channel, &peer->next_local_per_commit, + peer->next_index[LOCAL], LOCAL); + + /* Set the commit_sig on the commitment tx psbt */ + if (!psbt_input_set_signature(txs[0]->psbt, 0, + &peer->channel->funding_pubkey[REMOTE], + &commit_sig)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Unable to set signature internally"); + + if (!derive_simple_key(&peer->channel->basepoints[REMOTE].htlc, + &peer->next_local_per_commit, &remote_htlckey)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Deriving remote_htlckey"); + status_debug("Derived key %s from basepoint %s, point %s", + type_to_string(tmpctx, struct pubkey, &remote_htlckey), + type_to_string(tmpctx, struct pubkey, + &peer->channel->basepoints[REMOTE].htlc), + type_to_string(tmpctx, struct pubkey, + &peer->next_local_per_commit)); + /* BOLT #2: + * + * A receiving node: + * - once all pending updates are applied: + * - if `signature` is not valid for its local commitment transaction + * OR non-compliant with LOW-S-standard rule...: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (!check_tx_sig(txs[0], 0, NULL, funding_wscript, + &peer->channel->funding_pubkey[REMOTE], &commit_sig)) { + dump_htlcs(peer->channel, "receiving commit_sig"); + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad commit_sig signature %"PRIu64" %s for tx %s wscript %s key %s feerate %u", + peer->next_index[LOCAL], + type_to_string(msg, struct bitcoin_signature, + &commit_sig), + type_to_string(msg, struct bitcoin_tx, txs[0]), + tal_hex(msg, funding_wscript), + type_to_string(msg, struct pubkey, + &peer->channel->funding_pubkey + [REMOTE]), + channel_feerate(peer->channel, LOCAL)); + } + + /* BOLT #2: + * + * A receiving node: + *... + * - if `num_htlcs` is not equal to the number of HTLC outputs in the + * local commitment transaction: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (tal_count(htlc_sigs) != tal_count(txs) - 1) + peer_failed_warn(peer->pps, &peer->channel_id, + "Expected %zu htlc sigs, not %zu", + tal_count(txs) - 1, tal_count(htlc_sigs)); + + /* BOLT #2: + * + * - if any `htlc_signature` is not valid for the corresponding HTLC + * transaction OR non-compliant with LOW-S-standard rule...: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + for (i = 0; i < tal_count(htlc_sigs); i++) { + u8 *wscript; + + wscript = bitcoin_tx_output_get_witscript(tmpctx, txs[0], + txs[i+1]->wtx->inputs[0].index); + + if (!check_tx_sig(txs[1+i], 0, NULL, wscript, + &remote_htlckey, &htlc_sigs[i])) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad commit_sig signature %s for htlc %s wscript %s key %s", + type_to_string(msg, struct bitcoin_signature, &htlc_sigs[i]), + type_to_string(msg, struct bitcoin_tx, txs[1+i]), + tal_hex(msg, wscript), + type_to_string(msg, struct pubkey, + &remote_htlckey)); + } + + status_debug("Received commit_sig with %zu htlc sigs", + tal_count(htlc_sigs)); + + /* Validate the counterparty's signatures, returns prior per_commitment_secret. */ + htlcs = collect_htlcs(NULL, htlc_map); + msg2 = towire_hsmd_validate_commitment_tx(NULL, + txs[0], + (const struct simple_htlc **) htlcs, + peer->next_index[LOCAL], + channel_feerate(peer->channel, LOCAL), + &commit_sig, + htlc_sigs); + tal_free(htlcs); + msg2 = hsm_req(tmpctx, take(msg2)); + struct secret *old_secret; + struct pubkey next_point; + if (!fromwire_hsmd_validate_commitment_tx_reply(tmpctx, msg2, &old_secret, &next_point)) + status_failed(STATUS_FAIL_HSM_IO, + "Reading validate_commitment_tx reply: %s", + tal_hex(tmpctx, msg2)); + + send_revocation(peer, &commit_sig, htlc_sigs, changed_htlcs, txs[0], + old_secret, &next_point); + + /* We may now be quiescent on our side. */ + maybe_send_stfu(peer); + + /* This might have synced the feerates: if so, we may want to + * update */ + if (want_fee_update(peer, NULL)) + start_commit_timer(peer); +} + +/* Pops the penalty base for the given commitnum from our internal list. There + * may not be one, in which case we return NULL and leave the list + * unmodified. */ +static struct penalty_base * +penalty_base_by_commitnum(const tal_t *ctx, struct peer *peer, u64 commitnum) +{ + struct penalty_base *res = NULL; + for (size_t i = 0; i < tal_count(peer->pbases); i++) { + if (peer->pbases[i]->commitment_num == commitnum) { + res = tal_steal(ctx, peer->pbases[i]); + tal_arr_remove(&peer->pbases, i); + break; + } + } + return res; +} + +static u8 *got_revoke_msg(struct peer *peer, u64 revoke_num, + const struct secret *per_commitment_secret, + const struct pubkey *next_per_commit_point, + const struct htlc **changed_htlcs, + const struct fee_states *fee_states, + const struct height_states *blockheight_states) +{ + u8 *msg; + struct penalty_base *pbase; + struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); + const struct bitcoin_tx *ptx = NULL; + + for (size_t i = 0; i < tal_count(changed_htlcs); i++) { + struct changed_htlc c; + const struct htlc *htlc = changed_htlcs[i]; + + status_debug("HTLC %"PRIu64"[%s] => %s", + htlc->id, side_to_str(htlc_owner(htlc)), + htlc_state_name(htlc->state)); + + c.id = changed_htlcs[i]->id; + c.newstate = changed_htlcs[i]->state; + tal_arr_expand(&changed, c); + } + + pbase = penalty_base_by_commitnum(tmpctx, peer, revoke_num); + + if (pbase) { + ptx = penalty_tx_create( + NULL, peer->channel, peer->feerate_penalty, + peer->final_index, peer->final_ext_key, + peer->final_scriptpubkey, per_commitment_secret, + &pbase->txid, pbase->outnum, pbase->amount, + HSM_FD); + } + + msg = towire_channeld_got_revoke(peer, revoke_num, per_commitment_secret, + next_per_commit_point, fee_states, + blockheight_states, changed, + pbase, ptx); + tal_free(ptx); + return msg; +} + +static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) +{ + struct secret old_commit_secret; + struct privkey privkey; + struct channel_id channel_id; + const u8 *revocation_msg; + struct pubkey per_commit_point, next_per_commit; + const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); + + if (!fromwire_revoke_and_ack(msg, &channel_id, &old_commit_secret, + &next_per_commit)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad revoke_and_ack %s", tal_hex(msg, msg)); + } + + if (peer->revocations_received != peer->next_index[REMOTE] - 2) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Unexpected revoke_and_ack"); + } + + /* Submit the old revocation secret to the signer so it can + * independently verify that the latest state is commited. It + * is also validated in this routine after the signer returns. + */ + revocation_msg = towire_hsmd_validate_revocation(tmpctx, + peer->next_index[REMOTE] - 2, + &old_commit_secret); + revocation_msg = hsm_req(tmpctx, take(revocation_msg)); + if (!fromwire_hsmd_validate_revocation_reply(revocation_msg)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad hsmd_validate_revocation_reply: %s", + tal_hex(tmpctx, revocation_msg)); + + /* BOLT #2: + * + * A receiving node: + * - if `per_commitment_secret` is not a valid secret key or does not + * generate the previous `per_commitment_point`: + * - MUST send an `error` and fail the channel. + */ + memcpy(&privkey, &old_commit_secret, sizeof(privkey)); + if (!pubkey_from_privkey(&privkey, &per_commit_point)) { + peer_failed_err(peer->pps, &peer->channel_id, + "Bad privkey %s", + type_to_string(msg, struct privkey, &privkey)); + } + if (!pubkey_eq(&per_commit_point, &peer->old_remote_per_commit)) { + peer_failed_err(peer->pps, &peer->channel_id, + "Wrong privkey %s for %"PRIu64" %s", + type_to_string(msg, struct privkey, &privkey), + peer->next_index[LOCAL]-2, + type_to_string(msg, struct pubkey, + &peer->old_remote_per_commit)); + } + + /* We start timer even if this returns false: we might have delayed + * commit because we were waiting for this! */ + if (channel_rcvd_revoke_and_ack(peer->channel, &changed_htlcs)) + status_debug("Commits outstanding after recv revoke_and_ack"); + else + status_debug("No commits outstanding after recv revoke_and_ack"); + + /* Tell master about things this locks in, wait for response */ + msg = got_revoke_msg(peer, peer->revocations_received++, + &old_commit_secret, &next_per_commit, + changed_htlcs, + peer->channel->fee_states, + peer->channel->blockheight_states); + master_wait_sync_reply(tmpctx, peer, take(msg), + WIRE_CHANNELD_GOT_REVOKE_REPLY); + + peer->old_remote_per_commit = peer->remote_per_commit; + peer->remote_per_commit = next_per_commit; + status_debug("revoke_and_ack %s: remote_per_commit = %s, old_remote_per_commit = %s", + side_to_str(peer->channel->opener), + type_to_string(tmpctx, struct pubkey, + &peer->remote_per_commit), + type_to_string(tmpctx, struct pubkey, + &peer->old_remote_per_commit)); + + /* We may now be quiescent on our side. */ + maybe_send_stfu(peer); + + start_commit_timer(peer); +} + +static void handle_peer_fulfill_htlc(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u64 id; + struct preimage preimage; + enum channel_remove_err e; + struct htlc *h; + + if (!fromwire_update_fulfill_htlc(msg, &channel_id, + &id, &preimage)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fulfill_htlc %s", tal_hex(msg, msg)); + } + + e = channel_fulfill_htlc(peer->channel, LOCAL, id, &preimage, &h); + switch (e) { + case CHANNEL_ERR_REMOVE_OK: + /* FIXME: We could send preimages to master immediately. */ + start_commit_timer(peer); + return; + /* These shouldn't happen, because any offered HTLC (which would give + * us the preimage) should have timed out long before. If we + * were to get preimages from other sources, this could happen. */ + case CHANNEL_ERR_NO_SUCH_ID: + case CHANNEL_ERR_ALREADY_FULFILLED: + case CHANNEL_ERR_HTLC_UNCOMMITTED: + case CHANNEL_ERR_HTLC_NOT_IRREVOCABLE: + case CHANNEL_ERR_BAD_PREIMAGE: + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fulfill_htlc: failed to fulfill %" + PRIu64 " error %s", id, channel_remove_err_name(e)); + } + abort(); +} + +static void handle_peer_fail_htlc(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u64 id; + enum channel_remove_err e; + u8 *reason; + struct htlc *htlc; + struct failed_htlc *f; + + /* reason is not an onionreply because spec doesn't know about that */ + if (!fromwire_update_fail_htlc(msg, msg, + &channel_id, &id, &reason)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fail_htlc %s", tal_hex(msg, msg)); + } + + e = channel_fail_htlc(peer->channel, LOCAL, id, &htlc); + switch (e) { + case CHANNEL_ERR_REMOVE_OK: { + htlc->failed = f = tal(htlc, struct failed_htlc); + f->id = id; + f->sha256_of_onion = NULL; + f->onion = new_onionreply(f, take(reason)); + start_commit_timer(peer); + return; + } + case CHANNEL_ERR_NO_SUCH_ID: + case CHANNEL_ERR_ALREADY_FULFILLED: + case CHANNEL_ERR_HTLC_UNCOMMITTED: + case CHANNEL_ERR_HTLC_NOT_IRREVOCABLE: + case CHANNEL_ERR_BAD_PREIMAGE: + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fail_htlc: failed to remove %" + PRIu64 " error %s", id, + channel_remove_err_name(e)); + } + abort(); +} + +static void handle_peer_fail_malformed_htlc(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u64 id; + enum channel_remove_err e; + struct sha256 sha256_of_onion; + u16 failure_code; + struct htlc *htlc; + struct failed_htlc *f; + + if (!fromwire_update_fail_malformed_htlc(msg, &channel_id, &id, + &sha256_of_onion, + &failure_code)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fail_malformed_htlc %s", + tal_hex(msg, msg)); + } + + /* BOLT #2: + * + * - if the `BADONION` bit in `failure_code` is not set for + * `update_fail_malformed_htlc`: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (!(failure_code & BADONION)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fail_malformed_htlc failure code %u", + failure_code); + } + + e = channel_fail_htlc(peer->channel, LOCAL, id, &htlc); + switch (e) { + case CHANNEL_ERR_REMOVE_OK: + htlc->failed = f = tal(htlc, struct failed_htlc); + f->id = id; + f->onion = NULL; + f->sha256_of_onion = tal_dup(f, struct sha256, &sha256_of_onion); + f->badonion = failure_code; + start_commit_timer(peer); + return; + case CHANNEL_ERR_NO_SUCH_ID: + case CHANNEL_ERR_ALREADY_FULFILLED: + case CHANNEL_ERR_HTLC_UNCOMMITTED: + case CHANNEL_ERR_HTLC_NOT_IRREVOCABLE: + case CHANNEL_ERR_BAD_PREIMAGE: + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_fail_malformed_htlc: failed to remove %" + PRIu64 " error %s", id, channel_remove_err_name(e)); + } + abort(); +} + +static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) +{ + struct channel_id channel_id; + u8 *scriptpubkey; + struct tlv_shutdown_tlvs *tlvs; + struct bitcoin_outpoint *wrong_funding; + + /* Disable the channel. */ + send_channel_update(peer, ROUTING_FLAGS_DISABLED); + + if (!fromwire_shutdown(tmpctx, shutdown, &channel_id, &scriptpubkey, + &tlvs)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad shutdown %s", tal_hex(peer, shutdown)); + + /* FIXME: We shouldn't let them initiate a shutdown while the + * channel is active (if we leased funds) */ + + /* BOLT #2: + * + * - if both nodes advertised the `option_upfront_shutdown_script` + * feature, and the receiving node received a non-zero-length + * `shutdown_scriptpubkey` in `open_channel` or `accept_channel`, and + * that `shutdown_scriptpubkey` is not equal to `scriptpubkey`: + * - MAY send a `warning`. + * - MUST fail the connection. + */ + /* openingd only sets this if feature was negotiated at opening. */ + if (tal_count(peer->remote_upfront_shutdown_script) + && !memeq(scriptpubkey, tal_count(scriptpubkey), + peer->remote_upfront_shutdown_script, + tal_count(peer->remote_upfront_shutdown_script))) + peer_failed_warn(peer->pps, &peer->channel_id, + "scriptpubkey %s is not as agreed upfront (%s)", + tal_hex(peer, scriptpubkey), + tal_hex(peer, peer->remote_upfront_shutdown_script)); + + /* We only accept an wrong_funding if: + * 1. It was negotiated. + * 2. It's not dual-funding. + * 3. They opened it. + * 4. The channel was never used. + */ + if (tlvs->wrong_funding) { + if (!feature_negotiated(peer->our_features, + peer->their_features, + OPT_SHUTDOWN_WRONG_FUNDING)) + peer_failed_warn(peer->pps, &peer->channel_id, + "wrong_funding shutdown needs" + " feature %u", + OPT_SHUTDOWN_WRONG_FUNDING); + if (feature_negotiated(peer->our_features, + peer->their_features, + OPT_DUAL_FUND)) + peer_failed_warn(peer->pps, &peer->channel_id, + "wrong_funding shutdown invalid" + " with dual-funding"); + if (peer->channel->opener != REMOTE) + peer_failed_warn(peer->pps, &peer->channel_id, + "No shutdown wrong_funding" + " for channels we opened!"); + if (peer->next_index[REMOTE] != 1 + || peer->next_index[LOCAL] != 1) + peer_failed_warn(peer->pps, &peer->channel_id, + "No shutdown wrong_funding" + " for used channels!"); + + /* Turn into our outpoint type. */ + wrong_funding = tal(tmpctx, struct bitcoin_outpoint); + wrong_funding->txid = tlvs->wrong_funding->txid; + wrong_funding->n = tlvs->wrong_funding->outnum; + } else { + wrong_funding = NULL; + } + + /* Tell master: we don't have to wait because on reconnect other end + * will re-send anyway. */ + wire_sync_write(MASTER_FD, + take(towire_channeld_got_shutdown(NULL, scriptpubkey, + wrong_funding))); + + peer->shutdown_sent[REMOTE] = true; + /* BOLT #2: + * + * A receiving node: + * ... + * - once there are no outstanding updates on the peer, UNLESS + * it has already sent a `shutdown`: + * - MUST reply to a `shutdown` message with a `shutdown` + */ + if (!peer->shutdown_sent[LOCAL]) { + peer->send_shutdown = true; + start_commit_timer(peer); + } + billboard_update(peer); +} + +static void handle_unexpected_tx_sigs(struct peer *peer, const u8 *msg) +{ + const struct witness_stack **ws; + struct channel_id cid; + struct bitcoin_txid txid; + + /* In a rare case, a v2 peer may re-send a tx_sigs message. + * This happens when they've/we've exchanged funding_locked, + * but they did not receive our funding_locked. */ + if (!fromwire_tx_signatures(tmpctx, msg, &cid, &txid, + cast_const3(struct witness_stack ***, &ws))) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad tx_signatures %s", + tal_hex(msg, msg)); + + status_info("Unexpected `tx_signatures` from peer. %s", + peer->tx_sigs_allowed ? "Allowing." : "Failing."); + + if (!peer->tx_sigs_allowed) + peer_failed_warn(peer->pps, &peer->channel_id, + "Unexpected `tx_signatures`"); + + peer->tx_sigs_allowed = false; +} + +static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u64 next_commitment_number; + u64 next_revocation_number; + struct secret your_last_per_commitment_secret; + struct pubkey my_current_per_commitment_point; +#if EXPERIMENTAL_FEATURES + struct tlv_channel_reestablish_tlvs *tlvs; +#endif + + + if (!fromwire_channel_reestablish +#if EXPERIMENTAL_FEATURES + (tmpctx, msg, &channel_id, + &next_commitment_number, + &next_revocation_number, + &your_last_per_commitment_secret, + &my_current_per_commitment_point, + &tlvs) +#else + (msg, &channel_id, + &next_commitment_number, + &next_revocation_number, + &your_last_per_commitment_secret, + &my_current_per_commitment_point) +#endif + ) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad channel_reestablish %s", tal_hex(peer, msg)); + + /* Is it the same as the peer channel ID? */ + if (channel_id_eq(&channel_id, &peer->channel_id)) { + /* Log this event as unusual. */ + status_unusual("Got repeated WIRE_CHANNEL_REESTABLISH " + "for channel %s, ignoring: %s", + type_to_string(tmpctx, struct channel_id, + &peer->channel_id), + tal_hex(tmpctx, msg)); + /* This is a mitigation for a known bug in some peer software + * that sometimes double-sends a reestablish message. + * + * Ideally we would send some kind of `error` message to the + * peer here, but if we sent an `error` message with the + * same channel ID it would cause the peer to drop the + * channel unilaterally. + * We also cannot use 0x00...00 because that means "all + * channels", so a proper peer (like C-lightning) will + * unilaterally close all channels we have with it, if we + * sent the 0x00...00 channel ID. + * + * So just do not send an error. + */ + return; + } + + /* We only support one channel here, so the unexpected channel is the + * peer getting its wires crossed somewhere. + * Fail the channel they sent, not the channel we are actively + * handling. */ + peer_failed_err(peer->pps, &channel_id, + "Peer sent unexpected message %u, (%s) " + "for nonexistent channel %s", + WIRE_CHANNEL_REESTABLISH, "WIRE_CHANNEL_REESTABLISH", + type_to_string(tmpctx, struct channel_id, + &channel_id)); +} + +static void peer_in(struct peer *peer, const u8 *msg) +{ + enum peer_wire type = fromwire_peektype(msg); + + if (handle_peer_error(peer->pps, &peer->channel_id, msg)) + return; + + /* Must get funding_locked before almost anything. */ + if (!peer->funding_locked[REMOTE]) { + if (type != WIRE_FUNDING_LOCKED_ELTOO + && type != WIRE_SHUTDOWN + /* We expect these for v2 !! */ + && type != WIRE_TX_SIGNATURES + /* lnd sends these early; it's harmless. */ + && type != WIRE_UPDATE_FEE + && type != WIRE_ANNOUNCEMENT_SIGNATURES) { + peer_failed_warn(peer->pps, &peer->channel_id, + "%s (%u) before funding locked eltoo", + peer_wire_name(type), type); + } + } + + switch (type) { + case WIRE_FUNDING_LOCKED_ELTOO: + handle_peer_funding_locked_eltoo(peer, msg); + return; + case WIRE_ANNOUNCEMENT_SIGNATURES: + handle_peer_announcement_signatures(peer, msg); + return; + case WIRE_UPDATE_ADD_HTLC: + handle_peer_add_htlc(peer, msg); + return; + case WIRE_COMMITMENT_SIGNED: + handle_peer_commit_sig(peer, msg); + return; + case WIRE_UPDATE_FEE: + handle_peer_feechange(peer, msg); + return; + case WIRE_UPDATE_BLOCKHEIGHT: + handle_peer_blockheight_change(peer, msg); + return; + case WIRE_REVOKE_AND_ACK: + handle_peer_revoke_and_ack(peer, msg); + return; + case WIRE_UPDATE_FULFILL_HTLC: + handle_peer_fulfill_htlc(peer, msg); + return; + case WIRE_UPDATE_FAIL_HTLC: + handle_peer_fail_htlc(peer, msg); + return; + case WIRE_UPDATE_FAIL_MALFORMED_HTLC: + handle_peer_fail_malformed_htlc(peer, msg); + return; + case WIRE_SHUTDOWN: + handle_peer_shutdown(peer, msg); + return; + case WIRE_UPDATE_NOOP: + case WIRE_YIELD: + /* FIXME handle these messages */ + return; + +#if EXPERIMENTAL_FEATURES + case WIRE_STFU: + handle_stfu(peer, msg); + return; +#endif + case WIRE_INIT: + case WIRE_OPEN_CHANNEL: + case WIRE_ACCEPT_CHANNEL: + case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_SIGNED: + case WIRE_CLOSING_SIGNED: + case WIRE_TX_ADD_INPUT: + case WIRE_TX_REMOVE_INPUT: + case WIRE_TX_ADD_OUTPUT: + case WIRE_TX_REMOVE_OUTPUT: + case WIRE_TX_COMPLETE: + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_TX_SIGNATURES: + handle_unexpected_tx_sigs(peer, msg); + return; + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: + break; + + case WIRE_CHANNEL_REESTABLISH: + handle_unexpected_reestablish(peer, msg); + return; + + /* These are all swallowed by connectd */ + case WIRE_CHANNEL_ANNOUNCEMENT: + case WIRE_CHANNEL_UPDATE: + case WIRE_NODE_ANNOUNCEMENT: + case WIRE_QUERY_SHORT_CHANNEL_IDS: + case WIRE_QUERY_CHANNEL_RANGE: + case WIRE_REPLY_CHANNEL_RANGE: + case WIRE_GOSSIP_TIMESTAMP_FILTER: + case WIRE_REPLY_SHORT_CHANNEL_IDS_END: + case WIRE_PING: + case WIRE_PONG: + case WIRE_WARNING: + case WIRE_ERROR: + case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: + case WIRE_FUNDING_LOCKED: + /* Eltoo stuff */ + case WIRE_OPEN_CHANNEL_ELTOO: + case WIRE_ACCEPT_CHANNEL_ELTOO: + case WIRE_FUNDING_CREATED_ELTOO: + case WIRE_FUNDING_SIGNED_ELTOO: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: + case WIRE_CHANNEL_REESTABLISH_ELTOO: + case WIRE_SHUTDOWN_ELTOO: + case WIRE_CLOSING_SIGNED_ELTOO: + /* Eltoo stuff ends */ + + abort(); + } + + peer_failed_warn(peer->pps, &peer->channel_id, + "Peer sent unknown message %u (%s)", + type, peer_wire_name(type)); +} + +static void resend_revoke(struct peer *peer) +{ + struct pubkey point; + /* Current commit is peer->next_index[LOCAL]-1, revoke prior */ + u8 *msg = make_revocation_msg(peer, peer->next_index[LOCAL]-2, &point); + peer_write(peer->pps, take(msg)); +} + +static void send_fail_or_fulfill(struct peer *peer, const struct htlc *h) +{ + u8 *msg; + + if (h->failed) { + const struct failed_htlc *f = h->failed; + if (f->sha256_of_onion) { + msg = towire_update_fail_malformed_htlc(NULL, + &peer->channel_id, + h->id, + f->sha256_of_onion, + f->badonion); + } else { + msg = towire_update_fail_htlc(peer, &peer->channel_id, h->id, + f->onion->contents); + } + } else if (h->r) { + msg = towire_update_fulfill_htlc(NULL, &peer->channel_id, h->id, + h->r); + } else + peer_failed_warn(peer->pps, &peer->channel_id, + "HTLC %"PRIu64" state %s not failed/fulfilled", + h->id, htlc_state_name(h->state)); + peer_write(peer->pps, take(msg)); +} + +static int cmp_changed_htlc_id(const struct changed_htlc *a, + const struct changed_htlc *b, + void *unused) +{ + /* ids can be the same (sender and receiver are indep) but in + * that case we don't care about order. */ + if (a->id > b->id) + return 1; + else if (a->id < b->id) + return -1; + return 0; +} + +static void resend_commitment(struct peer *peer, struct changed_htlc *last) +{ + size_t i; + struct bitcoin_signature commit_sig, *htlc_sigs; + u8 *msg; + struct bitcoin_tx **txs; + const u8 *funding_wscript; + const struct htlc **htlc_map; + struct wally_tx_output *direct_outputs[NUM_SIDES]; + + status_debug("Retransmitting commitment, feerate LOCAL=%u REMOTE=%u," + " blockheight LOCAL=%u REMOTE=%u", + channel_feerate(peer->channel, LOCAL), + channel_feerate(peer->channel, REMOTE), + channel_blockheight(peer->channel, LOCAL), + channel_blockheight(peer->channel, REMOTE)); + + /* Note that HTLCs must be *added* in order. Simplest thing to do + * is to sort them all into ascending ID order here (we could do + * this when we save them in channel_sending_commit, but older versions + * won't have them sorted in the db, so doing it here is better). */ + asort(last, tal_count(last), cmp_changed_htlc_id, NULL); + + /* BOLT #2: + * + * - if `next_commitment_number` is equal to the commitment + * number of the last `commitment_signed` message the receiving node + * has sent: + * - MUST reuse the same commitment number for its next + * `commitment_signed`. + */ + /* In our case, we consider ourselves already committed to this, so + * retransmission is simplest. */ + /* We need to send fulfills/failures before adds, so we split them + * up into two loops -- this is the 'fulfill/fail' loop */ + for (i = 0; i < tal_count(last); i++) { + const struct htlc *h; + + h = channel_get_htlc(peer->channel, + htlc_state_owner(last[i].newstate), + last[i].id); + /* I think this can happen if we actually received revoke_and_ack + * then they asked for a retransmit */ + if (!h) + peer_failed_warn(peer->pps, &peer->channel_id, + "Can't find HTLC %"PRIu64" to resend", + last[i].id); + + if (h->state == SENT_REMOVE_COMMIT) + send_fail_or_fulfill(peer, h); + } + /* We need to send fulfills/failures before adds, so we split them + * up into two loops -- this is the 'add' loop */ + for (i = 0; i < tal_count(last); i++) { + const struct htlc *h; + + h = channel_get_htlc(peer->channel, + htlc_state_owner(last[i].newstate), + last[i].id); + + /* I think this can happen if we actually received revoke_and_ack + * then they asked for a retransmit */ + if (!h) + peer_failed_warn(peer->pps, &peer->channel_id, + "Can't find HTLC %"PRIu64" to resend", + last[i].id); + + if (h->state == SENT_ADD_COMMIT) { +#if EXPERIMENTAL_FEATURES + struct tlv_update_add_tlvs *tlvs; + if (h->blinding) { + tlvs = tlv_update_add_tlvs_new(tmpctx); + tlvs->blinding = tal_dup(tlvs, struct pubkey, + h->blinding); + } else + tlvs = NULL; +#endif + u8 *msg = towire_update_add_htlc(NULL, &peer->channel_id, + h->id, h->amount, + &h->rhash, + abs_locktime_to_blocks( + &h->expiry), + h->routing +#if EXPERIMENTAL_FEATURES + , tlvs +#endif + ); + peer_write(peer->pps, take(msg)); + } + } + + /* Make sure they have the correct fee and blockheight. */ + if (peer->channel->opener == LOCAL) { + msg = towire_update_fee(NULL, &peer->channel_id, + channel_feerate(peer->channel, REMOTE)); + peer_write(peer->pps, take(msg)); + + if (peer->channel->lease_expiry > 0) { + msg = towire_update_blockheight(NULL, &peer->channel_id, + channel_blockheight(peer->channel, REMOTE)); + peer_write(peer->pps, take(msg)); + } + } + + /* Re-send the commitment_signed itself. */ + txs = channel_txs(tmpctx, &htlc_map, direct_outputs, + &funding_wscript, peer->channel, &peer->remote_per_commit, + peer->next_index[REMOTE]-1, REMOTE); + + htlc_sigs = calc_commitsigs(tmpctx, peer, txs, funding_wscript, htlc_map, peer->next_index[REMOTE]-1, + &commit_sig); + msg = towire_commitment_signed(NULL, &peer->channel_id, + &commit_sig.s, + raw_sigs(tmpctx, htlc_sigs)); + peer_write(peer->pps, take(msg)); + + /* If we have already received the revocation for the previous, the + * other side shouldn't be asking for a retransmit! */ + if (peer->revocations_received != peer->next_index[REMOTE] - 2) + status_unusual("Retransmitted commitment_signed %"PRIu64 + " but they already send revocation %"PRIu64"?", + peer->next_index[REMOTE]-1, + peer->revocations_received); +} + +/* BOLT #2: + * + * A receiving node: + * - if `option_static_remotekey` applies to the commitment transaction: + * - if `next_revocation_number` is greater than expected above, AND + * `your_last_per_commitment_secret` is correct for that + * `next_revocation_number` minus 1: + *... + * - otherwise, if it supports `option_data_loss_protect`: + * - if `next_revocation_number` is greater than expected above, + * AND `your_last_per_commitment_secret` is correct for that + * `next_revocation_number` minus 1: + */ +static void check_future_dataloss_fields(struct peer *peer, + u64 next_revocation_number, + const struct secret *last_local_per_commit_secret, + /* This is NULL if option_static_remotekey */ + const struct pubkey *remote_current_per_commitment_point) +{ + const u8 *msg; + bool correct; + + assert(next_revocation_number > peer->next_index[LOCAL] - 1); + + msg = towire_hsmd_check_future_secret(NULL, + next_revocation_number - 1, + last_local_per_commit_secret); + msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_check_future_secret_reply(msg, &correct)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad hsm_check_future_secret_reply: %s", + tal_hex(tmpctx, msg)); + + if (!correct) + peer_failed_err(peer->pps, + &peer->channel_id, + "bad future last_local_per_commit_secret: %"PRIu64 + " vs %"PRIu64, + next_revocation_number, + peer->next_index[LOCAL] - 1); + + /* Oh shit, they really are from the future! */ + peer_billboard(true, "They have future commitment number %"PRIu64 + " vs our %"PRIu64". We must wait for them to close!", + next_revocation_number, + peer->next_index[LOCAL] - 1); + + /* BOLT #2: + * - MUST NOT broadcast its commitment transaction. + * - SHOULD send an `error` to request the peer to fail the channel. + * - SHOULD store `my_current_per_commitment_point` to + * retrieve funds should the sending node broadcast its + * commitment transaction on-chain. + */ + wire_sync_write(MASTER_FD, + take(towire_channeld_fail_fallen_behind(NULL, + remote_current_per_commitment_point))); + + /* We have to send them an error to trigger dropping to chain. */ + peer_failed_err(peer->pps, &peer->channel_id, + "Awaiting unilateral close"); +} + +/* BOLT #2: + * + * A receiving node: + * - if `option_static_remotekey` applies to the commitment transaction: + * ... + * - if `your_last_per_commitment_secret` does not match the expected values: + * - SHOULD send an `error` and fail the channel. + * - otherwise, if it supports `option_data_loss_protect`: + *... + * - otherwise (`your_last_per_commitment_secret` or + * `my_current_per_commitment_point` do not match the expected values): + * - SHOULD send an `error` and fail the channel. + */ +static void check_current_dataloss_fields(struct peer *peer, + u64 next_revocation_number, + u64 next_commitment_number, + const struct secret *last_local_per_commit_secret, + /* NULL if option_static_remotekey */ + const struct pubkey *remote_current_per_commitment_point) +{ + struct secret old_commit_secret; + + /* By the time we're called, we've ensured this is a valid revocation + * number. */ + assert(next_revocation_number == peer->next_index[LOCAL] - 2 + || next_revocation_number == peer->next_index[LOCAL] - 1); + + /* By the time we're called, we've ensured we're within 1 of + * their commitment chain */ + assert(next_commitment_number == peer->next_index[REMOTE] || + next_commitment_number == peer->next_index[REMOTE] - 1); + + if (!last_local_per_commit_secret) + return; + + /* BOLT #2: + * - if `next_revocation_number` equals 0: + * - MUST set `your_last_per_commitment_secret` to all zeroes + */ + + status_debug("next_revocation_number = %"PRIu64, + next_revocation_number); + if (next_revocation_number == 0) + memset(&old_commit_secret, 0, sizeof(old_commit_secret)); + else { + struct pubkey unused; + /* This gets previous revocation number, since asking for + * commitment point N gives secret for N-2 */ + get_per_commitment_point(next_revocation_number+1, + &unused, &old_commit_secret); + } + + if (!secret_eq_consttime(&old_commit_secret, + last_local_per_commit_secret)) + peer_failed_err(peer->pps, + &peer->channel_id, + "bad reestablish: your_last_per_commitment_secret %"PRIu64 + ": %s should be %s", + next_revocation_number, + type_to_string(tmpctx, struct secret, + last_local_per_commit_secret), + type_to_string(tmpctx, struct secret, + &old_commit_secret)); + + if (!remote_current_per_commitment_point) { + status_debug("option_static_remotekey: fields are correct"); + return; + } + + status_debug("Reestablish, comparing commitments. Remote's next local commitment number" + " is %"PRIu64". Our next remote is %"PRIu64" with %"PRIu64 + " revocations received", + next_commitment_number, + peer->next_index[REMOTE], + peer->revocations_received); + + /* Either they haven't received our commitment yet, or we're up to date */ + if (next_commitment_number == peer->revocations_received + 1) { + if (!pubkey_eq(remote_current_per_commitment_point, + &peer->old_remote_per_commit)) { + peer_failed_warn(peer->pps, + &peer->channel_id, + "bad reestablish: remote's " + "my_current_per_commitment_point %"PRIu64 + "is %s; expected %s (new is %s).", + next_commitment_number - 1, + type_to_string(tmpctx, struct pubkey, + remote_current_per_commitment_point), + type_to_string(tmpctx, struct pubkey, + &peer->old_remote_per_commit), + type_to_string(tmpctx, struct pubkey, + &peer->remote_per_commit)); + } + } else { + /* We've sent a commit sig but haven't gotten a revoke+ack back */ + if (!pubkey_eq(remote_current_per_commitment_point, + &peer->remote_per_commit)) { + peer_failed_warn(peer->pps, + &peer->channel_id, + "bad reestablish: remote's " + "my_current_per_commitment_point %"PRIu64 + "is %s; expected %s (old is %s).", + next_commitment_number - 1, + type_to_string(tmpctx, struct pubkey, + remote_current_per_commitment_point), + type_to_string(tmpctx, struct pubkey, + &peer->remote_per_commit), + type_to_string(tmpctx, struct pubkey, + &peer->old_remote_per_commit)); + } + } + + status_debug("option_data_loss_protect: fields are correct"); +} + +/* Older LND sometimes sends funding_locked before reestablish! */ +/* ... or announcement_signatures. Sigh, let's handle whatever they send. */ +static bool capture_premature_msg(const u8 ***shit_lnd_says, const u8 *msg) +{ + if (fromwire_peektype(msg) == WIRE_CHANNEL_REESTABLISH) + return false; + + /* Don't allow infinite memory consumption. */ + if (tal_count(*shit_lnd_says) > 10) + return false; + + status_debug("Stashing early %s msg!", + peer_wire_name(fromwire_peektype(msg))); + + tal_arr_expand(shit_lnd_says, tal_steal(*shit_lnd_says, msg)); + return true; +} + +#if EXPERIMENTAL_FEATURES +/* Unwrap a channel_type into a raw byte array for the wire: can be NULL */ +static u8 *to_bytearr(const tal_t *ctx, + const struct channel_type *channel_type TAKES) +{ + u8 *ret; + bool steal; + + steal = taken(channel_type); + if (!channel_type) + return NULL; + + if (steal) { + ret = tal_steal(ctx, channel_type->features); + tal_free(channel_type); + } else + ret = tal_dup_talarr(ctx, u8, channel_type->features); + return ret; +} + +/* This is the no-tlvs version, where we can't handle old tlvs */ +static bool fromwire_channel_reestablish_notlvs(const void *p, struct channel_id *channel_id, u64 *next_commitment_number, u64 *next_revocation_number, struct secret *your_last_per_commitment_secret, struct pubkey *my_current_per_commitment_point) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_CHANNEL_REESTABLISH) + return false; + fromwire_channel_id(&cursor, &plen, channel_id); + *next_commitment_number = fromwire_u64(&cursor, &plen); + *next_revocation_number = fromwire_u64(&cursor, &plen); + fromwire_secret(&cursor, &plen, your_last_per_commitment_secret); + fromwire_pubkey(&cursor, &plen, my_current_per_commitment_point); + return cursor != NULL; +} +#endif + +static void peer_reconnect(struct peer *peer, + const struct secret *last_remote_per_commit_secret, + bool reestablish_only) +{ + struct channel_id channel_id; + /* Note: BOLT #2 uses these names! */ + u64 next_commitment_number, next_revocation_number; + bool retransmit_revoke_and_ack, retransmit_commitment_signed; + struct htlc_map_iter it; + const struct htlc *htlc; + u8 *msg; + struct pubkey my_current_per_commitment_point, + remote_current_per_commitment_point; + struct secret last_local_per_commitment_secret; + bool dataloss_protect, check_extra_fields; + const u8 **premature_msgs = tal_arr(peer, const u8 *, 0); +#if EXPERIMENTAL_FEATURES + struct tlv_channel_reestablish_tlvs *send_tlvs, *recv_tlvs; +#endif + + dataloss_protect = feature_negotiated(peer->our_features, + peer->their_features, + OPT_DATA_LOSS_PROTECT); + + /* Both these options give us extra fields to check. */ + check_extra_fields + = dataloss_protect || channel_has(peer->channel, OPT_STATIC_REMOTEKEY); + + /* Our current per-commitment point is the commitment point in the last + * received signed commitment */ + get_per_commitment_point(peer->next_index[LOCAL] - 1, + &my_current_per_commitment_point, NULL); + +#if EXPERIMENTAL_FEATURES + /* Subtle: we free tmpctx below as we loop, so tal off peer */ + send_tlvs = tlv_channel_reestablish_tlvs_new(peer); + + /* FIXME: v0.10.1 would send a different tlv set, due to older spec. + * That did *not* offer OPT_QUIESCE, so in that case don't send tlvs. */ + if (!feature_negotiated(peer->our_features, + peer->their_features, + OPT_QUIESCE)) + goto skip_tlvs; + + /* BOLT-upgrade_protocol #2: + * A node sending `channel_reestablish`, if it supports upgrading channels: + * - MUST set `next_to_send` the commitment number of the next + * `commitment_signed` it expects to send. + */ + send_tlvs->next_to_send = tal_dup(send_tlvs, u64, &peer->next_index[REMOTE]); + + /* BOLT-upgrade_protocol #2: + * - if it initiated the channel: + * - MUST set `desired_type` to the channel_type it wants for the + * channel. + */ + if (peer->channel->opener == LOCAL) + send_tlvs->desired_channel_type = + to_bytearr(send_tlvs, + take(channel_desired_type(NULL, + peer->channel))); + else { + /* BOLT-upgrade_protocol #2: + * - otherwise: + * - MUST set `current_type` to the current channel_type of the + * channel. + * - MUST set `upgradable` to the channel types it could change + * to. + * - MAY not set `upgradable` if it would be empty. + */ + send_tlvs->current_channel_type + = to_bytearr(send_tlvs, peer->channel->type); + send_tlvs->upgradable_channel_type + = to_bytearr(send_tlvs, + take(channel_upgradable_type(NULL, + peer->channel))); + } + +skip_tlvs: +#endif + + /* BOLT #2: + * + * - upon reconnection: + * - if a channel is in an error state: + * - SHOULD retransmit the error packet and ignore any other packets for + * that channel. + * - otherwise: + * - MUST transmit `channel_reestablish` for each channel. + * - MUST wait to receive the other node's `channel_reestablish` + * message before sending any other messages for that channel. + * + * The sending node: + * - MUST set `next_commitment_number` to the commitment number + * of the next `commitment_signed` it expects to receive. + * - MUST set `next_revocation_number` to the commitment number + * of the next `revoke_and_ack` message it expects to receive. + * - if `option_static_remotekey` applies to the commitment transaction: + * - MUST set `my_current_per_commitment_point` to a valid point. + * - otherwise: + * - MUST set `my_current_per_commitment_point` to its commitment + * point for the last signed commitment it received from its + * channel peer (i.e. the commitment_point corresponding to the + * commitment transaction the sender would use to unilaterally + * close). + * - if `next_revocation_number` equals 0: + * - MUST set `your_last_per_commitment_secret` to all zeroes + * - otherwise: + * - MUST set `your_last_per_commitment_secret` to the last + * `per_commitment_secret` it received + */ + if (channel_has(peer->channel, OPT_STATIC_REMOTEKEY)) { + msg = towire_channel_reestablish + (NULL, &peer->channel_id, + peer->next_index[LOCAL], + peer->revocations_received, + last_remote_per_commit_secret, + /* Can send any (valid) point here */ + &peer->remote_per_commit +#if EXPERIMENTAL_FEATURES + , send_tlvs +#endif + ); + } else { + msg = towire_channel_reestablish + (NULL, &peer->channel_id, + peer->next_index[LOCAL], + peer->revocations_received, + last_remote_per_commit_secret, + &my_current_per_commitment_point +#if EXPERIMENTAL_FEATURES + , send_tlvs +#endif + ); + } + + peer_write(peer->pps, take(msg)); + + peer_billboard(false, "Sent reestablish, waiting for theirs"); + + /* Read until they say something interesting (don't forward + * gossip *to* them yet: we might try sending channel_update + * before we've reestablished channel). */ + do { + clean_tmpctx(); + msg = peer_read(tmpctx, peer->pps); + + /* connectd promised us the msg was reestablish? */ + if (reestablish_only) { + if (fromwire_peektype(msg) != WIRE_CHANNEL_REESTABLISH) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Expected reestablish, got: %s", + tal_hex(tmpctx, msg)); + } + } while (handle_peer_error(peer->pps, &peer->channel_id, msg) || + capture_premature_msg(&premature_msgs, msg)); + +#if EXPERIMENTAL_FEATURES + /* Initialize here in case we don't read it below! */ + recv_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx); + + /* FIXME: v0.10.1 would send a different tlv set, due to older spec. + * That did *not* offer OPT_QUIESCE, so in that case ignore tlvs. */ + if (!feature_negotiated(peer->our_features, + peer->their_features, + OPT_QUIESCE)) { + if (!fromwire_channel_reestablish_notlvs(msg, + &channel_id, + &next_commitment_number, + &next_revocation_number, + &last_local_per_commitment_secret, + &remote_current_per_commitment_point)) + peer_failed_warn(peer->pps, + &peer->channel_id, + "bad reestablish msg: %s %s", + peer_wire_name(fromwire_peektype(msg)), + tal_hex(msg, msg)); + } else if (!fromwire_channel_reestablish(tmpctx, msg, + &channel_id, + &next_commitment_number, + &next_revocation_number, + &last_local_per_commitment_secret, + &remote_current_per_commitment_point, + &recv_tlvs)) { + peer_failed_warn(peer->pps, + &peer->channel_id, + "bad reestablish msg: %s %s", + peer_wire_name(fromwire_peektype(msg)), + tal_hex(msg, msg)); + } +#else /* !EXPERIMENTAL_FEATURES */ + if (!fromwire_channel_reestablish(msg, + &channel_id, + &next_commitment_number, + &next_revocation_number, + &last_local_per_commitment_secret, + &remote_current_per_commitment_point)) { + peer_failed_warn(peer->pps, + &peer->channel_id, + "bad reestablish msg: %s %s", + peer_wire_name(fromwire_peektype(msg)), + tal_hex(msg, msg)); + } +#endif + + if (!channel_id_eq(&channel_id, &peer->channel_id)) { + peer_failed_err(peer->pps, + &channel_id, + "bad reestablish msg for unknown channel %s: %s", + type_to_string(tmpctx, struct channel_id, + &channel_id), + tal_hex(msg, msg)); + } + + status_debug("Got reestablish commit=%"PRIu64" revoke=%"PRIu64, + next_commitment_number, + next_revocation_number); + + /* BOLT #2: + * + * - if `next_commitment_number` is 1 in both the + * `channel_reestablish` it sent and received: + * - MUST retransmit `funding_locked`. + * - otherwise: + * - MUST NOT retransmit `funding_locked`. + */ + if (peer->funding_locked[LOCAL] + && peer->next_index[LOCAL] == 1 + && next_commitment_number == 1) { + u8 *msg; + + status_debug("Retransmitting funding_locked for channel %s", + type_to_string(tmpctx, struct channel_id, &peer->channel_id)); + /* Contains per commit point #1, for first post-opening commit */ + msg = towire_funding_locked(NULL, + &peer->channel_id, + &peer->next_local_per_commit); + peer_write(peer->pps, take(msg)); + } + + /* Note: next_index is the index of the current commit we're working + * on, but BOLT #2 refers to the *last* commit index, so we -1 where + * required. */ + + /* BOLT #2: + * + * - if `next_revocation_number` is equal to the commitment + * number of the last `revoke_and_ack` the receiving node sent, AND + * the receiving node hasn't already received a `closing_signed`: + * - MUST re-send the `revoke_and_ack`. + * - if it has previously sent a `commitment_signed` that needs to be + * retransmitted: + * - MUST retransmit `revoke_and_ack` and `commitment_signed` in the + * same relative order as initially transmitted. + * - otherwise: + * - if `next_revocation_number` is not equal to 1 greater + * than the commitment number of the last `revoke_and_ack` the + * receiving node has sent: + * - SHOULD send an `error` and fail the channel. + * - if it has not sent `revoke_and_ack`, AND + * `next_revocation_number` is not equal to 0: + * - SHOULD send an `error` and fail the channel. + */ + if (next_revocation_number == peer->next_index[LOCAL] - 2) { + /* Don't try to retransmit revocation index -1! */ + if (peer->next_index[LOCAL] < 2) { + peer_failed_err(peer->pps, + &peer->channel_id, + "bad reestablish revocation_number: %" + PRIu64, + next_revocation_number); + } + retransmit_revoke_and_ack = true; + } else if (next_revocation_number < peer->next_index[LOCAL] - 1) { + peer_failed_err(peer->pps, + &peer->channel_id, + "bad reestablish revocation_number: %"PRIu64 + " vs %"PRIu64, + next_revocation_number, + peer->next_index[LOCAL]); + } else if (next_revocation_number > peer->next_index[LOCAL] - 1) { + if (!check_extra_fields) + /* They don't support option_data_loss_protect or + * option_static_remotekey, we fail it due to + * unexpected number */ + peer_failed_err(peer->pps, + &peer->channel_id, + "bad reestablish revocation_number: %"PRIu64 + " vs %"PRIu64, + next_revocation_number, + peer->next_index[LOCAL] - 1); + + /* Remote claims it's ahead of us: can it prove it? + * Does not return. */ + check_future_dataloss_fields(peer, + next_revocation_number, + &last_local_per_commitment_secret, + channel_has(peer->channel, + OPT_STATIC_REMOTEKEY) + ? NULL : + &remote_current_per_commitment_point); + } else + retransmit_revoke_and_ack = false; + + /* BOLT #2: + * + * - if `next_commitment_number` is equal to the commitment + * number of the last `commitment_signed` message the receiving node + * has sent: + * - MUST reuse the same commitment number for its next + * `commitment_signed`. + */ + if (next_commitment_number == peer->next_index[REMOTE] - 1) { + /* We completed opening, we don't re-transmit that one! */ + if (next_commitment_number == 0) + peer_failed_err(peer->pps, + &peer->channel_id, + "bad reestablish commitment_number: %" + PRIu64, + next_commitment_number); + + retransmit_commitment_signed = true; + + /* BOLT #2: + * + * - otherwise: + * - if `next_commitment_number` is not 1 greater than the + * commitment number of the last `commitment_signed` message the + * receiving node has sent: + * - SHOULD send an `error` and fail the channel. + */ + } else if (next_commitment_number != peer->next_index[REMOTE]) + peer_failed_err(peer->pps, + &peer->channel_id, + "bad reestablish commitment_number: %"PRIu64 + " vs %"PRIu64, + next_commitment_number, + peer->next_index[REMOTE]); + else + retransmit_commitment_signed = false; + + /* After we checked basic sanity, we check dataloss fields if any */ + if (check_extra_fields) + check_current_dataloss_fields(peer, + next_revocation_number, + next_commitment_number, + &last_local_per_commitment_secret, + channel_has(peer->channel, + OPT_STATIC_REMOTEKEY) + ? NULL + : &remote_current_per_commitment_point); + + /* BOLT #2: + * - if it has previously sent a `commitment_signed` that needs to be + * retransmitted: + * - MUST retransmit `revoke_and_ack` and `commitment_signed` in the + * same relative order as initially transmitted. + */ + if (retransmit_revoke_and_ack && !peer->last_was_revoke) + resend_revoke(peer); + + if (retransmit_commitment_signed) + resend_commitment(peer, peer->last_sent_commit); + + /* This covers the case where we sent revoke after commit. */ + if (retransmit_revoke_and_ack && peer->last_was_revoke) + resend_revoke(peer); + + /* BOLT #2: + * + * - upon reconnection: + * - if it has sent a previous `shutdown`: + * - MUST retransmit `shutdown`. + */ + /* (If we had sent `closing_signed`, we'd be in closingd). */ + maybe_send_shutdown(peer); + +#if EXPERIMENTAL_FEATURES + if (recv_tlvs->desired_channel_type) + status_debug("They sent desired_channel_type [%s]", + fmt_featurebits(tmpctx, + recv_tlvs->desired_channel_type)); + if (recv_tlvs->current_channel_type) + status_debug("They sent current_channel_type [%s]", + fmt_featurebits(tmpctx, + recv_tlvs->current_channel_type)); + + if (recv_tlvs->upgradable_channel_type) + status_debug("They offered upgrade to [%s]", + fmt_featurebits(tmpctx, + recv_tlvs->upgradable_channel_type)); + + /* BOLT-upgrade_protocol #2: + * + * A node receiving `channel_reestablish`: + * - if it has to retransmit `commitment_signed` or `revoke_and_ack`: + * - MUST consider the channel feature change failed. + */ + if (retransmit_commitment_signed || retransmit_revoke_and_ack) { + status_debug("No upgrade: we retransmitted"); + /* BOLT-upgrade_protocol #2: + * + * - if `next_to_send` is missing, or not equal to the + * `next_commitment_number` it sent: + * - MUST consider the channel feature change failed. + */ + } else if (!recv_tlvs->next_to_send) { + status_debug("No upgrade: no next_to_send received"); + } else if (*recv_tlvs->next_to_send != peer->next_index[LOCAL]) { + status_debug("No upgrade: they're retransmitting"); + /* BOLT-upgrade_protocol #2: + * + * - if updates are pending on either sides' commitment transaction: + * - MUST consider the channel feature change failed. + */ + /* Note that we can have HTLCs we *want* to add or remove + * but haven't yet: thats OK! */ + } else if (pending_updates(peer->channel, LOCAL, true) + || pending_updates(peer->channel, REMOTE, true)) { + status_debug("No upgrade: pending changes"); + } else { + const struct tlv_channel_reestablish_tlvs *initr, *ninitr; + const u8 *type; + + if (peer->channel->opener == LOCAL) { + initr = send_tlvs; + ninitr = recv_tlvs; + } else { + initr = recv_tlvs; + ninitr = send_tlvs; + } + + /* BOLT-upgrade_protocol #2: + * + * - if `desired_channel_type` matches `current_channel_type` or any + * `upgradable_channel_type`: + * - MUST consider the channel type to be `desired_channel_type`. + * - otherwise: + * - MUST consider the channel type change failed. + * - if there is a `current_channel_type` field: + * - MUST consider the channel type to be `current_channel_type`. + */ + if (match_type(initr->desired_channel_type, + ninitr->current_channel_type) + || match_type(initr->desired_channel_type, + ninitr->upgradable_channel_type)) + type = initr->desired_channel_type; + else if (ninitr->current_channel_type) + type = ninitr->current_channel_type; + else + type = NULL; + + if (type) + set_channel_type(peer->channel, type); + } + tal_free(send_tlvs); + +#endif /* EXPERIMENTAL_FEATURES */ + + /* Now stop, we've been polite long enough. */ + if (reestablish_only) { + /* If we were successfully closing, we still go to closingd. */ + if (shutdown_complete(peer)) { + send_shutdown_complete(peer); + daemon_shutdown(); + exit(0); + } + peer_failed_err(peer->pps, + &peer->channel_id, + "Channel is already closed"); + } + + /* Corner case: we didn't send shutdown before because update_add_htlc + * pending, but now they're cleared by restart, and we're actually + * complete. In that case, their `shutdown` will trigger us. */ + + /* Start commit timer: if we sent revoke we might need it. */ + start_commit_timer(peer); + + /* Now, re-send any that we're supposed to be failing. */ + for (htlc = htlc_map_first(peer->channel->htlcs, &it); + htlc; + htlc = htlc_map_next(peer->channel->htlcs, &it)) { + if (htlc->state == SENT_REMOVE_HTLC) + send_fail_or_fulfill(peer, htlc); + } + + /* We allow peer to send us tx-sigs, until funding locked received */ + peer->tx_sigs_allowed = true; + peer_billboard(true, "Reconnected, and reestablished."); + + /* BOLT #2: + * - upon reconnection: + *... + * - MUST transmit `channel_reestablish` for each channel. + * - MUST wait to receive the other node's `channel_reestablish` + * message before sending any other messages for that channel. + */ + /* LND doesn't wait. */ + for (size_t i = 0; i < tal_count(premature_msgs); i++) + peer_in(peer, premature_msgs[i]); + tal_free(premature_msgs); +} + +/* ignores the funding_depth unless depth >= minimum_depth + * (except to update billboard, and set peer->depth_togo). */ +static void handle_funding_depth(struct peer *peer, const u8 *msg) +{ + u32 depth; + struct short_channel_id *scid; + + if (!fromwire_channeld_funding_depth(tmpctx, + msg, + &scid, + &depth)) + master_badmsg(WIRE_CHANNELD_FUNDING_DEPTH, msg); + + /* Too late, we're shutting down! */ + if (peer->shutdown_sent[LOCAL]) + return; + + if (depth < peer->channel->minimum_depth) { + peer->depth_togo = peer->channel->minimum_depth - depth; + + } else { + peer->depth_togo = 0; + + assert(scid); + peer->short_channel_ids[LOCAL] = *scid; + + if (!peer->funding_locked[LOCAL]) { + status_debug("funding_locked: sending commit index" + " %"PRIu64": %s", + peer->next_index[LOCAL], + type_to_string(tmpctx, struct pubkey, + &peer->next_local_per_commit)); + msg = towire_funding_locked(NULL, + &peer->channel_id, + &peer->next_local_per_commit); + peer_write(peer->pps, take(msg)); + + peer->funding_locked[LOCAL] = true; + } + + peer->announce_depth_reached = (depth >= ANNOUNCE_MIN_DEPTH); + + /* Send temporary or final announcements */ + channel_announcement_negotiate(peer); + } + + billboard_update(peer); +} + +static const u8 *get_cupdate(const struct peer *peer) +{ + /* Technically we only need to tell it the first time (unless it's + * changed). But it's not that common. */ + wire_sync_write(MASTER_FD, + take(towire_channeld_used_channel_update(NULL))); + return peer->channel_update; +} + +static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) +{ + u8 *msg; + u32 cltv_expiry; + struct amount_msat amount; + struct sha256 payment_hash; + u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; + enum channel_add_err e; + const u8 *failwiremsg; + const char *failstr; + struct amount_sat htlc_fee; + struct pubkey *blinding; + + if (!peer->funding_locked[LOCAL] || !peer->funding_locked[REMOTE]) + status_failed(STATUS_FAIL_MASTER_IO, + "funding not locked for offer_htlc"); + + if (!fromwire_channeld_offer_htlc(tmpctx, inmsg, &amount, + &cltv_expiry, &payment_hash, + onion_routing_packet, &blinding)) + master_badmsg(WIRE_CHANNELD_OFFER_HTLC, inmsg); + +#if EXPERIMENTAL_FEATURES + struct tlv_update_add_tlvs *tlvs; + if (blinding) { + tlvs = tlv_update_add_tlvs_new(tmpctx); + tlvs->blinding = tal_dup(tlvs, struct pubkey, blinding); + } else + tlvs = NULL; +#endif + + e = channel_add_htlc(peer->channel, LOCAL, peer->htlc_id, + amount, cltv_expiry, &payment_hash, + onion_routing_packet, take(blinding), NULL, + &htlc_fee, true); + status_debug("Adding HTLC %"PRIu64" amount=%s cltv=%u gave %s", + peer->htlc_id, + type_to_string(tmpctx, struct amount_msat, &amount), + cltv_expiry, + channel_add_err_name(e)); + + switch (e) { + case CHANNEL_ERR_ADD_OK: + /* Tell the peer. */ + msg = towire_update_add_htlc(NULL, &peer->channel_id, + peer->htlc_id, amount, + &payment_hash, cltv_expiry, + onion_routing_packet +#if EXPERIMENTAL_FEATURES + , tlvs +#endif + ); + peer_write(peer->pps, take(msg)); + start_commit_timer(peer); + /* Tell the master. */ + msg = towire_channeld_offer_htlc_reply(NULL, peer->htlc_id, + 0, ""); + wire_sync_write(MASTER_FD, take(msg)); + peer->htlc_id++; + return; + case CHANNEL_ERR_INVALID_EXPIRY: + failwiremsg = towire_incorrect_cltv_expiry(inmsg, cltv_expiry, get_cupdate(peer)); + failstr = tal_fmt(inmsg, "Invalid cltv_expiry %u", cltv_expiry); + goto failed; + case CHANNEL_ERR_DUPLICATE: + case CHANNEL_ERR_DUPLICATE_ID_DIFFERENT: + status_failed(STATUS_FAIL_MASTER_IO, + "Duplicate HTLC %"PRIu64, peer->htlc_id); + + case CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED: + failwiremsg = towire_required_node_feature_missing(inmsg); + failstr = "Mini mode: maximum value exceeded"; + goto failed; + /* FIXME: Fuzz the boundaries a bit to avoid probing? */ + case CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED: + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); + failstr = tal_fmt(inmsg, "Capacity exceeded - HTLC fee: %s", fmt_amount_sat(inmsg, htlc_fee)); + goto failed; + case CHANNEL_ERR_HTLC_BELOW_MINIMUM: + failwiremsg = towire_amount_below_minimum(inmsg, amount, get_cupdate(peer)); + failstr = tal_fmt(inmsg, "HTLC too small (%s minimum)", + type_to_string(tmpctx, + struct amount_msat, + &peer->channel->config[REMOTE].htlc_minimum)); + goto failed; + case CHANNEL_ERR_TOO_MANY_HTLCS: + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); + failstr = "Too many HTLCs"; + goto failed; + case CHANNEL_ERR_DUST_FAILURE: + /* BOLT-919 #2: + * - upon an outgoing HTLC: + * - if a HTLC's `amount_msat` is inferior the counterparty's... + * - SHOULD NOT send this HTLC + * - SHOULD fail this HTLC if it's forwarded + */ + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); + failstr = "HTLC too dusty, allowed dust limit reached"; + goto failed; + } + /* Shouldn't return anything else! */ + abort(); + +failed: + msg = towire_channeld_offer_htlc_reply(NULL, 0, failwiremsg, failstr); + wire_sync_write(MASTER_FD, take(msg)); +} + +static void handle_feerates(struct peer *peer, const u8 *inmsg) +{ + u32 feerate; + + if (!fromwire_channeld_feerates(inmsg, &feerate, + &peer->feerate_min, + &peer->feerate_max, + &peer->feerate_penalty)) + master_badmsg(WIRE_CHANNELD_FEERATES, inmsg); + + /* BOLT #2: + * + * The node _responsible_ for paying the Bitcoin fee: + * - SHOULD send `update_fee` to ensure the current fee rate is + * sufficient (by a significant margin) for timely processing of the + * commitment transaction. + */ + if (peer->channel->opener == LOCAL) { + peer->desired_feerate = feerate; + /* Don't do this for the first feerate, wait until something else + * happens. LND seems to get upset in some cases otherwise: + * see https://github.com/ElementsProject/lightning/issues/3596 */ + if (peer->next_index[LOCAL] != 1 + || peer->next_index[REMOTE] != 1) + start_commit_timer(peer); + } else { + /* BOLT #2: + * + * The node _not responsible_ for paying the Bitcoin fee: + * - MUST NOT send `update_fee`. + */ + /* FIXME: We could drop to chain if fees are too low, but + * that's fraught too. */ + } +} + +static void handle_blockheight(struct peer *peer, const u8 *inmsg) +{ + u32 blockheight; + + if (!fromwire_channeld_blockheight(inmsg, &blockheight)) + master_badmsg(WIRE_CHANNELD_BLOCKHEIGHT, inmsg); + + /* Save it, so we know */ + peer->our_blockheight = blockheight; + if (peer->channel->opener == LOCAL) + start_commit_timer(peer); + else { + u32 peer_height = get_blockheight(peer->channel->blockheight_states, + peer->channel->opener, + REMOTE); + /* BOLT- #2: + * The node _not responsible_ for initiating the channel: + * ... + * - if last received `blockheight` is > 1008 behind + * currently known blockheight: + * - SHOULD fail he channel + */ + assert(peer_height + 1008 > peer_height); + if (peer_height + 1008 < blockheight) + peer_failed_err(peer->pps, &peer->channel_id, + "Peer is too far behind, terminating" + " leased channel. Our current" + " %u, theirs %u", + blockheight, peer_height); + /* We're behind them... what do. It's possible they're lying, + * but if we're in a lease this is actually in our favor so + * we log it but otherwise continue on unchanged */ + if (peer_height > blockheight + && peer_height > blockheight + 100) + status_unusual("Peer reporting we've fallen %u" + " blocks behind. Our height %u," + " their height %u", + peer_height - blockheight, + blockheight, peer_height); + + } +} + +static void handle_config_channel(struct peer *peer, const u8 *inmsg) +{ + u32 *base, *ppm; + struct amount_msat *htlc_min, *htlc_max; + bool changed; + + if (!fromwire_channeld_config_channel(inmsg, inmsg, + &base, &ppm, + &htlc_min, + &htlc_max)) + master_badmsg(WIRE_CHANNELD_CONFIG_CHANNEL, inmsg); + + /* only send channel updates if values actually changed */ + changed = false; + if (base && *base != peer->fee_base) { + peer->fee_base = *base; + changed = true; + } + if (ppm && *ppm != peer->fee_per_satoshi) { + peer->fee_per_satoshi = *ppm; + changed = true; + } + if (htlc_min && !amount_msat_eq(*htlc_min, peer->htlc_minimum_msat)) { + peer->htlc_minimum_msat = *htlc_min; + changed = true; + } + if (htlc_max && !amount_msat_eq(*htlc_max, peer->htlc_maximum_msat)) { + peer->htlc_maximum_msat = *htlc_max; + changed = true; + } + + if (changed) + send_channel_update(peer, 0); +} + + +static void handle_preimage(struct peer *peer, const u8 *inmsg) +{ + struct fulfilled_htlc fulfilled_htlc; + struct htlc *h; + + if (!fromwire_channeld_fulfill_htlc(inmsg, &fulfilled_htlc)) + master_badmsg(WIRE_CHANNELD_FULFILL_HTLC, inmsg); + + switch (channel_fulfill_htlc(peer->channel, REMOTE, + fulfilled_htlc.id, + &fulfilled_htlc.payment_preimage, + &h)) { + case CHANNEL_ERR_REMOVE_OK: + send_fail_or_fulfill(peer, h); + start_commit_timer(peer); + return; + /* These shouldn't happen, because any offered HTLC (which would give + * us the preimage) should have timed out long before. If we + * were to get preimages from other sources, this could happen. */ + case CHANNEL_ERR_NO_SUCH_ID: + case CHANNEL_ERR_ALREADY_FULFILLED: + case CHANNEL_ERR_HTLC_UNCOMMITTED: + case CHANNEL_ERR_HTLC_NOT_IRREVOCABLE: + case CHANNEL_ERR_BAD_PREIMAGE: + status_failed(STATUS_FAIL_MASTER_IO, + "HTLC %"PRIu64" preimage failed", + fulfilled_htlc.id); + } + abort(); +} + +static void handle_fail(struct peer *peer, const u8 *inmsg) +{ + struct failed_htlc *failed_htlc; + enum channel_remove_err e; + struct htlc *h; + + if (!fromwire_channeld_fail_htlc(inmsg, inmsg, &failed_htlc)) + master_badmsg(WIRE_CHANNELD_FAIL_HTLC, inmsg); + + e = channel_fail_htlc(peer->channel, REMOTE, failed_htlc->id, &h); + switch (e) { + case CHANNEL_ERR_REMOVE_OK: + h->failed = tal_steal(h, failed_htlc); + send_fail_or_fulfill(peer, h); + start_commit_timer(peer); + return; + case CHANNEL_ERR_NO_SUCH_ID: + case CHANNEL_ERR_ALREADY_FULFILLED: + case CHANNEL_ERR_HTLC_UNCOMMITTED: + case CHANNEL_ERR_HTLC_NOT_IRREVOCABLE: + case CHANNEL_ERR_BAD_PREIMAGE: + status_failed(STATUS_FAIL_MASTER_IO, + "HTLC %"PRIu64" removal failed: %s", + failed_htlc->id, + channel_remove_err_name(e)); + } + abort(); +} + +static void handle_shutdown_cmd(struct peer *peer, const u8 *inmsg) +{ + u32 *final_index; + struct ext_key *final_ext_key; + u8 *local_shutdown_script; + + if (!fromwire_channeld_send_shutdown(peer, inmsg, + &final_index, + &final_ext_key, + &local_shutdown_script, + &peer->shutdown_wrong_funding)) + master_badmsg(WIRE_CHANNELD_SEND_SHUTDOWN, inmsg); + + tal_free(peer->final_index); + peer->final_index = final_index; + + tal_free(peer->final_ext_key); + peer->final_ext_key = final_ext_key; + + tal_free(peer->final_scriptpubkey); + peer->final_scriptpubkey = local_shutdown_script; + + /* We can't send this until commit (if any) is done, so start timer. */ + peer->send_shutdown = true; + start_commit_timer(peer); +} + +/* Lightningd tells us when channel_update has changed. */ +static void handle_channel_update(struct peer *peer, const u8 *msg) +{ + peer->channel_update = tal_free(peer->channel_update); + if (!fromwire_channeld_channel_update(peer, msg, &peer->channel_update)) + master_badmsg(WIRE_CHANNELD_CHANNEL_UPDATE, msg); +} + +static void handle_send_error(struct peer *peer, const u8 *msg) +{ + char *reason; + if (!fromwire_channeld_send_error(msg, msg, &reason)) + master_badmsg(WIRE_CHANNELD_SEND_ERROR, msg); + status_debug("Send error reason: %s", reason); + peer_write(peer->pps, + take(towire_errorfmt(NULL, &peer->channel_id, + "%s", reason))); + + wire_sync_write(MASTER_FD, + take(towire_channeld_send_error_reply(NULL))); +} + +#if DEVELOPER +static void handle_dev_reenable_commit(struct peer *peer) +{ + peer->dev_disable_commit = tal_free(peer->dev_disable_commit); + start_commit_timer(peer); + status_debug("dev_reenable_commit"); + wire_sync_write(MASTER_FD, + take(towire_channeld_dev_reenable_commit_reply(NULL))); +} + +static void handle_dev_memleak(struct peer *peer, const u8 *msg) +{ + struct htable *memtable; + bool found_leak; + + memtable = memleak_find_allocations(tmpctx, msg, msg); + + /* Now delete peer and things it has pointers to. */ + memleak_remove_region(memtable, peer, tal_bytelen(peer)); + + found_leak = dump_memleak(memtable, memleak_status_broken); + wire_sync_write(MASTER_FD, + take(towire_channeld_dev_memleak_reply(NULL, + found_leak))); +} + +#if EXPERIMENTAL_FEATURES +static void handle_dev_quiesce(struct peer *peer, const u8 *msg) +{ + if (!fromwire_channeld_dev_quiesce(msg)) + master_badmsg(WIRE_CHANNELD_DEV_QUIESCE, msg); + + /* Don't do this twice. */ + if (peer->stfu) + status_failed(STATUS_FAIL_MASTER_IO, "dev_quiesce already"); + + peer->stfu = true; + peer->stfu_initiator = LOCAL; + maybe_send_stfu(peer); +} +#endif /* EXPERIMENTAL_FEATURES */ +#endif /* DEVELOPER */ + +static void req_in(struct peer *peer, const u8 *msg) +{ + enum channeld_wire t = fromwire_peektype(msg); + + switch (t) { + case WIRE_CHANNELD_FUNDING_DEPTH: + handle_funding_depth(peer, msg); + return; + case WIRE_CHANNELD_OFFER_HTLC: + if (handle_master_request_later(peer, msg)) + return; + handle_offer_htlc(peer, msg); + return; + case WIRE_CHANNELD_FEERATES: + if (handle_master_request_later(peer, msg)) + return; + handle_feerates(peer, msg); + return; + case WIRE_CHANNELD_BLOCKHEIGHT: + if (handle_master_request_later(peer, msg)) + return; + handle_blockheight(peer, msg); + return; + case WIRE_CHANNELD_FULFILL_HTLC: + if (handle_master_request_later(peer, msg)) + return; + handle_preimage(peer, msg); + return; + case WIRE_CHANNELD_FAIL_HTLC: + if (handle_master_request_later(peer, msg)) + return; + handle_fail(peer, msg); + return; + case WIRE_CHANNELD_CONFIG_CHANNEL: + if (handle_master_request_later(peer, msg)) + return; + handle_config_channel(peer, msg); + return; + case WIRE_CHANNELD_SEND_SHUTDOWN: + handle_shutdown_cmd(peer, msg); + return; + case WIRE_CHANNELD_SEND_ERROR: + handle_send_error(peer, msg); + return; + case WIRE_CHANNELD_CHANNEL_UPDATE: + handle_channel_update(peer, msg); + return; +#if DEVELOPER + case WIRE_CHANNELD_DEV_REENABLE_COMMIT: + handle_dev_reenable_commit(peer); + return; + case WIRE_CHANNELD_DEV_MEMLEAK: + handle_dev_memleak(peer, msg); + return; + case WIRE_CHANNELD_DEV_QUIESCE: +#if EXPERIMENTAL_FEATURES + handle_dev_quiesce(peer, msg); + return; +#endif /* EXPERIMENTAL_FEATURES */ +#else + case WIRE_CHANNELD_DEV_REENABLE_COMMIT: + case WIRE_CHANNELD_DEV_MEMLEAK: + case WIRE_CHANNELD_DEV_QUIESCE: +#endif /* DEVELOPER */ + case WIRE_CHANNELD_INIT: + case WIRE_CHANNELD_OFFER_HTLC_REPLY: + case WIRE_CHANNELD_SENDING_COMMITSIG: + case WIRE_CHANNELD_GOT_COMMITSIG: + case WIRE_CHANNELD_GOT_REVOKE: + case WIRE_CHANNELD_SENDING_COMMITSIG_REPLY: + case WIRE_CHANNELD_GOT_COMMITSIG_REPLY: + case WIRE_CHANNELD_GOT_REVOKE_REPLY: + case WIRE_CHANNELD_GOT_FUNDING_LOCKED: + case WIRE_CHANNELD_GOT_ANNOUNCEMENT: + case WIRE_CHANNELD_GOT_SHUTDOWN: + case WIRE_CHANNELD_SHUTDOWN_COMPLETE: + case WIRE_CHANNELD_DEV_REENABLE_COMMIT_REPLY: + case WIRE_CHANNELD_FAIL_FALLEN_BEHIND: + case WIRE_CHANNELD_DEV_MEMLEAK_REPLY: + case WIRE_CHANNELD_SEND_ERROR_REPLY: + case WIRE_CHANNELD_DEV_QUIESCE_REPLY: + case WIRE_CHANNELD_UPGRADED: + case WIRE_CHANNELD_USED_CHANNEL_UPDATE: + case WIRE_CHANNELD_LOCAL_CHANNEL_UPDATE: + case WIRE_CHANNELD_LOCAL_CHANNEL_ANNOUNCEMENT: + case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: + break; + } + master_badmsg(-1, msg); +} + +/* We do this synchronously. */ +static void init_channel(struct peer *peer) +{ + struct basepoints points[NUM_SIDES]; + struct amount_sat funding_sats; + struct amount_msat local_msat; + struct pubkey funding_pubkey[NUM_SIDES]; + struct channel_config conf[NUM_SIDES]; + struct bitcoin_outpoint funding; + enum side opener; + struct existing_htlc **htlcs; + bool reconnected; + u32 final_index; + struct ext_key final_ext_key; + u8 *fwd_msg; + const u8 *msg; + struct fee_states *fee_states; + struct height_states *blockheight_states; + u32 minimum_depth, lease_expiry; + struct secret last_remote_per_commit_secret; + secp256k1_ecdsa_signature *remote_ann_node_sig; + secp256k1_ecdsa_signature *remote_ann_bitcoin_sig; + struct penalty_base *pbases; + bool reestablish_only; + struct channel_type *channel_type; + u32 *dev_disable_commit; /* Always NULL */ + bool dev_fast_gossip; +#if !DEVELOPER + bool dev_fail_process_onionpacket; /* Ignored */ +#endif + + assert(!(fcntl(MASTER_FD, F_GETFL) & O_NONBLOCK)); + + msg = wire_sync_read(tmpctx, MASTER_FD); + if (!fromwire_channeld_init(peer, msg, + &chainparams, + &peer->our_features, + &peer->channel_id, + &funding, + &funding_sats, + &minimum_depth, + &peer->our_blockheight, + &blockheight_states, + &lease_expiry, + &conf[LOCAL], &conf[REMOTE], + &fee_states, + &peer->feerate_min, + &peer->feerate_max, + &peer->feerate_penalty, + &peer->their_commit_sig, + &funding_pubkey[REMOTE], + &points[REMOTE], + &peer->remote_per_commit, + &peer->old_remote_per_commit, + &opener, + &peer->fee_base, + &peer->fee_per_satoshi, + &peer->htlc_minimum_msat, + &peer->htlc_maximum_msat, + &local_msat, + &points[LOCAL], + &funding_pubkey[LOCAL], + &peer->node_ids[LOCAL], + &peer->node_ids[REMOTE], + &peer->commit_msec, + &peer->cltv_delta, + &peer->last_was_revoke, + &peer->last_sent_commit, + &peer->next_index[LOCAL], + &peer->next_index[REMOTE], + &peer->revocations_received, + &peer->htlc_id, + &htlcs, + &peer->funding_locked[LOCAL], + &peer->funding_locked[REMOTE], + &peer->short_channel_ids[LOCAL], + &reconnected, + &peer->send_shutdown, + &peer->shutdown_sent[REMOTE], + &final_index, + &final_ext_key, + &peer->final_scriptpubkey, + &peer->channel_flags, + &fwd_msg, + &peer->announce_depth_reached, + &last_remote_per_commit_secret, + &peer->their_features, + &peer->remote_upfront_shutdown_script, + &remote_ann_node_sig, + &remote_ann_bitcoin_sig, + &channel_type, + &dev_fast_gossip, + &dev_fail_process_onionpacket, + &dev_disable_commit, + &pbases, + &reestablish_only, + &peer->channel_update)) { + master_badmsg(WIRE_CHANNELD_INIT, msg); + } + + peer->final_index = tal_dup(peer, u32, &final_index); + peer->final_ext_key = tal_dup(peer, struct ext_key, &final_ext_key); + +#if DEVELOPER + peer->dev_disable_commit = dev_disable_commit; + peer->dev_fast_gossip = dev_fast_gossip; +#endif + + status_debug("option_static_remotekey = %u, option_anchor_outputs = %u", + channel_type_has(channel_type, OPT_STATIC_REMOTEKEY), + channel_type_has(channel_type, OPT_ANCHOR_OUTPUTS)); + + /* Keeping an array of pointers is better since it allows us to avoid + * extra allocations later. */ + peer->pbases = tal_arr(peer, struct penalty_base *, 0); + for (size_t i=0; ipbases, + tal_dup(peer, struct penalty_base, &pbases[i])); + tal_free(pbases); + + /* stdin == requests, 3 == peer */ + peer->pps = new_per_peer_state(peer); + per_peer_state_set_fd(peer->pps, 3); + + status_debug("init %s: remote_per_commit = %s, old_remote_per_commit = %s" + " next_idx_local = %"PRIu64 + " next_idx_remote = %"PRIu64 + " revocations_received = %"PRIu64 + " feerates %s range %u-%u" + " blockheights %s, our current %u", + side_to_str(opener), + type_to_string(tmpctx, struct pubkey, + &peer->remote_per_commit), + type_to_string(tmpctx, struct pubkey, + &peer->old_remote_per_commit), + peer->next_index[LOCAL], peer->next_index[REMOTE], + peer->revocations_received, + type_to_string(tmpctx, struct fee_states, fee_states), + peer->feerate_min, peer->feerate_max, + type_to_string(tmpctx, struct height_states, blockheight_states), + peer->our_blockheight); + + if (remote_ann_node_sig && remote_ann_bitcoin_sig) { + peer->announcement_node_sigs[REMOTE] = *remote_ann_node_sig; + peer->announcement_bitcoin_sigs[REMOTE] = *remote_ann_bitcoin_sig; + peer->have_sigs[REMOTE] = true; + + /* Before we store announcement into DB, we have made sure + * remote short_channel_id matched the local. Now we initial + * it directly! + */ + peer->short_channel_ids[REMOTE] = peer->short_channel_ids[LOCAL]; + tal_free(remote_ann_node_sig); + tal_free(remote_ann_bitcoin_sig); + } + + /* First commit is used for opening: if we've sent 0, we're on + * index 1. */ + assert(peer->next_index[LOCAL] > 0); + assert(peer->next_index[REMOTE] > 0); + + get_per_commitment_point(peer->next_index[LOCAL], + &peer->next_local_per_commit, NULL); + + peer->channel = new_full_channel(peer, &peer->channel_id, + &funding, + minimum_depth, + take(blockheight_states), + lease_expiry, + funding_sats, + local_msat, + take(fee_states), + &conf[LOCAL], &conf[REMOTE], + &points[LOCAL], &points[REMOTE], + &funding_pubkey[LOCAL], + &funding_pubkey[REMOTE], + take(channel_type), + feature_offered(peer->their_features, + OPT_LARGE_CHANNELS), + opener); + + if (!channel_force_htlcs(peer->channel, + cast_const2(const struct existing_htlc **, htlcs))) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not restore HTLCs"); + + /* We don't need these any more, so free them. */ + tal_free(htlcs); + + peer->channel_direction = node_id_idx(&peer->node_ids[LOCAL], + &peer->node_ids[REMOTE]); + + /* Default desired feerate is the feerate we set for them last. */ + if (peer->channel->opener == LOCAL) + peer->desired_feerate = channel_feerate(peer->channel, REMOTE); + + /* from now we need keep watch over WIRE_CHANNELD_FUNDING_DEPTH */ + peer->depth_togo = minimum_depth; + + /* OK, now we can process peer messages. */ + if (reconnected) + peer_reconnect(peer, &last_remote_per_commit_secret, + reestablish_only); + else + assert(!reestablish_only); + + /* If we have a messages to send, send them immediately */ + if (fwd_msg) + peer_write(peer->pps, take(fwd_msg)); + + /* Reenable channel */ + channel_announcement_negotiate(peer); + + billboard_update(peer); +} + +int main(int argc, char *argv[]) +{ + setup_locale(); + + int i, nfds; + fd_set fds_in, fds_out; + struct peer *peer; + + subdaemon_setup(argc, argv); + + status_setup_sync(MASTER_FD); + + peer = tal(NULL, struct peer); + timers_init(&peer->timers, time_mono()); + peer->commit_timer = NULL; + peer->have_sigs[LOCAL] = peer->have_sigs[REMOTE] = false; + peer->announce_depth_reached = false; + peer->channel_local_active = false; + peer->from_master = msg_queue_new(peer, true); + peer->shutdown_sent[LOCAL] = false; + peer->shutdown_wrong_funding = NULL; + peer->last_update_timestamp = 0; + peer->last_empty_commitment = 0; +#if EXPERIMENTAL_FEATURES + peer->stfu = false; + peer->stfu_sent[LOCAL] = peer->stfu_sent[REMOTE] = false; + peer->update_queue = msg_queue_new(peer, false); +#endif + + /* We send these to HSM to get real signatures; don't have valgrind + * complain. */ + for (i = 0; i < NUM_SIDES; i++) { + memset(&peer->announcement_node_sigs[i], 0, + sizeof(peer->announcement_node_sigs[i])); + memset(&peer->announcement_bitcoin_sigs[i], 0, + sizeof(peer->announcement_bitcoin_sigs[i])); + } + + /* Prepare the ecdh() function for use */ + ecdh_hsmd_setup(HSM_FD, status_failed); + + /* Read init_channel message sync. */ + init_channel(peer); + + FD_ZERO(&fds_in); + FD_SET(MASTER_FD, &fds_in); + FD_SET(peer->pps->peer_fd, &fds_in); + + FD_ZERO(&fds_out); + FD_SET(peer->pps->peer_fd, &fds_out); + nfds = peer->pps->peer_fd+1; + + while (!shutdown_complete(peer)) { + struct timemono first; + fd_set rfds = fds_in; + struct timeval timeout, *tptr; + struct timer *expired; + const u8 *msg; + struct timemono now = time_mono(); + + /* Free any temporary allocations */ + clean_tmpctx(); + + /* For simplicity, we process one event at a time. */ + msg = msg_dequeue(peer->from_master); + if (msg) { + status_debug("Now dealing with deferred %s", + channeld_wire_name( + fromwire_peektype(msg))); + req_in(peer, msg); + tal_free(msg); + continue; + } + + expired = timers_expire(&peer->timers, now); + if (expired) { + timer_expired(expired); + continue; + } + + /* Might not be waiting for anything. */ + tptr = NULL; + + if (timer_earliest(&peer->timers, &first)) { + timeout = timespec_to_timeval( + timemono_between(first, now).ts); + tptr = &timeout; + } + + if (select(nfds, &rfds, NULL, NULL, tptr) < 0) { + /* Signals OK, eg. SIGUSR1 */ + if (errno == EINTR) + continue; + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "select failed: %s", strerror(errno)); + } + + if (FD_ISSET(MASTER_FD, &rfds)) { + msg = wire_sync_read(tmpctx, MASTER_FD); + + if (!msg) + status_failed(STATUS_FAIL_MASTER_IO, + "Can't read command: %s", + strerror(errno)); + req_in(peer, msg); + } else if (FD_ISSET(peer->pps->peer_fd, &rfds)) { + /* This could take forever, but who cares? */ + msg = peer_read(tmpctx, peer->pps); + peer_in(peer, msg); + } + } + + /* We only exit when shutdown is complete. */ + assert(shutdown_complete(peer)); + send_shutdown_complete(peer); + daemon_shutdown(); + return 0; +} diff --git a/channeld/eltoo_channeld.h b/channeld/eltoo_channeld.h new file mode 100644 index 000000000000..a2b26b08246a --- /dev/null +++ b/channeld/eltoo_channeld.h @@ -0,0 +1,10 @@ +#ifndef LIGHTNING_CHANNELD_CHANNELD_H +#define LIGHTNING_CHANNELD_CHANNELD_H +#include "config.h" +#include +#include +#include + +const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES); + +#endif /* LIGHTNING_CHANNELD_CHANNELD_H */ diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c new file mode 100644 index 000000000000..05448eb25b2c --- /dev/null +++ b/channeld/eltoo_full_channel.c @@ -0,0 +1,1585 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + /* Needs to be at end, since it doesn't include its own hdrs */ + #include "full_channel_error_names_gen.h" + +#if DEVELOPER +static void memleak_help_htlcmap(struct htable *memtable, + struct htlc_map *htlcs) +{ + memleak_remove_htable(memtable, &htlcs->raw); +} +#endif /* DEVELOPER */ + +/* This is a dangerous thing! Because we apply HTLCs in many places + * in bulk, we can temporarily go negative. You must check balance_ok() + * at the end! */ +struct balance { + s64 msat; +}; + +static void to_balance(struct balance *balance, + const struct amount_msat msat) +{ + balance->msat = msat.millisatoshis; /* Raw: balance */ + assert(balance->msat >= 0); +} + +/* What does adding the HTLC do to the balance for this side (subtracts) */ +static void balance_add_htlc(struct balance *balance, + const struct htlc *htlc, + enum side side) +{ + if (htlc_owner(htlc) == side) + balance->msat -= htlc->amount.millisatoshis; /* Raw: balance */ +} + +/* What does removing the HTLC do to the balance for this side (adds) */ +static void balance_remove_htlc(struct balance *balance, + const struct htlc *htlc, + enum side side) +{ + enum side paid_to; + + /* Fulfilled HTLCs are paid to recipient, otherwise returns to owner */ + if (htlc->r) + paid_to = !htlc_owner(htlc); + else + paid_to = htlc_owner(htlc); + + if (side == paid_to) + balance->msat += htlc->amount.millisatoshis; /* Raw: balance */ +} + +static bool balance_ok(const struct balance *balance, + struct amount_msat *msat) + WARN_UNUSED_RESULT; + +static bool balance_ok(const struct balance *balance, + struct amount_msat *msat) +{ + if (balance->msat < 0) + return false; + *msat = amount_msat(balance->msat); + return true; +} + +struct channel *new_full_channel(const tal_t *ctx, + const struct channel_id *cid, + const struct bitcoin_outpoint *funding, + u32 minimum_depth, + const struct height_states *blockheight_states, + u32 lease_expiry, + struct amount_sat funding_sats, + struct amount_msat local_msat, + const struct fee_states *fee_states TAKES, + const struct channel_config *local, + const struct channel_config *remote, + const struct basepoints *local_basepoints, + const struct basepoints *remote_basepoints, + const struct pubkey *local_funding_pubkey, + const struct pubkey *remote_funding_pubkey, + const struct channel_type *type TAKES, + bool option_wumbo, + enum side opener) +{ + struct channel *channel = new_initial_channel(ctx, + cid, + funding, + minimum_depth, + blockheight_states, + lease_expiry, + funding_sats, + local_msat, + fee_states, + local, remote, + local_basepoints, + remote_basepoints, + local_funding_pubkey, + remote_funding_pubkey, + type, + option_wumbo, + opener); + + if (channel) { + channel->htlcs = tal(channel, struct htlc_map); + htlc_map_init(channel->htlcs); + memleak_add_helper(channel->htlcs, memleak_help_htlcmap); + tal_add_destructor(channel->htlcs, htlc_map_clear); + } + return channel; +} + +static void htlc_arr_append(const struct htlc ***arr, const struct htlc *htlc) +{ + if (!arr) + return; + tal_arr_expand(arr, htlc); +} + +static void dump_htlc(const struct htlc *htlc, const char *prefix) +{ + enum htlc_state remote_state; + + if (htlc->state <= RCVD_REMOVE_ACK_REVOCATION) + remote_state = htlc->state + 10; + else + remote_state = htlc->state - 10; + + status_debug("%s: HTLC %s %"PRIu64" = %s/%s %s", + prefix, + htlc_owner(htlc) == LOCAL ? "LOCAL" : "REMOTE", + htlc->id, + htlc_state_name(htlc->state), + htlc_state_name(remote_state), + htlc->r ? "FULFILLED" : htlc->failed ? "FAILED" + : ""); +} + +void dump_htlcs(const struct channel *channel, const char *prefix) +{ +#ifdef SUPERVERBOSE + struct htlc_map_iter it; + const struct htlc *htlc; + + for (htlc = htlc_map_first(channel->htlcs, &it); + htlc; + htlc = htlc_map_next(channel->htlcs, &it)) { + dump_htlc(htlc, prefix); + } +#endif +} + +/* Returns up to three arrays: + * committed: HTLCs currently committed. + * pending_removal: HTLCs pending removal (subset of committed) + * pending_addition: HTLCs pending addition (no overlap with committed) + * + * Also returns number of HTLCs for other side. + */ +static size_t gather_htlcs(const tal_t *ctx, + const struct channel *channel, + enum side side, + const struct htlc ***committed, + const struct htlc ***pending_removal, + const struct htlc ***pending_addition) +{ + struct htlc_map_iter it; + const struct htlc *htlc; + const int committed_flag = HTLC_FLAG(side, HTLC_F_COMMITTED); + const int pending_flag = HTLC_FLAG(side, HTLC_F_PENDING); + size_t num_other_side = 0; + + *committed = tal_arr(ctx, const struct htlc *, 0); + if (pending_removal) + *pending_removal = tal_arr(ctx, const struct htlc *, 0); + if (pending_addition) + *pending_addition = tal_arr(ctx, const struct htlc *, 0); + + if (!channel->htlcs) + return num_other_side; + + for (htlc = htlc_map_first(channel->htlcs, &it); + htlc; + htlc = htlc_map_next(channel->htlcs, &it)) { + if (htlc_has(htlc, committed_flag)) { +#ifdef SUPERVERBOSE + dump_htlc(htlc, "COMMITTED"); +#endif + htlc_arr_append(committed, htlc); + if (htlc_has(htlc, pending_flag)) { +#ifdef SUPERVERBOSE + dump_htlc(htlc, "REMOVING"); +#endif + htlc_arr_append(pending_removal, htlc); + } else if (htlc_owner(htlc) != side) + num_other_side++; + } else if (htlc_has(htlc, pending_flag)) { + htlc_arr_append(pending_addition, htlc); +#ifdef SUPERVERBOSE + dump_htlc(htlc, "ADDING"); +#endif + if (htlc_owner(htlc) != side) + num_other_side++; + } + } + return num_other_side; +} + +static bool sum_offered_msatoshis(struct amount_msat *total, + const struct htlc **htlcs, + enum side side) +{ + size_t i; + + *total = AMOUNT_MSAT(0); + for (i = 0; i < tal_count(htlcs); i++) { + if (htlc_owner(htlcs[i]) == side) { + if (!amount_msat_add(total, *total, htlcs[i]->amount)) + return false; + } + } + return true; +} + +static void add_htlcs(struct bitcoin_tx ***txs, + const struct htlc **htlcmap, + const struct channel *channel, + const struct keyset *keyset, + enum side side) +{ + struct bitcoin_outpoint outpoint; + u32 feerate_per_kw = channel_feerate(channel, side); + bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + + /* Get txid of commitment transaction */ + bitcoin_txid((*txs)[0], &outpoint.txid); + + for (outpoint.n = 0; outpoint.n < tal_count(htlcmap); outpoint.n++) { + const struct htlc *htlc = htlcmap[outpoint.n]; + struct bitcoin_tx *tx; + struct ripemd160 ripemd; + const u8 *wscript; + + if (!htlc) + continue; + + if (htlc_owner(htlc) == side) { + ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); + wscript = htlc_offered_wscript(tmpctx, &ripemd, keyset, + option_anchor_outputs); + tx = htlc_timeout_tx(*txs, chainparams, &outpoint, + wscript, + htlc->amount, + htlc->expiry.locktime, + channel->config[!side].to_self_delay, + feerate_per_kw, + keyset, + option_anchor_outputs); + } else { + ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); + wscript = htlc_received_wscript(tmpctx, &ripemd, + &htlc->expiry, keyset, + option_anchor_outputs); + tx = htlc_success_tx(*txs, chainparams, &outpoint, + wscript, + htlc->amount, + channel->config[!side].to_self_delay, + feerate_per_kw, + keyset, + option_anchor_outputs); + } + + /* Append to array. */ + tal_arr_expand(txs, tx); + } +} + +/* FIXME: We could cache these. */ +struct bitcoin_tx **channel_txs(const tal_t *ctx, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + const u8 **funding_wscript, + const struct channel *channel, + const struct pubkey *per_commitment_point, + u64 commitment_number, + enum side side) +{ + struct bitcoin_tx **txs; + const struct htlc **committed; + struct keyset keyset; + + if (!derive_keyset(per_commitment_point, + &channel->basepoints[side], + &channel->basepoints[!side], + channel_has(channel, OPT_STATIC_REMOTEKEY), + &keyset)) + return NULL; + + /* Figure out what @side will already be committed to. */ + gather_htlcs(ctx, channel, side, &committed, NULL, NULL); + + /* Generating and saving witness script required to spend + * the funding output */ + *funding_wscript = bitcoin_redeem_2of2(ctx, + &channel->funding_pubkey[side], + &channel->funding_pubkey[!side]); + + txs = tal_arr(ctx, struct bitcoin_tx *, 1); + txs[0] = commit_tx( + ctx, &channel->funding, + channel->funding_sats, + &channel->funding_pubkey[side], + &channel->funding_pubkey[!side], + channel->opener, + channel->config[!side].to_self_delay, + channel->lease_expiry, + channel_blockheight(channel, side), + &keyset, channel_feerate(channel, side), + channel->config[side].dust_limit, channel->view[side].owed[side], + channel->view[side].owed[!side], committed, htlcmap, direct_outputs, + commitment_number ^ channel->commitment_number_obscurer, + channel_has(channel, OPT_ANCHOR_OUTPUTS), + side); + + /* Set the remote/local pubkeys on the commitment tx psbt */ + psbt_input_add_pubkey(txs[0]->psbt, 0, + &channel->funding_pubkey[side]); + psbt_input_add_pubkey(txs[0]->psbt, 0, + &channel->funding_pubkey[!side]); + + add_htlcs(&txs, *htlcmap, channel, &keyset, side); + + tal_free(committed); + return txs; +} + +/* If @side is faced with these HTLCs, how much will it have left + * above reserve (eg. to pay fees). Returns false if would be < 0. */ +static bool get_room_above_reserve(const struct channel *channel, + const struct channel_view *view, + const struct htlc **adding, + const struct htlc **removing, + enum side side, + struct amount_msat *remainder) +{ + /* Reserve is set by the *other* side */ + struct amount_sat reserve = channel->config[!side].channel_reserve; + struct balance balance; + + to_balance(&balance, view->owed[side]); + + for (size_t i = 0; i < tal_count(removing); i++) + balance_remove_htlc(&balance, removing[i], side); + + for (size_t i = 0; i < tal_count(adding); i++) + balance_add_htlc(&balance, adding[i], side); + + /* Can happen if amount completely exceeds capacity */ + if (!balance_ok(&balance, remainder)) { + status_debug("Failed to add %zu remove %zu htlcs", + tal_count(adding), tal_count(removing)); + return false; + } + + if (!amount_msat_sub_sat(remainder, *remainder, reserve)) { + status_debug("%s cannot afford htlc: would make balance %s" + " below reserve %s", + side_to_str(side), + type_to_string(tmpctx, struct amount_msat, + remainder), + type_to_string(tmpctx, struct amount_sat, + &reserve)); + return false; + } + return true; +} + +static size_t num_untrimmed_htlcs(enum side side, + struct amount_sat dust_limit, + u32 feerate, + bool option_static_remotekey, + const struct htlc **committed, + const struct htlc **adding, + const struct htlc **removing) +{ + return commit_tx_num_untrimmed(committed, feerate, dust_limit, + option_static_remotekey, side) + + commit_tx_num_untrimmed(adding, feerate, dust_limit, + option_static_remotekey, side) + - commit_tx_num_untrimmed(removing, feerate, dust_limit, + option_static_remotekey, side); +} + +static struct amount_sat fee_for_htlcs(const struct channel *channel, + const struct htlc **committed, + const struct htlc **adding, + const struct htlc **removing, + enum side side) +{ + u32 feerate = channel_feerate(channel, side); + struct amount_sat dust_limit = channel->config[side].dust_limit; + size_t untrimmed; + bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + + untrimmed = num_untrimmed_htlcs(side, dust_limit, feerate, + option_anchor_outputs, + committed, adding, removing); + + return commit_tx_base_fee(feerate, untrimmed, option_anchor_outputs); +} + +static bool htlc_dust(const struct channel *channel, + const struct htlc **committed, + const struct htlc **adding, + const struct htlc **removing, + enum side side, + u32 feerate, + struct amount_msat *trim_total) +{ + struct amount_sat dust_limit = channel->config[side].dust_limit; + bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + struct amount_msat trim_rmvd = AMOUNT_MSAT(0); + + if (!commit_tx_amount_trimmed(committed, feerate, + dust_limit, + option_anchor_outputs, + side, trim_total)) + return false; + if (!commit_tx_amount_trimmed(adding, feerate, + dust_limit, + option_anchor_outputs, + side, trim_total)) + return false; + if (!commit_tx_amount_trimmed(removing, feerate, + dust_limit, + option_anchor_outputs, + side, &trim_rmvd)) + return false; + + return amount_msat_sub(trim_total, *trim_total, trim_rmvd); +} + +/* + * There is a corner case where the opener can spend so much that the + * non-opener can't add any non-dust HTLCs (since the opener would + * have to pay the additional fee, but it can't afford to). This + * leads to the channel starving at the feast! This was reported by + * ACINQ's @t-bast + * (https://github.com/lightningnetwork/lightning-rfc/issues/728) and + * demonstrated with Core Lightning by @m-schmoock + * (https://github.com/ElementsProject/lightning/pull/3498). + * + * To mostly avoid this situation, at least from our side, we apply an + * additional constraint when we're opener trying to add an HTLC: make + * sure we can afford one more HTLC, even if fees increase by 100%. + * + * We could do this for the peer, as well, by rejecting their HTLC + * immediately in this case. But rejecting a remote HTLC here causes + * us to get upset with them and close the channel: we're not well + * architected to reject HTLCs in channeld (it's usually lightningd's + * job, but it doesn't have all the channel balance change calculation + * logic. So we look after ourselves for now, and hope other nodes start + * self-regulating too. + * + * This mitigation will become BOLT #2 standard by: + * https://github.com/lightningnetwork/lightning-rfc/issues/740 + */ +static bool local_opener_has_fee_headroom(const struct channel *channel, + struct amount_msat remainder, + const struct htlc **committed, + const struct htlc **adding, + const struct htlc **removing) +{ + u32 feerate = channel_feerate(channel, LOCAL); + size_t untrimmed; + struct amount_sat fee; + bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + + assert(channel->opener == LOCAL); + + /* How many untrimmed at current feerate? Increasing feerate can + * only *reduce* this number, so use current feerate here! */ + untrimmed = num_untrimmed_htlcs(LOCAL, channel->config[LOCAL].dust_limit, + feerate, + option_anchor_outputs, + committed, adding, removing); + + /* Now, how much would it cost us if feerate increases 100% and we added + * another HTLC? */ + fee = commit_tx_base_fee(2 * feerate, untrimmed + 1, + option_anchor_outputs); + if (amount_msat_greater_eq_sat(remainder, fee)) + return true; + + status_debug("Adding HTLC would leave us only %s: we need %s for" + " another HTLC if fees increase by 100%% to %uperkw", + type_to_string(tmpctx, struct amount_msat, &remainder), + type_to_string(tmpctx, struct amount_sat, &fee), + feerate + feerate); + return false; +} + +static enum channel_add_err add_htlc(struct channel *channel, + enum htlc_state state, + u64 id, + struct amount_msat amount, + u32 cltv_expiry, + const struct sha256 *payment_hash, + const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)], + const struct pubkey *blinding TAKES, + struct htlc **htlcp, + bool enforce_aggregate_limits, + struct amount_sat *htlc_fee, + bool err_immediate_failures) +{ + struct htlc *htlc, *old; + struct amount_msat msat_in_htlcs, committed_msat, + adding_msat, removing_msat, htlc_dust_amt; + enum side sender = htlc_state_owner(state), recipient = !sender; + const struct htlc **committed, **adding, **removing; + const struct channel_view *view; + size_t htlc_count; + bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + u32 feerate, feerate_ceil; + + htlc = tal(tmpctx, struct htlc); + + htlc->id = id; + htlc->amount = amount; + htlc->state = state; + htlc->fail_immediate = false; + + htlc->rhash = *payment_hash; + htlc->blinding = tal_dup_or_null(htlc, struct pubkey, blinding); + htlc->failed = NULL; + htlc->r = NULL; + htlc->routing = tal_dup_arr(htlc, u8, routing, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), 0); + + /* FIXME: Change expiry to simple u32 */ + + /* BOLT #2: + * + * A receiving node: + *... + * - if sending node sets `cltv_expiry` to greater or equal to + * 500000000: + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (!blocks_to_abs_locktime(cltv_expiry, &htlc->expiry)) { + return CHANNEL_ERR_INVALID_EXPIRY; + } + + old = htlc_get(channel->htlcs, htlc->id, htlc_owner(htlc)); + if (old) { + if (old->state != htlc->state + || !amount_msat_eq(old->amount, htlc->amount) + || old->expiry.locktime != htlc->expiry.locktime + || !sha256_eq(&old->rhash, &htlc->rhash)) + return CHANNEL_ERR_DUPLICATE_ID_DIFFERENT; + else + return CHANNEL_ERR_DUPLICATE; + } + + /* We're always considering the recipient's view of the channel here */ + view = &channel->view[recipient]; + + /* BOLT #2: + * + * A receiving node: + * - receiving an `amount_msat` equal to 0, OR less than its own + * `htlc_minimum_msat`: + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (amount_msat_eq(htlc->amount, AMOUNT_MSAT(0))) { + return CHANNEL_ERR_HTLC_BELOW_MINIMUM; + } + if (amount_msat_less(htlc->amount, channel->config[recipient].htlc_minimum)) { + return CHANNEL_ERR_HTLC_BELOW_MINIMUM; + } + + /* FIXME: There used to be a requirement that we not send more than + * 2^32 msat, *but* only electrum enforced it. Remove in next version: + * + * A sending node: + *... + * - for channels with `chain_hash` identifying the Bitcoin blockchain: + * - MUST set the four most significant bytes of `amount_msat` to 0. + */ + if (sender == LOCAL + && amount_msat_greater(htlc->amount, chainparams->max_payment) + && !channel->option_wumbo) { + return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; + } + + /* Figure out what receiver will already be committed to. */ + htlc_count = gather_htlcs(tmpctx, channel, recipient, &committed, &removing, &adding); + htlc_arr_append(&adding, htlc); + + /* BOLT #2: + * + * - if a sending node adds more than receiver `max_accepted_htlcs` + * HTLCs to its local commitment transaction... + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (htlc_count + 1 > channel->config[recipient].max_accepted_htlcs) { + return CHANNEL_ERR_TOO_MANY_HTLCS; + } + + /* Also *we* should not add more htlc's we configured. This + * mitigates attacks in which a peer can force the opener of + * the channel to pay unnecessary onchain fees during a fee + * spike with large commitment transactions. + */ + if (sender == LOCAL + && htlc_count + 1 > channel->config[LOCAL].max_accepted_htlcs) { + return CHANNEL_ERR_TOO_MANY_HTLCS; + } + + /* These cannot overflow with HTLC amount limitations, but + * maybe adding could later if they try to add a maximal HTLC. */ + if (!sum_offered_msatoshis(&committed_msat, + committed, htlc_owner(htlc)) + || !sum_offered_msatoshis(&removing_msat, + removing, htlc_owner(htlc)) + || !sum_offered_msatoshis(&adding_msat, + adding, htlc_owner(htlc))) { + return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; + } + + if (!amount_msat_add(&msat_in_htlcs, committed_msat, adding_msat) + || !amount_msat_sub(&msat_in_htlcs, msat_in_htlcs, removing_msat)) { + return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; + } + + /* BOLT #2: + * + * - if a sending node... adds more than receiver + * `max_htlc_value_in_flight_msat` worth of offered HTLCs to its + * local commitment transaction: + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + + /* We don't enforce this for channel_force_htlcs: some might already + * be fulfilled/failed */ + if (enforce_aggregate_limits + && amount_msat_greater(msat_in_htlcs, + channel->config[recipient].max_htlc_value_in_flight)) { + return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; + } + + /* BOLT #2: + * + * A receiving node: + *... + * - receiving an `amount_msat` that the sending node cannot afford at + * the current `feerate_per_kw` (while maintaining its channel + * reserve and any `to_local_anchor` and `to_remote_anchor` costs): + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (enforce_aggregate_limits) { + struct amount_msat remainder; + struct amount_sat fee = fee_for_htlcs(channel, + committed, + adding, + removing, + recipient); + /* set fee output pointer if given */ + if (htlc_fee) + *htlc_fee = fee; + + /* This is a little subtle: + * + * The change is being applied to the receiver but it will + * come back to the sender after revoke_and_ack. So the check + * here is that the remainder to the sender doesn't go below the + * sender's reserve. */ + if (!get_room_above_reserve(channel, view, + adding, removing, sender, + &remainder)) + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + + /* BOLT #3: + * If `option_anchors` applies to the commitment + * transaction, also subtract two times the fixed anchor size + * of 330 sats from the funder (either `to_local` or + * `to_remote`). + */ + if (option_anchor_outputs + && channel->opener == sender + && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660))) + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + + if (channel->opener== sender) { + if (amount_msat_less_sat(remainder, fee)) { + status_debug("Cannot afford fee %s with %s above reserve", + type_to_string(tmpctx, struct amount_sat, + &fee), + type_to_string(tmpctx, struct amount_msat, + &remainder)); + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + } + + if (sender == LOCAL + && !local_opener_has_fee_headroom(channel, + remainder, + committed, + adding, + removing)) { + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + } + } + + /* Try not to add a payment which will take opener into fees + * on either our side or theirs. */ + if (sender == LOCAL) { + if (!get_room_above_reserve(channel, view, + adding, removing, + channel->opener, + &remainder)) + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + + if (option_anchor_outputs + && channel->opener != sender + && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660))) + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + + /* Should be able to afford both their own commit tx + * fee, and other's commit tx fee, which are subtly + * different! */ + fee = fee_for_htlcs(channel, + committed, + adding, + removing, + channel->opener); + /* set fee output pointer if given */ + if (htlc_fee && amount_sat_greater(fee, *htlc_fee)) + *htlc_fee = fee; + if (amount_msat_less_sat(remainder, fee)) { + status_debug("Funder could not afford own fee %s with %s above reserve", + type_to_string(tmpctx, + struct amount_sat, + &fee), + type_to_string(tmpctx, + struct amount_msat, + &remainder)); + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + } + fee = fee_for_htlcs(channel, + committed, + adding, + removing, + !channel->opener); + /* set fee output pointer if given */ + if (htlc_fee && amount_sat_greater(fee, *htlc_fee)) + *htlc_fee = fee; + if (amount_msat_less_sat(remainder, fee)) { + status_debug("Funder could not afford peer's fee %s with %s above reserve", + type_to_string(tmpctx, + struct amount_sat, + &fee), + type_to_string(tmpctx, + struct amount_msat, + &remainder)); + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + } + } + } + + htlc_dust_amt = AMOUNT_MSAT(0); + feerate = channel_feerate(channel, recipient); + /* Note that we check for trimmed htlcs at an + * *accelerated* rate, so that future feerate changes + * don't suddenly surprise us */ + feerate_ceil = htlc_trim_feerate_ceiling(feerate); + + if (!htlc_dust(channel, committed, + adding, removing, recipient, + feerate_ceil, &htlc_dust_amt)) + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + + if (amount_msat_greater(htlc_dust_amt, + channel->config[LOCAL].max_dust_htlc_exposure_msat)) { + /* BOLT-919 #2: + * A node: + * - upon an incoming HTLC: + * - if a HTLC's `amount_msat` is inferior to the + * counterparty's `dust_limit_satoshis` plus the HTLC-timeout fee + * at the `dust_buffer_feerate`: ... + * - SHOULD fail this HTLC once it's committed + * - SHOULD NOT reveal a preimage for this HTLC + */ + /* Note: Marking this as 'fail_immediate' and + * NOT returning an ERR will fail this HTLC + * once it's committed */ + htlc->fail_immediate = true; + if (err_immediate_failures) + return CHANNEL_ERR_DUST_FAILURE; + } + + + /* Also check the sender, as they'll eventually have the same + * constraint */ + htlc_dust_amt = AMOUNT_MSAT(0); + feerate = channel_feerate(channel, sender); + feerate_ceil = htlc_trim_feerate_ceiling(feerate); + if (!htlc_dust(channel, committed, adding, + removing, sender, feerate_ceil, + &htlc_dust_amt)) + return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + + if (amount_msat_greater(htlc_dust_amt, + channel->config[LOCAL].max_dust_htlc_exposure_msat)) { + htlc->fail_immediate = true; + if (err_immediate_failures) + return CHANNEL_ERR_DUST_FAILURE; + } + dump_htlc(htlc, "NEW:"); + htlc_map_add(channel->htlcs, tal_steal(channel, htlc)); + if (htlcp) + *htlcp = htlc; + + return CHANNEL_ERR_ADD_OK; +} + +enum channel_add_err channel_add_htlc(struct channel *channel, + enum side sender, + u64 id, + struct amount_msat amount, + u32 cltv_expiry, + const struct sha256 *payment_hash, + const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)], + const struct pubkey *blinding TAKES, + struct htlc **htlcp, + struct amount_sat *htlc_fee, + bool err_immediate_failures) +{ + enum htlc_state state; + + if (sender == LOCAL) + state = SENT_ADD_HTLC; + else + state = RCVD_ADD_HTLC; + + /* BOLT #2: + * - MUST increase the value of `id` by 1 for each successive offer. + */ + /* This is a weak (bit cheap) check: */ + if (htlc_get(channel->htlcs, id+1, sender)) + status_broken("Peer sent out-of-order HTLC ids (is that you, old c-lightning node?)"); + + return add_htlc(channel, state, id, amount, cltv_expiry, + payment_hash, routing, blinding, + htlcp, true, htlc_fee, err_immediate_failures); +} + +struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id) +{ + return htlc_get(channel->htlcs, id, sender); +} + +enum channel_remove_err channel_fulfill_htlc(struct channel *channel, + enum side owner, + u64 id, + const struct preimage *preimage, + struct htlc **htlcp) +{ + struct sha256 hash; + struct htlc *htlc; + + htlc = channel_get_htlc(channel, owner, id); + if (!htlc) + return CHANNEL_ERR_NO_SUCH_ID; + + if (htlc->r) + return CHANNEL_ERR_ALREADY_FULFILLED; + + sha256(&hash, preimage, sizeof(*preimage)); + /* BOLT #2: + * + * - if the `payment_preimage` value in `update_fulfill_htlc` + * doesn't SHA256 hash to the corresponding HTLC `payment_hash`: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (!sha256_eq(&hash, &htlc->rhash)) + return CHANNEL_ERR_BAD_PREIMAGE; + + htlc->r = tal_dup(htlc, struct preimage, preimage); + + /* BOLT #2: + * + * - if the `id` does not correspond to an HTLC in its current + * commitment transaction: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { + status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", + htlc->id, htlc_state_name(htlc->state)); + return CHANNEL_ERR_HTLC_UNCOMMITTED; + } + + /* We enforce a stricter check, forcing state machine to be linear, + * based on: */ + /* BOLT #2: + * + * A node: + *... + * - until the corresponding HTLC is irrevocably committed in both + * sides' commitment transactions: + * - MUST NOT send an `update_fulfill_htlc`, `update_fail_htlc`, or + * `update_fail_malformed_htlc`. + */ + if (htlc->state == SENT_ADD_ACK_REVOCATION) + htlc->state = RCVD_REMOVE_HTLC; + else if (htlc->state == RCVD_ADD_ACK_REVOCATION) + htlc->state = SENT_REMOVE_HTLC; + else { + status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", + htlc->id, htlc_state_name(htlc->state)); + return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; + } + + dump_htlc(htlc, "FULFILL:"); + + if (htlcp) + *htlcp = htlc; + + return CHANNEL_ERR_REMOVE_OK; +} + +enum channel_remove_err channel_fail_htlc(struct channel *channel, + enum side owner, u64 id, + struct htlc **htlcp) +{ + struct htlc *htlc; + + htlc = channel_get_htlc(channel, owner, id); + if (!htlc) + return CHANNEL_ERR_NO_SUCH_ID; + + /* BOLT #2: + * + * A receiving node: + * - if the `id` does not correspond to an HTLC in its current + * commitment transaction: + * - MUST send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { + status_unusual("channel_fail_htlc: %"PRIu64" in state %s", + htlc->id, htlc_state_name(htlc->state)); + return CHANNEL_ERR_HTLC_UNCOMMITTED; + } + + /* FIXME: Technically, they can fail this before we're committed to + * it. This implies a non-linear state machine. */ + if (htlc->state == SENT_ADD_ACK_REVOCATION) + htlc->state = RCVD_REMOVE_HTLC; + else if (htlc->state == RCVD_ADD_ACK_REVOCATION) + htlc->state = SENT_REMOVE_HTLC; + else { + status_unusual("channel_fail_htlc: %"PRIu64" in state %s", + htlc->id, htlc_state_name(htlc->state)); + return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; + } + + dump_htlc(htlc, "FAIL:"); + if (htlcp) + *htlcp = htlc; + return CHANNEL_ERR_REMOVE_OK; +} + +static void htlc_incstate(struct channel *channel, + struct htlc *htlc, + enum side sidechanged, + struct balance owed[NUM_SIDES]) +{ + int preflags, postflags; + const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED); + + status_debug("htlc %"PRIu64": %s->%s", htlc->id, + htlc_state_name(htlc->state), + htlc_state_name(htlc->state+1)); + + preflags = htlc_state_flags(htlc->state); + postflags = htlc_state_flags(htlc->state + 1); + /* You can't change sides. */ + assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) + == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); + + htlc->state++; + + /* If we've added or removed, adjust balances. */ + if (!(preflags & committed_f) && (postflags & committed_f)) { + status_debug("htlc added %s: local %"PRId64" remote %"PRId64, + side_to_str(sidechanged), + owed[LOCAL].msat, owed[REMOTE].msat); + balance_add_htlc(&owed[LOCAL], htlc, LOCAL); + balance_add_htlc(&owed[REMOTE], htlc, REMOTE); + status_debug("-> local %"PRId64" remote %"PRId64, + owed[LOCAL].msat, owed[REMOTE].msat); + } else if ((preflags & committed_f) && !(postflags & committed_f)) { + status_debug("htlc added %s: local %"PRId64" remote %"PRId64, + side_to_str(sidechanged), + owed[LOCAL].msat, owed[REMOTE].msat); + balance_remove_htlc(&owed[LOCAL], htlc, LOCAL); + balance_remove_htlc(&owed[REMOTE], htlc, REMOTE); + status_debug("-> local %"PRId64" remote %"PRId64, + owed[LOCAL].msat, owed[REMOTE].msat); + } +} + +/* Returns true if a change was made. */ +static bool fee_incstate(struct channel *channel, + enum side sidechanged, + enum htlc_state hstate) +{ + int preflags, postflags; + + preflags = htlc_state_flags(hstate); + postflags = htlc_state_flags(hstate + 1); + + /* You can't change sides. */ + assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) + == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); + + /* These only advance through ADDING states. */ + if (!(htlc_state_flags(hstate) & HTLC_ADDING)) + return false; + + if (!inc_fee_state(channel->fee_states, hstate)) + return false; + + status_debug("Feerate: %s->%s %s now %u", + htlc_state_name(hstate), + htlc_state_name(hstate+1), + side_to_str(sidechanged), + *channel->fee_states->feerate[hstate+1]); + return true; +} + +static bool blockheight_incstate(struct channel *channel, + enum side sidechanged, + enum htlc_state hstate) +{ + int preflags, postflags; + + preflags = htlc_state_flags(hstate); + postflags = htlc_state_flags(hstate + 1); + + /* You can't change sides. */ + assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) + == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); + + /* These only advance through ADDING states. */ + if (!(htlc_state_flags(hstate) & HTLC_ADDING)) + return false; + + if (!inc_height_state(channel->blockheight_states, hstate)) + return false; + + status_debug("Blockheight: %s->%s %s now %u", + htlc_state_name(hstate), + htlc_state_name(hstate+1), + side_to_str(sidechanged), + *channel->blockheight_states->height[hstate+1]); + return true; +} + +/* Returns flags which were changed. */ +static int change_htlcs(struct channel *channel, + enum side sidechanged, + const enum htlc_state *htlc_states, + size_t n_hstates, + const struct htlc ***htlcs, + const char *prefix) +{ + struct htlc_map_iter it; + struct htlc *h; + int cflags = 0; + int i; + struct balance owed[NUM_SIDES]; + + for (i = 0; i < NUM_SIDES; i++) + to_balance(&owed[i], channel->view[sidechanged].owed[i]); + + for (h = htlc_map_first(channel->htlcs, &it); + h; + h = htlc_map_next(channel->htlcs, &it)) { + for (i = 0; i < n_hstates; i++) { + if (h->state == htlc_states[i]) { + htlc_incstate(channel, h, sidechanged, owed); + dump_htlc(h, prefix); + htlc_arr_append(htlcs, h); + cflags |= (htlc_state_flags(htlc_states[i]) + ^ htlc_state_flags(h->state)); + } + } + } + + for (i = 0; i < NUM_SIDES; i++) { + if (!balance_ok(&owed[i], &channel->view[sidechanged].owed[i])) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "%s: %s balance underflow: %s -> %"PRId64, + side_to_str(sidechanged), + side_to_str(i), + type_to_string(tmpctx, struct amount_msat, + &channel->view[sidechanged].owed[i]), + owed[i].msat); + } + } + + /* Update fees and blockheight (do backwards, to avoid + * double-increment!). */ + for (i = n_hstates - 1; i >= 0; i--) { + if (fee_incstate(channel, sidechanged, htlc_states[i])) + cflags |= (htlc_state_flags(htlc_states[i]) + ^ htlc_state_flags(htlc_states[i]+1)); + + if (blockheight_incstate(channel, sidechanged, htlc_states[i])) + cflags |= (htlc_state_flags(htlc_states[i]) + ^ htlc_state_flags(htlc_states[i]+1)); + } + + return cflags; +} + +/* FIXME: The sender's requirements are *implied* by this, not stated! */ +/* BOLT #2: + * + * A receiving node: + *... + * - if the sender cannot afford the new fee rate on the receiving node's + * current commitment transaction: + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ +u32 approx_max_feerate(const struct channel *channel) +{ + size_t num; + u64 weight; + struct amount_sat avail; + const struct htlc **committed, **adding, **removing; + bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + + gather_htlcs(tmpctx, channel, !channel->opener, + &committed, &removing, &adding); + + /* Assume none are trimmed; this gives lower bound on feerate. */ + num = tal_count(committed) + tal_count(adding) - tal_count(removing); + + weight = commit_tx_base_weight(num, option_anchor_outputs); + + /* Available is their view */ + avail = amount_msat_to_sat_round_down(channel->view[!channel->opener].owed[channel->opener]); + + /* BOLT #3: + * If `option_anchors` applies to the commitment + * transaction, also subtract two times the fixed anchor size + * of 330 sats from the funder (either `to_local` or + * `to_remote`). + */ + if (option_anchor_outputs + && !amount_sat_sub(&avail, avail, AMOUNT_SAT(660))) { + avail = AMOUNT_SAT(0); + } else { + /* We should never go below reserve. */ + if (!amount_sat_sub(&avail, avail, + channel->config[!channel->opener].channel_reserve)) + avail = AMOUNT_SAT(0); + } + + return avail.satoshis / weight * 1000; /* Raw: once-off reverse feerate*/ +} + +/* Is the sum of trimmed htlcs, as this new feerate, above our + * max allowed htlc dust limit? */ +static struct amount_msat htlc_calculate_dust(const struct channel *channel, + u32 feerate_per_kw, + enum side side) +{ + const struct htlc **committed, **adding, **removing; + struct amount_msat acc_dust = AMOUNT_MSAT(0); + + gather_htlcs(tmpctx, channel, side, + &committed, &removing, &adding); + + htlc_dust(channel, committed, adding, removing, + side, feerate_per_kw, &acc_dust); + + return acc_dust; +} + +bool htlc_dust_ok(const struct channel *channel, + u32 feerate_per_kw, + enum side side) +{ + struct amount_msat total_dusted; + + total_dusted = htlc_calculate_dust(channel, feerate_per_kw, side); + + return amount_msat_greater_eq( + channel->config[LOCAL].max_dust_htlc_exposure_msat, + total_dusted); +} + +bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw) +{ + struct amount_sat needed, fee; + struct amount_sat dust_limit = channel->config[!channel->opener].dust_limit; + size_t untrimmed; + const struct htlc **committed, **adding, **removing; + bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); + + gather_htlcs(tmpctx, channel, !channel->opener, + &committed, &removing, &adding); + + untrimmed = commit_tx_num_untrimmed(committed, feerate_per_kw, dust_limit, + option_anchor_outputs, + !channel->opener) + + commit_tx_num_untrimmed(adding, feerate_per_kw, dust_limit, + option_anchor_outputs, + !channel->opener) + - commit_tx_num_untrimmed(removing, feerate_per_kw, dust_limit, + option_anchor_outputs, + !channel->opener); + + fee = commit_tx_base_fee(feerate_per_kw, untrimmed, + option_anchor_outputs); + + /* BOLT #3: + * If `option_anchors` applies to the commitment + * transaction, also subtract two times the fixed anchor size + * of 330 sats from the funder (either `to_local` or + * `to_remote`). + */ + if (option_anchor_outputs + && !amount_sat_add(&fee, fee, AMOUNT_SAT(660))) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Cannot add 660 sats to %s for anchor", + type_to_string(tmpctx, struct amount_sat, + &fee)); + + /* BOLT #2: + * + * - if the sender cannot afford the new fee rate on the receiving + * node's current commitment transaction: + * - SHOULD send a `warning` and close the connection, or send an + * `error` and fail the channel. + */ + /* Note: sender == opener */ + + /* How much does it think it has? Must be >= reserve + fee */ + if (!amount_sat_add(&needed, fee, + channel->config[!channel->opener].channel_reserve)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Cannot add fee %s and reserve %s", + type_to_string(tmpctx, struct amount_sat, + &fee), + type_to_string(tmpctx, struct amount_sat, + &channel->config[!channel->opener].channel_reserve)); + + status_debug("We need %s at feerate %u for %zu untrimmed htlcs: we have %s/%s", + type_to_string(tmpctx, struct amount_sat, &needed), + feerate_per_kw, untrimmed, + type_to_string(tmpctx, struct amount_msat, + &channel->view[LOCAL].owed[channel->opener]), + type_to_string(tmpctx, struct amount_msat, + &channel->view[REMOTE].owed[channel->opener])); + return amount_msat_greater_eq_sat(channel->view[!channel->opener].owed[channel->opener], + needed); +} + +bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw) +{ + if (!can_opener_afford_feerate(channel, feerate_per_kw)) + return false; + + /* BOLT-919 #2: + * - if the `dust_balance_on_holder_tx` at the + * new `dust_buffer_feerate` is superior to + * the `max_dust_htlc_exposure_msat`: + * ... + * - MAY fail the channel + */ + if (!htlc_dust_ok(channel, feerate_per_kw, REMOTE) || + !htlc_dust_ok(channel, feerate_per_kw, LOCAL)) + return false; + + status_debug("Setting %s feerate to %u", + side_to_str(!channel->opener), feerate_per_kw); + + start_fee_update(channel->fee_states, channel->opener, feerate_per_kw); + return true; +} + +void channel_update_blockheight(struct channel *channel, + u32 blockheight) +{ + status_debug("Setting %s blockheight to %u", + side_to_str(!channel->opener), blockheight); + + start_height_update(channel->blockheight_states, channel->opener, + blockheight); +} + +bool channel_sending_commit(struct channel *channel, + const struct htlc ***htlcs) +{ + int change; + const enum htlc_state states[] = { SENT_ADD_HTLC, + SENT_REMOVE_REVOCATION, + SENT_ADD_REVOCATION, + SENT_REMOVE_HTLC }; + status_debug("Trying commit"); + + change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), + htlcs, "sending_commit"); + if (!change) + return false; + + return true; +} + +bool channel_rcvd_revoke_and_ack(struct channel *channel, + const struct htlc ***htlcs) +{ + int change; + const enum htlc_state states[] = { SENT_ADD_COMMIT, + SENT_REMOVE_ACK_COMMIT, + SENT_ADD_ACK_COMMIT, + SENT_REMOVE_COMMIT }; + + status_debug("Received revoke_and_ack"); + change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), + htlcs, "rcvd_revoke_and_ack"); + + /* Their ack can queue changes on our side. */ + return (change & HTLC_LOCAL_F_PENDING); +} + +/* FIXME: We can actually merge these two... */ +bool channel_rcvd_commit(struct channel *channel, const struct htlc ***htlcs) +{ + int change; + const enum htlc_state states[] = { RCVD_ADD_REVOCATION, + RCVD_REMOVE_HTLC, + RCVD_ADD_HTLC, + RCVD_REMOVE_REVOCATION }; + + status_debug("Received commit"); + change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), + htlcs, "rcvd_commit"); + if (!change) + return false; + return true; +} + +bool channel_sending_revoke_and_ack(struct channel *channel) +{ + int change; + const enum htlc_state states[] = { RCVD_ADD_ACK_COMMIT, + RCVD_REMOVE_COMMIT, + RCVD_ADD_COMMIT, + RCVD_REMOVE_ACK_COMMIT }; + status_debug("Sending revoke_and_ack"); + change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), NULL, + "sending_revoke_and_ack"); + + /* Our ack can queue changes on their side. */ + return (change & HTLC_REMOTE_F_PENDING); +} + +size_t num_channel_htlcs(const struct channel *channel) +{ + struct htlc_map_iter it; + const struct htlc *htlc; + size_t n = 0; + + for (htlc = htlc_map_first(channel->htlcs, &it); + htlc; + htlc = htlc_map_next(channel->htlcs, &it)) { + /* FIXME: Clean these out! */ + if (!htlc_is_dead(htlc)) + n++; + } + return n; +} + +static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES], + struct htlc *htlc) +{ + enum side side; + + for (side = 0; side < NUM_SIDES; side++) { + /* Did it ever add it? */ + if (!htlc_has(htlc, HTLC_FLAG(side, HTLC_F_WAS_COMMITTED))) + continue; + + /* Add it. */ + balance_add_htlc(&view_owed[side][LOCAL], htlc, LOCAL); + balance_add_htlc(&view_owed[side][REMOTE], htlc, REMOTE); + + /* If it is no longer committed, remove it (depending + * on fail || fulfill). */ + if (htlc_has(htlc, HTLC_FLAG(side, HTLC_F_COMMITTED))) + continue; + + if (!htlc->failed && !htlc->r) { + status_broken("%s HTLC %"PRIu64 + " %s neither fail nor fulfill?", + htlc_state_owner(htlc->state) == LOCAL + ? "out" : "in", + htlc->id, + htlc_state_name(htlc->state)); + return false; + } + balance_remove_htlc(&view_owed[side][LOCAL], htlc, LOCAL); + balance_remove_htlc(&view_owed[side][REMOTE], htlc, REMOTE); + } + return true; +} + +bool pending_updates(const struct channel *channel, + enum side side, + bool uncommitted_ok) +{ + struct htlc_map_iter it; + const struct htlc *htlc; + + /* Initiator might have fee changes or blockheight updates in play. */ + if (side == channel->opener) { + if (!feerate_changes_done(channel->fee_states, uncommitted_ok)) + return true; + + if (!blockheight_changes_done(channel->blockheight_states, + uncommitted_ok)) + return true; + } + + for (htlc = htlc_map_first(channel->htlcs, &it); + htlc; + htlc = htlc_map_next(channel->htlcs, &it)) { + int flags = htlc_state_flags(htlc->state); + + /* If it's still being added, its owner added it. */ + if (flags & HTLC_ADDING) { + /* It might be OK if it's added, but not committed */ + if (uncommitted_ok + && (flags & HTLC_FLAG(!side, HTLC_F_PENDING))) + continue; + if (htlc_owner(htlc) == side) + return true; + /* If it's being removed, non-owner removed it */ + } else if (htlc_state_flags(htlc->state) & HTLC_REMOVING) { + /* It might be OK if it's removed, but not committed */ + if (uncommitted_ok + && (flags & HTLC_FLAG(!side, HTLC_F_PENDING))) + continue; + if (htlc_owner(htlc) != side) + return true; + } + } + + return false; +} + +bool channel_force_htlcs(struct channel *channel, + const struct existing_htlc **htlcs) +{ + struct balance view_owed[NUM_SIDES][NUM_SIDES]; + + /* You'd think, since we traverse HTLCs in ID order, this would never + * go negative. But this ignores the fact that HTLCs ids from each + * side have no correlation with each other. Copy into struct balance, + * to allow transient underflow. */ + for (int view = 0; view < NUM_SIDES; view++) { + for (int side = 0; side < NUM_SIDES; side++) { + to_balance(&view_owed[view][side], + channel->view[view].owed[side]); + } + } + + for (size_t i = 0; i < tal_count(htlcs); i++) { + enum channel_add_err e; + struct htlc *htlc; + + status_debug("Restoring HTLC %zu/%zu:" + " id=%"PRIu64" amount=%s cltv=%u" + " payment_hash=%s %s", + i, tal_count(htlcs), + htlcs[i]->id, + type_to_string(tmpctx, struct amount_msat, + &htlcs[i]->amount), + htlcs[i]->cltv_expiry, + type_to_string(tmpctx, struct sha256, + &htlcs[i]->payment_hash), + htlcs[i]->payment_preimage ? "(have preimage)" + : htlcs[i]->failed ? "(failed)" : ""); + + e = add_htlc(channel, htlcs[i]->state, + htlcs[i]->id, htlcs[i]->amount, + htlcs[i]->cltv_expiry, + &htlcs[i]->payment_hash, + htlcs[i]->onion_routing_packet, + htlcs[i]->blinding, + &htlc, false, NULL, false); + if (e != CHANNEL_ERR_ADD_OK) { + status_broken("%s HTLC %"PRIu64" failed error %u", + htlc_state_owner(htlcs[i]->state) == LOCAL + ? "out" : "in", htlcs[i]->id, e); + return false; + } + if (htlcs[i]->payment_preimage) + htlc->r = tal_dup(htlc, struct preimage, + htlcs[i]->payment_preimage); + if (htlcs[i]->failed) + htlc->failed = tal_steal(htlc, htlcs[i]->failed); + + if (!adjust_balance(view_owed, htlc)) + return false; + } + + /* Convert back and check */ + for (int view = 0; view < NUM_SIDES; view++) { + for (int side = 0; side < NUM_SIDES; side++) { + if (!balance_ok(&view_owed[view][side], + &channel->view[view].owed[side])) { + status_broken("view %s[%s] balance underflow:" + " %"PRId64, + side_to_str(view), + side_to_str(side), + view_owed[view][side].msat); + return false; + } + } + } + + return true; +} + +const char *channel_add_err_name(enum channel_add_err e) +{ + static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)]; + + for (size_t i = 0; enum_channel_add_err_names[i].name; i++) { + if (enum_channel_add_err_names[i].v == e) + return enum_channel_add_err_names[i].name; + } + snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); + return invalidbuf; +} + +const char *channel_remove_err_name(enum channel_remove_err e) +{ + static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)]; + + for (size_t i = 0; enum_channel_remove_err_names[i].name; i++) { + if (enum_channel_remove_err_names[i].v == e) + return enum_channel_remove_err_names[i].name; + } + snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); + return invalidbuf; +} diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h new file mode 100644 index 000000000000..6f674a75f2c0 --- /dev/null +++ b/channeld/eltoo_full_channel.h @@ -0,0 +1,295 @@ +/* This is the full channel routines, with HTLC support. */ +#ifndef LIGHTNING_CHANNELD_FULL_CHANNEL_H +#define LIGHTNING_CHANNELD_FULL_CHANNEL_H +#include "config.h" +#include +#include +#include +#include + +struct channel_id; +struct existing_htlc; + +/** + * new_full_channel: Given initial fees and funding, what is initial state? + * @ctx: tal context to allocate return value from. + * @cid: The channel id. + * @funding: The commitment transaction id/output number. + * @minimum_depth: The minimum confirmations needed for funding transaction. + * @blockheight_states: The blockheight update states. + * @lease_expiry: The block the lease on this channel expires at; 0 if no lease. + * @funding_sats: The commitment transaction amount. + * @local_msat: The amount for the local side (remainder goes to remote) + * @fee_states: The fee update states. + * @local: local channel configuration + * @remote: remote channel configuration + * @local_basepoints: local basepoints. + * @remote_basepoints: remote basepoints. + * @local_fundingkey: local funding key + * @remote_fundingkey: remote funding key + * @type: type for this channel + * @option_wumbo: large channel negotiated. + * @opener: which side initiated it. + * + * Returns state, or NULL if malformed. + */ +struct channel *new_full_channel(const tal_t *ctx, + const struct channel_id *cid, + const struct bitcoin_outpoint *funding, + u32 minimum_depth, + const struct height_states *blockheight_states, + u32 lease_expiry, + struct amount_sat funding_sats, + struct amount_msat local_msat, + const struct fee_states *fee_states TAKES, + const struct channel_config *local, + const struct channel_config *remote, + const struct basepoints *local_basepoints, + const struct basepoints *remote_basepoints, + const struct pubkey *local_funding_pubkey, + const struct pubkey *remote_funding_pubkey, + const struct channel_type *type TAKES, + bool option_wumbo, + enum side opener); + +/** + * channel_txs: Get the current commitment and htlc txs for the channel. + * @ctx: tal context to allocate return value from. + * @channel: The channel to evaluate + * @htlc_map: Pointer to htlcs for each tx output (allocated off @ctx). + * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). + * @funding_wscript: Pointer to wscript for the funding tx output + * @per_commitment_point: Per-commitment point to determine keys + * @commitment_number: The index of this commitment. + * @side: which side to get the commitment transaction for + * + * Returns the unsigned commitment transaction for the committed state + * for @side, followed by the htlc transactions in output order and + * fills in @htlc_map, or NULL on key derivation failure. + */ +struct bitcoin_tx **channel_txs(const tal_t *ctx, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + const u8 **funding_wscript, + const struct channel *channel, + const struct pubkey *per_commitment_point, + u64 commitment_number, + enum side side); + +/** + * actual_feerate: what is the actual feerate for the local side. + * @channel: The channel state + * @theirsig: The other side's signature + * + * The fee calculated on a commitment transaction is a worst-case + * approximation. It's also possible that the desired feerate is not + * met, because the initiator sets it while the other side is adding many + * htlcs. + * + * This is the fee rate we actually care about, if we're going to check + * whether it's actually too low. + */ +u32 actual_feerate(const struct channel *channel, + const struct signature *theirsig); + +/** + * channel_add_htlc: append an HTLC to channel if it can afford it + * @channel: The channel + * @offerer: the side offering the HTLC (to the other side). + * @id: unique HTLC id. + * @amount: amount in millisatoshi. + * @cltv_expiry: block number when HTLC can no longer be redeemed. + * @payment_hash: hash whose preimage can redeem HTLC. + * @routing: routing information (copied) + * @blinding: optional blinding information for this HTLC. + * @htlcp: optional pointer for resulting htlc: filled in if and only if CHANNEL_ERR_NONE. + * @err_immediate_failures: in some cases (dusty htlcs) we want to immediately + * fail the htlc; for peer incoming don't want to + * error, but rather mark it as failed and fail after + * it's been committed to (so set this to false) + * + * If this returns CHANNEL_ERR_NONE, the fee htlc was added and + * the output amounts adjusted accordingly. Otherwise nothing + * is changed. + */ +enum channel_add_err channel_add_htlc(struct channel *channel, + enum side sender, + u64 id, + struct amount_msat msatoshi, + u32 cltv_expiry, + const struct sha256 *payment_hash, + const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)], + const struct pubkey *blinding TAKES, + struct htlc **htlcp, + struct amount_sat *htlc_fee, + bool err_immediate_failures); + +/** + * channel_get_htlc: find an HTLC + * @channel: The channel + * @offerer: the side offering the HTLC. + * @id: unique HTLC id. + */ +struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id); + +/** + * channel_fail_htlc: remove an HTLC, funds to the side which offered it. + * @channel: The channel state + * @owner: the side who offered the HTLC (opposite to that failing it) + * @id: unique HTLC id. + * @htlcp: optional pointer for failed htlc: filled in if and only if CHANNEL_ERR_REMOVE_OK. + * + * This will remove the htlc and credit the value of the HTLC (back) + * to its offerer. + */ +enum channel_remove_err channel_fail_htlc(struct channel *channel, + enum side owner, u64 id, + struct htlc **htlcp); + +/** + * channel_fulfill_htlc: remove an HTLC, funds to side which accepted it. + * @channel: The channel state + * @owner: the side who offered the HTLC (opposite to that fulfilling it) + * @id: unique HTLC id. + * @htlcp: optional pointer for resulting htlc: filled in if and only if CHANNEL_ERR_FULFILL_OK. + * + * If the htlc exists, is not already fulfilled, the preimage is correct and + * HTLC committed at the recipient, this will add a pending change to + * remove the htlc and give the value of the HTLC to its recipient, + * and return CHANNEL_ERR_FULFILL_OK. Otherwise, it will return another error. + */ +enum channel_remove_err channel_fulfill_htlc(struct channel *channel, + enum side owner, + u64 id, + const struct preimage *preimage, + struct htlc **htlcp); + +/** + * approx_max_feerate: what's the max opener could raise fee rate to? + * @channel: The channel state + * + * This is not exact! To check if their offer is valid, try + * channel_update_feerate. + */ +u32 approx_max_feerate(const struct channel *channel); + +/** + * can_opener_afford_feerate: could the opener pay the fee? + * @channel: The channel state + * @feerate: The feerate in satoshi per 1000 bytes. + */ +bool can_opener_afford_feerate(const struct channel *channel, u32 feerate); + +/** + * htlc_dust_ok: will this feerate keep our dusted htlc's beneath + * the updated feerate? + * + * @channel: The channel state + * @feerate_per_kw: new feerate to test ok'ness for + * @side: which side's htlcs to verify + */ +bool htlc_dust_ok(const struct channel *channel, + u32 feerate_per_kw, + enum side side); + +/** + * channel_update_feerate: Change fee rate on non-opener side. + * @channel: The channel + * @feerate_per_kw: fee in satoshi per 1000 bytes. + * + * Returns true if it's affordable, otherwise does nothing. + */ +bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw); + +/* + * channel_update_blockheight: Change blockheight on non-opener side. + * @channel: The channel + * @blockheight: current blockheight + */ +void channel_update_blockheight(struct channel *channel, u32 blockheight); + +/** + * channel_feerate: Get fee rate for this side of channel. + * @channel: The channel + * @side: the side + */ +u32 channel_feerate(const struct channel *channel, enum side side); + +/** + * channel_sending_commit: commit all remote outstanding changes. + * @channel: the channel + * @htlcs: initially-empty tal_arr() for htlcs which changed state. + * + * This is where we commit to pending changes we've added; returns true if + * anything changed for the remote side (if not, don't send!) */ +bool channel_sending_commit(struct channel *channel, + const struct htlc ***htlcs); + +/** + * channel_rcvd_revoke_and_ack: accept ack on remote committed changes. + * @channel: the channel + * @htlcs: initially-empty tal_arr() for htlcs which changed state. + * + * This is where we commit to pending changes we've added; returns true if + * anything changed for our local commitment (ie. we have pending changes). + */ +bool channel_rcvd_revoke_and_ack(struct channel *channel, + const struct htlc ***htlcs); + +/** + * channel_rcvd_commit: commit all local outstanding changes. + * @channel: the channel + * @htlcs: initially-empty tal_arr() for htlcs which changed state. + * + * This is where we commit to pending changes we've added; returns true if + * anything changed for our local commitment (ie. we had pending changes). + */ +bool channel_rcvd_commit(struct channel *channel, + const struct htlc ***htlcs); + +/** + * channel_sending_revoke_and_ack: sending ack on local committed changes. + * @channel: the channel + * + * This is where we commit to pending changes we've added. Returns true if + * anything changed for the remote commitment (ie. send a new commit).*/ +bool channel_sending_revoke_and_ack(struct channel *channel); + +/** + * num_channel_htlcs: how many (live) HTLCs at all in channel? + * @channel: the channel + */ +size_t num_channel_htlcs(const struct channel *channel); + +/** + * channel_force_htlcs: force these htlcs into the (new) channel + * @channel: the channel + * @htlcs: the htlcs to add (tal_arr) elements stolen. + * + * This is used for restoring a channel state. + */ +bool channel_force_htlcs(struct channel *channel, + const struct existing_htlc **htlcs); + +/** + * dump_htlcs: debugging dump of all HTLCs + * @channel: the channel + * @prefix: the prefix to prepend to each line. + * + * Uses status_debug() on every HTLC. + */ +void dump_htlcs(const struct channel *channel, const char *prefix); + +/** + * pending_updates: does this side have updates pending in channel? + * @channel: the channel + * @side: the side who is offering or failing/fulfilling HTLC, or feechange + * @uncommitted_ok: don't count uncommitted changes. + */ +bool pending_updates(const struct channel *channel, enum side side, + bool uncommitted_ok); + +const char *channel_add_err_name(enum channel_add_err e); +const char *channel_remove_err_name(enum channel_remove_err e); + +#endif /* LIGHTNING_CHANNELD_FULL_CHANNEL_H */ diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 9c73949decb1..db6a78690e56 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -548,6 +548,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: handle_local_private_channel(sd->channel, msg); break; + case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: + /* FIXME Handle this */ + break; #if EXPERIMENTAL_FEATURES case WIRE_CHANNELD_UPGRADED: handle_channel_upgrade(sd->channel, msg); From f52ef98f1ce4090750a381e06c1c20bd3f607bf4 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 12 Aug 2022 13:41:29 -0400 Subject: [PATCH 129/283] put nonces into keyset --- openingd/eltoo_openingd.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 265c501edc78..1846c01c436b 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -99,10 +99,6 @@ struct eltoo_state { struct channel_type *channel_type; struct feature_set *our_features; - - /* Nonces used for the next signing operation */ - struct nonce our_next_nonce; - struct nonce their_next_nonce; }; /*~ If we can't agree on parameters, we fail to open the channel. @@ -328,7 +324,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) peer_write(state->pps, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &state->our_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->channel->eltoo_keyset.self_next_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -347,7 +343,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->our_funding_pubkey, &state->our_settlement_pubkey, channel_flags, - &state->our_next_nonce, + &state->channel->eltoo_keyset.self_next_nonce, open_tlvs); peer_write(state->pps, take(msg)); @@ -377,7 +373,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->remoteconf.max_accepted_htlcs, &state->their_funding_pubkey, &state->their_settlement_pubkey, - &state->their_next_nonce, + &state->channel->eltoo_keyset.other_next_nonce, &accept_tlvs)) { peer_failed_err(state->pps, &state->channel_id, @@ -540,10 +536,10 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, *update_tx, settle_tx, &state->their_funding_pubkey, - &state->their_next_nonce); + &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -561,7 +557,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->funding.txid, state->funding.n, &our_update_psig, - &state->our_next_nonce); + &state->channel->eltoo_keyset.self_next_nonce); peer_write(state->pps, msg); /* BOLT #2: @@ -583,7 +579,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!msg) return false; - if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &state->their_next_nonce)) + if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &state->channel->eltoo_keyset.other_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); /* BOLT #2: @@ -730,7 +726,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->their_funding_pubkey, &state->their_settlement_pubkey, &channel_flags, - &state->their_next_nonce, + &state->channel->eltoo_keyset.other_next_nonce, &open_tlvs)) peer_failed_err(state->pps, &state->channel_id, @@ -850,7 +846,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) peer_write(state->pps, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &state->our_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->channel->eltoo_keyset.self_next_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -865,7 +861,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, &state->our_settlement_pubkey, - &state->our_next_nonce, + &state->channel->eltoo_keyset.self_next_nonce, accept_tlvs); peer_write(state->pps, take(msg)); @@ -883,7 +879,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->funding.txid, &funding_txout, &their_update_psig, - &state->their_next_nonce)) + &state->channel->eltoo_keyset.other_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); /* We only allow 16 bits for this on the wire. */ @@ -1000,10 +996,10 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) update_tx, settle_tx, &state->their_funding_pubkey, - &state->their_next_nonce); + &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->our_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -1024,7 +1020,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ - msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &state->our_next_nonce); + msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &state->channel->eltoo_keyset.self_next_nonce); return towire_openingd_eltoo_fundee(state, &state->remoteconf, From 5108aefd879fb7e5a8801d1557a9ee3bc5c1f1ae Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 12 Aug 2022 13:41:40 -0400 Subject: [PATCH 130/283] put nonces into keyset --- common/keyset.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/keyset.h b/common/keyset.h index 4bcfdc9c0744..651bec587214 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -19,6 +19,7 @@ struct eltoo_keyset { struct pubkey self_funding_key, other_funding_key; /* MuSig2 key using funding keys as input */ struct pubkey inner_pubkey; + struct nonce self_next_nonce, other_next_nonce; }; /* Self == owner of commitment tx, other == non-owner. */ From 96f03097b8a299a94279204d5390b1c512e2f7fb Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 15 Aug 2022 11:48:46 -0400 Subject: [PATCH 131/283] Stuff compiling, reworked musig session flow --- bitcoin/signature.c | 17 +- bitcoin/signature.h | 9 + channeld/channeld.c | 1 + channeld/channeld_wire.csv | 6 + channeld/eltoo_channeld.c | 576 ++++++---------------------------- channeld/eltoo_full_channel.c | 538 ++++--------------------------- common/keyset.h | 5 +- hsmd/hsmd_wire.csv | 2 + hsmd/libhsmd.c | 10 +- lightningd/channel_control.c | 3 + openingd/eltoo_openingd.c | 6 +- 11 files changed, 200 insertions(+), 973 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 5073c245cf19..9aecf19073a3 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -691,7 +691,9 @@ void fromwire_bip340sig(const u8 **cursor, size_t *max, void towire_partial_sig(u8 **pptr, const struct partial_sig *p_sig) { - secp256k1_musig_partial_sig_serialize(secp256k1_ctx, *pptr, &p_sig->p_sig); + u8 bip340sig_arr[32]; + secp256k1_musig_partial_sig_serialize(secp256k1_ctx, bip340sig_arr, &p_sig->p_sig); + towire_u8_array(pptr, bip340sig_arr, sizeof(bip340sig_arr)); } void fromwire_partial_sig(const u8 **cursor, size_t *max, @@ -709,6 +711,19 @@ void fromwire_partial_sig(const u8 **cursor, size_t *max, } } +void towire_musig_session(u8 **pptr, const struct musig_session *session) +{ + /* No proper serialization/parsing supplied, we're just copying bytes */ + towire_u8_array(pptr, session->session.data, 133); +} + +void fromwire_musig_session(const u8 **cursor, size_t *max, + struct musig_session *session){ + /* No proper serialization/parsing supplied, we're just copying bytes */ + if (!fromwire(cursor, max, session->session.data, 133)) + return; +} + char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig) { return tal_hexstr(ctx, bip340sig->u8, sizeof(bip340sig->u8)); diff --git a/bitcoin/signature.h b/bitcoin/signature.h index cb471b357017..86842a65c714 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -33,6 +33,11 @@ struct partial_sig { secp256k1_musig_partial_sig p_sig; }; +/* State required(along with pubkey) to bring partial_sig's together */ +struct musig_session { + secp256k1_musig_session session; +}; + #define SIGHASH_MASK 0x7F static inline bool sighash_single(enum sighash_type sighash_type) @@ -313,6 +318,10 @@ void towire_partial_sig(u8 **pptr, const struct partial_sig *p_sig); void fromwire_partial_sig(const u8 **cursor, size_t *max, struct partial_sig *p_sig); +void towire_musig_session(u8 **pptr, const struct musig_session *session); +void fromwire_musig_session(const u8 **cursor, size_t *max, + struct musig_session *session); + /* Get a hex string sig */ char *fmt_signature(const tal_t *ctx, const secp256k1_ecdsa_signature *sig); char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig); diff --git a/channeld/channeld.c b/channeld/channeld.c index e5996829d725..336e023dcb46 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3739,6 +3739,7 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_LOCAL_CHANNEL_ANNOUNCEMENT: case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: + case WIRE_CHANNELD_GOT_UPDATESIG: break; } master_badmsg(-1, msg); diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index b781c10d1ac1..8a92f31b3524 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -280,3 +280,9 @@ msgdata,channeld_blockheight,blockheight,u32, # When we receive funding_locked. msgtype,channeld_got_funding_locked_eltoo,1079 + +# When we have a update_signed message, tell master to remember. +msgtype,channeld_got_updatesig,1081 +msgdata,channeld_got_updatesig,update_num,u32, +msgdata,channeld_got_updatesig,update_sig,bip340sig, + diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 0a75cd0645a5..8d762b317c93 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -15,9 +15,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include @@ -50,7 +50,7 @@ #define MASTER_FD STDIN_FILENO #define HSM_FD 4 -struct peer { +struct eltoo_peer { struct per_peer_state *pps; bool funding_locked[NUM_SIDES]; u64 next_index[NUM_SIDES]; @@ -64,22 +64,6 @@ struct peer { /* Tolerable amounts for feerate (only relevant for fundee). */ u32 feerate_min, feerate_max; - /* Feerate to be used when creating penalty transactions. */ - u32 feerate_penalty; - - /* Local next per-commit point. */ - struct pubkey next_local_per_commit; - - /* Remote's current per-commit point. */ - struct pubkey remote_per_commit; - - /* Remotes's last per-commitment point: we keep this to check - * revoke_and_ack's `per_commitment_secret` is correct. */ - struct pubkey old_remote_per_commit; - - /* Their sig for current commit. */ - struct bitcoin_signature their_commit_sig; - /* BOLT #2: * * A sending node: @@ -90,7 +74,7 @@ struct peer { u64 htlc_id; struct channel_id channel_id; - struct channel *channel; + struct eltoo_channel *channel; /* Messages from master: we queue them since we might be * waiting for a specific reply. */ @@ -101,12 +85,6 @@ struct peer { u64 commit_timer_attempts; u32 commit_msec; - /* The feerate we want. */ - u32 desired_feerate; - - /* Current blockheight */ - u32 our_blockheight; - /* Announcement related information */ struct node_id node_ids[NUM_SIDES]; struct short_channel_id short_channel_ids[NUM_SIDES]; @@ -159,10 +137,12 @@ struct peer { bool dev_fast_gossip; #endif /* Information used for reestablishment. */ + /* FIXME figure out what goes here bool last_was_revoke; struct changed_htlc *last_sent_commit; u64 revocations_received; u8 channel_flags; + */ bool announce_depth_reached; bool channel_local_active; @@ -179,9 +159,6 @@ struct peer { /* Empty commitments. Spec violation, but a minor one. */ u64 last_empty_commitment; - /* Penalty bases for this channel / peer. */ - struct penalty_base **pbases; - /* We allow a 'tx-sigs' message between reconnect + funding_locked */ bool tx_sigs_allowed; @@ -584,7 +561,7 @@ static void channel_announcement_negotiate(struct peer *peer) } } -static void handle_peer_funding_locked_eltoo(struct peer *peer, const u8 *msg) +static void handle_peer_funding_locked_eltoo(struct eltoo_peer *peer, const u8 *msg) { struct channel_id chanid; @@ -602,11 +579,9 @@ static void handle_peer_funding_locked_eltoo(struct peer *peer, const u8 *msg) if (peer->shutdown_sent[LOCAL]) return; - peer->old_remote_per_commit = peer->remote_per_commit; - if (!fromwire_funding_locked(msg, &chanid, - &peer->remote_per_commit)) + if (!fromwire_funding_locked_eltoo(msg, &chanid)) peer_failed_warn(peer->pps, &peer->channel_id, - "Bad funding_locked %s", tal_hex(msg, msg)); + "Bad funding_locked_eltoo %s", tal_hex(msg, msg)); if (!channel_id_eq(&chanid, &peer->channel_id)) peer_failed_err(peer->pps, &chanid, @@ -618,14 +593,13 @@ static void handle_peer_funding_locked_eltoo(struct peer *peer, const u8 *msg) peer->tx_sigs_allowed = false; peer->funding_locked[REMOTE] = true; wire_sync_write(MASTER_FD, - take(towire_channeld_got_funding_locked_eltoo(NULL, - &peer->remote_per_commit))); + take(towire_channeld_got_funding_locked_eltoo(NULL))); channel_announcement_negotiate(peer); billboard_update(peer); } -static void handle_peer_announcement_signatures(struct peer *peer, const u8 *msg) +static void handle_peer_announcement_signatures(struct eltoo_peer *peer, const u8 *msg) { struct channel_id chanid; @@ -653,7 +627,7 @@ static void handle_peer_announcement_signatures(struct peer *peer, const u8 *msg channel_announcement_negotiate(peer); } -static void handle_peer_add_htlc(struct peer *peer, const u8 *msg) +static void handle_peer_add_htlc(struct eltoo_peer *peer, const u8 *msg) { struct channel_id channel_id; u64 id; @@ -687,88 +661,22 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg) #endif add_err = channel_add_htlc(peer->channel, REMOTE, id, amount, cltv_expiry, &payment_hash, - onion_routing_packet, blinding, &htlc, NULL, - /* We don't immediately fail incoming htlcs, - * instead we wait and fail them after - * they've been committed */ - false); + onion_routing_packet, blinding, &htlc, + /* err_immediate_failures */ false); if (add_err != CHANNEL_ERR_ADD_OK) peer_failed_warn(peer->pps, &peer->channel_id, "Bad peer_add_htlc: %s", channel_add_err_name(add_err)); } -/* We don't get upset if they're outside the range, as long as they're - * improving (or at least, not getting worse!). */ -static bool feerate_same_or_better(const struct channel *channel, - u32 feerate, u32 feerate_min, u32 feerate_max) -{ - u32 current = channel_feerate(channel, LOCAL); - - /* Too low? But is it going upwards? */ - if (feerate < feerate_min) - return feerate >= current; - if (feerate > feerate_max) - return feerate <= current; - return true; -} - static void handle_peer_feechange(struct peer *peer, const u8 *msg) { struct channel_id channel_id; u32 feerate; - if (!fromwire_update_fee(msg, &channel_id, &feerate)) { - peer_failed_warn(peer->pps, &peer->channel_id, - "Bad update_fee %s", tal_hex(msg, msg)); - } - - /* BOLT #2: - * - * A receiving node: - *... - * - if the sender is not responsible for paying the Bitcoin fee: - * - MUST send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ - if (peer->channel->opener != REMOTE) - peer_failed_warn(peer->pps, &peer->channel_id, - "update_fee from non-opener?"); - - status_debug("update_fee %u, range %u-%u", - feerate, peer->feerate_min, peer->feerate_max); - - /* BOLT #2: - * - * A receiving node: - * - if the `update_fee` is too low for timely processing, OR is - * unreasonably large: - * - MUST send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ - if (!feerate_same_or_better(peer->channel, feerate, - peer->feerate_min, peer->feerate_max)) - peer_failed_warn(peer->pps, &peer->channel_id, - "update_fee %u outside range %u-%u" - " (currently %u)", - feerate, - peer->feerate_min, peer->feerate_max, - channel_feerate(peer->channel, LOCAL)); - - /* BOLT #2: - * - * - if the sender cannot afford the new fee rate on the receiving - * node's current commitment transaction: - * - SHOULD send a `warning` and close the connection, or send an - * `error` and fail the channel. - * - but MAY delay this check until the `update_fee` is committed. - */ - if (!channel_update_feerate(peer->channel, feerate)) - peer_failed_warn(peer->pps, &peer->channel_id, - "update_fee %u unaffordable", - feerate); - - status_debug("peer updated fee to %u", feerate); + fromwire_update_fee(msg, &channel_id, &feerate); + peer_failed_warn(peer->pps, &peer->channel_id, + "update_fee isn't allowed in eltoo %s", tal_hex(msg, msg)); } static void handle_peer_blockheight_change(struct peer *peer, const u8 *msg) @@ -1092,103 +1000,6 @@ static secp256k1_ecdsa_signature *raw_sigs(const tal_t *ctx, return raw; } -static struct bitcoin_signature *unraw_sigs(const tal_t *ctx, - const secp256k1_ecdsa_signature *raw, - bool option_anchor_outputs) -{ - struct bitcoin_signature *sigs; - - sigs = tal_arr(ctx, struct bitcoin_signature, tal_count(raw)); - for (size_t i = 0; i < tal_count(raw); i++) { - sigs[i].s = raw[i]; - - /* BOLT #3: - * ## HTLC-Timeout and HTLC-Success Transactions - *... - * * if `option_anchors` applies to this commitment - * transaction, `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is - * used as described in [BOLT #5] - */ - if (option_anchor_outputs) - sigs[i].sighash_type = SIGHASH_SINGLE|SIGHASH_ANYONECANPAY; - else - sigs[i].sighash_type = SIGHASH_ALL; - } - return sigs; -} - -/* Do we want to update fees? */ -static bool want_fee_update(const struct peer *peer, u32 *target) -{ - u32 current, val; - - if (peer->channel->opener != LOCAL) - return false; - -#if EXPERIMENTAL_FEATURES - /* No fee update while quiescing! */ - if (peer->stfu) - return false; -#endif - current = channel_feerate(peer->channel, REMOTE); - - /* max is *approximate*: only take it into account if we're - * trying to increase feerate. */ - if (peer->desired_feerate > current) { - /* FIXME: We should avoid adding HTLCs until we can meet this - * feerate! */ - u32 max = approx_max_feerate(peer->channel); - - val = peer->desired_feerate; - /* Respect max, but don't let us *decrease* us */ - if (val > max) - val = max; - if (val < current) - val = current; - } else - val = peer->desired_feerate; - - if (target) - *target = val; - - return val != current; -} - -/* Do we want to update blockheight? */ -static bool want_blockheight_update(const struct peer *peer, u32 *height) -{ - u32 last; - - if (peer->channel->opener != LOCAL) - return false; - - if (peer->channel->lease_expiry == 0) - return false; - -#if EXPERIMENTAL_FEATURES - /* No fee update while quiescing! */ - if (peer->stfu) - return false; -#endif - /* What's the current blockheight */ - last = get_blockheight(peer->channel->blockheight_states, - peer->channel->opener, LOCAL); - - if (peer->our_blockheight < last) { - status_broken("current blockheight %u less than last %u", - peer->our_blockheight, last); - return false; - } - - if (peer->our_blockheight == last) - return false; - - if (height) - *height = peer->our_blockheight; - - return true; -} - static void send_commit(struct peer *peer) { u8 *msg; @@ -1239,64 +1050,6 @@ static void send_commit(struct peer *peer) return; } - /* If we wanted to update fees, do it now. */ - if (want_fee_update(peer, &feerate_target)) { - /* FIXME: We occasionally desynchronize with LND here, so - * don't stress things by having more than one feerate change - * in-flight! */ - if (feerate_changes_done(peer->channel->fee_states, false)) { - u8 *msg; - - /* BOLT-919 #2: - * - * A sending node: - * - if the `dust_balance_on_counterparty_tx` at the - * new `dust_buffer_feerate` is superior to - * `max_dust_htlc_exposure_msat`: - * - MAY NOT send `update_fee` - * - MAY fail the channel - * - if the `dust_balance_on_holder_tx` at the - * new `dust_buffer_feerate` is superior to - * the `max_dust_htlc_exposure_msat`: - * - MAY NOT send `update_fee` - * - MAY fail the channel - */ - /* Is this feerate update going to push the committed - * htlcs over our allowed dust limits? */ - if (!htlc_dust_ok(peer->channel, feerate_target, REMOTE) - || !htlc_dust_ok(peer->channel, feerate_target, LOCAL)) - peer_failed_warn(peer->pps, &peer->channel_id, - "Too much dust to update fee (Desired" - " feerate update %d)", feerate_target); - - if (!channel_update_feerate(peer->channel, feerate_target)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Could not afford feerate %u" - " (vs max %u)", - feerate_target, approx_max_feerate(peer->channel)); - - msg = towire_update_fee(NULL, &peer->channel_id, - feerate_target); - peer_write(peer->pps, take(msg)); - } - } - - if (want_blockheight_update(peer, &our_blockheight)) { - if (blockheight_changes_done(peer->channel->blockheight_states, - false)) { - u8 *msg; - - channel_update_blockheight(peer->channel, - our_blockheight); - - msg = towire_update_blockheight(NULL, - &peer->channel_id, - our_blockheight); - - peer_write(peer->pps, take(msg)); - } - } - /* BOLT #2: * * A sending node: @@ -1305,13 +1058,7 @@ static void send_commit(struct peer *peer) */ changed_htlcs = tal_arr(tmpctx, const struct htlc *, 0); if (!channel_sending_commit(peer->channel, &changed_htlcs)) { - status_debug("Can't send commit: nothing to send," - " feechange %s (%s)" - " blockheight %s (%s)", - want_fee_update(peer, NULL) ? "wanted": "not wanted", - type_to_string(tmpctx, struct fee_states, peer->channel->fee_states), - want_blockheight_update(peer, NULL) ? "wanted" : "not wanted", - type_to_string(tmpctx, struct height_states, peer->channel->blockheight_states)); + status_debug("Can't send commit: nothing to send"); /* Covers the case where we've just been told to shutdown. */ maybe_send_shutdown(peer); @@ -1388,54 +1135,9 @@ static void start_commit_timer(struct peer *peer) send_commit, peer); } -/* If old_secret is NULL, we don't care, otherwise it is filled in. */ -static void get_per_commitment_point(u64 index, struct pubkey *point, - struct secret *old_secret) +static u8 *make_update_signed_ack_msg(const struct peer *peer, struct partial_sig *our_update_psig) { - struct secret *s; - const u8 *msg; - - msg = hsm_req(tmpctx, - take(towire_hsmd_get_per_commitment_point(NULL, index))); - - if (!fromwire_hsmd_get_per_commitment_point_reply(tmpctx, msg, - point, - &s)) - status_failed(STATUS_FAIL_HSM_IO, - "Bad per_commitment_point reply %s", - tal_hex(tmpctx, msg)); - - if (old_secret) { - if (!s) - status_failed(STATUS_FAIL_HSM_IO, - "No secret in per_commitment_point_reply %" - PRIu64, - index); - *old_secret = *s; - } -} - -/* revoke_index == current index - 1 (usually; not for retransmission) */ -static u8 *make_revocation_msg(const struct peer *peer, u64 revoke_index, - struct pubkey *point) -{ - struct secret old_commit_secret; - - get_per_commitment_point(revoke_index+2, point, &old_commit_secret); - - return towire_revoke_and_ack(peer, &peer->channel_id, &old_commit_secret, - point); -} - -static u8 *make_revocation_msg_from_secret(const struct peer *peer, - u64 revoke_index, - struct pubkey *point, - const struct secret *old_commit_secret, - const struct pubkey *next_point) -{ - *point = *next_point; - return towire_revoke_and_ack(peer, &peer->channel_id, - old_commit_secret, next_point); + return towire_update_signed_ack(peer, &peer->channel_id, our_update_psig, &peer->channel->eltoo_keyset.next_nonce); } /* Convert changed htlcs into parts which lightningd expects. */ @@ -1493,13 +1195,11 @@ static void marshall_htlc_info(const tal_t *ctx, } } -static void send_revocation(struct peer *peer, - const struct bitcoin_signature *commit_sig, - const struct bitcoin_signature *htlc_sigs, - const struct htlc **changed_htlcs, - const struct bitcoin_tx *committx, - const struct secret *old_secret, - const struct pubkey *next_point) +static void send_update_sign_ack(struct peer *peer, + const struct partial_sig *our_update_psig, + const struct bip340sit *update_sig, + const struct bitcoin_tx *update_tx, + const struct nonce *our_next_nonce) { struct changed_htlc *changed; struct fulfilled_htlc *fulfilled; @@ -1517,30 +1217,26 @@ static void send_revocation(struct peer *peer, &failed, &added); - /* Revoke previous commit, get new point. */ - msg = make_revocation_msg_from_secret(peer, peer->next_index[LOCAL]-1, - &peer->next_local_per_commit, - old_secret, next_point); + msg = make_update_signed_ack_msg(peer, &our_update_psig); /* From now on we apply changes to the next commitment */ peer->next_index[LOCAL]++; /* If this queues more changes on the other end, send commit. */ + /* FIXME I don't think this can happen with eltoo/turn taking? if (channel_sending_revoke_and_ack(peer->channel)) { status_debug("revoke_and_ack made pending: commit timer"); start_commit_timer(peer); - } + } */ - /* Tell master daemon about commitsig (and by implication, that we're + /* Tell master daemon about update_sig (and by implication, that we're * sending revoke_and_ack), then wait for it to ack. */ /* We had to do this after channel_sending_revoke_and_ack, since we * want it to save the fee_states produced there. */ msg_for_master - = towire_channeld_got_commitsig(NULL, + = towire_channeld_got_updatesig(NULL, peer->next_index[LOCAL] - 1, - peer->channel->fee_states, - peer->channel->blockheight_states, - commit_sig, htlc_sigs, + update_sig, htlc_sigs, added, fulfilled, failed, @@ -1553,14 +1249,20 @@ static void send_revocation(struct peer *peer, peer_write(peer->pps, take(msg)); } -static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) +static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) { struct channel_id channel_id; + + /* struct bitcoin_signature commit_sig; secp256k1_ecdsa_signature *raw_sigs; struct bitcoin_signature *htlc_sigs; struct pubkey remote_htlckey; - struct bitcoin_tx **txs; + */ + struct bitcoin_tx **update_and_settle_txs; + struct partial_sig their_update_psig, our_update_psig; + struct bip340sig update_sig; + struct nonce next_nonce; const struct htlc **htlc_map, **changed_htlcs; const u8 *funding_wscript; size_t i; @@ -1579,162 +1281,61 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) peer->next_index[LOCAL]); if (peer->last_empty_commitment == peer->next_index[LOCAL] - 1) peer_failed_warn(peer->pps, &peer->channel_id, - "commit_sig with no changes (again!)"); + "update_signed with no changes (again!)"); peer->last_empty_commitment = peer->next_index[LOCAL]; } - /* We were supposed to check this was affordable as we go. */ - if (peer->channel->opener == REMOTE) { - status_debug("Feerates are %u/%u", - channel_feerate(peer->channel, LOCAL), - channel_feerate(peer->channel, REMOTE)); - assert(can_opener_afford_feerate(peer->channel, - channel_feerate(peer->channel, - LOCAL))); - } - - if (!fromwire_commitment_signed(tmpctx, msg, - &channel_id, &commit_sig.s, &raw_sigs)) + if (!fromwire_update_signed(tmpctx, msg, + &channel_id, &their_update_psig, &next_nonce)) peer_failed_warn(peer->pps, &peer->channel_id, - "Bad commit_sig %s", tal_hex(msg, msg)); - /* SIGHASH_ALL is implied. */ - commit_sig.sighash_type = SIGHASH_ALL; - htlc_sigs = unraw_sigs(tmpctx, raw_sigs, - channel_has(peer->channel, OPT_ANCHOR_OUTPUTS)); - - txs = - channel_txs(tmpctx, &htlc_map, NULL, - &funding_wscript, peer->channel, &peer->next_local_per_commit, - peer->next_index[LOCAL], LOCAL); + "Bad update_signed %s", tal_hex(msg, msg)); - /* Set the commit_sig on the commitment tx psbt */ - if (!psbt_input_set_signature(txs[0]->psbt, 0, - &peer->channel->funding_pubkey[REMOTE], - &commit_sig)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Unable to set signature internally"); + status_debug("Received update_sig"); - if (!derive_simple_key(&peer->channel->basepoints[REMOTE].htlc, - &peer->next_local_per_commit, &remote_htlckey)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Deriving remote_htlckey"); - status_debug("Derived key %s from basepoint %s, point %s", - type_to_string(tmpctx, struct pubkey, &remote_htlckey), - type_to_string(tmpctx, struct pubkey, - &peer->channel->basepoints[REMOTE].htlc), - type_to_string(tmpctx, struct pubkey, - &peer->next_local_per_commit)); - /* BOLT #2: - * - * A receiving node: - * - once all pending updates are applied: - * - if `signature` is not valid for its local commitment transaction - * OR non-compliant with LOW-S-standard rule...: - * - MUST send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ - if (!check_tx_sig(txs[0], 0, NULL, funding_wscript, - &peer->channel->funding_pubkey[REMOTE], &commit_sig)) { - dump_htlcs(peer->channel, "receiving commit_sig"); - peer_failed_warn(peer->pps, &peer->channel_id, - "Bad commit_sig signature %"PRIu64" %s for tx %s wscript %s key %s feerate %u", - peer->next_index[LOCAL], - type_to_string(msg, struct bitcoin_signature, - &commit_sig), - type_to_string(msg, struct bitcoin_tx, txs[0]), - tal_hex(msg, funding_wscript), - type_to_string(msg, struct pubkey, - &peer->channel->funding_pubkey - [REMOTE]), - channel_feerate(peer->channel, LOCAL)); - } - - /* BOLT #2: - * - * A receiving node: - *... - * - if `num_htlcs` is not equal to the number of HTLC outputs in the - * local commitment transaction: - * - MUST send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ - if (tal_count(htlc_sigs) != tal_count(txs) - 1) - peer_failed_warn(peer->pps, &peer->channel_id, - "Expected %zu htlc sigs, not %zu", - tal_count(txs) - 1, tal_count(htlc_sigs)); - - /* BOLT #2: - * - * - if any `htlc_signature` is not valid for the corresponding HTLC - * transaction OR non-compliant with LOW-S-standard rule...: - * - MUST send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ - for (i = 0; i < tal_count(htlc_sigs); i++) { - u8 *wscript; - - wscript = bitcoin_tx_output_get_witscript(tmpctx, txs[0], - txs[i+1]->wtx->inputs[0].index); - - if (!check_tx_sig(txs[1+i], 0, NULL, wscript, - &remote_htlckey, &htlc_sigs[i])) - peer_failed_warn(peer->pps, &peer->channel_id, - "Bad commit_sig signature %s for htlc %s wscript %s key %s", - type_to_string(msg, struct bitcoin_signature, &htlc_sigs[i]), - type_to_string(msg, struct bitcoin_tx, txs[1+i]), - tal_hex(msg, wscript), - type_to_string(msg, struct pubkey, - &remote_htlckey)); - } - - status_debug("Received commit_sig with %zu htlc sigs", - tal_count(htlc_sigs)); - - /* Validate the counterparty's signatures, returns prior per_commitment_secret. */ - htlcs = collect_htlcs(NULL, htlc_map); - msg2 = towire_hsmd_validate_commitment_tx(NULL, - txs[0], - (const struct simple_htlc **) htlcs, - peer->next_index[LOCAL], - channel_feerate(peer->channel, LOCAL), - &commit_sig, - htlc_sigs); - tal_free(htlcs); - msg2 = hsm_req(tmpctx, take(msg2)); - struct secret *old_secret; - struct pubkey next_point; - if (!fromwire_hsmd_validate_commitment_tx_reply(tmpctx, msg2, &old_secret, &next_point)) - status_failed(STATUS_FAIL_HSM_IO, - "Reading validate_commitment_tx reply: %s", - tal_hex(tmpctx, msg2)); + update_and_settle_txs = + eltoo_channel_txs(tmpctx, &htlc_map, /* direct_outputs */ NULL, + peer->channel, + peer->next_index[LOCAL], LOCAL); - send_revocation(peer, &commit_sig, htlc_sigs, changed_htlcs, txs[0], - old_secret, &next_point); + /* FIXME we need to finish the MuSig sig/verification, and send ACK ... */ + + /* We sign the same update transaction as peer should have signed */ + msg = towire_hsmd_psign_update_tx(NULL, + &peer->channel_id, + update_and_settle_txs[0], + update_and_settle_txs[1], + &peer->channel->eltoo_keyset.other_funding_key, + &peer->channel->eltoo_keyset.other_next_nonce); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &peer->channel->eltoo_keyset.self_next_nonce)) + status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", + tal_hex(tmpctx, msg)); + + /* Before replying, make sure signature is correct */ + msg = towire_hsmd_combine_psig(NULL, + &peer->channel_id, + &our_update_psig, + &their_update_psig, + update_and_settle_txs[0], + update_and_settle_txs[1], + &peer->channel->eltoo_keyset.inner_pubkey); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { + status_failed(STATUS_FAIL_HSM_IO, + "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); + } + + send_update_sign_ack(peer, + &our_update_psig, + changed_htlcs, + txs[0], + &peer->channel->eltoo_keyset.self_next_nonce); /* We may now be quiescent on our side. */ maybe_send_stfu(peer); - /* This might have synced the feerates: if so, we may want to - * update */ - if (want_fee_update(peer, NULL)) - start_commit_timer(peer); -} - -/* Pops the penalty base for the given commitnum from our internal list. There - * may not be one, in which case we return NULL and leave the list - * unmodified. */ -static struct penalty_base * -penalty_base_by_commitnum(const tal_t *ctx, struct peer *peer, u64 commitnum) -{ - struct penalty_base *res = NULL; - for (size_t i = 0; i < tal_count(peer->pbases); i++) { - if (peer->pbases[i]->commitment_num == commitnum) { - res = tal_steal(ctx, peer->pbases[i]); - tal_arr_remove(&peer->pbases, i); - break; - } - } - return res; } static u8 *got_revoke_msg(struct peer *peer, u64 revoke_num, @@ -2184,7 +1785,7 @@ static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) &channel_id)); } -static void peer_in(struct peer *peer, const u8 *msg) +static void peer_in(struct peer *elto_peer, const u8 *msg) { enum peer_wire type = fromwire_peektype(msg); @@ -2211,17 +1812,22 @@ static void peer_in(struct peer *peer, const u8 *msg) handle_peer_funding_locked_eltoo(peer, msg); return; case WIRE_ANNOUNCEMENT_SIGNATURES: + /* untouched */ handle_peer_announcement_signatures(peer, msg); return; case WIRE_UPDATE_ADD_HTLC: handle_peer_add_htlc(peer, msg); return; - case WIRE_COMMITMENT_SIGNED: - handle_peer_commit_sig(peer, msg); + case WIRE_COMMITMENT_SIGNED: + /* FIXME How should we handle ilegal messages in general? */ return; case WIRE_UPDATE_FEE: handle_peer_feechange(peer, msg); return; + /* FIXME below */ + case WIRE_UPDATE_SIGNED: + handle_peer_update_sig(peer, msg); + return; case WIRE_UPDATE_BLOCKHEIGHT: handle_peer_blockheight_change(peer, msg); return; diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 05448eb25b2c..6b7f2e0177ce 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -79,39 +79,33 @@ static bool balance_ok(const struct balance *balance, return true; } -struct channel *new_full_channel(const tal_t *ctx, +struct eltoo_channel *new_full_eltoo_channel(const tal_t *ctx, const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, - const struct height_states *blockheight_states, - u32 lease_expiry, struct amount_sat funding_sats, struct amount_msat local_msat, - const struct fee_states *fee_states TAKES, const struct channel_config *local, const struct channel_config *remote, - const struct basepoints *local_basepoints, - const struct basepoints *remote_basepoints, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, + const struct pubkey *local_settle_pubkey, + const struct pubkey *remote_settle_pubkey, const struct channel_type *type TAKES, bool option_wumbo, enum side opener) { - struct channel *channel = new_initial_channel(ctx, + struct eltoo_channel *channel = new_initial_eltoo_channel(ctx, cid, funding, minimum_depth, - blockheight_states, - lease_expiry, funding_sats, local_msat, - fee_states, local, remote, - local_basepoints, - remote_basepoints, local_funding_pubkey, remote_funding_pubkey, + local_settle_pubkey, + remote_settle_pubkey, type, option_wumbo, opener); @@ -290,104 +284,51 @@ static void add_htlcs(struct bitcoin_tx ***txs, } } -/* FIXME: We could cache these. */ -struct bitcoin_tx **channel_txs(const tal_t *ctx, - const struct htlc ***htlcmap, - struct wally_tx_output *direct_outputs[NUM_SIDES], - const u8 **funding_wscript, - const struct channel *channel, - const struct pubkey *per_commitment_point, - u64 commitment_number, - enum side side) -{ - struct bitcoin_tx **txs; - const struct htlc **committed; - struct keyset keyset; - - if (!derive_keyset(per_commitment_point, - &channel->basepoints[side], - &channel->basepoints[!side], - channel_has(channel, OPT_STATIC_REMOTEKEY), - &keyset)) - return NULL; - - /* Figure out what @side will already be committed to. */ - gather_htlcs(ctx, channel, side, &committed, NULL, NULL); - - /* Generating and saving witness script required to spend - * the funding output */ - *funding_wscript = bitcoin_redeem_2of2(ctx, - &channel->funding_pubkey[side], - &channel->funding_pubkey[!side]); - - txs = tal_arr(ctx, struct bitcoin_tx *, 1); - txs[0] = commit_tx( - ctx, &channel->funding, - channel->funding_sats, - &channel->funding_pubkey[side], - &channel->funding_pubkey[!side], - channel->opener, - channel->config[!side].to_self_delay, - channel->lease_expiry, - channel_blockheight(channel, side), - &keyset, channel_feerate(channel, side), - channel->config[side].dust_limit, channel->view[side].owed[side], - channel->view[side].owed[!side], committed, htlcmap, direct_outputs, - commitment_number ^ channel->commitment_number_obscurer, - channel_has(channel, OPT_ANCHOR_OUTPUTS), - side); - - /* Set the remote/local pubkeys on the commitment tx psbt */ - psbt_input_add_pubkey(txs[0]->psbt, 0, - &channel->funding_pubkey[side]); - psbt_input_add_pubkey(txs[0]->psbt, 0, - &channel->funding_pubkey[!side]); - - add_htlcs(&txs, *htlcmap, channel, &keyset, side); - - tal_free(committed); - return txs; -} - -/* If @side is faced with these HTLCs, how much will it have left - * above reserve (eg. to pay fees). Returns false if would be < 0. */ -static bool get_room_above_reserve(const struct channel *channel, - const struct channel_view *view, - const struct htlc **adding, - const struct htlc **removing, - enum side side, - struct amount_msat *remainder) +struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + const struct eltoo_channel *channel, + u64 update_number, + enum side side) { - /* Reserve is set by the *other* side */ - struct amount_sat reserve = channel->config[!side].channel_reserve; - struct balance balance; - - to_balance(&balance, view->owed[side]); - - for (size_t i = 0; i < tal_count(removing); i++) - balance_remove_htlc(&balance, removing[i], side); - - for (size_t i = 0; i < tal_count(adding); i++) - balance_add_htlc(&balance, adding[i], side); - - /* Can happen if amount completely exceeds capacity */ - if (!balance_ok(&balance, remainder)) { - status_debug("Failed to add %zu remove %zu htlcs", - tal_count(adding), tal_count(removing)); - return false; - } - - if (!amount_msat_sub_sat(remainder, *remainder, reserve)) { - status_debug("%s cannot afford htlc: would make balance %s" - " below reserve %s", - side_to_str(side), - type_to_string(tmpctx, struct amount_msat, - remainder), - type_to_string(tmpctx, struct amount_sat, - &reserve)); - return false; - } - return true; + struct bitcoin_tx **txs; + const struct htlc **committed; + char** err_reason; + + /* Figure out what @side will already be committed to. */ + gather_htlcs(ctx, channel, side, &committed, NULL, NULL); + + txs = tal_arr(ctx, struct bitcoin_tx *, 2); + /* settle txn has finalized witness data, just needs prevout rebinding */ + txs[1] = settle_tx( + ctx, &channel->funding, + channel->funding_sats, + channel->config[side].shared_delay, + &channel->eltoo_keyset, + channel->config[side].dust_limit, channel->view[side].owed[side], + channel->view[side].owed[!side], committed, htlcmap, direct_outputs, + update_number); + + /* We only fill out witness data for update transactions for onchain events */ + txs[0] = unbound_update_tx(ctx, + txs[0], + channel->funding_sats, + &channel->eltoo_keyset.inner_pubkey, + err_reason); + + /* FIXME We don't handle failure to construct transactions yet */ + assert(txs[0]); + assert(txs[1]); + + /* Set the remote/local pubkeys on the update tx psbt FIXME add + inner pubkey when possible */ + psbt_input_add_pubkey(txs[0]->psbt, 0, + &channel->funding_pubkey[side]); + psbt_input_add_pubkey(txs[0]->psbt, 0, + &channel->funding_pubkey[!side]); + + tal_free(committed); + return txs; } static size_t num_untrimmed_htlcs(enum side side, @@ -406,116 +347,7 @@ static size_t num_untrimmed_htlcs(enum side side, option_static_remotekey, side); } -static struct amount_sat fee_for_htlcs(const struct channel *channel, - const struct htlc **committed, - const struct htlc **adding, - const struct htlc **removing, - enum side side) -{ - u32 feerate = channel_feerate(channel, side); - struct amount_sat dust_limit = channel->config[side].dust_limit; - size_t untrimmed; - bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); - - untrimmed = num_untrimmed_htlcs(side, dust_limit, feerate, - option_anchor_outputs, - committed, adding, removing); - - return commit_tx_base_fee(feerate, untrimmed, option_anchor_outputs); -} - -static bool htlc_dust(const struct channel *channel, - const struct htlc **committed, - const struct htlc **adding, - const struct htlc **removing, - enum side side, - u32 feerate, - struct amount_msat *trim_total) -{ - struct amount_sat dust_limit = channel->config[side].dust_limit; - bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); - struct amount_msat trim_rmvd = AMOUNT_MSAT(0); - - if (!commit_tx_amount_trimmed(committed, feerate, - dust_limit, - option_anchor_outputs, - side, trim_total)) - return false; - if (!commit_tx_amount_trimmed(adding, feerate, - dust_limit, - option_anchor_outputs, - side, trim_total)) - return false; - if (!commit_tx_amount_trimmed(removing, feerate, - dust_limit, - option_anchor_outputs, - side, &trim_rmvd)) - return false; - - return amount_msat_sub(trim_total, *trim_total, trim_rmvd); -} - -/* - * There is a corner case where the opener can spend so much that the - * non-opener can't add any non-dust HTLCs (since the opener would - * have to pay the additional fee, but it can't afford to). This - * leads to the channel starving at the feast! This was reported by - * ACINQ's @t-bast - * (https://github.com/lightningnetwork/lightning-rfc/issues/728) and - * demonstrated with Core Lightning by @m-schmoock - * (https://github.com/ElementsProject/lightning/pull/3498). - * - * To mostly avoid this situation, at least from our side, we apply an - * additional constraint when we're opener trying to add an HTLC: make - * sure we can afford one more HTLC, even if fees increase by 100%. - * - * We could do this for the peer, as well, by rejecting their HTLC - * immediately in this case. But rejecting a remote HTLC here causes - * us to get upset with them and close the channel: we're not well - * architected to reject HTLCs in channeld (it's usually lightningd's - * job, but it doesn't have all the channel balance change calculation - * logic. So we look after ourselves for now, and hope other nodes start - * self-regulating too. - * - * This mitigation will become BOLT #2 standard by: - * https://github.com/lightningnetwork/lightning-rfc/issues/740 - */ -static bool local_opener_has_fee_headroom(const struct channel *channel, - struct amount_msat remainder, - const struct htlc **committed, - const struct htlc **adding, - const struct htlc **removing) -{ - u32 feerate = channel_feerate(channel, LOCAL); - size_t untrimmed; - struct amount_sat fee; - bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); - - assert(channel->opener == LOCAL); - - /* How many untrimmed at current feerate? Increasing feerate can - * only *reduce* this number, so use current feerate here! */ - untrimmed = num_untrimmed_htlcs(LOCAL, channel->config[LOCAL].dust_limit, - feerate, - option_anchor_outputs, - committed, adding, removing); - - /* Now, how much would it cost us if feerate increases 100% and we added - * another HTLC? */ - fee = commit_tx_base_fee(2 * feerate, untrimmed + 1, - option_anchor_outputs); - if (amount_msat_greater_eq_sat(remainder, fee)) - return true; - - status_debug("Adding HTLC would leave us only %s: we need %s for" - " another HTLC if fees increase by 100%% to %uperkw", - type_to_string(tmpctx, struct amount_msat, &remainder), - type_to_string(tmpctx, struct amount_sat, &fee), - feerate + feerate); - return false; -} - -static enum channel_add_err add_htlc(struct channel *channel, +static enum channel_add_err add_htlc(struct eltoo_channel *channel, enum htlc_state state, u64 id, struct amount_msat amount, @@ -535,8 +367,6 @@ static enum channel_add_err add_htlc(struct channel *channel, const struct htlc **committed, **adding, **removing; const struct channel_view *view; size_t htlc_count; - bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); - u32 feerate, feerate_ceil; htlc = tal(tmpctx, struct htlc); @@ -667,173 +497,21 @@ static enum channel_add_err add_htlc(struct channel *channel, return CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED; } - /* BOLT #2: - * - * A receiving node: - *... - * - receiving an `amount_msat` that the sending node cannot afford at - * the current `feerate_per_kw` (while maintaining its channel - * reserve and any `to_local_anchor` and `to_remote_anchor` costs): - * - SHOULD send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ - if (enforce_aggregate_limits) { - struct amount_msat remainder; - struct amount_sat fee = fee_for_htlcs(channel, - committed, - adding, - removing, - recipient); - /* set fee output pointer if given */ - if (htlc_fee) - *htlc_fee = fee; - - /* This is a little subtle: - * - * The change is being applied to the receiver but it will - * come back to the sender after revoke_and_ack. So the check - * here is that the remainder to the sender doesn't go below the - * sender's reserve. */ - if (!get_room_above_reserve(channel, view, - adding, removing, sender, - &remainder)) - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - - /* BOLT #3: - * If `option_anchors` applies to the commitment - * transaction, also subtract two times the fixed anchor size - * of 330 sats from the funder (either `to_local` or - * `to_remote`). - */ - if (option_anchor_outputs - && channel->opener == sender - && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660))) - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - - if (channel->opener== sender) { - if (amount_msat_less_sat(remainder, fee)) { - status_debug("Cannot afford fee %s with %s above reserve", - type_to_string(tmpctx, struct amount_sat, - &fee), - type_to_string(tmpctx, struct amount_msat, - &remainder)); - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - } + /* No fee "fun", just don't make relay dust */ - if (sender == LOCAL - && !local_opener_has_fee_headroom(channel, - remainder, - committed, - adding, - removing)) { - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - } - } - - /* Try not to add a payment which will take opener into fees - * on either our side or theirs. */ - if (sender == LOCAL) { - if (!get_room_above_reserve(channel, view, - adding, removing, - channel->opener, - &remainder)) - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - - if (option_anchor_outputs - && channel->opener != sender - && !amount_msat_sub_sat(&remainder, remainder, AMOUNT_SAT(660))) - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - - /* Should be able to afford both their own commit tx - * fee, and other's commit tx fee, which are subtly - * different! */ - fee = fee_for_htlcs(channel, - committed, - adding, - removing, - channel->opener); - /* set fee output pointer if given */ - if (htlc_fee && amount_sat_greater(fee, *htlc_fee)) - *htlc_fee = fee; - if (amount_msat_less_sat(remainder, fee)) { - status_debug("Funder could not afford own fee %s with %s above reserve", - type_to_string(tmpctx, - struct amount_sat, - &fee), - type_to_string(tmpctx, - struct amount_msat, - &remainder)); - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - } - fee = fee_for_htlcs(channel, - committed, - adding, - removing, - !channel->opener); - /* set fee output pointer if given */ - if (htlc_fee && amount_sat_greater(fee, *htlc_fee)) - *htlc_fee = fee; - if (amount_msat_less_sat(remainder, fee)) { - status_debug("Funder could not afford peer's fee %s with %s above reserve", - type_to_string(tmpctx, - struct amount_sat, - &fee), - type_to_string(tmpctx, - struct amount_msat, - &remainder)); - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - } - } - } - - htlc_dust_amt = AMOUNT_MSAT(0); - feerate = channel_feerate(channel, recipient); - /* Note that we check for trimmed htlcs at an - * *accelerated* rate, so that future feerate changes - * don't suddenly surprise us */ - feerate_ceil = htlc_trim_feerate_ceiling(feerate); - - if (!htlc_dust(channel, committed, - adding, removing, recipient, - feerate_ceil, &htlc_dust_amt)) - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; + htlc_dust_amt = channel->config[side].dust_limit; + assert(channel->config[side].dust_limit, channel->config[!side].dust_limit); + /* This really shouldn't happen unless you never want an HTLC... */ if (amount_msat_greater(htlc_dust_amt, channel->config[LOCAL].max_dust_htlc_exposure_msat)) { - /* BOLT-919 #2: - * A node: - * - upon an incoming HTLC: - * - if a HTLC's `amount_msat` is inferior to the - * counterparty's `dust_limit_satoshis` plus the HTLC-timeout fee - * at the `dust_buffer_feerate`: ... - * - SHOULD fail this HTLC once it's committed - * - SHOULD NOT reveal a preimage for this HTLC - */ - /* Note: Marking this as 'fail_immediate' and - * NOT returning an ERR will fail this HTLC - * once it's committed */ htlc->fail_immediate = true; if (err_immediate_failures) return CHANNEL_ERR_DUST_FAILURE; } - /* Also check the sender, as they'll eventually have the same * constraint */ - htlc_dust_amt = AMOUNT_MSAT(0); - feerate = channel_feerate(channel, sender); - feerate_ceil = htlc_trim_feerate_ceiling(feerate); - if (!htlc_dust(channel, committed, adding, - removing, sender, feerate_ceil, - &htlc_dust_amt)) - return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - - if (amount_msat_greater(htlc_dust_amt, - channel->config[LOCAL].max_dust_htlc_exposure_msat)) { - htlc->fail_immediate = true; - if (err_immediate_failures) - return CHANNEL_ERR_DUST_FAILURE; - } dump_htlc(htlc, "NEW:"); htlc_map_add(channel->htlcs, tal_steal(channel, htlc)); if (htlcp) @@ -842,7 +520,7 @@ static enum channel_add_err add_htlc(struct channel *channel, return CHANNEL_ERR_ADD_OK; } -enum channel_add_err channel_add_htlc(struct channel *channel, +enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, enum side sender, u64 id, struct amount_msat amount, @@ -851,9 +529,9 @@ enum channel_add_err channel_add_htlc(struct channel *channel, const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)], const struct pubkey *blinding TAKES, struct htlc **htlcp, - struct amount_sat *htlc_fee, bool err_immediate_failures) { + /* FIXME figure out HTLC state machine for eltoo */ enum htlc_state state; if (sender == LOCAL) @@ -870,7 +548,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel, return add_htlc(channel, state, id, amount, cltv_expiry, payment_hash, routing, blinding, - htlcp, true, htlc_fee, err_immediate_failures); + htlcp, true, err_immediate_failures); } struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id) @@ -1225,106 +903,6 @@ bool htlc_dust_ok(const struct channel *channel, total_dusted); } -bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw) -{ - struct amount_sat needed, fee; - struct amount_sat dust_limit = channel->config[!channel->opener].dust_limit; - size_t untrimmed; - const struct htlc **committed, **adding, **removing; - bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); - - gather_htlcs(tmpctx, channel, !channel->opener, - &committed, &removing, &adding); - - untrimmed = commit_tx_num_untrimmed(committed, feerate_per_kw, dust_limit, - option_anchor_outputs, - !channel->opener) - + commit_tx_num_untrimmed(adding, feerate_per_kw, dust_limit, - option_anchor_outputs, - !channel->opener) - - commit_tx_num_untrimmed(removing, feerate_per_kw, dust_limit, - option_anchor_outputs, - !channel->opener); - - fee = commit_tx_base_fee(feerate_per_kw, untrimmed, - option_anchor_outputs); - - /* BOLT #3: - * If `option_anchors` applies to the commitment - * transaction, also subtract two times the fixed anchor size - * of 330 sats from the funder (either `to_local` or - * `to_remote`). - */ - if (option_anchor_outputs - && !amount_sat_add(&fee, fee, AMOUNT_SAT(660))) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Cannot add 660 sats to %s for anchor", - type_to_string(tmpctx, struct amount_sat, - &fee)); - - /* BOLT #2: - * - * - if the sender cannot afford the new fee rate on the receiving - * node's current commitment transaction: - * - SHOULD send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ - /* Note: sender == opener */ - - /* How much does it think it has? Must be >= reserve + fee */ - if (!amount_sat_add(&needed, fee, - channel->config[!channel->opener].channel_reserve)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Cannot add fee %s and reserve %s", - type_to_string(tmpctx, struct amount_sat, - &fee), - type_to_string(tmpctx, struct amount_sat, - &channel->config[!channel->opener].channel_reserve)); - - status_debug("We need %s at feerate %u for %zu untrimmed htlcs: we have %s/%s", - type_to_string(tmpctx, struct amount_sat, &needed), - feerate_per_kw, untrimmed, - type_to_string(tmpctx, struct amount_msat, - &channel->view[LOCAL].owed[channel->opener]), - type_to_string(tmpctx, struct amount_msat, - &channel->view[REMOTE].owed[channel->opener])); - return amount_msat_greater_eq_sat(channel->view[!channel->opener].owed[channel->opener], - needed); -} - -bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw) -{ - if (!can_opener_afford_feerate(channel, feerate_per_kw)) - return false; - - /* BOLT-919 #2: - * - if the `dust_balance_on_holder_tx` at the - * new `dust_buffer_feerate` is superior to - * the `max_dust_htlc_exposure_msat`: - * ... - * - MAY fail the channel - */ - if (!htlc_dust_ok(channel, feerate_per_kw, REMOTE) || - !htlc_dust_ok(channel, feerate_per_kw, LOCAL)) - return false; - - status_debug("Setting %s feerate to %u", - side_to_str(!channel->opener), feerate_per_kw); - - start_fee_update(channel->fee_states, channel->opener, feerate_per_kw); - return true; -} - -void channel_update_blockheight(struct channel *channel, - u32 blockheight) -{ - status_debug("Setting %s blockheight to %u", - side_to_str(!channel->opener), blockheight); - - start_height_update(channel->blockheight_states, channel->opener, - blockheight); -} - bool channel_sending_commit(struct channel *channel, const struct htlc ***htlcs) { diff --git a/common/keyset.h b/common/keyset.h index 651bec587214..2d94b266f916 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -2,6 +2,7 @@ #define LIGHTNING_COMMON_KEYSET_H #include "config.h" #include +#include struct basepoints; @@ -17,9 +18,11 @@ struct keyset { struct eltoo_keyset { struct pubkey self_settle_key, other_settle_key; struct pubkey self_funding_key, other_funding_key; - /* MuSig2 key using funding keys as input */ + /* MuSig2 key using funding keys as input, session + non-empty once partial sig created locally! */ struct pubkey inner_pubkey; struct nonce self_next_nonce, other_next_nonce; + struct musig_session session; }; /* Self == owner of commitment tx, other == non-owner. */ diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 73e9207692c2..dca7f320918e 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -321,6 +321,7 @@ msgdata,hsmd_psign_update_tx,remote_nonce,nonce, msgtype,hsmd_psign_update_tx_reply,162 msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, +msgdata,hsmd_psign_update_tx_reply,session,musig_session, msgdata,hsmd_psign_update_tx_reply,next_nonce,nonce, msgtype,hsmd_validate_update_tx_psig,163 @@ -336,6 +337,7 @@ msgtype,hsmd_combine_psig,92 msgdata,hsmd_combine_psig,channel_id,channel_id, msgdata,hsmd_combine_psig,p_sig_1,partial_sig, msgdata,hsmd_combine_psig,p_sig_2,partial_sig, +msgdata,hsmd_combine_psig,session,musig_session, msgdata,hsmd_combine_psig,update_tx,bitcoin_tx, msgdata,hsmd_combine_psig,settle_tx,bitcoin_tx, msgdata,hsmd_combine_psig,inner_pubkey,pubkey, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index fbc7d9bf9d85..cab178749534 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -39,7 +39,6 @@ struct { struct channel_id musig_channel; secp256k1_musig_secnonce sec_nonce; struct nonce pub_nonce; - secp256k1_musig_session session; } secretstuff; /* Have we initialized the secretstuff? */ @@ -1383,11 +1382,13 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) struct bip340sig sig; struct pubkey inner_pubkey; const secp256k1_musig_partial_sig *p_sig_ptrs[2]; + struct musig_session session; if (!fromwire_hsmd_combine_psig(tmpctx, msg_in, &channel_id, &p_sig_1, &p_sig_2, + &session, &update_tx, &settle_tx, &inner_pubkey)) { @@ -1403,7 +1404,7 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) if (!bipmusig_partial_sigs_combine_verify(p_sig_ptrs, /* num_signers */ 2, &inner_pubkey, - &secretstuff.session, + &session.session, &hash_out, &sig)) { /* FIXME better complaint from hsmd */ @@ -1426,6 +1427,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) struct secrets secrets; struct nonce remote_nonce; struct channel_id channel_id; + struct musig_session session; /* MuSig stuff */ struct pubkey dummy_inner_pubkey; /* only cache needed for signing */ @@ -1482,7 +1484,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) /* num_signers */ 2, &hash_out, &keyagg_cache, - &secretstuff.session, + &session.session, &p_sig.p_sig); /* Refill and return own next_nonce, using RNG+extra stuff for more security */ @@ -1492,7 +1494,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) &keyagg_cache, hash_out.sha.u.u8); - return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &secretstuff.pub_nonce); + return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &secretstuff.pub_nonce); } diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index db6a78690e56..a0be1b5da13b 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -551,6 +551,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: /* FIXME Handle this */ break; + case WIRE_CHANNELD_GOT_UPDATESIG: + /* FIXME handle this */ + break; #if EXPERIMENTAL_FEATURES case WIRE_CHANNELD_UPGRADED: handle_channel_upgrade(sd->channel, msg); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 1846c01c436b..4f8cf6cb28a1 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -539,7 +539,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.session, &state->channel->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -629,6 +629,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->channel_id, &our_update_psig, &their_update_psig, + &state->channel->eltoo_keyset.session, *update_tx, settle_tx, &state->channel->eltoo_keyset.inner_pubkey); @@ -999,7 +1000,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.session, &state->channel->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -1008,6 +1009,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->channel_id, &our_update_psig, &their_update_psig, + &state->channel->eltoo_keyset.session, update_tx, settle_tx, &state->channel->eltoo_keyset.inner_pubkey); From e79488f619cfae4e824fb9ae46c5bddb37a2ac1c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 16 Aug 2022 13:00:46 -0400 Subject: [PATCH 132/283] Many changes --- channeld/channeld_htlc.h | 2 + channeld/channeld_wire.csv | 28 +++++- channeld/eltoo_channeld.c | 172 ++++++++++++++-------------------- channeld/eltoo_full_channel.c | 62 ++++++------ channeld/eltoo_full_channel.h | 4 +- common/htlc.h | 15 +++ common/htlc_state.c | 85 +++++++++++++++++ common/htlc_state.h | 51 +++++++--- common/keyset.h | 1 + 9 files changed, 269 insertions(+), 151 deletions(-) diff --git a/channeld/channeld_htlc.h b/channeld/channeld_htlc.h index 3a40416f6c1c..381ff1784c03 100644 --- a/channeld/channeld_htlc.h +++ b/channeld/channeld_htlc.h @@ -9,6 +9,8 @@ struct htlc { /* What's the status. */ enum htlc_state state; + /* FIXME Can this live here? */ + enum eltoo_htlc_state eltoo_state; /* The unique ID for this peer and this direction (LOCAL or REMOTE) */ u64 id; /* The amount in millisatoshi. */ diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 8a92f31b3524..13d1886d7fa9 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -284,5 +284,31 @@ msgtype,channeld_got_funding_locked_eltoo,1079 # When we have a update_signed message, tell master to remember. msgtype,channeld_got_updatesig,1081 msgdata,channeld_got_updatesig,update_num,u32, -msgdata,channeld_got_updatesig,update_sig,bip340sig, +msgdata,channeld_got_updatesig,our_p_sig,partial_sig, +msgdata,channeld_got_updatesig,their_p_sig,partial_sig, +msgdata,channeld_got_updatesig,session,musig_session, +# RCVD_ADD_UPDATE: we're now committed to their new offered HTLCs. +msgdata,channeld_got_updatesig,num_added,u16, +msgdata,channeld_got_updatesig,added,added_htlc,num_added +# RCVD_REMOVE_UPDATE: we're now no longer committed to these HTLCs. +msgdata,channeld_got_updatesig,num_fulfilled,u16, +msgdata,channeld_got_updatesig,fulfilled,fulfilled_htlc,num_fulfilled +msgdata,channeld_got_updatesig,num_failed,u16, +msgdata,channeld_got_updatesig,failed,failed_htlc,num_failed +# RCVD_ADD_ACK, RCVD_REMOVE_ACK +msgdata,channeld_got_updatesig,num_changed,u16, +msgdata,channeld_got_updatesig,changed,changed_htlc,num_changed +msgdata,channeld_got_updatesig,update_tx,bitcoin_tx, +msgdata,channeld_got_updatesig,settle_tx,bitcoin_tx, +# Wait for reply, to make sure it's on disk before we send revocation. +msgtype,channeld_got_updatesig_reply,1181 + +msgtype,channeld_got_ack,1082 +msgdata,channeld_got_ack,updatenum,u64, +# RCVD_ADD_ACK, RCVD_REMOVE_ACK +msgdata,channeld_got_ack,num_changed,u16, +msgdata,channeld_got_ack,changed,changed_htlc,num_changed +# Wait for reply, to make sure it's on disk before we continue +# (eg. if we sent another commitment_signed, that would implicitly ack). +msgtype,channeld_got_ack_reply,1122 diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 8d762b317c93..b77a51eb5b16 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -53,7 +53,7 @@ struct eltoo_peer { struct per_peer_state *pps; bool funding_locked[NUM_SIDES]; - u64 next_index[NUM_SIDES]; + u64 next_index; /* Features peer supports. */ u8 *their_features; @@ -144,6 +144,10 @@ struct eltoo_peer { u8 channel_flags; */ + /* Number of update_signed(_ack) messages received by peer */ + u64 updates_received; + + bool announce_depth_reached; bool channel_local_active; @@ -1123,7 +1127,7 @@ static void send_commit(struct peer *peer) start_commit_timer(peer); } -static void start_commit_timer(struct peer *peer) +static void start_commit_timer(struct eltoo_peer *peer) { /* Already armed? */ if (peer->commit_timer) @@ -1196,9 +1200,12 @@ static void marshall_htlc_info(const tal_t *ctx, } static void send_update_sign_ack(struct peer *peer, + const struct htlc **changed_htlcs, const struct partial_sig *our_update_psig, - const struct bip340sit *update_sig, + const struct partial_sig *their_update_psig, + const struct musig_session *session, const struct bitcoin_tx *update_tx, + const struct bitcoin_tx *settle_tx, const struct nonce *our_next_nonce) { struct changed_htlc *changed; @@ -1230,20 +1237,21 @@ static void send_update_sign_ack(struct peer *peer, } */ /* Tell master daemon about update_sig (and by implication, that we're - * sending revoke_and_ack), then wait for it to ack. */ - /* We had to do this after channel_sending_revoke_and_ack, since we - * want it to save the fee_states produced there. */ + * sending update_sig_ack), then wait for it to ack. */ msg_for_master = towire_channeld_got_updatesig(NULL, peer->next_index[LOCAL] - 1, - update_sig, htlc_sigs, + our_update_psig, + their_update_psig, + session, added, fulfilled, failed, changed, - committx); + update_tx, + settle_tx); master_wait_sync_reply(tmpctx, peer, take(msg_for_master), - WIRE_CHANNELD_GOT_COMMITSIG_REPLY); + WIRE_CHANNELD_GOT_UPDATESIG_REPLY); /* Now we can finally send revoke_and_ack to peer */ peer_write(peer->pps, take(msg)); @@ -1270,7 +1278,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) const u8 * msg2; changed_htlcs = tal_arr(msg, const struct htlc *, 0); - if (!channel_rcvd_commit(peer->channel, &changed_htlcs)) { + /* Does our counterparty offer any changes? */ + if (!channel_rcvd_update(peer->channel, &changed_htlcs)) { /* BOLT #2: * * A sending node: @@ -1308,7 +1317,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &peer->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -1317,6 +1326,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel_id, &our_update_psig, &their_update_psig, + &peer->channel->eltoo_keyset.session update_and_settle_txs[0], update_and_settle_txs[1], &peer->channel->eltoo_keyset.inner_pubkey); @@ -1328,9 +1338,12 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) } send_update_sign_ack(peer, - &our_update_psig, changed_htlcs, - txs[0], + &our_update_psig, + &their_update_psig, + &peer->channel->eltoo_keyset.session, + update_and_settle_txs[0], + update_and_settle_txs[1], &peer->channel->eltoo_keyset.self_next_nonce); /* We may now be quiescent on our side. */ @@ -1338,15 +1351,11 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) } -static u8 *got_revoke_msg(struct peer *peer, u64 revoke_num, - const struct secret *per_commitment_secret, - const struct pubkey *next_per_commit_point, - const struct htlc **changed_htlcs, - const struct fee_states *fee_states, - const struct height_states *blockheight_states) +static u8 *got_ack_msg(struct peer *peer, + u64 update_num, + const struct htlc **changed_htlcs) { u8 *msg; - struct penalty_base *pbase; struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); const struct bitcoin_tx *ptx = NULL; @@ -1363,104 +1372,58 @@ static u8 *got_revoke_msg(struct peer *peer, u64 revoke_num, tal_arr_expand(&changed, c); } - pbase = penalty_base_by_commitnum(tmpctx, peer, revoke_num); - - if (pbase) { - ptx = penalty_tx_create( - NULL, peer->channel, peer->feerate_penalty, - peer->final_index, peer->final_ext_key, - peer->final_scriptpubkey, per_commitment_secret, - &pbase->txid, pbase->outnum, pbase->amount, - HSM_FD); - } + msg = towire_channeld_got_ack(peer, update_num, + changed); - msg = towire_channeld_got_revoke(peer, revoke_num, per_commitment_secret, - next_per_commit_point, fee_states, - blockheight_states, changed, - pbase, ptx); - tal_free(ptx); return msg; } -static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) +static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) { - struct secret old_commit_secret; - struct privkey privkey; struct channel_id channel_id; - const u8 *revocation_msg; - struct pubkey per_commit_point, next_per_commit; + const u8 *comb_msg; + struct bip340sig update_sig; const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); - if (!fromwire_revoke_and_ack(msg, &channel_id, &old_commit_secret, - &next_per_commit)) { + if (!fromwire_update_signed_ack(msg, &channel_id, &peer->channel->eltoo_keyset.other_psig, + &peer->channel->eltoo_keyset.other_next_nonce)) { peer_failed_warn(peer->pps, &peer->channel_id, - "Bad revoke_and_ack %s", tal_hex(msg, msg)); + "Bad update_signed_ack %s", tal_hex(msg, msg)); } - if (peer->revocations_received != peer->next_index[REMOTE] - 2) { - peer_failed_warn(peer->pps, &peer->channel_id, - "Unexpected revoke_and_ack"); - } + comb_msg = towire_hsmd_combine_psig(tmpctx, + &channel_id, + &peer->channel->eltoo_keyset.self_psig, + &peer->channel->eltoo_keyset.other_psig, + &peer->channel->eltoo_keyset.session, + /* FIXME where should these proposed txns live? vs state */ + &peer->channel->proposed_update_tx, + &peer->channel->proposed_settle_tx, + &peer->channel->eltoo_keyset.inner_pubkey); + - /* Submit the old revocation secret to the signer so it can - * independently verify that the latest state is commited. It - * is also validated in this routine after the signer returns. - */ - revocation_msg = towire_hsmd_validate_revocation(tmpctx, - peer->next_index[REMOTE] - 2, - &old_commit_secret); - revocation_msg = hsm_req(tmpctx, take(revocation_msg)); - if (!fromwire_hsmd_validate_revocation_reply(revocation_msg)) + if (!fromwire_hsmd_combine_psig_reply(comb_msg, &update_sig)) status_failed(STATUS_FAIL_HSM_IO, - "Bad hsmd_validate_revocation_reply: %s", - tal_hex(tmpctx, revocation_msg)); - - /* BOLT #2: - * - * A receiving node: - * - if `per_commitment_secret` is not a valid secret key or does not - * generate the previous `per_commitment_point`: - * - MUST send an `error` and fail the channel. - */ - memcpy(&privkey, &old_commit_secret, sizeof(privkey)); - if (!pubkey_from_privkey(&privkey, &per_commit_point)) { - peer_failed_err(peer->pps, &peer->channel_id, - "Bad privkey %s", - type_to_string(msg, struct privkey, &privkey)); - } - if (!pubkey_eq(&per_commit_point, &peer->old_remote_per_commit)) { - peer_failed_err(peer->pps, &peer->channel_id, - "Wrong privkey %s for %"PRIu64" %s", - type_to_string(msg, struct privkey, &privkey), - peer->next_index[LOCAL]-2, - type_to_string(msg, struct pubkey, - &peer->old_remote_per_commit)); - } + "Bad hsmd_combine_psig_reply: %s", + tal_hex(tmpctx, comb_msg)); /* We start timer even if this returns false: we might have delayed * commit because we were waiting for this! */ - if (channel_rcvd_revoke_and_ack(peer->channel, &changed_htlcs)) - status_debug("Commits outstanding after recv revoke_and_ack"); - else - status_debug("No commits outstanding after recv revoke_and_ack"); + if (channel_rcvd_update_sign_ack(peer->channel, &changed_htlcs)) { + /* FIXME I don't think this is possible? */ + status_debug("Commits outstanding after recv update_sign_ack"); + } else { + status_debug("No commits outstanding after recv update_sign_ack"); + } /* Tell master about things this locks in, wait for response */ - msg = got_revoke_msg(peer, peer->revocations_received++, - &old_commit_secret, &next_per_commit, - changed_htlcs, - peer->channel->fee_states, - peer->channel->blockheight_states); + msg = got_ack_msg(peer, peer->next_index++, + changed_htlcs); master_wait_sync_reply(tmpctx, peer, take(msg), - WIRE_CHANNELD_GOT_REVOKE_REPLY); + WIRE_CHANNELD_GOT_ACK_REPLY); - peer->old_remote_per_commit = peer->remote_per_commit; - peer->remote_per_commit = next_per_commit; - status_debug("revoke_and_ack %s: remote_per_commit = %s, old_remote_per_commit = %s", - side_to_str(peer->channel->opener), - type_to_string(tmpctx, struct pubkey, - &peer->remote_per_commit), - type_to_string(tmpctx, struct pubkey, - &peer->old_remote_per_commit)); + status_debug("update_signed_ack %s: update = %d", + side_to_str(peer->channel->opener), peer->next_index - 1); /* We may now be quiescent on our side. */ maybe_send_stfu(peer); @@ -1468,7 +1431,7 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) start_commit_timer(peer); } -static void handle_peer_fulfill_htlc(struct peer *peer, const u8 *msg) +static void handle_peer_fulfill_htlc(struct eltoo_peer *peer, const u8 *msg) { struct channel_id channel_id; u64 id; @@ -1819,24 +1782,27 @@ static void peer_in(struct peer *elto_peer, const u8 *msg) handle_peer_add_htlc(peer, msg); return; case WIRE_COMMITMENT_SIGNED: - /* FIXME How should we handle ilegal messages in general? */ + /* FIXME How should we handle illegal messages in general? */ return; case WIRE_UPDATE_FEE: handle_peer_feechange(peer, msg); return; - /* FIXME below */ case WIRE_UPDATE_SIGNED: handle_peer_update_sig(peer, msg); return; case WIRE_UPDATE_BLOCKHEIGHT: - handle_peer_blockheight_change(peer, msg); + /* FIXME How should we handle illegal messages in general? */ return; case WIRE_REVOKE_AND_ACK: - handle_peer_revoke_and_ack(peer, msg); + /* FIXME How should we handle illegal messages in general? */ + return; + case WIRE_UPDATE_SIGNED_ACK: + handle_peer_update_sig_ack(peer, msg); return; case WIRE_UPDATE_FULFILL_HTLC: handle_peer_fulfill_htlc(peer, msg); return; + /* FIXME below */ case WIRE_UPDATE_FAIL_HTLC: handle_peer_fail_htlc(peer, msg); return; diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 6b7f2e0177ce..5e49b331caad 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -128,24 +128,25 @@ static void htlc_arr_append(const struct htlc ***arr, const struct htlc *htlc) static void dump_htlc(const struct htlc *htlc, const char *prefix) { - enum htlc_state remote_state; + enum eltoo_htlc_state remote_state; + enum eltoo_htlc_state state = htlc->eltoo_state; - if (htlc->state <= RCVD_REMOVE_ACK_REVOCATION) - remote_state = htlc->state + 10; + if (htlc->eltoo_state <= SENT_REMOVE_ACK) + remote_state = state + 6; else - remote_state = htlc->state - 10; + remote_state = state - 6; status_debug("%s: HTLC %s %"PRIu64" = %s/%s %s", prefix, - htlc_owner(htlc) == LOCAL ? "LOCAL" : "REMOTE", + eltoo_htlc_state_owner(state) == LOCAL ? "LOCAL" : "REMOTE", htlc->id, - htlc_state_name(htlc->state), - htlc_state_name(remote_state), + eltoo_htlc_state_name(state), + eltoo_htlc_state_name(remote_state), htlc->r ? "FULFILLED" : htlc->failed ? "FAILED" : ""); } -void dump_htlcs(const struct channel *channel, const char *prefix) +void dump_htlcs(const struct eltoo_channel *channel, const char *prefix) { #ifdef SUPERVERBOSE struct htlc_map_iter it; @@ -348,7 +349,7 @@ static size_t num_untrimmed_htlcs(enum side side, } static enum channel_add_err add_htlc(struct eltoo_channel *channel, - enum htlc_state state, + enum eltoo_htlc_state state, u64 id, struct amount_msat amount, u32 cltv_expiry, @@ -363,7 +364,7 @@ static enum channel_add_err add_htlc(struct eltoo_channel *channel, struct htlc *htlc, *old; struct amount_msat msat_in_htlcs, committed_msat, adding_msat, removing_msat, htlc_dust_amt; - enum side sender = htlc_state_owner(state), recipient = !sender; + enum side sender = eltoo_htlc_state_owner(state), recipient = !sender; const struct htlc **committed, **adding, **removing; const struct channel_view *view; size_t htlc_count; @@ -532,7 +533,7 @@ enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, bool err_immediate_failures) { /* FIXME figure out HTLC state machine for eltoo */ - enum htlc_state state; + enum eltoo_htlc_state state; if (sender == LOCAL) state = SENT_ADD_HTLC; @@ -556,7 +557,7 @@ struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id) return htlc_get(channel->htlcs, id, sender); } -enum channel_remove_err channel_fulfill_htlc(struct channel *channel, +enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, enum side owner, u64 id, const struct preimage *preimage, @@ -594,7 +595,7 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, */ if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", - htlc->id, htlc_state_name(htlc->state)); + htlc->id, htlc_state_name(htlc->eltoo_state)); return CHANNEL_ERR_HTLC_UNCOMMITTED; } @@ -609,13 +610,13 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, * - MUST NOT send an `update_fulfill_htlc`, `update_fail_htlc`, or * `update_fail_malformed_htlc`. */ - if (htlc->state == SENT_ADD_ACK_REVOCATION) - htlc->state = RCVD_REMOVE_HTLC; - else if (htlc->state == RCVD_ADD_ACK_REVOCATION) - htlc->state = SENT_REMOVE_HTLC; + if (htlc->eltoo_state == RCVD_ADD_ACK) + htlc->eltoo_state = RCVD_REMOVE_HTLC; + else if (htlc->eltoo_state == SENT_ADD_ACK) + htlc->eltoo_state = SENT_REMOVE_HTLC; else { status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", - htlc->id, htlc_state_name(htlc->state)); + htlc->id, htlc_state_name(htlc->eltoo_state)); return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; } @@ -921,35 +922,32 @@ bool channel_sending_commit(struct channel *channel, return true; } -bool channel_rcvd_revoke_and_ack(struct channel *channel, +bool channel_rcvd_update_sign_ack(struct channel *channel, const struct htlc ***htlcs) { int change; - const enum htlc_state states[] = { SENT_ADD_COMMIT, - SENT_REMOVE_ACK_COMMIT, - SENT_ADD_ACK_COMMIT, - SENT_REMOVE_COMMIT }; + const enum htlc_state states[] = { SENT_ADD_UPDATE, + SENT_REMOVE_UPDATE }; - status_debug("Received revoke_and_ack"); + status_debug("Received update_sign_ack"); change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), - htlcs, "rcvd_revoke_and_ack"); + htlcs, "rcvd_update_sign_ack"); - /* Their ack can queue changes on our side. */ + /* FIXME what should this be? ... Their ack can queue changes on our side. */ return (change & HTLC_LOCAL_F_PENDING); } -/* FIXME: We can actually merge these two... */ -bool channel_rcvd_commit(struct channel *channel, const struct htlc ***htlcs) +bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs) { int change; - const enum htlc_state states[] = { RCVD_ADD_REVOCATION, + const enum eltoo_htlc_state states[] = { RCVD_ADD_UPDATE, RCVD_REMOVE_HTLC, RCVD_ADD_HTLC, - RCVD_REMOVE_REVOCATION }; + RCVD_REMOVE_UPDATE }; - status_debug("Received commit"); + status_debug("Received Update"); change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), - htlcs, "rcvd_commit"); + htlcs, "rcvd_update"); if (!change) return false; return true; diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h index 6f674a75f2c0..78d3feca14f4 100644 --- a/channeld/eltoo_full_channel.h +++ b/channeld/eltoo_full_channel.h @@ -237,12 +237,12 @@ bool channel_rcvd_revoke_and_ack(struct channel *channel, const struct htlc ***htlcs); /** - * channel_rcvd_commit: commit all local outstanding changes. + * channel_rcvd_update: commit all outstanding changes. * @channel: the channel * @htlcs: initially-empty tal_arr() for htlcs which changed state. * * This is where we commit to pending changes we've added; returns true if - * anything changed for our local commitment (ie. we had pending changes). + * anything changed for our update (ie. we had pending changes added by other). */ bool channel_rcvd_commit(struct channel *channel, const struct htlc ***htlcs); diff --git a/common/htlc.h b/common/htlc.h index c300f0ffe5d9..f403e6e3f81a 100644 --- a/common/htlc.h +++ b/common/htlc.h @@ -60,6 +60,21 @@ static inline enum side htlc_state_owner(enum htlc_state state) } } +static inline enum side eltoo_htlc_state_owner(enum eltoo_htlc_state state) +{ + if (state < RCVD_ADD_HTLC) { + assert((eltoo_htlc_state_flags(state) + & (HTLC_REMOTE_F_OWNER|HTLC_LOCAL_F_OWNER)) + == HTLC_LOCAL_F_OWNER); + return LOCAL; + } else { + assert((eltoo_htlc_state_flags(state) + & (HTLC_REMOTE_F_OWNER|HTLC_LOCAL_F_OWNER)) + == HTLC_REMOTE_F_OWNER); + return REMOTE; + } +} + static inline const char *side_to_str(enum side side) { switch (side) { diff --git a/common/htlc_state.c b/common/htlc_state.c index 75b841d3837e..f02a022c0ba9 100644 --- a/common/htlc_state.c +++ b/common/htlc_state.c @@ -139,3 +139,88 @@ int htlc_state_flags(enum htlc_state state) return per_state_bits[state]; } +const char *eltoo_htlc_state_name(enum eltoo_htlc_state s) +{ + size_t i; + + for (i = 0; enum_eltoo_htlc_state_names[i].name; i++) + if (enum_eltoo_htlc_state_names[i].v == s) + return enum_eltoo_htlc_state_names[i].name; + return "unknown"; +} + +/* This is the flags for each state. */ +/* FIXME someone how knows this has to look at it ... */ +static const int eltoo_per_state_bits[] = { + [SENT_ADD_HTLC] = HTLC_ADDING + HTLC_LOCAL_F_OWNER + + HTLC_REMOTE_F_PENDING + + HTLC_LOCAL_F_PENDING, + + [SENT_ADD_UPDATE] = HTLC_ADDING + HTLC_LOCAL_F_OWNER + + HTLC_REMOTE_F_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED + + HTLC_LOCAL_F_COMMITTED + + HTLC_LOCAL_F_WAS_COMMITTED, + + [RCVD_ADD_ACK] = HTLC_ADDING + HTLC_LOCAL_F_OWNER + + HTLC_REMOTE_F_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED + + HTLC_LOCAL_F_COMMITTED + + HTLC_LOCAL_F_WAS_COMMITTED, + + [RCVD_REMOVE_HTLC] = HTLC_REMOVING + HTLC_LOCAL_F_OWNER + + HTLC_LOCAL_F_PENDING + + HTLC_LOCAL_F_COMMITTED + + HTLC_LOCAL_F_WAS_COMMITTED + + HTLC_REMOTE_F_PENDING + + HTLC_REMOTE_F_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED, + + [RCVD_REMOVE_UPDATE] = HTLC_REMOVING + HTLC_LOCAL_F_OWNER + + HTLC_LOCAL_F_WAS_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED, + + [SENT_REMOVE_ACK] = HTLC_REMOVING + HTLC_LOCAL_F_OWNER + + HTLC_LOCAL_F_WAS_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED, + + [RCVD_ADD_HTLC] = HTLC_ADDING + HTLC_REMOTE_F_OWNER + + HTLC_LOCAL_F_PENDING + + HTLC_REMOTE_F_PENDING, + + [RCVD_ADD_UPDATE] = HTLC_ADDING + HTLC_REMOTE_F_OWNER + + HTLC_REMOTE_F_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED + + HTLC_LOCAL_F_COMMITTED + + HTLC_LOCAL_F_WAS_COMMITTED, + + [SENT_ADD_ACK] = HTLC_ADDING + HTLC_REMOTE_F_OWNER + + HTLC_REMOTE_F_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED + + HTLC_LOCAL_F_COMMITTED + + HTLC_LOCAL_F_WAS_COMMITTED, + + [SENT_REMOVE_HTLC] = HTLC_REMOVING + HTLC_REMOTE_F_OWNER + + HTLC_LOCAL_F_PENDING + + HTLC_LOCAL_F_COMMITTED + + HTLC_LOCAL_F_WAS_COMMITTED + + HTLC_REMOTE_F_PENDING + + HTLC_REMOTE_F_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED, + + [SENT_REMOVE_UPDATE] = HTLC_REMOVING + HTLC_REMOTE_F_OWNER + + HTLC_LOCAL_F_WAS_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED, + + [RCVD_REMOVE_ACK] = HTLC_REMOVING + HTLC_REMOTE_F_OWNER + + HTLC_LOCAL_F_WAS_COMMITTED + + HTLC_REMOTE_F_WAS_COMMITTED, +}; + +int eltoo_htlc_state_flags(enum eltoo_htlc_state state) +{ + assert(state < ARRAY_SIZE(eltoo_per_state_bits)); + assert(eltoo_per_state_bits[state]); + return eltoo_per_state_bits[state]; +} + diff --git a/common/htlc_state.h b/common/htlc_state.h index 7026c034c6a2..d107943430fd 100644 --- a/common/htlc_state.h +++ b/common/htlc_state.h @@ -7,28 +7,28 @@ * reorder or insert new values (appending at the end is ok) /!\ */ enum htlc_state { - /* When we add a new htlc, it goes in this order. */ - SENT_ADD_HTLC, - SENT_ADD_COMMIT, - RCVD_ADD_REVOCATION, - RCVD_ADD_ACK_COMMIT, - SENT_ADD_ACK_REVOCATION, - - /* When they remove an HTLC, it goes from SENT_ADD_ACK_REVOCATION: */ - RCVD_REMOVE_HTLC, - RCVD_REMOVE_COMMIT, + /* When _we_ add a new htlc, it goes in this order. */ + SENT_ADD_HTLC, /* --update_add_htlc--> */ + SENT_ADD_COMMIT, /* --commitment_signed--> */ + RCVD_ADD_REVOCATION, /* <--revoke_and_ack-- */ + RCVD_ADD_ACK_COMMIT, /* <--commitment_signed-- */ + SENT_ADD_ACK_REVOCATION, /* --revoke_and_ack--> */ + + /* ... then when _they_ remove the HTLC: */ + RCVD_REMOVE_HTLC, /* <--update_{fulfill,fail,fail_malformed}_htlc-- */ + RCVD_REMOVE_COMMIT, /* rest of messages same as "add", in reverse direction */ SENT_REMOVE_REVOCATION, SENT_REMOVE_ACK_COMMIT, RCVD_REMOVE_ACK_REVOCATION, - /* When they add a new htlc, it goes in this order. */ - RCVD_ADD_HTLC, + /* When _they_ add a new htlc, it goes in this order. */ + RCVD_ADD_HTLC, RCVD_ADD_COMMIT, SENT_ADD_REVOCATION, SENT_ADD_ACK_COMMIT, RCVD_ADD_ACK_REVOCATION, - /* When we remove an HTLC, it goes from RCVD_ADD_ACK_REVOCATION: */ + /* ... then when _we_ remove the HTLC: */ SENT_REMOVE_HTLC, SENT_REMOVE_COMMIT, RCVD_REMOVE_REVOCATION, @@ -37,4 +37,29 @@ enum htlc_state { HTLC_STATE_INVALID }; + +enum eltoo_htlc_state { + /* When _we_ add a new htlc, it goes in this order. */ + SENT_ADD_HTLC, /* --update_add_htlc--> */ + SENT_ADD_UPDATE, /* --update_signed--> */ + RCVD_ADD_ACK, /* <--update_signed_ack-- */ + + /* ... then when _they_ remove the HTLC: */ + RCVD_REMOVE_HTLC, /* <--update_{fulfill,fail,fail_malformed}_htlc-- */ + RCVD_REMOVE_UPDATE, /* rest of messages same as "add", in reverse direction */ + SENT_REMOVE_ACK, + + /* When _they_ add a new htlc, it goes in this order. */ + RCVD_ADD_HTLC, + RCVD_ADD_UPDATE, + SENT_ADD_ACK, + + /* ... then when _we_ remove the HTLC: */ + SENT_REMOVE_HTLC, + SENT_REMOVE_UPDATE, + RCVD_REMOVE_ACK, + + HTLC_STATE_INVALID +}; + #endif /* LIGHTNING_COMMON_HTLC_STATE_H */ diff --git a/common/keyset.h b/common/keyset.h index 2d94b266f916..db44b60cce7b 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -22,6 +22,7 @@ struct eltoo_keyset { non-empty once partial sig created locally! */ struct pubkey inner_pubkey; struct nonce self_next_nonce, other_next_nonce; + struct partial_sig self_psig, other_psig; struct musig_session session; }; From 2ee681c1d54379c08d0c9658300ddf5cc24cebc6 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 18 Aug 2022 13:05:18 -0400 Subject: [PATCH 133/283] start compiling --- channeld/channeld_htlc.h | 23 + channeld/channeld_wire.csv | 86 ++ channeld/eltoo_channeld.c | 1415 ++++----------------------------- channeld/eltoo_full_channel.c | 159 +--- channeld/eltoo_full_channel.h | 52 +- common/htlc_wire.h | 1 + 6 files changed, 347 insertions(+), 1389 deletions(-) diff --git a/channeld/channeld_htlc.h b/channeld/channeld_htlc.h index 381ff1784c03..3177a88b8d58 100644 --- a/channeld/channeld_htlc.h +++ b/channeld/channeld_htlc.h @@ -40,11 +40,21 @@ static inline bool htlc_has(const struct htlc *h, int flag) return htlc_state_flags(h->state) & flag; } +static inline bool eltoo_htlc_has(const struct htlc *h, int flag) +{ + return eltoo_htlc_state_flags(h->state) & flag; +} + static inline enum side htlc_owner(const struct htlc *h) { return htlc_state_owner(h->state); } +static inline enum side eltoo_htlc_owner(const struct htlc *h) +{ + return eltoo_htlc_state_owner(h->eltoo_state); +} + /* htlc_map: ID -> htlc mapping. */ static inline u64 htlc_key(const struct htlc *h) { @@ -74,6 +84,19 @@ static inline struct htlc *htlc_get(struct htlc_map *htlcs, u64 id, enum side ow return NULL; } +static inline struct htlc *eltoo_htlc_get(struct htlc_map *htlcs, u64 id, enum side owner) +{ + struct htlc *h; + struct htlc_map_iter it; + + for (h = htlc_map_getfirst(htlcs, id, &it); + h; + h = htlc_map_getnext(htlcs, id, &it)) { + if (h->id == id && eltoo_htlc_has(h, HTLC_FLAG(owner,HTLC_F_OWNER))) + return h; + } + return NULL; +} /* FIXME: Move these out of the hash! */ static inline bool htlc_is_dead(const struct htlc *htlc) { diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 13d1886d7fa9..967c761eaff2 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -278,6 +278,67 @@ msgdata,channeld_blockheight,blockheight,u32, # ELTOO STUFF +# Begin! (passes gossipd-client fd) +msgtype,channeld_init_eltoo,1000 +msgdata,channeld_init_eltoo,chainparams,chainparams, +msgdata,channeld_init_eltoo,our_features,feature_set, +msgdata,channeld_init_eltoo,channel_id,channel_id, +msgdata,channeld_init_eltoo,funding,bitcoin_outpoint, +msgdata,channeld_init_eltoo,funding_satoshi,amount_sat, +msgdata,channeld_init_eltoo,minimum_depth,u32, +msgdata,channeld_init_eltoo,our_blockheight,u32, +msgdata,channeld_init_eltoo,our_config,channel_config, +msgdata,channeld_init_eltoo,their_config,channel_config, +msgdata,channeld_init_eltoo,feerate_min,u32, +msgdata,channeld_init_eltoo,feerate_max,u32, +msgdata,channeld_init_eltoo,their_update_psig,partial_sig, +msgdata,channeld_init_eltoo,our_update_psig,partial_sig, +msgdata,channeld_init_eltoo,session,musig_session, +msgdata,channeld_init_eltoo,their_funding_pubkey,pubkey, +msgdata,channeld_init_eltoo,opener,enum side, +msgdata,channeld_init_eltoo,fee_base,u32, +msgdata,channeld_init_eltoo,fee_proportional,u32, +msgdata,channeld_init_eltoo,htlc_minimum_msat,amount_msat, +msgdata,channeld_init_eltoo,htlc_maximum_msat,amount_msat, +msgdata,channeld_init_eltoo,local_msatoshi,amount_msat, +msgdata,channeld_init_eltoo,our_funding_pubkey,pubkey, +msgdata,channeld_init_eltoo,local_node_id,node_id, +msgdata,channeld_init_eltoo,remote_node_id,node_id, +msgdata,channeld_init_eltoo,commit_msec,u32, +msgdata,channeld_init_eltoo,cltv_delta,u16, +msgdata,channeld_init_eltoo,next_index,u64, +msgdata,channeld_init_eltoo,updates_received,u64, +msgdata,channeld_init_eltoo,next_htlc_id,u64, +msgdata,channeld_init_eltoo,num_existing_htlcs,u16, +msgdata,channeld_init_eltoo,htlcs,existing_htlc,num_existing_htlcs +msgdata,channeld_init_eltoo,local_funding_locked,bool, +msgdata,channeld_init_eltoo,remote_funding_locked,bool, +msgdata,channeld_init_eltoo,funding_short_id,short_channel_id, +msgdata,channeld_init_eltoo,reestablish,bool, +msgdata,channeld_init_eltoo,send_shutdown,bool, +msgdata,channeld_init_eltoo,remote_shutdown_received,bool, +msgdata,channeld_init_eltoo,final_index,u32, +msgdata,channeld_init_eltoo,final_ext_key,ext_key, +msgdata,channeld_init_eltoo,final_scriptpubkey_len,u16, +msgdata,channeld_init_eltoo,final_scriptpubkey,u8,final_scriptpubkey_len +msgdata,channeld_init_eltoo,flags,u8, +msgdata,channeld_init_eltoo,init_peer_pkt_len,u16, +msgdata,channeld_init_eltoo,init_peer_pkt,u8,init_peer_pkt_len +msgdata,channeld_init_eltoo,reached_announce_depth,bool, +msgdata,channeld_init_eltoo,flen,u16, +msgdata,channeld_init_eltoo,their_features,u8,flen +msgdata,channeld_init_eltoo,upfront_shutdown_script_len,u16, +msgdata,channeld_init_eltoo,upfront_shutdown_script,u8,upfront_shutdown_script_len +msgdata,channeld_init_eltoo,remote_ann_node_sig,?secp256k1_ecdsa_signature, +msgdata,channeld_init_eltoo,remote_ann_bitcoin_sig,?secp256k1_ecdsa_signature, +msgdata,channeld_init_eltoo,desired_type,channel_type, +msgdata,channeld_init_eltoo,dev_fast_gossip,bool, +msgdata,channeld_init_eltoo,dev_fail_process_onionpacket,bool, +msgdata,channeld_init_eltoo,dev_disable_commit,?u32, +msgdata,channeld_init_eltoo,reestablish_only,bool, +msgdata,channeld_init_eltoo,channel_update_len,u16, +msgdata,channeld_init_eltoo,channel_update,u8,channel_update_len + # When we receive funding_locked. msgtype,channeld_got_funding_locked_eltoo,1079 @@ -309,6 +370,31 @@ msgdata,channeld_got_ack,updatenum,u64, # RCVD_ADD_ACK, RCVD_REMOVE_ACK msgdata,channeld_got_ack,num_changed,u16, msgdata,channeld_got_ack,changed,changed_htlc,num_changed +msgdata,channeld_got_ack,update_sig,bip340sig, # Wait for reply, to make sure it's on disk before we continue # (eg. if we sent another commitment_signed, that would implicitly ack). msgtype,channeld_got_ack_reply,1122 + +# Peer told us that channel is shutting down +msgtype,channeld_got_shutdown_eltoo,1084 +msgdata,channeld_got_shutdown_eltoo,scriptpubkey_len,u16, +msgdata,channeld_got_shutdown_eltoo,scriptpubkey,u8,scriptpubkey_len +msgdata,channeld_got_shutdown_eltoo,wrong_funding,?bitcoin_outpoint, + +# When we send a update_signed message, tell master. +msgtype,channeld_sending_updatesig,1080 +msgdata,channeld_sending_updatesig,update_num,u64, +# SENT_ADD_UPDATE, SENT_REMOVE_ACK, SENT_ADD_ACK, SENT_REMOVE_UPDATE +msgdata,channeld_sending_updatesig,num_changed,u16, +msgdata,channeld_sending_updatesig,changed,changed_htlc,num_changed +msgdata,channeld_sending_updatesig,our_update_p_sig,partial_sig, +msgdata,channeld_sending_updatesig,session,musig_session, + +# Wait for reply, to make sure it's on disk before we send commit. +msgtype,channeld_sending_updatesig_reply,1180 + +# Peer told us that channel is shutting down +msgtype,channeld_got_shutdown_eltoo,1084 +msgdata,channeld_got_shutdown_eltoo,scriptpubkey_len,u16, +msgdata,channeld_got_shutdown_eltoo,scriptpubkey,u8,scriptpubkey_len +msgdata,channeld_got_shutdown_eltoo,wrong_funding,?bitcoin_outpoint, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index b77a51eb5b16..097eaa70cc71 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -147,7 +147,6 @@ struct eltoo_peer { /* Number of update_signed(_ack) messages received by peer */ u64 updates_received; - bool announce_depth_reached; bool channel_local_active; @@ -170,10 +169,10 @@ struct eltoo_peer { u8 *channel_update; }; -static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer); -static void start_commit_timer(struct peer *peer); +static u8 *create_channel_announcement(const tal_t *ctx, struct eltoo_peer *peer); +static void start_update_timer(struct eltoo_peer *peer); -static void billboard_update(const struct peer *peer) +static void billboard_update(const struct eltoo_peer *peer) { const char *update = billboard_message(tmpctx, peer->funding_locked, peer->have_sigs, @@ -200,7 +199,7 @@ const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES) } #if EXPERIMENTAL_FEATURES -static void maybe_send_stfu(struct peer *peer) +static void maybe_send_stfu(struct eltoo_peer *peer) { if (!peer->stfu) return; @@ -219,7 +218,7 @@ static void maybe_send_stfu(struct peer *peer) } } -static void handle_stfu(struct peer *peer, const u8 *stfu) +static void handle_stfu(struct eltoo_peer *peer, const u8 *stfu) { struct channel_id channel_id; u8 remote_initiated; @@ -275,7 +274,7 @@ static void handle_stfu(struct peer *peer, const u8 *stfu) } /* Returns true if we queued this for later handling (steals if true) */ -static bool handle_master_request_later(struct peer *peer, const u8 *msg) +static bool handle_master_request_later(struct eltoo_peer *peer, const u8 *msg) { if (peer->stfu) { msg_enqueue(peer->update_queue, take(msg)); @@ -294,7 +293,7 @@ static bool match_type(const u8 *t1, const u8 *t2) return featurebits_eq(t1, t2); } -static void set_channel_type(struct channel *channel, const u8 *type) +static void set_channel_type(struct eltoo_channel *channel, const u8 *type) { const struct channel_type *cur = channel->type; @@ -319,7 +318,7 @@ static bool handle_master_request_later(struct peer *peer, const u8 *msg) return false; } -static void maybe_send_stfu(struct peer *peer) +static void maybe_send_stfu(struct eltoo_peer *peer) { } #endif @@ -327,7 +326,7 @@ static void maybe_send_stfu(struct peer *peer) /* Tell gossipd to create channel_update (then it goes into * gossip_store, then streams out to peers, or sends it directly if * it's a private channel) */ -static void send_channel_update(struct peer *peer, int disable_flag) +static void send_channel_update(struct eltoo_peer *peer, int disable_flag) { u8 *msg; @@ -353,7 +352,7 @@ static void send_channel_update(struct peer *peer, int disable_flag) /* Tell gossipd and the other side what parameters we expect should * they route through us */ -static void send_channel_initial_update(struct peer *peer) +static void send_channel_initial_update(struct eltoo_peer *peer) { send_channel_update(peer, 0); } @@ -368,7 +367,7 @@ static void send_channel_initial_update(struct peer *peer) * channel_update is not preceeded by a channel_announcement and won't make much * sense to other nodes, so we don't tell gossipd about it. */ -static void make_channel_local_active(struct peer *peer) +static void make_channel_local_active(struct eltoo_peer *peer) { u8 *msg; const u8 *annfeatures = get_agreed_channelfeatures(tmpctx, @@ -389,7 +388,7 @@ static void make_channel_local_active(struct peer *peer) send_channel_initial_update, peer)); } -static void send_announcement_signatures(struct peer *peer) +static void send_announcement_signatures(struct eltoo_peer *peer) { /* First 2 + 256 byte are the signatures and msg type, skip them */ size_t offset = 258; @@ -444,7 +443,7 @@ static void send_announcement_signatures(struct peer *peer) /* Tentatively create a channel_announcement, possibly with invalid * signatures. The signatures need to be collected first, by asking * the HSM and by exchanging announcement_signature messages. */ -static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer) +static u8 *create_channel_announcement(const tal_t *ctx, struct eltoo_peer *peer) { int first, second; u8 *cannounce, *features @@ -475,7 +474,7 @@ static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer) } /* Once we have both, we'd better make sure we agree what they are! */ -static void check_short_ids_match(struct peer *peer) +static void check_short_ids_match(struct eltoo_peer *peer) { assert(peer->have_sigs[LOCAL]); assert(peer->have_sigs[REMOTE]); @@ -491,7 +490,7 @@ static void check_short_ids_match(struct peer *peer) &peer->short_channel_ids[REMOTE])); } -static void announce_channel(struct peer *peer) +static void announce_channel(struct eltoo_peer *peer) { u8 *cannounce; @@ -503,7 +502,7 @@ static void announce_channel(struct peer *peer) send_channel_update(peer, 0); } -static void channel_announcement_negotiate(struct peer *peer) +static void channel_announcement_negotiate(struct eltoo_peer *peer) { /* Don't do any announcement work if we're shutting down */ if (peer->shutdown_sent[LOCAL]) @@ -673,85 +672,6 @@ static void handle_peer_add_htlc(struct eltoo_peer *peer, const u8 *msg) channel_add_err_name(add_err)); } -static void handle_peer_feechange(struct peer *peer, const u8 *msg) -{ - struct channel_id channel_id; - u32 feerate; - - fromwire_update_fee(msg, &channel_id, &feerate); - peer_failed_warn(peer->pps, &peer->channel_id, - "update_fee isn't allowed in eltoo %s", tal_hex(msg, msg)); -} - -static void handle_peer_blockheight_change(struct peer *peer, const u8 *msg) -{ - struct channel_id channel_id; - u32 blockheight, current; - - if (!fromwire_update_blockheight(msg, &channel_id, &blockheight)) - peer_failed_warn(peer->pps, &peer->channel_id, - "Bad update_blockheight %s", - tal_hex(msg, msg)); - - /* BOLT- #2: - * A receiving node: - * ... - * - if the sender is not the initiator: - * - MUST fail the channel. - */ - if (peer->channel->opener != REMOTE) - peer_failed_warn(peer->pps, &peer->channel_id, - "update_blockheight from non-opener?"); - - current = get_blockheight(peer->channel->blockheight_states, - peer->channel->opener, LOCAL); - - status_debug("update_blockheight %u. last update height %u," - " our current height %u", - blockheight, current, peer->our_blockheight); - - /* BOLT- #2: - * A receiving node: - * - if the `update_blockheight` is less than the last - * received `blockheight`: - * - SHOULD fail the channel. - * ... - * - if `blockheight` is more than 1008 blocks behind - * the current blockheight: - * - SHOULD fail the channel - */ - /* Overflow check */ - if (blockheight + 1008 < blockheight) - peer_failed_warn(peer->pps, &peer->channel_id, - "blockheight + 1008 overflow (%u)", - blockheight); - - /* If they're behind the last one they sent, we just warn and - * reconnect, as they might be catching up */ - /* FIXME: track for how long they send backwards blockheight? */ - if (blockheight < current) - peer_failed_warn(peer->pps, &peer->channel_id, - "update_blockheight %u older than previous %u", - blockheight, current); - - /* BOLT- #2: - * A receiving node: - * ... - * - if `blockheight` is more than 1008 blocks behind - * the current blockheight: - * - SHOULD fail the channel - */ - assert(blockheight < blockheight + 1008); - if (blockheight + 1008 < peer->our_blockheight) - peer_failed_err(peer->pps, &peer->channel_id, - "update_blockheight %u outside" - " permissible range", blockheight); - - channel_update_blockheight(peer->channel, blockheight); - - status_debug("peer updated blockheight to %u", blockheight); -} - static struct changed_htlc *changed_htlc_arr(const tal_t *ctx, const struct htlc **changed_htlcs) { @@ -766,25 +686,20 @@ static struct changed_htlc *changed_htlc_arr(const tal_t *ctx, return changed; } -static u8 *sending_commitsig_msg(const tal_t *ctx, - u64 remote_commit_index, - struct penalty_base *pbase, - const struct fee_states *fee_states, - const struct height_states *blockheight_states, +static u8 *sending_updatesig_msg(const tal_t *ctx, + u64 update_index, const struct htlc **changed_htlcs, - const struct bitcoin_signature *commit_sig, - const struct bitcoin_signature *htlc_sigs) + const struct partial_sig *our_update_psig, + const struct musig_session *session) { struct changed_htlc *changed; u8 *msg; - /* We tell master what (of our) HTLCs peer will now be + /* We tell master what (of our) HTLCs we will be * committed to. */ changed = changed_htlc_arr(tmpctx, changed_htlcs); - msg = towire_channeld_sending_commitsig(ctx, remote_commit_index, - pbase, fee_states, - blockheight_states, changed, - commit_sig, htlc_sigs); + msg = towire_channeld_sending_updatesig(ctx, update_index, + changed, our_update_psig, session); return msg; } @@ -794,7 +709,7 @@ static bool shutdown_complete(const struct peer *peer) && peer->shutdown_sent[REMOTE] && num_channel_htlcs(peer->channel) == 0 /* We could be awaiting revoke-and-ack for a feechange */ - && peer->revocations_received == peer->next_index[REMOTE] - 1; + && peer->revocations_received == peer->next_index - 1; } @@ -807,7 +722,7 @@ static bool shutdown_complete(const struct peer *peer) * - MUST NOT send a `shutdown`. */ /* So we only call this after reestablish or immediately after sending commit */ -static void maybe_send_shutdown(struct peer *peer) +static void maybe_send_shutdown(struct eltoo_peer *peer) { u8 *msg; struct tlv_shutdown_tlvs *tlvs; @@ -1004,18 +919,13 @@ static secp256k1_ecdsa_signature *raw_sigs(const tal_t *ctx, return raw; } -static void send_commit(struct peer *peer) +static void send_update(struct eltoo_peer *peer) { u8 *msg; const struct htlc **changed_htlcs; - struct bitcoin_signature commit_sig, *htlc_sigs; - struct bitcoin_tx **txs; - const u8 *funding_wscript; + struct bitcoin_tx **update_and_settle_txs; const struct htlc **htlc_map; struct wally_tx_output *direct_outputs[NUM_SIDES]; - struct penalty_base *pbase; - u32 our_blockheight; - u32 feerate_target; #if DEVELOPER if (peer->dev_disable_commit && !*peer->dev_disable_commit) { @@ -1026,19 +936,19 @@ static void send_commit(struct peer *peer) /* FIXME: Document this requirement in BOLT 2! */ /* We can't send two commits in a row. */ - if (peer->revocations_received != peer->next_index[REMOTE] - 1) { - assert(peer->revocations_received - == peer->next_index[REMOTE] - 2); + if (peer->updates_received != peer->next_index - 1) { + assert(peer->updates_received + == peer->next_index - 2); peer->commit_timer_attempts++; /* Only report this in extreme cases */ if (peer->commit_timer_attempts % 100 == 0) status_debug("Can't send commit:" - " waiting for revoke_and_ack with %" + " waiting for update_ack with %" PRIu64" attempts", peer->commit_timer_attempts); /* Mark this as done and try again. */ peer->commit_timer = NULL; - start_commit_timer(peer); + start_update_timer(peer); return; } @@ -1061,7 +971,7 @@ static void send_commit(struct peer *peer) * any updates. */ changed_htlcs = tal_arr(tmpctx, const struct htlc *, 0); - if (!channel_sending_commit(peer->channel, &changed_htlcs)) { + if (!channel_sending_update(peer->channel, &changed_htlcs)) { status_debug("Can't send commit: nothing to send"); /* Covers the case where we've just been told to shutdown. */ @@ -1071,23 +981,22 @@ static void send_commit(struct peer *peer) return; } - txs = channel_txs(tmpctx, &htlc_map, direct_outputs, - &funding_wscript, peer->channel, &peer->remote_per_commit, - peer->next_index[REMOTE], REMOTE); - - htlc_sigs = - calc_commitsigs(tmpctx, peer, txs, funding_wscript, htlc_map, - peer->next_index[REMOTE], &commit_sig); + update_and_settle_txs = eltoo_channel_txs(tmpctx, &htlc_map, direct_outputs, + peer->channel, + peer->next_index, REMOTE); - if (direct_outputs[LOCAL] != NULL) { - pbase = penalty_base_new(tmpctx, peer->next_index[REMOTE], - txs[0], direct_outputs[LOCAL]); + msg = towire_hsmd_psign_update_tx(tmpctx, + &peer->channel_id, + update_and_settle_txs[0], + update_and_settle_txs[1], + &peer->channel->eltoo_keyset.other_funding_pubkey, + &peer->channel->eltoo_keyset.other_next_nonce); - /* Add the penalty_base to our in-memory list as well, so we - * can find it again later. */ - tal_arr_expand(&peer->pbases, tal_steal(peer, pbase)); - } else - pbase = NULL; + msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.self_next_nonce)) + status_failed(STATUS_FAIL_HSM_IO, + "Reading psign_update_tx reply: %s", + tal_hex(tmpctx, msg)); #if DEVELOPER if (peer->dev_disable_commit) { @@ -1097,37 +1006,33 @@ static void send_commit(struct peer *peer) } #endif - status_debug("Telling master we're about to commit..."); + status_debug("Telling master we're about to update..."); /* Tell master to save this next commit to database, then wait. */ - msg = sending_commitsig_msg(NULL, peer->next_index[REMOTE], - pbase, - peer->channel->fee_states, - peer->channel->blockheight_states, + msg = sending_updatesig_msg(NULL, peer->next_index, changed_htlcs, - &commit_sig, - htlc_sigs); + &peer->channel->eltoo_keyset.self_psig, + &peer->channel->eltoo_keyset.session); /* Message is empty; receiving it is the point. */ master_wait_sync_reply(tmpctx, peer, take(msg), - WIRE_CHANNELD_SENDING_COMMITSIG_REPLY); + WIRE_CHANNELD_SENDING_UPDATESIG_REPLY); - status_debug("Sending commit_sig with %zu htlc sigs", - tal_count(htlc_sigs)); + status_debug("Sending update_sig"); - peer->next_index[REMOTE]++; + peer->next_index++; - msg = towire_commitment_signed(NULL, &peer->channel_id, - &commit_sig.s, - raw_sigs(tmpctx, htlc_sigs)); + msg = towire_update_signed(NULL, &peer->channel_id, + &peer->channel->eltoo_keyset.self_psig, + &peer->channel->eltoo_keyset.self_next_nonce); peer_write(peer->pps, take(msg)); maybe_send_shutdown(peer); /* Timer now considered expired, you can add a new one. */ peer->commit_timer = NULL; - start_commit_timer(peer); + start_update_timer(peer); } -static void start_commit_timer(struct eltoo_peer *peer) +static void start_update_timer(struct eltoo_peer *peer) { /* Already armed? */ if (peer->commit_timer) @@ -1136,12 +1041,12 @@ static void start_commit_timer(struct eltoo_peer *peer) peer->commit_timer_attempts = 0; peer->commit_timer = new_reltimer(&peer->timers, peer, time_from_msec(peer->commit_msec), - send_commit, peer); + send_update, peer); } -static u8 *make_update_signed_ack_msg(const struct peer *peer, struct partial_sig *our_update_psig) +static u8 *make_update_signed_ack_msg(const struct peer *peer) { - return towire_update_signed_ack(peer, &peer->channel_id, our_update_psig, &peer->channel->eltoo_keyset.next_nonce); + return towire_update_signed_ack(peer, &peer->channel_id, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.self_next_nonce); } /* Convert changed htlcs into parts which lightningd expects. */ @@ -1159,7 +1064,7 @@ static void marshall_htlc_info(const tal_t *ctx, for (size_t i = 0; i < tal_count(changed_htlcs); i++) { const struct htlc *htlc = changed_htlcs[i]; - if (htlc->state == RCVD_ADD_COMMIT) { + if (htlc->eltoo_state == RCVD_ADD_UPDATE) { struct added_htlc a; a.id = htlc->id; @@ -1176,7 +1081,7 @@ static void marshall_htlc_info(const tal_t *ctx, a.blinding = NULL; a.fail_immediate = htlc->fail_immediate; tal_arr_expand(added, a); - } else if (htlc->state == RCVD_REMOVE_COMMIT) { + } else if (htlc->eltoo_state == RCVD_REMOVE_UPDATE) { if (htlc->r) { struct fulfilled_htlc f; assert(!htlc->failed); @@ -1189,17 +1094,17 @@ static void marshall_htlc_info(const tal_t *ctx, } } else { struct changed_htlc c; - assert(htlc->state == RCVD_REMOVE_ACK_COMMIT - || htlc->state == RCVD_ADD_ACK_COMMIT); + assert(htlc->eltoo_state == RCVD_REMOVE_ACK + || htlc->eltoo_state == RCVD_ADD_ACK); c.id = htlc->id; - c.newstate = htlc->state; + c.eltoo_newstate = htlc->eltoo_state; tal_arr_expand(changed, c); } } } -static void send_update_sign_ack(struct peer *peer, +static void send_update_sign_ack(struct eltoo_peer *peer, const struct htlc **changed_htlcs, const struct partial_sig *our_update_psig, const struct partial_sig *their_update_psig, @@ -1224,23 +1129,23 @@ static void send_update_sign_ack(struct peer *peer, &failed, &added); - msg = make_update_signed_ack_msg(peer, &our_update_psig); + msg = make_update_signed_ack_msg(peer); /* From now on we apply changes to the next commitment */ - peer->next_index[LOCAL]++; + peer->next_index++; /* If this queues more changes on the other end, send commit. */ /* FIXME I don't think this can happen with eltoo/turn taking? if (channel_sending_revoke_and_ack(peer->channel)) { status_debug("revoke_and_ack made pending: commit timer"); - start_commit_timer(peer); + start_update_timer(peer); } */ /* Tell master daemon about update_sig (and by implication, that we're * sending update_sig_ack), then wait for it to ack. */ msg_for_master = towire_channeld_got_updatesig(NULL, - peer->next_index[LOCAL] - 1, + peer->next_index - 1, our_update_psig, their_update_psig, session, @@ -1253,7 +1158,7 @@ static void send_update_sign_ack(struct peer *peer, master_wait_sync_reply(tmpctx, peer, take(msg_for_master), WIRE_CHANNELD_GOT_UPDATESIG_REPLY); - /* Now we can finally send revoke_and_ack to peer */ + /* Now we can finally send update_signed_ack to peer */ peer_write(peer->pps, take(msg)); } @@ -1268,9 +1173,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) struct pubkey remote_htlckey; */ struct bitcoin_tx **update_and_settle_txs; - struct partial_sig their_update_psig, our_update_psig; struct bip340sig update_sig; - struct nonce next_nonce; const struct htlc **htlc_map, **changed_htlcs; const u8 *funding_wscript; size_t i; @@ -1287,15 +1190,15 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) * include any updates. */ status_debug("Oh hi LND! Empty commitment at #%"PRIu64, - peer->next_index[LOCAL]); - if (peer->last_empty_commitment == peer->next_index[LOCAL] - 1) + peer->next_index); + if (peer->last_empty_commitment == peer->next_index - 1) peer_failed_warn(peer->pps, &peer->channel_id, "update_signed with no changes (again!)"); - peer->last_empty_commitment = peer->next_index[LOCAL]; + peer->last_empty_commitment = peer->next_index; } if (!fromwire_update_signed(tmpctx, msg, - &channel_id, &their_update_psig, &next_nonce)) + &channel_id, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad update_signed %s", tal_hex(msg, msg)); @@ -1304,9 +1207,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) update_and_settle_txs = eltoo_channel_txs(tmpctx, &htlc_map, /* direct_outputs */ NULL, peer->channel, - peer->next_index[LOCAL], LOCAL); - - /* FIXME we need to finish the MuSig sig/verification, and send ACK ... */ + peer->next_index, LOCAL); /* We sign the same update transaction as peer should have signed */ msg = towire_hsmd_psign_update_tx(NULL, @@ -1317,15 +1218,15 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* Before replying, make sure signature is correct */ msg = towire_hsmd_combine_psig(NULL, &peer->channel_id, - &our_update_psig, - &their_update_psig, + &peer->channel->eltoo_keyset.self_psig, + &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.session update_and_settle_txs[0], update_and_settle_txs[1], @@ -1337,10 +1238,11 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); } + /* Tell master about this exchange, then the peer */ send_update_sign_ack(peer, changed_htlcs, - &our_update_psig, - &their_update_psig, + &peer->channel->eltoo_keyset.self_psig, + &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.session, update_and_settle_txs[0], update_and_settle_txs[1], @@ -1351,9 +1253,10 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) } -static u8 *got_ack_msg(struct peer *peer, +static u8 *got_signed_ack_msg(struct peer *peer, u64 update_num, - const struct htlc **changed_htlcs) + const struct htlc **changed_htlcs, + const bip340sig *update_sig) { u8 *msg; struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); @@ -1368,12 +1271,12 @@ static u8 *got_ack_msg(struct peer *peer, htlc_state_name(htlc->state)); c.id = changed_htlcs[i]->id; - c.newstate = changed_htlcs[i]->state; + c.eltoo_newstate = changed_htlcs[i]->eltoo_state; tal_arr_expand(&changed, c); } msg = towire_channeld_got_ack(peer, update_num, - changed); + changed, update_sig); return msg; } @@ -1384,6 +1287,9 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) const u8 *comb_msg; struct bip340sig update_sig; const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); + struct bitcoin_tx **update_and_settle_txs; + const struct htlc **htlc_map; + struct wally_tx_output *direct_outputs[NUM_SIDES]; if (!fromwire_update_signed_ack(msg, &channel_id, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) { @@ -1391,14 +1297,18 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) "Bad update_signed_ack %s", tal_hex(msg, msg)); } + /* We shouldn't allow any updates until we complete this round, so reconstruct latest tx */ + update_and_settle_txs = eltoo_channel_txs(tmpctx, &htlc_map, /* direct_outputs */ NULL, + peer->channel, + peer->next_index, REMOTE); + comb_msg = towire_hsmd_combine_psig(tmpctx, &channel_id, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.session, - /* FIXME where should these proposed txns live? vs state */ - &peer->channel->proposed_update_tx, - &peer->channel->proposed_settle_tx, + update_and_settle_txs[0], + update_and_settle_txs[1], &peer->channel->eltoo_keyset.inner_pubkey); @@ -1416,9 +1326,9 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) status_debug("No commits outstanding after recv update_sign_ack"); } - /* Tell master about things this locks in, wait for response */ - msg = got_ack_msg(peer, peer->next_index++, - changed_htlcs); + /* Tell master about things this locks in(and final signature), wait for response */ + msg = got_signed_ack_msg(peer, peer->next_index++, + changed_htlcs, &update_sig); master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNELD_GOT_ACK_REPLY); @@ -1428,7 +1338,7 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) /* We may now be quiescent on our side. */ maybe_send_stfu(peer); - start_commit_timer(peer); + start_update_timer(peer); } static void handle_peer_fulfill_htlc(struct eltoo_peer *peer, const u8 *msg) @@ -1449,7 +1359,7 @@ static void handle_peer_fulfill_htlc(struct eltoo_peer *peer, const u8 *msg) switch (e) { case CHANNEL_ERR_REMOVE_OK: /* FIXME: We could send preimages to master immediately. */ - start_commit_timer(peer); + start_update_timer(peer); return; /* These shouldn't happen, because any offered HTLC (which would give * us the preimage) should have timed out long before. If we @@ -1466,7 +1376,7 @@ static void handle_peer_fulfill_htlc(struct eltoo_peer *peer, const u8 *msg) abort(); } -static void handle_peer_fail_htlc(struct peer *peer, const u8 *msg) +static void handle_peer_fail_htlc(struct eltoo_peer *peer, const u8 *msg) { struct channel_id channel_id; u64 id; @@ -1489,7 +1399,7 @@ static void handle_peer_fail_htlc(struct peer *peer, const u8 *msg) f->id = id; f->sha256_of_onion = NULL; f->onion = new_onionreply(f, take(reason)); - start_commit_timer(peer); + start_update_timer(peer); return; } case CHANNEL_ERR_NO_SUCH_ID: @@ -1505,7 +1415,7 @@ static void handle_peer_fail_htlc(struct peer *peer, const u8 *msg) abort(); } -static void handle_peer_fail_malformed_htlc(struct peer *peer, const u8 *msg) +static void handle_peer_fail_malformed_htlc(struct eltoo_peer *peer, const u8 *msg) { struct channel_id channel_id; u64 id; @@ -1544,7 +1454,7 @@ static void handle_peer_fail_malformed_htlc(struct peer *peer, const u8 *msg) f->onion = NULL; f->sha256_of_onion = tal_dup(f, struct sha256, &sha256_of_onion); f->badonion = failure_code; - start_commit_timer(peer); + start_update_timer(peer); return; case CHANNEL_ERR_NO_SUCH_ID: case CHANNEL_ERR_ALREADY_FULFILLED: @@ -1558,7 +1468,7 @@ static void handle_peer_fail_malformed_htlc(struct peer *peer, const u8 *msg) abort(); } -static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) +static void handle_peer_shutdown(struct eltoo_peer *peer, const u8 *shutdown) { struct channel_id channel_id; u8 *scriptpubkey; @@ -1566,10 +1476,11 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) struct bitcoin_outpoint *wrong_funding; /* Disable the channel. */ + /* FIXME Re-enable when gossip worked on send_channel_update(peer, ROUTING_FLAGS_DISABLED); - - if (!fromwire_shutdown(tmpctx, shutdown, &channel_id, &scriptpubkey, - &tlvs)) + */ + if (!fromwire_shutdown_eltoo(tmpctx, shutdown, &channel_id, &scriptpubkey, + &peer->channel->eltoo_keyset.other_next_nonce, &tlvs)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad shutdown %s", tal_hex(peer, shutdown)); @@ -1619,8 +1530,8 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) peer_failed_warn(peer->pps, &peer->channel_id, "No shutdown wrong_funding" " for channels we opened!"); - if (peer->next_index[REMOTE] != 1 - || peer->next_index[LOCAL] != 1) + if (peer->next_index != 1 + || peer->next_index != 1) peer_failed_warn(peer->pps, &peer->channel_id, "No shutdown wrong_funding" " for used channels!"); @@ -1636,8 +1547,8 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) /* Tell master: we don't have to wait because on reconnect other end * will re-send anyway. */ wire_sync_write(MASTER_FD, - take(towire_channeld_got_shutdown(NULL, scriptpubkey, - wrong_funding))); + take(towire_channeld_got_shutdown_eltoo(NULL, scriptpubkey, + wrong_funding, &peer->channel->eltoo_keyset.other_next_nonce))); peer->shutdown_sent[REMOTE] = true; /* BOLT #2: @@ -1650,62 +1561,34 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) */ if (!peer->shutdown_sent[LOCAL]) { peer->send_shutdown = true; - start_commit_timer(peer); + start_update_timer(peer); } billboard_update(peer); } -static void handle_unexpected_tx_sigs(struct peer *peer, const u8 *msg) -{ - const struct witness_stack **ws; - struct channel_id cid; - struct bitcoin_txid txid; - - /* In a rare case, a v2 peer may re-send a tx_sigs message. - * This happens when they've/we've exchanged funding_locked, - * but they did not receive our funding_locked. */ - if (!fromwire_tx_signatures(tmpctx, msg, &cid, &txid, - cast_const3(struct witness_stack ***, &ws))) - peer_failed_warn(peer->pps, &peer->channel_id, - "Bad tx_signatures %s", - tal_hex(msg, msg)); - - status_info("Unexpected `tx_signatures` from peer. %s", - peer->tx_sigs_allowed ? "Allowing." : "Failing."); - - if (!peer->tx_sigs_allowed) - peer_failed_warn(peer->pps, &peer->channel_id, - "Unexpected `tx_signatures`"); - - peer->tx_sigs_allowed = false; -} - static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) { struct channel_id channel_id; - u64 next_commitment_number; - u64 next_revocation_number; - struct secret your_last_per_commitment_secret; - struct pubkey my_current_per_commitment_point; + u64 last_update_number; + struct partial_sig their_last_psig; + struct nonce their_next_nonce; #if EXPERIMENTAL_FEATURES struct tlv_channel_reestablish_tlvs *tlvs; #endif - if (!fromwire_channel_reestablish + if (!fromwire_channel_reestablish_eltoo #if EXPERIMENTAL_FEATURES (tmpctx, msg, &channel_id, - &next_commitment_number, - &next_revocation_number, - &your_last_per_commitment_secret, - &my_current_per_commitment_point, + &last_update_number, + &their_last_psig, + &their_next_nonce, &tlvs) #else (msg, &channel_id, - &next_commitment_number, - &next_revocation_number, - &your_last_per_commitment_secret, - &my_current_per_commitment_point) + &last_update_number, + &their_last_psig, + &their_next_nonce) #endif ) peer_failed_warn(peer->pps, &peer->channel_id, @@ -1802,7 +1685,6 @@ static void peer_in(struct peer *elto_peer, const u8 *msg) case WIRE_UPDATE_FULFILL_HTLC: handle_peer_fulfill_htlc(peer, msg); return; - /* FIXME below */ case WIRE_UPDATE_FAIL_HTLC: handle_peer_fail_htlc(peer, msg); return; @@ -1812,6 +1694,7 @@ static void peer_in(struct peer *elto_peer, const u8 *msg) case WIRE_SHUTDOWN: handle_peer_shutdown(peer, msg); return; + /* FIXME below */ case WIRE_UPDATE_NOOP: case WIRE_YIELD: /* FIXME handle these messages */ @@ -1836,13 +1719,11 @@ static void peer_in(struct peer *elto_peer, const u8 *msg) case WIRE_OPEN_CHANNEL2: case WIRE_ACCEPT_CHANNEL2: case WIRE_TX_SIGNATURES: - handle_unexpected_tx_sigs(peer, msg); - return; case WIRE_INIT_RBF: case WIRE_ACK_RBF: - break; - case WIRE_CHANNEL_REESTABLISH: + break; + case WIRE_CHANNEL_REESTABLISH_ELTOO: handle_unexpected_reestablish(peer, msg); return; @@ -1882,15 +1763,7 @@ static void peer_in(struct peer *elto_peer, const u8 *msg) type, peer_wire_name(type)); } -static void resend_revoke(struct peer *peer) -{ - struct pubkey point; - /* Current commit is peer->next_index[LOCAL]-1, revoke prior */ - u8 *msg = make_revocation_msg(peer, peer->next_index[LOCAL]-2, &point); - peer_write(peer->pps, take(msg)); -} - -static void send_fail_or_fulfill(struct peer *peer, const struct htlc *h) +static void send_fail_or_fulfill(struct eltoo_peer *peer, const struct htlc *h) { u8 *msg; @@ -1929,309 +1802,6 @@ static int cmp_changed_htlc_id(const struct changed_htlc *a, return 0; } -static void resend_commitment(struct peer *peer, struct changed_htlc *last) -{ - size_t i; - struct bitcoin_signature commit_sig, *htlc_sigs; - u8 *msg; - struct bitcoin_tx **txs; - const u8 *funding_wscript; - const struct htlc **htlc_map; - struct wally_tx_output *direct_outputs[NUM_SIDES]; - - status_debug("Retransmitting commitment, feerate LOCAL=%u REMOTE=%u," - " blockheight LOCAL=%u REMOTE=%u", - channel_feerate(peer->channel, LOCAL), - channel_feerate(peer->channel, REMOTE), - channel_blockheight(peer->channel, LOCAL), - channel_blockheight(peer->channel, REMOTE)); - - /* Note that HTLCs must be *added* in order. Simplest thing to do - * is to sort them all into ascending ID order here (we could do - * this when we save them in channel_sending_commit, but older versions - * won't have them sorted in the db, so doing it here is better). */ - asort(last, tal_count(last), cmp_changed_htlc_id, NULL); - - /* BOLT #2: - * - * - if `next_commitment_number` is equal to the commitment - * number of the last `commitment_signed` message the receiving node - * has sent: - * - MUST reuse the same commitment number for its next - * `commitment_signed`. - */ - /* In our case, we consider ourselves already committed to this, so - * retransmission is simplest. */ - /* We need to send fulfills/failures before adds, so we split them - * up into two loops -- this is the 'fulfill/fail' loop */ - for (i = 0; i < tal_count(last); i++) { - const struct htlc *h; - - h = channel_get_htlc(peer->channel, - htlc_state_owner(last[i].newstate), - last[i].id); - /* I think this can happen if we actually received revoke_and_ack - * then they asked for a retransmit */ - if (!h) - peer_failed_warn(peer->pps, &peer->channel_id, - "Can't find HTLC %"PRIu64" to resend", - last[i].id); - - if (h->state == SENT_REMOVE_COMMIT) - send_fail_or_fulfill(peer, h); - } - /* We need to send fulfills/failures before adds, so we split them - * up into two loops -- this is the 'add' loop */ - for (i = 0; i < tal_count(last); i++) { - const struct htlc *h; - - h = channel_get_htlc(peer->channel, - htlc_state_owner(last[i].newstate), - last[i].id); - - /* I think this can happen if we actually received revoke_and_ack - * then they asked for a retransmit */ - if (!h) - peer_failed_warn(peer->pps, &peer->channel_id, - "Can't find HTLC %"PRIu64" to resend", - last[i].id); - - if (h->state == SENT_ADD_COMMIT) { -#if EXPERIMENTAL_FEATURES - struct tlv_update_add_tlvs *tlvs; - if (h->blinding) { - tlvs = tlv_update_add_tlvs_new(tmpctx); - tlvs->blinding = tal_dup(tlvs, struct pubkey, - h->blinding); - } else - tlvs = NULL; -#endif - u8 *msg = towire_update_add_htlc(NULL, &peer->channel_id, - h->id, h->amount, - &h->rhash, - abs_locktime_to_blocks( - &h->expiry), - h->routing -#if EXPERIMENTAL_FEATURES - , tlvs -#endif - ); - peer_write(peer->pps, take(msg)); - } - } - - /* Make sure they have the correct fee and blockheight. */ - if (peer->channel->opener == LOCAL) { - msg = towire_update_fee(NULL, &peer->channel_id, - channel_feerate(peer->channel, REMOTE)); - peer_write(peer->pps, take(msg)); - - if (peer->channel->lease_expiry > 0) { - msg = towire_update_blockheight(NULL, &peer->channel_id, - channel_blockheight(peer->channel, REMOTE)); - peer_write(peer->pps, take(msg)); - } - } - - /* Re-send the commitment_signed itself. */ - txs = channel_txs(tmpctx, &htlc_map, direct_outputs, - &funding_wscript, peer->channel, &peer->remote_per_commit, - peer->next_index[REMOTE]-1, REMOTE); - - htlc_sigs = calc_commitsigs(tmpctx, peer, txs, funding_wscript, htlc_map, peer->next_index[REMOTE]-1, - &commit_sig); - msg = towire_commitment_signed(NULL, &peer->channel_id, - &commit_sig.s, - raw_sigs(tmpctx, htlc_sigs)); - peer_write(peer->pps, take(msg)); - - /* If we have already received the revocation for the previous, the - * other side shouldn't be asking for a retransmit! */ - if (peer->revocations_received != peer->next_index[REMOTE] - 2) - status_unusual("Retransmitted commitment_signed %"PRIu64 - " but they already send revocation %"PRIu64"?", - peer->next_index[REMOTE]-1, - peer->revocations_received); -} - -/* BOLT #2: - * - * A receiving node: - * - if `option_static_remotekey` applies to the commitment transaction: - * - if `next_revocation_number` is greater than expected above, AND - * `your_last_per_commitment_secret` is correct for that - * `next_revocation_number` minus 1: - *... - * - otherwise, if it supports `option_data_loss_protect`: - * - if `next_revocation_number` is greater than expected above, - * AND `your_last_per_commitment_secret` is correct for that - * `next_revocation_number` minus 1: - */ -static void check_future_dataloss_fields(struct peer *peer, - u64 next_revocation_number, - const struct secret *last_local_per_commit_secret, - /* This is NULL if option_static_remotekey */ - const struct pubkey *remote_current_per_commitment_point) -{ - const u8 *msg; - bool correct; - - assert(next_revocation_number > peer->next_index[LOCAL] - 1); - - msg = towire_hsmd_check_future_secret(NULL, - next_revocation_number - 1, - last_local_per_commit_secret); - msg = hsm_req(tmpctx, take(msg)); - if (!fromwire_hsmd_check_future_secret_reply(msg, &correct)) - status_failed(STATUS_FAIL_HSM_IO, - "Bad hsm_check_future_secret_reply: %s", - tal_hex(tmpctx, msg)); - - if (!correct) - peer_failed_err(peer->pps, - &peer->channel_id, - "bad future last_local_per_commit_secret: %"PRIu64 - " vs %"PRIu64, - next_revocation_number, - peer->next_index[LOCAL] - 1); - - /* Oh shit, they really are from the future! */ - peer_billboard(true, "They have future commitment number %"PRIu64 - " vs our %"PRIu64". We must wait for them to close!", - next_revocation_number, - peer->next_index[LOCAL] - 1); - - /* BOLT #2: - * - MUST NOT broadcast its commitment transaction. - * - SHOULD send an `error` to request the peer to fail the channel. - * - SHOULD store `my_current_per_commitment_point` to - * retrieve funds should the sending node broadcast its - * commitment transaction on-chain. - */ - wire_sync_write(MASTER_FD, - take(towire_channeld_fail_fallen_behind(NULL, - remote_current_per_commitment_point))); - - /* We have to send them an error to trigger dropping to chain. */ - peer_failed_err(peer->pps, &peer->channel_id, - "Awaiting unilateral close"); -} - -/* BOLT #2: - * - * A receiving node: - * - if `option_static_remotekey` applies to the commitment transaction: - * ... - * - if `your_last_per_commitment_secret` does not match the expected values: - * - SHOULD send an `error` and fail the channel. - * - otherwise, if it supports `option_data_loss_protect`: - *... - * - otherwise (`your_last_per_commitment_secret` or - * `my_current_per_commitment_point` do not match the expected values): - * - SHOULD send an `error` and fail the channel. - */ -static void check_current_dataloss_fields(struct peer *peer, - u64 next_revocation_number, - u64 next_commitment_number, - const struct secret *last_local_per_commit_secret, - /* NULL if option_static_remotekey */ - const struct pubkey *remote_current_per_commitment_point) -{ - struct secret old_commit_secret; - - /* By the time we're called, we've ensured this is a valid revocation - * number. */ - assert(next_revocation_number == peer->next_index[LOCAL] - 2 - || next_revocation_number == peer->next_index[LOCAL] - 1); - - /* By the time we're called, we've ensured we're within 1 of - * their commitment chain */ - assert(next_commitment_number == peer->next_index[REMOTE] || - next_commitment_number == peer->next_index[REMOTE] - 1); - - if (!last_local_per_commit_secret) - return; - - /* BOLT #2: - * - if `next_revocation_number` equals 0: - * - MUST set `your_last_per_commitment_secret` to all zeroes - */ - - status_debug("next_revocation_number = %"PRIu64, - next_revocation_number); - if (next_revocation_number == 0) - memset(&old_commit_secret, 0, sizeof(old_commit_secret)); - else { - struct pubkey unused; - /* This gets previous revocation number, since asking for - * commitment point N gives secret for N-2 */ - get_per_commitment_point(next_revocation_number+1, - &unused, &old_commit_secret); - } - - if (!secret_eq_consttime(&old_commit_secret, - last_local_per_commit_secret)) - peer_failed_err(peer->pps, - &peer->channel_id, - "bad reestablish: your_last_per_commitment_secret %"PRIu64 - ": %s should be %s", - next_revocation_number, - type_to_string(tmpctx, struct secret, - last_local_per_commit_secret), - type_to_string(tmpctx, struct secret, - &old_commit_secret)); - - if (!remote_current_per_commitment_point) { - status_debug("option_static_remotekey: fields are correct"); - return; - } - - status_debug("Reestablish, comparing commitments. Remote's next local commitment number" - " is %"PRIu64". Our next remote is %"PRIu64" with %"PRIu64 - " revocations received", - next_commitment_number, - peer->next_index[REMOTE], - peer->revocations_received); - - /* Either they haven't received our commitment yet, or we're up to date */ - if (next_commitment_number == peer->revocations_received + 1) { - if (!pubkey_eq(remote_current_per_commitment_point, - &peer->old_remote_per_commit)) { - peer_failed_warn(peer->pps, - &peer->channel_id, - "bad reestablish: remote's " - "my_current_per_commitment_point %"PRIu64 - "is %s; expected %s (new is %s).", - next_commitment_number - 1, - type_to_string(tmpctx, struct pubkey, - remote_current_per_commitment_point), - type_to_string(tmpctx, struct pubkey, - &peer->old_remote_per_commit), - type_to_string(tmpctx, struct pubkey, - &peer->remote_per_commit)); - } - } else { - /* We've sent a commit sig but haven't gotten a revoke+ack back */ - if (!pubkey_eq(remote_current_per_commitment_point, - &peer->remote_per_commit)) { - peer_failed_warn(peer->pps, - &peer->channel_id, - "bad reestablish: remote's " - "my_current_per_commitment_point %"PRIu64 - "is %s; expected %s (old is %s).", - next_commitment_number - 1, - type_to_string(tmpctx, struct pubkey, - remote_current_per_commitment_point), - type_to_string(tmpctx, struct pubkey, - &peer->remote_per_commit), - type_to_string(tmpctx, struct pubkey, - &peer->old_remote_per_commit)); - } - } - - status_debug("option_data_loss_protect: fields are correct"); -} - /* Older LND sometimes sends funding_locked before reestablish! */ /* ... or announcement_signatures. Sigh, let's handle whatever they send. */ static bool capture_premature_msg(const u8 ***shit_lnd_says, const u8 *msg) @@ -2270,530 +1840,15 @@ static u8 *to_bytearr(const tal_t *ctx, return ret; } -/* This is the no-tlvs version, where we can't handle old tlvs */ -static bool fromwire_channel_reestablish_notlvs(const void *p, struct channel_id *channel_id, u64 *next_commitment_number, u64 *next_revocation_number, struct secret *your_last_per_commitment_secret, struct pubkey *my_current_per_commitment_point) -{ - const u8 *cursor = p; - size_t plen = tal_count(p); - - if (fromwire_u16(&cursor, &plen) != WIRE_CHANNEL_REESTABLISH) - return false; - fromwire_channel_id(&cursor, &plen, channel_id); - *next_commitment_number = fromwire_u64(&cursor, &plen); - *next_revocation_number = fromwire_u64(&cursor, &plen); - fromwire_secret(&cursor, &plen, your_last_per_commitment_secret); - fromwire_pubkey(&cursor, &plen, my_current_per_commitment_point); - return cursor != NULL; -} -#endif - +/* FIXME Reconnect fun! Let's compile first. :) */ static void peer_reconnect(struct peer *peer, - const struct secret *last_remote_per_commit_secret, bool reestablish_only) { - struct channel_id channel_id; - /* Note: BOLT #2 uses these names! */ - u64 next_commitment_number, next_revocation_number; - bool retransmit_revoke_and_ack, retransmit_commitment_signed; - struct htlc_map_iter it; - const struct htlc *htlc; - u8 *msg; - struct pubkey my_current_per_commitment_point, - remote_current_per_commitment_point; - struct secret last_local_per_commitment_secret; - bool dataloss_protect, check_extra_fields; - const u8 **premature_msgs = tal_arr(peer, const u8 *, 0); -#if EXPERIMENTAL_FEATURES - struct tlv_channel_reestablish_tlvs *send_tlvs, *recv_tlvs; -#endif - - dataloss_protect = feature_negotiated(peer->our_features, - peer->their_features, - OPT_DATA_LOSS_PROTECT); - - /* Both these options give us extra fields to check. */ - check_extra_fields - = dataloss_protect || channel_has(peer->channel, OPT_STATIC_REMOTEKEY); - - /* Our current per-commitment point is the commitment point in the last - * received signed commitment */ - get_per_commitment_point(peer->next_index[LOCAL] - 1, - &my_current_per_commitment_point, NULL); - -#if EXPERIMENTAL_FEATURES - /* Subtle: we free tmpctx below as we loop, so tal off peer */ - send_tlvs = tlv_channel_reestablish_tlvs_new(peer); - - /* FIXME: v0.10.1 would send a different tlv set, due to older spec. - * That did *not* offer OPT_QUIESCE, so in that case don't send tlvs. */ - if (!feature_negotiated(peer->our_features, - peer->their_features, - OPT_QUIESCE)) - goto skip_tlvs; - - /* BOLT-upgrade_protocol #2: - * A node sending `channel_reestablish`, if it supports upgrading channels: - * - MUST set `next_to_send` the commitment number of the next - * `commitment_signed` it expects to send. - */ - send_tlvs->next_to_send = tal_dup(send_tlvs, u64, &peer->next_index[REMOTE]); - - /* BOLT-upgrade_protocol #2: - * - if it initiated the channel: - * - MUST set `desired_type` to the channel_type it wants for the - * channel. - */ - if (peer->channel->opener == LOCAL) - send_tlvs->desired_channel_type = - to_bytearr(send_tlvs, - take(channel_desired_type(NULL, - peer->channel))); - else { - /* BOLT-upgrade_protocol #2: - * - otherwise: - * - MUST set `current_type` to the current channel_type of the - * channel. - * - MUST set `upgradable` to the channel types it could change - * to. - * - MAY not set `upgradable` if it would be empty. - */ - send_tlvs->current_channel_type - = to_bytearr(send_tlvs, peer->channel->type); - send_tlvs->upgradable_channel_type - = to_bytearr(send_tlvs, - take(channel_upgradable_type(NULL, - peer->channel))); - } - -skip_tlvs: -#endif - - /* BOLT #2: - * - * - upon reconnection: - * - if a channel is in an error state: - * - SHOULD retransmit the error packet and ignore any other packets for - * that channel. - * - otherwise: - * - MUST transmit `channel_reestablish` for each channel. - * - MUST wait to receive the other node's `channel_reestablish` - * message before sending any other messages for that channel. - * - * The sending node: - * - MUST set `next_commitment_number` to the commitment number - * of the next `commitment_signed` it expects to receive. - * - MUST set `next_revocation_number` to the commitment number - * of the next `revoke_and_ack` message it expects to receive. - * - if `option_static_remotekey` applies to the commitment transaction: - * - MUST set `my_current_per_commitment_point` to a valid point. - * - otherwise: - * - MUST set `my_current_per_commitment_point` to its commitment - * point for the last signed commitment it received from its - * channel peer (i.e. the commitment_point corresponding to the - * commitment transaction the sender would use to unilaterally - * close). - * - if `next_revocation_number` equals 0: - * - MUST set `your_last_per_commitment_secret` to all zeroes - * - otherwise: - * - MUST set `your_last_per_commitment_secret` to the last - * `per_commitment_secret` it received - */ - if (channel_has(peer->channel, OPT_STATIC_REMOTEKEY)) { - msg = towire_channel_reestablish - (NULL, &peer->channel_id, - peer->next_index[LOCAL], - peer->revocations_received, - last_remote_per_commit_secret, - /* Can send any (valid) point here */ - &peer->remote_per_commit -#if EXPERIMENTAL_FEATURES - , send_tlvs -#endif - ); - } else { - msg = towire_channel_reestablish - (NULL, &peer->channel_id, - peer->next_index[LOCAL], - peer->revocations_received, - last_remote_per_commit_secret, - &my_current_per_commitment_point -#if EXPERIMENTAL_FEATURES - , send_tlvs -#endif - ); - } - - peer_write(peer->pps, take(msg)); - - peer_billboard(false, "Sent reestablish, waiting for theirs"); - - /* Read until they say something interesting (don't forward - * gossip *to* them yet: we might try sending channel_update - * before we've reestablished channel). */ - do { - clean_tmpctx(); - msg = peer_read(tmpctx, peer->pps); - - /* connectd promised us the msg was reestablish? */ - if (reestablish_only) { - if (fromwire_peektype(msg) != WIRE_CHANNEL_REESTABLISH) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Expected reestablish, got: %s", - tal_hex(tmpctx, msg)); - } - } while (handle_peer_error(peer->pps, &peer->channel_id, msg) || - capture_premature_msg(&premature_msgs, msg)); - -#if EXPERIMENTAL_FEATURES - /* Initialize here in case we don't read it below! */ - recv_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx); - - /* FIXME: v0.10.1 would send a different tlv set, due to older spec. - * That did *not* offer OPT_QUIESCE, so in that case ignore tlvs. */ - if (!feature_negotiated(peer->our_features, - peer->their_features, - OPT_QUIESCE)) { - if (!fromwire_channel_reestablish_notlvs(msg, - &channel_id, - &next_commitment_number, - &next_revocation_number, - &last_local_per_commitment_secret, - &remote_current_per_commitment_point)) - peer_failed_warn(peer->pps, - &peer->channel_id, - "bad reestablish msg: %s %s", - peer_wire_name(fromwire_peektype(msg)), - tal_hex(msg, msg)); - } else if (!fromwire_channel_reestablish(tmpctx, msg, - &channel_id, - &next_commitment_number, - &next_revocation_number, - &last_local_per_commitment_secret, - &remote_current_per_commitment_point, - &recv_tlvs)) { - peer_failed_warn(peer->pps, - &peer->channel_id, - "bad reestablish msg: %s %s", - peer_wire_name(fromwire_peektype(msg)), - tal_hex(msg, msg)); - } -#else /* !EXPERIMENTAL_FEATURES */ - if (!fromwire_channel_reestablish(msg, - &channel_id, - &next_commitment_number, - &next_revocation_number, - &last_local_per_commitment_secret, - &remote_current_per_commitment_point)) { - peer_failed_warn(peer->pps, - &peer->channel_id, - "bad reestablish msg: %s %s", - peer_wire_name(fromwire_peektype(msg)), - tal_hex(msg, msg)); - } -#endif - - if (!channel_id_eq(&channel_id, &peer->channel_id)) { - peer_failed_err(peer->pps, - &channel_id, - "bad reestablish msg for unknown channel %s: %s", - type_to_string(tmpctx, struct channel_id, - &channel_id), - tal_hex(msg, msg)); - } - - status_debug("Got reestablish commit=%"PRIu64" revoke=%"PRIu64, - next_commitment_number, - next_revocation_number); - - /* BOLT #2: - * - * - if `next_commitment_number` is 1 in both the - * `channel_reestablish` it sent and received: - * - MUST retransmit `funding_locked`. - * - otherwise: - * - MUST NOT retransmit `funding_locked`. - */ - if (peer->funding_locked[LOCAL] - && peer->next_index[LOCAL] == 1 - && next_commitment_number == 1) { - u8 *msg; - - status_debug("Retransmitting funding_locked for channel %s", - type_to_string(tmpctx, struct channel_id, &peer->channel_id)); - /* Contains per commit point #1, for first post-opening commit */ - msg = towire_funding_locked(NULL, - &peer->channel_id, - &peer->next_local_per_commit); - peer_write(peer->pps, take(msg)); - } - - /* Note: next_index is the index of the current commit we're working - * on, but BOLT #2 refers to the *last* commit index, so we -1 where - * required. */ - - /* BOLT #2: - * - * - if `next_revocation_number` is equal to the commitment - * number of the last `revoke_and_ack` the receiving node sent, AND - * the receiving node hasn't already received a `closing_signed`: - * - MUST re-send the `revoke_and_ack`. - * - if it has previously sent a `commitment_signed` that needs to be - * retransmitted: - * - MUST retransmit `revoke_and_ack` and `commitment_signed` in the - * same relative order as initially transmitted. - * - otherwise: - * - if `next_revocation_number` is not equal to 1 greater - * than the commitment number of the last `revoke_and_ack` the - * receiving node has sent: - * - SHOULD send an `error` and fail the channel. - * - if it has not sent `revoke_and_ack`, AND - * `next_revocation_number` is not equal to 0: - * - SHOULD send an `error` and fail the channel. - */ - if (next_revocation_number == peer->next_index[LOCAL] - 2) { - /* Don't try to retransmit revocation index -1! */ - if (peer->next_index[LOCAL] < 2) { - peer_failed_err(peer->pps, - &peer->channel_id, - "bad reestablish revocation_number: %" - PRIu64, - next_revocation_number); - } - retransmit_revoke_and_ack = true; - } else if (next_revocation_number < peer->next_index[LOCAL] - 1) { - peer_failed_err(peer->pps, - &peer->channel_id, - "bad reestablish revocation_number: %"PRIu64 - " vs %"PRIu64, - next_revocation_number, - peer->next_index[LOCAL]); - } else if (next_revocation_number > peer->next_index[LOCAL] - 1) { - if (!check_extra_fields) - /* They don't support option_data_loss_protect or - * option_static_remotekey, we fail it due to - * unexpected number */ - peer_failed_err(peer->pps, - &peer->channel_id, - "bad reestablish revocation_number: %"PRIu64 - " vs %"PRIu64, - next_revocation_number, - peer->next_index[LOCAL] - 1); - - /* Remote claims it's ahead of us: can it prove it? - * Does not return. */ - check_future_dataloss_fields(peer, - next_revocation_number, - &last_local_per_commitment_secret, - channel_has(peer->channel, - OPT_STATIC_REMOTEKEY) - ? NULL : - &remote_current_per_commitment_point); - } else - retransmit_revoke_and_ack = false; - - /* BOLT #2: - * - * - if `next_commitment_number` is equal to the commitment - * number of the last `commitment_signed` message the receiving node - * has sent: - * - MUST reuse the same commitment number for its next - * `commitment_signed`. - */ - if (next_commitment_number == peer->next_index[REMOTE] - 1) { - /* We completed opening, we don't re-transmit that one! */ - if (next_commitment_number == 0) - peer_failed_err(peer->pps, - &peer->channel_id, - "bad reestablish commitment_number: %" - PRIu64, - next_commitment_number); - - retransmit_commitment_signed = true; - - /* BOLT #2: - * - * - otherwise: - * - if `next_commitment_number` is not 1 greater than the - * commitment number of the last `commitment_signed` message the - * receiving node has sent: - * - SHOULD send an `error` and fail the channel. - */ - } else if (next_commitment_number != peer->next_index[REMOTE]) - peer_failed_err(peer->pps, - &peer->channel_id, - "bad reestablish commitment_number: %"PRIu64 - " vs %"PRIu64, - next_commitment_number, - peer->next_index[REMOTE]); - else - retransmit_commitment_signed = false; - - /* After we checked basic sanity, we check dataloss fields if any */ - if (check_extra_fields) - check_current_dataloss_fields(peer, - next_revocation_number, - next_commitment_number, - &last_local_per_commitment_secret, - channel_has(peer->channel, - OPT_STATIC_REMOTEKEY) - ? NULL - : &remote_current_per_commitment_point); - - /* BOLT #2: - * - if it has previously sent a `commitment_signed` that needs to be - * retransmitted: - * - MUST retransmit `revoke_and_ack` and `commitment_signed` in the - * same relative order as initially transmitted. - */ - if (retransmit_revoke_and_ack && !peer->last_was_revoke) - resend_revoke(peer); - - if (retransmit_commitment_signed) - resend_commitment(peer, peer->last_sent_commit); - - /* This covers the case where we sent revoke after commit. */ - if (retransmit_revoke_and_ack && peer->last_was_revoke) - resend_revoke(peer); - - /* BOLT #2: - * - * - upon reconnection: - * - if it has sent a previous `shutdown`: - * - MUST retransmit `shutdown`. - */ - /* (If we had sent `closing_signed`, we'd be in closingd). */ - maybe_send_shutdown(peer); - -#if EXPERIMENTAL_FEATURES - if (recv_tlvs->desired_channel_type) - status_debug("They sent desired_channel_type [%s]", - fmt_featurebits(tmpctx, - recv_tlvs->desired_channel_type)); - if (recv_tlvs->current_channel_type) - status_debug("They sent current_channel_type [%s]", - fmt_featurebits(tmpctx, - recv_tlvs->current_channel_type)); - - if (recv_tlvs->upgradable_channel_type) - status_debug("They offered upgrade to [%s]", - fmt_featurebits(tmpctx, - recv_tlvs->upgradable_channel_type)); - - /* BOLT-upgrade_protocol #2: - * - * A node receiving `channel_reestablish`: - * - if it has to retransmit `commitment_signed` or `revoke_and_ack`: - * - MUST consider the channel feature change failed. - */ - if (retransmit_commitment_signed || retransmit_revoke_and_ack) { - status_debug("No upgrade: we retransmitted"); - /* BOLT-upgrade_protocol #2: - * - * - if `next_to_send` is missing, or not equal to the - * `next_commitment_number` it sent: - * - MUST consider the channel feature change failed. - */ - } else if (!recv_tlvs->next_to_send) { - status_debug("No upgrade: no next_to_send received"); - } else if (*recv_tlvs->next_to_send != peer->next_index[LOCAL]) { - status_debug("No upgrade: they're retransmitting"); - /* BOLT-upgrade_protocol #2: - * - * - if updates are pending on either sides' commitment transaction: - * - MUST consider the channel feature change failed. - */ - /* Note that we can have HTLCs we *want* to add or remove - * but haven't yet: thats OK! */ - } else if (pending_updates(peer->channel, LOCAL, true) - || pending_updates(peer->channel, REMOTE, true)) { - status_debug("No upgrade: pending changes"); - } else { - const struct tlv_channel_reestablish_tlvs *initr, *ninitr; - const u8 *type; - - if (peer->channel->opener == LOCAL) { - initr = send_tlvs; - ninitr = recv_tlvs; - } else { - initr = recv_tlvs; - ninitr = send_tlvs; - } - - /* BOLT-upgrade_protocol #2: - * - * - if `desired_channel_type` matches `current_channel_type` or any - * `upgradable_channel_type`: - * - MUST consider the channel type to be `desired_channel_type`. - * - otherwise: - * - MUST consider the channel type change failed. - * - if there is a `current_channel_type` field: - * - MUST consider the channel type to be `current_channel_type`. - */ - if (match_type(initr->desired_channel_type, - ninitr->current_channel_type) - || match_type(initr->desired_channel_type, - ninitr->upgradable_channel_type)) - type = initr->desired_channel_type; - else if (ninitr->current_channel_type) - type = ninitr->current_channel_type; - else - type = NULL; - - if (type) - set_channel_type(peer->channel, type); - } - tal_free(send_tlvs); - -#endif /* EXPERIMENTAL_FEATURES */ - - /* Now stop, we've been polite long enough. */ - if (reestablish_only) { - /* If we were successfully closing, we still go to closingd. */ - if (shutdown_complete(peer)) { - send_shutdown_complete(peer); - daemon_shutdown(); - exit(0); - } - peer_failed_err(peer->pps, - &peer->channel_id, - "Channel is already closed"); - } - - /* Corner case: we didn't send shutdown before because update_add_htlc - * pending, but now they're cleared by restart, and we're actually - * complete. In that case, their `shutdown` will trigger us. */ - - /* Start commit timer: if we sent revoke we might need it. */ - start_commit_timer(peer); - - /* Now, re-send any that we're supposed to be failing. */ - for (htlc = htlc_map_first(peer->channel->htlcs, &it); - htlc; - htlc = htlc_map_next(peer->channel->htlcs, &it)) { - if (htlc->state == SENT_REMOVE_HTLC) - send_fail_or_fulfill(peer, htlc); - } - - /* We allow peer to send us tx-sigs, until funding locked received */ - peer->tx_sigs_allowed = true; - peer_billboard(true, "Reconnected, and reestablished."); - - /* BOLT #2: - * - upon reconnection: - *... - * - MUST transmit `channel_reestablish` for each channel. - * - MUST wait to receive the other node's `channel_reestablish` - * message before sending any other messages for that channel. - */ - /* LND doesn't wait. */ - for (size_t i = 0; i < tal_count(premature_msgs); i++) - peer_in(peer, premature_msgs[i]); - tal_free(premature_msgs); } /* ignores the funding_depth unless depth >= minimum_depth * (except to update billboard, and set peer->depth_togo). */ -static void handle_funding_depth(struct peer *peer, const u8 *msg) +static void handle_funding_depth(struct eltoo_peer *peer, const u8 *msg) { u32 depth; struct short_channel_id *scid; @@ -2820,7 +1875,7 @@ static void handle_funding_depth(struct peer *peer, const u8 *msg) if (!peer->funding_locked[LOCAL]) { status_debug("funding_locked: sending commit index" " %"PRIu64": %s", - peer->next_index[LOCAL], + peer->next_index, type_to_string(tmpctx, struct pubkey, &peer->next_local_per_commit)); msg = towire_funding_locked(NULL, @@ -2840,7 +1895,7 @@ static void handle_funding_depth(struct peer *peer, const u8 *msg) billboard_update(peer); } -static const u8 *get_cupdate(const struct peer *peer) +static const u8 *get_cupdate(const struct eltoo_peer *peer) { /* Technically we only need to tell it the first time (unless it's * changed). But it's not that common. */ @@ -2849,7 +1904,7 @@ static const u8 *get_cupdate(const struct peer *peer) return peer->channel_update; } -static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) +static void handle_offer_htlc(struct eltoo_peer *peer, const u8 *inmsg) { u8 *msg; u32 cltv_expiry; @@ -2902,7 +1957,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) #endif ); peer_write(peer->pps, take(msg)); - start_commit_timer(peer); + start_update_timer(peer); /* Tell the master. */ msg = towire_channeld_offer_htlc_reply(NULL, peer->htlc_id, 0, ""); @@ -2957,86 +2012,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) wire_sync_write(MASTER_FD, take(msg)); } -static void handle_feerates(struct peer *peer, const u8 *inmsg) -{ - u32 feerate; - - if (!fromwire_channeld_feerates(inmsg, &feerate, - &peer->feerate_min, - &peer->feerate_max, - &peer->feerate_penalty)) - master_badmsg(WIRE_CHANNELD_FEERATES, inmsg); - - /* BOLT #2: - * - * The node _responsible_ for paying the Bitcoin fee: - * - SHOULD send `update_fee` to ensure the current fee rate is - * sufficient (by a significant margin) for timely processing of the - * commitment transaction. - */ - if (peer->channel->opener == LOCAL) { - peer->desired_feerate = feerate; - /* Don't do this for the first feerate, wait until something else - * happens. LND seems to get upset in some cases otherwise: - * see https://github.com/ElementsProject/lightning/issues/3596 */ - if (peer->next_index[LOCAL] != 1 - || peer->next_index[REMOTE] != 1) - start_commit_timer(peer); - } else { - /* BOLT #2: - * - * The node _not responsible_ for paying the Bitcoin fee: - * - MUST NOT send `update_fee`. - */ - /* FIXME: We could drop to chain if fees are too low, but - * that's fraught too. */ - } -} - -static void handle_blockheight(struct peer *peer, const u8 *inmsg) -{ - u32 blockheight; - - if (!fromwire_channeld_blockheight(inmsg, &blockheight)) - master_badmsg(WIRE_CHANNELD_BLOCKHEIGHT, inmsg); - - /* Save it, so we know */ - peer->our_blockheight = blockheight; - if (peer->channel->opener == LOCAL) - start_commit_timer(peer); - else { - u32 peer_height = get_blockheight(peer->channel->blockheight_states, - peer->channel->opener, - REMOTE); - /* BOLT- #2: - * The node _not responsible_ for initiating the channel: - * ... - * - if last received `blockheight` is > 1008 behind - * currently known blockheight: - * - SHOULD fail he channel - */ - assert(peer_height + 1008 > peer_height); - if (peer_height + 1008 < blockheight) - peer_failed_err(peer->pps, &peer->channel_id, - "Peer is too far behind, terminating" - " leased channel. Our current" - " %u, theirs %u", - blockheight, peer_height); - /* We're behind them... what do. It's possible they're lying, - * but if we're in a lease this is actually in our favor so - * we log it but otherwise continue on unchanged */ - if (peer_height > blockheight - && peer_height > blockheight + 100) - status_unusual("Peer reporting we've fallen %u" - " blocks behind. Our height %u," - " their height %u", - peer_height - blockheight, - blockheight, peer_height); - - } -} - -static void handle_config_channel(struct peer *peer, const u8 *inmsg) +static void handle_config_channel(struct eltoo_peer *peer, const u8 *inmsg) { u32 *base, *ppm; struct amount_msat *htlc_min, *htlc_max; @@ -3072,7 +2048,7 @@ static void handle_config_channel(struct peer *peer, const u8 *inmsg) } -static void handle_preimage(struct peer *peer, const u8 *inmsg) +static void handle_preimage(struct eltoo_peer *peer, const u8 *inmsg) { struct fulfilled_htlc fulfilled_htlc; struct htlc *h; @@ -3086,7 +2062,7 @@ static void handle_preimage(struct peer *peer, const u8 *inmsg) &h)) { case CHANNEL_ERR_REMOVE_OK: send_fail_or_fulfill(peer, h); - start_commit_timer(peer); + start_update_timer(peer); return; /* These shouldn't happen, because any offered HTLC (which would give * us the preimage) should have timed out long before. If we @@ -3103,7 +2079,7 @@ static void handle_preimage(struct peer *peer, const u8 *inmsg) abort(); } -static void handle_fail(struct peer *peer, const u8 *inmsg) +static void handle_fail(struct eltoo_peer *peer, const u8 *inmsg) { struct failed_htlc *failed_htlc; enum channel_remove_err e; @@ -3117,7 +2093,7 @@ static void handle_fail(struct peer *peer, const u8 *inmsg) case CHANNEL_ERR_REMOVE_OK: h->failed = tal_steal(h, failed_htlc); send_fail_or_fulfill(peer, h); - start_commit_timer(peer); + start_update_timer(peer); return; case CHANNEL_ERR_NO_SUCH_ID: case CHANNEL_ERR_ALREADY_FULFILLED: @@ -3132,7 +2108,7 @@ static void handle_fail(struct peer *peer, const u8 *inmsg) abort(); } -static void handle_shutdown_cmd(struct peer *peer, const u8 *inmsg) +static void handle_shutdown_cmd(struct eltoo_peer *peer, const u8 *inmsg) { u32 *final_index; struct ext_key *final_ext_key; @@ -3156,18 +2132,18 @@ static void handle_shutdown_cmd(struct peer *peer, const u8 *inmsg) /* We can't send this until commit (if any) is done, so start timer. */ peer->send_shutdown = true; - start_commit_timer(peer); + start_update_timer(peer); } /* Lightningd tells us when channel_update has changed. */ -static void handle_channel_update(struct peer *peer, const u8 *msg) +static void handle_channel_update(struct eltoo_peer *peer, const u8 *msg) { peer->channel_update = tal_free(peer->channel_update); if (!fromwire_channeld_channel_update(peer, msg, &peer->channel_update)) master_badmsg(WIRE_CHANNELD_CHANNEL_UPDATE, msg); } -static void handle_send_error(struct peer *peer, const u8 *msg) +static void handle_send_error(struct eltoo_peer *peer, const u8 *msg) { char *reason; if (!fromwire_channeld_send_error(msg, msg, &reason)) @@ -3182,16 +2158,16 @@ static void handle_send_error(struct peer *peer, const u8 *msg) } #if DEVELOPER -static void handle_dev_reenable_commit(struct peer *peer) +static void handle_dev_reenable_commit(struct eltoo_peer *peer) { peer->dev_disable_commit = tal_free(peer->dev_disable_commit); - start_commit_timer(peer); + start_update_timer(peer); status_debug("dev_reenable_commit"); wire_sync_write(MASTER_FD, take(towire_channeld_dev_reenable_commit_reply(NULL))); } -static void handle_dev_memleak(struct peer *peer, const u8 *msg) +static void handle_dev_memleak(struct eltoo_peer *peer, const u8 *msg) { struct htable *memtable; bool found_leak; @@ -3208,7 +2184,7 @@ static void handle_dev_memleak(struct peer *peer, const u8 *msg) } #if EXPERIMENTAL_FEATURES -static void handle_dev_quiesce(struct peer *peer, const u8 *msg) +static void handle_dev_quiesce(struct eltoo_peer *peer, const u8 *msg) { if (!fromwire_channeld_dev_quiesce(msg)) master_badmsg(WIRE_CHANNELD_DEV_QUIESCE, msg); @@ -3224,7 +2200,7 @@ static void handle_dev_quiesce(struct peer *peer, const u8 *msg) #endif /* EXPERIMENTAL_FEATURES */ #endif /* DEVELOPER */ -static void req_in(struct peer *peer, const u8 *msg) +static void req_in(struct eltoo_peer *peer, const u8 *msg) { enum channeld_wire t = fromwire_peektype(msg); @@ -3238,14 +2214,10 @@ static void req_in(struct peer *peer, const u8 *msg) handle_offer_htlc(peer, msg); return; case WIRE_CHANNELD_FEERATES: - if (handle_master_request_later(peer, msg)) - return; - handle_feerates(peer, msg); + /* FIXME handle illegal messages */ return; case WIRE_CHANNELD_BLOCKHEIGHT: - if (handle_master_request_later(peer, msg)) - return; - handle_blockheight(peer, msg); + /* FIXME handle illegal messages */ return; case WIRE_CHANNELD_FULFILL_HTLC: if (handle_master_request_later(peer, msg)) @@ -3316,9 +2288,8 @@ static void req_in(struct peer *peer, const u8 *msg) } /* We do this synchronously. */ -static void init_channel(struct peer *peer) +static void init_channel(struct eltoo_peer *peer) { - struct basepoints points[NUM_SIDES]; struct amount_sat funding_sats; struct amount_msat local_msat; struct pubkey funding_pubkey[NUM_SIDES]; @@ -3331,13 +2302,9 @@ static void init_channel(struct peer *peer) struct ext_key final_ext_key; u8 *fwd_msg; const u8 *msg; - struct fee_states *fee_states; - struct height_states *blockheight_states; - u32 minimum_depth, lease_expiry; - struct secret last_remote_per_commit_secret; + u32 minimum_depth; secp256k1_ecdsa_signature *remote_ann_node_sig; secp256k1_ecdsa_signature *remote_ann_bitcoin_sig; - struct penalty_base *pbases; bool reestablish_only; struct channel_type *channel_type; u32 *dev_disable_commit; /* Always NULL */ @@ -3357,35 +2324,26 @@ static void init_channel(struct peer *peer) &funding_sats, &minimum_depth, &peer->our_blockheight, - &blockheight_states, - &lease_expiry, &conf[LOCAL], &conf[REMOTE], - &fee_states, &peer->feerate_min, &peer->feerate_max, - &peer->feerate_penalty, - &peer->their_commit_sig, + &peer->channel->eltoo_keyset.other_update_psig, + &peer->channel->eltoo_keyset.self_update_psig, + &peer->channel->eltoo_keyset.session, &funding_pubkey[REMOTE], - &points[REMOTE], - &peer->remote_per_commit, - &peer->old_remote_per_commit, &opener, &peer->fee_base, &peer->fee_per_satoshi, &peer->htlc_minimum_msat, &peer->htlc_maximum_msat, &local_msat, - &points[LOCAL], &funding_pubkey[LOCAL], &peer->node_ids[LOCAL], &peer->node_ids[REMOTE], &peer->commit_msec, &peer->cltv_delta, - &peer->last_was_revoke, - &peer->last_sent_commit, - &peer->next_index[LOCAL], - &peer->next_index[REMOTE], - &peer->revocations_received, + &peer->next_index, + &peer->updates_received, &peer->htlc_id, &htlcs, &peer->funding_locked[LOCAL], @@ -3400,7 +2358,6 @@ static void init_channel(struct peer *peer) &peer->channel_flags, &fwd_msg, &peer->announce_depth_reached, - &last_remote_per_commit_secret, &peer->their_features, &peer->remote_upfront_shutdown_script, &remote_ann_node_sig, @@ -3409,7 +2366,6 @@ static void init_channel(struct peer *peer) &dev_fast_gossip, &dev_fail_process_onionpacket, &dev_disable_commit, - &pbases, &reestablish_only, &peer->channel_update)) { master_badmsg(WIRE_CHANNELD_INIT, msg); @@ -3423,39 +2379,19 @@ static void init_channel(struct peer *peer) peer->dev_fast_gossip = dev_fast_gossip; #endif - status_debug("option_static_remotekey = %u, option_anchor_outputs = %u", - channel_type_has(channel_type, OPT_STATIC_REMOTEKEY), - channel_type_has(channel_type, OPT_ANCHOR_OUTPUTS)); - - /* Keeping an array of pointers is better since it allows us to avoid - * extra allocations later. */ - peer->pbases = tal_arr(peer, struct penalty_base *, 0); - for (size_t i=0; ipbases, - tal_dup(peer, struct penalty_base, &pbases[i])); - tal_free(pbases); - /* stdin == requests, 3 == peer */ peer->pps = new_per_peer_state(peer); per_peer_state_set_fd(peer->pps, 3); - status_debug("init %s: remote_per_commit = %s, old_remote_per_commit = %s" - " next_idx_local = %"PRIu64 - " next_idx_remote = %"PRIu64 - " revocations_received = %"PRIu64 - " feerates %s range %u-%u" - " blockheights %s, our current %u", + status_debug("init %s: " + " next_idx = %"PRIu64 + " updates_received = %"PRIu64 + " feerates %s range %u-%u" side_to_str(opener), - type_to_string(tmpctx, struct pubkey, - &peer->remote_per_commit), - type_to_string(tmpctx, struct pubkey, - &peer->old_remote_per_commit), - peer->next_index[LOCAL], peer->next_index[REMOTE], - peer->revocations_received, + peer->next_index, peer->next_index, + peer->updates_received, type_to_string(tmpctx, struct fee_states, fee_states), - peer->feerate_min, peer->feerate_max, - type_to_string(tmpctx, struct height_states, blockheight_states), - peer->our_blockheight); + peer->feerate_min, peer->feerate_max); if (remote_ann_node_sig && remote_ann_bitcoin_sig) { peer->announcement_node_sigs[REMOTE] = *remote_ann_node_sig; @@ -3473,22 +2409,14 @@ static void init_channel(struct peer *peer) /* First commit is used for opening: if we've sent 0, we're on * index 1. */ - assert(peer->next_index[LOCAL] > 0); - assert(peer->next_index[REMOTE] > 0); - - get_per_commitment_point(peer->next_index[LOCAL], - &peer->next_local_per_commit, NULL); + assert(peer->next_index > 0); - peer->channel = new_full_channel(peer, &peer->channel_id, + peer->channel = new_full_eltoo_channel(peer, &peer->channel_id, &funding, minimum_depth, - take(blockheight_states), - lease_expiry, funding_sats, local_msat, - take(fee_states), &conf[LOCAL], &conf[REMOTE], - &points[LOCAL], &points[REMOTE], &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], take(channel_type), @@ -3516,8 +2444,7 @@ static void init_channel(struct peer *peer) /* OK, now we can process peer messages. */ if (reconnected) - peer_reconnect(peer, &last_remote_per_commit_secret, - reestablish_only); + peer_reconnect(peer, reestablish_only); else assert(!reestablish_only); diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 5e49b331caad..7cd70513cc0f 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -45,7 +45,7 @@ static void balance_add_htlc(struct balance *balance, const struct htlc *htlc, enum side side) { - if (htlc_owner(htlc) == side) + if (eltoo_htlc_owner(htlc) == side) balance->msat -= htlc->amount.millisatoshis; /* Raw: balance */ } @@ -58,9 +58,9 @@ static void balance_remove_htlc(struct balance *balance, /* Fulfilled HTLCs are paid to recipient, otherwise returns to owner */ if (htlc->r) - paid_to = !htlc_owner(htlc); + paid_to = !eltoo_htlc_owner(htlc); else - paid_to = htlc_owner(htlc); + paid_to = eltoo_htlc_owner(htlc); if (side == paid_to) balance->msat += htlc->amount.millisatoshis; /* Raw: balance */ @@ -192,19 +192,19 @@ static size_t gather_htlcs(const tal_t *ctx, for (htlc = htlc_map_first(channel->htlcs, &it); htlc; htlc = htlc_map_next(channel->htlcs, &it)) { - if (htlc_has(htlc, committed_flag)) { + if (eltoo_htlc_has(htlc, committed_flag)) { #ifdef SUPERVERBOSE dump_htlc(htlc, "COMMITTED"); #endif htlc_arr_append(committed, htlc); - if (htlc_has(htlc, pending_flag)) { + if (eltoo_htlc_has(htlc, pending_flag)) { #ifdef SUPERVERBOSE dump_htlc(htlc, "REMOVING"); #endif htlc_arr_append(pending_removal, htlc); } else if (htlc_owner(htlc) != side) num_other_side++; - } else if (htlc_has(htlc, pending_flag)) { + } else if (eltoo_htlc_has(htlc, pending_flag)) { htlc_arr_append(pending_addition, htlc); #ifdef SUPERVERBOSE dump_htlc(htlc, "ADDING"); @@ -552,9 +552,9 @@ enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, htlcp, true, err_immediate_failures); } -struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id) +struct htlc *eltoo_channel_get_htlc(struct eltoo_channel *channel, enum side sender, u64 id) { - return htlc_get(channel->htlcs, id, sender); + return eltoo_htlc_get(channel->htlcs, id, sender); } enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, @@ -593,7 +593,7 @@ enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, * - MUST send a `warning` and close the connection, or send an * `error` and fail the channel. */ - if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { + if (!eltoo_htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", htlc->id, htlc_state_name(htlc->eltoo_state)); return CHANNEL_ERR_HTLC_UNCOMMITTED; @@ -628,13 +628,13 @@ enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, return CHANNEL_ERR_REMOVE_OK; } -enum channel_remove_err channel_fail_htlc(struct channel *channel, +enum channel_remove_err channel_fail_htlc(struct eltoo_channel *channel, enum side owner, u64 id, struct htlc **htlcp) { struct htlc *htlc; - htlc = channel_get_htlc(channel, owner, id); + htlc = eltoo_channel_get_htlc(channel, owner, id); if (!htlc) return CHANNEL_ERR_NO_SUCH_ID; @@ -646,21 +646,21 @@ enum channel_remove_err channel_fail_htlc(struct channel *channel, * - MUST send a `warning` and close the connection, or send an * `error` and fail the channel. */ - if (!htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { + if (!eltoo_htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { status_unusual("channel_fail_htlc: %"PRIu64" in state %s", - htlc->id, htlc_state_name(htlc->state)); + htlc->id, eltoo_htlc_state_name(htlc->eltoo_state)); return CHANNEL_ERR_HTLC_UNCOMMITTED; } /* FIXME: Technically, they can fail this before we're committed to * it. This implies a non-linear state machine. */ - if (htlc->state == SENT_ADD_ACK_REVOCATION) - htlc->state = RCVD_REMOVE_HTLC; - else if (htlc->state == RCVD_ADD_ACK_REVOCATION) - htlc->state = SENT_REMOVE_HTLC; + if (htlc->eltoo_state == SENT_ADD_ACK) + htlc->eltoo_state = SENT_REMOVE_HTLC; + else if (htlc->eltoo_state == RCVD_ADD_ACK) + htlc->eltoo_state = RCVD_REMOVE_HTLC; else { status_unusual("channel_fail_htlc: %"PRIu64" in state %s", - htlc->id, htlc_state_name(htlc->state)); + htlc->id, eltoo_htlc_state_name(htlc->eltoo_state)); return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; } @@ -670,7 +670,7 @@ enum channel_remove_err channel_fail_htlc(struct channel *channel, return CHANNEL_ERR_REMOVE_OK; } -static void htlc_incstate(struct channel *channel, +static void htlc_incstate(struct eltoo_channel *channel, struct htlc *htlc, enum side sidechanged, struct balance owed[NUM_SIDES]) @@ -679,16 +679,16 @@ static void htlc_incstate(struct channel *channel, const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED); status_debug("htlc %"PRIu64": %s->%s", htlc->id, - htlc_state_name(htlc->state), - htlc_state_name(htlc->state+1)); + eltoo_htlc_state_name(htlc->eltoo_state), + eltoo_htlc_state_name(htlc->eltoo_state+1)); - preflags = htlc_state_flags(htlc->state); - postflags = htlc_state_flags(htlc->state + 1); + preflags = eltoo_htlc_state_flags(htlc->eltoo_state); + postflags = eltoo_htlc_state_flags(htlc->eltoo_state + 1); /* You can't change sides. */ assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); - htlc->state++; + htlc->eltoo_state++; /* If we've added or removed, adjust balances. */ if (!(preflags & committed_f) && (postflags & committed_f)) { @@ -710,67 +710,10 @@ static void htlc_incstate(struct channel *channel, } } -/* Returns true if a change was made. */ -static bool fee_incstate(struct channel *channel, - enum side sidechanged, - enum htlc_state hstate) -{ - int preflags, postflags; - - preflags = htlc_state_flags(hstate); - postflags = htlc_state_flags(hstate + 1); - - /* You can't change sides. */ - assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) - == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); - - /* These only advance through ADDING states. */ - if (!(htlc_state_flags(hstate) & HTLC_ADDING)) - return false; - - if (!inc_fee_state(channel->fee_states, hstate)) - return false; - - status_debug("Feerate: %s->%s %s now %u", - htlc_state_name(hstate), - htlc_state_name(hstate+1), - side_to_str(sidechanged), - *channel->fee_states->feerate[hstate+1]); - return true; -} - -static bool blockheight_incstate(struct channel *channel, - enum side sidechanged, - enum htlc_state hstate) -{ - int preflags, postflags; - - preflags = htlc_state_flags(hstate); - postflags = htlc_state_flags(hstate + 1); - - /* You can't change sides. */ - assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) - == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); - - /* These only advance through ADDING states. */ - if (!(htlc_state_flags(hstate) & HTLC_ADDING)) - return false; - - if (!inc_height_state(channel->blockheight_states, hstate)) - return false; - - status_debug("Blockheight: %s->%s %s now %u", - htlc_state_name(hstate), - htlc_state_name(hstate+1), - side_to_str(sidechanged), - *channel->blockheight_states->height[hstate+1]); - return true; -} - /* Returns flags which were changed. */ -static int change_htlcs(struct channel *channel, +static int change_htlcs(struct eltoo_channel *channel, enum side sidechanged, - const enum htlc_state *htlc_states, + const enum eltoo_htlc_state *htlc_states, size_t n_hstates, const struct htlc ***htlcs, const char *prefix) @@ -788,12 +731,12 @@ static int change_htlcs(struct channel *channel, h; h = htlc_map_next(channel->htlcs, &it)) { for (i = 0; i < n_hstates; i++) { - if (h->state == htlc_states[i]) { + if (h->eltoo_state == htlc_states[i]) { htlc_incstate(channel, h, sidechanged, owed); dump_htlc(h, prefix); htlc_arr_append(htlcs, h); - cflags |= (htlc_state_flags(htlc_states[i]) - ^ htlc_state_flags(h->state)); + cflags |= (eltoo_htlc_state_flags(htlc_states[i]) + ^ eltoo_htlc_state_flags(h->eltoo_state)); } } } @@ -810,18 +753,6 @@ static int change_htlcs(struct channel *channel, } } - /* Update fees and blockheight (do backwards, to avoid - * double-increment!). */ - for (i = n_hstates - 1; i >= 0; i--) { - if (fee_incstate(channel, sidechanged, htlc_states[i])) - cflags |= (htlc_state_flags(htlc_states[i]) - ^ htlc_state_flags(htlc_states[i]+1)); - - if (blockheight_incstate(channel, sidechanged, htlc_states[i])) - cflags |= (htlc_state_flags(htlc_states[i]) - ^ htlc_state_flags(htlc_states[i]+1)); - } - return cflags; } @@ -904,15 +835,13 @@ bool htlc_dust_ok(const struct channel *channel, total_dusted); } -bool channel_sending_commit(struct channel *channel, +bool channel_sending_update(struct eltoo_channel *channel, const struct htlc ***htlcs) { int change; - const enum htlc_state states[] = { SENT_ADD_HTLC, - SENT_REMOVE_REVOCATION, - SENT_ADD_REVOCATION, + const enum eltoo_htlc_state states[] = { SENT_ADD_HTLC, SENT_REMOVE_HTLC }; - status_debug("Trying commit"); + status_debug("Trying update"); change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), htlcs, "sending_commit"); @@ -968,7 +897,7 @@ bool channel_sending_revoke_and_ack(struct channel *channel) return (change & HTLC_REMOTE_F_PENDING); } -size_t num_channel_htlcs(const struct channel *channel) +size_t num_channel_htlcs(const struct eltoo_channel *channel) { struct htlc_map_iter it; const struct htlc *htlc; @@ -991,7 +920,7 @@ static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES], for (side = 0; side < NUM_SIDES; side++) { /* Did it ever add it? */ - if (!htlc_has(htlc, HTLC_FLAG(side, HTLC_F_WAS_COMMITTED))) + if (!eltoo_htlc_has(htlc, HTLC_FLAG(side, HTLC_F_WAS_COMMITTED))) continue; /* Add it. */ @@ -1000,13 +929,13 @@ static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES], /* If it is no longer committed, remove it (depending * on fail || fulfill). */ - if (htlc_has(htlc, HTLC_FLAG(side, HTLC_F_COMMITTED))) + if (eltoo_htlc_has(htlc, HTLC_FLAG(side, HTLC_F_COMMITTED))) continue; if (!htlc->failed && !htlc->r) { status_broken("%s HTLC %"PRIu64 " %s neither fail nor fulfill?", - htlc_state_owner(htlc->state) == LOCAL + eltoo_htlc_state_owner(htlc->eltoo_state) == LOCAL ? "out" : "in", htlc->id, htlc_state_name(htlc->state)); @@ -1018,22 +947,14 @@ static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES], return true; } -bool pending_updates(const struct channel *channel, +bool pending_updates(const struct eltoo_channel *channel, enum side side, bool uncommitted_ok) { struct htlc_map_iter it; const struct htlc *htlc; - /* Initiator might have fee changes or blockheight updates in play. */ - if (side == channel->opener) { - if (!feerate_changes_done(channel->fee_states, uncommitted_ok)) - return true; - - if (!blockheight_changes_done(channel->blockheight_states, - uncommitted_ok)) - return true; - } + /* No blockheight updates for eltoo for now, continue */ for (htlc = htlc_map_first(channel->htlcs, &it); htlc; @@ -1062,7 +983,7 @@ bool pending_updates(const struct channel *channel, return false; } -bool channel_force_htlcs(struct channel *channel, +bool channel_force_htlcs(struct eltoo_channel *channel, const struct existing_htlc **htlcs) { struct balance view_owed[NUM_SIDES][NUM_SIDES]; @@ -1104,7 +1025,7 @@ bool channel_force_htlcs(struct channel *channel, &htlc, false, NULL, false); if (e != CHANNEL_ERR_ADD_OK) { status_broken("%s HTLC %"PRIu64" failed error %u", - htlc_state_owner(htlcs[i]->state) == LOCAL + eltoo_htlc_state_owner(htlcs[i]->eltoo_state) == LOCAL ? "out" : "in", htlcs[i]->id, e); return false; } diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h index 78d3feca14f4..13de18d0ff8f 100644 --- a/channeld/eltoo_full_channel.h +++ b/channeld/eltoo_full_channel.h @@ -7,7 +7,7 @@ #include #include -struct channel_id; +struct eltoo_channel_id; struct existing_htlc; /** @@ -33,8 +33,8 @@ struct existing_htlc; * * Returns state, or NULL if malformed. */ -struct channel *new_full_channel(const tal_t *ctx, - const struct channel_id *cid, +struct eltoo_channel *new_full_channel(const tal_t *ctx, + const struct eltoo_channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, const struct height_states *blockheight_states, @@ -42,13 +42,13 @@ struct channel *new_full_channel(const tal_t *ctx, struct amount_sat funding_sats, struct amount_msat local_msat, const struct fee_states *fee_states TAKES, - const struct channel_config *local, - const struct channel_config *remote, + const struct eltoo_channel_config *local, + const struct eltoo_channel_config *remote, const struct basepoints *local_basepoints, const struct basepoints *remote_basepoints, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, - const struct channel_type *type TAKES, + const struct eltoo_channel_type *type TAKES, bool option_wumbo, enum side opener); @@ -71,7 +71,7 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, const struct htlc ***htlcmap, struct wally_tx_output *direct_outputs[NUM_SIDES], const u8 **funding_wscript, - const struct channel *channel, + const struct eltoo_channel *channel, const struct pubkey *per_commitment_point, u64 commitment_number, enum side side); @@ -89,7 +89,7 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, * This is the fee rate we actually care about, if we're going to check * whether it's actually too low. */ -u32 actual_feerate(const struct channel *channel, +u32 actual_feerate(const struct eltoo_channel *channel, const struct signature *theirsig); /** @@ -112,7 +112,7 @@ u32 actual_feerate(const struct channel *channel, * the output amounts adjusted accordingly. Otherwise nothing * is changed. */ -enum channel_add_err channel_add_htlc(struct channel *channel, +enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, enum side sender, u64 id, struct amount_msat msatoshi, @@ -130,7 +130,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel, * @offerer: the side offering the HTLC. * @id: unique HTLC id. */ -struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id); +struct htlc *channel_get_htlc(struct eltoo_channel *channel, enum side sender, u64 id); /** * channel_fail_htlc: remove an HTLC, funds to the side which offered it. @@ -142,7 +142,7 @@ struct htlc *channel_get_htlc(struct channel *channel, enum side sender, u64 id) * This will remove the htlc and credit the value of the HTLC (back) * to its offerer. */ -enum channel_remove_err channel_fail_htlc(struct channel *channel, +enum channel_remove_err channel_fail_htlc(struct eltoo_channel *channel, enum side owner, u64 id, struct htlc **htlcp); @@ -158,7 +158,7 @@ enum channel_remove_err channel_fail_htlc(struct channel *channel, * remove the htlc and give the value of the HTLC to its recipient, * and return CHANNEL_ERR_FULFILL_OK. Otherwise, it will return another error. */ -enum channel_remove_err channel_fulfill_htlc(struct channel *channel, +enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, enum side owner, u64 id, const struct preimage *preimage, @@ -171,14 +171,14 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, * This is not exact! To check if their offer is valid, try * channel_update_feerate. */ -u32 approx_max_feerate(const struct channel *channel); +u32 approx_max_feerate(const struct eltoo_channel *channel); /** * can_opener_afford_feerate: could the opener pay the fee? * @channel: The channel state * @feerate: The feerate in satoshi per 1000 bytes. */ -bool can_opener_afford_feerate(const struct channel *channel, u32 feerate); +bool can_opener_afford_feerate(const struct eltoo_channel *channel, u32 feerate); /** * htlc_dust_ok: will this feerate keep our dusted htlc's beneath @@ -188,7 +188,7 @@ bool can_opener_afford_feerate(const struct channel *channel, u32 feerate); * @feerate_per_kw: new feerate to test ok'ness for * @side: which side's htlcs to verify */ -bool htlc_dust_ok(const struct channel *channel, +bool htlc_dust_ok(const struct eltoo_channel *channel, u32 feerate_per_kw, enum side side); @@ -199,21 +199,21 @@ bool htlc_dust_ok(const struct channel *channel, * * Returns true if it's affordable, otherwise does nothing. */ -bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw); +bool channel_update_feerate(struct eltoo_channel *channel, u32 feerate_per_kw); /* * channel_update_blockheight: Change blockheight on non-opener side. * @channel: The channel * @blockheight: current blockheight */ -void channel_update_blockheight(struct channel *channel, u32 blockheight); +void channel_update_blockheight(struct eltoo_channel *channel, u32 blockheight); /** * channel_feerate: Get fee rate for this side of channel. * @channel: The channel * @side: the side */ -u32 channel_feerate(const struct channel *channel, enum side side); +u32 channel_feerate(const struct eltoo_channel *channel, enum side side); /** * channel_sending_commit: commit all remote outstanding changes. @@ -222,7 +222,7 @@ u32 channel_feerate(const struct channel *channel, enum side side); * * This is where we commit to pending changes we've added; returns true if * anything changed for the remote side (if not, don't send!) */ -bool channel_sending_commit(struct channel *channel, +bool channel_sending_commit(struct eltoo_channel *channel, const struct htlc ***htlcs); /** @@ -233,7 +233,7 @@ bool channel_sending_commit(struct channel *channel, * This is where we commit to pending changes we've added; returns true if * anything changed for our local commitment (ie. we have pending changes). */ -bool channel_rcvd_revoke_and_ack(struct channel *channel, +bool channel_rcvd_revoke_and_ack(struct eltoo_channel *channel, const struct htlc ***htlcs); /** @@ -244,7 +244,7 @@ bool channel_rcvd_revoke_and_ack(struct channel *channel, * This is where we commit to pending changes we've added; returns true if * anything changed for our update (ie. we had pending changes added by other). */ -bool channel_rcvd_commit(struct channel *channel, +bool channel_rcvd_commit(struct eltoo_channel *channel, const struct htlc ***htlcs); /** @@ -253,13 +253,13 @@ bool channel_rcvd_commit(struct channel *channel, * * This is where we commit to pending changes we've added. Returns true if * anything changed for the remote commitment (ie. send a new commit).*/ -bool channel_sending_revoke_and_ack(struct channel *channel); +bool channel_sending_revoke_and_ack(struct eltoo_channel *channel); /** * num_channel_htlcs: how many (live) HTLCs at all in channel? * @channel: the channel */ -size_t num_channel_htlcs(const struct channel *channel); +size_t num_channel_htlcs(const struct eltoo_channel *channel); /** * channel_force_htlcs: force these htlcs into the (new) channel @@ -268,7 +268,7 @@ size_t num_channel_htlcs(const struct channel *channel); * * This is used for restoring a channel state. */ -bool channel_force_htlcs(struct channel *channel, +bool channel_force_htlcs(struct eltoo_channel *channel, const struct existing_htlc **htlcs); /** @@ -278,7 +278,7 @@ bool channel_force_htlcs(struct channel *channel, * * Uses status_debug() on every HTLC. */ -void dump_htlcs(const struct channel *channel, const char *prefix); +void dump_htlcs(const struct eltoo_channel *channel, const char *prefix); /** * pending_updates: does this side have updates pending in channel? @@ -286,7 +286,7 @@ void dump_htlcs(const struct channel *channel, const char *prefix); * @side: the side who is offering or failing/fulfilling HTLC, or feechange * @uncommitted_ok: don't count uncommitted changes. */ -bool pending_updates(const struct channel *channel, enum side side, +bool pending_updates(const struct eltoo_channel *channel, enum side side, bool uncommitted_ok); const char *channel_add_err_name(enum channel_add_err e); diff --git a/common/htlc_wire.h b/common/htlc_wire.h index b89b5961a90b..6ee8ee3466cc 100644 --- a/common/htlc_wire.h +++ b/common/htlc_wire.h @@ -60,6 +60,7 @@ struct failed_htlc { struct changed_htlc { enum htlc_state newstate; + enum eltoo_htlc_state eltoo_newstate; u64 id; }; From b89649aaca2d1ea5155eac8671183aba7404812c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 18 Aug 2022 13:55:01 -0400 Subject: [PATCH 134/283] more compiling --- channeld/channeld.c | 7 ++++ channeld/channeld_htlc.h | 28 ++++++------- channeld/channeld_wire.csv | 4 +- channeld/eltoo_channeld.c | 12 +++--- channeld/eltoo_full_channel.c | 74 +++++++++++++++++------------------ common/htlc.h | 16 +------- common/htlc_state.c | 13 +----- common/htlc_state.h | 34 +++++++--------- common/htlc_wire.h | 1 - lightningd/channel_control.c | 7 ++++ 10 files changed, 87 insertions(+), 109 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 336e023dcb46..6475ded381b8 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3740,6 +3740,13 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: case WIRE_CHANNELD_GOT_UPDATESIG: + case WIRE_CHANNELD_GOT_UPDATESIG_REPLY: + case WIRE_CHANNELD_GOT_ACK: + case WIRE_CHANNELD_GOT_SHUTDOWN_ELTOO: + case WIRE_CHANNELD_SENDING_UPDATESIG: + case WIRE_CHANNELD_SENDING_UPDATESIG_REPLY: + case WIRE_CHANNELD_INIT_ELTOO: + case WIRE_CHANNELD_GOT_ACK_REPLY: break; } master_badmsg(-1, msg); diff --git a/channeld/channeld_htlc.h b/channeld/channeld_htlc.h index 3177a88b8d58..223707199065 100644 --- a/channeld/channeld_htlc.h +++ b/channeld/channeld_htlc.h @@ -9,8 +9,6 @@ struct htlc { /* What's the status. */ enum htlc_state state; - /* FIXME Can this live here? */ - enum eltoo_htlc_state eltoo_state; /* The unique ID for this peer and this direction (LOCAL or REMOTE) */ u64 id; /* The amount in millisatoshi. */ @@ -42,7 +40,7 @@ static inline bool htlc_has(const struct htlc *h, int flag) static inline bool eltoo_htlc_has(const struct htlc *h, int flag) { - return eltoo_htlc_state_flags(h->state) & flag; + return eltoo_htlc_state_flags(h->state) & flag; } static inline enum side htlc_owner(const struct htlc *h) @@ -50,11 +48,6 @@ static inline enum side htlc_owner(const struct htlc *h) return htlc_state_owner(h->state); } -static inline enum side eltoo_htlc_owner(const struct htlc *h) -{ - return eltoo_htlc_state_owner(h->eltoo_state); -} - /* htlc_map: ID -> htlc mapping. */ static inline u64 htlc_key(const struct htlc *h) { @@ -86,17 +79,18 @@ static inline struct htlc *htlc_get(struct htlc_map *htlcs, u64 id, enum side ow static inline struct htlc *eltoo_htlc_get(struct htlc_map *htlcs, u64 id, enum side owner) { - struct htlc *h; - struct htlc_map_iter it; + struct htlc *h; + struct htlc_map_iter it; - for (h = htlc_map_getfirst(htlcs, id, &it); - h; - h = htlc_map_getnext(htlcs, id, &it)) { - if (h->id == id && eltoo_htlc_has(h, HTLC_FLAG(owner,HTLC_F_OWNER))) - return h; - } - return NULL; + for (h = htlc_map_getfirst(htlcs, id, &it); + h; + h = htlc_map_getnext(htlcs, id, &it)) { + if (h->id == id && eltoo_htlc_has(h, HTLC_FLAG(owner,HTLC_F_OWNER))) + return h; + } + return NULL; } + /* FIXME: Move these out of the hash! */ static inline bool htlc_is_dead(const struct htlc *htlc) { diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 967c761eaff2..4c33ebdb7b68 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -279,7 +279,7 @@ msgdata,channeld_blockheight,blockheight,u32, # ELTOO STUFF # Begin! (passes gossipd-client fd) -msgtype,channeld_init_eltoo,1000 +msgtype,channeld_init_eltoo,1060 msgdata,channeld_init_eltoo,chainparams,chainparams, msgdata,channeld_init_eltoo,our_features,feature_set, msgdata,channeld_init_eltoo,channel_id,channel_id, @@ -373,7 +373,7 @@ msgdata,channeld_got_ack,changed,changed_htlc,num_changed msgdata,channeld_got_ack,update_sig,bip340sig, # Wait for reply, to make sure it's on disk before we continue # (eg. if we sent another commitment_signed, that would implicitly ack). -msgtype,channeld_got_ack_reply,1122 +msgtype,channeld_got_ack_reply,1182 # Peer told us that channel is shutting down msgtype,channeld_got_shutdown_eltoo,1084 diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 097eaa70cc71..382ce2ef5e2b 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1064,7 +1064,7 @@ static void marshall_htlc_info(const tal_t *ctx, for (size_t i = 0; i < tal_count(changed_htlcs); i++) { const struct htlc *htlc = changed_htlcs[i]; - if (htlc->eltoo_state == RCVD_ADD_UPDATE) { + if (htlc->state == RCVD_ADD_UPDATE) { struct added_htlc a; a.id = htlc->id; @@ -1081,7 +1081,7 @@ static void marshall_htlc_info(const tal_t *ctx, a.blinding = NULL; a.fail_immediate = htlc->fail_immediate; tal_arr_expand(added, a); - } else if (htlc->eltoo_state == RCVD_REMOVE_UPDATE) { + } else if (htlc->state == RCVD_REMOVE_UPDATE) { if (htlc->r) { struct fulfilled_htlc f; assert(!htlc->failed); @@ -1094,11 +1094,11 @@ static void marshall_htlc_info(const tal_t *ctx, } } else { struct changed_htlc c; - assert(htlc->eltoo_state == RCVD_REMOVE_ACK - || htlc->eltoo_state == RCVD_ADD_ACK); + assert(htlc->state == RCVD_REMOVE_ACK + || htlc->state == RCVD_ADD_ACK); c.id = htlc->id; - c.eltoo_newstate = htlc->eltoo_state; + c.newstate = htlc->state; tal_arr_expand(changed, c); } } @@ -1271,7 +1271,7 @@ static u8 *got_signed_ack_msg(struct peer *peer, htlc_state_name(htlc->state)); c.id = changed_htlcs[i]->id; - c.eltoo_newstate = changed_htlcs[i]->eltoo_state; + c.newstate = changed_htlcs[i]->state; tal_arr_expand(&changed, c); } diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 7cd70513cc0f..d76334b7a322 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -128,20 +128,20 @@ static void htlc_arr_append(const struct htlc ***arr, const struct htlc *htlc) static void dump_htlc(const struct htlc *htlc, const char *prefix) { - enum eltoo_htlc_state remote_state; - enum eltoo_htlc_state state = htlc->eltoo_state; + enum htlc_state remote_state; + enum htlc_state state = htlc->state; - if (htlc->eltoo_state <= SENT_REMOVE_ACK) - remote_state = state + 6; + if (htlc->state <= SENT_REMOVE_ACK) + remote_state = state + 10; else - remote_state = state - 6; + remote_state = state - 10; status_debug("%s: HTLC %s %"PRIu64" = %s/%s %s", prefix, - eltoo_htlc_state_owner(state) == LOCAL ? "LOCAL" : "REMOTE", + htlc_state_owner(state) == LOCAL ? "LOCAL" : "REMOTE", htlc->id, - eltoo_htlc_state_name(state), - eltoo_htlc_state_name(remote_state), + htlc_state_name(state), + htlc_state_name(remote_state), htlc->r ? "FULFILLED" : htlc->failed ? "FAILED" : ""); } @@ -349,7 +349,7 @@ static size_t num_untrimmed_htlcs(enum side side, } static enum channel_add_err add_htlc(struct eltoo_channel *channel, - enum eltoo_htlc_state state, + enum htlc_state state, u64 id, struct amount_msat amount, u32 cltv_expiry, @@ -364,7 +364,7 @@ static enum channel_add_err add_htlc(struct eltoo_channel *channel, struct htlc *htlc, *old; struct amount_msat msat_in_htlcs, committed_msat, adding_msat, removing_msat, htlc_dust_amt; - enum side sender = eltoo_htlc_state_owner(state), recipient = !sender; + enum side sender = htlc_state_owner(state), recipient = !sender; const struct htlc **committed, **adding, **removing; const struct channel_view *view; size_t htlc_count; @@ -533,7 +533,7 @@ enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, bool err_immediate_failures) { /* FIXME figure out HTLC state machine for eltoo */ - enum eltoo_htlc_state state; + enum htlc_state state; if (sender == LOCAL) state = SENT_ADD_HTLC; @@ -595,7 +595,7 @@ enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, */ if (!eltoo_htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", - htlc->id, htlc_state_name(htlc->eltoo_state)); + htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_UNCOMMITTED; } @@ -610,13 +610,13 @@ enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, * - MUST NOT send an `update_fulfill_htlc`, `update_fail_htlc`, or * `update_fail_malformed_htlc`. */ - if (htlc->eltoo_state == RCVD_ADD_ACK) - htlc->eltoo_state = RCVD_REMOVE_HTLC; - else if (htlc->eltoo_state == SENT_ADD_ACK) - htlc->eltoo_state = SENT_REMOVE_HTLC; + if (htlc->state == RCVD_ADD_ACK) + htlc->state = RCVD_REMOVE_HTLC; + else if (htlc->state == SENT_ADD_ACK) + htlc->state = SENT_REMOVE_HTLC; else { status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", - htlc->id, htlc_state_name(htlc->eltoo_state)); + htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; } @@ -648,19 +648,19 @@ enum channel_remove_err channel_fail_htlc(struct eltoo_channel *channel, */ if (!eltoo_htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { status_unusual("channel_fail_htlc: %"PRIu64" in state %s", - htlc->id, eltoo_htlc_state_name(htlc->eltoo_state)); + htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_UNCOMMITTED; } /* FIXME: Technically, they can fail this before we're committed to * it. This implies a non-linear state machine. */ - if (htlc->eltoo_state == SENT_ADD_ACK) - htlc->eltoo_state = SENT_REMOVE_HTLC; - else if (htlc->eltoo_state == RCVD_ADD_ACK) - htlc->eltoo_state = RCVD_REMOVE_HTLC; + if (htlc->state == SENT_ADD_ACK) + htlc->state = SENT_REMOVE_HTLC; + else if (htlc->state == RCVD_ADD_ACK) + htlc->state = RCVD_REMOVE_HTLC; else { status_unusual("channel_fail_htlc: %"PRIu64" in state %s", - htlc->id, eltoo_htlc_state_name(htlc->eltoo_state)); + htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; } @@ -679,16 +679,16 @@ static void htlc_incstate(struct eltoo_channel *channel, const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED); status_debug("htlc %"PRIu64": %s->%s", htlc->id, - eltoo_htlc_state_name(htlc->eltoo_state), - eltoo_htlc_state_name(htlc->eltoo_state+1)); + htlc_state_name(htlc->state), + htlc_state_name(htlc->state+1)); - preflags = eltoo_htlc_state_flags(htlc->eltoo_state); - postflags = eltoo_htlc_state_flags(htlc->eltoo_state + 1); + preflags = eltoo_htlc_state_flags(htlc->state); + postflags = eltoo_htlc_state_flags(htlc->state + 1); /* You can't change sides. */ assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); - htlc->eltoo_state++; + htlc->state++; /* If we've added or removed, adjust balances. */ if (!(preflags & committed_f) && (postflags & committed_f)) { @@ -713,7 +713,7 @@ static void htlc_incstate(struct eltoo_channel *channel, /* Returns flags which were changed. */ static int change_htlcs(struct eltoo_channel *channel, enum side sidechanged, - const enum eltoo_htlc_state *htlc_states, + const enum htlc_state *htlc_states, size_t n_hstates, const struct htlc ***htlcs, const char *prefix) @@ -731,12 +731,12 @@ static int change_htlcs(struct eltoo_channel *channel, h; h = htlc_map_next(channel->htlcs, &it)) { for (i = 0; i < n_hstates; i++) { - if (h->eltoo_state == htlc_states[i]) { + if (h->state == htlc_states[i]) { htlc_incstate(channel, h, sidechanged, owed); dump_htlc(h, prefix); htlc_arr_append(htlcs, h); cflags |= (eltoo_htlc_state_flags(htlc_states[i]) - ^ eltoo_htlc_state_flags(h->eltoo_state)); + ^ eltoo_htlc_state_flags(h->state)); } } } @@ -839,7 +839,7 @@ bool channel_sending_update(struct eltoo_channel *channel, const struct htlc ***htlcs) { int change; - const enum eltoo_htlc_state states[] = { SENT_ADD_HTLC, + const enum htlc_state states[] = { SENT_ADD_HTLC, SENT_REMOVE_HTLC }; status_debug("Trying update"); @@ -869,7 +869,7 @@ bool channel_rcvd_update_sign_ack(struct channel *channel, bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs) { int change; - const enum eltoo_htlc_state states[] = { RCVD_ADD_UPDATE, + const enum htlc_state states[] = { RCVD_ADD_UPDATE, RCVD_REMOVE_HTLC, RCVD_ADD_HTLC, RCVD_REMOVE_UPDATE }; @@ -935,7 +935,7 @@ static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES], if (!htlc->failed && !htlc->r) { status_broken("%s HTLC %"PRIu64 " %s neither fail nor fulfill?", - eltoo_htlc_state_owner(htlc->eltoo_state) == LOCAL + htlc_state_owner(htlc->state) == LOCAL ? "out" : "in", htlc->id, htlc_state_name(htlc->state)); @@ -959,7 +959,7 @@ bool pending_updates(const struct eltoo_channel *channel, for (htlc = htlc_map_first(channel->htlcs, &it); htlc; htlc = htlc_map_next(channel->htlcs, &it)) { - int flags = htlc_state_flags(htlc->state); + int flags = eltoo_htlc_state_flags(htlc->state); /* If it's still being added, its owner added it. */ if (flags & HTLC_ADDING) { @@ -970,7 +970,7 @@ bool pending_updates(const struct eltoo_channel *channel, if (htlc_owner(htlc) == side) return true; /* If it's being removed, non-owner removed it */ - } else if (htlc_state_flags(htlc->state) & HTLC_REMOVING) { + } else if (eltoo_htlc_state_flags(htlc->state) & HTLC_REMOVING) { /* It might be OK if it's removed, but not committed */ if (uncommitted_ok && (flags & HTLC_FLAG(!side, HTLC_F_PENDING))) @@ -1025,7 +1025,7 @@ bool channel_force_htlcs(struct eltoo_channel *channel, &htlc, false, NULL, false); if (e != CHANNEL_ERR_ADD_OK) { status_broken("%s HTLC %"PRIu64" failed error %u", - eltoo_htlc_state_owner(htlcs[i]->eltoo_state) == LOCAL + htlc_state_owner(htlcs[i]->state) == LOCAL ? "out" : "in", htlcs[i]->id, e); return false; } diff --git a/common/htlc.h b/common/htlc.h index f403e6e3f81a..0685cab7daae 100644 --- a/common/htlc.h +++ b/common/htlc.h @@ -44,6 +44,7 @@ enum side { const char *htlc_state_name(enum htlc_state s); int htlc_state_flags(enum htlc_state state); +int eltoo_htlc_state_flags(enum htlc_state state); static inline enum side htlc_state_owner(enum htlc_state state) { @@ -60,21 +61,6 @@ static inline enum side htlc_state_owner(enum htlc_state state) } } -static inline enum side eltoo_htlc_state_owner(enum eltoo_htlc_state state) -{ - if (state < RCVD_ADD_HTLC) { - assert((eltoo_htlc_state_flags(state) - & (HTLC_REMOTE_F_OWNER|HTLC_LOCAL_F_OWNER)) - == HTLC_LOCAL_F_OWNER); - return LOCAL; - } else { - assert((eltoo_htlc_state_flags(state) - & (HTLC_REMOTE_F_OWNER|HTLC_LOCAL_F_OWNER)) - == HTLC_REMOTE_F_OWNER); - return REMOTE; - } -} - static inline const char *side_to_str(enum side side) { switch (side) { diff --git a/common/htlc_state.c b/common/htlc_state.c index f02a022c0ba9..9dd4d8c93e67 100644 --- a/common/htlc_state.c +++ b/common/htlc_state.c @@ -139,16 +139,6 @@ int htlc_state_flags(enum htlc_state state) return per_state_bits[state]; } -const char *eltoo_htlc_state_name(enum eltoo_htlc_state s) -{ - size_t i; - - for (i = 0; enum_eltoo_htlc_state_names[i].name; i++) - if (enum_eltoo_htlc_state_names[i].v == s) - return enum_eltoo_htlc_state_names[i].name; - return "unknown"; -} - /* This is the flags for each state. */ /* FIXME someone how knows this has to look at it ... */ static const int eltoo_per_state_bits[] = { @@ -217,10 +207,9 @@ static const int eltoo_per_state_bits[] = { + HTLC_REMOTE_F_WAS_COMMITTED, }; -int eltoo_htlc_state_flags(enum eltoo_htlc_state state) +int eltoo_htlc_state_flags(enum htlc_state state) { assert(state < ARRAY_SIZE(eltoo_per_state_bits)); assert(eltoo_per_state_bits[state]); return eltoo_per_state_bits[state]; } - diff --git a/common/htlc_state.h b/common/htlc_state.h index d107943430fd..3a8dcaacf77f 100644 --- a/common/htlc_state.h +++ b/common/htlc_state.h @@ -38,28 +38,24 @@ enum htlc_state { HTLC_STATE_INVALID }; -enum eltoo_htlc_state { - /* When _we_ add a new htlc, it goes in this order. */ - SENT_ADD_HTLC, /* --update_add_htlc--> */ - SENT_ADD_UPDATE, /* --update_signed--> */ - RCVD_ADD_ACK, /* <--update_signed_ack-- */ +/* Eltoo: Only first three states in htlc_state are used */ - /* ... then when _they_ remove the HTLC: */ - RCVD_REMOVE_HTLC, /* <--update_{fulfill,fail,fail_malformed}_htlc-- */ - RCVD_REMOVE_UPDATE, /* rest of messages same as "add", in reverse direction */ - SENT_REMOVE_ACK, +/* SENT_ADD_HTLC is same*/ +#define SENT_ADD_UPDATE (SENT_ADD_COMMIT) +#define RCVD_ADD_ACK (RCVD_ADD_REVOCATION) - /* When _they_ add a new htlc, it goes in this order. */ - RCVD_ADD_HTLC, - RCVD_ADD_UPDATE, - SENT_ADD_ACK, +/* SENT_REMOVE_HTLC is same */ +#define SENT_REMOVE_UPDATE (SENT_REMOVE_COMMIT) +#define RCVD_REMOVE_ACK (RCVD_REMOVE_REVOCATION) - /* ... then when _we_ remove the HTLC: */ - SENT_REMOVE_HTLC, - SENT_REMOVE_UPDATE, - RCVD_REMOVE_ACK, +/* RCVD_ADD_HTLC is same*/ +#define RCVD_ADD_UPDATE (RCVD_ADD_COMMIT) +#define SENT_ADD_ACK (SENT_ADD_REVOCATION) - HTLC_STATE_INVALID -}; +/* RCVD_REMOVE_HTLC is same */ +#define RCVD_REMOVE_UPDATE (RCVD_REMOVE_COMMIT) +#define SENT_REMOVE_ACK (SENT_REMOVE_REVOCATION) + +/* HTLC_STATE_INVALID is same */ #endif /* LIGHTNING_COMMON_HTLC_STATE_H */ diff --git a/common/htlc_wire.h b/common/htlc_wire.h index 6ee8ee3466cc..b89b5961a90b 100644 --- a/common/htlc_wire.h +++ b/common/htlc_wire.h @@ -60,7 +60,6 @@ struct failed_htlc { struct changed_htlc { enum htlc_state newstate; - enum eltoo_htlc_state eltoo_newstate; u64 id; }; diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index a0be1b5da13b..d59a9c6c062d 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -554,6 +554,13 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_GOT_UPDATESIG: /* FIXME handle this */ break; + case WIRE_CHANNELD_INIT_ELTOO: + case WIRE_CHANNELD_GOT_UPDATESIG_REPLY: + case WIRE_CHANNELD_GOT_ACK: + case WIRE_CHANNELD_GOT_ACK_REPLY: + case WIRE_CHANNELD_GOT_SHUTDOWN_ELTOO: + case WIRE_CHANNELD_SENDING_UPDATESIG: + case WIRE_CHANNELD_SENDING_UPDATESIG_REPLY: #if EXPERIMENTAL_FEATURES case WIRE_CHANNELD_UPGRADED: handle_channel_upgrade(sd->channel, msg); From 398a9e9d81cedaad2f02c93e31476522bcea0e09 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 18 Aug 2022 15:51:00 -0400 Subject: [PATCH 135/283] eltoo_channeld starting to compile --- channeld/Makefile | 27 ++++++++++++++++++++++++--- channeld/test/Makefile | 2 +- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/channeld/Makefile b/channeld/Makefile index 295fef246838..250724f2cb62 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -21,10 +21,29 @@ CHANNELD_SRC := channeld/channeld.c \ CHANNELD_OBJS := $(CHANNELD_SRC:.c=.o) $(CHANNELD_OBJS): $(CHANNELD_HEADERS) +ELTOO_CHANNELD_HEADERS := \ + channeld/full_channel_error_names_gen.h \ + channeld/channeld_wiregen.h \ + channeld/channeld_htlc.h \ + channeld/eltoo_channeld.h \ + channeld/eltoo_full_channel.h \ + channeld/full_channel_error.h \ + channeld/settle_tx.h \ + channeld/watchtower.h + +ELTOO_CHANNELD_SRC := channeld/eltoo_channeld.c \ + channeld/eltoo_full_channel.c \ + channeld/channeld_wiregen.c \ + channeld/settle_tx.c \ + channeld/watchtower.c + +ELTOO_CHANNELD_OBJS := $(ELTOO_CHANNELD_SRC:.c=.o) +$(ELTOO_CHANNELD_OBJS): $(ELTOO_CHANNELD_HEADERS) + # Make sure these depend on everything. -ALL_C_SOURCES += $(CHANNELD_SRC) -ALL_C_HEADERS += $(CHANNELD_HEADERS) -ALL_PROGRAMS += lightningd/lightning_channeld +ALL_C_SOURCES += $(ELTOO_CHANNELD_SRC) $(CHANNELD_SRC) +ALL_C_HEADERS += $(ELTOO_CHANNELD_HEADERS) $(CHANNELD_HEADERS) +ALL_PROGRAMS += lightningd/lightning_channeld lightningd/lightning_eltoo_channeld # Here's what lightningd depends on LIGHTNINGD_CONTROL_HEADERS += channeld/channeld_wiregen.h @@ -104,4 +123,6 @@ channeld/full_channel_error_names_gen.h: channeld/full_channel_error.h ccan/ccan lightningd/lightning_channeld: $(CHANNELD_OBJS) $(WIRE_ONION_OBJS) $(CHANNELD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS) +lightningd/lightning_eltoo_channeld: $(ELTOO_CHANNELD_OBJS) $(WIRE_ONION_OBJS) $(CHANNELD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS) + include channeld/test/Makefile diff --git a/channeld/test/Makefile b/channeld/test/Makefile index ff98e7e1b128..81c4750cddeb 100644 --- a/channeld/test/Makefile +++ b/channeld/test/Makefile @@ -29,6 +29,6 @@ CHANNELD_TEST_COMMON_OBJS := \ $(CHANNELD_TEST_PROGRAMS): $(CCAN_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CHANNELD_TEST_COMMON_OBJS) -$(CHANNELD_TEST_OBJS): $(CHANNELD_HEADERS) $(CHANNELD_SRC) +$(CHANNELD_TEST_OBJS): $(CHANNELD_HEADERS) $(CHANNELD_SRC) $(ELTOO_CHANNELD_SRC) check-units: $(CHANNELD_TEST_PROGRAMS:%=unittest/%) From 8dc1b52920d5cdfcba26d100dd7faf5ff0f2359b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 18 Aug 2022 16:43:52 -0400 Subject: [PATCH 136/283] Adding more files --- channeld/channeld_wire.csv | 1 - channeld/eltoo_channeld.c | 239 +-------- channeld/eltoo_full_channel.h | 17 +- lightningd/eltoo_channel.c | 937 ++++++++++++++++++++++++++++++++++ lightningd/eltoo_channel.h | 481 +++++++++++++++++ 5 files changed, 1446 insertions(+), 229 deletions(-) create mode 100644 lightningd/eltoo_channel.c create mode 100644 lightningd/eltoo_channel.h diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 4c33ebdb7b68..abb71d475a3e 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -286,7 +286,6 @@ msgdata,channeld_init_eltoo,channel_id,channel_id, msgdata,channeld_init_eltoo,funding,bitcoin_outpoint, msgdata,channeld_init_eltoo,funding_satoshi,amount_sat, msgdata,channeld_init_eltoo,minimum_depth,u32, -msgdata,channeld_init_eltoo,our_blockheight,u32, msgdata,channeld_init_eltoo,our_config,channel_config, msgdata,channeld_init_eltoo,their_config,channel_config, msgdata,channeld_init_eltoo,feerate_min,u32, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 382ce2ef5e2b..325744581591 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -141,8 +141,8 @@ struct eltoo_peer { bool last_was_revoke; struct changed_htlc *last_sent_commit; u64 revocations_received; - u8 channel_flags; */ + u8 channel_flags; /* Number of update_signed(_ack) messages received by peer */ u64 updates_received; @@ -283,35 +283,6 @@ static bool handle_master_request_later(struct eltoo_peer *peer, const u8 *msg) return false; } -/* Compare, with false if either is NULL */ -static bool match_type(const u8 *t1, const u8 *t2) -{ - /* Missing fields are possible. */ - if (!t1 || !t2) - return false; - - return featurebits_eq(t1, t2); -} - -static void set_channel_type(struct eltoo_channel *channel, const u8 *type) -{ - const struct channel_type *cur = channel->type; - - if (featurebits_eq(cur->features, type)) - return; - - /* We only allow one upgrade at the moment, so that's it. */ - assert(!channel_has(channel, OPT_STATIC_REMOTEKEY)); - assert(feature_offered(type, OPT_STATIC_REMOTEKEY)); - - /* Do upgrade, tell master. */ - tal_free(channel->type); - channel->type = channel_type_from(channel, type); - status_unusual("Upgraded channel to [%s]", - fmt_featurebits(tmpctx, type)); - wire_sync_write(MASTER_FD, - take(towire_channeld_upgraded(NULL, channel->type))); -} #else /* !EXPERIMENTAL_FEATURES */ static bool handle_master_request_later(struct peer *peer, const u8 *msg) { @@ -703,13 +674,14 @@ static u8 *sending_updatesig_msg(const tal_t *ctx, return msg; } -static bool shutdown_complete(const struct peer *peer) +static bool shutdown_complete(const struct eltoo_peer *peer) { + /* FIXME last line is very wrong */ return peer->shutdown_sent[LOCAL] && peer->shutdown_sent[REMOTE] && num_channel_htlcs(peer->channel) == 0 /* We could be awaiting revoke-and-ack for a feechange */ - && peer->revocations_received == peer->next_index - 1; + && peer->updates_received == peer->next_index - 1; } @@ -751,7 +723,7 @@ static void maybe_send_shutdown(struct eltoo_peer *peer) billboard_update(peer); } -static void send_shutdown_complete(struct peer *peer) +static void send_shutdown_complete(struct eltoo_peer *peer) { /* Now we can tell master shutdown is complete. */ wire_sync_write(MASTER_FD, @@ -798,127 +770,6 @@ static u8 *master_wait_sync_reply(const tal_t *ctx, return reply; } -/* Collect the htlcs for call to hsmd. */ -static struct simple_htlc **collect_htlcs(const tal_t *ctx, const struct htlc **htlc_map) -{ - struct simple_htlc **htlcs; - - htlcs = tal_arr(ctx, struct simple_htlc *, 0); - size_t num_entries = tal_count(htlc_map); - for (size_t ndx = 0; ndx < num_entries; ++ndx) { - struct htlc const *hh = htlc_map[ndx]; - if (hh) { - struct simple_htlc *simple = - new_simple_htlc(htlcs, - htlc_state_owner(hh->state), - hh->amount, - &hh->rhash, - hh->expiry.locktime); - tal_arr_expand(&htlcs, simple); - } - } - return htlcs; -} - -/* Returns HTLC sigs, sets commit_sig */ -static struct bitcoin_signature *calc_commitsigs(const tal_t *ctx, - const struct peer *peer, - struct bitcoin_tx **txs, - const u8 *funding_wscript, - const struct htlc **htlc_map, - u64 commit_index, - struct bitcoin_signature *commit_sig) -{ - struct simple_htlc **htlcs; - size_t i; - struct pubkey local_htlckey; - const u8 *msg; - struct bitcoin_signature *htlc_sigs; - - htlcs = collect_htlcs(tmpctx, htlc_map); - msg = towire_hsmd_sign_remote_commitment_tx(NULL, txs[0], - &peer->channel->funding_pubkey[REMOTE], - &peer->remote_per_commit, - channel_has(peer->channel, - OPT_STATIC_REMOTEKEY), - commit_index, - (const struct simple_htlc **) htlcs, - channel_feerate(peer->channel, REMOTE)); - - msg = hsm_req(tmpctx, take(msg)); - if (!fromwire_hsmd_sign_tx_reply(msg, commit_sig)) - status_failed(STATUS_FAIL_HSM_IO, - "Reading sign_remote_commitment_tx reply: %s", - tal_hex(tmpctx, msg)); - - status_debug("Creating commit_sig signature %"PRIu64" %s for tx %s wscript %s key %s", - commit_index, - type_to_string(tmpctx, struct bitcoin_signature, - commit_sig), - type_to_string(tmpctx, struct bitcoin_tx, txs[0]), - tal_hex(tmpctx, funding_wscript), - type_to_string(tmpctx, struct pubkey, - &peer->channel->funding_pubkey[LOCAL])); - dump_htlcs(peer->channel, "Sending commit_sig"); - - if (!derive_simple_key(&peer->channel->basepoints[LOCAL].htlc, - &peer->remote_per_commit, - &local_htlckey)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Deriving local_htlckey"); - - /* BOLT #2: - * - * A sending node: - *... - * - MUST include one `htlc_signature` for every HTLC transaction - * corresponding to the ordering of the commitment transaction - */ - htlc_sigs = tal_arr(ctx, struct bitcoin_signature, tal_count(txs) - 1); - - for (i = 0; i < tal_count(htlc_sigs); i++) { - u8 *wscript; - - wscript = bitcoin_tx_output_get_witscript(tmpctx, txs[0], - txs[i+1]->wtx->inputs[0].index); - msg = towire_hsmd_sign_remote_htlc_tx(NULL, txs[i + 1], wscript, - &peer->remote_per_commit, - channel_has(peer->channel, - OPT_ANCHOR_OUTPUTS)); - - msg = hsm_req(tmpctx, take(msg)); - if (!fromwire_hsmd_sign_tx_reply(msg, &htlc_sigs[i])) - status_failed(STATUS_FAIL_HSM_IO, - "Bad sign_remote_htlc_tx reply: %s", - tal_hex(tmpctx, msg)); - - status_debug("Creating HTLC signature %s for tx %s wscript %s key %s", - type_to_string(tmpctx, struct bitcoin_signature, - &htlc_sigs[i]), - type_to_string(tmpctx, struct bitcoin_tx, txs[1+i]), - tal_hex(tmpctx, wscript), - type_to_string(tmpctx, struct pubkey, - &local_htlckey)); - assert(check_tx_sig(txs[1+i], 0, NULL, wscript, - &local_htlckey, - &htlc_sigs[i])); - } - - return htlc_sigs; -} - -/* Peer protocol doesn't want sighash flags. */ -static secp256k1_ecdsa_signature *raw_sigs(const tal_t *ctx, - const struct bitcoin_signature *sigs) -{ - secp256k1_ecdsa_signature *raw; - - raw = tal_arr(ctx, secp256k1_ecdsa_signature, tal_count(sigs)); - for (size_t i = 0; i < tal_count(sigs); i++) - raw[i] = sigs[i].s; - return raw; -} - static void send_update(struct eltoo_peer *peer) { u8 *msg; @@ -1044,7 +895,7 @@ static void start_update_timer(struct eltoo_peer *peer) send_update, peer); } -static u8 *make_update_signed_ack_msg(const struct peer *peer) +static u8 *make_update_signed_ack_msg(const struct eltoo_peer *peer) { return towire_update_signed_ack(peer, &peer->channel_id, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.self_next_nonce); } @@ -1631,7 +1482,7 @@ static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) &channel_id)); } -static void peer_in(struct peer *elto_peer, const u8 *msg) +static void peer_in(struct eltoo_peer *peer, const u8 *msg) { enum peer_wire type = fromwire_peektype(msg); @@ -1789,59 +1640,8 @@ static void send_fail_or_fulfill(struct eltoo_peer *peer, const struct htlc *h) peer_write(peer->pps, take(msg)); } -static int cmp_changed_htlc_id(const struct changed_htlc *a, - const struct changed_htlc *b, - void *unused) -{ - /* ids can be the same (sender and receiver are indep) but in - * that case we don't care about order. */ - if (a->id > b->id) - return 1; - else if (a->id < b->id) - return -1; - return 0; -} - -/* Older LND sometimes sends funding_locked before reestablish! */ -/* ... or announcement_signatures. Sigh, let's handle whatever they send. */ -static bool capture_premature_msg(const u8 ***shit_lnd_says, const u8 *msg) -{ - if (fromwire_peektype(msg) == WIRE_CHANNEL_REESTABLISH) - return false; - - /* Don't allow infinite memory consumption. */ - if (tal_count(*shit_lnd_says) > 10) - return false; - - status_debug("Stashing early %s msg!", - peer_wire_name(fromwire_peektype(msg))); - - tal_arr_expand(shit_lnd_says, tal_steal(*shit_lnd_says, msg)); - return true; -} - -#if EXPERIMENTAL_FEATURES -/* Unwrap a channel_type into a raw byte array for the wire: can be NULL */ -static u8 *to_bytearr(const tal_t *ctx, - const struct channel_type *channel_type TAKES) -{ - u8 *ret; - bool steal; - - steal = taken(channel_type); - if (!channel_type) - return NULL; - - if (steal) { - ret = tal_steal(ctx, channel_type->features); - tal_free(channel_type); - } else - ret = tal_dup_talarr(ctx, u8, channel_type->features); - return ret; -} - /* FIXME Reconnect fun! Let's compile first. :) */ -static void peer_reconnect(struct peer *peer, +static void peer_reconnect(struct eltoo_peer *peer, bool reestablish_only) { } @@ -2282,6 +2082,16 @@ static void req_in(struct eltoo_peer *peer, const u8 *msg) case WIRE_CHANNELD_LOCAL_CHANNEL_UPDATE: case WIRE_CHANNELD_LOCAL_CHANNEL_ANNOUNCEMENT: case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: + /* FIXME deal with these? */ + case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: + case WIRE_CHANNELD_GOT_UPDATESIG: + case WIRE_CHANNELD_GOT_UPDATESIG_REPLY: + case WIRE_CHANNELD_GOT_ACK: + case WIRE_CHANNELD_GOT_ACK_REPLY: + case WIRE_CHANNELD_GOT_SHUTDOWN_ELTOO: + case WIRE_CHANNELD_SENDING_UPDATESIG: + case WIRE_CHANNELD_SENDING_UPDATESIG_REPLY: + case WIRE_CHANNELD_INIT_ELTOO: break; } master_badmsg(-1, msg); @@ -2316,14 +2126,13 @@ static void init_channel(struct eltoo_peer *peer) assert(!(fcntl(MASTER_FD, F_GETFL) & O_NONBLOCK)); msg = wire_sync_read(tmpctx, MASTER_FD); - if (!fromwire_channeld_init(peer, msg, + if (!fromwire_channeld_init_eltoo(peer, msg, &chainparams, &peer->our_features, &peer->channel_id, &funding, &funding_sats, &minimum_depth, - &peer->our_blockheight, &conf[LOCAL], &conf[REMOTE], &peer->feerate_min, &peer->feerate_max, @@ -2386,7 +2195,7 @@ static void init_channel(struct eltoo_peer *peer) status_debug("init %s: " " next_idx = %"PRIu64 " updates_received = %"PRIu64 - " feerates %s range %u-%u" + " feerates %s range %u-%u", side_to_str(opener), peer->next_index, peer->next_index, peer->updates_received, @@ -2435,10 +2244,6 @@ static void init_channel(struct eltoo_peer *peer) peer->channel_direction = node_id_idx(&peer->node_ids[LOCAL], &peer->node_ids[REMOTE]); - /* Default desired feerate is the feerate we set for them last. */ - if (peer->channel->opener == LOCAL) - peer->desired_feerate = channel_feerate(peer->channel, REMOTE); - /* from now we need keep watch over WIRE_CHANNELD_FUNDING_DEPTH */ peer->depth_togo = minimum_depth; @@ -2464,13 +2269,13 @@ int main(int argc, char *argv[]) int i, nfds; fd_set fds_in, fds_out; - struct peer *peer; + struct eltoo_peer *peer; subdaemon_setup(argc, argv); status_setup_sync(MASTER_FD); - peer = tal(NULL, struct peer); + peer = tal(NULL, struct eltoo_peer); timers_init(&peer->timers, time_mono()); peer->commit_timer = NULL; peer->have_sigs[LOCAL] = peer->have_sigs[REMOTE] = false; diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h index 13de18d0ff8f..fc71702382ce 100644 --- a/channeld/eltoo_full_channel.h +++ b/channeld/eltoo_full_channel.h @@ -7,7 +7,7 @@ #include #include -struct eltoo_channel_id; +struct channel_id; struct existing_htlc; /** @@ -33,22 +33,17 @@ struct existing_htlc; * * Returns state, or NULL if malformed. */ -struct eltoo_channel *new_full_channel(const tal_t *ctx, - const struct eltoo_channel_id *cid, +struct eltoo_channel *new_full_eltoo_channel(const tal_t *ctx, + const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, - const struct height_states *blockheight_states, - u32 lease_expiry, struct amount_sat funding_sats, struct amount_msat local_msat, - const struct fee_states *fee_states TAKES, - const struct eltoo_channel_config *local, - const struct eltoo_channel_config *remote, - const struct basepoints *local_basepoints, - const struct basepoints *remote_basepoints, + const struct channel_config *local, + const struct channel_config *remote, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, - const struct eltoo_channel_type *type TAKES, + const struct channel_type *type TAKES, bool option_wumbo, enum side opener); diff --git a/lightningd/eltoo_channel.c b/lightningd/eltoo_channel.c new file mode 100644 index 000000000000..789d75554161 --- /dev/null +++ b/lightningd/eltoo_channel.c @@ -0,0 +1,937 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void channel_set_owner(struct channel *channel, struct subd *owner) +{ + struct subd *old_owner = channel->owner; + channel->owner = owner; + + if (old_owner) { + subd_release_channel(old_owner, channel); + if (channel->connected) + maybe_disconnect_peer(channel->peer->ld, channel->peer); + } + channel->connected = (owner && owner->talks_to_peer); +} + +struct htlc_out *channel_has_htlc_out(struct channel *channel) +{ + struct htlc_out_map_iter outi; + struct htlc_out *hout; + struct lightningd *ld = channel->peer->ld; + + for (hout = htlc_out_map_first(&ld->htlcs_out, &outi); + hout; + hout = htlc_out_map_next(&ld->htlcs_out, &outi)) { + if (hout->key.channel == channel) + return hout; + } + + return NULL; +} + +struct htlc_in *channel_has_htlc_in(struct channel *channel) +{ + struct htlc_in_map_iter ini; + struct htlc_in *hin; + struct lightningd *ld = channel->peer->ld; + + for (hin = htlc_in_map_first(&ld->htlcs_in, &ini); + hin; + hin = htlc_in_map_next(&ld->htlcs_in, &ini)) { + if (hin->key.channel == channel) + return hin; + } + + return NULL; +} + +static void destroy_channel(struct channel *channel) +{ + /* Must not have any HTLCs! */ + struct htlc_out *hout = channel_has_htlc_out(channel); + struct htlc_in *hin = channel_has_htlc_in(channel); + + if (hout) + fatal("Freeing channel %s has hout %s", + channel_state_name(channel), + htlc_state_name(hout->hstate)); + + if (hin) + fatal("Freeing channel %s has hin %s", + channel_state_name(channel), + htlc_state_name(hin->hstate)); + + for (size_t i = 0; i < tal_count(channel->forgets); i++) + was_pending(command_fail(channel->forgets[i], LIGHTNINGD, + "Channel structure was freed!")); + + /* Free any old owner still hanging around. */ + channel_set_owner(channel, NULL); + + list_del_from(&channel->peer->channels, &channel->list); +} + +void delete_channel(struct channel *channel STEALS) +{ + struct peer *peer = channel->peer; + if (channel->dbid != 0) + wallet_channel_close(channel->peer->ld->wallet, channel->dbid); + tal_free(channel); + + maybe_delete_peer(peer); +} + +void get_channel_basepoints(struct lightningd *ld, + const struct node_id *peer_id, + const u64 dbid, + struct basepoints *local_basepoints, + struct pubkey *local_funding_pubkey) +{ + u8 *msg; + + assert(dbid != 0); + msg = towire_hsmd_get_channel_basepoints(NULL, peer_id, dbid); + if (!wire_sync_write(ld->hsm_fd, take(msg))) + fatal("Could not write to HSM: %s", strerror(errno)); + + msg = wire_sync_read(tmpctx, ld->hsm_fd); + if (!fromwire_hsmd_get_channel_basepoints_reply(msg, local_basepoints, + local_funding_pubkey)) + fatal("HSM gave bad hsm_get_channel_basepoints_reply %s", + tal_hex(msg, msg)); +} + +static void destroy_inflight(struct channel_inflight *inflight) +{ + list_del_from(&inflight->channel->inflights, &inflight->list); +} + +struct channel_inflight * +new_inflight(struct channel *channel, + const struct bitcoin_outpoint *funding_outpoint, + u32 funding_feerate, + struct amount_sat total_funds, + struct amount_sat our_funds, + struct wally_psbt *psbt STEALS, + struct bitcoin_tx *last_tx, + const struct bitcoin_signature last_sig, + const u32 lease_expiry, + const secp256k1_ecdsa_signature *lease_commit_sig, + const u32 lease_chan_max_msat, const u16 lease_chan_max_ppt, + const u32 lease_blockheight_start, + const struct amount_msat lease_fee) +{ + struct wally_psbt *last_tx_psbt_clone; + struct channel_inflight *inflight + = tal(channel, struct channel_inflight); + struct funding_info *funding + = tal(inflight, struct funding_info); + + funding->outpoint = *funding_outpoint; + funding->total_funds = total_funds; + funding->feerate = funding_feerate; + funding->our_funds = our_funds; + + inflight->funding = funding; + inflight->channel = channel; + inflight->remote_tx_sigs = false; + inflight->funding_psbt = tal_steal(inflight, psbt); + + /* Make a 'clone' of this tx */ + last_tx_psbt_clone = clone_psbt(inflight, last_tx->psbt); + inflight->last_tx = bitcoin_tx_with_psbt(inflight, last_tx_psbt_clone); + inflight->last_sig = last_sig; + inflight->tx_broadcast = false; + + /* Channel lease infos */ + inflight->lease_blockheight_start = lease_blockheight_start; + inflight->lease_expiry = lease_expiry; + inflight->lease_commit_sig + = tal_dup_or_null(inflight, secp256k1_ecdsa_signature, + lease_commit_sig); + + inflight->lease_chan_max_msat = lease_chan_max_msat; + inflight->lease_chan_max_ppt = lease_chan_max_ppt; + inflight->lease_fee = lease_fee; + + list_add_tail(&channel->inflights, &inflight->list); + tal_add_destructor(inflight, destroy_inflight); + + return inflight; +} + +struct open_attempt *new_channel_open_attempt(struct channel *channel) +{ + struct open_attempt *oa = tal(channel, struct open_attempt); + oa->channel = channel; + /* Copy over the config; we'll clobber the reserve */ + oa->our_config = channel->our_config; + oa->role = channel->opener == LOCAL ? TX_INITIATOR : TX_ACCEPTER; + oa->our_upfront_shutdown_script = NULL; + oa->cmd = NULL; + oa->aborted = false; + oa->open_msg = NULL; + + return oa; +} + +struct channel *new_unsaved_channel(struct peer *peer, + u32 feerate_base, + u32 feerate_ppm) +{ + struct lightningd *ld = peer->ld; + struct channel *channel = tal(ld, struct channel); + u8 *msg; + + channel->peer = peer; + /* Not saved to the database yet! */ + channel->unsaved_dbid = wallet_get_channel_dbid(ld->wallet); + /* A zero value database id means it's not saved in the database yet */ + channel->dbid = 0; + channel->error = NULL; + channel->openchannel_signed_cmd = NULL; + channel->state = DUALOPEND_OPEN_INIT; + channel->owner = NULL; + memset(&channel->billboard, 0, sizeof(channel->billboard)); + channel->billboard.transient = tal_fmt(channel, "%s", + "Empty channel init'd"); + channel->log = new_log(channel, ld->log_book, + &peer->id, + "chan#%"PRIu64, + channel->unsaved_dbid); + + channel->our_config.id = 0; + channel->open_attempt = NULL; + + channel->last_htlc_sigs = NULL; + channel->remote_funding_locked = false; + channel->scid = NULL; + channel->next_index[LOCAL] = 1; + channel->next_index[REMOTE] = 1; + channel->next_htlc_id = 0; + /* FIXME: remove push when v1 deprecated */ + channel->push = AMOUNT_MSAT(0); + channel->closing_fee_negotiation_step = 50; + channel->closing_fee_negotiation_step_unit + = CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; + channel->shutdown_wrong_funding = NULL; + channel->closing_feerate_range = NULL; + channel->channel_update = NULL; + + /* Channel is connected! */ + channel->connected = true; + channel->shutdown_scriptpubkey[REMOTE] = NULL; + channel->last_was_revoke = false; + channel->last_sent_commit = NULL; + channel->last_tx_type = TX_UNKNOWN; + + channel->feerate_base = feerate_base; + channel->feerate_ppm = feerate_ppm; + channel->old_feerate_timeout.ts.tv_sec = 0; + channel->old_feerate_timeout.ts.tv_nsec = 0; + /* closer not yet known */ + channel->closer = NUM_SIDES; + + /* BOLT-7b04b1461739c5036add61782d58ac490842d98b #9 + * | 222/223 | `option_dual_fund` + * | Use v2 of channel open, enables dual funding + * | IN9 + * | `option_anchor_outputs` */ + channel->static_remotekey_start[LOCAL] + = channel->static_remotekey_start[REMOTE] = 0; + channel->type = channel_type_anchor_outputs(channel); + channel->future_per_commitment_point = NULL; + + channel->lease_commit_sig = NULL; + + /* No shachain yet */ + channel->their_shachain.id = 0; + shachain_init(&channel->their_shachain.chain); + + msg = towire_hsmd_new_channel(NULL, &peer->id, channel->unsaved_dbid); + if (!wire_sync_write(ld->hsm_fd, take(msg))) + fatal("Could not write to HSM: %s", strerror(errno)); + msg = wire_sync_read(tmpctx, ld->hsm_fd); + if (!fromwire_hsmd_new_channel_reply(msg)) + fatal("HSM gave bad hsm_new_channel_reply %s", + tal_hex(msg, msg)); + + get_channel_basepoints(ld, &peer->id, channel->unsaved_dbid, + &channel->local_basepoints, + &channel->local_funding_pubkey); + + channel->forgets = tal_arr(channel, struct command *, 0); + list_add_tail(&peer->channels, &channel->list); + channel->rr_number = peer->ld->rr_counter++; + tal_add_destructor(channel, destroy_channel); + + list_head_init(&channel->inflights); + return channel; +} + +/* + * The maximum msat that this node could possibly accept for an htlc. + * It's the default htlc_maximum_msat in channel_updates, if none is + * explicitly set (and the cap on what can be set!). + * + * We advertize the maximum value possible, defined as the smaller + * of the remote's maximum in-flight HTLC or the total channel + * capacity the reserve we have to keep. + * FIXME: does this need fuzz? + */ +struct amount_msat htlc_max_possible_send(const struct channel *channel) +{ + struct amount_sat lower_bound; + struct amount_msat lower_bound_msat; + + /* These shouldn't fail */ + if (!amount_sat_sub(&lower_bound, channel->funding_sats, + channel->channel_info.their_config.channel_reserve)) { + log_broken(channel->log, "%s: their reserve %s > funding %s!", + __func__, + type_to_string(tmpctx, struct amount_sat, + &channel->funding_sats), + type_to_string(tmpctx, struct amount_sat, + &channel->channel_info.their_config.channel_reserve)); + return AMOUNT_MSAT(0); + } + + if (!amount_sat_to_msat(&lower_bound_msat, lower_bound)) { + log_broken(channel->log, "%s: impossible size channel %s!", + __func__, + type_to_string(tmpctx, struct amount_sat, + &lower_bound)); + return AMOUNT_MSAT(0); + } + + if (amount_msat_less(channel->channel_info.their_config.max_htlc_value_in_flight, + lower_bound_msat)) + lower_bound_msat = channel->channel_info.their_config.max_htlc_value_in_flight; + + return lower_bound_msat; +} + +struct channel *new_channel(struct peer *peer, u64 dbid, + /* NULL or stolen */ + struct wallet_shachain *their_shachain, + enum channel_state state, + enum side opener, + /* NULL or stolen */ + struct log *log, + const char *transient_billboard TAKES, + u8 channel_flags, + const struct channel_config *our_config, + u32 minimum_depth, + u64 next_index_local, + u64 next_index_remote, + u64 next_htlc_id, + const struct bitcoin_outpoint *funding, + struct amount_sat funding_sats, + struct amount_msat push, + struct amount_sat our_funds, + bool remote_funding_locked, + /* NULL or stolen */ + struct short_channel_id *scid, + struct channel_id *cid, + struct amount_msat our_msat, + struct amount_msat msat_to_us_min, + struct amount_msat msat_to_us_max, + /* Stolen */ + struct bitcoin_tx *last_tx, + const struct bitcoin_signature *last_sig, + /* NULL or stolen */ + const struct bitcoin_signature *last_htlc_sigs, + const struct channel_info *channel_info, + const struct fee_states *fee_states TAKES, + /* NULL or stolen */ + u8 *remote_shutdown_scriptpubkey, + const u8 *local_shutdown_scriptpubkey, + u64 final_key_idx, + bool last_was_revoke, + /* NULL or stolen */ + struct changed_htlc *last_sent_commit, + u32 first_blocknum, + u32 min_possible_feerate, + u32 max_possible_feerate, + bool connected, + const struct basepoints *local_basepoints, + const struct pubkey *local_funding_pubkey, + const struct pubkey *future_per_commitment_point, + u32 feerate_base, + u32 feerate_ppm, + const u8 *remote_upfront_shutdown_script, + u64 local_static_remotekey_start, + u64 remote_static_remotekey_start, + const struct channel_type *type STEALS, + enum side closer, + enum state_change reason, + /* NULL or stolen */ + const struct bitcoin_outpoint *shutdown_wrong_funding, + const struct height_states *height_states TAKES, + u32 lease_expiry, + secp256k1_ecdsa_signature *lease_commit_sig STEALS, + u32 lease_chan_max_msat, + u16 lease_chan_max_ppt, + struct amount_msat htlc_minimum_msat, + struct amount_msat htlc_maximum_msat) +{ + struct channel *channel = tal(peer->ld, struct channel); + struct amount_msat htlc_min, htlc_max; + + assert(dbid != 0); + channel->peer = peer; + channel->dbid = dbid; + channel->unsaved_dbid = 0; + channel->error = NULL; + channel->open_attempt = NULL; + channel->openchannel_signed_cmd = NULL; + if (their_shachain) + channel->their_shachain = *their_shachain; + else { + channel->their_shachain.id = 0; + shachain_init(&channel->their_shachain.chain); + } + channel->state = state; + channel->opener = opener; + channel->owner = NULL; + memset(&channel->billboard, 0, sizeof(channel->billboard)); + channel->billboard.transient = tal_strdup(channel, transient_billboard); + + if (!log) { + channel->log = new_log(channel, + peer->ld->log_book, + &channel->peer->id, + "chan#%"PRIu64, + dbid); + } else + channel->log = tal_steal(channel, log); + channel->channel_flags = channel_flags; + channel->our_config = *our_config; + channel->minimum_depth = minimum_depth; + channel->next_index[LOCAL] = next_index_local; + channel->next_index[REMOTE] = next_index_remote; + channel->next_htlc_id = next_htlc_id; + channel->funding = *funding; + channel->funding_sats = funding_sats; + channel->push = push; + channel->our_funds = our_funds; + channel->remote_funding_locked = remote_funding_locked; + channel->scid = tal_steal(channel, scid); + channel->cid = *cid; + channel->our_msat = our_msat; + channel->msat_to_us_min = msat_to_us_min; + channel->msat_to_us_max = msat_to_us_max; + channel->last_tx = tal_steal(channel, last_tx); + channel->last_tx->chainparams = chainparams; + channel->last_tx_type = TX_UNKNOWN; + channel->last_sig = *last_sig; + channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs); + channel->channel_info = *channel_info; + channel->fee_states = dup_fee_states(channel, fee_states); + channel->shutdown_scriptpubkey[REMOTE] + = tal_steal(channel, remote_shutdown_scriptpubkey); + channel->final_key_idx = final_key_idx; + channel->closing_fee_negotiation_step = 50; + channel->closing_fee_negotiation_step_unit + = CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; + channel->shutdown_wrong_funding + = tal_steal(channel, shutdown_wrong_funding); + channel->closing_feerate_range = NULL; + if (local_shutdown_scriptpubkey) + channel->shutdown_scriptpubkey[LOCAL] + = tal_steal(channel, local_shutdown_scriptpubkey); + else + channel->shutdown_scriptpubkey[LOCAL] + = p2wpkh_for_keyidx(channel, channel->peer->ld, + channel->final_key_idx); + channel->last_was_revoke = last_was_revoke; + channel->last_sent_commit = tal_steal(channel, last_sent_commit); + channel->first_blocknum = first_blocknum; + channel->min_possible_feerate = min_possible_feerate; + channel->max_possible_feerate = max_possible_feerate; + channel->connected = connected; + channel->local_basepoints = *local_basepoints; + channel->local_funding_pubkey = *local_funding_pubkey; + channel->future_per_commitment_point + = tal_steal(channel, future_per_commitment_point); + channel->feerate_base = feerate_base; + channel->feerate_ppm = feerate_ppm; + channel->old_feerate_timeout.ts.tv_sec = 0; + channel->old_feerate_timeout.ts.tv_nsec = 0; + channel->remote_upfront_shutdown_script + = tal_steal(channel, remote_upfront_shutdown_script); + channel->static_remotekey_start[LOCAL] = local_static_remotekey_start; + channel->static_remotekey_start[REMOTE] = remote_static_remotekey_start; + channel->type = tal_steal(channel, type); + channel->forgets = tal_arr(channel, struct command *, 0); + + channel->lease_expiry = lease_expiry; + channel->lease_commit_sig = tal_steal(channel, lease_commit_sig); + channel->lease_chan_max_msat = lease_chan_max_msat; + channel->lease_chan_max_ppt = lease_chan_max_ppt; + channel->blockheight_states = dup_height_states(channel, height_states); + channel->channel_update = NULL; + + /* DB migration, for example, sets min to 0, max to large: fixup */ + htlc_min = channel->channel_info.their_config.htlc_minimum; + if (amount_msat_greater(htlc_min, htlc_minimum_msat)) + channel->htlc_minimum_msat = htlc_min; + else + channel->htlc_minimum_msat = htlc_minimum_msat; + htlc_max = htlc_max_possible_send(channel); + if (amount_msat_less(htlc_max, htlc_maximum_msat)) + channel->htlc_maximum_msat = htlc_max; + else + channel->htlc_maximum_msat = htlc_maximum_msat; + + list_add_tail(&peer->channels, &channel->list); + channel->rr_number = peer->ld->rr_counter++; + tal_add_destructor(channel, destroy_channel); + + list_head_init(&channel->inflights); + + channel->closer = closer; + channel->state_change_cause = reason; + + /* Make sure we see any spends using this key */ + txfilter_add_scriptpubkey(peer->ld->owned_txfilter, + take(p2wpkh_for_keyidx(NULL, peer->ld, + channel->final_key_idx))); + + return channel; +} + +const char *channel_state_name(const struct channel *channel) +{ + return channel_state_str(channel->state); +} + +const char *channel_state_str(enum channel_state state) +{ + for (size_t i = 0; enum_channel_state_names[i].name; i++) + if (enum_channel_state_names[i].v == state) + return enum_channel_state_names[i].name; + return "unknown"; +} + +struct channel *peer_any_active_channel(struct peer *peer, bool *others) +{ + struct channel *channel, *ret = NULL; + + list_for_each(&peer->channels, channel, list) { + if (!channel_active(channel)) + continue; + /* Already found one? */ + if (ret) { + if (others) + *others = true; + } else { + if (others) + *others = false; + ret = channel; + } + } + return ret; +} + +struct channel *peer_any_unsaved_channel(struct peer *peer, bool *others) +{ + struct channel *channel, *ret = NULL; + + list_for_each(&peer->channels, channel, list) { + if (!channel_unsaved(channel)) + continue; + /* Already found one? */ + if (ret) { + if (others) + *others = true; + } else { + if (others) + *others = false; + ret = channel; + } + } + return ret; +} + +struct channel_inflight *channel_inflight_find(struct channel *channel, + const struct bitcoin_txid *txid) +{ + struct channel_inflight *inflight; + list_for_each(&channel->inflights, inflight, list) { + if (bitcoin_txid_eq(txid, &inflight->funding->outpoint.txid)) + return inflight; + } + + return NULL; +} + +struct channel *any_channel_by_scid(struct lightningd *ld, + const struct short_channel_id *scid) +{ + struct peer *p; + struct channel *chan; + list_for_each(&ld->peers, p, list) { + list_for_each(&p->channels, chan, list) { + if (chan->scid + && short_channel_id_eq(scid, chan->scid)) + return chan; + } + } + return NULL; +} + +struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid) +{ + struct peer *p; + struct channel *chan; + list_for_each(&ld->peers, p, list) { + list_for_each(&p->channels, chan, list) { + if (chan->dbid == dbid) + return chan; + } + } + return NULL; +} + +struct channel *channel_by_cid(struct lightningd *ld, + const struct channel_id *cid) +{ + struct peer *p; + struct channel *channel; + + list_for_each(&ld->peers, p, list) { + if (p->uncommitted_channel) { + /* We can't use this method for old, uncommitted + * channels; there's no "channel" struct here! */ + if (channel_id_eq(&p->uncommitted_channel->cid, cid)) + return NULL; + } + list_for_each(&p->channels, channel, list) { + if (channel_id_eq(&channel->cid, cid)) { + return channel; + } + } + } + return NULL; +} + +struct channel *find_channel_by_id(const struct peer *peer, + const struct channel_id *cid) +{ + struct channel *c; + + list_for_each(&peer->channels, c, list) { + if (channel_id_eq(&c->cid, cid)) + return c; + } + return NULL; +} + +struct channel *find_channel_by_scid(const struct peer *peer, + const struct short_channel_id *scid) +{ + struct channel *c; + + list_for_each(&peer->channels, c, list) { + if (c->scid && short_channel_id_eq(c->scid, scid)) + return c; + } + return NULL; +} + +void channel_set_last_tx(struct channel *channel, + struct bitcoin_tx *tx, + const struct bitcoin_signature *sig, + enum wallet_tx_type txtypes) +{ + assert(tx->chainparams); + channel->last_sig = *sig; + tal_free(channel->last_tx); + channel->last_tx = tal_steal(channel, tx); + channel->last_tx_type = txtypes; +} + +void channel_set_state(struct channel *channel, + enum channel_state old_state, + enum channel_state state, + enum state_change reason, + char *why) +{ + struct timeabs timestamp; + + /* set closer, if known */ + if (state > CHANNELD_NORMAL && channel->closer == NUM_SIDES) { + if (reason == REASON_LOCAL) channel->closer = LOCAL; + if (reason == REASON_USER) channel->closer = LOCAL; + if (reason == REASON_REMOTE) channel->closer = REMOTE; + if (reason == REASON_ONCHAIN) channel->closer = REMOTE; + } + + /* use or update state_change_cause, if known */ + if (reason != REASON_UNKNOWN) + channel->state_change_cause = reason; + else + reason = channel->state_change_cause; + + log_info(channel->log, "State changed from %s to %s", + channel_state_name(channel), channel_state_str(state)); + if (channel->state != old_state) + fatal("channel state %s should be %s", + channel_state_name(channel), channel_state_str(old_state)); + + channel->state = state; + + /* TODO(cdecker) Selectively save updated fields to DB */ + wallet_channel_save(channel->peer->ld->wallet, channel); + + /* plugin notification channel_state_changed and DB entry */ + if (state != old_state) { /* see issue #4029 */ + timestamp = time_now(); + wallet_state_change_add(channel->peer->ld->wallet, + channel->dbid, + ×tamp, + old_state, + state, + reason, + why); + notify_channel_state_changed(channel->peer->ld, + &channel->peer->id, + &channel->cid, + channel->scid, + ×tamp, + old_state, + state, + reason, + why); + } +} + +const char *channel_change_state_reason_str(enum state_change reason) +{ + switch (reason) { + case REASON_UNKNOWN: return "unknown"; + case REASON_LOCAL: return "local"; + case REASON_USER: return "user"; + case REASON_REMOTE: return "remote"; + case REASON_PROTOCOL: return "protocol"; + case REASON_ONCHAIN: return "onchain"; + } + abort(); +} + +void channel_fail_permanent(struct channel *channel, + enum state_change reason, + const char *fmt, + ...) +{ + struct lightningd *ld = channel->peer->ld; + va_list ap; + char *why; + + va_start(ap, fmt); + why = tal_vfmt(tmpctx, fmt, ap); + va_end(ap); + + log_unusual(channel->log, "Peer permanent failure in %s: %s", + channel_state_name(channel), why); + + /* We can have multiple errors, eg. onchaind failures. */ + if (!channel->error) + channel->error = towire_errorfmt(channel, + &channel->cid, "%s", why); + + channel_set_owner(channel, NULL); + /* Drop non-cooperatively (unilateral) to chain. */ + drop_to_chain(ld, channel, false); + + if (channel_active(channel)) + channel_set_state(channel, + channel->state, + AWAITING_UNILATERAL, + reason, + why); + + tal_free(why); +} + +void channel_fail_forget(struct channel *channel, const char *fmt, ...) +{ + va_list ap; + char *why; + + assert(channel->opener == REMOTE && + channel->state == CHANNELD_AWAITING_LOCKIN); + va_start(ap, fmt); + why = tal_vfmt(tmpctx, fmt, ap); + va_end(ap); + + log_unusual(channel->log, "Peer permanent failure in %s: %s, " + "forget channel", + channel_state_name(channel), why); + + if (!channel->error) + channel->error = towire_errorfmt(channel, + &channel->cid, "%s", why); + + delete_channel(channel); + tal_free(why); +} + +struct channel_inflight * +channel_current_inflight(const struct channel *channel) +{ + /* The last inflight should always be the one in progress */ + return list_tail(&channel->inflights, + struct channel_inflight, list); +} + +u32 channel_last_funding_feerate(const struct channel *channel) +{ + struct channel_inflight *inflight; + inflight = channel_current_inflight(channel); + if (!inflight) + return 0; + return inflight->funding->feerate; +} + +void channel_cleanup_commands(struct channel *channel, const char *why) +{ + if (channel->open_attempt) { + struct open_attempt *oa = channel->open_attempt; + if (oa->cmd) { + /* If we requested this be aborted, it's a success */ + if (oa->aborted) { + struct json_stream *response; + response = json_stream_success(oa->cmd); + json_add_channel_id(response, + "channel_id", + &channel->cid); + json_add_bool(response, "channel_canceled", + list_empty(&channel->inflights)); + json_add_string(response, "reason", why); + was_pending(command_success(oa->cmd, response)); + } else + was_pending(command_fail(oa->cmd, LIGHTNINGD, + "%s", why)); + } + notify_channel_open_failed(channel->peer->ld, &channel->cid); + channel->open_attempt = tal_free(channel->open_attempt); + } + + if (channel->openchannel_signed_cmd) { + was_pending(command_fail(channel->openchannel_signed_cmd, + LIGHTNINGD, "%s", why)); + channel->openchannel_signed_cmd = NULL; + } +} + +void channel_internal_error(struct channel *channel, const char *fmt, ...) +{ + va_list ap; + char *why; + + va_start(ap, fmt); + why = tal_vfmt(channel, fmt, ap); + va_end(ap); + + log_broken(channel->log, "Internal error %s: %s", + channel_state_name(channel), why); + + channel_cleanup_commands(channel, why); + + if (channel_unsaved(channel)) { + channel_set_owner(channel, NULL); + delete_channel(channel); + tal_free(why); + return; + } + + /* Don't expose internal error causes to remove unless doing dev */ +#if DEVELOPER + channel_fail_permanent(channel, REASON_LOCAL, "Internal error: %s", why); +#else + channel_fail_permanent(channel, REASON_LOCAL, "Internal error"); +#endif + tal_free(why); +} + +void channel_set_billboard(struct channel *channel, bool perm, const char *str) +{ + const char **p; + + if (perm) + p = &channel->billboard.permanent[channel->state]; + else + p = &channel->billboard.transient; + *p = tal_free(*p); + + if (str) { + *p = tal_fmt(channel, "%s:%s", channel_state_name(channel), str); + if (taken(str)) + tal_free(str); + } +} + +static void err_and_reconnect(struct channel *channel, + const char *why, + u32 seconds_before_reconnect) +{ + log_info(channel->log, "Peer transient failure in %s: %s", + channel_state_name(channel), why); + +#if DEVELOPER + if (dev_disconnect_permanent(channel->peer->ld)) { + channel_fail_permanent(channel, + REASON_LOCAL, + "dev_disconnect permfail"); + return; + } +#endif + + channel_set_owner(channel, NULL); + + /* Their address only useful if we connected to them */ + try_reconnect(channel, channel->peer, seconds_before_reconnect, + channel->peer->connected_incoming + ? NULL + : &channel->peer->addr); +} + +void channel_fail_reconnect_later(struct channel *channel, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_and_reconnect(channel, tal_vfmt(tmpctx, fmt, ap), 60); + va_end(ap); +} + +void channel_fail_reconnect(struct channel *channel, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_and_reconnect(channel, tal_vfmt(tmpctx, fmt, ap), 1); + va_end(ap); +} diff --git a/lightningd/eltoo_channel.h b/lightningd/eltoo_channel.h new file mode 100644 index 000000000000..db81ce8c484c --- /dev/null +++ b/lightningd/eltoo_channel.h @@ -0,0 +1,481 @@ +#ifndef LIGHTNING_LIGHTNINGD_CHANNEL_H +#define LIGHTNING_LIGHTNINGD_CHANNEL_H +#include "config.h" +#include +#include +#include +#include +#include +#include + +struct channel_id; +struct uncommitted_channel; +struct wally_psbt; + +struct billboard { + /* Status information to display on listpeers */ + const char *permanent[CHANNEL_STATE_MAX+1]; + const char *transient; +}; + +struct funding_info { + struct bitcoin_outpoint outpoint; + u32 feerate; + struct amount_sat total_funds; + + /* Our original funds, in funding amount */ + struct amount_sat our_funds; +}; + +struct channel_inflight { + /* Inside channel->inflights. */ + struct list_node list; + + /* Channel context */ + struct channel *channel; + + /* Funding info */ + const struct funding_info *funding; + struct wally_psbt *funding_psbt; + bool remote_tx_sigs; + bool tx_broadcast; + + /* Commitment tx and sigs */ + struct bitcoin_tx *last_tx; + struct bitcoin_signature last_sig; + + /* Channel lease infos */ + u32 lease_expiry; + secp256k1_ecdsa_signature *lease_commit_sig; + u32 lease_chan_max_msat; + u16 lease_chan_max_ppt; + u32 lease_blockheight_start; + + /* We save this data so we can do nice accounting; + * on the channel we slot it into the 'push' field */ + struct amount_msat lease_fee; +}; + +struct open_attempt { + /* on uncommitted_channel struct */ + struct channel *channel; + struct channel_config our_config; + enum tx_role role; + bool aborted; + + /* On funding_channel struct */ + struct command *cmd; + struct amount_sat funding; + const u8 *our_upfront_shutdown_script; + + /* First msg to send to dualopend (to make it create channel) */ + const u8 *open_msg; +}; + +struct channel { + /* Inside peer->channels. */ + struct list_node list; + + /* Peer context */ + struct peer *peer; + + /* Inflight channel opens */ + struct list_head inflights; + + /* Open attempt */ + struct open_attempt *open_attempt; + + /* Database ID: 0 == not in db yet */ + u64 dbid; + + /* Populated by new_unsaved_channel */ + u64 unsaved_dbid; + + /* Error message (iff in error state) */ + u8 *error; + + /* Their shachain. */ + struct wallet_shachain their_shachain; + + /* What's happening. */ + enum channel_state state; + + /* Which side offered channel? */ + enum side opener; + + /* Is there a single subdaemon responsible for us? */ + struct subd *owner; + + /* History */ + struct log *log; + struct billboard billboard; + + /* Channel flags from opening message. */ + u8 channel_flags; + + /* Our channel config. */ + struct channel_config our_config; + + /* Minimum funding depth (specified by us if they fund). */ + u32 minimum_depth; + + /* Tracking commitment transaction numbers. */ + u64 next_index[NUM_SIDES]; + u64 next_htlc_id; + + /* Funding outpoint and amount */ + struct bitcoin_outpoint funding; + struct amount_sat funding_sats; + + /* Our original funds, in funding amount */ + struct amount_sat our_funds; + + struct amount_msat push; + bool remote_funding_locked; + /* Channel if locked locally. */ + struct short_channel_id *scid; + + struct channel_id cid; + + /* Amount going to us, not counting unfinished HTLCs; if we have one. */ + struct amount_msat our_msat; + /* Statistics for min and max our_msatoshi. */ + struct amount_msat msat_to_us_min; + struct amount_msat msat_to_us_max; + + /* Last tx they gave us. */ + struct bitcoin_tx *last_tx; + enum wallet_tx_type last_tx_type; + struct bitcoin_signature last_sig; + const struct bitcoin_signature *last_htlc_sigs; + + /* Keys for channel */ + struct channel_info channel_info; + + /* Fee status */ + const struct fee_states *fee_states; + + /* Height states (option_will_fund, update_blockheight) */ + const struct height_states *blockheight_states; + + /* Our local basepoints */ + struct basepoints local_basepoints; + + /* Our funding tx pubkey. */ + struct pubkey local_funding_pubkey; + + /* scriptpubkey for shutdown, if applicable. */ + const u8 *shutdown_scriptpubkey[NUM_SIDES]; + /* Address for any final outputs */ + u64 final_key_idx; + + /* Amount to give up on each step of the closing fee negotiation. */ + u64 closing_fee_negotiation_step; + + /* Whether closing_fee_negotiation_step is in satoshi or %. */ + u8 closing_fee_negotiation_step_unit; + + /* optional wrong_funding for mutual close */ + const struct bitcoin_outpoint *shutdown_wrong_funding; + + /* optional feerate min/max for mutual close */ + u32 *closing_feerate_range; + + /* Reestablishment stuff: last sent commit and revocation details. */ + bool last_was_revoke; + struct changed_htlc *last_sent_commit; + + /* Blockheight at creation, scans for funding confirmations + * will start here */ + u32 first_blocknum; + + /* Feerate range */ + u32 min_possible_feerate, max_possible_feerate; + + /* Does gossipd need to know if the owner dies? (ie. not onchaind) */ + bool connected; + + /* Do we have an "impossible" future per_commitment_point from + * peer via option_data_loss_protect? */ + const struct pubkey *future_per_commitment_point; + + /* Min/max htlc amount allowed in channel. */ + struct amount_msat htlc_minimum_msat, htlc_maximum_msat; + + /* Feerate per channel */ + u32 feerate_base, feerate_ppm; + + /* But allow these feerates/htlcs up until this time. */ + struct timeabs old_feerate_timeout; + u32 old_feerate_base, old_feerate_ppm; + struct amount_msat old_htlc_minimum_msat, old_htlc_maximum_msat; + + /* If they used option_upfront_shutdown_script. */ + const u8 *remote_upfront_shutdown_script; + + /* At what commit numbers does `option_static_remotekey` apply? */ + u64 static_remotekey_start[NUM_SIDES]; + + /* What features apply to this channel? */ + const struct channel_type *type; + + /* Any commands trying to forget us. */ + struct command **forgets; + + /* Our position in the round-robin list. */ + u64 rr_number; + + /* the one that initiated a bilateral close, NUM_SIDES if unknown. */ + enum side closer; + + /* Last known state_change cause */ + enum state_change state_change_cause; + + /* Outstanding command for this channel, v2 only */ + struct command *openchannel_signed_cmd; + + /* Block lease expires at, zero is no lease */ + u32 lease_expiry; + + /* Lease commitment, useful someone breaks their promise + * wrt channel fees */ + secp256k1_ecdsa_signature *lease_commit_sig; + + /* Lease commited maximum channel fee base msat */ + u32 lease_chan_max_msat; + /* Lease commited max part per thousandth channel fee (ppm * 1000) */ + u16 lease_chan_max_ppt; + + /* Latest channel_update, for use in error messages. */ + u8 *channel_update; +}; + +/* For v2 opens, a channel that has not yet been committed/saved to disk */ +struct channel *new_unsaved_channel(struct peer *peer, + u32 feerate_base, + u32 feerate_ppm); + +struct open_attempt *new_channel_open_attempt(struct channel *channel); + +struct channel *new_channel(struct peer *peer, u64 dbid, + /* NULL or stolen */ + struct wallet_shachain *their_shachain STEALS, + enum channel_state state, + enum side opener, + /* NULL or stolen */ + struct log *log STEALS, + const char *transient_billboard TAKES, + u8 channel_flags, + const struct channel_config *our_config, + u32 minimum_depth, + u64 next_index_local, + u64 next_index_remote, + u64 next_htlc_id, + const struct bitcoin_outpoint *funding, + struct amount_sat funding_sats, + struct amount_msat push, + struct amount_sat our_funds, + bool remote_funding_locked, + /* NULL or stolen */ + struct short_channel_id *scid STEALS, + struct channel_id *cid, + struct amount_msat our_msatoshi, + struct amount_msat msatoshi_to_us_min, + struct amount_msat msatoshi_to_us_max, + struct bitcoin_tx *last_tx STEALS, + const struct bitcoin_signature *last_sig, + /* NULL or stolen */ + const struct bitcoin_signature *last_htlc_sigs STEALS, + const struct channel_info *channel_info, + const struct fee_states *fee_states TAKES, + /* NULL or stolen */ + u8 *remote_shutdown_scriptpubkey STEALS, + const u8 *local_shutdown_scriptpubkey, + u64 final_key_idx, + bool last_was_revoke, + /* NULL or stolen */ + struct changed_htlc *last_sent_commit STEALS, + u32 first_blocknum, + u32 min_possible_feerate, + u32 max_possible_feerate, + bool connected, + const struct basepoints *local_basepoints, + const struct pubkey *local_funding_pubkey, + const struct pubkey *future_per_commitment_point, + u32 feerate_base, + u32 feerate_ppm, + /* NULL or stolen */ + const u8 *remote_upfront_shutdown_script STEALS, + u64 local_static_remotekey_start, + u64 remote_static_remotekey_start, + const struct channel_type *type STEALS, + enum side closer, + enum state_change reason, + /* NULL or stolen */ + const struct bitcoin_outpoint *shutdown_wrong_funding STEALS, + const struct height_states *height_states TAKES, + u32 lease_expiry, + secp256k1_ecdsa_signature *lease_commit_sig STEALS, + u32 lease_chan_max_msat, + u16 lease_chan_max_ppt, + struct amount_msat htlc_minimum_msat, + struct amount_msat htlc_maximum_msat); + +/* new_inflight - Create a new channel_inflight for a channel */ +struct channel_inflight * +new_inflight(struct channel *channel, + const struct bitcoin_outpoint *funding_outpoint, + u32 funding_feerate, + struct amount_sat funding_sat, + struct amount_sat our_funds, + struct wally_psbt *funding_psbt STEALS, + struct bitcoin_tx *last_tx STEALS, + const struct bitcoin_signature last_sig, + const u32 lease_expiry, + const secp256k1_ecdsa_signature *lease_commit_sig, + const u32 lease_chan_max_msat, + const u16 lease_chan_max_ppt, + const u32 lease_blockheight_start, + const struct amount_msat lease_fee); + +/* Given a txid, find an inflight channel stub. Returns NULL if none found */ +struct channel_inflight *channel_inflight_find(struct channel *channel, + const struct bitcoin_txid *txid); + +/* What's the most recent inflight for this channel? */ +struct channel_inflight * +channel_current_inflight(const struct channel *channel); + +/* What's the last feerate used for a funding tx on this channel? */ +u32 channel_last_funding_feerate(const struct channel *channel); + +void delete_channel(struct channel *channel STEALS); + +const char *channel_state_name(const struct channel *channel); +const char *channel_state_str(enum channel_state state); + +void channel_set_owner(struct channel *channel, struct subd *owner); + +/* Channel has failed, but can try again. */ +void channel_fail_reconnect(struct channel *channel, + const char *fmt, ...) PRINTF_FMT(2,3); +/* Channel has failed, but can try again after a minute. */ +void channel_fail_reconnect_later(struct channel *channel, + const char *fmt,...) PRINTF_FMT(2,3); + +/* Channel has failed, give up on it. */ +void channel_fail_permanent(struct channel *channel, + enum state_change reason, + const char *fmt, + ...); +/* Forget the channel. This is only used for the case when we "receive" error + * during CHANNELD_AWAITING_LOCKIN if we are "fundee". */ +void channel_fail_forget(struct channel *channel, const char *fmt, ...); +/* Permanent error, but due to internal problems, not peer. */ +void channel_internal_error(struct channel *channel, const char *fmt, ...); + +/* Clean up any in-progress commands for a channel */ +void channel_cleanup_commands(struct channel *channel, const char *why); + +void channel_set_state(struct channel *channel, + enum channel_state old_state, + enum channel_state state, + enum state_change reason, + char *why); + +const char *channel_change_state_reason_str(enum state_change reason); + +/* Find a channel which is not onchain, if any: sets *others if there + * is more than one. */ +struct channel *peer_any_active_channel(struct peer *peer, bool *others); + +/* Find a channel which is not yet saved to disk */ +struct channel *peer_any_unsaved_channel(struct peer *peer, bool *others); + +struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid); + +struct channel *any_channel_by_scid(struct lightningd *ld, + const struct short_channel_id *scid); + +/* Get channel by channel_id */ +struct channel *channel_by_cid(struct lightningd *ld, + const struct channel_id *cid); + +/* Find this channel within peer */ +struct channel *find_channel_by_id(const struct peer *peer, + const struct channel_id *cid); + +/* Find this channel within peer */ +struct channel *find_channel_by_scid(const struct peer *peer, + const struct short_channel_id *scid); + +void channel_set_last_tx(struct channel *channel, + struct bitcoin_tx *tx, + const struct bitcoin_signature *sig, + enum wallet_tx_type type); + +static inline bool channel_can_add_htlc(const struct channel *channel) +{ + return channel->state == CHANNELD_NORMAL; +} + +static inline bool channel_fees_can_change(const struct channel *channel) +{ + return channel->state == CHANNELD_NORMAL + || channel->state == CHANNELD_SHUTTING_DOWN; +} + +static inline bool channel_state_on_chain(enum channel_state state) +{ + return state == ONCHAIN; +} + +static inline bool channel_on_chain(const struct channel *channel) +{ + return channel_state_on_chain(channel->state); +} + +static inline bool channel_unsaved(const struct channel *channel) +{ + return channel->state == DUALOPEND_OPEN_INIT + && channel->dbid == 0; +} + +static inline bool channel_active(const struct channel *channel) +{ + return channel->state != FUNDING_SPEND_SEEN + && channel->state != CLOSINGD_COMPLETE + && !channel_unsaved(channel) + && !channel_on_chain(channel); +} + +static inline bool channel_closed(const struct channel *channel) +{ + return channel->state == CLOSINGD_COMPLETE + || channel->state == AWAITING_UNILATERAL + || channel->state == FUNDING_SPEND_SEEN + || channel->state == ONCHAIN + || channel->state == CLOSED; +} + +static inline bool channel_has(const struct channel *channel, int f) +{ + return channel_type_has(channel->type, f); +} + +void get_channel_basepoints(struct lightningd *ld, + const struct node_id *peer_id, + const u64 dbid, + struct basepoints *local_basepoints, + struct pubkey *local_funding_pubkey); + +void channel_set_billboard(struct channel *channel, bool perm, + const char *str TAKES); + +struct htlc_in *channel_has_htlc_in(struct channel *channel); +struct htlc_out *channel_has_htlc_out(struct channel *channel); + +const u8 *get_channel_update(struct channel *channel); + +struct amount_msat htlc_max_possible_send(const struct channel *channel); +#endif /* LIGHTNING_LIGHTNINGD_CHANNEL_H */ From d92d6a307d87a097b54c846730ceb47a03657431 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 19 Aug 2022 09:37:10 -0400 Subject: [PATCH 137/283] get rid of eltoo_channel_config --- channeld/eltoo_channeld.c | 1 + common/channel_config.c | 70 ++++++++++++++++---------------- common/channel_config.h | 49 ++++------------------ common/initial_channel.h | 8 ++++ common/initial_eltoo_channel.c | 4 +- common/initial_eltoo_channel.h | 6 +-- lightningd/Makefile | 1 + openingd/common.c | 4 +- openingd/common.h | 4 +- openingd/eltoo_openingd.c | 2 +- openingd/eltoo_openingd_wire.csv | 6 +-- 11 files changed, 67 insertions(+), 88 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 325744581591..61e7560e1c38 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -75,6 +75,7 @@ struct eltoo_peer { struct channel_id channel_id; struct eltoo_channel *channel; + struct channel *channel; /* Messages from master: we queue them since we might be * waiting for a specific reply. */ diff --git a/common/channel_config.c b/common/channel_config.c index 5f25b846cadb..9332ec216973 100644 --- a/common/channel_config.c +++ b/common/channel_config.c @@ -4,44 +4,44 @@ void towire_channel_config(u8 **pptr, const struct channel_config *config) { - towire_amount_sat(pptr, config->dust_limit); - towire_amount_msat(pptr, config->max_htlc_value_in_flight); - towire_amount_sat(pptr, config->channel_reserve); - towire_amount_msat(pptr, config->htlc_minimum); - towire_u16(pptr, config->to_self_delay); - towire_u16(pptr, config->max_accepted_htlcs); - towire_amount_msat(pptr, config->max_dust_htlc_exposure_msat); + towire_bool(pptr, config->is_eltoo); + if (!config->is_eltoo) { + towire_amount_sat(pptr, config->dust_limit); + towire_amount_msat(pptr, config->max_htlc_value_in_flight); + towire_amount_sat(pptr, config->channel_reserve); + towire_amount_msat(pptr, config->htlc_minimum); + towire_u16(pptr, config->to_self_delay); + towire_u16(pptr, config->max_accepted_htlcs); + towire_amount_msat(pptr, config->max_dust_htlc_exposure_msat); + towire_u16(pptr, config->shared_delay); + } else { + towire_amount_sat(pptr, config->dust_limit); + towire_amount_msat(pptr, config->max_htlc_value_in_flight); + towire_amount_msat(pptr, config->htlc_minimum); + towire_u16(pptr, config->shared_delay); + towire_u16(pptr, config->max_accepted_htlcs); + towire_amount_msat(pptr, config->max_dust_htlc_exposure_msat); + } } void fromwire_channel_config(const u8 **ptr, size_t *max, struct channel_config *config) { - config->dust_limit = fromwire_amount_sat(ptr, max); - config->max_htlc_value_in_flight = fromwire_amount_msat(ptr, max); - config->channel_reserve = fromwire_amount_sat(ptr, max); - config->htlc_minimum = fromwire_amount_msat(ptr, max); - config->to_self_delay = fromwire_u16(ptr, max); - config->max_accepted_htlcs = fromwire_u16(ptr, max); - config->max_dust_htlc_exposure_msat = fromwire_amount_msat(ptr, max); -} - -void towire_eltoo_channel_config(u8 **pptr, const struct eltoo_channel_config *config) -{ - towire_amount_sat(pptr, config->dust_limit); - towire_amount_msat(pptr, config->max_htlc_value_in_flight); - towire_amount_msat(pptr, config->htlc_minimum); - towire_u16(pptr, config->shared_delay); - towire_u16(pptr, config->max_accepted_htlcs); - towire_amount_msat(pptr, config->max_dust_htlc_exposure_msat); -} - -void fromwire_eltoo_channel_config(const u8 **ptr, size_t *max, - struct eltoo_channel_config *config) -{ - config->dust_limit = fromwire_amount_sat(ptr, max); - config->max_htlc_value_in_flight = fromwire_amount_msat(ptr, max); - config->htlc_minimum = fromwire_amount_msat(ptr, max); - config->shared_delay = fromwire_u16(ptr, max); - config->max_accepted_htlcs = fromwire_u16(ptr, max); - config->max_dust_htlc_exposure_msat = fromwire_amount_msat(ptr, max); + config->is_eltoo = fromwire_bool(ptr, max); + if (!config->is_eltoo) { + config->dust_limit = fromwire_amount_sat(ptr, max); + config->max_htlc_value_in_flight = fromwire_amount_msat(ptr, max); + config->channel_reserve = fromwire_amount_sat(ptr, max); + config->htlc_minimum = fromwire_amount_msat(ptr, max); + config->to_self_delay = fromwire_u16(ptr, max); + config->max_accepted_htlcs = fromwire_u16(ptr, max); + config->max_dust_htlc_exposure_msat = fromwire_amount_msat(ptr, max); + } else { + config->dust_limit = fromwire_amount_sat(ptr, max); + config->max_htlc_value_in_flight = fromwire_amount_msat(ptr, max); + config->htlc_minimum = fromwire_amount_msat(ptr, max); + config->shared_delay = fromwire_u16(ptr, max); + config->max_accepted_htlcs = fromwire_u16(ptr, max); + config->max_dust_htlc_exposure_msat = fromwire_amount_msat(ptr, max); + } } diff --git a/common/channel_config.h b/common/channel_config.h index 79891185647f..2636cd5f7f13 100644 --- a/common/channel_config.h +++ b/common/channel_config.h @@ -77,58 +77,27 @@ struct channel_config { * maximum dust exposure allowed for this channel */ struct amount_msat max_dust_htlc_exposure_msat; -}; - -void towire_channel_config(u8 **pptr, const struct channel_config *config); -void fromwire_channel_config(const u8 **ptr, size_t *max, - struct channel_config *config); -struct eltoo_channel_config { - /* Database ID */ - u64 id; - /* BOLT #2: - * - * `dust_limit_satoshis` is the threshold below which outputs should - * not be generated for this node's commitment or HTLC transaction + /* Eltoo fields start here + * + * We do not use: to_self_delay, channel_reserve */ - struct amount_sat dust_limit; - /* BOLT #2: - * - * `max_htlc_value_in_flight_msat` is a cap on total value of - * outstanding HTLCs, which allows a node to limit its exposure to - * HTLCs */ - struct amount_msat max_htlc_value_in_flight; - - /* BOLT #2: - * - * `htlc_minimum_msat` indicates the smallest value HTLC this node - * will accept. - */ - struct amount_msat htlc_minimum; + bool is_eltoo; - /* BOLT #2: + /* BOLT #X: * * `to_self_delay` is replaced with a symmetrical `shared_delay` which * must be agreed upon by nodes. This is currently set by the opener. */ u16 shared_delay; - /* BOLT #2: - * - * similarly, `max_accepted_htlcs` limits the number of outstanding - * HTLCs the other node can offer. */ - u16 max_accepted_htlcs; + /* Eltoo fields end here */ - /* BOLT-TBD #X - * - * maximum dust exposure allowed for this channel - */ - struct amount_msat max_dust_htlc_exposure_msat; }; -void towire_eltoo_channel_config(u8 **pptr, const struct eltoo_channel_config *config); -void fromwire_eltoo_channel_config(const u8 **ptr, size_t *max, - struct eltoo_channel_config *config); +void towire_channel_config(u8 **pptr, const struct channel_config *config); +void fromwire_channel_config(const u8 **ptr, size_t *max, + struct channel_config *config); #endif /* LIGHTNING_COMMON_CHANNEL_CONFIG_H */ diff --git a/common/initial_channel.h b/common/initial_channel.h index 713d55f5fc76..3b9251f66c28 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -70,6 +70,14 @@ struct channel { /* When the lease expires for the funds in this channel */ u32 lease_expiry; + + /* Eltoo fields below */ + + /* Keys used for the lifetime of the channel */ + struct eltoo_keyset eltoo_keyset; + + /* End Eltoo fields*/ + }; /** diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index c2883cf8e2e5..c1e73d127795 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -17,8 +17,8 @@ struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, u32 minimum_depth, struct amount_sat funding_sats, struct amount_msat local_msatoshi, - const struct eltoo_channel_config *local, - const struct eltoo_channel_config *remote, + const struct channel_config *local, + const struct channel_config *remote, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, diff --git a/common/initial_eltoo_channel.h b/common/initial_eltoo_channel.h index 7abcbec6d8f4..f9f58da1cbda 100644 --- a/common/initial_eltoo_channel.h +++ b/common/initial_eltoo_channel.h @@ -42,7 +42,7 @@ struct eltoo_channel { enum side opener; /* Limits and settings on this channel. */ - struct eltoo_channel_config config[NUM_SIDES]; + struct channel_config config[NUM_SIDES]; /* Mask for obscuring the encoding of the update number. */ u32 update_number_obscurer; @@ -87,8 +87,8 @@ struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, u32 minimum_depth, struct amount_sat funding_sats, struct amount_msat local_msatoshi, - const struct eltoo_channel_config *local, - const struct eltoo_channel_config *remote, + const struct channel_config *local, + const struct channel_config *remote, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, diff --git a/lightningd/Makefile b/lightningd/Makefile index 8876dc55c929..da7e88b04f2d 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -9,6 +9,7 @@ LIGHTNINGD_SRC := \ lightningd/coin_mvts.c \ lightningd/dual_open_control.c \ lightningd/connect_control.c \ + lightningd/eltoo_channel.c \ lightningd/onion_message.c \ lightningd/gossip_control.c \ lightningd/hsm_control.c \ diff --git a/openingd/common.c b/openingd/common.c index 2be6fe5d8652..8b71e04a8ca9 100644 --- a/openingd/common.c +++ b/openingd/common.c @@ -13,8 +13,8 @@ bool check_eltoo_config_bounds(const tal_t *ctx, struct amount_sat funding, u32 max_shared_delay, struct amount_msat min_effective_htlc_capacity, - const struct eltoo_channel_config *remoteconf, - const struct eltoo_channel_config *localconf, + const struct channel_config *remoteconf, + const struct channel_config *localconf, char **err_reason) { /* For eltoo, funding is capacity always */ diff --git a/openingd/common.h b/openingd/common.h index c7394b4755f8..0c32d37de37f 100644 --- a/openingd/common.h +++ b/openingd/common.h @@ -13,8 +13,8 @@ bool check_eltoo_config_bounds(const tal_t *ctx, struct amount_sat funding, u32 max_shared_delay, struct amount_msat min_effective_htlc_capacity, - const struct eltoo_channel_config *remoteconf, - const struct eltoo_channel_config *localconf, + const struct channel_config *remoteconf, + const struct channel_config *localconf, char **err_reason); bool check_config_bounds(const tal_t *ctx, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 4f8cf6cb28a1..42d2f7fa769e 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -88,7 +88,7 @@ struct eltoo_state { * indicate the restrictions each side places on the channel. * FIXME do we need just the one? */ - struct eltoo_channel_config localconf, remoteconf; + struct channel_config localconf, remoteconf; /* The channel structure, as defined in common/initial_channel.h. While * the structure has room for HTLCs, those routines are channeld-specific diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index a74a2e3890f4..b900b3645a4e 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -14,7 +14,7 @@ msgdata,openingd_eltoo_init,chainparams,chainparams, msgdata,openingd_eltoo_init,our_features,feature_set, msgdata,openingd_eltoo_init,their_init_features_len,u16, msgdata,openingd_eltoo_init,their_init_features,u8,their_init_features_len -msgdata,openingd_eltoo_init,our_config,eltoo_channel_config, +msgdata,openingd_eltoo_init,our_config,channel_config, # Minimum/maximum configuration values we'll accept msgdata,openingd_eltoo_init,max_shared_delay,u32, msgdata,openingd_eltoo_init,min_effective_htlc_capacity_msat,amount_msat, @@ -30,7 +30,7 @@ msgdata,openingd_eltoo_init,dev_temporary_channel_id,?byte,32 # Openingd->master: we've successfully offered channel. # This gives their psig, means we can broadcast tx: we're done. msgtype,openingd_eltoo_funder_reply,6601 -msgdata,openingd_eltoo_funder_reply,their_config,eltoo_channel_config, +msgdata,openingd_eltoo_funder_reply,their_config,channel_config, msgdata,openingd_eltoo_funder_reply,first_commit,bitcoin_tx, msgdata,openingd_eltoo_funder_reply,first_update_psig,bip340sig, msgdata,openingd_eltoo_funder_reply,minimum_depth,u32, @@ -76,7 +76,7 @@ msgdata,openingd_eltoo_failed,reason,wirestring, # Openingd->master: they offered channel. # This gives their txid and info, means we can send funding_signed: we're done. msgtype,openingd_eltoo_fundee,6503 -msgdata,openingd_eltoo_fundee,their_config,eltoo_channel_config, +msgdata,openingd_eltoo_fundee,their_config,channel_config, msgdata,openingd_eltoo_fundee,first_settlement,bitcoin_tx, msgdata,openingd_eltoo_fundee,first_update_sig,bip340sig, msgdata,openingd_eltoo_fundee,remote_fundingkey,pubkey, From 00006d22444056b948d2b8db0daf418d9dc1313b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 19 Aug 2022 13:22:30 -0400 Subject: [PATCH 138/283] Working on compiling/deduping... --- channeld/channeld_wire.csv | 7 +- channeld/eltoo_channeld.c | 95 +--- channeld/eltoo_channeld.h | 6 +- channeld/eltoo_full_channel.c | 229 ++------ channeld/eltoo_full_channel.h | 143 ++--- channeld/settle_tx.h | 11 +- channeld/test/run-settle_tx.c | 15 +- common/Makefile | 1 + common/initial_channel.h | 6 +- common/initial_eltoo_channel.c | 19 +- common/initial_eltoo_channel.h | 71 +-- common/initial_settlement_tx.c | 3 +- common/initial_settlement_tx.h | 4 +- common/update_tx.c | 3 +- common/update_tx.h | 4 +- lightningd/Makefile | 1 - lightningd/eltoo_channel.c | 937 --------------------------------- lightningd/eltoo_channel.h | 481 ----------------- openingd/eltoo_openingd.c | 26 +- 19 files changed, 133 insertions(+), 1929 deletions(-) delete mode 100644 lightningd/eltoo_channel.c delete mode 100644 lightningd/eltoo_channel.h diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index abb71d475a3e..bc664918efe1 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -378,7 +378,7 @@ msgtype,channeld_got_ack_reply,1182 msgtype,channeld_got_shutdown_eltoo,1084 msgdata,channeld_got_shutdown_eltoo,scriptpubkey_len,u16, msgdata,channeld_got_shutdown_eltoo,scriptpubkey,u8,scriptpubkey_len -msgdata,channeld_got_shutdown_eltoo,wrong_funding,?bitcoin_outpoint, +msgdata,channeld_got_shutdown_eltoo,their_next_nonce,nonce, # When we send a update_signed message, tell master. msgtype,channeld_sending_updatesig,1080 @@ -392,8 +392,3 @@ msgdata,channeld_sending_updatesig,session,musig_session, # Wait for reply, to make sure it's on disk before we send commit. msgtype,channeld_sending_updatesig_reply,1180 -# Peer told us that channel is shutting down -msgtype,channeld_got_shutdown_eltoo,1084 -msgdata,channeld_got_shutdown_eltoo,scriptpubkey_len,u16, -msgdata,channeld_got_shutdown_eltoo,scriptpubkey,u8,scriptpubkey_len -msgdata,channeld_got_shutdown_eltoo,wrong_funding,?bitcoin_outpoint, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 61e7560e1c38..a5eb44e6c65d 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -74,8 +75,7 @@ struct eltoo_peer { u64 htlc_id; struct channel_id channel_id; - struct eltoo_channel *channel; - struct channel *channel; + struct channel *channel; /* Messages from master: we queue them since we might be * waiting for a specific reply. */ @@ -285,7 +285,7 @@ static bool handle_master_request_later(struct eltoo_peer *peer, const u8 *msg) } #else /* !EXPERIMENTAL_FEATURES */ -static bool handle_master_request_later(struct peer *peer, const u8 *msg) +static bool handle_master_request_later(struct eltoo_peer *peer, const u8 *msg) { return false; } @@ -634,7 +634,7 @@ static void handle_peer_add_htlc(struct eltoo_peer *peer, const u8 *msg) #if EXPERIMENTAL_FEATURES blinding = tlvs->blinding; #endif - add_err = channel_add_htlc(peer->channel, REMOTE, id, amount, + add_err = eltoo_channel_add_htlc(peer->channel, REMOTE, id, amount, cltv_expiry, &payment_hash, onion_routing_packet, blinding, &htlc, /* err_immediate_failures */ false); @@ -735,7 +735,7 @@ static void send_shutdown_complete(struct eltoo_peer *peer) /* This queues other traffic from the fd until we get reply. */ static u8 *master_wait_sync_reply(const tal_t *ctx, - struct peer *peer, + struct eltoo_peer *peer, const u8 *msg, int replytype) { @@ -774,6 +774,7 @@ static u8 *master_wait_sync_reply(const tal_t *ctx, static void send_update(struct eltoo_peer *peer) { u8 *msg; + const u8 *hsmd_msg; const struct htlc **changed_htlcs; struct bitcoin_tx **update_and_settle_txs; const struct htlc **htlc_map; @@ -841,11 +842,11 @@ static void send_update(struct eltoo_peer *peer) &peer->channel_id, update_and_settle_txs[0], update_and_settle_txs[1], - &peer->channel->eltoo_keyset.other_funding_pubkey, + &peer->channel->eltoo_keyset.other_funding_key, &peer->channel->eltoo_keyset.other_next_nonce); - msg = hsm_req(tmpctx, take(msg)); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.self_next_nonce)) + hsmd_msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Reading psign_update_tx reply: %s", tal_hex(tmpctx, msg)); @@ -1017,20 +1018,9 @@ static void send_update_sign_ack(struct eltoo_peer *peer, static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) { struct channel_id channel_id; - - /* - struct bitcoin_signature commit_sig; - secp256k1_ecdsa_signature *raw_sigs; - struct bitcoin_signature *htlc_sigs; - struct pubkey remote_htlckey; - */ struct bitcoin_tx **update_and_settle_txs; struct bip340sig update_sig; const struct htlc **htlc_map, **changed_htlcs; - const u8 *funding_wscript; - size_t i; - struct simple_htlc **htlcs; - const u8 * msg2; changed_htlcs = tal_arr(msg, const struct htlc *, 0); /* Does our counterparty offer any changes? */ @@ -1049,7 +1039,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) peer->last_empty_commitment = peer->next_index; } - if (!fromwire_update_signed(tmpctx, msg, + if (!fromwire_update_signed(msg, &channel_id, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad update_signed %s", tal_hex(msg, msg)); @@ -1079,7 +1069,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel_id, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.other_psig, - &peer->channel->eltoo_keyset.session + &peer->channel->eltoo_keyset.session, update_and_settle_txs[0], update_and_settle_txs[1], &peer->channel->eltoo_keyset.inner_pubkey); @@ -1105,14 +1095,13 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) } -static u8 *got_signed_ack_msg(struct peer *peer, +static u8 *got_signed_ack_msg(struct eltoo_peer *peer, u64 update_num, const struct htlc **changed_htlcs, - const bip340sig *update_sig) + const struct bip340sig *update_sig) { u8 *msg; struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); - const struct bitcoin_tx *ptx = NULL; for (size_t i = 0; i < tal_count(changed_htlcs); i++) { struct changed_htlc c; @@ -1141,7 +1130,6 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); struct bitcoin_tx **update_and_settle_txs; const struct htlc **htlc_map; - struct wally_tx_output *direct_outputs[NUM_SIDES]; if (!fromwire_update_signed_ack(msg, &channel_id, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) { @@ -1184,7 +1172,7 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNELD_GOT_ACK_REPLY); - status_debug("update_signed_ack %s: update = %d", + status_debug("update_signed_ack %s: update = %lu", side_to_str(peer->channel->opener), peer->next_index - 1); /* We may now be quiescent on our side. */ @@ -1324,15 +1312,14 @@ static void handle_peer_shutdown(struct eltoo_peer *peer, const u8 *shutdown) { struct channel_id channel_id; u8 *scriptpubkey; - struct tlv_shutdown_tlvs *tlvs; - struct bitcoin_outpoint *wrong_funding; /* Disable the channel. */ /* FIXME Re-enable when gossip worked on send_channel_update(peer, ROUTING_FLAGS_DISABLED); */ + /* No OPT_SHUTDOWN_WRONG_FUNDING support for now */ if (!fromwire_shutdown_eltoo(tmpctx, shutdown, &channel_id, &scriptpubkey, - &peer->channel->eltoo_keyset.other_next_nonce, &tlvs)) + &peer->channel->eltoo_keyset.other_next_nonce)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad shutdown %s", tal_hex(peer, shutdown)); @@ -1358,49 +1345,12 @@ static void handle_peer_shutdown(struct eltoo_peer *peer, const u8 *shutdown) tal_hex(peer, scriptpubkey), tal_hex(peer, peer->remote_upfront_shutdown_script)); - /* We only accept an wrong_funding if: - * 1. It was negotiated. - * 2. It's not dual-funding. - * 3. They opened it. - * 4. The channel was never used. - */ - if (tlvs->wrong_funding) { - if (!feature_negotiated(peer->our_features, - peer->their_features, - OPT_SHUTDOWN_WRONG_FUNDING)) - peer_failed_warn(peer->pps, &peer->channel_id, - "wrong_funding shutdown needs" - " feature %u", - OPT_SHUTDOWN_WRONG_FUNDING); - if (feature_negotiated(peer->our_features, - peer->their_features, - OPT_DUAL_FUND)) - peer_failed_warn(peer->pps, &peer->channel_id, - "wrong_funding shutdown invalid" - " with dual-funding"); - if (peer->channel->opener != REMOTE) - peer_failed_warn(peer->pps, &peer->channel_id, - "No shutdown wrong_funding" - " for channels we opened!"); - if (peer->next_index != 1 - || peer->next_index != 1) - peer_failed_warn(peer->pps, &peer->channel_id, - "No shutdown wrong_funding" - " for used channels!"); - - /* Turn into our outpoint type. */ - wrong_funding = tal(tmpctx, struct bitcoin_outpoint); - wrong_funding->txid = tlvs->wrong_funding->txid; - wrong_funding->n = tlvs->wrong_funding->outnum; - } else { - wrong_funding = NULL; - } /* Tell master: we don't have to wait because on reconnect other end * will re-send anyway. */ wire_sync_write(MASTER_FD, take(towire_channeld_got_shutdown_eltoo(NULL, scriptpubkey, - wrong_funding, &peer->channel->eltoo_keyset.other_next_nonce))); + &peer->channel->eltoo_keyset.other_next_nonce))); peer->shutdown_sent[REMOTE] = true; /* BOLT #2: @@ -1418,7 +1368,7 @@ static void handle_peer_shutdown(struct eltoo_peer *peer, const u8 *shutdown) billboard_update(peer); } -static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) +static void handle_unexpected_reestablish(struct eltoo_peer *peer, const u8 *msg) { struct channel_id channel_id; u64 last_update_number; @@ -1429,19 +1379,12 @@ static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) #endif + /* No reestablish tlvs for now */ if (!fromwire_channel_reestablish_eltoo -#if EXPERIMENTAL_FEATURES - (tmpctx, msg, &channel_id, - &last_update_number, - &their_last_psig, - &their_next_nonce, - &tlvs) -#else (msg, &channel_id, &last_update_number, &their_last_psig, &their_next_nonce) -#endif ) peer_failed_warn(peer->pps, &peer->channel_id, "Bad channel_reestablish %s", tal_hex(peer, msg)); diff --git a/channeld/eltoo_channeld.h b/channeld/eltoo_channeld.h index a2b26b08246a..9dd2cdfa9979 100644 --- a/channeld/eltoo_channeld.h +++ b/channeld/eltoo_channeld.h @@ -1,5 +1,5 @@ -#ifndef LIGHTNING_CHANNELD_CHANNELD_H -#define LIGHTNING_CHANNELD_CHANNELD_H +#ifndef LIGHTNING_CHANNELD_ELTOO_CHANNELD_H +#define LIGHTNING_CHANNELD_ELTOO_CHANNELD_H #include "config.h" #include #include @@ -7,4 +7,4 @@ const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES); -#endif /* LIGHTNING_CHANNELD_CHANNELD_H */ +#endif /* LIGHTNING_CHANNELD_ELTOO_CHANNELD_H */ diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index d76334b7a322..75730cc1b8c0 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -3,8 +3,11 @@ #include #include #include -#include +#include +#include +#include #include +#include #include #include #include @@ -14,6 +17,7 @@ #include #include #include +#include #include /* Needs to be at end, since it doesn't include its own hdrs */ #include "full_channel_error_names_gen.h" @@ -45,7 +49,7 @@ static void balance_add_htlc(struct balance *balance, const struct htlc *htlc, enum side side) { - if (eltoo_htlc_owner(htlc) == side) + if (htlc_owner(htlc) == side) balance->msat -= htlc->amount.millisatoshis; /* Raw: balance */ } @@ -58,9 +62,9 @@ static void balance_remove_htlc(struct balance *balance, /* Fulfilled HTLCs are paid to recipient, otherwise returns to owner */ if (htlc->r) - paid_to = !eltoo_htlc_owner(htlc); + paid_to = !htlc_owner(htlc); else - paid_to = eltoo_htlc_owner(htlc); + paid_to = htlc_owner(htlc); if (side == paid_to) balance->msat += htlc->amount.millisatoshis; /* Raw: balance */ @@ -79,7 +83,7 @@ static bool balance_ok(const struct balance *balance, return true; } -struct eltoo_channel *new_full_eltoo_channel(const tal_t *ctx, +struct channel *new_full_eltoo_channel(const tal_t *ctx, const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, @@ -95,7 +99,7 @@ struct eltoo_channel *new_full_eltoo_channel(const tal_t *ctx, bool option_wumbo, enum side opener) { - struct eltoo_channel *channel = new_initial_eltoo_channel(ctx, + struct channel *channel = new_initial_eltoo_channel(ctx, cid, funding, minimum_depth, @@ -146,7 +150,7 @@ static void dump_htlc(const struct htlc *htlc, const char *prefix) : ""); } -void dump_htlcs(const struct eltoo_channel *channel, const char *prefix) +void dump_htlcs(const struct channel *channel, const char *prefix) { #ifdef SUPERVERBOSE struct htlc_map_iter it; @@ -232,69 +236,15 @@ static bool sum_offered_msatoshis(struct amount_msat *total, return true; } -static void add_htlcs(struct bitcoin_tx ***txs, - const struct htlc **htlcmap, - const struct channel *channel, - const struct keyset *keyset, - enum side side) -{ - struct bitcoin_outpoint outpoint; - u32 feerate_per_kw = channel_feerate(channel, side); - bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); - - /* Get txid of commitment transaction */ - bitcoin_txid((*txs)[0], &outpoint.txid); - - for (outpoint.n = 0; outpoint.n < tal_count(htlcmap); outpoint.n++) { - const struct htlc *htlc = htlcmap[outpoint.n]; - struct bitcoin_tx *tx; - struct ripemd160 ripemd; - const u8 *wscript; - - if (!htlc) - continue; - - if (htlc_owner(htlc) == side) { - ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); - wscript = htlc_offered_wscript(tmpctx, &ripemd, keyset, - option_anchor_outputs); - tx = htlc_timeout_tx(*txs, chainparams, &outpoint, - wscript, - htlc->amount, - htlc->expiry.locktime, - channel->config[!side].to_self_delay, - feerate_per_kw, - keyset, - option_anchor_outputs); - } else { - ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); - wscript = htlc_received_wscript(tmpctx, &ripemd, - &htlc->expiry, keyset, - option_anchor_outputs); - tx = htlc_success_tx(*txs, chainparams, &outpoint, - wscript, - htlc->amount, - channel->config[!side].to_self_delay, - feerate_per_kw, - keyset, - option_anchor_outputs); - } - - /* Append to array. */ - tal_arr_expand(txs, tx); - } -} - struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, const struct htlc ***htlcmap, struct wally_tx_output *direct_outputs[NUM_SIDES], - const struct eltoo_channel *channel, + const struct channel *channel, u64 update_number, enum side side) { struct bitcoin_tx **txs; const struct htlc **committed; - char** err_reason; /* Figure out what @side will already be committed to. */ gather_htlcs(ctx, channel, side, &committed, NULL, NULL); @@ -314,8 +264,7 @@ struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, txs[0] = unbound_update_tx(ctx, txs[0], channel->funding_sats, - &channel->eltoo_keyset.inner_pubkey, - err_reason); + &channel->eltoo_keyset.inner_pubkey); /* FIXME We don't handle failure to construct transactions yet */ assert(txs[0]); @@ -332,23 +281,7 @@ struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, return txs; } -static size_t num_untrimmed_htlcs(enum side side, - struct amount_sat dust_limit, - u32 feerate, - bool option_static_remotekey, - const struct htlc **committed, - const struct htlc **adding, - const struct htlc **removing) -{ - return commit_tx_num_untrimmed(committed, feerate, dust_limit, - option_static_remotekey, side) - + commit_tx_num_untrimmed(adding, feerate, dust_limit, - option_static_remotekey, side) - - commit_tx_num_untrimmed(removing, feerate, dust_limit, - option_static_remotekey, side); -} - -static enum channel_add_err add_htlc(struct eltoo_channel *channel, +static enum channel_add_err add_htlc(struct channel *channel, enum htlc_state state, u64 id, struct amount_msat amount, @@ -358,7 +291,6 @@ static enum channel_add_err add_htlc(struct eltoo_channel *channel, const struct pubkey *blinding TAKES, struct htlc **htlcp, bool enforce_aggregate_limits, - struct amount_sat *htlc_fee, bool err_immediate_failures) { struct htlc *htlc, *old; @@ -366,8 +298,8 @@ static enum channel_add_err add_htlc(struct eltoo_channel *channel, adding_msat, removing_msat, htlc_dust_amt; enum side sender = htlc_state_owner(state), recipient = !sender; const struct htlc **committed, **adding, **removing; - const struct channel_view *view; - size_t htlc_count; + size_t htlc_count; + bool ok; htlc = tal(tmpctx, struct htlc); @@ -408,9 +340,6 @@ static enum channel_add_err add_htlc(struct eltoo_channel *channel, return CHANNEL_ERR_DUPLICATE; } - /* We're always considering the recipient's view of the channel here */ - view = &channel->view[recipient]; - /* BOLT #2: * * A receiving node: @@ -500,8 +429,12 @@ static enum channel_add_err add_htlc(struct eltoo_channel *channel, /* No fee "fun", just don't make relay dust */ - htlc_dust_amt = channel->config[side].dust_limit; - assert(channel->config[side].dust_limit, channel->config[!side].dust_limit); + ok = amount_sat_to_msat(&htlc_dust_amt, channel->config[sender].dust_limit); + /* Shouldn't happen? */ + assert(ok); + + assert(channel->config[sender].dust_limit.satoshis == + channel->config[!sender].dust_limit.satoshis); /* This really shouldn't happen unless you never want an HTLC... */ if (amount_msat_greater(htlc_dust_amt, @@ -521,7 +454,7 @@ static enum channel_add_err add_htlc(struct eltoo_channel *channel, return CHANNEL_ERR_ADD_OK; } -enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, +enum channel_add_err eltoo_channel_add_htlc(struct channel *channel, enum side sender, u64 id, struct amount_msat amount, @@ -552,12 +485,12 @@ enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, htlcp, true, err_immediate_failures); } -struct htlc *eltoo_channel_get_htlc(struct eltoo_channel *channel, enum side sender, u64 id) +struct htlc *eltoo_channel_get_htlc(struct channel *channel, enum side sender, u64 id) { return eltoo_htlc_get(channel->htlcs, id, sender); } -enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, +enum channel_remove_err channel_fulfill_htlc(struct channel *channel, enum side owner, u64 id, const struct preimage *preimage, @@ -566,7 +499,7 @@ enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, struct sha256 hash; struct htlc *htlc; - htlc = channel_get_htlc(channel, owner, id); + htlc = eltoo_channel_get_htlc(channel, owner, id); if (!htlc) return CHANNEL_ERR_NO_SUCH_ID; @@ -628,7 +561,7 @@ enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, return CHANNEL_ERR_REMOVE_OK; } -enum channel_remove_err channel_fail_htlc(struct eltoo_channel *channel, +enum channel_remove_err channel_fail_htlc(struct channel *channel, enum side owner, u64 id, struct htlc **htlcp) { @@ -670,7 +603,7 @@ enum channel_remove_err channel_fail_htlc(struct eltoo_channel *channel, return CHANNEL_ERR_REMOVE_OK; } -static void htlc_incstate(struct eltoo_channel *channel, +static void htlc_incstate(struct channel *channel, struct htlc *htlc, enum side sidechanged, struct balance owed[NUM_SIDES]) @@ -711,7 +644,7 @@ static void htlc_incstate(struct eltoo_channel *channel, } /* Returns flags which were changed. */ -static int change_htlcs(struct eltoo_channel *channel, +static int change_htlcs(struct channel *channel, enum side sidechanged, const enum htlc_state *htlc_states, size_t n_hstates, @@ -756,86 +689,7 @@ static int change_htlcs(struct eltoo_channel *channel, return cflags; } -/* FIXME: The sender's requirements are *implied* by this, not stated! */ -/* BOLT #2: - * - * A receiving node: - *... - * - if the sender cannot afford the new fee rate on the receiving node's - * current commitment transaction: - * - SHOULD send a `warning` and close the connection, or send an - * `error` and fail the channel. - */ -u32 approx_max_feerate(const struct channel *channel) -{ - size_t num; - u64 weight; - struct amount_sat avail; - const struct htlc **committed, **adding, **removing; - bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); - - gather_htlcs(tmpctx, channel, !channel->opener, - &committed, &removing, &adding); - - /* Assume none are trimmed; this gives lower bound on feerate. */ - num = tal_count(committed) + tal_count(adding) - tal_count(removing); - - weight = commit_tx_base_weight(num, option_anchor_outputs); - - /* Available is their view */ - avail = amount_msat_to_sat_round_down(channel->view[!channel->opener].owed[channel->opener]); - - /* BOLT #3: - * If `option_anchors` applies to the commitment - * transaction, also subtract two times the fixed anchor size - * of 330 sats from the funder (either `to_local` or - * `to_remote`). - */ - if (option_anchor_outputs - && !amount_sat_sub(&avail, avail, AMOUNT_SAT(660))) { - avail = AMOUNT_SAT(0); - } else { - /* We should never go below reserve. */ - if (!amount_sat_sub(&avail, avail, - channel->config[!channel->opener].channel_reserve)) - avail = AMOUNT_SAT(0); - } - - return avail.satoshis / weight * 1000; /* Raw: once-off reverse feerate*/ -} - -/* Is the sum of trimmed htlcs, as this new feerate, above our - * max allowed htlc dust limit? */ -static struct amount_msat htlc_calculate_dust(const struct channel *channel, - u32 feerate_per_kw, - enum side side) -{ - const struct htlc **committed, **adding, **removing; - struct amount_msat acc_dust = AMOUNT_MSAT(0); - - gather_htlcs(tmpctx, channel, side, - &committed, &removing, &adding); - - htlc_dust(channel, committed, adding, removing, - side, feerate_per_kw, &acc_dust); - - return acc_dust; -} - -bool htlc_dust_ok(const struct channel *channel, - u32 feerate_per_kw, - enum side side) -{ - struct amount_msat total_dusted; - - total_dusted = htlc_calculate_dust(channel, feerate_per_kw, side); - - return amount_msat_greater_eq( - channel->config[LOCAL].max_dust_htlc_exposure_msat, - total_dusted); -} - -bool channel_sending_update(struct eltoo_channel *channel, +bool channel_sending_update(struct channel *channel, const struct htlc ***htlcs) { int change; @@ -882,22 +736,7 @@ bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs) return true; } -bool channel_sending_revoke_and_ack(struct channel *channel) -{ - int change; - const enum htlc_state states[] = { RCVD_ADD_ACK_COMMIT, - RCVD_REMOVE_COMMIT, - RCVD_ADD_COMMIT, - RCVD_REMOVE_ACK_COMMIT }; - status_debug("Sending revoke_and_ack"); - change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), NULL, - "sending_revoke_and_ack"); - - /* Our ack can queue changes on their side. */ - return (change & HTLC_REMOTE_F_PENDING); -} - -size_t num_channel_htlcs(const struct eltoo_channel *channel) +size_t num_channel_htlcs(const struct channel *channel) { struct htlc_map_iter it; const struct htlc *htlc; @@ -947,7 +786,7 @@ static bool adjust_balance(struct balance view_owed[NUM_SIDES][NUM_SIDES], return true; } -bool pending_updates(const struct eltoo_channel *channel, +bool pending_updates(const struct channel *channel, enum side side, bool uncommitted_ok) { @@ -983,7 +822,7 @@ bool pending_updates(const struct eltoo_channel *channel, return false; } -bool channel_force_htlcs(struct eltoo_channel *channel, +bool channel_force_htlcs(struct channel *channel, const struct existing_htlc **htlcs) { struct balance view_owed[NUM_SIDES][NUM_SIDES]; @@ -1022,7 +861,7 @@ bool channel_force_htlcs(struct eltoo_channel *channel, &htlcs[i]->payment_hash, htlcs[i]->onion_routing_packet, htlcs[i]->blinding, - &htlc, false, NULL, false); + &htlc, false, false); if (e != CHANNEL_ERR_ADD_OK) { status_broken("%s HTLC %"PRIu64" failed error %u", htlc_state_owner(htlcs[i]->state) == LOCAL diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h index fc71702382ce..05ca1c11950b 100644 --- a/channeld/eltoo_full_channel.h +++ b/channeld/eltoo_full_channel.h @@ -1,10 +1,10 @@ /* This is the full channel routines, with HTLC support. */ -#ifndef LIGHTNING_CHANNELD_FULL_CHANNEL_H -#define LIGHTNING_CHANNELD_FULL_CHANNEL_H +#ifndef LIGHTNING_CHANNELD_ELTOO_FULL_CHANNEL_H +#define LIGHTNING_CHANNELD_ELTOO_FULL_CHANNEL_H #include "config.h" #include #include -#include +#include #include struct channel_id; @@ -16,24 +16,21 @@ struct existing_htlc; * @cid: The channel id. * @funding: The commitment transaction id/output number. * @minimum_depth: The minimum confirmations needed for funding transaction. - * @blockheight_states: The blockheight update states. - * @lease_expiry: The block the lease on this channel expires at; 0 if no lease. * @funding_sats: The commitment transaction amount. * @local_msat: The amount for the local side (remainder goes to remote) - * @fee_states: The fee update states. * @local: local channel configuration * @remote: remote channel configuration - * @local_basepoints: local basepoints. - * @remote_basepoints: remote basepoints. * @local_fundingkey: local funding key * @remote_fundingkey: remote funding key + * @local_settle_pubkey: local settlement key + * @remote_settle_pubkey: remote settlement key * @type: type for this channel * @option_wumbo: large channel negotiated. * @opener: which side initiated it. * * Returns state, or NULL if malformed. */ -struct eltoo_channel *new_full_eltoo_channel(const tal_t *ctx, +struct channel *new_full_eltoo_channel(const tal_t *ctx, const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, @@ -43,6 +40,8 @@ struct eltoo_channel *new_full_eltoo_channel(const tal_t *ctx, const struct channel_config *remote, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, + const struct pubkey *local_settle_pubkey, + const struct pubkey *remote_settle_pubkey, const struct channel_type *type TAKES, bool option_wumbo, enum side opener); @@ -62,33 +61,15 @@ struct eltoo_channel *new_full_eltoo_channel(const tal_t *ctx, * for @side, followed by the htlc transactions in output order and * fills in @htlc_map, or NULL on key derivation failure. */ -struct bitcoin_tx **channel_txs(const tal_t *ctx, - const struct htlc ***htlcmap, - struct wally_tx_output *direct_outputs[NUM_SIDES], - const u8 **funding_wscript, - const struct eltoo_channel *channel, - const struct pubkey *per_commitment_point, - u64 commitment_number, - enum side side); +struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, + const struct htlc ***htlcmap, + struct wally_tx_output *direct_outputs[NUM_SIDES], + const struct channel *channel, + u64 update_number, + enum side side); /** - * actual_feerate: what is the actual feerate for the local side. - * @channel: The channel state - * @theirsig: The other side's signature - * - * The fee calculated on a commitment transaction is a worst-case - * approximation. It's also possible that the desired feerate is not - * met, because the initiator sets it while the other side is adding many - * htlcs. - * - * This is the fee rate we actually care about, if we're going to check - * whether it's actually too low. - */ -u32 actual_feerate(const struct eltoo_channel *channel, - const struct signature *theirsig); - -/** - * channel_add_htlc: append an HTLC to channel if it can afford it + * eltoo_channel_add_htlc: append an HTLC to channel if it can afford it * @channel: The channel * @offerer: the side offering the HTLC (to the other side). * @id: unique HTLC id. @@ -107,7 +88,7 @@ u32 actual_feerate(const struct eltoo_channel *channel, * the output amounts adjusted accordingly. Otherwise nothing * is changed. */ -enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, +enum channel_add_err eltoo_channel_add_htlc(struct channel *channel, enum side sender, u64 id, struct amount_msat msatoshi, @@ -116,16 +97,15 @@ enum channel_add_err channel_add_htlc(struct eltoo_channel *channel, const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)], const struct pubkey *blinding TAKES, struct htlc **htlcp, - struct amount_sat *htlc_fee, bool err_immediate_failures); /** - * channel_get_htlc: find an HTLC + * eltoo_channel_get_htlc: find an HTLC * @channel: The channel * @offerer: the side offering the HTLC. * @id: unique HTLC id. */ -struct htlc *channel_get_htlc(struct eltoo_channel *channel, enum side sender, u64 id); +struct htlc *eltoo_channel_get_htlc(struct channel *channel, enum side sender, u64 id); /** * channel_fail_htlc: remove an HTLC, funds to the side which offered it. @@ -137,7 +117,7 @@ struct htlc *channel_get_htlc(struct eltoo_channel *channel, enum side sender, u * This will remove the htlc and credit the value of the HTLC (back) * to its offerer. */ -enum channel_remove_err channel_fail_htlc(struct eltoo_channel *channel, +enum channel_remove_err channel_fail_htlc(struct channel *channel, enum side owner, u64 id, struct htlc **htlcp); @@ -153,82 +133,29 @@ enum channel_remove_err channel_fail_htlc(struct eltoo_channel *channel, * remove the htlc and give the value of the HTLC to its recipient, * and return CHANNEL_ERR_FULFILL_OK. Otherwise, it will return another error. */ -enum channel_remove_err channel_fulfill_htlc(struct eltoo_channel *channel, +enum channel_remove_err channel_fulfill_htlc(struct channel *channel, enum side owner, u64 id, const struct preimage *preimage, struct htlc **htlcp); /** - * approx_max_feerate: what's the max opener could raise fee rate to? - * @channel: The channel state - * - * This is not exact! To check if their offer is valid, try - * channel_update_feerate. - */ -u32 approx_max_feerate(const struct eltoo_channel *channel); - -/** - * can_opener_afford_feerate: could the opener pay the fee? - * @channel: The channel state - * @feerate: The feerate in satoshi per 1000 bytes. - */ -bool can_opener_afford_feerate(const struct eltoo_channel *channel, u32 feerate); - -/** - * htlc_dust_ok: will this feerate keep our dusted htlc's beneath - * the updated feerate? - * - * @channel: The channel state - * @feerate_per_kw: new feerate to test ok'ness for - * @side: which side's htlcs to verify - */ -bool htlc_dust_ok(const struct eltoo_channel *channel, - u32 feerate_per_kw, - enum side side); - -/** - * channel_update_feerate: Change fee rate on non-opener side. - * @channel: The channel - * @feerate_per_kw: fee in satoshi per 1000 bytes. - * - * Returns true if it's affordable, otherwise does nothing. - */ -bool channel_update_feerate(struct eltoo_channel *channel, u32 feerate_per_kw); - -/* - * channel_update_blockheight: Change blockheight on non-opener side. - * @channel: The channel - * @blockheight: current blockheight - */ -void channel_update_blockheight(struct eltoo_channel *channel, u32 blockheight); - -/** - * channel_feerate: Get fee rate for this side of channel. - * @channel: The channel - * @side: the side - */ -u32 channel_feerate(const struct eltoo_channel *channel, enum side side); - -/** - * channel_sending_commit: commit all remote outstanding changes. + * channel_sending_update: commit all remote outstanding changes. * @channel: the channel * @htlcs: initially-empty tal_arr() for htlcs which changed state. * * This is where we commit to pending changes we've added; returns true if * anything changed for the remote side (if not, don't send!) */ -bool channel_sending_commit(struct eltoo_channel *channel, +bool channel_sending_update(struct channel *channel, const struct htlc ***htlcs); /** - * channel_rcvd_revoke_and_ack: accept ack on remote committed changes. + * channel_rcvd_update_sign_ack: accept ack on update. * @channel: the channel * @htlcs: initially-empty tal_arr() for htlcs which changed state. * - * This is where we commit to pending changes we've added; returns true if - * anything changed for our local commitment (ie. we have pending changes). */ -bool channel_rcvd_revoke_and_ack(struct eltoo_channel *channel, +bool channel_rcvd_update_sign_ack(struct channel *channel, const struct htlc ***htlcs); /** @@ -236,25 +163,15 @@ bool channel_rcvd_revoke_and_ack(struct eltoo_channel *channel, * @channel: the channel * @htlcs: initially-empty tal_arr() for htlcs which changed state. * - * This is where we commit to pending changes we've added; returns true if - * anything changed for our update (ie. we had pending changes added by other). */ -bool channel_rcvd_commit(struct eltoo_channel *channel, +bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs); -/** - * channel_sending_revoke_and_ack: sending ack on local committed changes. - * @channel: the channel - * - * This is where we commit to pending changes we've added. Returns true if - * anything changed for the remote commitment (ie. send a new commit).*/ -bool channel_sending_revoke_and_ack(struct eltoo_channel *channel); - /** * num_channel_htlcs: how many (live) HTLCs at all in channel? * @channel: the channel */ -size_t num_channel_htlcs(const struct eltoo_channel *channel); +size_t num_channel_htlcs(const struct channel *channel); /** * channel_force_htlcs: force these htlcs into the (new) channel @@ -263,7 +180,7 @@ size_t num_channel_htlcs(const struct eltoo_channel *channel); * * This is used for restoring a channel state. */ -bool channel_force_htlcs(struct eltoo_channel *channel, +bool channel_force_htlcs(struct channel *channel, const struct existing_htlc **htlcs); /** @@ -273,7 +190,7 @@ bool channel_force_htlcs(struct eltoo_channel *channel, * * Uses status_debug() on every HTLC. */ -void dump_htlcs(const struct eltoo_channel *channel, const char *prefix); +void dump_htlcs(const struct channel *channel, const char *prefix); /** * pending_updates: does this side have updates pending in channel? @@ -281,10 +198,10 @@ void dump_htlcs(const struct eltoo_channel *channel, const char *prefix); * @side: the side who is offering or failing/fulfilling HTLC, or feechange * @uncommitted_ok: don't count uncommitted changes. */ -bool pending_updates(const struct eltoo_channel *channel, enum side side, +bool pending_updates(const struct channel *channel, enum side side, bool uncommitted_ok); const char *channel_add_err_name(enum channel_add_err e); const char *channel_remove_err_name(enum channel_remove_err e); -#endif /* LIGHTNING_CHANNELD_FULL_CHANNEL_H */ +#endif /* LIGHTNING_CHANNELD_ELTOO_FULL_CHANNEL_H */ diff --git a/channeld/settle_tx.h b/channeld/settle_tx.h index 228b84648b94..3d61549866cf 100644 --- a/channeld/settle_tx.h +++ b/channeld/settle_tx.h @@ -1,5 +1,5 @@ -#ifndef LIGHTNING_CHANNELD_COMMIT_TX_H -#define LIGHTNING_CHANNELD_COMMIT_TX_H +#ifndef LIGHTNING_CHANNELD_SETTLE_TX_H +#define LIGHTNING_CHANNELD_SETTLE_TX_H #include "config.h" #include #include @@ -30,11 +30,6 @@ bool settle_tx_amount_trimmed(const struct htlc **htlcs, struct amount_sat dust_limit, struct amount_msat *amt); -static void add_eltoo_htlc_out(struct bitcoin_tx *tx, - const struct htlc *htlc, - const struct eltoo_keyset *eltoo_keyset, - enum side receiver_side); - /** * settle_tx: create (unsigned) settlement tx to spend the funding tx output * @ctx: context to allocate transaction and @htlc_map from. @@ -63,4 +58,4 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, struct wally_tx_output *direct_outputs[NUM_SIDES], u64 obscured_update_number); -#endif /* LIGHTNING_CHANNELD_COMMIT_TX_H */ +#endif /* LIGHTNING_CHANNELD_SETTLE_TX_H */ diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index d59dc2827aef..cbc82ea746a6 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -560,8 +560,7 @@ static int test_invalid_update_tx(void) self_pay, other_pay, obscured_update_number, - /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, - &err_reason); + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL); psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); printf("Settlement psbt 0: %s\n", psbt_b64); @@ -582,8 +581,7 @@ static int test_invalid_update_tx(void) update_tx = unbound_update_tx(tmpctx, tx, update_output_sats, - &inner_pubkey, - &err_reason); + &inner_pubkey); /* Signing happens next */ annex_0 = make_eltoo_annex(tmpctx, tx); @@ -627,8 +625,7 @@ static int test_invalid_update_tx(void) update_tx_1_A = unbound_update_tx(tmpctx, settle_tx_1, update_output_sats, - &inner_pubkey, - &err_reason); + &inner_pubkey); /* Authorize this next state update */ annex_1 = make_eltoo_annex(tmpctx, settle_tx_1); @@ -731,8 +728,7 @@ static int test_initial_settlement_tx(void) self_pay, other_pay, obscured_update_number, - /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, - &err_reason); + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL); psbt_b64 = psbt_to_b64(tmpctx, tx->psbt); printf("Initial Settlement psbt: %s\n", psbt_b64); @@ -753,8 +749,7 @@ static int test_initial_settlement_tx(void) update_tx = unbound_update_tx(tmpctx, tx, update_output_sats, - &inner_pubkey, - &err_reason); + &inner_pubkey); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); printf("Unbound update psbt: %s\n", psbt_b64); diff --git a/common/Makefile b/common/Makefile index d35eb7303895..4b8c34c2b7da 100644 --- a/common/Makefile +++ b/common/Makefile @@ -46,6 +46,7 @@ COMMON_SRC_NOGEN := \ common/htlc_wire.c \ common/initial_channel.c \ common/initial_commit_tx.c \ + common/initial_eltoo_channel.c \ common/initial_settlement_tx.c \ common/iso4217.c \ common/json.c \ diff --git a/common/initial_channel.h b/common/initial_channel.h index 3b9251f66c28..61943ecaabaa 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -8,6 +8,7 @@ #include #include #include +#include struct signature; struct added_htlc; @@ -73,9 +74,12 @@ struct channel { /* Eltoo fields below */ - /* Keys used for the lifetime of the channel */ + /* Keys and signing state used for the lifetime of the channel */ struct eltoo_keyset eltoo_keyset; + /* Mask for obscuring the encoding of the update number. */ + u64 update_number_obscurer; + /* End Eltoo fields*/ }; diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index c1e73d127795..d65972acff77 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -5,13 +5,14 @@ #include #include #include +#include #include #include #include #include #include -struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, +struct channel *new_initial_eltoo_channel(const tal_t *ctx, const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, @@ -27,7 +28,7 @@ struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, bool option_wumbo, enum side opener) { - struct eltoo_channel *channel = tal(ctx, struct eltoo_channel); + struct channel *channel = tal(ctx, struct channel); struct amount_msat remote_msatoshi; const struct pubkey *pubkey_ptrs[2]; secp256k1_musig_keyagg_cache keyagg_cache; @@ -74,9 +75,8 @@ struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, } struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, - const struct eltoo_channel *channel, - struct wally_tx_output *direct_outputs[NUM_SIDES], - char** err_reason) + const struct channel *channel, + struct wally_tx_output *direct_outputs[NUM_SIDES]) { struct bitcoin_tx *init_settle_tx; @@ -92,8 +92,7 @@ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, channel->view->owed[LOCAL], channel->view->owed[REMOTE], 0 ^ channel->update_number_obscurer, - direct_outputs, - err_reason); + direct_outputs); if (init_settle_tx) { psbt_input_add_pubkey(init_settle_tx->psbt, 0, @@ -107,8 +106,7 @@ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, - const struct eltoo_channel *channel, - char** err_reason) + const struct channel *channel) { struct bitcoin_tx *init_update_tx; /* This should be gathered from settle_tx PSBT when stored there, @@ -123,8 +121,7 @@ struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, init_update_tx = unbound_update_tx(ctx, settle_tx, channel->funding_sats, - &dummy_inner_pubkey, - err_reason); + &dummy_inner_pubkey); if (init_update_tx) { psbt_input_add_pubkey(init_update_tx->psbt, 0, diff --git a/common/initial_eltoo_channel.h b/common/initial_eltoo_channel.h index f9f58da1cbda..bf36411618b4 100644 --- a/common/initial_eltoo_channel.h +++ b/common/initial_eltoo_channel.h @@ -1,66 +1,21 @@ /* This represents a channel with no HTLCs: all that's required for openingd. */ -#ifndef LIGHTNING_COMMON_INITIAL_CHANNEL_H -#define LIGHTNING_COMMON_INITIAL_CHANNEL_H +#ifndef LIGHTNING_COMMON_INITIAL_ELTOO_CHANNEL_H +#define LIGHTNING_COMMON_INITIAL_ELTOO_CHANNEL_H #include "config.h" #include #include #include -#include #include +#include #include +#include struct signature; struct added_htlc; struct failed_htlc; struct fulfilled_htlc; -/* View from each side */ -struct channel_view { - /* How much is owed to each side (includes pending changes) */ - struct amount_msat owed[NUM_SIDES]; -}; - -struct eltoo_channel { - - /* The id for this channel */ - struct channel_id cid; - - /* Funding txid and output. */ - struct bitcoin_outpoint funding; - - /* Keys used for the lifetime of the channel */ - struct eltoo_keyset eltoo_keyset; - - /* satoshis in from commitment tx */ - struct amount_sat funding_sats; - - /* confirmations needed for locking funding */ - u32 minimum_depth; - - /* Who is paying fees. */ - enum side opener; - - /* Limits and settings on this channel. */ - struct channel_config config[NUM_SIDES]; - - /* Mask for obscuring the encoding of the update number. */ - u32 update_number_obscurer; - - /* All live HTLCs for this channel */ - struct htlc_map *htlcs; - - /* What it looks like to nodes. */ - struct channel_view view[NUM_SIDES]; - - /* Features which apply to this channel. */ - struct channel_type *type; - - /* Are we using big channels? */ - bool option_wumbo; - -}; - /** * new_initial_channel: Given initial funding, what is initial state? * @ctx: tal context to allocate return value from. @@ -81,7 +36,7 @@ struct eltoo_channel { * * Returns channel, or NULL if malformed. */ -struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, +struct channel *new_initial_eltoo_channel(const tal_t *ctx, const struct channel_id *cid, const struct bitcoin_outpoint *funding, u32 minimum_depth, @@ -102,15 +57,13 @@ struct eltoo_channel *new_initial_eltoo_channel(const tal_t *ctx, * @ctx: tal context to allocate return value from. * @channel: The channel to evaluate * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). - * @err_reason: When NULL is returned, this will point to a human readable reason. * * Returns the fully signed settlement transaction, or NULL * if the channel size was insufficient to cover reserves. */ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, - const struct eltoo_channel *channel, - struct wally_tx_output *direct_outputs[NUM_SIDES], - char** err_reason); + const struct channel *channel, + struct wally_tx_output *direct_outputs[NUM_SIDES]); /** * initial_update_channel_tx: Get the current update tx for the *empty* channel. Must be called @@ -118,14 +71,10 @@ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, * @ctx: tal context to allocate return value from. * @settle_tx: The settlement transaction to commit to * @channel: The channel to evaluate - * @err_reason: When NULL is returned, this will point to a human readable reason. * - * Returns the fully signed settlement transaction, or NULL - * if the channel size was insufficient to cover reserves. - */ + */ struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, - const struct eltoo_channel *channel, - char** err_reason); + const struct channel *channel); -#endif /* LIGHTNING_COMMON_INITIAL_CHANNEL_H */ +#endif /* LIGHTNING_COMMON_INITIAL_ELTOO_CHANNEL_H */ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index a3cb6a8cf494..3e977b7ae376 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -123,8 +123,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct amount_msat self_pay, struct amount_msat other_pay, u32 obscured_update_number, - struct wally_tx_output *direct_outputs[NUM_SIDES], - char** err_reason) + struct wally_tx_output *direct_outputs[NUM_SIDES]) { struct bitcoin_tx *tx; size_t output_index, num_untrimmed; diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 73b8007bffbb..ce703dec49d9 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -24,7 +24,6 @@ struct wally_tx_output; * @other_pay: amount to pay directly to the other side * @obscured_update_number: obscured update number "o+k" * @direct_outputs: If non-NULL, fill with pointers to the direct (non-HTLC) outputs (or NULL if none). - * @err_reason: When NULL is returned, this will point to a human readable reason. * */ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, @@ -36,8 +35,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct amount_msat self_pay, struct amount_msat other_pay, u32 obscured_update_number, - struct wally_tx_output *direct_outputs[NUM_SIDES], - char** err_reason); + struct wally_tx_output *direct_outputs[NUM_SIDES]); /* We always add a single ephemeral anchor output to settlement transactions */ diff --git a/common/update_tx.c b/common/update_tx.c index 5ac7b4372678..662d3db63648 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -188,8 +188,7 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, struct amount_sat funding_sats, - const struct pubkey *inner_pubkey, - char** err_reason) + const struct pubkey *inner_pubkey) { struct bitcoin_tx *update_tx; int pos; diff --git a/common/update_tx.h b/common/update_tx.h index 085f9df32d2f..58b847caba26 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -69,14 +69,12 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, * @settlement_tx: initial settlement tx created via `initial_settlement_tx` * @funding_sats: funding amount * @inner_pubkey: inner public key for the eltoo channel - * @err_reason: When NULL is returned, this will point to a human readable reason. * */ struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, struct amount_sat funding_sats, - const struct pubkey *inner_pubkey, - char** err_reason); + const struct pubkey *inner_pubkey); #endif /* LIGHTNING_COMMON_UPDATE_TX_H */ diff --git a/lightningd/Makefile b/lightningd/Makefile index da7e88b04f2d..8876dc55c929 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -9,7 +9,6 @@ LIGHTNINGD_SRC := \ lightningd/coin_mvts.c \ lightningd/dual_open_control.c \ lightningd/connect_control.c \ - lightningd/eltoo_channel.c \ lightningd/onion_message.c \ lightningd/gossip_control.c \ lightningd/hsm_control.c \ diff --git a/lightningd/eltoo_channel.c b/lightningd/eltoo_channel.c deleted file mode 100644 index 789d75554161..000000000000 --- a/lightningd/eltoo_channel.c +++ /dev/null @@ -1,937 +0,0 @@ -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void channel_set_owner(struct channel *channel, struct subd *owner) -{ - struct subd *old_owner = channel->owner; - channel->owner = owner; - - if (old_owner) { - subd_release_channel(old_owner, channel); - if (channel->connected) - maybe_disconnect_peer(channel->peer->ld, channel->peer); - } - channel->connected = (owner && owner->talks_to_peer); -} - -struct htlc_out *channel_has_htlc_out(struct channel *channel) -{ - struct htlc_out_map_iter outi; - struct htlc_out *hout; - struct lightningd *ld = channel->peer->ld; - - for (hout = htlc_out_map_first(&ld->htlcs_out, &outi); - hout; - hout = htlc_out_map_next(&ld->htlcs_out, &outi)) { - if (hout->key.channel == channel) - return hout; - } - - return NULL; -} - -struct htlc_in *channel_has_htlc_in(struct channel *channel) -{ - struct htlc_in_map_iter ini; - struct htlc_in *hin; - struct lightningd *ld = channel->peer->ld; - - for (hin = htlc_in_map_first(&ld->htlcs_in, &ini); - hin; - hin = htlc_in_map_next(&ld->htlcs_in, &ini)) { - if (hin->key.channel == channel) - return hin; - } - - return NULL; -} - -static void destroy_channel(struct channel *channel) -{ - /* Must not have any HTLCs! */ - struct htlc_out *hout = channel_has_htlc_out(channel); - struct htlc_in *hin = channel_has_htlc_in(channel); - - if (hout) - fatal("Freeing channel %s has hout %s", - channel_state_name(channel), - htlc_state_name(hout->hstate)); - - if (hin) - fatal("Freeing channel %s has hin %s", - channel_state_name(channel), - htlc_state_name(hin->hstate)); - - for (size_t i = 0; i < tal_count(channel->forgets); i++) - was_pending(command_fail(channel->forgets[i], LIGHTNINGD, - "Channel structure was freed!")); - - /* Free any old owner still hanging around. */ - channel_set_owner(channel, NULL); - - list_del_from(&channel->peer->channels, &channel->list); -} - -void delete_channel(struct channel *channel STEALS) -{ - struct peer *peer = channel->peer; - if (channel->dbid != 0) - wallet_channel_close(channel->peer->ld->wallet, channel->dbid); - tal_free(channel); - - maybe_delete_peer(peer); -} - -void get_channel_basepoints(struct lightningd *ld, - const struct node_id *peer_id, - const u64 dbid, - struct basepoints *local_basepoints, - struct pubkey *local_funding_pubkey) -{ - u8 *msg; - - assert(dbid != 0); - msg = towire_hsmd_get_channel_basepoints(NULL, peer_id, dbid); - if (!wire_sync_write(ld->hsm_fd, take(msg))) - fatal("Could not write to HSM: %s", strerror(errno)); - - msg = wire_sync_read(tmpctx, ld->hsm_fd); - if (!fromwire_hsmd_get_channel_basepoints_reply(msg, local_basepoints, - local_funding_pubkey)) - fatal("HSM gave bad hsm_get_channel_basepoints_reply %s", - tal_hex(msg, msg)); -} - -static void destroy_inflight(struct channel_inflight *inflight) -{ - list_del_from(&inflight->channel->inflights, &inflight->list); -} - -struct channel_inflight * -new_inflight(struct channel *channel, - const struct bitcoin_outpoint *funding_outpoint, - u32 funding_feerate, - struct amount_sat total_funds, - struct amount_sat our_funds, - struct wally_psbt *psbt STEALS, - struct bitcoin_tx *last_tx, - const struct bitcoin_signature last_sig, - const u32 lease_expiry, - const secp256k1_ecdsa_signature *lease_commit_sig, - const u32 lease_chan_max_msat, const u16 lease_chan_max_ppt, - const u32 lease_blockheight_start, - const struct amount_msat lease_fee) -{ - struct wally_psbt *last_tx_psbt_clone; - struct channel_inflight *inflight - = tal(channel, struct channel_inflight); - struct funding_info *funding - = tal(inflight, struct funding_info); - - funding->outpoint = *funding_outpoint; - funding->total_funds = total_funds; - funding->feerate = funding_feerate; - funding->our_funds = our_funds; - - inflight->funding = funding; - inflight->channel = channel; - inflight->remote_tx_sigs = false; - inflight->funding_psbt = tal_steal(inflight, psbt); - - /* Make a 'clone' of this tx */ - last_tx_psbt_clone = clone_psbt(inflight, last_tx->psbt); - inflight->last_tx = bitcoin_tx_with_psbt(inflight, last_tx_psbt_clone); - inflight->last_sig = last_sig; - inflight->tx_broadcast = false; - - /* Channel lease infos */ - inflight->lease_blockheight_start = lease_blockheight_start; - inflight->lease_expiry = lease_expiry; - inflight->lease_commit_sig - = tal_dup_or_null(inflight, secp256k1_ecdsa_signature, - lease_commit_sig); - - inflight->lease_chan_max_msat = lease_chan_max_msat; - inflight->lease_chan_max_ppt = lease_chan_max_ppt; - inflight->lease_fee = lease_fee; - - list_add_tail(&channel->inflights, &inflight->list); - tal_add_destructor(inflight, destroy_inflight); - - return inflight; -} - -struct open_attempt *new_channel_open_attempt(struct channel *channel) -{ - struct open_attempt *oa = tal(channel, struct open_attempt); - oa->channel = channel; - /* Copy over the config; we'll clobber the reserve */ - oa->our_config = channel->our_config; - oa->role = channel->opener == LOCAL ? TX_INITIATOR : TX_ACCEPTER; - oa->our_upfront_shutdown_script = NULL; - oa->cmd = NULL; - oa->aborted = false; - oa->open_msg = NULL; - - return oa; -} - -struct channel *new_unsaved_channel(struct peer *peer, - u32 feerate_base, - u32 feerate_ppm) -{ - struct lightningd *ld = peer->ld; - struct channel *channel = tal(ld, struct channel); - u8 *msg; - - channel->peer = peer; - /* Not saved to the database yet! */ - channel->unsaved_dbid = wallet_get_channel_dbid(ld->wallet); - /* A zero value database id means it's not saved in the database yet */ - channel->dbid = 0; - channel->error = NULL; - channel->openchannel_signed_cmd = NULL; - channel->state = DUALOPEND_OPEN_INIT; - channel->owner = NULL; - memset(&channel->billboard, 0, sizeof(channel->billboard)); - channel->billboard.transient = tal_fmt(channel, "%s", - "Empty channel init'd"); - channel->log = new_log(channel, ld->log_book, - &peer->id, - "chan#%"PRIu64, - channel->unsaved_dbid); - - channel->our_config.id = 0; - channel->open_attempt = NULL; - - channel->last_htlc_sigs = NULL; - channel->remote_funding_locked = false; - channel->scid = NULL; - channel->next_index[LOCAL] = 1; - channel->next_index[REMOTE] = 1; - channel->next_htlc_id = 0; - /* FIXME: remove push when v1 deprecated */ - channel->push = AMOUNT_MSAT(0); - channel->closing_fee_negotiation_step = 50; - channel->closing_fee_negotiation_step_unit - = CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; - channel->shutdown_wrong_funding = NULL; - channel->closing_feerate_range = NULL; - channel->channel_update = NULL; - - /* Channel is connected! */ - channel->connected = true; - channel->shutdown_scriptpubkey[REMOTE] = NULL; - channel->last_was_revoke = false; - channel->last_sent_commit = NULL; - channel->last_tx_type = TX_UNKNOWN; - - channel->feerate_base = feerate_base; - channel->feerate_ppm = feerate_ppm; - channel->old_feerate_timeout.ts.tv_sec = 0; - channel->old_feerate_timeout.ts.tv_nsec = 0; - /* closer not yet known */ - channel->closer = NUM_SIDES; - - /* BOLT-7b04b1461739c5036add61782d58ac490842d98b #9 - * | 222/223 | `option_dual_fund` - * | Use v2 of channel open, enables dual funding - * | IN9 - * | `option_anchor_outputs` */ - channel->static_remotekey_start[LOCAL] - = channel->static_remotekey_start[REMOTE] = 0; - channel->type = channel_type_anchor_outputs(channel); - channel->future_per_commitment_point = NULL; - - channel->lease_commit_sig = NULL; - - /* No shachain yet */ - channel->their_shachain.id = 0; - shachain_init(&channel->their_shachain.chain); - - msg = towire_hsmd_new_channel(NULL, &peer->id, channel->unsaved_dbid); - if (!wire_sync_write(ld->hsm_fd, take(msg))) - fatal("Could not write to HSM: %s", strerror(errno)); - msg = wire_sync_read(tmpctx, ld->hsm_fd); - if (!fromwire_hsmd_new_channel_reply(msg)) - fatal("HSM gave bad hsm_new_channel_reply %s", - tal_hex(msg, msg)); - - get_channel_basepoints(ld, &peer->id, channel->unsaved_dbid, - &channel->local_basepoints, - &channel->local_funding_pubkey); - - channel->forgets = tal_arr(channel, struct command *, 0); - list_add_tail(&peer->channels, &channel->list); - channel->rr_number = peer->ld->rr_counter++; - tal_add_destructor(channel, destroy_channel); - - list_head_init(&channel->inflights); - return channel; -} - -/* - * The maximum msat that this node could possibly accept for an htlc. - * It's the default htlc_maximum_msat in channel_updates, if none is - * explicitly set (and the cap on what can be set!). - * - * We advertize the maximum value possible, defined as the smaller - * of the remote's maximum in-flight HTLC or the total channel - * capacity the reserve we have to keep. - * FIXME: does this need fuzz? - */ -struct amount_msat htlc_max_possible_send(const struct channel *channel) -{ - struct amount_sat lower_bound; - struct amount_msat lower_bound_msat; - - /* These shouldn't fail */ - if (!amount_sat_sub(&lower_bound, channel->funding_sats, - channel->channel_info.their_config.channel_reserve)) { - log_broken(channel->log, "%s: their reserve %s > funding %s!", - __func__, - type_to_string(tmpctx, struct amount_sat, - &channel->funding_sats), - type_to_string(tmpctx, struct amount_sat, - &channel->channel_info.their_config.channel_reserve)); - return AMOUNT_MSAT(0); - } - - if (!amount_sat_to_msat(&lower_bound_msat, lower_bound)) { - log_broken(channel->log, "%s: impossible size channel %s!", - __func__, - type_to_string(tmpctx, struct amount_sat, - &lower_bound)); - return AMOUNT_MSAT(0); - } - - if (amount_msat_less(channel->channel_info.their_config.max_htlc_value_in_flight, - lower_bound_msat)) - lower_bound_msat = channel->channel_info.their_config.max_htlc_value_in_flight; - - return lower_bound_msat; -} - -struct channel *new_channel(struct peer *peer, u64 dbid, - /* NULL or stolen */ - struct wallet_shachain *their_shachain, - enum channel_state state, - enum side opener, - /* NULL or stolen */ - struct log *log, - const char *transient_billboard TAKES, - u8 channel_flags, - const struct channel_config *our_config, - u32 minimum_depth, - u64 next_index_local, - u64 next_index_remote, - u64 next_htlc_id, - const struct bitcoin_outpoint *funding, - struct amount_sat funding_sats, - struct amount_msat push, - struct amount_sat our_funds, - bool remote_funding_locked, - /* NULL or stolen */ - struct short_channel_id *scid, - struct channel_id *cid, - struct amount_msat our_msat, - struct amount_msat msat_to_us_min, - struct amount_msat msat_to_us_max, - /* Stolen */ - struct bitcoin_tx *last_tx, - const struct bitcoin_signature *last_sig, - /* NULL or stolen */ - const struct bitcoin_signature *last_htlc_sigs, - const struct channel_info *channel_info, - const struct fee_states *fee_states TAKES, - /* NULL or stolen */ - u8 *remote_shutdown_scriptpubkey, - const u8 *local_shutdown_scriptpubkey, - u64 final_key_idx, - bool last_was_revoke, - /* NULL or stolen */ - struct changed_htlc *last_sent_commit, - u32 first_blocknum, - u32 min_possible_feerate, - u32 max_possible_feerate, - bool connected, - const struct basepoints *local_basepoints, - const struct pubkey *local_funding_pubkey, - const struct pubkey *future_per_commitment_point, - u32 feerate_base, - u32 feerate_ppm, - const u8 *remote_upfront_shutdown_script, - u64 local_static_remotekey_start, - u64 remote_static_remotekey_start, - const struct channel_type *type STEALS, - enum side closer, - enum state_change reason, - /* NULL or stolen */ - const struct bitcoin_outpoint *shutdown_wrong_funding, - const struct height_states *height_states TAKES, - u32 lease_expiry, - secp256k1_ecdsa_signature *lease_commit_sig STEALS, - u32 lease_chan_max_msat, - u16 lease_chan_max_ppt, - struct amount_msat htlc_minimum_msat, - struct amount_msat htlc_maximum_msat) -{ - struct channel *channel = tal(peer->ld, struct channel); - struct amount_msat htlc_min, htlc_max; - - assert(dbid != 0); - channel->peer = peer; - channel->dbid = dbid; - channel->unsaved_dbid = 0; - channel->error = NULL; - channel->open_attempt = NULL; - channel->openchannel_signed_cmd = NULL; - if (their_shachain) - channel->their_shachain = *their_shachain; - else { - channel->their_shachain.id = 0; - shachain_init(&channel->their_shachain.chain); - } - channel->state = state; - channel->opener = opener; - channel->owner = NULL; - memset(&channel->billboard, 0, sizeof(channel->billboard)); - channel->billboard.transient = tal_strdup(channel, transient_billboard); - - if (!log) { - channel->log = new_log(channel, - peer->ld->log_book, - &channel->peer->id, - "chan#%"PRIu64, - dbid); - } else - channel->log = tal_steal(channel, log); - channel->channel_flags = channel_flags; - channel->our_config = *our_config; - channel->minimum_depth = minimum_depth; - channel->next_index[LOCAL] = next_index_local; - channel->next_index[REMOTE] = next_index_remote; - channel->next_htlc_id = next_htlc_id; - channel->funding = *funding; - channel->funding_sats = funding_sats; - channel->push = push; - channel->our_funds = our_funds; - channel->remote_funding_locked = remote_funding_locked; - channel->scid = tal_steal(channel, scid); - channel->cid = *cid; - channel->our_msat = our_msat; - channel->msat_to_us_min = msat_to_us_min; - channel->msat_to_us_max = msat_to_us_max; - channel->last_tx = tal_steal(channel, last_tx); - channel->last_tx->chainparams = chainparams; - channel->last_tx_type = TX_UNKNOWN; - channel->last_sig = *last_sig; - channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs); - channel->channel_info = *channel_info; - channel->fee_states = dup_fee_states(channel, fee_states); - channel->shutdown_scriptpubkey[REMOTE] - = tal_steal(channel, remote_shutdown_scriptpubkey); - channel->final_key_idx = final_key_idx; - channel->closing_fee_negotiation_step = 50; - channel->closing_fee_negotiation_step_unit - = CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; - channel->shutdown_wrong_funding - = tal_steal(channel, shutdown_wrong_funding); - channel->closing_feerate_range = NULL; - if (local_shutdown_scriptpubkey) - channel->shutdown_scriptpubkey[LOCAL] - = tal_steal(channel, local_shutdown_scriptpubkey); - else - channel->shutdown_scriptpubkey[LOCAL] - = p2wpkh_for_keyidx(channel, channel->peer->ld, - channel->final_key_idx); - channel->last_was_revoke = last_was_revoke; - channel->last_sent_commit = tal_steal(channel, last_sent_commit); - channel->first_blocknum = first_blocknum; - channel->min_possible_feerate = min_possible_feerate; - channel->max_possible_feerate = max_possible_feerate; - channel->connected = connected; - channel->local_basepoints = *local_basepoints; - channel->local_funding_pubkey = *local_funding_pubkey; - channel->future_per_commitment_point - = tal_steal(channel, future_per_commitment_point); - channel->feerate_base = feerate_base; - channel->feerate_ppm = feerate_ppm; - channel->old_feerate_timeout.ts.tv_sec = 0; - channel->old_feerate_timeout.ts.tv_nsec = 0; - channel->remote_upfront_shutdown_script - = tal_steal(channel, remote_upfront_shutdown_script); - channel->static_remotekey_start[LOCAL] = local_static_remotekey_start; - channel->static_remotekey_start[REMOTE] = remote_static_remotekey_start; - channel->type = tal_steal(channel, type); - channel->forgets = tal_arr(channel, struct command *, 0); - - channel->lease_expiry = lease_expiry; - channel->lease_commit_sig = tal_steal(channel, lease_commit_sig); - channel->lease_chan_max_msat = lease_chan_max_msat; - channel->lease_chan_max_ppt = lease_chan_max_ppt; - channel->blockheight_states = dup_height_states(channel, height_states); - channel->channel_update = NULL; - - /* DB migration, for example, sets min to 0, max to large: fixup */ - htlc_min = channel->channel_info.their_config.htlc_minimum; - if (amount_msat_greater(htlc_min, htlc_minimum_msat)) - channel->htlc_minimum_msat = htlc_min; - else - channel->htlc_minimum_msat = htlc_minimum_msat; - htlc_max = htlc_max_possible_send(channel); - if (amount_msat_less(htlc_max, htlc_maximum_msat)) - channel->htlc_maximum_msat = htlc_max; - else - channel->htlc_maximum_msat = htlc_maximum_msat; - - list_add_tail(&peer->channels, &channel->list); - channel->rr_number = peer->ld->rr_counter++; - tal_add_destructor(channel, destroy_channel); - - list_head_init(&channel->inflights); - - channel->closer = closer; - channel->state_change_cause = reason; - - /* Make sure we see any spends using this key */ - txfilter_add_scriptpubkey(peer->ld->owned_txfilter, - take(p2wpkh_for_keyidx(NULL, peer->ld, - channel->final_key_idx))); - - return channel; -} - -const char *channel_state_name(const struct channel *channel) -{ - return channel_state_str(channel->state); -} - -const char *channel_state_str(enum channel_state state) -{ - for (size_t i = 0; enum_channel_state_names[i].name; i++) - if (enum_channel_state_names[i].v == state) - return enum_channel_state_names[i].name; - return "unknown"; -} - -struct channel *peer_any_active_channel(struct peer *peer, bool *others) -{ - struct channel *channel, *ret = NULL; - - list_for_each(&peer->channels, channel, list) { - if (!channel_active(channel)) - continue; - /* Already found one? */ - if (ret) { - if (others) - *others = true; - } else { - if (others) - *others = false; - ret = channel; - } - } - return ret; -} - -struct channel *peer_any_unsaved_channel(struct peer *peer, bool *others) -{ - struct channel *channel, *ret = NULL; - - list_for_each(&peer->channels, channel, list) { - if (!channel_unsaved(channel)) - continue; - /* Already found one? */ - if (ret) { - if (others) - *others = true; - } else { - if (others) - *others = false; - ret = channel; - } - } - return ret; -} - -struct channel_inflight *channel_inflight_find(struct channel *channel, - const struct bitcoin_txid *txid) -{ - struct channel_inflight *inflight; - list_for_each(&channel->inflights, inflight, list) { - if (bitcoin_txid_eq(txid, &inflight->funding->outpoint.txid)) - return inflight; - } - - return NULL; -} - -struct channel *any_channel_by_scid(struct lightningd *ld, - const struct short_channel_id *scid) -{ - struct peer *p; - struct channel *chan; - list_for_each(&ld->peers, p, list) { - list_for_each(&p->channels, chan, list) { - if (chan->scid - && short_channel_id_eq(scid, chan->scid)) - return chan; - } - } - return NULL; -} - -struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid) -{ - struct peer *p; - struct channel *chan; - list_for_each(&ld->peers, p, list) { - list_for_each(&p->channels, chan, list) { - if (chan->dbid == dbid) - return chan; - } - } - return NULL; -} - -struct channel *channel_by_cid(struct lightningd *ld, - const struct channel_id *cid) -{ - struct peer *p; - struct channel *channel; - - list_for_each(&ld->peers, p, list) { - if (p->uncommitted_channel) { - /* We can't use this method for old, uncommitted - * channels; there's no "channel" struct here! */ - if (channel_id_eq(&p->uncommitted_channel->cid, cid)) - return NULL; - } - list_for_each(&p->channels, channel, list) { - if (channel_id_eq(&channel->cid, cid)) { - return channel; - } - } - } - return NULL; -} - -struct channel *find_channel_by_id(const struct peer *peer, - const struct channel_id *cid) -{ - struct channel *c; - - list_for_each(&peer->channels, c, list) { - if (channel_id_eq(&c->cid, cid)) - return c; - } - return NULL; -} - -struct channel *find_channel_by_scid(const struct peer *peer, - const struct short_channel_id *scid) -{ - struct channel *c; - - list_for_each(&peer->channels, c, list) { - if (c->scid && short_channel_id_eq(c->scid, scid)) - return c; - } - return NULL; -} - -void channel_set_last_tx(struct channel *channel, - struct bitcoin_tx *tx, - const struct bitcoin_signature *sig, - enum wallet_tx_type txtypes) -{ - assert(tx->chainparams); - channel->last_sig = *sig; - tal_free(channel->last_tx); - channel->last_tx = tal_steal(channel, tx); - channel->last_tx_type = txtypes; -} - -void channel_set_state(struct channel *channel, - enum channel_state old_state, - enum channel_state state, - enum state_change reason, - char *why) -{ - struct timeabs timestamp; - - /* set closer, if known */ - if (state > CHANNELD_NORMAL && channel->closer == NUM_SIDES) { - if (reason == REASON_LOCAL) channel->closer = LOCAL; - if (reason == REASON_USER) channel->closer = LOCAL; - if (reason == REASON_REMOTE) channel->closer = REMOTE; - if (reason == REASON_ONCHAIN) channel->closer = REMOTE; - } - - /* use or update state_change_cause, if known */ - if (reason != REASON_UNKNOWN) - channel->state_change_cause = reason; - else - reason = channel->state_change_cause; - - log_info(channel->log, "State changed from %s to %s", - channel_state_name(channel), channel_state_str(state)); - if (channel->state != old_state) - fatal("channel state %s should be %s", - channel_state_name(channel), channel_state_str(old_state)); - - channel->state = state; - - /* TODO(cdecker) Selectively save updated fields to DB */ - wallet_channel_save(channel->peer->ld->wallet, channel); - - /* plugin notification channel_state_changed and DB entry */ - if (state != old_state) { /* see issue #4029 */ - timestamp = time_now(); - wallet_state_change_add(channel->peer->ld->wallet, - channel->dbid, - ×tamp, - old_state, - state, - reason, - why); - notify_channel_state_changed(channel->peer->ld, - &channel->peer->id, - &channel->cid, - channel->scid, - ×tamp, - old_state, - state, - reason, - why); - } -} - -const char *channel_change_state_reason_str(enum state_change reason) -{ - switch (reason) { - case REASON_UNKNOWN: return "unknown"; - case REASON_LOCAL: return "local"; - case REASON_USER: return "user"; - case REASON_REMOTE: return "remote"; - case REASON_PROTOCOL: return "protocol"; - case REASON_ONCHAIN: return "onchain"; - } - abort(); -} - -void channel_fail_permanent(struct channel *channel, - enum state_change reason, - const char *fmt, - ...) -{ - struct lightningd *ld = channel->peer->ld; - va_list ap; - char *why; - - va_start(ap, fmt); - why = tal_vfmt(tmpctx, fmt, ap); - va_end(ap); - - log_unusual(channel->log, "Peer permanent failure in %s: %s", - channel_state_name(channel), why); - - /* We can have multiple errors, eg. onchaind failures. */ - if (!channel->error) - channel->error = towire_errorfmt(channel, - &channel->cid, "%s", why); - - channel_set_owner(channel, NULL); - /* Drop non-cooperatively (unilateral) to chain. */ - drop_to_chain(ld, channel, false); - - if (channel_active(channel)) - channel_set_state(channel, - channel->state, - AWAITING_UNILATERAL, - reason, - why); - - tal_free(why); -} - -void channel_fail_forget(struct channel *channel, const char *fmt, ...) -{ - va_list ap; - char *why; - - assert(channel->opener == REMOTE && - channel->state == CHANNELD_AWAITING_LOCKIN); - va_start(ap, fmt); - why = tal_vfmt(tmpctx, fmt, ap); - va_end(ap); - - log_unusual(channel->log, "Peer permanent failure in %s: %s, " - "forget channel", - channel_state_name(channel), why); - - if (!channel->error) - channel->error = towire_errorfmt(channel, - &channel->cid, "%s", why); - - delete_channel(channel); - tal_free(why); -} - -struct channel_inflight * -channel_current_inflight(const struct channel *channel) -{ - /* The last inflight should always be the one in progress */ - return list_tail(&channel->inflights, - struct channel_inflight, list); -} - -u32 channel_last_funding_feerate(const struct channel *channel) -{ - struct channel_inflight *inflight; - inflight = channel_current_inflight(channel); - if (!inflight) - return 0; - return inflight->funding->feerate; -} - -void channel_cleanup_commands(struct channel *channel, const char *why) -{ - if (channel->open_attempt) { - struct open_attempt *oa = channel->open_attempt; - if (oa->cmd) { - /* If we requested this be aborted, it's a success */ - if (oa->aborted) { - struct json_stream *response; - response = json_stream_success(oa->cmd); - json_add_channel_id(response, - "channel_id", - &channel->cid); - json_add_bool(response, "channel_canceled", - list_empty(&channel->inflights)); - json_add_string(response, "reason", why); - was_pending(command_success(oa->cmd, response)); - } else - was_pending(command_fail(oa->cmd, LIGHTNINGD, - "%s", why)); - } - notify_channel_open_failed(channel->peer->ld, &channel->cid); - channel->open_attempt = tal_free(channel->open_attempt); - } - - if (channel->openchannel_signed_cmd) { - was_pending(command_fail(channel->openchannel_signed_cmd, - LIGHTNINGD, "%s", why)); - channel->openchannel_signed_cmd = NULL; - } -} - -void channel_internal_error(struct channel *channel, const char *fmt, ...) -{ - va_list ap; - char *why; - - va_start(ap, fmt); - why = tal_vfmt(channel, fmt, ap); - va_end(ap); - - log_broken(channel->log, "Internal error %s: %s", - channel_state_name(channel), why); - - channel_cleanup_commands(channel, why); - - if (channel_unsaved(channel)) { - channel_set_owner(channel, NULL); - delete_channel(channel); - tal_free(why); - return; - } - - /* Don't expose internal error causes to remove unless doing dev */ -#if DEVELOPER - channel_fail_permanent(channel, REASON_LOCAL, "Internal error: %s", why); -#else - channel_fail_permanent(channel, REASON_LOCAL, "Internal error"); -#endif - tal_free(why); -} - -void channel_set_billboard(struct channel *channel, bool perm, const char *str) -{ - const char **p; - - if (perm) - p = &channel->billboard.permanent[channel->state]; - else - p = &channel->billboard.transient; - *p = tal_free(*p); - - if (str) { - *p = tal_fmt(channel, "%s:%s", channel_state_name(channel), str); - if (taken(str)) - tal_free(str); - } -} - -static void err_and_reconnect(struct channel *channel, - const char *why, - u32 seconds_before_reconnect) -{ - log_info(channel->log, "Peer transient failure in %s: %s", - channel_state_name(channel), why); - -#if DEVELOPER - if (dev_disconnect_permanent(channel->peer->ld)) { - channel_fail_permanent(channel, - REASON_LOCAL, - "dev_disconnect permfail"); - return; - } -#endif - - channel_set_owner(channel, NULL); - - /* Their address only useful if we connected to them */ - try_reconnect(channel, channel->peer, seconds_before_reconnect, - channel->peer->connected_incoming - ? NULL - : &channel->peer->addr); -} - -void channel_fail_reconnect_later(struct channel *channel, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_and_reconnect(channel, tal_vfmt(tmpctx, fmt, ap), 60); - va_end(ap); -} - -void channel_fail_reconnect(struct channel *channel, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_and_reconnect(channel, tal_vfmt(tmpctx, fmt, ap), 1); - va_end(ap); -} diff --git a/lightningd/eltoo_channel.h b/lightningd/eltoo_channel.h deleted file mode 100644 index db81ce8c484c..000000000000 --- a/lightningd/eltoo_channel.h +++ /dev/null @@ -1,481 +0,0 @@ -#ifndef LIGHTNING_LIGHTNINGD_CHANNEL_H -#define LIGHTNING_LIGHTNINGD_CHANNEL_H -#include "config.h" -#include -#include -#include -#include -#include -#include - -struct channel_id; -struct uncommitted_channel; -struct wally_psbt; - -struct billboard { - /* Status information to display on listpeers */ - const char *permanent[CHANNEL_STATE_MAX+1]; - const char *transient; -}; - -struct funding_info { - struct bitcoin_outpoint outpoint; - u32 feerate; - struct amount_sat total_funds; - - /* Our original funds, in funding amount */ - struct amount_sat our_funds; -}; - -struct channel_inflight { - /* Inside channel->inflights. */ - struct list_node list; - - /* Channel context */ - struct channel *channel; - - /* Funding info */ - const struct funding_info *funding; - struct wally_psbt *funding_psbt; - bool remote_tx_sigs; - bool tx_broadcast; - - /* Commitment tx and sigs */ - struct bitcoin_tx *last_tx; - struct bitcoin_signature last_sig; - - /* Channel lease infos */ - u32 lease_expiry; - secp256k1_ecdsa_signature *lease_commit_sig; - u32 lease_chan_max_msat; - u16 lease_chan_max_ppt; - u32 lease_blockheight_start; - - /* We save this data so we can do nice accounting; - * on the channel we slot it into the 'push' field */ - struct amount_msat lease_fee; -}; - -struct open_attempt { - /* on uncommitted_channel struct */ - struct channel *channel; - struct channel_config our_config; - enum tx_role role; - bool aborted; - - /* On funding_channel struct */ - struct command *cmd; - struct amount_sat funding; - const u8 *our_upfront_shutdown_script; - - /* First msg to send to dualopend (to make it create channel) */ - const u8 *open_msg; -}; - -struct channel { - /* Inside peer->channels. */ - struct list_node list; - - /* Peer context */ - struct peer *peer; - - /* Inflight channel opens */ - struct list_head inflights; - - /* Open attempt */ - struct open_attempt *open_attempt; - - /* Database ID: 0 == not in db yet */ - u64 dbid; - - /* Populated by new_unsaved_channel */ - u64 unsaved_dbid; - - /* Error message (iff in error state) */ - u8 *error; - - /* Their shachain. */ - struct wallet_shachain their_shachain; - - /* What's happening. */ - enum channel_state state; - - /* Which side offered channel? */ - enum side opener; - - /* Is there a single subdaemon responsible for us? */ - struct subd *owner; - - /* History */ - struct log *log; - struct billboard billboard; - - /* Channel flags from opening message. */ - u8 channel_flags; - - /* Our channel config. */ - struct channel_config our_config; - - /* Minimum funding depth (specified by us if they fund). */ - u32 minimum_depth; - - /* Tracking commitment transaction numbers. */ - u64 next_index[NUM_SIDES]; - u64 next_htlc_id; - - /* Funding outpoint and amount */ - struct bitcoin_outpoint funding; - struct amount_sat funding_sats; - - /* Our original funds, in funding amount */ - struct amount_sat our_funds; - - struct amount_msat push; - bool remote_funding_locked; - /* Channel if locked locally. */ - struct short_channel_id *scid; - - struct channel_id cid; - - /* Amount going to us, not counting unfinished HTLCs; if we have one. */ - struct amount_msat our_msat; - /* Statistics for min and max our_msatoshi. */ - struct amount_msat msat_to_us_min; - struct amount_msat msat_to_us_max; - - /* Last tx they gave us. */ - struct bitcoin_tx *last_tx; - enum wallet_tx_type last_tx_type; - struct bitcoin_signature last_sig; - const struct bitcoin_signature *last_htlc_sigs; - - /* Keys for channel */ - struct channel_info channel_info; - - /* Fee status */ - const struct fee_states *fee_states; - - /* Height states (option_will_fund, update_blockheight) */ - const struct height_states *blockheight_states; - - /* Our local basepoints */ - struct basepoints local_basepoints; - - /* Our funding tx pubkey. */ - struct pubkey local_funding_pubkey; - - /* scriptpubkey for shutdown, if applicable. */ - const u8 *shutdown_scriptpubkey[NUM_SIDES]; - /* Address for any final outputs */ - u64 final_key_idx; - - /* Amount to give up on each step of the closing fee negotiation. */ - u64 closing_fee_negotiation_step; - - /* Whether closing_fee_negotiation_step is in satoshi or %. */ - u8 closing_fee_negotiation_step_unit; - - /* optional wrong_funding for mutual close */ - const struct bitcoin_outpoint *shutdown_wrong_funding; - - /* optional feerate min/max for mutual close */ - u32 *closing_feerate_range; - - /* Reestablishment stuff: last sent commit and revocation details. */ - bool last_was_revoke; - struct changed_htlc *last_sent_commit; - - /* Blockheight at creation, scans for funding confirmations - * will start here */ - u32 first_blocknum; - - /* Feerate range */ - u32 min_possible_feerate, max_possible_feerate; - - /* Does gossipd need to know if the owner dies? (ie. not onchaind) */ - bool connected; - - /* Do we have an "impossible" future per_commitment_point from - * peer via option_data_loss_protect? */ - const struct pubkey *future_per_commitment_point; - - /* Min/max htlc amount allowed in channel. */ - struct amount_msat htlc_minimum_msat, htlc_maximum_msat; - - /* Feerate per channel */ - u32 feerate_base, feerate_ppm; - - /* But allow these feerates/htlcs up until this time. */ - struct timeabs old_feerate_timeout; - u32 old_feerate_base, old_feerate_ppm; - struct amount_msat old_htlc_minimum_msat, old_htlc_maximum_msat; - - /* If they used option_upfront_shutdown_script. */ - const u8 *remote_upfront_shutdown_script; - - /* At what commit numbers does `option_static_remotekey` apply? */ - u64 static_remotekey_start[NUM_SIDES]; - - /* What features apply to this channel? */ - const struct channel_type *type; - - /* Any commands trying to forget us. */ - struct command **forgets; - - /* Our position in the round-robin list. */ - u64 rr_number; - - /* the one that initiated a bilateral close, NUM_SIDES if unknown. */ - enum side closer; - - /* Last known state_change cause */ - enum state_change state_change_cause; - - /* Outstanding command for this channel, v2 only */ - struct command *openchannel_signed_cmd; - - /* Block lease expires at, zero is no lease */ - u32 lease_expiry; - - /* Lease commitment, useful someone breaks their promise - * wrt channel fees */ - secp256k1_ecdsa_signature *lease_commit_sig; - - /* Lease commited maximum channel fee base msat */ - u32 lease_chan_max_msat; - /* Lease commited max part per thousandth channel fee (ppm * 1000) */ - u16 lease_chan_max_ppt; - - /* Latest channel_update, for use in error messages. */ - u8 *channel_update; -}; - -/* For v2 opens, a channel that has not yet been committed/saved to disk */ -struct channel *new_unsaved_channel(struct peer *peer, - u32 feerate_base, - u32 feerate_ppm); - -struct open_attempt *new_channel_open_attempt(struct channel *channel); - -struct channel *new_channel(struct peer *peer, u64 dbid, - /* NULL or stolen */ - struct wallet_shachain *their_shachain STEALS, - enum channel_state state, - enum side opener, - /* NULL or stolen */ - struct log *log STEALS, - const char *transient_billboard TAKES, - u8 channel_flags, - const struct channel_config *our_config, - u32 minimum_depth, - u64 next_index_local, - u64 next_index_remote, - u64 next_htlc_id, - const struct bitcoin_outpoint *funding, - struct amount_sat funding_sats, - struct amount_msat push, - struct amount_sat our_funds, - bool remote_funding_locked, - /* NULL or stolen */ - struct short_channel_id *scid STEALS, - struct channel_id *cid, - struct amount_msat our_msatoshi, - struct amount_msat msatoshi_to_us_min, - struct amount_msat msatoshi_to_us_max, - struct bitcoin_tx *last_tx STEALS, - const struct bitcoin_signature *last_sig, - /* NULL or stolen */ - const struct bitcoin_signature *last_htlc_sigs STEALS, - const struct channel_info *channel_info, - const struct fee_states *fee_states TAKES, - /* NULL or stolen */ - u8 *remote_shutdown_scriptpubkey STEALS, - const u8 *local_shutdown_scriptpubkey, - u64 final_key_idx, - bool last_was_revoke, - /* NULL or stolen */ - struct changed_htlc *last_sent_commit STEALS, - u32 first_blocknum, - u32 min_possible_feerate, - u32 max_possible_feerate, - bool connected, - const struct basepoints *local_basepoints, - const struct pubkey *local_funding_pubkey, - const struct pubkey *future_per_commitment_point, - u32 feerate_base, - u32 feerate_ppm, - /* NULL or stolen */ - const u8 *remote_upfront_shutdown_script STEALS, - u64 local_static_remotekey_start, - u64 remote_static_remotekey_start, - const struct channel_type *type STEALS, - enum side closer, - enum state_change reason, - /* NULL or stolen */ - const struct bitcoin_outpoint *shutdown_wrong_funding STEALS, - const struct height_states *height_states TAKES, - u32 lease_expiry, - secp256k1_ecdsa_signature *lease_commit_sig STEALS, - u32 lease_chan_max_msat, - u16 lease_chan_max_ppt, - struct amount_msat htlc_minimum_msat, - struct amount_msat htlc_maximum_msat); - -/* new_inflight - Create a new channel_inflight for a channel */ -struct channel_inflight * -new_inflight(struct channel *channel, - const struct bitcoin_outpoint *funding_outpoint, - u32 funding_feerate, - struct amount_sat funding_sat, - struct amount_sat our_funds, - struct wally_psbt *funding_psbt STEALS, - struct bitcoin_tx *last_tx STEALS, - const struct bitcoin_signature last_sig, - const u32 lease_expiry, - const secp256k1_ecdsa_signature *lease_commit_sig, - const u32 lease_chan_max_msat, - const u16 lease_chan_max_ppt, - const u32 lease_blockheight_start, - const struct amount_msat lease_fee); - -/* Given a txid, find an inflight channel stub. Returns NULL if none found */ -struct channel_inflight *channel_inflight_find(struct channel *channel, - const struct bitcoin_txid *txid); - -/* What's the most recent inflight for this channel? */ -struct channel_inflight * -channel_current_inflight(const struct channel *channel); - -/* What's the last feerate used for a funding tx on this channel? */ -u32 channel_last_funding_feerate(const struct channel *channel); - -void delete_channel(struct channel *channel STEALS); - -const char *channel_state_name(const struct channel *channel); -const char *channel_state_str(enum channel_state state); - -void channel_set_owner(struct channel *channel, struct subd *owner); - -/* Channel has failed, but can try again. */ -void channel_fail_reconnect(struct channel *channel, - const char *fmt, ...) PRINTF_FMT(2,3); -/* Channel has failed, but can try again after a minute. */ -void channel_fail_reconnect_later(struct channel *channel, - const char *fmt,...) PRINTF_FMT(2,3); - -/* Channel has failed, give up on it. */ -void channel_fail_permanent(struct channel *channel, - enum state_change reason, - const char *fmt, - ...); -/* Forget the channel. This is only used for the case when we "receive" error - * during CHANNELD_AWAITING_LOCKIN if we are "fundee". */ -void channel_fail_forget(struct channel *channel, const char *fmt, ...); -/* Permanent error, but due to internal problems, not peer. */ -void channel_internal_error(struct channel *channel, const char *fmt, ...); - -/* Clean up any in-progress commands for a channel */ -void channel_cleanup_commands(struct channel *channel, const char *why); - -void channel_set_state(struct channel *channel, - enum channel_state old_state, - enum channel_state state, - enum state_change reason, - char *why); - -const char *channel_change_state_reason_str(enum state_change reason); - -/* Find a channel which is not onchain, if any: sets *others if there - * is more than one. */ -struct channel *peer_any_active_channel(struct peer *peer, bool *others); - -/* Find a channel which is not yet saved to disk */ -struct channel *peer_any_unsaved_channel(struct peer *peer, bool *others); - -struct channel *channel_by_dbid(struct lightningd *ld, const u64 dbid); - -struct channel *any_channel_by_scid(struct lightningd *ld, - const struct short_channel_id *scid); - -/* Get channel by channel_id */ -struct channel *channel_by_cid(struct lightningd *ld, - const struct channel_id *cid); - -/* Find this channel within peer */ -struct channel *find_channel_by_id(const struct peer *peer, - const struct channel_id *cid); - -/* Find this channel within peer */ -struct channel *find_channel_by_scid(const struct peer *peer, - const struct short_channel_id *scid); - -void channel_set_last_tx(struct channel *channel, - struct bitcoin_tx *tx, - const struct bitcoin_signature *sig, - enum wallet_tx_type type); - -static inline bool channel_can_add_htlc(const struct channel *channel) -{ - return channel->state == CHANNELD_NORMAL; -} - -static inline bool channel_fees_can_change(const struct channel *channel) -{ - return channel->state == CHANNELD_NORMAL - || channel->state == CHANNELD_SHUTTING_DOWN; -} - -static inline bool channel_state_on_chain(enum channel_state state) -{ - return state == ONCHAIN; -} - -static inline bool channel_on_chain(const struct channel *channel) -{ - return channel_state_on_chain(channel->state); -} - -static inline bool channel_unsaved(const struct channel *channel) -{ - return channel->state == DUALOPEND_OPEN_INIT - && channel->dbid == 0; -} - -static inline bool channel_active(const struct channel *channel) -{ - return channel->state != FUNDING_SPEND_SEEN - && channel->state != CLOSINGD_COMPLETE - && !channel_unsaved(channel) - && !channel_on_chain(channel); -} - -static inline bool channel_closed(const struct channel *channel) -{ - return channel->state == CLOSINGD_COMPLETE - || channel->state == AWAITING_UNILATERAL - || channel->state == FUNDING_SPEND_SEEN - || channel->state == ONCHAIN - || channel->state == CLOSED; -} - -static inline bool channel_has(const struct channel *channel, int f) -{ - return channel_type_has(channel->type, f); -} - -void get_channel_basepoints(struct lightningd *ld, - const struct node_id *peer_id, - const u64 dbid, - struct basepoints *local_basepoints, - struct pubkey *local_funding_pubkey); - -void channel_set_billboard(struct channel *channel, bool perm, - const char *str TAKES); - -struct htlc_in *channel_has_htlc_in(struct channel *channel); -struct htlc_out *channel_has_htlc_out(struct channel *channel); - -const u8 *get_channel_update(struct channel *channel); - -struct amount_msat htlc_max_possible_send(const struct channel *channel); -#endif /* LIGHTNING_LIGHTNINGD_CHANNEL_H */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 42d2f7fa769e..53b4fcc90cd1 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -16,6 +16,7 @@ #include #include #include +#include // channel #include #include #include @@ -93,7 +94,7 @@ struct eltoo_state { /* The channel structure, as defined in common/initial_channel.h. While * the structure has room for HTLCs, those routines are channeld-specific * as initial channels never have HTLCs. */ - struct eltoo_channel *channel; + struct channel *channel; /* Channel type we agreed on (even before channel populated) */ struct channel_type *channel_type; @@ -444,7 +445,6 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, u8 *msg; struct channel_id id_in; struct channel_id cid; - char *err_reason; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct bitcoin_tx *settle_tx; struct partial_sig our_update_psig, their_update_psig; @@ -513,18 +513,18 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * transaction. */ settle_tx = initial_settle_channel_tx(tmpctx, state->channel, - direct_outputs, &err_reason); + direct_outputs); if (!settle_tx) { negotiation_failed(state, - "Could not make settle tx: %s", err_reason); + "Could not make settle tx???"); return false; } - *update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel, &err_reason); + *update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel); if (!*update_tx) { negotiation_failed(state, - "Could not make update tx: %s", err_reason); + "Could not make update tx???"); return false; } @@ -816,12 +816,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->localconf, &err_reason)) { negotiation_failed(state, "%s", err_reason); - return NULL; - } - - /* If they give us a reason to reject, do so. */ - if (err_reason) { - negotiation_failed(state, "%s", err_reason); tal_free(err_reason); return NULL; } @@ -950,19 +944,19 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) * `error` and fail the channel. */ settle_tx = initial_settle_channel_tx(tmpctx, state->channel, - direct_outputs, &err_reason); + direct_outputs); /* This shouldn't happen either, AFAICT. */ if (!settle_tx) { negotiation_failed(state, - "Failed to make settle tx: %s", err_reason); + "Failed to make settle tx???"); return NULL; } - update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel, &err_reason); + update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel); /* Nor this */ if (!update_tx) { negotiation_failed(state, - "Failed to make update tx: %s", err_reason); + "Failed to make update tx???"); return NULL; } From b76ca54dd534a38c03e7b465c17df02236817f10 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 29 Aug 2022 10:45:25 -0400 Subject: [PATCH 139/283] eltoo_channeld compiling --- channeld/Makefile | 1 + channeld/channeld_wire.csv | 4 +-- channeld/eltoo_channeld.c | 59 ++++++++++++++--------------------- channeld/test/run-settle_tx.c | 2 -- 4 files changed, 26 insertions(+), 40 deletions(-) diff --git a/channeld/Makefile b/channeld/Makefile index 250724f2cb62..510abed7d3b6 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -80,6 +80,7 @@ CHANNELD_COMMON_OBJS := \ common/htlc_tx.o \ common/htlc_wire.o \ common/initial_channel.o \ + common/initial_eltoo_channel.o \ common/initial_commit_tx.o \ common/initial_settlement_tx.o \ common/keyset.o \ diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index bc664918efe1..fd023132d4d6 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -288,12 +288,11 @@ msgdata,channeld_init_eltoo,funding_satoshi,amount_sat, msgdata,channeld_init_eltoo,minimum_depth,u32, msgdata,channeld_init_eltoo,our_config,channel_config, msgdata,channeld_init_eltoo,their_config,channel_config, -msgdata,channeld_init_eltoo,feerate_min,u32, -msgdata,channeld_init_eltoo,feerate_max,u32, msgdata,channeld_init_eltoo,their_update_psig,partial_sig, msgdata,channeld_init_eltoo,our_update_psig,partial_sig, msgdata,channeld_init_eltoo,session,musig_session, msgdata,channeld_init_eltoo,their_funding_pubkey,pubkey, +msgdata,channeld_init_eltoo,their_settle_pubkey,pubkey, msgdata,channeld_init_eltoo,opener,enum side, msgdata,channeld_init_eltoo,fee_base,u32, msgdata,channeld_init_eltoo,fee_proportional,u32, @@ -301,6 +300,7 @@ msgdata,channeld_init_eltoo,htlc_minimum_msat,amount_msat, msgdata,channeld_init_eltoo,htlc_maximum_msat,amount_msat, msgdata,channeld_init_eltoo,local_msatoshi,amount_msat, msgdata,channeld_init_eltoo,our_funding_pubkey,pubkey, +msgdata,channeld_init_eltoo,our_settle_pubkey,pubkey, msgdata,channeld_init_eltoo,local_node_id,node_id, msgdata,channeld_init_eltoo,remote_node_id,node_id, msgdata,channeld_init_eltoo,commit_msec,u32, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index a5eb44e6c65d..4000f5b261da 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -62,9 +62,6 @@ struct eltoo_peer { /* Features we support. */ struct feature_set *our_features; - /* Tolerable amounts for feerate (only relevant for fundee). */ - u32 feerate_min, feerate_max; - /* BOLT #2: * * A sending node: @@ -681,9 +678,7 @@ static bool shutdown_complete(const struct eltoo_peer *peer) return peer->shutdown_sent[LOCAL] && peer->shutdown_sent[REMOTE] && num_channel_htlcs(peer->channel) == 0 - /* We could be awaiting revoke-and-ack for a feechange */ && peer->updates_received == peer->next_index - 1; - } /* BOLT #2: @@ -1374,10 +1369,6 @@ static void handle_unexpected_reestablish(struct eltoo_peer *peer, const u8 *msg u64 last_update_number; struct partial_sig their_last_psig; struct nonce their_next_nonce; -#if EXPERIMENTAL_FEATURES - struct tlv_channel_reestablish_tlvs *tlvs; -#endif - /* No reestablish tlvs for now */ if (!fromwire_channel_reestablish_eltoo @@ -1463,7 +1454,7 @@ static void peer_in(struct eltoo_peer *peer, const u8 *msg) /* FIXME How should we handle illegal messages in general? */ return; case WIRE_UPDATE_FEE: - handle_peer_feechange(peer, msg); + /* FIXME How should we handle illegal messages in general? */ return; case WIRE_UPDATE_SIGNED: handle_peer_update_sig(peer, msg); @@ -1543,9 +1534,6 @@ static void peer_in(struct eltoo_peer *peer, const u8 *msg) case WIRE_ACCEPT_CHANNEL_ELTOO: case WIRE_FUNDING_CREATED_ELTOO: case WIRE_FUNDING_SIGNED_ELTOO: - case WIRE_UPDATE_SIGNED: - case WIRE_UPDATE_SIGNED_ACK: - case WIRE_CHANNEL_REESTABLISH_ELTOO: case WIRE_SHUTDOWN_ELTOO: case WIRE_CLOSING_SIGNED_ELTOO: /* Eltoo stuff ends */ @@ -1617,14 +1605,11 @@ static void handle_funding_depth(struct eltoo_peer *peer, const u8 *msg) peer->short_channel_ids[LOCAL] = *scid; if (!peer->funding_locked[LOCAL]) { - status_debug("funding_locked: sending commit index" - " %"PRIu64": %s", - peer->next_index, - type_to_string(tmpctx, struct pubkey, - &peer->next_local_per_commit)); - msg = towire_funding_locked(NULL, - &peer->channel_id, - &peer->next_local_per_commit); + status_debug("funding_locked_eltoo" + " %"PRIu64"", + peer->next_index); + msg = towire_funding_locked_eltoo(NULL, + &peer->channel_id); peer_write(peer->pps, take(msg)); peer->funding_locked[LOCAL] = true; @@ -1658,7 +1643,6 @@ static void handle_offer_htlc(struct eltoo_peer *peer, const u8 *inmsg) enum channel_add_err e; const u8 *failwiremsg; const char *failstr; - struct amount_sat htlc_fee; struct pubkey *blinding; if (!peer->funding_locked[LOCAL] || !peer->funding_locked[REMOTE]) @@ -1679,10 +1663,10 @@ static void handle_offer_htlc(struct eltoo_peer *peer, const u8 *inmsg) tlvs = NULL; #endif - e = channel_add_htlc(peer->channel, LOCAL, peer->htlc_id, + e = eltoo_channel_add_htlc(peer->channel, LOCAL, peer->htlc_id, amount, cltv_expiry, &payment_hash, onion_routing_packet, take(blinding), NULL, - &htlc_fee, true); + true); status_debug("Adding HTLC %"PRIu64" amount=%s cltv=%u gave %s", peer->htlc_id, type_to_string(tmpctx, struct amount_msat, &amount), @@ -1724,7 +1708,7 @@ static void handle_offer_htlc(struct eltoo_peer *peer, const u8 *inmsg) /* FIXME: Fuzz the boundaries a bit to avoid probing? */ case CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED: failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); - failstr = tal_fmt(inmsg, "Capacity exceeded - HTLC fee: %s", fmt_amount_sat(inmsg, htlc_fee)); + failstr = tal_fmt(inmsg, "Capacity exceeded"); goto failed; case CHANNEL_ERR_HTLC_BELOW_MINIMUM: failwiremsg = towire_amount_below_minimum(inmsg, amount, get_cupdate(peer)); @@ -2047,6 +2031,10 @@ static void init_channel(struct eltoo_peer *peer) struct amount_sat funding_sats; struct amount_msat local_msat; struct pubkey funding_pubkey[NUM_SIDES]; + struct pubkey settle_pubkey[NUM_SIDES]; + /* FIXME thread these musig things through to channel creation */ + struct partial_sig self_psig, other_psig; + struct musig_session session; struct channel_config conf[NUM_SIDES]; struct bitcoin_outpoint funding; enum side opener; @@ -2078,12 +2066,11 @@ static void init_channel(struct eltoo_peer *peer) &funding_sats, &minimum_depth, &conf[LOCAL], &conf[REMOTE], - &peer->feerate_min, - &peer->feerate_max, - &peer->channel->eltoo_keyset.other_update_psig, - &peer->channel->eltoo_keyset.self_update_psig, - &peer->channel->eltoo_keyset.session, + &other_psig, + &self_psig, + &session, &funding_pubkey[REMOTE], + &settle_pubkey[REMOTE], &opener, &peer->fee_base, &peer->fee_per_satoshi, @@ -2091,6 +2078,7 @@ static void init_channel(struct eltoo_peer *peer) &peer->htlc_maximum_msat, &local_msat, &funding_pubkey[LOCAL], + &settle_pubkey[LOCAL], &peer->node_ids[LOCAL], &peer->node_ids[REMOTE], &peer->commit_msec, @@ -2138,13 +2126,10 @@ static void init_channel(struct eltoo_peer *peer) status_debug("init %s: " " next_idx = %"PRIu64 - " updates_received = %"PRIu64 - " feerates %s range %u-%u", + " updates_received = %"PRIu64, side_to_str(opener), - peer->next_index, peer->next_index, - peer->updates_received, - type_to_string(tmpctx, struct fee_states, fee_states), - peer->feerate_min, peer->feerate_max); + peer->next_index, + peer->updates_received); if (remote_ann_node_sig && remote_ann_bitcoin_sig) { peer->announcement_node_sigs[REMOTE] = *remote_ann_node_sig; @@ -2172,6 +2157,8 @@ static void init_channel(struct eltoo_peer *peer) &conf[LOCAL], &conf[REMOTE], &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], + &settle_pubkey[LOCAL], + &settle_pubkey[REMOTE], take(channel_type), feature_offered(peer->their_features, OPT_LARGE_CHANNELS), diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index cbc82ea746a6..17231344363c 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -501,7 +501,6 @@ static int test_invalid_update_tx(void) struct amount_msat other_pay; u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ - char* err_reason; struct bitcoin_tx *tx, *tx_cmp, *update_tx, *settle_tx_1, *update_tx_1_A; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; @@ -670,7 +669,6 @@ static int test_initial_settlement_tx(void) struct amount_msat other_pay; u32 obscured_update_number; /* struct wally_tx_output direct_outputs[NUM_SIDES]; Can't figure out how it's used */ - char* err_reason; struct bitcoin_tx *tx, *tx_cmp, *update_tx; struct privkey alice_funding_privkey, bob_funding_privkey, alice_settle_privkey, bob_settle_privkey; int ok; From 6add5a10df0dff2e9a25bab5ff23b6ba7fa0a5b2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 29 Aug 2022 11:35:46 -0400 Subject: [PATCH 140/283] Thread through some more reestablishment state --- channeld/eltoo_channeld.c | 10 ++++++---- channeld/eltoo_full_channel.c | 6 ++++++ channeld/eltoo_full_channel.h | 6 ++++++ common/initial_eltoo_channel.c | 8 ++++++++ common/initial_eltoo_channel.h | 6 ++++++ openingd/eltoo_openingd.c | 16 +++++++++++++++- 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 4000f5b261da..01774597cd23 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -2032,8 +2032,7 @@ static void init_channel(struct eltoo_peer *peer) struct amount_msat local_msat; struct pubkey funding_pubkey[NUM_SIDES]; struct pubkey settle_pubkey[NUM_SIDES]; - /* FIXME thread these musig things through to channel creation */ - struct partial_sig self_psig, other_psig; + struct partial_sig psigs[NUM_SIDES]; struct musig_session session; struct channel_config conf[NUM_SIDES]; struct bitcoin_outpoint funding; @@ -2066,8 +2065,8 @@ static void init_channel(struct eltoo_peer *peer) &funding_sats, &minimum_depth, &conf[LOCAL], &conf[REMOTE], - &other_psig, - &self_psig, + &psigs[REMOTE], + &psigs[LOCAL], &session, &funding_pubkey[REMOTE], &settle_pubkey[REMOTE], @@ -2159,6 +2158,9 @@ static void init_channel(struct eltoo_peer *peer) &funding_pubkey[REMOTE], &settle_pubkey[LOCAL], &settle_pubkey[REMOTE], + &psigs[LOCAL], + &psigs[REMOTE], + &session, take(channel_type), feature_offered(peer->their_features, OPT_LARGE_CHANNELS), diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 75730cc1b8c0..5962cd5b85bc 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -95,6 +95,9 @@ struct channel *new_full_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, + const struct partial_sig *self_psig, + const struct partial_sig *other_psig, + const struct musig_session *session, const struct channel_type *type TAKES, bool option_wumbo, enum side opener) @@ -110,6 +113,9 @@ struct channel *new_full_eltoo_channel(const tal_t *ctx, remote_funding_pubkey, local_settle_pubkey, remote_settle_pubkey, + self_psig, + other_psig, + session, type, option_wumbo, opener); diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h index 05ca1c11950b..b666dbc145fd 100644 --- a/channeld/eltoo_full_channel.h +++ b/channeld/eltoo_full_channel.h @@ -24,6 +24,9 @@ struct existing_htlc; * @remote_fundingkey: remote funding key * @local_settle_pubkey: local settlement key * @remote_settle_pubkey: remote settlement key + * @self_psig: local partial signature for reestablishment only + * @other_psig: remote partial signature for reestablishment only + * @session: musig session for reestablishment only * @type: type for this channel * @option_wumbo: large channel negotiated. * @opener: which side initiated it. @@ -42,6 +45,9 @@ struct channel *new_full_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, + const struct partial_sig *self_psig, + const struct partial_sig *other_psig, + const struct musig_session *session, const struct channel_type *type TAKES, bool option_wumbo, enum side opener); diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index d65972acff77..070fdadcf3ef 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -24,6 +24,9 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, + const struct partial_sig *self_psig, + const struct partial_sig *other_psig, + const struct musig_session *session, const struct channel_type *type TAKES, bool option_wumbo, enum side opener) @@ -48,6 +51,11 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, channel->eltoo_keyset.other_funding_key = *remote_funding_pubkey; channel->eltoo_keyset.self_settle_key = *local_settle_pubkey; channel->eltoo_keyset.other_settle_key = *remote_settle_pubkey; + channel->eltoo_keyset.other_settle_key = *remote_settle_pubkey; + channel->eltoo_keyset.self_psig = *self_psig; + channel->eltoo_keyset.other_psig = *other_psig; + channel->eltoo_keyset.session = *session; + channel->htlcs = NULL; pubkey_ptrs[0] = local_funding_pubkey; diff --git a/common/initial_eltoo_channel.h b/common/initial_eltoo_channel.h index bf36411618b4..61fda747f72d 100644 --- a/common/initial_eltoo_channel.h +++ b/common/initial_eltoo_channel.h @@ -30,6 +30,9 @@ struct fulfilled_htlc; * @remote_funding_pubkey: remote funding key * @local_settle_pubkey: local settlement key * @remote_settle_key: remote settlement key + * @self_psig: local partial signature for reestablishment only + * @other_psig: remote partial signature for reestablishment only + * @session: musig session for reestablishment only * @type: type for this channel * @option_wumbo: has peer currently negotiated wumbo? * @opener: which side initiated it. @@ -48,6 +51,9 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, + const struct partial_sig *self_psig, + const struct partial_sig *other_psig, + const struct musig_session *session, const struct channel_type *type TAKES, bool option_wumbo, enum side opener); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 53b4fcc90cd1..ff511a414c9a 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -449,6 +449,10 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, struct bitcoin_tx *settle_tx; struct partial_sig our_update_psig, their_update_psig; + /* Dummy fields since they're unused at time of channel creation */ + struct partial_sig dummy_self_psig, dummy_other_psig; + struct musig_session dummy_session; + /*~ Channel is ready; Report the channel parameters to the signer. */ msg = towire_hsmd_ready_eltoo_channel(NULL, /* is_outbound */ true, @@ -471,7 +475,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /*~ Now we can initialize the `struct channel`. This represents * the current channel state and is how we can generate the current - * commitment transaction. + * update and settlement transactions. * * The routines to support `struct channel` are split into a common * part (common/initial_channel) which doesn't support HTLCs and is @@ -491,6 +495,9 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->their_funding_pubkey, &state->our_settlement_pubkey, &state->their_settlement_pubkey, + &dummy_self_psig, + &dummy_other_psig, + &dummy_session, state->channel_type, feature_offered(state->their_features, OPT_LARGE_CHANNELS), @@ -707,6 +714,10 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct wally_tx_output *direct_outputs[NUM_SIDES]; struct partial_sig our_update_psig, their_update_psig; + /* Dummy fields since they're unused at time of channel creation */ + struct partial_sig dummy_self_psig, dummy_other_psig; + struct musig_session dummy_session; + /* BOLT #2: * * The receiving node MUST fail the channel if: @@ -925,6 +936,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->their_funding_pubkey, &state->our_settlement_pubkey, &state->their_settlement_pubkey, + &dummy_self_psig, + &dummy_other_psig, + &dummy_session, state->channel_type, feature_offered(state->their_features, OPT_LARGE_CHANNELS), From f17d1a2e49e83250b303e4387a6f833c9c3e964d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 31 Aug 2022 16:34:05 -0400 Subject: [PATCH 141/283] fixup extra shared_delay serialization --- common/channel_config.c | 1 - 1 file changed, 1 deletion(-) diff --git a/common/channel_config.c b/common/channel_config.c index 9332ec216973..9a7cd56a4dfa 100644 --- a/common/channel_config.c +++ b/common/channel_config.c @@ -13,7 +13,6 @@ void towire_channel_config(u8 **pptr, const struct channel_config *config) towire_u16(pptr, config->to_self_delay); towire_u16(pptr, config->max_accepted_htlcs); towire_amount_msat(pptr, config->max_dust_htlc_exposure_msat); - towire_u16(pptr, config->shared_delay); } else { towire_amount_sat(pptr, config->dust_limit); towire_amount_msat(pptr, config->max_htlc_value_in_flight); From dede6b7c7686e1c5be521ce46270ce33632165d2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 1 Sep 2022 11:37:26 -0400 Subject: [PATCH 142/283] set eltoo channel to false for now --- lightningd/opening_common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index f866a91f5be0..0fb02045a139 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -162,4 +162,7 @@ void channel_config(struct lightningd *ld, /* This is filled in by lightning_openingd, for consistency. */ ours->channel_reserve = AMOUNT_SAT(UINT64_MAX); + + /* Is ln-penalty channel */ + ours->is_eltoo = false; } From 822869055306e850eb2bc23e2f4c77902747980b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 1 Sep 2022 17:04:56 -0400 Subject: [PATCH 143/283] More motion towards eltoo fundchannel --- common/features.c | 5 + common/features.h | 3 + contrib/startup_regtest.sh | 6 +- lightningd/lightningd.c | 5 +- lightningd/opening_common.c | 46 +++++++ lightningd/opening_common.h | 10 ++ lightningd/opening_control.c | 127 ++++++++++++++++---- lightningd/opening_control.h | 3 +- lightningd/peer_control.c | 10 +- lightningd/test/run-invoice-select-inchan.c | 2 +- openingd/eltoo_openingd.c | 2 + openingd/eltoo_openingd_wire.csv | 21 ++++ plugins/spender/multifundchannel.c | 8 +- wallet/test/run-wallet.c | 3 +- 14 files changed, 220 insertions(+), 31 deletions(-) diff --git a/common/features.c b/common/features.c index bd7db0bfb4a1..c01e49f3853b 100644 --- a/common/features.c +++ b/common/features.c @@ -105,6 +105,11 @@ static const struct feature_style feature_styles[] = { * we refuse to parse it. */ [BOLT11_FEATURE] = FEATURE_REPRESENT, [CHANNEL_FEATURE] = FEATURE_DONT_REPRESENT } }, + { OPT_ELTOO, + .copy_style = { [INIT_FEATURE] = FEATURE_REPRESENT, + [NODE_ANNOUNCE_FEATURE] = FEATURE_DONT_REPRESENT, + [BOLT11_FEATURE] = FEATURE_DONT_REPRESENT, + [CHANNEL_FEATURE] = FEATURE_DONT_REPRESENT } }, }; struct dependency { diff --git a/common/features.h b/common/features.h index 3bea463565c8..d8645015f5fa 100644 --- a/common/features.h +++ b/common/features.h @@ -147,4 +147,7 @@ const char *fmt_featurebits(const tal_t *ctx, const u8 *featurebits); #define OPT_SHUTDOWN_WRONG_FUNDING 104 + /* `option_eltoo` | ... I ... */ +#define OPT_ELTOO 50 + #endif /* LIGHTNING_COMMON_FEATURES_H */ diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 280ef85f95ad..1937214e160a 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=dualopend" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 @@ -126,9 +126,9 @@ start_nodes() { start_ln() { # Start bitcoind in the background test -f "$PATH_TO_BITCOIN/regtest/bitcoind.pid" || \ - bitcoind -regtest -txindex -fallbackfee=0.00000253 -daemon + bitcoind -regtest -txindex -fallbackfee=0.00000253 -daemon -daemonwait - # Wait for it to start. + # Wait for it to start while ! bitcoin-cli -regtest ping 2> /tmp/null; do echo "awaiting bitcoind..." && sleep 1; done # Kick it out of initialblockdownload if necessary diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index b8e60b3fff65..882295e08d2b 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -309,7 +309,9 @@ static const char *subdaemons[] = { "lightning_gossipd", "lightning_hsmd", "lightning_onchaind", - "lightning_openingd" + "lightning_openingd", + "lightning_eltoo_channeld", + "lightning_eltoo_openingd" }; /* Return true if called with a recognized subdaemon e.g. "hsmd" */ @@ -828,6 +830,7 @@ static struct feature_set *default_features(const tal_t *ctx) OPTIONAL_FEATURE(OPT_ANCHOR_OUTPUTS), OPTIONAL_FEATURE(OPT_QUIESCE), OPTIONAL_FEATURE(OPT_ONION_MESSAGES), + OPTIONAL_FEATURE(OPT_ELTOO), #endif }; diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index 0fb02045a139..51439a346bb3 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -166,3 +166,49 @@ void channel_config(struct lightningd *ld, /* Is ln-penalty channel */ ours->is_eltoo = false; } + +void eltoo_channel_config(struct lightningd *ld, + struct channel_config *ours, + u32 *max_shared_delay, + struct amount_msat *min_effective_htlc_capacity) +{ + /* FIXME: depend on feerate. */ + *max_shared_delay = 60; + + /* Take minimal effective capacity from config min_capacity_sat */ + if (!amount_sat_to_msat(min_effective_htlc_capacity, + amount_sat(ld->config.min_capacity_sat))) + fatal("amount_msat overflow for config.min_capacity_sat"); + + /* BOLT #2: + * + * The sending node SHOULD: + *... + * - set `dust_limit_satoshis` to a sufficient value to allow + * commitment transactions to propagate through the Bitcoin network. + */ + ours->dust_limit = chainparams->dust_limit; + ours->max_htlc_value_in_flight = AMOUNT_MSAT(UINT64_MAX); + + ours->max_dust_htlc_exposure_msat + = ld->config.max_dust_htlc_exposure_msat; + + /* Don't care */ + ours->htlc_minimum = ld->config.htlc_minimum_msat; + + /* BOLT #2: + * + * The sending node SHOULD: + * - set `to_self_delay` sufficient to ensure the sender can + * irreversibly spend a commitment transaction output, in case of + * misbehavior by the receiver. + */ + ours->to_self_delay = ld->config.locktime_blocks; + + ours->max_accepted_htlcs = ld->config.max_concurrent_htlcs; + + /* This is filled in by lightning_openingd, for consistency. */ + ours->channel_reserve = AMOUNT_SAT(UINT64_MAX); + + ours->is_eltoo = true; +} diff --git a/lightningd/opening_common.h b/lightningd/opening_common.h index 8d1b1c490e6f..8ce38e5c9e8c 100644 --- a/lightningd/opening_common.h +++ b/lightningd/opening_common.h @@ -46,6 +46,9 @@ struct uncommitted_channel { /* Public key for funding tx. */ struct pubkey local_funding_pubkey; + /* Public key for settlement tx. (eltoo only) */ + struct pubkey local_settle_pubkey; + /* If true, we are already in fundee-mode and any future * `fundchannel_start` on our end should fail. */ @@ -58,6 +61,8 @@ struct uncommitted_channel { /* Our channel config. */ struct channel_config our_config; + + bool is_eltoo; }; struct funding_channel { @@ -123,4 +128,9 @@ void channel_config(struct lightningd *ld, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity); +void eltoo_channel_config(struct lightningd *ld, + struct channel_config *ours, + u32 *max_shared_delay, + struct amount_msat *min_effective_htlc_capacity); + #endif /* LIGHTNING_LIGHTNINGD_OPENING_COMMON_H */ diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 9499a76e3e41..81f0b833555c 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -28,6 +28,7 @@ #include #include #include +#include #include void json_add_uncommitted_channel(struct json_stream *response, @@ -792,6 +793,66 @@ static void opening_got_offer(struct subd *openingd, plugin_hook_call_openchannel(openingd->ld, payload); } +static unsigned int eltoo_openingd_msg(struct subd *openingd, + const u8 *msg, const int *fds) +{ + enum eltoo_openingd_wire t = fromwire_peektype(msg); + struct uncommitted_channel *uc = openingd->channel; + + switch (t) { + case WIRE_OPENINGD_ELTOO_FUNDER_REPLY: + if (!uc->fc) { + log_broken(openingd->log, "Unexpected FUNDER_REPLY %s", + tal_hex(tmpctx, msg)); + tal_free(openingd); + return 0; + } + if (tal_count(fds) != 1) + return 1; + opening_funder_finished(openingd, msg, fds, uc->fc); + return 0; + case WIRE_OPENINGD_ELTOO_FUNDER_START_REPLY: + if (!uc->fc) { + log_broken(openingd->log, "Unexpected FUNDER_START_REPLY %s", + tal_hex(tmpctx, msg)); + tal_free(openingd); + return 0; + } + opening_funder_start_replied(openingd, msg, fds, uc->fc); + return 0; + case WIRE_OPENINGD_ELTOO_FAILED: + openingd_failed(openingd, msg, uc); + return 0; + + case WIRE_OPENINGD_ELTOO_FUNDEE: + if (tal_count(fds) != 1) + return 1; + opening_fundee_finished(openingd, msg, fds, uc); + return 0; + + case WIRE_OPENINGD_ELTOO_GOT_OFFER: + opening_got_offer(openingd, msg, uc); + return 0; + + /* We send these! */ + case WIRE_OPENINGD_ELTOO_INIT: + case WIRE_OPENINGD_ELTOO_FUNDER_START: + case WIRE_OPENINGD_ELTOO_FUNDER_COMPLETE: + case WIRE_OPENINGD_ELTOO_FUNDER_CANCEL: + case WIRE_OPENINGD_ELTOO_GOT_OFFER_REPLY: + case WIRE_OPENINGD_ELTOO_DEV_MEMLEAK: + /* Replies never get here */ + case WIRE_OPENINGD_DEV_MEMLEAK_REPLY: + break; + } + + log_broken(openingd->log, "Unexpected msg %s: %s", + openingd_wire_name(t), tal_hex(tmpctx, msg)); + tal_free(openingd); + return 0; +} + + static unsigned int openingd_msg(struct subd *openingd, const u8 *msg, const int *fds) { @@ -851,10 +912,10 @@ static unsigned int openingd_msg(struct subd *openingd, return 0; } -bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) +bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd, bool eltoo) { int hsmfd; - u32 max_to_self_delay; + u32 max_delay; struct amount_msat min_effective_htlc_capacity; struct uncommitted_channel *uc; const u8 *msg; @@ -863,15 +924,17 @@ bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) uc = peer->uncommitted_channel; assert(!uc->open_daemon); + uc->is_eltoo = eltoo; + hsmfd = hsm_get_client_fd(peer->ld, &uc->peer->id, uc->dbid, HSM_CAP_COMMITMENT_POINT | HSM_CAP_SIGN_REMOTE_TX); uc->open_daemon = new_channel_subd(peer, peer->ld, - "lightning_openingd", + eltoo ? "lightning_eltoo_openingd" : "lightning_openingd", uc, &peer->id, uc->log, - true, openingd_wire_name, - openingd_msg, + true, eltoo ? eltoo_openingd_wire_name : openingd_wire_name, + eltoo ? eltoo_openingd_msg : openingd_msg, opend_channel_errmsg, opend_channel_set_billboard, take(&peer_fd->fd), @@ -885,9 +948,15 @@ bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) return false; } - channel_config(peer->ld, &uc->our_config, - &max_to_self_delay, - &min_effective_htlc_capacity); + if (eltoo) { + eltoo_channel_config(peer->ld, &uc->our_config, + &max_delay /* max_shared_delay */, + &min_effective_htlc_capacity); + } else { + channel_config(peer->ld, &uc->our_config, + &max_delay /* max_to_self_delay */, + &min_effective_htlc_capacity); + } /* BOLT #2: * @@ -897,19 +966,35 @@ bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) */ uc->minimum_depth = peer->ld->config.anchor_confirms; - msg = towire_openingd_init(NULL, - chainparams, - peer->ld->our_features, - peer->their_features, - &uc->our_config, - max_to_self_delay, - min_effective_htlc_capacity, - &uc->local_basepoints, - &uc->local_funding_pubkey, - uc->minimum_depth, - feerate_min(peer->ld, NULL), - feerate_max(peer->ld, NULL), - IFDEV(peer->ld->dev_force_tmp_channel_id, NULL)); + if (eltoo) { + msg = towire_openingd_eltoo_init(NULL, + chainparams, + peer->ld->our_features, + peer->their_features, + &uc->our_config, + max_delay /* max_shared_delay */, + min_effective_htlc_capacity, + &uc->local_funding_pubkey, + &uc->local_settle_pubkey, + uc->minimum_depth, + feerate_min(peer->ld, NULL), + feerate_max(peer->ld, NULL), + IFDEV(peer->ld->dev_force_tmp_channel_id, NULL)); + } else { + msg = towire_openingd_init(NULL, + chainparams, + peer->ld->our_features, + peer->their_features, + &uc->our_config, + max_delay /* max_to_self_delay */, + min_effective_htlc_capacity, + &uc->local_basepoints, + &uc->local_funding_pubkey, + uc->minimum_depth, + feerate_min(peer->ld, NULL), + feerate_max(peer->ld, NULL), + IFDEV(peer->ld->dev_force_tmp_channel_id, NULL)); + } subd_send_msg(uc->open_daemon, take(msg)); return true; } diff --git a/lightningd/opening_control.h b/lightningd/opening_control.h index a8f8d982a73a..44be4b58dcc4 100644 --- a/lightningd/opening_control.h +++ b/lightningd/opening_control.h @@ -15,7 +15,8 @@ void json_add_uncommitted_channel(struct json_stream *response, const struct uncommitted_channel *uc); bool peer_start_openingd(struct peer *peer, - struct peer_fd *peer_fd); + struct peer_fd *peer_fd, + bool eltoo); struct subd *peer_get_owning_subd(struct peer *peer); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 7994e6fbb6b5..2d64fb7c4bff 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1216,6 +1216,7 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) struct channel_id channel_id; struct peer *peer; bool dual_fund; + bool eltoo; u8 *error; struct peer_fd *peer_fd = new_peer_fd(tmpctx, fd); @@ -1287,6 +1288,10 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) peer->their_features, OPT_DUAL_FUND); + eltoo = feature_negotiated(ld->our_features, + peer->their_features, + OPT_ELTOO); + /* Did we ask for this? */ if (!msgtype) { /* If it was dual_fund, it will have peer_unsaved_channel above */ @@ -1301,7 +1306,7 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) if (!uc->open_daemon && uc->fc && uc->fc->open_msg) { - if (peer_start_openingd(peer, peer_fd)) { + if (peer_start_openingd(peer, peer_fd, eltoo)) { subd_send_msg(uc->open_daemon, uc->fc->open_msg); } @@ -1328,7 +1333,7 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) goto send_error; } peer->uncommitted_channel = new_uncommitted_channel(peer); - peer_start_openingd(peer, peer_fd); + peer_start_openingd(peer, peer_fd, eltoo); break; case WIRE_OPEN_CHANNEL2: if (!dual_fund) { @@ -1342,6 +1347,7 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) channel->cid = channel_id; peer_start_dualopend(peer, peer_fd, channel); break; + /* FIXME we should crash here if offered an eltoo channel */ default: log_peer_unusual(ld->log, &peer->id, "Unknown channel %s for %s", diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 976af4bb8f54..0e1f67e8b2fd 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -610,7 +610,7 @@ bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UN { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } /* Generated stub for peer_start_openingd */ bool peer_start_openingd(struct peer *peer UNNEEDED, - struct peer_fd *peer_fd UNNEEDED) + struct peer_fd *peer_fd UNNEEDED, bool eltoo) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for plugin_hook_call_ */ bool plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook *hook UNNEEDED, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index ff511a414c9a..90936aa6b31c 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -1159,6 +1159,8 @@ static u8 *handle_master_in(struct eltoo_state *state) case WIRE_OPENINGD_ELTOO_FUNDER_START_REPLY: case WIRE_OPENINGD_ELTOO_FUNDEE: case WIRE_OPENINGD_ELTOO_FAILED: + case WIRE_OPENINGD_ELTOO_GOT_OFFER: + case WIRE_OPENINGD_ELTOO_GOT_OFFER_REPLY: break; } diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index b900b3645a4e..e1dd7995eee7 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -98,3 +98,24 @@ msgtype,openingd_eltoo_dev_memleak,6533 msgtype,openingd_eltoo_dev_memleak_reply,6133 msgdata,openingd_eltoo_dev_memleak_reply,leak,bool, + +# Openingd->master: they offered channel, should we continue? +msgtype,openingd_eltoo_got_offer,6505 +msgdata,openingd_eltoo_got_offer,funding_satoshis,amount_sat, +msgdata,openingd_eltoo_got_offer,push_msat,amount_msat, +msgdata,openingd_eltoo_got_offer,dust_limit_satoshis,amount_sat, +msgdata,openingd_eltoo_got_offer,max_htlc_value_in_flight_msat,amount_msat, +msgdata,openingd_eltoo_got_offer,htlc_minimum_msat,amount_msat, +msgdata,openingd_eltoo_got_offer,shared_delay,u16, +msgdata,openingd_eltoo_got_offer,max_accepted_htlcs,u16, +msgdata,openingd_eltoo_got_offer,channel_flags,u8, +msgdata,openingd_eltoo_got_offer,shutdown_len,u16, +msgdata,openingd_eltoo_got_offer,shutdown_scriptpubkey,u8,shutdown_len + +# master->openingd: optional rejection message +msgtype,openingd_eltoo_got_offer_reply,6605 +msgdata,openingd_eltoo_got_offer_reply,rejection,?wirestring, +msgdata,openingd_eltoo_got_offer_reply,shutdown_len,u16, +msgdata,openingd_eltoo_got_offer_reply,our_shutdown_scriptpubkey,?u8,shutdown_len +msgdata,openingd_eltoo_got_offer_reply,our_shutdown_wallet_index,?u32, + diff --git a/plugins/spender/multifundchannel.c b/plugins/spender/multifundchannel.c index 41b55a17b9c9..44c19b3e62e6 100644 --- a/plugins/spender/multifundchannel.c +++ b/plugins/spender/multifundchannel.c @@ -1608,8 +1608,14 @@ connect_ok(struct command *cmd, /* Set the open protocol to use now */ if (feature_negotiated(plugin_feature_set(mfc->cmd->plugin), dest->their_features, - OPT_DUAL_FUND)) + OPT_ELTOO)) { + /* FIXME v2 opens not supported for eltoo yet... */ + dest->protocol = FUND_CHANNEL; + } else if (feature_negotiated(plugin_feature_set(mfc->cmd->plugin), + dest->their_features, + OPT_DUAL_FUND)) { dest->protocol = OPEN_CHANNEL; + } dest->state = MULTIFUNDCHANNEL_CONNECTED; return connect_done(dest); diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index eee265e4f0ac..7dd11ffa3e19 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -650,7 +650,8 @@ bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UN { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } /* Generated stub for peer_start_openingd */ bool peer_start_openingd(struct peer *peer UNNEEDED, - struct peer_fd *peer_fd UNNEEDED) + struct peer_fd *peer_fd UNNEEDED, + bool eltoo) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for peer_wire_name */ const char *peer_wire_name(int e UNNEEDED) From 82ddc790cadc5c536a275f281af0fe9578f393e6 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 1 Sep 2022 17:17:07 -0400 Subject: [PATCH 144/283] fundchannel hanging now --- lightningd/opening_control.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 81f0b833555c..809c0e9a4ca5 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1141,6 +1141,7 @@ static struct command_result *json_fundchannel_start(struct command *cmd, struct peer *peer; bool *announce_channel; u32 *feerate_per_kw; + bool dual, eltoo; struct amount_sat *amount; struct amount_msat *push_msat; @@ -1199,10 +1200,15 @@ static struct command_result *json_fundchannel_start(struct command *cmd, return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, "Peer not connected"); - if (!peer->uncommitted_channel) { - if (feature_negotiated(cmd->ld->our_features, + eltoo = feature_negotiated(cmd->ld->our_features, + peer->their_features, + OPT_ELTOO); + dual = feature_negotiated(cmd->ld->our_features, peer->their_features, - OPT_DUAL_FUND)) + OPT_DUAL_FUND); + + if (!peer->uncommitted_channel) { + if (!eltoo && dual) return command_fail(cmd, FUNDING_STATE_INVALID, "Peer negotiated" " `option_dual_fund`," From 8d5f928e23ad6610e1fc87ca951d005e80bc4ebf Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 11:37:12 -0400 Subject: [PATCH 145/283] Try threading through settle pubkey from hsmd --- common/derive_basepoints.c | 10 +++++++++- common/derive_basepoints.h | 3 +++ common/test/run-derive_basepoints.c | 18 +++++++++++++++++- hsmd/hsmd_wire.csv | 1 + hsmd/libhsmd.c | 19 ++++++++++--------- lightningd/channel.c | 9 ++++++--- lightningd/channel.h | 3 ++- lightningd/opening_common.c | 2 +- lightningd/peer_control.c | 11 ++++++----- wallet/db.c | 15 ++++++++++----- wallet/test/run-db.c | 5 +++-- wallet/test/run-wallet.c | 4 +++- 12 files changed, 71 insertions(+), 29 deletions(-) diff --git a/common/derive_basepoints.c b/common/derive_basepoints.c index cbb3b6525c3e..1154f3048bf6 100644 --- a/common/derive_basepoints.c +++ b/common/derive_basepoints.c @@ -39,7 +39,7 @@ void fromwire_secrets(const u8 **ptr, size_t *max, struct secrets *s) #endif struct keys { - struct privkey f, r, h, p, d; + struct privkey f, s, r, h, p, d; struct sha256 shaseed; }; @@ -51,6 +51,7 @@ static void derive_keys(const struct secret *seed, struct keys *keys) #if DEVELOPER if (dev_force_channel_secrets) { keys->f = dev_force_channel_secrets->funding_privkey; + keys->s = dev_force_channel_secrets->settle_privkey; keys->r.secret = dev_force_channel_secrets->revocation_basepoint_secret; keys->p.secret = dev_force_channel_secrets->payment_basepoint_secret; keys->h.secret = dev_force_channel_secrets->htlc_basepoint_secret; @@ -63,6 +64,7 @@ static void derive_keys(const struct secret *seed, struct keys *keys) bool derive_basepoints(const struct secret *seed, struct pubkey *funding_pubkey, + struct pubkey *settle_pubkey, struct basepoints *basepoints, struct secrets *secrets, struct sha256 *shaseed) @@ -73,6 +75,7 @@ bool derive_basepoints(const struct secret *seed, if (secrets) { secrets->funding_privkey = keys.f; + secrets->settle_privkey = keys.s; secrets->revocation_basepoint_secret = keys.r.secret; secrets->payment_basepoint_secret = keys.p.secret; secrets->htlc_basepoint_secret = keys.h.secret; @@ -84,6 +87,11 @@ bool derive_basepoints(const struct secret *seed, return false; } + if (settle_pubkey) { + if (!pubkey_from_privkey(&keys.f, settle_pubkey)) + return false; + } + if (basepoints) { if (!pubkey_from_privkey(&keys.r, &basepoints->revocation) || !pubkey_from_privkey(&keys.p, &basepoints->payment) diff --git a/common/derive_basepoints.h b/common/derive_basepoints.h index efe1adb42af6..a43af9301f10 100644 --- a/common/derive_basepoints.h +++ b/common/derive_basepoints.h @@ -17,6 +17,7 @@ struct basepoints { struct secrets { struct privkey funding_privkey; + struct privkey settle_privkey; struct secret revocation_basepoint_secret; struct secret payment_basepoint_secret; struct secret htlc_basepoint_secret; @@ -27,12 +28,14 @@ struct secrets { * derive_basepoints - given a (per-peer) seed, get the basepoints * @seed: (in) seed (derived by master daemon from counter and main seed) * @funding_pubkey: (out) pubkey for funding tx output (if non-NULL) + * @settle_pubkey: (out) pubkey used for settlement transactions (eltoo only) * @basepoints: (out) basepoints for channel (if non-NULL) * @secrets: (out) basepoints for channel (if non-NULL) * @shaseed: (out) seed for shachain (if non-NULL) */ bool derive_basepoints(const struct secret *seed, struct pubkey *funding_pubkey, + struct pubkey *settle_pubkey, struct basepoints *basepoints, struct secrets *secrets, struct sha256 *shaseed); diff --git a/common/test/run-derive_basepoints.c b/common/test/run-derive_basepoints.c index e53b89754eac..d0150e6ab1b9 100644 --- a/common/test/run-derive_basepoints.c +++ b/common/test/run-derive_basepoints.c @@ -109,6 +109,7 @@ STRUCTEQ_DEF(basepoints, 0, delayed_payment.pubkey); STRUCTEQ_DEF(secrets, 0, funding_privkey.secret.data, + settle_privkey.secret.data, revocation_basepoint_secret.data, payment_basepoint_secret.data, htlc_basepoint_secret.data, @@ -119,6 +120,7 @@ STRUCTEQ_DEF(privkey, 0, struct info { struct secret seed; struct pubkey funding_pubkey; + struct pubkey settle_pubkey; struct basepoints basepoints; struct secrets secrets; struct sha256 shaseed; @@ -141,6 +143,7 @@ int main(int argc, char *argv[]) common_setup(argv[0]); baseline = new_info(ctx); assert(derive_basepoints(&baseline->seed, &baseline->funding_pubkey, + &baseline->settle_pubkey, &baseline->basepoints, &baseline->secrets, &baseline->shaseed)); @@ -148,6 +151,7 @@ int main(int argc, char *argv[]) /* Same seed, same result. */ info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, + &baseline->settle_pubkey, &info->basepoints, &info->secrets, &info->shaseed)); @@ -164,6 +168,7 @@ int main(int argc, char *argv[]) assert(derive_basepoints(&info->seed, &info->funding_pubkey, + &info->settle_pubkey, &info->basepoints, &info->secrets, &info->shaseed)); @@ -178,7 +183,7 @@ int main(int argc, char *argv[]) /* Any field can be NULL (except seed). */ info = new_info(ctx); - assert(derive_basepoints(&info->seed, NULL, + assert(derive_basepoints(&info->seed, NULL, &info->settle_pubkey, &info->basepoints, &info->secrets, &info->shaseed)); @@ -186,8 +191,17 @@ int main(int argc, char *argv[]) assert(secrets_eq(&baseline->secrets, &info->secrets)); assert(sha256_eq(&baseline->shaseed, &info->shaseed)); + info = new_info(ctx); + assert(derive_basepoints(&info->seed, &info->funding_pubkey, NULL, + &info->basepoints, + &info->secrets, + &info->shaseed)); + assert(basepoints_eq(&baseline->basepoints, &info->basepoints)); + assert(secrets_eq(&baseline->secrets, &info->secrets)); + info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, + &info->settle_pubkey, NULL, &info->secrets, &info->shaseed)); @@ -197,6 +211,7 @@ int main(int argc, char *argv[]) info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, + &info->settle_pubkey, &info->basepoints, NULL, &info->shaseed)); @@ -206,6 +221,7 @@ int main(int argc, char *argv[]) info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, + &info->settle_pubkey, &info->basepoints, &info->secrets, NULL)); diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index dca7f320918e..6f5dfe6fc1cd 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -51,6 +51,7 @@ msgdata,hsmd_get_channel_basepoints,dbid,u64, msgtype,hsmd_get_channel_basepoints_reply,110 msgdata,hsmd_get_channel_basepoints_reply,basepoints,basepoints, msgdata,hsmd_get_channel_basepoints_reply,funding_pubkey,pubkey, +msgdata,hsmd_get_channel_basepoints_reply,settle_pubkey,pubkey, #include # Provide channel parameters. diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index cab178749534..07873bc84a8a 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -431,7 +431,7 @@ static void hsm_unilateral_close_privkey(struct privkey *dst, struct secrets secrets; get_channel_seed(&info->peer_id, info->channel_id, &channel_seed); - derive_basepoints(&channel_seed, NULL, &basepoints, &secrets, NULL); + derive_basepoints(&channel_seed, NULL, NULL, &basepoints, &secrets, NULL); /* BOLT #3: * @@ -783,15 +783,16 @@ static u8 *handle_get_channel_basepoints(struct hsmd_client *c, struct secret seed; struct basepoints basepoints; struct pubkey funding_pubkey; + struct pubkey settle_pubkey; if (!fromwire_hsmd_get_channel_basepoints(msg_in, &peer_id, &dbid)) return hsmd_status_malformed_request(c, msg_in); get_channel_seed(&peer_id, dbid, &seed); - derive_basepoints(&seed, &funding_pubkey, &basepoints, NULL, NULL); + derive_basepoints(&seed, &funding_pubkey, &settle_pubkey, &basepoints, NULL, NULL); return towire_hsmd_get_channel_basepoints_reply(NULL, &basepoints, - &funding_pubkey); + &funding_pubkey, &settle_pubkey); } static u8 *handle_gen_nonce(struct hsmd_client *c, @@ -808,7 +809,7 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, /* Generate privkey for additional nonce entropy */ get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - NULL, NULL, &secrets, NULL); + NULL, NULL, NULL, &secrets, NULL); /* Fill and return own next_nonce FIXME add in more entropy */ bipmusig_gen_nonce(&secretstuff.sec_nonce, @@ -1139,7 +1140,7 @@ static u8 *handle_sign_mutual_close_tx(struct hsmd_client *c, const u8 *msg_in) * outputs! */ get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, NULL, &secrets, NULL); funding_wscript = bitcoin_redeem_2of2(tmpctx, &local_funding_pubkey, @@ -1245,7 +1246,7 @@ static u8 *handle_sign_remote_htlc_tx(struct hsmd_client *c, const u8 *msg_in) tx->chainparams = c->chainparams; get_channel_seed(&c->id, c->dbid, &channel_seed); - derive_basepoints(&channel_seed, NULL, &basepoints, &secrets, NULL); + derive_basepoints(&channel_seed, NULL, NULL, &basepoints, &secrets, NULL); if (!derive_simple_privkey(&secrets.htlc_basepoint_secret, &basepoints.htlc, @@ -1317,7 +1318,7 @@ static u8 *handle_sign_remote_commitment_tx(struct hsmd_client *c, const u8 *msg get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, NULL, &secrets, NULL); funding_wscript = bitcoin_redeem_2of2(tmpctx, &local_funding_pubkey, @@ -1459,7 +1460,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, NULL, &secrets, NULL); /* Now that we have both public keys, we can derive the MuSig session */ @@ -1537,7 +1538,7 @@ static u8 *handle_sign_commitment_tx(struct hsmd_client *c, const u8 *msg_in) get_channel_seed(&peer_id, dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, NULL, &secrets, NULL); /*~ Bitcoin signatures cover the (part of) the script they're * executing; the rules are a bit complex in general, but for diff --git a/lightningd/channel.c b/lightningd/channel.c index 789d75554161..f8477da589a3 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -105,7 +105,8 @@ void get_channel_basepoints(struct lightningd *ld, const struct node_id *peer_id, const u64 dbid, struct basepoints *local_basepoints, - struct pubkey *local_funding_pubkey) + struct pubkey *local_funding_pubkey, + struct pubkey *local_settle_pubkey) { u8 *msg; @@ -116,7 +117,7 @@ void get_channel_basepoints(struct lightningd *ld, msg = wire_sync_read(tmpctx, ld->hsm_fd); if (!fromwire_hsmd_get_channel_basepoints_reply(msg, local_basepoints, - local_funding_pubkey)) + local_funding_pubkey, local_settle_pubkey)) fatal("HSM gave bad hsm_get_channel_basepoints_reply %s", tal_hex(msg, msg)); } @@ -202,6 +203,7 @@ struct channel *new_unsaved_channel(struct peer *peer, struct lightningd *ld = peer->ld; struct channel *channel = tal(ld, struct channel); u8 *msg; + struct pubkey unused_settle_pubkey; channel->peer = peer; /* Not saved to the database yet! */ @@ -278,7 +280,8 @@ struct channel *new_unsaved_channel(struct peer *peer, get_channel_basepoints(ld, &peer->id, channel->unsaved_dbid, &channel->local_basepoints, - &channel->local_funding_pubkey); + &channel->local_funding_pubkey, + &unused_settle_pubkey); channel->forgets = tal_arr(channel, struct command *, 0); list_add_tail(&peer->channels, &channel->list); diff --git a/lightningd/channel.h b/lightningd/channel.h index db81ce8c484c..66c8ce9ccc6e 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -467,7 +467,8 @@ void get_channel_basepoints(struct lightningd *ld, const struct node_id *peer_id, const u64 dbid, struct basepoints *local_basepoints, - struct pubkey *local_funding_pubkey); + struct pubkey *local_funding_pubkey, + struct pubkey *local_settle_pubkey); void channel_set_billboard(struct channel *channel, bool perm, const char *str TAKES); diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index 51439a346bb3..bd2bc7af7560 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -66,7 +66,7 @@ new_uncommitted_channel(struct peer *peer) tal_hex(new_channel_msg, new_channel_msg)); get_channel_basepoints(ld, &uc->peer->id, uc->dbid, - &uc->local_basepoints, &uc->local_funding_pubkey); + &uc->local_basepoints, &uc->local_funding_pubkey, &uc->local_settle_pubkey); uc->peer->uncommitted_channel = uc; tal_add_destructor(uc, destroy_uncommitted_channel); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 2d64fb7c4bff..d66c59e04c88 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1284,14 +1284,15 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) abort(); } - dual_fund = feature_negotiated(ld->our_features, - peer->their_features, - OPT_DUAL_FUND); - eltoo = feature_negotiated(ld->our_features, peer->their_features, OPT_ELTOO); + /* Single funder only for now if eltoo */ + dual_fund = !eltoo && feature_negotiated(ld->our_features, + peer->their_features, + OPT_DUAL_FUND); + /* Did we ask for this? */ if (!msgtype) { /* If it was dual_fund, it will have peer_unsaved_channel above */ @@ -1322,6 +1323,7 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) /* OK, it's an unknown channel. Create a new one if they're trying. */ switch (*msgtype) { case WIRE_OPEN_CHANNEL: + case WIRE_OPEN_CHANNEL_ELTOO: if (dual_fund) { error = towire_errorfmt(tmpctx, &channel_id, "OPT_DUAL_FUND: cannot use open_channel"); @@ -1347,7 +1349,6 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) channel->cid = channel_id; peer_start_dualopend(peer, peer_fd, channel); break; - /* FIXME we should crash here if offered an eltoo channel */ default: log_peer_unusual(ld->log, &peer->id, "Unknown channel %s for %s", diff --git a/wallet/db.c b/wallet/db.c index 04497400dcdb..c48c2c3a932d 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -1143,7 +1143,7 @@ static void fillin_missing_local_basepoints(struct lightningd *ld, u8 *msg; struct db_stmt *upstmt; struct basepoints base; - struct pubkey funding_pubkey; + struct pubkey funding_pubkey, settle_pubkey; dbid = db_col_u64(stmt, "channels.id"); db_col_node_id(stmt, "peers.node_id", &peer_id); @@ -1155,7 +1155,7 @@ static void fillin_missing_local_basepoints(struct lightningd *ld, msg = wire_sync_read(tmpctx, mc->hsm_fd); if (!fromwire_hsmd_get_channel_basepoints_reply( - msg, &base, &funding_pubkey)) + msg, &base, &funding_pubkey, &settle_pubkey)) fatal("malformed hsmd_get_channel_basepoints_reply " "from hsmd"); @@ -1173,8 +1173,9 @@ static void fillin_missing_local_basepoints(struct lightningd *ld, db_bind_pubkey(upstmt, 2, &base.htlc); db_bind_pubkey(upstmt, 3, &base.delayed_payment); db_bind_pubkey(upstmt, 4, &funding_pubkey); + db_bind_pubkey(upstmt, 5, &settle_pubkey); - db_bind_u64(upstmt, 5, dbid); + db_bind_u64(upstmt, 6, dbid); db_exec_prepared_v2(take(upstmt)); } @@ -1237,6 +1238,7 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, struct amount_sat funding_sat; struct node_id peer_id; struct pubkey local_funding_pubkey, remote_funding_pubkey; + struct pubkey local_settle_pubkey; struct basepoints local_basepoints UNUSED; struct bitcoin_signature last_sig; u64 cdb_id; @@ -1264,7 +1266,8 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, db_col_txid(stmt, "inflight.funding_tx_id", &funding_txid); get_channel_basepoints(ld, &peer_id, cdb_id, - &local_basepoints, &local_funding_pubkey); + &local_basepoints, &local_funding_pubkey, + &local_settle_pubkey); funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey, &remote_funding_pubkey); @@ -1329,6 +1332,7 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, struct amount_sat funding_sat; struct node_id peer_id; struct pubkey local_funding_pubkey, remote_funding_pubkey; + struct pubkey local_settle_pubkey; struct basepoints local_basepoints UNUSED; struct bitcoin_signature last_sig; u64 cdb_id; @@ -1353,7 +1357,8 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, db_col_pubkey(stmt, "c.fundingkey_remote", &remote_funding_pubkey); get_channel_basepoints(ld, &peer_id, cdb_id, - &local_basepoints, &local_funding_pubkey); + &local_basepoints, &local_funding_pubkey, + &local_settle_pubkey); funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey, &remote_funding_pubkey); diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index 054ddc31d3b3..acfe69acb36f 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -28,7 +28,7 @@ void derive_channel_id(struct channel_id *channel_id UNNEEDED, void fatal(const char *fmt UNNEEDED, ...) { fprintf(stderr, "fatal called!\n"); abort(); } /* Generated stub for fromwire_hsmd_get_channel_basepoints_reply */ -bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, struct basepoints *basepoints UNNEEDED, struct pubkey *funding_pubkey UNNEEDED) +bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, struct basepoints *basepoints UNNEEDED, struct pubkey *funding_pubkey UNNEEDED, struct pubkey *settle_pubkey UNNEEDED) { fprintf(stderr, "fromwire_hsmd_get_channel_basepoints_reply called!\n"); abort(); } /* Generated stub for fromwire_hsmd_get_output_scriptpubkey_reply */ bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **script UNNEEDED) @@ -38,7 +38,8 @@ void get_channel_basepoints(struct lightningd *ld UNNEEDED, const struct node_id *peer_id UNNEEDED, const u64 dbid UNNEEDED, struct basepoints *local_basepoints UNNEEDED, - struct pubkey *local_funding_pubkey UNNEEDED) + struct pubkey *local_funding_pubkey UNNEEDED, + struct pubkey *local_settle_pubkey UNNEEDED) { fprintf(stderr, "get_channel_basepoints called!\n"); abort(); } /* Generated stub for towire_hsmd_get_channel_basepoints */ u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct node_id *peerid UNNEEDED, u64 dbid UNNEEDED) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 7dd11ffa3e19..8be3e8440fdc 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -884,7 +884,8 @@ void plugin_hook_db_sync(struct db *db UNNEEDED) } bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, struct basepoints *basepoints, - struct pubkey *funding_pubkey) + struct pubkey *funding_pubkey, + struct pubkey *settle_pubkey) { struct pubkey pk; pubkey_from_der(tal_hexdata(tmpctx, @@ -893,6 +894,7 @@ bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, 66), 33, &pk); *funding_pubkey = pk; + *settle_pubkey = pk; basepoints->revocation = pk; basepoints->payment = pk; basepoints->htlc = pk; From 262fcad896a5a66b3f829ff75e6b14e2d6e38f71 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 13:39:28 -0400 Subject: [PATCH 146/283] bunch of stuff --- lightningd/channel.c | 4 +- lightningd/channel.h | 4 +- lightningd/opening_control.c | 150 ++++++++++++++++++++++++++----- lightningd/peer_htlcs.h | 2 +- openingd/eltoo_openingd_wire.csv | 2 +- wallet/test/run-wallet.c | 3 +- wallet/wallet.c | 3 +- 7 files changed, 139 insertions(+), 29 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index f8477da589a3..709e93a4b8d6 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -396,7 +396,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u32 lease_chan_max_msat, u16 lease_chan_max_ppt, struct amount_msat htlc_minimum_msat, - struct amount_msat htlc_maximum_msat) + struct amount_msat htlc_maximum_msat, + struct bip340sig *last_update_sig) { struct channel *channel = tal(peer->ld, struct channel); struct amount_msat htlc_min, htlc_max; @@ -448,6 +449,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->last_tx->chainparams = chainparams; channel->last_tx_type = TX_UNKNOWN; channel->last_sig = *last_sig; + channel->last_update_sig = *last_update_sig; channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs); channel->channel_info = *channel_info; channel->fee_states = dup_fee_states(channel, fee_states); diff --git a/lightningd/channel.h b/lightningd/channel.h index 66c8ce9ccc6e..2414657b1b1b 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -147,6 +147,7 @@ struct channel { struct bitcoin_tx *last_tx; enum wallet_tx_type last_tx_type; struct bitcoin_signature last_sig; + struct bip340sig last_update_sig; /* Eltoo only */ const struct bitcoin_signature *last_htlc_sigs; /* Keys for channel */ @@ -319,7 +320,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u32 lease_chan_max_msat, u16 lease_chan_max_ppt, struct amount_msat htlc_minimum_msat, - struct amount_msat htlc_maximum_msat); + struct amount_msat htlc_maximum_msat, + struct bip340sig *update_sig); /* new_inflight - Create a new channel_inflight for a channel */ struct channel_inflight * diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 809c0e9a4ca5..0a543bf7c673 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -91,7 +91,8 @@ wallet_commit_channel(struct lightningd *ld, u32 feerate, const u8 *our_upfront_shutdown_script, const u8 *remote_upfront_shutdown_script, - const struct channel_type *type) + const struct channel_type *type, + struct bip340sig *update_sig) { struct channel *channel; struct amount_msat our_msat; @@ -213,7 +214,8 @@ wallet_commit_channel(struct lightningd *ld, &lease_start_blockheight)), 0, NULL, 0, 0, /* No leases on v1s */ ld->config.htlc_minimum_msat, - ld->config.htlc_maximum_msat); + ld->config.htlc_maximum_msat, + update_sig); /* Now we finally put it in the database. */ wallet_channel_insert(ld->wallet, channel); @@ -296,22 +298,34 @@ static void funding_started_success(struct funding_channel *fc) static void opening_funder_start_replied(struct subd *openingd, const u8 *resp, const int *fds, - struct funding_channel *fc) + struct funding_channel *fc, + bool eltoo) { bool supports_shutdown_script; - if (!fromwire_openingd_funder_start_reply(fc, resp, + if (eltoo && !fromwire_openingd_eltoo_funder_start_reply(fc, resp, &fc->funding_scriptpubkey, &supports_shutdown_script, &fc->channel_type)) { log_broken(fc->uc->log, - "bad OPENING_FUNDER_REPLY %s", + "bad OPENING_ELTOO_FUNDER_REPLY %s", tal_hex(resp, resp)); was_pending(command_fail(fc->cmd, LIGHTNINGD, - "bad OPENING_FUNDER_REPLY %s", + "bad OPENING_ELTOO_FUNDER_REPLY %s", tal_hex(fc->cmd, resp))); goto failed; - } + } else if (!eltoo && !fromwire_openingd_funder_start_reply(fc, resp, + &fc->funding_scriptpubkey, + &supports_shutdown_script, + &fc->channel_type)) { + log_broken(fc->uc->log, + "bad OPENING_FUNDER_REPLY %s", + tal_hex(resp, resp)); + was_pending(command_fail(fc->cmd, LIGHTNINGD, + "bad OPENING_FUNDER_REPLY %s", + tal_hex(fc->cmd, resp))); + goto failed; + } /* If we're not using the upfront shutdown script, forget it */ if (!supports_shutdown_script) @@ -329,6 +343,83 @@ static void opening_funder_start_replied(struct subd *openingd, const u8 *resp, tal_free(fc->uc); } +/* FIXME all this needs changing */ +static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, + const int *fds, + struct funding_channel *fc) +{ + struct channel_info channel_info; + struct channel_id cid; + struct bitcoin_outpoint funding; + struct bip340sig first_update_sig; + struct bitcoin_tx *update_tx; + struct channel *channel; + struct lightningd *ld = openingd->ld; + u8 *remote_upfront_shutdown_script; + struct peer_fd *peer_fd; + struct channel_type *type; + + /* This is a new channel_info.their_config so set its ID to 0 */ + channel_info.their_config.id = 0; + + if (!fromwire_openingd_eltoo_funder_reply(resp, resp, + &channel_info.their_config, + &update_tx, + &first_update_sig, + &fc->uc->minimum_depth, + &channel_info.remote_fundingkey, + &channel_info.remote_settlekey, + &funding, + &remote_upfront_shutdown_script, + &type)) { + log_broken(fc->uc->log, + "bad OPENING_ELTOO_FUNDER_REPLY %s", + tal_hex(resp, resp)); + was_pending(command_fail(fc->cmd, LIGHTNINGD, + "bad OPENING_ELTOO_FUNDER_REPLY %s", + tal_hex(fc->cmd, resp))); + goto cleanup; + } + update_tx->chainparams = chainparams; + + peer_fd = new_peer_fd_arr(resp, fds); + + /* Saved with channel to disk */ + derive_channel_id(&cid, &funding); + + /* Steals fields from uc */ + channel = wallet_commit_channel(ld, fc->uc, + &cid, + update_tx, + NULL /* remote_commit_sig */, + &funding, + fc->funding_sats, + fc->push, + fc->channel_flags, + &channel_info, + 0 /* feerate */, + fc->our_upfront_shutdown_script, + remote_upfront_shutdown_script, + type, + &first_update_sig); + if (!channel) { + was_pending(command_fail(fc->cmd, LIGHTNINGD, + "Key generation failure")); + goto cleanup; + } + + /* Watch for funding confirms */ + channel_watch_funding(ld, channel); + + funding_success(channel); + /* FIXME Start eltoo_channeld instead */ + peer_start_channeld(channel, peer_fd, NULL, false, NULL); + +cleanup: + /* Frees fc too */ + tal_free(fc->uc); +} + static void opening_funder_finished(struct subd *openingd, const u8 *resp, const int *fds, struct funding_channel *fc) @@ -401,7 +492,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, feerate, fc->our_upfront_shutdown_script, remote_upfront_shutdown_script, - type); + type, + NULL /* update_sig */); if (!channel) { was_pending(command_fail(fc->cmd, LIGHTNINGD, "Key generation failure")); @@ -498,7 +590,8 @@ static void opening_fundee_finished(struct subd *openingd, feerate, local_upfront_shutdown_script, remote_upfront_shutdown_script, - type); + type, + NULL /* update_sig */); if (!channel) { uncommitted_channel_disconnect(uc, LOG_BROKEN, "Commit channel failed"); @@ -809,7 +902,7 @@ static unsigned int eltoo_openingd_msg(struct subd *openingd, } if (tal_count(fds) != 1) return 1; - opening_funder_finished(openingd, msg, fds, uc->fc); + opening_eltoo_funder_finished(openingd, msg, fds, uc->fc); return 0; case WIRE_OPENINGD_ELTOO_FUNDER_START_REPLY: if (!uc->fc) { @@ -818,7 +911,7 @@ static unsigned int eltoo_openingd_msg(struct subd *openingd, tal_free(openingd); return 0; } - opening_funder_start_replied(openingd, msg, fds, uc->fc); + opening_funder_start_replied(openingd, msg, fds, uc->fc, true /* eltoo */); return 0; case WIRE_OPENINGD_ELTOO_FAILED: openingd_failed(openingd, msg, uc); @@ -878,7 +971,7 @@ static unsigned int openingd_msg(struct subd *openingd, tal_free(openingd); return 0; } - opening_funder_start_replied(openingd, msg, fds, uc->fc); + opening_funder_start_replied(openingd, msg, fds, uc->fc, false /* eltoo */); return 0; case WIRE_OPENINGD_FAILED: openingd_failed(openingd, msg, uc); @@ -1203,12 +1296,12 @@ static struct command_result *json_fundchannel_start(struct command *cmd, eltoo = feature_negotiated(cmd->ld->our_features, peer->their_features, OPT_ELTOO); - dual = feature_negotiated(cmd->ld->our_features, + dual = !eltoo && feature_negotiated(cmd->ld->our_features, peer->their_features, OPT_DUAL_FUND); if (!peer->uncommitted_channel) { - if (!eltoo && dual) + if (dual) return command_fail(cmd, FUNDING_STATE_INVALID, "Peer negotiated" " `option_dual_fund`," @@ -1276,15 +1369,26 @@ static struct command_result *json_fundchannel_start(struct command *cmd, temporary_channel_id(&tmp_channel_id); - fc->open_msg - = towire_openingd_funder_start(fc, - *amount, - fc->push, - fc->our_upfront_shutdown_script, - upfront_shutdown_script_wallet_index, - *feerate_per_kw, - &tmp_channel_id, - fc->channel_flags); + if (eltoo) { + fc->open_msg + = towire_openingd_eltoo_funder_start(fc, + *amount, + fc->push, + fc->our_upfront_shutdown_script, + upfront_shutdown_script_wallet_index, + &tmp_channel_id, + fc->channel_flags); + } else { + fc->open_msg + = towire_openingd_funder_start(fc, + *amount, + fc->push, + fc->our_upfront_shutdown_script, + upfront_shutdown_script_wallet_index, + *feerate_per_kw, + &tmp_channel_id, + fc->channel_flags); + } /* Tell connectd to make this active; when it does, we can continue */ subd_send_msg(peer->ld->connectd, diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 1bcef7bb3502..a9c6495157b2 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -19,7 +19,7 @@ struct json_stream; /* FIXME: Define serialization primitive for this? */ struct channel_info { struct channel_config their_config; - struct pubkey remote_fundingkey; + struct pubkey remote_fundingkey, remote_settlekey; struct basepoints theirbase; /* The old_remote_per_commit is for the locked-in remote commit_tx, * and the remote_per_commit is for the commit_tx we're modifying now. */ diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index e1dd7995eee7..d545bd332c57 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -32,7 +32,7 @@ msgdata,openingd_eltoo_init,dev_temporary_channel_id,?byte,32 msgtype,openingd_eltoo_funder_reply,6601 msgdata,openingd_eltoo_funder_reply,their_config,channel_config, msgdata,openingd_eltoo_funder_reply,first_commit,bitcoin_tx, -msgdata,openingd_eltoo_funder_reply,first_update_psig,bip340sig, +msgdata,openingd_eltoo_funder_reply,first_update_sig,bip340sig, msgdata,openingd_eltoo_funder_reply,minimum_depth,u32, msgdata,openingd_eltoo_funder_reply,remote_funding_key,pubkey, msgdata,openingd_eltoo_funder_reply,remote_settlement_key,pubkey, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 8be3e8440fdc..bf1e75743eee 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1622,7 +1622,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) lease_commit_sig, 7777, 22, AMOUNT_MSAT(0), - AMOUNT_MSAT(-1ULL)); + AMOUNT_MSAT(-1ULL), + NULL /* last_update_sig */); db_begin_transaction(w->db); CHECK(!wallet_err); wallet_channel_insert(w, chan); diff --git a/wallet/wallet.c b/wallet/wallet.c index ff9506299b67..7a49cb807a9d 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1482,7 +1482,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm lease_chan_max_msat, lease_chan_max_ppt, htlc_minimum_msat, - htlc_maximum_msat); + htlc_maximum_msat, + NULL /* FIXME last_update_sig */); if (!wallet_channel_load_inflights(w, chan)) { tal_free(chan); From d478da30d5983015c597300f735381d43b5bc109 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 15:53:25 -0400 Subject: [PATCH 147/283] keyset shenanigans for opening --- contrib/startup_regtest.sh | 2 +- hsmd/libhsmd.c | 13 ++++++------ openingd/eltoo_openingd.c | 41 ++++++++++++++++++++------------------ 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 1937214e160a..cd997db5dbbd 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=dualopend" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_openingd" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 07873bc84a8a..d16fbc5256fb 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -109,6 +109,11 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_REMOTE_HTLC_TX: case WIRE_HSMD_VALIDATE_COMMITMENT_TX: case WIRE_HSMD_VALIDATE_REVOCATION: + case WIRE_HSMD_GEN_NONCE: + case WIRE_HSMD_PSIGN_UPDATE_TX: + case WIRE_HSMD_COMBINE_PSIG: + case WIRE_HSMD_READY_ELTOO_CHANNEL: + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: /* FIXME unused for now ... */ return (client->capabilities & HSM_CAP_SIGN_REMOTE_TX) != 0; case WIRE_HSMD_SIGN_MUTUAL_CLOSE_TX: @@ -128,11 +133,6 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_MESSAGE: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: case WIRE_HSMD_SIGN_BOLT12: - case WIRE_HSMD_READY_ELTOO_CHANNEL: - case WIRE_HSMD_PSIGN_UPDATE_TX: - case WIRE_HSMD_COMBINE_PSIG: - case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: - case WIRE_HSMD_GEN_NONCE: return (client->capabilities & HSM_CAP_MASTER) != 0; /*~ These are messages sent by the HSM so we should never receive them. */ @@ -799,7 +799,6 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, const u8 *msg_in) { struct channel_id channel_id; - struct nonce nonce; struct secret channel_seed; struct secrets secrets; @@ -818,7 +817,7 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, NULL /* keyagg_cache */, NULL /* msg32 */); - return towire_hsmd_gen_nonce_reply(NULL, &nonce); + return towire_hsmd_gen_nonce_reply(NULL, &secretstuff.pub_nonce); } /*~ The client has asked us to extract the shared secret from an EC Diffie diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 90936aa6b31c..be84aabc3258 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -70,6 +70,9 @@ struct eltoo_state { struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; + /* This seems necesssary for opening... move all keys here? */ + struct eltoo_keyset eltoo_keyset; + /* Initially temporary, then final channel id. */ struct channel_id channel_id; @@ -322,10 +325,10 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) /* Fetch MuSig nonce */ msg = towire_hsmd_gen_nonce(NULL, &state->channel_id); - peer_write(state->pps, take(msg)); + wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &state->channel->eltoo_keyset.self_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->eltoo_keyset.self_next_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -344,7 +347,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->our_funding_pubkey, &state->our_settlement_pubkey, channel_flags, - &state->channel->eltoo_keyset.self_next_nonce, + &state->eltoo_keyset.self_next_nonce, open_tlvs); peer_write(state->pps, take(msg)); @@ -374,7 +377,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->remoteconf.max_accepted_htlcs, &state->their_funding_pubkey, &state->their_settlement_pubkey, - &state->channel->eltoo_keyset.other_next_nonce, + &state->eltoo_keyset.other_next_nonce, &accept_tlvs)) { peer_failed_err(state->pps, &state->channel_id, @@ -543,10 +546,10 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, *update_tx, settle_tx, &state->their_funding_pubkey, - &state->channel->eltoo_keyset.other_next_nonce); + &state->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.session, &state->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -564,7 +567,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->funding.txid, state->funding.n, &our_update_psig, - &state->channel->eltoo_keyset.self_next_nonce); + &state->eltoo_keyset.self_next_nonce); peer_write(state->pps, msg); /* BOLT #2: @@ -586,7 +589,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!msg) return false; - if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &state->channel->eltoo_keyset.other_next_nonce)) + if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &state->eltoo_keyset.other_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); /* BOLT #2: @@ -636,10 +639,10 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->channel_id, &our_update_psig, &their_update_psig, - &state->channel->eltoo_keyset.session, + &state->eltoo_keyset.session, *update_tx, settle_tx, - &state->channel->eltoo_keyset.inner_pubkey); + &state->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, update_sig)) { @@ -738,7 +741,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->their_funding_pubkey, &state->their_settlement_pubkey, &channel_flags, - &state->channel->eltoo_keyset.other_next_nonce, + &state->eltoo_keyset.other_next_nonce, &open_tlvs)) peer_failed_err(state->pps, &state->channel_id, @@ -852,7 +855,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) peer_write(state->pps, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &state->channel->eltoo_keyset.self_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->eltoo_keyset.self_next_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -867,7 +870,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, &state->our_settlement_pubkey, - &state->channel->eltoo_keyset.self_next_nonce, + &state->eltoo_keyset.self_next_nonce, accept_tlvs); peer_write(state->pps, take(msg)); @@ -885,7 +888,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->funding.txid, &funding_txout, &their_update_psig, - &state->channel->eltoo_keyset.other_next_nonce)) + &state->eltoo_keyset.other_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); /* We only allow 16 bits for this on the wire. */ @@ -1005,10 +1008,10 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) update_tx, settle_tx, &state->their_funding_pubkey, - &state->channel->eltoo_keyset.other_next_nonce); + &state->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->channel->eltoo_keyset.session, &state->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -1017,10 +1020,10 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->channel_id, &our_update_psig, &their_update_psig, - &state->channel->eltoo_keyset.session, + &state->eltoo_keyset.session, update_tx, settle_tx, - &state->channel->eltoo_keyset.inner_pubkey); + &state->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { @@ -1030,7 +1033,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ - msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &state->channel->eltoo_keyset.self_next_nonce); + msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &state->eltoo_keyset.self_next_nonce); return towire_openingd_eltoo_fundee(state, &state->remoteconf, From a1bd0802ebd2176f3d50c8d2a4a8d81ffb570071 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 15:54:26 -0400 Subject: [PATCH 148/283] keyset shenanigans for opening --- openingd/eltoo_openingd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index be84aabc3258..961881e8bb64 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -70,7 +70,8 @@ struct eltoo_state { struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; - /* This seems necesssary for opening... move all keys here? */ + /* FIXME This seems necesssary for opening... move all keys here? + also need to "forward" the nonce for normal channel operation */ struct eltoo_keyset eltoo_keyset; /* Initially temporary, then final channel id. */ From a8e78fcd3280105dcd22a780ec6a01d4601db83d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 15:56:18 -0400 Subject: [PATCH 149/283] stop sending hsmd messages to peers... --- openingd/eltoo_openingd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 961881e8bb64..cf8f695d152c 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -853,7 +853,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* Fetch MuSig nonce for channel since we have none yet */ msg = towire_hsmd_gen_nonce(NULL, &state->channel_id); - peer_write(state->pps, take(msg)); + wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_gen_nonce_reply(msg, &state->eltoo_keyset.self_next_nonce)) { From 44d4f6115e61538f3e7da6ec61a6095403035faf Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 16:06:43 -0400 Subject: [PATCH 150/283] Send eltoo funder_complte msg if appropr --- lightningd/opening_control.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 0a543bf7c673..faadebd7dd96 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1104,6 +1104,7 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, struct wally_psbt *funding_psbt; u32 *funding_txout_num = NULL; struct funding_channel *fc; + bool eltoo; if (!param(cmd, buffer, params, p_req("id", param_node_id, &id), @@ -1172,10 +1173,22 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, /* Set the cmd to this new cmd */ peer->uncommitted_channel->fc->cmd = cmd; - msg = towire_openingd_funder_complete(NULL, - funding_txid, - *funding_txout_num, - peer->uncommitted_channel->fc->channel_type); + + eltoo = feature_negotiated(cmd->ld->our_features, + peer->their_features, + OPT_ELTOO); + + if (eltoo) { + msg = towire_openingd_eltoo_funder_complete(NULL, + funding_txid, + *funding_txout_num, + peer->uncommitted_channel->fc->channel_type); + } else { + msg = towire_openingd_funder_complete(NULL, + funding_txid, + *funding_txout_num, + peer->uncommitted_channel->fc->channel_type); + } subd_send_msg(peer->uncommitted_channel->open_daemon, take(msg)); return command_still_pending(cmd); } From 59fee253ee6c9ec7b212f897c7368dd3afd3fc0e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 16:28:53 -0400 Subject: [PATCH 151/283] more bullish errors --- openingd/eltoo_openingd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index cf8f695d152c..1a061ee03781 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -423,6 +423,12 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) return NULL; } + /* Should match what we offered if they accepted FIXME put this in bounds check? */ + if (state->remoteconf.shared_delay != state->localconf.shared_delay) { + negotiation_failed(state, "%s", err_reason); + return NULL; + } + funding_output_script = scriptpubkey_eltoo_funding(tmpctx, &state->our_funding_pubkey, &state->their_funding_pubkey); @@ -835,6 +841,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) return NULL; } + /* If we like shared_delay of opener, accept terms by matching */ + state->localconf.shared_delay = state->remoteconf.shared_delay; + if (!state->upfront_shutdown_script[LOCAL]) state->upfront_shutdown_script[LOCAL] = no_upfront_shutdown_script(state, From fc746363897235c01c91077949fd91f76fb55296 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 16:37:08 -0400 Subject: [PATCH 152/283] workshop delays in config --- lightningd/opening_common.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index bd2bc7af7560..35ad65420b20 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -173,7 +173,7 @@ void eltoo_channel_config(struct lightningd *ld, struct amount_msat *min_effective_htlc_capacity) { /* FIXME: depend on feerate. */ - *max_shared_delay = 60; + *max_shared_delay = ld->config.locktime_max; /* Take minimal effective capacity from config min_capacity_sat */ if (!amount_sat_to_msat(min_effective_htlc_capacity, @@ -196,14 +196,8 @@ void eltoo_channel_config(struct lightningd *ld, /* Don't care */ ours->htlc_minimum = ld->config.htlc_minimum_msat; - /* BOLT #2: - * - * The sending node SHOULD: - * - set `to_self_delay` sufficient to ensure the sender can - * irreversibly spend a commitment transaction output, in case of - * misbehavior by the receiver. - */ - ours->to_self_delay = ld->config.locktime_blocks; + /* FIXME better voodoo based on TODO BOLT description */ + ours->shared_delay = ld->config.locktime_blocks; ours->max_accepted_htlcs = ld->config.max_concurrent_htlcs; From 27973c19637572632029ce76cc3c37edaa7d6d58 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Sep 2022 16:45:44 -0400 Subject: [PATCH 153/283] enable printing of partial sigs --- bitcoin/signature.c | 7 +++++++ bitcoin/signature.h | 1 + 2 files changed, 8 insertions(+) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 9aecf19073a3..84986ba55aa0 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -711,6 +711,13 @@ void fromwire_partial_sig(const u8 **cursor, size_t *max, } } +char *fmt_partial_sig(const tal_t *ctx, const struct partial_sig *psig) +{ + return tal_hexstr(ctx, psig->p_sig.data, sizeof(psig->p_sig.data)); +} + +REGISTER_TYPE_TO_HEXSTR(partial_sig); + void towire_musig_session(u8 **pptr, const struct musig_session *session) { /* No proper serialization/parsing supplied, we're just copying bytes */ diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 86842a65c714..0aaae1046642 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -325,6 +325,7 @@ void fromwire_musig_session(const u8 **cursor, size_t *max, /* Get a hex string sig */ char *fmt_signature(const tal_t *ctx, const secp256k1_ecdsa_signature *sig); char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig); +char *fmt_partial_sig(const tal_t *ctx, const struct partial_sig *psig); /* For caller convenience, we hand in tag in parts (any can be "") */ void bip340_sighash_init(struct sha256_ctx *sctx, From 68a24bb4bda83f10be8674ef33efbb74fa982b32 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 6 Sep 2022 14:59:20 -0400 Subject: [PATCH 154/283] nice bug --- connectd/multiplex.c | 8 ++++++-- contrib/startup_regtest.sh | 2 +- lightningd/opening_control.c | 4 ++++ openingd/eltoo_openingd.c | 12 ++++++++++++ wire/peer_wire.c | 2 +- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/connectd/multiplex.c b/connectd/multiplex.c index 876d24ac039b..c8a1b2335bc5 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -496,6 +496,7 @@ static struct subd *activate_subd(struct peer *peer, take(towire_connectd_peer_active(NULL, &peer->id, tp, channel_id))); + daemon_conn_send_fd(peer->daemon->master, fd_for_subd); return subd; } @@ -789,6 +790,7 @@ static bool extract_funding_created_funding(const u8 *funding_created, switch (t) { case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_CREATED_ELTOO: /* BOLT #2: * 1. type: 34 (`funding_created`) * 2. data: @@ -844,6 +846,7 @@ static void maybe_update_channelid(struct subd *subd, const u8 *msg) { switch (fromwire_peektype(msg)) { case WIRE_OPEN_CHANNEL: + case WIRE_OPEN_CHANNEL_ELTOO: extract_channel_id(msg, &subd->channel_id); break; case WIRE_OPEN_CHANNEL2: @@ -854,6 +857,7 @@ static void maybe_update_channelid(struct subd *subd, const u8 *msg) update_v2_channelid(subd, msg); break; case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_CREATED_ELTOO: update_v1_channelid(subd, msg); break; } @@ -1042,8 +1046,8 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, subd = find_subd(peer, &channel_id); if (!subd) { enum peer_wire t = fromwire_peektype(decrypted); - status_peer_debug(&peer->id, "Activating for message %s", - peer_wire_name(t)); + status_peer_debug(&peer->id, "Activating for message %s, channel %s", + peer_wire_name(t), type_to_string(subd, struct channel_id, &channel_id)); subd = activate_subd(peer, &t, &channel_id); if (!subd) return io_close(peer_conn); diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index cd997db5dbbd..d68beb722b15 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_openingd" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & # "--dev-debugger=eltoo_openingd" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index faadebd7dd96..f43e10b7bfdd 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1,3 +1,4 @@ +#include #include "config.h" #include #include @@ -1407,6 +1408,9 @@ static struct command_result *json_fundchannel_start(struct command *cmd, subd_send_msg(peer->ld->connectd, take(towire_connectd_peer_make_active(NULL, &peer->id, &tmp_channel_id))); + printf("telling connectd about a channel: %s\n", + type_to_string(peer->ld->connectd, struct channel_id, &tmp_channel_id)); + return command_still_pending(cmd); } diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 1a061ee03781..4af58297d790 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -335,6 +335,9 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) "Failed to get nonce for channel: %s", tal_hex(msg, msg)); } + status_debug("temp channel_id being sent during open_channel: %s", + type_to_string(tmpctx, struct channel_id, &state->channel_id)); + msg = towire_open_channel_eltoo(NULL, &chainparams->genesis_blockhash, &state->channel_id, @@ -386,6 +389,9 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) } set_remote_upfront_shutdown(state, accept_tlvs->upfront_shutdown_script); + status_debug("temp channel_id being accepted during accept_channel: %s", + type_to_string(tmpctx, struct channel_id, &state->channel_id)); + /* BOLT #2: * - if `channel_type` is set, and `channel_type` was set in * `open_channel`, and they are not equal types: @@ -755,6 +761,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) "Parsing open_channel %s", tal_hex(tmpctx, open_channel_msg)); set_remote_upfront_shutdown(state, open_tlvs->upfront_shutdown_script); + status_debug("temp channel_id being received during open_channel: %s", + type_to_string(tmpctx, struct channel_id, &state->channel_id)); + /* BOLT #2: * The receiving node MUST fail the channel if: *... @@ -871,6 +880,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) "Failed to get nonce for channel: %s", tal_hex(msg, msg)); } + status_debug("temp channel_id being sent during accept channel: %s", + type_to_string(tmpctx, struct channel_id, &state->channel_id)); + msg = towire_accept_channel_eltoo(NULL, &state->channel_id, state->localconf.dust_limit, state->localconf.max_htlc_value_in_flight, diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 507a041fd088..7f672a9bd4b5 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -281,6 +281,7 @@ bool extract_channel_id(const u8 *in_pkt, struct channel_id *channel_id) */ /* Skip over chain_hash */ + case WIRE_OPEN_CHANNEL_ELTOO: fromwire_pad(&cursor, &max, sizeof(struct bitcoin_blkid)); /* These have them at the start */ @@ -439,7 +440,6 @@ bool extract_channel_id(const u8 *in_pkt, struct channel_id *channel_id) case WIRE_YIELD: /* FIXME add BOLT text here */ /* Eltoo stuff */ - case WIRE_OPEN_CHANNEL_ELTOO: case WIRE_ACCEPT_CHANNEL_ELTOO: case WIRE_FUNDING_CREATED_ELTOO: case WIRE_FUNDING_LOCKED_ELTOO: From 4fc3a7d9c3661919f5ccac2ed065fab5735b32d0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 6 Sep 2022 17:10:14 -0400 Subject: [PATCH 155/283] save progress --- bitcoin/pubkey.c | 12 +++++++ bitcoin/signature.c | 4 ++- channeld/eltoo_channeld.c | 4 +-- hsmd/hsmd_wire.csv | 1 + hsmd/libhsmd.c | 7 ++-- lightningd/opening_control.c | 2 -- openingd/eltoo_openingd.c | 64 +++++++++++++++++++++++++++++++----- 7 files changed, 78 insertions(+), 16 deletions(-) diff --git a/bitcoin/pubkey.c b/bitcoin/pubkey.c index e5dd11333641..5132757449a1 100644 --- a/bitcoin/pubkey.c +++ b/bitcoin/pubkey.c @@ -185,3 +185,15 @@ static char *point32_to_hexstr(const tal_t *ctx, const struct point32 *point32) return tal_hexstr(ctx, output, sizeof(output)); } REGISTER_TYPE_TO_STRING(point32, point32_to_hexstr); + +static char *nonce_to_hexstr(const tal_t *ctx, const struct nonce *nonce) +{ + u8 nonce_output[66]; + + secp256k1_musig_pubnonce_serialize(secp256k1_ctx, + nonce_output, + &nonce->nonce); + + return tal_hexstr(ctx, nonce_output, sizeof(nonce_output)); +} +REGISTER_TYPE_TO_STRING(nonce, nonce_to_hexstr); diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 84986ba55aa0..b4d0c5e30a39 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -12,6 +12,8 @@ #include #include +#include + #ifndef SUPERVERBOSE #define SUPERVERBOSE(...) #endif @@ -337,7 +339,7 @@ bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * co return false; } - return secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &xonly_inner_pubkey); + return secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &xonly_inner_pubkey); } void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 01774597cd23..a6c4138c7a28 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -841,7 +841,7 @@ static void send_update(struct eltoo_peer *peer) &peer->channel->eltoo_keyset.other_next_nonce); hsmd_msg = hsm_req(tmpctx, take(msg)); - if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Reading psign_update_tx reply: %s", tal_hex(tmpctx, msg)); @@ -1055,7 +1055,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 6f5dfe6fc1cd..6894f18023fb 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -324,6 +324,7 @@ msgtype,hsmd_psign_update_tx_reply,162 msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, msgdata,hsmd_psign_update_tx_reply,session,musig_session, msgdata,hsmd_psign_update_tx_reply,next_nonce,nonce, +msgdata,hsmd_psign_update_tx_reply,inner_pubkey,pubkey, msgtype,hsmd_validate_update_tx_psig,163 msgdata,hsmd_validate_update_tx_psig,channel_id,channel_id, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index d16fbc5256fb..5d7a43a5f0d1 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1401,6 +1401,7 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) annex = make_eltoo_annex(tmpctx, settle_tx); bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &hash_out); + if (!bipmusig_partial_sigs_combine_verify(p_sig_ptrs, /* num_signers */ 2, &inner_pubkey, @@ -1430,7 +1431,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) struct musig_session session; /* MuSig stuff */ - struct pubkey dummy_inner_pubkey; /* only cache needed for signing */ + struct pubkey inner_pubkey; secp256k1_musig_keyagg_cache keyagg_cache; const struct pubkey *pubkey_ptrs[2]; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; @@ -1466,7 +1467,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) annex = make_eltoo_annex(tmpctx, settle_tx); pubkey_ptrs[0] = &remote_funding_pubkey; pubkey_ptrs[1] = &local_funding_pubkey; - bipmusig_inner_pubkey(&dummy_inner_pubkey, + bipmusig_inner_pubkey(&inner_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2); @@ -1494,7 +1495,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) &keyagg_cache, hash_out.sha.u.u8); - return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &secretstuff.pub_nonce); + return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &secretstuff.pub_nonce, &inner_pubkey); } diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index f43e10b7bfdd..38d5861eb5d0 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1408,8 +1408,6 @@ static struct command_result *json_fundchannel_start(struct command *cmd, subd_send_msg(peer->ld->connectd, take(towire_connectd_peer_make_active(NULL, &peer->id, &tmp_channel_id))); - printf("telling connectd about a channel: %s\n", - type_to_string(peer->ld->connectd, struct channel_id, &tmp_channel_id)); return command_still_pending(cmd); } diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 4af58297d790..6573d094e6c4 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -561,18 +561,38 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->their_funding_pubkey, &state->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); + + status_debug("partial signature req on tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", + type_to_string(tmpctx, struct bitcoin_tx, *update_tx), + type_to_string(tmpctx, struct pubkey, + &state->our_funding_pubkey), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.other_next_nonce)); + msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce, &state->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* You can tell this has been a problem before, since there's a debug * message here: */ - status_debug("signature %s on tx %s using key %s", + status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", type_to_string(tmpctx, struct partial_sig, &our_update_psig), type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct pubkey, - &state->our_funding_pubkey)); + &state->our_funding_pubkey), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + type_to_string(tmpctx, struct pubkey, + &state->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.other_next_nonce)); /* Now we give our peer the partial signature for the first update * transaction. */ @@ -729,6 +749,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct partial_sig our_update_psig, their_update_psig; + /* These never leave openingd, keep local */ + struct nonce their_opening_nonce, our_opening_nonce; /* Dummy fields since they're unused at time of channel creation */ struct partial_sig dummy_self_psig, dummy_other_psig; @@ -754,7 +776,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->their_funding_pubkey, &state->their_settlement_pubkey, &channel_flags, - &state->eltoo_keyset.other_next_nonce, + &their_opening_nonce, &open_tlvs)) peer_failed_err(state->pps, &state->channel_id, @@ -874,7 +896,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &state->eltoo_keyset.self_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &our_opening_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -892,7 +914,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, &state->our_settlement_pubkey, - &state->eltoo_keyset.self_next_nonce, + &our_opening_nonce, accept_tlvs); peer_write(state->pps, take(msg)); @@ -904,7 +926,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) if (!msg) return NULL; - /* The message should be "funding_created" which tells us what funding + /* The message should be "funding_created_eltoo" which tells us what funding * tx they generated; the sighash type is implied, so we set it here. */ if (!fromwire_funding_created_eltoo(msg, &id_in, &state->funding.txid, @@ -1032,11 +1054,37 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->their_funding_pubkey, &state->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); + + status_debug("partial signature req on tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", + type_to_string(tmpctx, struct bitcoin_tx, update_tx), + type_to_string(tmpctx, struct pubkey, + &state->our_funding_pubkey), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.other_next_nonce)); + msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce, &state->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); + status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", + type_to_string(tmpctx, struct partial_sig, &our_update_psig), + type_to_string(tmpctx, struct bitcoin_tx, update_tx), + type_to_string(tmpctx, struct pubkey, + &state->our_funding_pubkey), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + type_to_string(tmpctx, struct pubkey, + &state->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &state->eltoo_keyset.other_next_nonce)); + /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ msg = towire_hsmd_combine_psig(NULL, &state->channel_id, From 626928103dc2d6e17109e662f6974d688a6241f3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 6 Sep 2022 17:29:39 -0400 Subject: [PATCH 156/283] Nonces working --- lightningd/opening_control.c | 1 + openingd/eltoo_openingd.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 38d5861eb5d0..9d4715acaff2 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -543,6 +543,7 @@ static void opening_fundee_finished(struct subd *openingd, channel_info.their_config.id = 0; peer_fd = new_peer_fd_arr(tmpctx, fds); + /* FIXME we need switching behavior for this message wrt eltoo */ if (!fromwire_openingd_fundee(tmpctx, reply, &channel_info.their_config, &remote_commit, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 6573d094e6c4..d56a56d34c0e 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -749,7 +749,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct partial_sig our_update_psig, their_update_psig; - /* These never leave openingd, keep local */ + /* These never leave openingd, keep local. funding_* nonces go in keyset and propagated + * to eltoo_channeld! */ struct nonce their_opening_nonce, our_opening_nonce; /* Dummy fields since they're unused at time of channel creation */ @@ -1039,7 +1040,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* BOLT #2: * - * ### The `funding_signed` Message + * ### The `funding_signed_eltoo` Message * * This message gives the funder the signature it needs for the first * commitment transaction, so it can broadcast the transaction knowing @@ -1052,7 +1053,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) update_tx, settle_tx, &state->their_funding_pubkey, - &state->eltoo_keyset.other_next_nonce); + &their_opening_nonce); wire_sync_write(HSM_FD, take(msg)); status_debug("partial signature req on tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", @@ -1062,11 +1063,12 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) type_to_string(tmpctx, struct pubkey, &state->their_funding_pubkey), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.self_next_nonce), + &our_opening_nonce), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.other_next_nonce)); + &their_opening_nonce)); msg = wire_sync_read(tmpctx, HSM_FD); + /* Reply puts next nonce into keyset and xmitted with funding_signed_eltoo */ if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce, &state->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); From a18027d2423300a2022420645db93ca1b6e85dc5 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 09:23:41 -0400 Subject: [PATCH 157/283] Maybe will fire off normal channel operation --- lightningd/opening_control.c | 99 ++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 9d4715acaff2..1d1f83f3cb50 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -515,6 +515,99 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, tal_free(fc->uc); } +static void opening_eltoo_fundee_finished(struct subd *openingd, + const u8 *reply, + const int *fds, + struct uncommitted_channel *uc) +{ + const u8 *fwd_msg; + struct channel_info channel_info; + struct bip340sig first_update_sig; + struct bitcoin_tx *settle_tx; + struct channel_id cid; + struct lightningd *ld = openingd->ld; + struct bitcoin_outpoint funding; + struct amount_sat funding_sats; + struct amount_msat push; + u8 channel_flags; + struct channel *channel; + u8 *remote_upfront_shutdown_script, *local_upfront_shutdown_script; + struct peer_fd *peer_fd; + struct channel_type *type; + + log_debug(uc->log, "Got opening_eltoo_fundee_finish_response"); + + /* This is a new channel_info.their_config, set its ID to 0 */ + channel_info.their_config.id = 0; + + peer_fd = new_peer_fd_arr(tmpctx, fds); + + /* FIXME is this really the right fields to send? */ + if (!fromwire_openingd_eltoo_fundee(tmpctx, reply, + &channel_info.their_config, + &settle_tx, + &first_update_sig, + &channel_info.remote_fundingkey, + &funding, + &funding_sats, + &push, + &channel_flags, + cast_const2(u8 **, &fwd_msg), + &local_upfront_shutdown_script, + &remote_upfront_shutdown_script, + &type)) { + log_broken(uc->log, "bad OPENING_ELTOO_FUNDEE_REPLY %s", + tal_hex(reply, reply)); + uncommitted_channel_disconnect(uc, LOG_BROKEN, + "bad OPENING_ELTOO_FUNDEE_REPLY"); + goto failed; + } + + settle_tx->chainparams = chainparams; + + derive_channel_id(&cid, &funding); + + /* Consumes uc */ + channel = wallet_commit_channel(ld, uc, + &cid, + settle_tx, + NULL /* remote_commit_sig */, + &funding, + funding_sats, + push, + channel_flags, + &channel_info, + 0 /* feerate */, + local_upfront_shutdown_script, + remote_upfront_shutdown_script, + type, + &first_update_sig); + if (!channel) { + uncommitted_channel_disconnect(uc, LOG_BROKEN, + "Commit channel failed"); + goto failed; + } + + log_debug(channel->log, "Watching funding tx %s", + type_to_string(reply, struct bitcoin_txid, + &channel->funding.txid)); + + channel_watch_funding(ld, channel); + + /* Tell plugins about the success */ + notify_channel_opened(ld, &channel->peer->id, &channel->funding_sats, + &channel->funding.txid, &channel->remote_funding_locked); + + /* On to normal operation! */ + peer_start_channeld(channel, peer_fd, fwd_msg, false, NULL); + + tal_free(uc); + return; + +failed: + tal_free(uc); +} + static void opening_fundee_finished(struct subd *openingd, const u8 *reply, const int *fds, @@ -543,8 +636,8 @@ static void opening_fundee_finished(struct subd *openingd, channel_info.their_config.id = 0; peer_fd = new_peer_fd_arr(tmpctx, fds); - /* FIXME we need switching behavior for this message wrt eltoo */ - if (!fromwire_openingd_fundee(tmpctx, reply, + + if (!fromwire_openingd_fundee(tmpctx, reply, &channel_info.their_config, &remote_commit, &pbase, @@ -922,7 +1015,7 @@ static unsigned int eltoo_openingd_msg(struct subd *openingd, case WIRE_OPENINGD_ELTOO_FUNDEE: if (tal_count(fds) != 1) return 1; - opening_fundee_finished(openingd, msg, fds, uc); + opening_eltoo_fundee_finished(openingd, msg, fds, uc); return 0; case WIRE_OPENINGD_ELTOO_GOT_OFFER: From 4a26071fa5482d08c490ed1c9cd910138b9f5565 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 09:26:25 -0400 Subject: [PATCH 158/283] failing at channeld creation :) --- lightningd/channel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 709e93a4b8d6..40b89f072c3f 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -448,8 +448,11 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->last_tx = tal_steal(channel, last_tx); channel->last_tx->chainparams = chainparams; channel->last_tx_type = TX_UNKNOWN; - channel->last_sig = *last_sig; - channel->last_update_sig = *last_update_sig; + if (last_sig) { + channel->last_sig = *last_sig; + } else { + channel->last_update_sig = *last_update_sig; + } channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs); channel->channel_info = *channel_info; channel->fee_states = dup_fee_states(channel, fee_states); From ed8ffb59f7ff3aa0c0cfa740c940f0c49794f174 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 10:17:59 -0400 Subject: [PATCH 159/283] maybe eltoo_channeld starts --- lightningd/channel.h | 5 ++ lightningd/channel_control.c | 153 +++++++++++++++++++++++++++++++++++ lightningd/channel_control.h | 6 ++ 3 files changed, 164 insertions(+) diff --git a/lightningd/channel.h b/lightningd/channel.h index 2414657b1b1b..0ae6349d61ee 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -148,6 +148,8 @@ struct channel { enum wallet_tx_type last_tx_type; struct bitcoin_signature last_sig; struct bip340sig last_update_sig; /* Eltoo only */ + struct partial_sig their_last_psig, our_last_psig; + struct musig_session session; const struct bitcoin_signature *last_htlc_sigs; /* Keys for channel */ @@ -165,6 +167,9 @@ struct channel { /* Our funding tx pubkey. */ struct pubkey local_funding_pubkey; + /* Our settle tx pubkey */ + struct pubkey local_settle_pubkey; + /* scriptpubkey for shutdown, if applicable. */ const u8 *shutdown_scriptpubkey[NUM_SIDES]; /* Address for any final outputs */ diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index d59a9c6c062d..daf42477c207 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -597,6 +597,159 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) return 0; } +void peer_start_eltoo_channeld(struct channel *channel, + struct peer_fd *peer_fd, + const u8 *fwd_msg, + bool reconnected, + bool reestablish_only) +{ + u8 *initmsg; + int hsmfd; + const struct existing_htlc **htlcs; + struct short_channel_id scid; + struct lightningd *ld = channel->peer->ld; + const struct config *cfg = &ld->config; + bool reached_announce_depth; + secp256k1_ecdsa_signature *remote_ann_node_sig, *remote_ann_bitcoin_sig; + + hsmfd = hsm_get_client_fd(ld, &channel->peer->id, + channel->dbid, + HSM_CAP_SIGN_GOSSIP + | HSM_CAP_ECDH + | HSM_CAP_COMMITMENT_POINT + | HSM_CAP_SIGN_REMOTE_TX + | HSM_CAP_SIGN_ONCHAIN_TX); + + channel_set_owner(channel, + new_channel_subd(channel, ld, + "lightning_eltoo_channeld", + channel, + &channel->peer->id, + channel->log, true, + channeld_wire_name, + channel_msg, + channel_errmsg, + channel_set_billboard, + take(&peer_fd->fd), + take(&hsmfd), NULL)); + + if (!channel->owner) { + log_broken(channel->log, "Could not subdaemon channel: %s", + strerror(errno)); + channel_fail_reconnect_later(channel, + "Failed to subdaemon channel"); + return; + } + + htlcs = peer_htlcs(tmpctx, channel); + + if (channel->scid) { + scid = *channel->scid; + reached_announce_depth + = is_scid_depth_announceable(&scid, + get_block_height(ld->topology)); + log_debug(channel->log, "Already have funding locked in%s", + reached_announce_depth + ? " (and ready to announce)" : ""); + } else { + log_debug(channel->log, "Waiting for funding confirmations"); + memset(&scid, 0, sizeof(scid)); + reached_announce_depth = false; + } + + /* Warn once. */ + if (ld->config.ignore_fee_limits) + log_debug(channel->log, "Ignoring fee limits!"); + + if (!wallet_remote_ann_sigs_load(tmpctx, channel->peer->ld->wallet, + channel->dbid, + &remote_ann_node_sig, + &remote_ann_bitcoin_sig)) { + channel_internal_error(channel, + "Could not load remote announcement" + " signatures"); + return; + } + + struct ext_key final_ext_key; + if (bip32_key_from_parent( + ld->wallet->bip32_base, + channel->final_key_idx, + BIP32_FLAG_KEY_PUBLIC, + &final_ext_key) != WALLY_OK) { + channel_internal_error(channel, + "Could not derive final_ext_key %"PRIu64, + channel->final_key_idx); + return; + } + + initmsg = towire_channeld_init_eltoo(tmpctx, + chainparams, + ld->our_features, + &channel->cid, + &channel->funding, + channel->funding_sats, + channel->minimum_depth, + &channel->our_config, + &channel->channel_info.their_config, + &channel->their_last_psig, + &channel->our_last_psig, + &channel->session, + &channel->channel_info.remote_fundingkey, + &channel->channel_info.remote_settlekey, + channel->opener, + channel->feerate_base, + channel->feerate_ppm, + channel->htlc_minimum_msat, + channel->htlc_maximum_msat, + channel->our_msat, + &channel->local_funding_pubkey, + &channel->local_settle_pubkey, + &ld->id, + &channel->peer->id, + cfg->commit_time_ms, + cfg->cltv_expiry_delta, + channel->next_index[LOCAL], + 0 /* updates_received FIXME is this even necessary? locktime has this */, + channel->next_htlc_id, + htlcs, + channel->scid != NULL, + channel->remote_funding_locked, + &scid, + reconnected, + /* Anything that indicates we are or have + * shut down */ + channel->state == CHANNELD_SHUTTING_DOWN + || channel->state == CLOSINGD_SIGEXCHANGE + || channel_closed(channel), + channel->shutdown_scriptpubkey[REMOTE] != NULL, + channel->final_key_idx, + &final_ext_key, + channel->shutdown_scriptpubkey[LOCAL], + channel->channel_flags, + fwd_msg, + reached_announce_depth, + channel->peer->their_features, + channel->remote_upfront_shutdown_script, + remote_ann_node_sig, + remote_ann_bitcoin_sig, + channel->type, + IFDEV(ld->dev_fast_gossip, false), + IFDEV(dev_fail_process_onionpacket, false), + IFDEV(ld->dev_disable_commit == -1 + ? NULL + : (u32 *)&ld->dev_disable_commit, + NULL), + reestablish_only, + channel->channel_update); + + /* We don't expect a response: we are triggered by funding_depth_cb. */ + subd_send_msg(channel->owner, take(initmsg)); + + /* No fee updates (or blockheights) for eltoo channels */ +} + + void peer_start_channeld(struct channel *channel, struct peer_fd *peer_fd, const u8 *fwd_msg, diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index 365e87655e2c..3239339b9698 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -10,6 +10,12 @@ struct lightningd; struct peer_fd; struct peer; +void peer_start_eltoo_channeld(struct channel *channel, + struct peer_fd *peer_fd, + const u8 *fwd_msg, + bool reconnected, + bool reestablish_only); + void peer_start_channeld(struct channel *channel, struct peer_fd *peer_fd, const u8 *fwd_msg, From f009304cf43baff5291d182fb8c3ff4207ddb918 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 10:33:51 -0400 Subject: [PATCH 160/283] more settle key stuff --- lightningd/channel.c | 2 ++ lightningd/channel.h | 1 + lightningd/opening_control.c | 7 +++---- wallet/test/run-wallet.c | 2 +- wallet/wallet.c | 5 +++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 40b89f072c3f..3f9ccb1a4584 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -379,6 +379,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, bool connected, const struct basepoints *local_basepoints, const struct pubkey *local_funding_pubkey, + const struct pubkey *local_settle_pubkey, const struct pubkey *future_per_commitment_point, u32 feerate_base, u32 feerate_ppm, @@ -480,6 +481,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->connected = connected; channel->local_basepoints = *local_basepoints; channel->local_funding_pubkey = *local_funding_pubkey; + channel->local_settle_pubkey = *local_settle_pubkey; channel->future_per_commitment_point = tal_steal(channel, future_per_commitment_point); channel->feerate_base = feerate_base; diff --git a/lightningd/channel.h b/lightningd/channel.h index 0ae6349d61ee..a4c57b0a1a28 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -307,6 +307,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, bool connected, const struct basepoints *local_basepoints, const struct pubkey *local_funding_pubkey, + const struct pubkey *local_settle_pubkey, const struct pubkey *future_per_commitment_point, u32 feerate_base, u32 feerate_ppm, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 1d1f83f3cb50..b488eb0c302b 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -202,6 +202,7 @@ wallet_commit_channel(struct lightningd *ld, true, &uc->local_basepoints, &uc->local_funding_pubkey, + &uc->local_settle_pubkey, NULL, ld->config.fee_base, ld->config.fee_per_satoshi, @@ -344,7 +345,6 @@ static void opening_funder_start_replied(struct subd *openingd, const u8 *resp, tal_free(fc->uc); } -/* FIXME all this needs changing */ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, const int *fds, struct funding_channel *fc) @@ -413,8 +413,7 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, channel_watch_funding(ld, channel); funding_success(channel); - /* FIXME Start eltoo_channeld instead */ - peer_start_channeld(channel, peer_fd, NULL, false, NULL); + peer_start_eltoo_channeld(channel, peer_fd, NULL, false /* reconnected */, false /* reestablish_only */); cleanup: /* Frees fc too */ @@ -599,7 +598,7 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, &channel->funding.txid, &channel->remote_funding_locked); /* On to normal operation! */ - peer_start_channeld(channel, peer_fd, fwd_msg, false, NULL); + peer_start_eltoo_channeld(channel, peer_fd, fwd_msg, false /* reconnected */, false /* reestablish_only */); tal_free(uc); return; diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index bf1e75743eee..c4c1babd137b 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1611,7 +1611,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) 10000, /* max_possible_feerate */ false, &basepoints, - &pk, NULL, + &pk, NULL /* local_settle_pubkey */, NULL, 1000, 100, NULL, 0, 0, channel_type_static_remotekey(NULL), LOCAL, REASON_UNKNOWN, diff --git a/wallet/wallet.c b/wallet/wallet.c index 7a49cb807a9d..af8a570b6441 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1260,7 +1260,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm struct changed_htlc *last_sent_commit; s64 final_key_idx, channel_config_id; struct basepoints local_basepoints; - struct pubkey local_funding_pubkey; + struct pubkey local_funding_pubkey, local_settle_pubkey; struct pubkey *future_per_commitment_point; struct amount_sat funding_sat, our_funding_sat; struct amount_msat push_msat, our_msat, msat_to_us_min, msat_to_us_max, htlc_minimum_msat, htlc_maximum_msat; @@ -1386,6 +1386,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_col_pubkey(stmt, "delayed_payment_basepoint_local", &local_basepoints.delayed_payment); db_col_pubkey(stmt, "funding_pubkey_local", &local_funding_pubkey); + db_col_pubkey(stmt, "settle_pubkey_local", &local_settle_pubkey); if (db_col_is_null(stmt, "shutdown_wrong_txid")) { db_col_ignore(stmt, "shutdown_wrong_outnum"); shutdown_wrong_funding = NULL; @@ -1465,7 +1466,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_col_int(stmt, "max_possible_feerate"), /* Not connected */ false, - &local_basepoints, &local_funding_pubkey, + &local_basepoints, &local_funding_pubkey, &local_settle_pubkey, future_per_commitment_point, db_col_int(stmt, "feerate_base"), db_col_int(stmt, "feerate_ppm"), From 88dd3671aadccaac807cc706785b8eddc150032f Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 12:00:51 -0400 Subject: [PATCH 161/283] Thinking of removing settle_pubkey in favor or remote basepoint --- contrib/startup_regtest.sh | 2 +- lightningd/opening_control.c | 1 + lightningd/peer_control.c | 15 +++++++++---- lightningd/test/run-invoice-select-inchan.c | 10 ++++++++- openingd/eltoo_openingd.c | 1 + openingd/eltoo_openingd_wire.csv | 1 + wallet/db.c | 10 +++++++-- wallet/test/run-wallet.c | 9 +++++++- wallet/wallet.c | 24 ++++++++++++--------- 9 files changed, 54 insertions(+), 19 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index d68beb722b15..cd997db5dbbd 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & # "--dev-debugger=eltoo_openingd" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_openingd" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index b488eb0c302b..37745a120fb5 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -547,6 +547,7 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, &settle_tx, &first_update_sig, &channel_info.remote_fundingkey, + &channel_info.remote_settlekey, &funding, &funding_sats, &push, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index d66c59e04c88..7f6a47cf52a4 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1275,10 +1275,17 @@ void peer_active(struct lightningd *ld, const u8 *msg, int fd) case CHANNELD_SHUTTING_DOWN: case CLOSINGD_SIGEXCHANGE: assert(!channel->owner); - peer_start_channeld(channel, - peer_fd, - NULL, true, - NULL); + if (true /* FIXME track eltoo-ness of channels */) { + peer_start_eltoo_channeld(channel, + peer_fd, + NULL, true, + NULL); + } else { + peer_start_channeld(channel, + peer_fd, + NULL, true, + NULL); + } goto subd_setup_done; } abort(); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 0e1f67e8b2fd..81c6f043863f 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -608,9 +608,17 @@ void peer_start_channeld(struct channel *channel UNNEEDED, bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, struct channel *channel UNNEEDED) { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } +/* Generated stub for peer_start_eltoo_channeld */ +void peer_start_eltoo_channeld(struct channel *channel UNNEEDED, + struct peer_fd *peer_fd UNNEEDED, + const u8 *fwd_msg UNNEEDED, + bool reconnected UNNEEDED, + bool reestablish_only UNNEEDED) +{ fprintf(stderr, "peer_start_eltoo_channeld called!\n"); abort(); } /* Generated stub for peer_start_openingd */ bool peer_start_openingd(struct peer *peer UNNEEDED, - struct peer_fd *peer_fd UNNEEDED, bool eltoo) + struct peer_fd *peer_fd UNNEEDED, + bool eltoo UNNEEDED) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for plugin_hook_call_ */ bool plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook *hook UNNEEDED, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index d56a56d34c0e..6360644d7698 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -1112,6 +1112,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) update_tx, &update_sig, &state->their_funding_pubkey, + &state->their_settlement_pubkey, &state->funding, state->funding_sats, state->push_msat, diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index d545bd332c57..a7cbdc6c64f7 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -80,6 +80,7 @@ msgdata,openingd_eltoo_fundee,their_config,channel_config, msgdata,openingd_eltoo_fundee,first_settlement,bitcoin_tx, msgdata,openingd_eltoo_fundee,first_update_sig,bip340sig, msgdata,openingd_eltoo_fundee,remote_fundingkey,pubkey, +msgdata,openingd_eltoo_fundee,remote_settlekey,pubkey, msgdata,openingd_eltoo_fundee,funding,bitcoin_outpoint, msgdata,openingd_eltoo_fundee,funding_satoshis,amount_sat, msgdata,openingd_eltoo_fundee,push_msat,amount_msat, diff --git a/wallet/db.c b/wallet/db.c index c48c2c3a932d..0f76d03bfd5f 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -123,6 +123,7 @@ static struct migration dbmigrations[] = { " msatoshi_local BIGINT," /* our_msatoshi */ /* START channel_info */ " fundingkey_remote BLOB," + " settlekey_remote BLOB," " revocation_basepoint_remote BLOB," " payment_basepoint_remote BLOB," " htlc_basepoint_remote BLOB," @@ -1219,6 +1220,7 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, " c.id" ", p.node_id" ", c.fundingkey_remote" + ", c.settlekey_remote" ", inflight.last_tx" ", inflight.last_sig" ", inflight.funding_satoshi" @@ -1238,7 +1240,7 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, struct amount_sat funding_sat; struct node_id peer_id; struct pubkey local_funding_pubkey, remote_funding_pubkey; - struct pubkey local_settle_pubkey; + struct pubkey local_settle_pubkey, remote_settle_pubkey; struct basepoints local_basepoints UNUSED; struct bitcoin_signature last_sig; u64 cdb_id; @@ -1263,6 +1265,7 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, db_col_node_id(stmt, "p.node_id", &peer_id); db_col_amount_sat(stmt, "inflight.funding_satoshi", &funding_sat); db_col_pubkey(stmt, "c.fundingkey_remote", &remote_funding_pubkey); + db_col_pubkey(stmt, "c.settlekey_remote", &remote_settle_pubkey); db_col_txid(stmt, "inflight.funding_tx_id", &funding_txid); get_channel_basepoints(ld, &peer_id, cdb_id, @@ -1321,6 +1324,7 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, ", c.last_tx" ", c.funding_satoshi" ", c.fundingkey_remote" + ", c.settlekey_remote" ", c.last_sig" " FROM channels c" " LEFT OUTER JOIN peers p" @@ -1332,7 +1336,7 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, struct amount_sat funding_sat; struct node_id peer_id; struct pubkey local_funding_pubkey, remote_funding_pubkey; - struct pubkey local_settle_pubkey; + struct pubkey local_settle_pubkey, remote_settle_pubkey; struct basepoints local_basepoints UNUSED; struct bitcoin_signature last_sig; u64 cdb_id; @@ -1348,6 +1352,7 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, if (db_col_is_null(stmt, "p.node_id")) { db_col_ignore(stmt, "c.funding_satoshi"); db_col_ignore(stmt, "c.fundingkey_remote"); + db_col_ignore(stmt, "c.settlekey_remote"); db_col_ignore(stmt, "c.last_sig"); continue; } @@ -1355,6 +1360,7 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, db_col_node_id(stmt, "p.node_id", &peer_id); db_col_amount_sat(stmt, "c.funding_satoshi", &funding_sat); db_col_pubkey(stmt, "c.fundingkey_remote", &remote_funding_pubkey); + db_col_pubkey(stmt, "c.settlekey_remote", &remote_settle_pubkey); get_channel_basepoints(ld, &peer_id, cdb_id, &local_basepoints, &local_funding_pubkey, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index c4c1babd137b..735b3a16d040 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -648,10 +648,17 @@ void peer_start_channeld(struct channel *channel UNNEEDED, bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, struct channel *channel UNNEEDED) { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } +/* Generated stub for peer_start_eltoo_channeld */ +void peer_start_eltoo_channeld(struct channel *channel UNNEEDED, + struct peer_fd *peer_fd UNNEEDED, + const u8 *fwd_msg UNNEEDED, + bool reconnected UNNEEDED, + bool reestablish_only UNNEEDED) +{ fprintf(stderr, "peer_start_eltoo_channeld called!\n"); abort(); } /* Generated stub for peer_start_openingd */ bool peer_start_openingd(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, - bool eltoo) + bool eltoo UNNEEDED) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for peer_wire_name */ const char *peer_wire_name(int e UNNEEDED) diff --git a/wallet/wallet.c b/wallet/wallet.c index af8a570b6441..6b8575835f23 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1335,6 +1335,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm /* Populate channel_info */ db_col_pubkey(stmt, "fundingkey_remote", &channel_info.remote_fundingkey); + db_col_pubkey(stmt, "settlekey_remote", &channel_info.remote_settlekey); db_col_pubkey(stmt, "revocation_basepoint_remote", &channel_info.theirbase.revocation); db_col_pubkey(stmt, "payment_basepoint_remote", &channel_info.theirbase.payment); db_col_pubkey(stmt, "htlc_basepoint_remote", &channel_info.theirbase.htlc); @@ -1537,6 +1538,7 @@ static bool wallet_channels_load_active(struct wallet *w) ", push_msatoshi" ", msatoshi_local" ", fundingkey_remote" + ", settlekey_remote" ", revocation_basepoint_remote" ", payment_basepoint_remote" ", htlc_basepoint_remote" @@ -1933,6 +1935,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) wallet_channel_config_save(w, &chan->channel_info.their_config); stmt = db_prepare_v2(w->db, SQL("UPDATE channels SET" " fundingkey_remote=?," + " settlekey_remote=?," " revocation_basepoint_remote=?," " payment_basepoint_remote=?," " htlc_basepoint_remote=?," @@ -1943,18 +1946,19 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " future_per_commitment_point=?" " WHERE id=?")); db_bind_pubkey(stmt, 0, &chan->channel_info.remote_fundingkey); - db_bind_pubkey(stmt, 1, &chan->channel_info.theirbase.revocation); - db_bind_pubkey(stmt, 2, &chan->channel_info.theirbase.payment); - db_bind_pubkey(stmt, 3, &chan->channel_info.theirbase.htlc); - db_bind_pubkey(stmt, 4, &chan->channel_info.theirbase.delayed_payment); - db_bind_pubkey(stmt, 5, &chan->channel_info.remote_per_commit); - db_bind_pubkey(stmt, 6, &chan->channel_info.old_remote_per_commit); - db_bind_u64(stmt, 7, chan->channel_info.their_config.id); + db_bind_pubkey(stmt, 1, &chan->channel_info.remote_settlekey); + db_bind_pubkey(stmt, 2, &chan->channel_info.theirbase.revocation); + db_bind_pubkey(stmt, 3, &chan->channel_info.theirbase.payment); + db_bind_pubkey(stmt, 4, &chan->channel_info.theirbase.htlc); + db_bind_pubkey(stmt, 5, &chan->channel_info.theirbase.delayed_payment); + db_bind_pubkey(stmt, 6, &chan->channel_info.remote_per_commit); + db_bind_pubkey(stmt, 7, &chan->channel_info.old_remote_per_commit); + db_bind_u64(stmt, 8, chan->channel_info.their_config.id); if (chan->future_per_commitment_point) - db_bind_pubkey(stmt, 8, chan->future_per_commitment_point); + db_bind_pubkey(stmt, 9, chan->future_per_commitment_point); else - db_bind_null(stmt, 8); - db_bind_u64(stmt, 9, chan->dbid); + db_bind_null(stmt, 9); + db_bind_u64(stmt, 10, chan->dbid); db_exec_prepared_v2(take(stmt)); /* FIXME: Updates channel_feerates by discarding and rewriting. */ From 7389f80e11239c9b63b098c0f896319cea0ac3b6 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 12:34:32 -0400 Subject: [PATCH 162/283] Attempt to reuse payment basepoint as settle pubkey --- common/derive_basepoints.c | 8 -------- common/derive_basepoints.h | 5 +---- common/test/run-derive_basepoints.c | 18 +----------------- hsmd/hsmd_wire.csv | 1 - hsmd/libhsmd.c | 19 +++++++++---------- lightningd/channel.c | 11 +++-------- lightningd/channel.h | 7 +------ lightningd/channel_control.c | 2 +- lightningd/opening_common.c | 2 +- lightningd/opening_common.h | 3 --- lightningd/opening_control.c | 3 +-- wallet/db.c | 21 +++++---------------- wallet/test/run-db.c | 5 ++--- wallet/test/run-wallet.c | 6 ++---- wallet/wallet.c | 29 ++++++++++++----------------- 15 files changed, 39 insertions(+), 101 deletions(-) diff --git a/common/derive_basepoints.c b/common/derive_basepoints.c index 1154f3048bf6..c1a7cf22cf87 100644 --- a/common/derive_basepoints.c +++ b/common/derive_basepoints.c @@ -51,7 +51,6 @@ static void derive_keys(const struct secret *seed, struct keys *keys) #if DEVELOPER if (dev_force_channel_secrets) { keys->f = dev_force_channel_secrets->funding_privkey; - keys->s = dev_force_channel_secrets->settle_privkey; keys->r.secret = dev_force_channel_secrets->revocation_basepoint_secret; keys->p.secret = dev_force_channel_secrets->payment_basepoint_secret; keys->h.secret = dev_force_channel_secrets->htlc_basepoint_secret; @@ -64,7 +63,6 @@ static void derive_keys(const struct secret *seed, struct keys *keys) bool derive_basepoints(const struct secret *seed, struct pubkey *funding_pubkey, - struct pubkey *settle_pubkey, struct basepoints *basepoints, struct secrets *secrets, struct sha256 *shaseed) @@ -75,7 +73,6 @@ bool derive_basepoints(const struct secret *seed, if (secrets) { secrets->funding_privkey = keys.f; - secrets->settle_privkey = keys.s; secrets->revocation_basepoint_secret = keys.r.secret; secrets->payment_basepoint_secret = keys.p.secret; secrets->htlc_basepoint_secret = keys.h.secret; @@ -87,11 +84,6 @@ bool derive_basepoints(const struct secret *seed, return false; } - if (settle_pubkey) { - if (!pubkey_from_privkey(&keys.f, settle_pubkey)) - return false; - } - if (basepoints) { if (!pubkey_from_privkey(&keys.r, &basepoints->revocation) || !pubkey_from_privkey(&keys.p, &basepoints->payment) diff --git a/common/derive_basepoints.h b/common/derive_basepoints.h index a43af9301f10..fb5294d7afad 100644 --- a/common/derive_basepoints.h +++ b/common/derive_basepoints.h @@ -10,14 +10,13 @@ struct sha256; struct basepoints { struct pubkey revocation; - struct pubkey payment; + struct pubkey payment; /* re-used as "settlement pubkey" for eltoo */ struct pubkey htlc; struct pubkey delayed_payment; }; struct secrets { struct privkey funding_privkey; - struct privkey settle_privkey; struct secret revocation_basepoint_secret; struct secret payment_basepoint_secret; struct secret htlc_basepoint_secret; @@ -28,14 +27,12 @@ struct secrets { * derive_basepoints - given a (per-peer) seed, get the basepoints * @seed: (in) seed (derived by master daemon from counter and main seed) * @funding_pubkey: (out) pubkey for funding tx output (if non-NULL) - * @settle_pubkey: (out) pubkey used for settlement transactions (eltoo only) * @basepoints: (out) basepoints for channel (if non-NULL) * @secrets: (out) basepoints for channel (if non-NULL) * @shaseed: (out) seed for shachain (if non-NULL) */ bool derive_basepoints(const struct secret *seed, struct pubkey *funding_pubkey, - struct pubkey *settle_pubkey, struct basepoints *basepoints, struct secrets *secrets, struct sha256 *shaseed); diff --git a/common/test/run-derive_basepoints.c b/common/test/run-derive_basepoints.c index d0150e6ab1b9..e53b89754eac 100644 --- a/common/test/run-derive_basepoints.c +++ b/common/test/run-derive_basepoints.c @@ -109,7 +109,6 @@ STRUCTEQ_DEF(basepoints, 0, delayed_payment.pubkey); STRUCTEQ_DEF(secrets, 0, funding_privkey.secret.data, - settle_privkey.secret.data, revocation_basepoint_secret.data, payment_basepoint_secret.data, htlc_basepoint_secret.data, @@ -120,7 +119,6 @@ STRUCTEQ_DEF(privkey, 0, struct info { struct secret seed; struct pubkey funding_pubkey; - struct pubkey settle_pubkey; struct basepoints basepoints; struct secrets secrets; struct sha256 shaseed; @@ -143,7 +141,6 @@ int main(int argc, char *argv[]) common_setup(argv[0]); baseline = new_info(ctx); assert(derive_basepoints(&baseline->seed, &baseline->funding_pubkey, - &baseline->settle_pubkey, &baseline->basepoints, &baseline->secrets, &baseline->shaseed)); @@ -151,7 +148,6 @@ int main(int argc, char *argv[]) /* Same seed, same result. */ info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, - &baseline->settle_pubkey, &info->basepoints, &info->secrets, &info->shaseed)); @@ -168,7 +164,6 @@ int main(int argc, char *argv[]) assert(derive_basepoints(&info->seed, &info->funding_pubkey, - &info->settle_pubkey, &info->basepoints, &info->secrets, &info->shaseed)); @@ -183,7 +178,7 @@ int main(int argc, char *argv[]) /* Any field can be NULL (except seed). */ info = new_info(ctx); - assert(derive_basepoints(&info->seed, NULL, &info->settle_pubkey, + assert(derive_basepoints(&info->seed, NULL, &info->basepoints, &info->secrets, &info->shaseed)); @@ -191,17 +186,8 @@ int main(int argc, char *argv[]) assert(secrets_eq(&baseline->secrets, &info->secrets)); assert(sha256_eq(&baseline->shaseed, &info->shaseed)); - info = new_info(ctx); - assert(derive_basepoints(&info->seed, &info->funding_pubkey, NULL, - &info->basepoints, - &info->secrets, - &info->shaseed)); - assert(basepoints_eq(&baseline->basepoints, &info->basepoints)); - assert(secrets_eq(&baseline->secrets, &info->secrets)); - info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, - &info->settle_pubkey, NULL, &info->secrets, &info->shaseed)); @@ -211,7 +197,6 @@ int main(int argc, char *argv[]) info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, - &info->settle_pubkey, &info->basepoints, NULL, &info->shaseed)); @@ -221,7 +206,6 @@ int main(int argc, char *argv[]) info = new_info(ctx); assert(derive_basepoints(&info->seed, &info->funding_pubkey, - &info->settle_pubkey, &info->basepoints, &info->secrets, NULL)); diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 6894f18023fb..5e54948c568e 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -51,7 +51,6 @@ msgdata,hsmd_get_channel_basepoints,dbid,u64, msgtype,hsmd_get_channel_basepoints_reply,110 msgdata,hsmd_get_channel_basepoints_reply,basepoints,basepoints, msgdata,hsmd_get_channel_basepoints_reply,funding_pubkey,pubkey, -msgdata,hsmd_get_channel_basepoints_reply,settle_pubkey,pubkey, #include # Provide channel parameters. diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 5d7a43a5f0d1..51bf7e88fa67 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -431,7 +431,7 @@ static void hsm_unilateral_close_privkey(struct privkey *dst, struct secrets secrets; get_channel_seed(&info->peer_id, info->channel_id, &channel_seed); - derive_basepoints(&channel_seed, NULL, NULL, &basepoints, &secrets, NULL); + derive_basepoints(&channel_seed, NULL, &basepoints, &secrets, NULL); /* BOLT #3: * @@ -783,16 +783,15 @@ static u8 *handle_get_channel_basepoints(struct hsmd_client *c, struct secret seed; struct basepoints basepoints; struct pubkey funding_pubkey; - struct pubkey settle_pubkey; if (!fromwire_hsmd_get_channel_basepoints(msg_in, &peer_id, &dbid)) return hsmd_status_malformed_request(c, msg_in); get_channel_seed(&peer_id, dbid, &seed); - derive_basepoints(&seed, &funding_pubkey, &settle_pubkey, &basepoints, NULL, NULL); + derive_basepoints(&seed, &funding_pubkey, &basepoints, NULL, NULL); return towire_hsmd_get_channel_basepoints_reply(NULL, &basepoints, - &funding_pubkey, &settle_pubkey); + &funding_pubkey); } static u8 *handle_gen_nonce(struct hsmd_client *c, @@ -808,7 +807,7 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, /* Generate privkey for additional nonce entropy */ get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - NULL, NULL, NULL, &secrets, NULL); + NULL, NULL, &secrets, NULL); /* Fill and return own next_nonce FIXME add in more entropy */ bipmusig_gen_nonce(&secretstuff.sec_nonce, @@ -1139,7 +1138,7 @@ static u8 *handle_sign_mutual_close_tx(struct hsmd_client *c, const u8 *msg_in) * outputs! */ get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, &secrets, NULL); funding_wscript = bitcoin_redeem_2of2(tmpctx, &local_funding_pubkey, @@ -1245,7 +1244,7 @@ static u8 *handle_sign_remote_htlc_tx(struct hsmd_client *c, const u8 *msg_in) tx->chainparams = c->chainparams; get_channel_seed(&c->id, c->dbid, &channel_seed); - derive_basepoints(&channel_seed, NULL, NULL, &basepoints, &secrets, NULL); + derive_basepoints(&channel_seed, NULL, &basepoints, &secrets, NULL); if (!derive_simple_privkey(&secrets.htlc_basepoint_secret, &basepoints.htlc, @@ -1317,7 +1316,7 @@ static u8 *handle_sign_remote_commitment_tx(struct hsmd_client *c, const u8 *msg get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, &secrets, NULL); funding_wscript = bitcoin_redeem_2of2(tmpctx, &local_funding_pubkey, @@ -1460,7 +1459,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, &secrets, NULL); /* Now that we have both public keys, we can derive the MuSig session */ @@ -1538,7 +1537,7 @@ static u8 *handle_sign_commitment_tx(struct hsmd_client *c, const u8 *msg_in) get_channel_seed(&peer_id, dbid, &channel_seed); derive_basepoints(&channel_seed, - &local_funding_pubkey, NULL, NULL, &secrets, NULL); + &local_funding_pubkey, NULL, &secrets, NULL); /*~ Bitcoin signatures cover the (part of) the script they're * executing; the rules are a bit complex in general, but for diff --git a/lightningd/channel.c b/lightningd/channel.c index 3f9ccb1a4584..d9f7fdff5529 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -105,8 +105,7 @@ void get_channel_basepoints(struct lightningd *ld, const struct node_id *peer_id, const u64 dbid, struct basepoints *local_basepoints, - struct pubkey *local_funding_pubkey, - struct pubkey *local_settle_pubkey) + struct pubkey *local_funding_pubkey) { u8 *msg; @@ -117,7 +116,7 @@ void get_channel_basepoints(struct lightningd *ld, msg = wire_sync_read(tmpctx, ld->hsm_fd); if (!fromwire_hsmd_get_channel_basepoints_reply(msg, local_basepoints, - local_funding_pubkey, local_settle_pubkey)) + local_funding_pubkey)) fatal("HSM gave bad hsm_get_channel_basepoints_reply %s", tal_hex(msg, msg)); } @@ -203,7 +202,6 @@ struct channel *new_unsaved_channel(struct peer *peer, struct lightningd *ld = peer->ld; struct channel *channel = tal(ld, struct channel); u8 *msg; - struct pubkey unused_settle_pubkey; channel->peer = peer; /* Not saved to the database yet! */ @@ -280,8 +278,7 @@ struct channel *new_unsaved_channel(struct peer *peer, get_channel_basepoints(ld, &peer->id, channel->unsaved_dbid, &channel->local_basepoints, - &channel->local_funding_pubkey, - &unused_settle_pubkey); + &channel->local_funding_pubkey); channel->forgets = tal_arr(channel, struct command *, 0); list_add_tail(&peer->channels, &channel->list); @@ -379,7 +376,6 @@ struct channel *new_channel(struct peer *peer, u64 dbid, bool connected, const struct basepoints *local_basepoints, const struct pubkey *local_funding_pubkey, - const struct pubkey *local_settle_pubkey, const struct pubkey *future_per_commitment_point, u32 feerate_base, u32 feerate_ppm, @@ -481,7 +477,6 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->connected = connected; channel->local_basepoints = *local_basepoints; channel->local_funding_pubkey = *local_funding_pubkey; - channel->local_settle_pubkey = *local_settle_pubkey; channel->future_per_commitment_point = tal_steal(channel, future_per_commitment_point); channel->feerate_base = feerate_base; diff --git a/lightningd/channel.h b/lightningd/channel.h index a4c57b0a1a28..2b96c4966b91 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -167,9 +167,6 @@ struct channel { /* Our funding tx pubkey. */ struct pubkey local_funding_pubkey; - /* Our settle tx pubkey */ - struct pubkey local_settle_pubkey; - /* scriptpubkey for shutdown, if applicable. */ const u8 *shutdown_scriptpubkey[NUM_SIDES]; /* Address for any final outputs */ @@ -307,7 +304,6 @@ struct channel *new_channel(struct peer *peer, u64 dbid, bool connected, const struct basepoints *local_basepoints, const struct pubkey *local_funding_pubkey, - const struct pubkey *local_settle_pubkey, const struct pubkey *future_per_commitment_point, u32 feerate_base, u32 feerate_ppm, @@ -475,8 +471,7 @@ void get_channel_basepoints(struct lightningd *ld, const struct node_id *peer_id, const u64 dbid, struct basepoints *local_basepoints, - struct pubkey *local_funding_pubkey, - struct pubkey *local_settle_pubkey); + struct pubkey *local_funding_pubkey); void channel_set_billboard(struct channel *channel, bool perm, const char *str TAKES); diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index daf42477c207..f42fe959e84a 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -704,7 +704,7 @@ void peer_start_eltoo_channeld(struct channel *channel, channel->htlc_maximum_msat, channel->our_msat, &channel->local_funding_pubkey, - &channel->local_settle_pubkey, + &channel->local_basepoints.payment /* our_settle_pubkey */, &ld->id, &channel->peer->id, cfg->commit_time_ms, diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index 35ad65420b20..9d11d676b1fe 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -66,7 +66,7 @@ new_uncommitted_channel(struct peer *peer) tal_hex(new_channel_msg, new_channel_msg)); get_channel_basepoints(ld, &uc->peer->id, uc->dbid, - &uc->local_basepoints, &uc->local_funding_pubkey, &uc->local_settle_pubkey); + &uc->local_basepoints, &uc->local_funding_pubkey); uc->peer->uncommitted_channel = uc; tal_add_destructor(uc, destroy_uncommitted_channel); diff --git a/lightningd/opening_common.h b/lightningd/opening_common.h index 8ce38e5c9e8c..3f30dbb7b927 100644 --- a/lightningd/opening_common.h +++ b/lightningd/opening_common.h @@ -46,9 +46,6 @@ struct uncommitted_channel { /* Public key for funding tx. */ struct pubkey local_funding_pubkey; - /* Public key for settlement tx. (eltoo only) */ - struct pubkey local_settle_pubkey; - /* If true, we are already in fundee-mode and any future * `fundchannel_start` on our end should fail. */ diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 37745a120fb5..41b62233c69b 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -202,7 +202,6 @@ wallet_commit_channel(struct lightningd *ld, true, &uc->local_basepoints, &uc->local_funding_pubkey, - &uc->local_settle_pubkey, NULL, ld->config.fee_base, ld->config.fee_per_satoshi, @@ -1163,7 +1162,7 @@ bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd, bool eltoo) max_delay /* max_shared_delay */, min_effective_htlc_capacity, &uc->local_funding_pubkey, - &uc->local_settle_pubkey, + &uc->local_basepoints.payment, uc->minimum_depth, feerate_min(peer->ld, NULL), feerate_max(peer->ld, NULL), diff --git a/wallet/db.c b/wallet/db.c index 0f76d03bfd5f..04497400dcdb 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -123,7 +123,6 @@ static struct migration dbmigrations[] = { " msatoshi_local BIGINT," /* our_msatoshi */ /* START channel_info */ " fundingkey_remote BLOB," - " settlekey_remote BLOB," " revocation_basepoint_remote BLOB," " payment_basepoint_remote BLOB," " htlc_basepoint_remote BLOB," @@ -1144,7 +1143,7 @@ static void fillin_missing_local_basepoints(struct lightningd *ld, u8 *msg; struct db_stmt *upstmt; struct basepoints base; - struct pubkey funding_pubkey, settle_pubkey; + struct pubkey funding_pubkey; dbid = db_col_u64(stmt, "channels.id"); db_col_node_id(stmt, "peers.node_id", &peer_id); @@ -1156,7 +1155,7 @@ static void fillin_missing_local_basepoints(struct lightningd *ld, msg = wire_sync_read(tmpctx, mc->hsm_fd); if (!fromwire_hsmd_get_channel_basepoints_reply( - msg, &base, &funding_pubkey, &settle_pubkey)) + msg, &base, &funding_pubkey)) fatal("malformed hsmd_get_channel_basepoints_reply " "from hsmd"); @@ -1174,9 +1173,8 @@ static void fillin_missing_local_basepoints(struct lightningd *ld, db_bind_pubkey(upstmt, 2, &base.htlc); db_bind_pubkey(upstmt, 3, &base.delayed_payment); db_bind_pubkey(upstmt, 4, &funding_pubkey); - db_bind_pubkey(upstmt, 5, &settle_pubkey); - db_bind_u64(upstmt, 6, dbid); + db_bind_u64(upstmt, 5, dbid); db_exec_prepared_v2(take(upstmt)); } @@ -1220,7 +1218,6 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, " c.id" ", p.node_id" ", c.fundingkey_remote" - ", c.settlekey_remote" ", inflight.last_tx" ", inflight.last_sig" ", inflight.funding_satoshi" @@ -1240,7 +1237,6 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, struct amount_sat funding_sat; struct node_id peer_id; struct pubkey local_funding_pubkey, remote_funding_pubkey; - struct pubkey local_settle_pubkey, remote_settle_pubkey; struct basepoints local_basepoints UNUSED; struct bitcoin_signature last_sig; u64 cdb_id; @@ -1265,12 +1261,10 @@ migrate_inflight_last_tx_to_psbt(struct lightningd *ld, struct db *db, db_col_node_id(stmt, "p.node_id", &peer_id); db_col_amount_sat(stmt, "inflight.funding_satoshi", &funding_sat); db_col_pubkey(stmt, "c.fundingkey_remote", &remote_funding_pubkey); - db_col_pubkey(stmt, "c.settlekey_remote", &remote_settle_pubkey); db_col_txid(stmt, "inflight.funding_tx_id", &funding_txid); get_channel_basepoints(ld, &peer_id, cdb_id, - &local_basepoints, &local_funding_pubkey, - &local_settle_pubkey); + &local_basepoints, &local_funding_pubkey); funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey, &remote_funding_pubkey); @@ -1324,7 +1318,6 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, ", c.last_tx" ", c.funding_satoshi" ", c.fundingkey_remote" - ", c.settlekey_remote" ", c.last_sig" " FROM channels c" " LEFT OUTER JOIN peers p" @@ -1336,7 +1329,6 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, struct amount_sat funding_sat; struct node_id peer_id; struct pubkey local_funding_pubkey, remote_funding_pubkey; - struct pubkey local_settle_pubkey, remote_settle_pubkey; struct basepoints local_basepoints UNUSED; struct bitcoin_signature last_sig; u64 cdb_id; @@ -1352,7 +1344,6 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, if (db_col_is_null(stmt, "p.node_id")) { db_col_ignore(stmt, "c.funding_satoshi"); db_col_ignore(stmt, "c.fundingkey_remote"); - db_col_ignore(stmt, "c.settlekey_remote"); db_col_ignore(stmt, "c.last_sig"); continue; } @@ -1360,11 +1351,9 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db, db_col_node_id(stmt, "p.node_id", &peer_id); db_col_amount_sat(stmt, "c.funding_satoshi", &funding_sat); db_col_pubkey(stmt, "c.fundingkey_remote", &remote_funding_pubkey); - db_col_pubkey(stmt, "c.settlekey_remote", &remote_settle_pubkey); get_channel_basepoints(ld, &peer_id, cdb_id, - &local_basepoints, &local_funding_pubkey, - &local_settle_pubkey); + &local_basepoints, &local_funding_pubkey); funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey, &remote_funding_pubkey); diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index acfe69acb36f..054ddc31d3b3 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -28,7 +28,7 @@ void derive_channel_id(struct channel_id *channel_id UNNEEDED, void fatal(const char *fmt UNNEEDED, ...) { fprintf(stderr, "fatal called!\n"); abort(); } /* Generated stub for fromwire_hsmd_get_channel_basepoints_reply */ -bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, struct basepoints *basepoints UNNEEDED, struct pubkey *funding_pubkey UNNEEDED, struct pubkey *settle_pubkey UNNEEDED) +bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, struct basepoints *basepoints UNNEEDED, struct pubkey *funding_pubkey UNNEEDED) { fprintf(stderr, "fromwire_hsmd_get_channel_basepoints_reply called!\n"); abort(); } /* Generated stub for fromwire_hsmd_get_output_scriptpubkey_reply */ bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **script UNNEEDED) @@ -38,8 +38,7 @@ void get_channel_basepoints(struct lightningd *ld UNNEEDED, const struct node_id *peer_id UNNEEDED, const u64 dbid UNNEEDED, struct basepoints *local_basepoints UNNEEDED, - struct pubkey *local_funding_pubkey UNNEEDED, - struct pubkey *local_settle_pubkey UNNEEDED) + struct pubkey *local_funding_pubkey UNNEEDED) { fprintf(stderr, "get_channel_basepoints called!\n"); abort(); } /* Generated stub for towire_hsmd_get_channel_basepoints */ u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct node_id *peerid UNNEEDED, u64 dbid UNNEEDED) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 735b3a16d040..ad291c0f78f2 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -891,8 +891,7 @@ void plugin_hook_db_sync(struct db *db UNNEEDED) } bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, struct basepoints *basepoints, - struct pubkey *funding_pubkey, - struct pubkey *settle_pubkey) + struct pubkey *funding_pubkey) { struct pubkey pk; pubkey_from_der(tal_hexdata(tmpctx, @@ -901,7 +900,6 @@ bool fromwire_hsmd_get_channel_basepoints_reply(const void *p UNNEEDED, 66), 33, &pk); *funding_pubkey = pk; - *settle_pubkey = pk; basepoints->revocation = pk; basepoints->payment = pk; basepoints->htlc = pk; @@ -1618,7 +1616,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) 10000, /* max_possible_feerate */ false, &basepoints, - &pk, NULL /* local_settle_pubkey */, NULL, + &pk, NULL, 1000, 100, NULL, 0, 0, channel_type_static_remotekey(NULL), LOCAL, REASON_UNKNOWN, diff --git a/wallet/wallet.c b/wallet/wallet.c index 6b8575835f23..7a49cb807a9d 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1260,7 +1260,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm struct changed_htlc *last_sent_commit; s64 final_key_idx, channel_config_id; struct basepoints local_basepoints; - struct pubkey local_funding_pubkey, local_settle_pubkey; + struct pubkey local_funding_pubkey; struct pubkey *future_per_commitment_point; struct amount_sat funding_sat, our_funding_sat; struct amount_msat push_msat, our_msat, msat_to_us_min, msat_to_us_max, htlc_minimum_msat, htlc_maximum_msat; @@ -1335,7 +1335,6 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm /* Populate channel_info */ db_col_pubkey(stmt, "fundingkey_remote", &channel_info.remote_fundingkey); - db_col_pubkey(stmt, "settlekey_remote", &channel_info.remote_settlekey); db_col_pubkey(stmt, "revocation_basepoint_remote", &channel_info.theirbase.revocation); db_col_pubkey(stmt, "payment_basepoint_remote", &channel_info.theirbase.payment); db_col_pubkey(stmt, "htlc_basepoint_remote", &channel_info.theirbase.htlc); @@ -1387,7 +1386,6 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_col_pubkey(stmt, "delayed_payment_basepoint_local", &local_basepoints.delayed_payment); db_col_pubkey(stmt, "funding_pubkey_local", &local_funding_pubkey); - db_col_pubkey(stmt, "settle_pubkey_local", &local_settle_pubkey); if (db_col_is_null(stmt, "shutdown_wrong_txid")) { db_col_ignore(stmt, "shutdown_wrong_outnum"); shutdown_wrong_funding = NULL; @@ -1467,7 +1465,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_col_int(stmt, "max_possible_feerate"), /* Not connected */ false, - &local_basepoints, &local_funding_pubkey, &local_settle_pubkey, + &local_basepoints, &local_funding_pubkey, future_per_commitment_point, db_col_int(stmt, "feerate_base"), db_col_int(stmt, "feerate_ppm"), @@ -1538,7 +1536,6 @@ static bool wallet_channels_load_active(struct wallet *w) ", push_msatoshi" ", msatoshi_local" ", fundingkey_remote" - ", settlekey_remote" ", revocation_basepoint_remote" ", payment_basepoint_remote" ", htlc_basepoint_remote" @@ -1935,7 +1932,6 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) wallet_channel_config_save(w, &chan->channel_info.their_config); stmt = db_prepare_v2(w->db, SQL("UPDATE channels SET" " fundingkey_remote=?," - " settlekey_remote=?," " revocation_basepoint_remote=?," " payment_basepoint_remote=?," " htlc_basepoint_remote=?," @@ -1946,19 +1942,18 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " future_per_commitment_point=?" " WHERE id=?")); db_bind_pubkey(stmt, 0, &chan->channel_info.remote_fundingkey); - db_bind_pubkey(stmt, 1, &chan->channel_info.remote_settlekey); - db_bind_pubkey(stmt, 2, &chan->channel_info.theirbase.revocation); - db_bind_pubkey(stmt, 3, &chan->channel_info.theirbase.payment); - db_bind_pubkey(stmt, 4, &chan->channel_info.theirbase.htlc); - db_bind_pubkey(stmt, 5, &chan->channel_info.theirbase.delayed_payment); - db_bind_pubkey(stmt, 6, &chan->channel_info.remote_per_commit); - db_bind_pubkey(stmt, 7, &chan->channel_info.old_remote_per_commit); - db_bind_u64(stmt, 8, chan->channel_info.their_config.id); + db_bind_pubkey(stmt, 1, &chan->channel_info.theirbase.revocation); + db_bind_pubkey(stmt, 2, &chan->channel_info.theirbase.payment); + db_bind_pubkey(stmt, 3, &chan->channel_info.theirbase.htlc); + db_bind_pubkey(stmt, 4, &chan->channel_info.theirbase.delayed_payment); + db_bind_pubkey(stmt, 5, &chan->channel_info.remote_per_commit); + db_bind_pubkey(stmt, 6, &chan->channel_info.old_remote_per_commit); + db_bind_u64(stmt, 7, chan->channel_info.their_config.id); if (chan->future_per_commitment_point) - db_bind_pubkey(stmt, 9, chan->future_per_commitment_point); + db_bind_pubkey(stmt, 8, chan->future_per_commitment_point); else - db_bind_null(stmt, 9); - db_bind_u64(stmt, 10, chan->dbid); + db_bind_null(stmt, 8); + db_bind_u64(stmt, 9, chan->dbid); db_exec_prepared_v2(take(stmt)); /* FIXME: Updates channel_feerates by discarding and rewriting. */ From 4bbedd3b3ac6cb74b46bf66375215d761bac05bf Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 13:50:35 -0400 Subject: [PATCH 163/283] lock-in sanity checks for 2-of-2 CMS failing --- contrib/startup_regtest.sh | 12 ++++++++++++ lightningd/channel_control.c | 2 +- lightningd/opening_control.c | 4 ++-- lightningd/peer_control.c | 1 + lightningd/peer_htlcs.h | 2 +- openingd/eltoo_openingd.c | 4 ++-- 6 files changed, 19 insertions(+), 6 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index cd997db5dbbd..0cabc21a4a0a 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -148,6 +148,18 @@ start_ln() { echo " bt-cli, stop_ln" } +setup_ln() { + l2id=$(l2-cli getinfo | jq -r .id) + l1addr=$(l1-cli newaddr | jq -r .bech32) + bt-cli loadwallet "default" + btcaddr=$(bt-cli getnewaddress) + bt-cli sendtoaddress $l1addr 1 + bt-cli generatetoaddress 101 $btcaddr + l1-cli connect $l2id@localhost:7272 + sleep 1 + l1-cli fundchannel $l2id 10000 +} + stop_nodes() { if [ -z "$2" ]; then network=regtest diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index f42fe959e84a..15b75861bd6b 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -696,7 +696,7 @@ void peer_start_eltoo_channeld(struct channel *channel, &channel->our_last_psig, &channel->session, &channel->channel_info.remote_fundingkey, - &channel->channel_info.remote_settlekey, + &channel->channel_info.theirbase.payment, channel->opener, channel->feerate_base, channel->feerate_ppm, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 41b62233c69b..706e04ad434e 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -368,7 +368,7 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, &first_update_sig, &fc->uc->minimum_depth, &channel_info.remote_fundingkey, - &channel_info.remote_settlekey, + &channel_info.theirbase.payment, &funding, &remote_upfront_shutdown_script, &type)) { @@ -546,7 +546,7 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, &settle_tx, &first_update_sig, &channel_info.remote_fundingkey, - &channel_info.remote_settlekey, + &channel_info.theirbase.payment, &funding, &funding_sats, &push, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 7f6a47cf52a4..2d66b7c3d90f 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1551,6 +1551,7 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, struct short_channel_id scid; /* Sanity check */ + /* FIXME this doesn't work for eltoo. */ if (!check_funding_tx(tx, channel)) { channel_internal_error(channel, "Bad tx %s: %s", type_to_string(tmpctx, diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index a9c6495157b2..1bcef7bb3502 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -19,7 +19,7 @@ struct json_stream; /* FIXME: Define serialization primitive for this? */ struct channel_info { struct channel_config their_config; - struct pubkey remote_fundingkey, remote_settlekey; + struct pubkey remote_fundingkey; struct basepoints theirbase; /* The old_remote_per_commit is for the locked-in remote commit_tx, * and the remote_per_commit is for the commit_tx we're modifying now. */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 6360644d7698..5f3d927ad450 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -535,7 +535,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * peer's signature, via `funding_signed`, it will broadcast the funding * transaction. */ - settle_tx = initial_settle_channel_tx(tmpctx, state->channel, + settle_tx = initial_settle_channel_tx(state, state->channel, direct_outputs); if (!settle_tx) { negotiation_failed(state, @@ -543,7 +543,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, return false; } - *update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel); + *update_tx = initial_update_channel_tx(state, settle_tx, state->channel); if (!*update_tx) { negotiation_failed(state, From 18349773fd65f9fc5b5c481d12eff027d77477be Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 14:52:18 -0400 Subject: [PATCH 164/283] disable sanity checks and signature announcements for now --- channeld/eltoo_channeld.c | 2 ++ contrib/startup_regtest.sh | 2 +- lightningd/peer_control.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index a6c4138c7a28..f3ad46271594 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -359,6 +359,7 @@ static void make_channel_local_active(struct eltoo_peer *peer) static void send_announcement_signatures(struct eltoo_peer *peer) { + return; /* First 2 + 256 byte are the signatures and msg type, skip them */ size_t offset = 258; struct sha256_double hash; @@ -509,6 +510,7 @@ static void channel_announcement_negotiate(struct eltoo_peer *peer) * receive the remote announcement reply. But we will rebuild the channel with announcement * from the DB directly, other than waiting for the remote announcement reply. */ + /* FIXME no announcements for now */ send_announcement_signatures(peer); peer->have_sigs[LOCAL] = true; billboard_update(peer); diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 0cabc21a4a0a..980b7af279e4 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -156,7 +156,7 @@ setup_ln() { bt-cli sendtoaddress $l1addr 1 bt-cli generatetoaddress 101 $btcaddr l1-cli connect $l2id@localhost:7272 - sleep 1 + sleep 3 l1-cli fundchannel $l2id 10000 } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 2d66b7c3d90f..6bf15996a372 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1552,7 +1552,7 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, /* Sanity check */ /* FIXME this doesn't work for eltoo. */ - if (!check_funding_tx(tx, channel)) { + if (false && !check_funding_tx(tx, channel)) { channel_internal_error(channel, "Bad tx %s: %s", type_to_string(tmpctx, struct bitcoin_txid, txid), From a52cc8b5d8116051c02bb122a9d34a890b9ed4dc Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 16:12:25 -0400 Subject: [PATCH 165/283] reloading working a bit --- common/derive_basepoints.c | 2 +- contrib/startup_regtest.sh | 2 +- lightningd/channel_control.c | 3 ++- lightningd/opening_control.c | 19 +++++++++++++++++++ openingd/eltoo_openingd.c | 2 +- wallet/wallet.c | 24 +++++++++++++----------- 6 files changed, 37 insertions(+), 15 deletions(-) diff --git a/common/derive_basepoints.c b/common/derive_basepoints.c index c1a7cf22cf87..cbb3b6525c3e 100644 --- a/common/derive_basepoints.c +++ b/common/derive_basepoints.c @@ -39,7 +39,7 @@ void fromwire_secrets(const u8 **ptr, size_t *max, struct secrets *s) #endif struct keys { - struct privkey f, s, r, h, p, d; + struct privkey f, r, h, p, d; struct sha256 shaseed; }; diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 980b7af279e4..1f9c3d97e167 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -156,7 +156,7 @@ setup_ln() { bt-cli sendtoaddress $l1addr 1 bt-cli generatetoaddress 101 $btcaddr l1-cli connect $l2id@localhost:7272 - sleep 3 + sleep 5 l1-cli fundchannel $l2id 10000 } diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 15b75861bd6b..2b40a3d142dd 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -696,7 +696,8 @@ void peer_start_eltoo_channeld(struct channel *channel, &channel->our_last_psig, &channel->session, &channel->channel_info.remote_fundingkey, - &channel->channel_info.theirbase.payment, + &channel->channel_info.remote_fundingkey, +/* &channel->channel_info.theirbase.payment,*/ channel->opener, channel->feerate_base, channel->feerate_ppm, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 706e04ad434e..83a9ca876fe7 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -382,6 +382,15 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, } update_tx->chainparams = chainparams; + /* We make sure other basepoints are valid + * even if unused... + * FIXME wallet db gets upset if I don't do this due to statement construction... */ + memcpy(&channel_info.theirbase.revocation, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.theirbase.htlc, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.theirbase.delayed_payment, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.old_remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + peer_fd = new_peer_fd_arr(resp, fds); /* Saved with channel to disk */ @@ -562,6 +571,16 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, goto failed; } + + /* We make sure other basepoints are valid + * even if unused... + * FIXME wallet db gets upset if I don't do this due to statement construction... */ + memcpy(&channel_info.theirbase.revocation, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.theirbase.htlc, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.theirbase.delayed_payment, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + memcpy(&channel_info.old_remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + settle_tx->chainparams = chainparams; derive_channel_id(&cid, &funding); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 5f3d927ad450..65b383239930 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -349,7 +349,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) state->localconf.shared_delay, state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, - &state->our_settlement_pubkey, + &state->our_settlement_pubkey, /* FIXME is this set?? */ channel_flags, &state->eltoo_keyset.self_next_nonce, open_tlvs); diff --git a/wallet/wallet.c b/wallet/wallet.c index 7a49cb807a9d..9dd62a6992b8 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1212,7 +1212,7 @@ static bool wallet_channel_config_load(struct wallet *w, const u64 id, const char *query = SQL( "SELECT dust_limit_satoshis, max_htlc_value_in_flight_msat, " "channel_reserve_satoshis, htlc_minimum_msat, to_self_delay, " - "max_accepted_htlcs, max_dust_htlc_exposure_msat" + "max_accepted_htlcs, max_dust_htlc_exposure_msat " " FROM channel_configs WHERE id= ? ;"); struct db_stmt *stmt = db_prepare_v2(w->db, query); db_bind_u64(stmt, 0, id); @@ -1330,17 +1330,18 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm ok &= wallet_channel_config_load(w, channel_config_id, &our_config); db_col_sha256d(stmt, "funding_tx_id", &funding.txid.shad); funding.n = db_col_int(stmt, "funding_tx_outnum"), - ok &= db_col_signature(stmt, "last_sig", &last_sig.s); + /* No last_sig expected for eltoo */ + ok &= db_col_signature(stmt, "last_sig", &last_sig.s) || our_config.is_eltoo ; last_sig.sighash_type = SIGHASH_ALL; /* Populate channel_info */ db_col_pubkey(stmt, "fundingkey_remote", &channel_info.remote_fundingkey); - db_col_pubkey(stmt, "revocation_basepoint_remote", &channel_info.theirbase.revocation); - db_col_pubkey(stmt, "payment_basepoint_remote", &channel_info.theirbase.payment); - db_col_pubkey(stmt, "htlc_basepoint_remote", &channel_info.theirbase.htlc); - db_col_pubkey(stmt, "delayed_payment_basepoint_remote", &channel_info.theirbase.delayed_payment); - db_col_pubkey(stmt, "per_commit_remote", &channel_info.remote_per_commit); - db_col_pubkey(stmt, "old_per_commit_remote", &channel_info.old_remote_per_commit); + db_col_pubkey(stmt, "revocation_basepoint_remote", &channel_info.theirbase.revocation); + db_col_pubkey(stmt, "payment_basepoint_remote", &channel_info.theirbase.payment); + db_col_pubkey(stmt, "htlc_basepoint_remote", &channel_info.theirbase.htlc); + db_col_pubkey(stmt, "delayed_payment_basepoint_remote", &channel_info.theirbase.delayed_payment); + db_col_pubkey(stmt, "per_commit_remote", &channel_info.remote_per_commit); + db_col_pubkey(stmt, "old_per_commit_remote", &channel_info.old_remote_per_commit); wallet_channel_config_load(w, db_col_u64(stmt, "channel_config_remote"), &channel_info.their_config); @@ -1349,7 +1350,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm = wallet_channel_fee_states_load(w, db_col_u64(stmt, "id"), db_col_int(stmt, "funder")); - if (!fee_states) + /* No fee states expected for eltoo */ + if (!our_config.is_eltoo && !fee_states) ok = false; if (!ok) { @@ -1357,12 +1359,12 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm return NULL; } - /* Blockheight states for the channel! */ + /* Blockheight states for the channel! (not eltoo for now) */ height_states = wallet_channel_height_states_load(w, db_col_u64(stmt, "id"), db_col_int(stmt, "funder")); - if (!height_states) + if (!our_config.is_eltoo && !height_states) ok = false; if (!ok) { From 95ce0ad4572bd81ec3ede08d5419cee92337c2d4 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Sep 2022 16:26:01 -0400 Subject: [PATCH 166/283] shared_delay seems to be loading properly --- contrib/startup_regtest.sh | 2 +- wallet/db.c | 1 + wallet/wallet.c | 9 ++++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 1f9c3d97e167..820a6c11b09c 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_openingd" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & #"--dev-debugger=eltoo_openingd" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 diff --git a/wallet/db.c b/wallet/db.c index 04497400dcdb..3fb617a89dab 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -152,6 +152,7 @@ static struct migration dbmigrations[] = { " htlc_minimum_msat BIGINT," " to_self_delay INTEGER," " max_accepted_htlcs INTEGER," + " shared_delay INTEGER," " PRIMARY KEY (id)" ");"), NULL}, diff --git a/wallet/wallet.c b/wallet/wallet.c index 9dd62a6992b8..0ebe9b57f4b0 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1212,7 +1212,7 @@ static bool wallet_channel_config_load(struct wallet *w, const u64 id, const char *query = SQL( "SELECT dust_limit_satoshis, max_htlc_value_in_flight_msat, " "channel_reserve_satoshis, htlc_minimum_msat, to_self_delay, " - "max_accepted_htlcs, max_dust_htlc_exposure_msat " + "max_accepted_htlcs, max_dust_htlc_exposure_msat, shared_delay " " FROM channel_configs WHERE id= ? ;"); struct db_stmt *stmt = db_prepare_v2(w->db, query); db_bind_u64(stmt, 0, id); @@ -1232,6 +1232,7 @@ static bool wallet_channel_config_load(struct wallet *w, const u64 id, cc->max_accepted_htlcs = db_col_int(stmt, "max_accepted_htlcs"); db_col_amount_msat(stmt, "max_dust_htlc_exposure_msat", &cc->max_dust_htlc_exposure_msat); + cc->shared_delay = db_col_int(stmt, "shared_delay"); tal_free(stmt); return ok; } @@ -1775,7 +1776,8 @@ static void wallet_channel_config_save(struct wallet *w, " htlc_minimum_msat=?," " to_self_delay=?," " max_accepted_htlcs=?," - " max_dust_htlc_exposure_msat=?" + " max_dust_htlc_exposure_msat=?," + " shared_delay=?" " WHERE id=?;")); db_bind_amount_sat(stmt, 0, &cc->dust_limit); db_bind_amount_msat(stmt, 1, &cc->max_htlc_value_in_flight); @@ -1784,7 +1786,8 @@ static void wallet_channel_config_save(struct wallet *w, db_bind_int(stmt, 4, cc->to_self_delay); db_bind_int(stmt, 5, cc->max_accepted_htlcs); db_bind_amount_msat(stmt, 6, &cc->max_dust_htlc_exposure_msat); - db_bind_u64(stmt, 7, cc->id); + db_bind_int(stmt, 7, cc->shared_delay); + db_bind_u64(stmt, 8, cc->id); db_exec_prepared_v2(take(stmt)); } From 76443c841376737e17adba2e9caa67e7fd4a0477 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 8 Sep 2022 09:33:36 -0400 Subject: [PATCH 167/283] refactor bind_update_tx_to_* to take bip340sig --- channeld/test/run-settle_tx.c | 27 +++++++++++---------------- common/initial_eltoo_channel.c | 1 + common/update_tx.c | 20 ++++++++++++++++++-- common/update_tx.h | 8 ++++---- openingd/eltoo_openingd.c | 17 ++++++++++++++++- 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 17231344363c..22716f4feb96 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -97,9 +97,8 @@ static struct secret secret_from_hex(const char *hex) return s; } -static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *alice_privkey, struct privkey *bob_privkey, struct pubkey *inner_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache) +static struct bip340sig musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *alice_privkey, struct privkey *bob_privkey, struct pubkey *inner_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache) { - u8 *final_sig; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; struct sha256_double msg_out; secp256k1_musig_session session[2]; @@ -146,11 +145,7 @@ static u8 *musig_sign(struct bitcoin_tx *update_tx, u8 *annex, struct privkey *a assert(ok); } - final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); - memcpy(final_sig, sig.u8, sizeof(sig.u8)); - /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ - final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; - return final_sig; + return sig; } static void tx_must_be_eq(const struct bitcoin_tx *a, @@ -515,7 +510,7 @@ static int test_invalid_update_tx(void) /* MuSig signing stuff */ u8 *annex_0, *annex_1; - u8 *final_sig; + struct bip340sig sig; /* Test initial settlement tx */ @@ -584,7 +579,7 @@ static int test_invalid_update_tx(void) /* Signing happens next */ annex_0 = make_eltoo_annex(tmpctx, tx); - final_sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); + sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* Re-bind, add final script/tapscript info into PSBT */ bind_update_tx_to_funding_outpoint(update_tx, @@ -592,7 +587,7 @@ static int test_invalid_update_tx(void) &update_output, &eltoo_keyset, &inner_pubkey, - final_sig); + &sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); printf("Update transaction 0: %s\n", psbt_b64); @@ -628,7 +623,7 @@ static int test_invalid_update_tx(void) /* Authorize this next state update */ annex_1 = make_eltoo_annex(tmpctx, settle_tx_1); - final_sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); + sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* This can RBF the first update tx */ bind_update_tx_to_funding_outpoint(update_tx_1_A, @@ -636,7 +631,7 @@ static int test_invalid_update_tx(void) &update_output, &eltoo_keyset, &inner_pubkey, - final_sig); + &sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx_1_A->psbt); printf("Update transaction 1A(funding output): %s\n", psbt_b64); @@ -649,7 +644,7 @@ static int test_invalid_update_tx(void) annex_0, /* annex you see on chain */ obscured_update_number - 1, /* locktime you see on old update tx */ &inner_pubkey, - final_sig); + &sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx_1_A->psbt); printf("Update transaction 1B(update output): %s\n", psbt_b64); @@ -682,7 +677,7 @@ static int test_initial_settlement_tx(void) /* MuSig signing stuff */ struct pubkey inner_pubkey; u8 *annex; - u8 *final_sig; + struct bip340sig sig; /* Test initial settlement tx */ @@ -754,7 +749,7 @@ static int test_initial_settlement_tx(void) /* Signing happens next */ annex = make_eltoo_annex(tmpctx, tx); - final_sig = musig_sign(update_tx, annex, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); + sig = musig_sign(update_tx, annex, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* We want to close the channel without cooperation... time to rebind and finalize */ @@ -764,7 +759,7 @@ static int test_initial_settlement_tx(void) &update_output, &eltoo_keyset, &inner_pubkey, - final_sig); + &sig); psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); printf("Initial update psbt with finalized witness for input: %s\n", psbt_b64); diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index 070fdadcf3ef..c8929de553ec 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -91,6 +91,7 @@ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, /* This assumes no HTLCs! */ assert(!channel->htlcs); + /* Note that funding prevout here is not quite right, but we'll re-bind at-chain time */ init_settle_tx = initial_settlement_tx(ctx, &channel->funding, channel->funding_sats, diff --git a/common/update_tx.c b/common/update_tx.c index 662d3db63648..2df22145d797 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -67,7 +67,7 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, const struct bitcoin_outpoint *funding_outpoint, const struct eltoo_keyset *eltoo_keyset, const struct pubkey *psbt_inner_pubkey, - u8 *final_sig) + const struct bip340sig *sig) { const struct pubkey *pubkey_ptrs[2]; u8 *update_tapscript[1]; @@ -77,11 +77,19 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, secp256k1_musig_keyagg_cache unused_coop_cache; u8 **update_witness; struct amount_sat funding_sats; + u8 *final_sig; /* Stuff that should go in PSBT eventually */ struct sha256 psbt_tap_merkle_root; unsigned char psbt_tap_tweak[32]; + + /* Construct bytes of sig with flag */ + final_sig = tal_arr(tmpctx, u8, sizeof(sig->u8)+1); + memcpy(final_sig, sig->u8, sizeof(sig->u8)); + /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ + final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; + /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); @@ -127,7 +135,7 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, const u8 *invalidated_annex_hint, u32 invalidated_update_number, struct pubkey *psbt_inner_pubkey, - u8 *final_sig) + const struct bip340sig *sig) { const struct pubkey *pubkey_ptrs[2]; u8 *update_tapscript; @@ -137,11 +145,19 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, secp256k1_musig_keyagg_cache unused_coop_cache; u8 **update_witness; struct amount_sat funding_sats; + u8 *final_sig; /* Stuff that should go in PSBT eventually */ struct sha256 psbt_tap_merkle_root; unsigned char psbt_tap_tweak[32]; + /* Construct bytes of sig with flag */ + final_sig = tal_arr(tmpctx, u8, sizeof(sig->u8)+1); + memcpy(final_sig, sig->u8, sizeof(sig->u8)); + /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ + final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; + + /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); diff --git a/common/update_tx.h b/common/update_tx.h index 58b847caba26..f345cc151501 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -29,14 +29,14 @@ void tx_add_unbound_input(struct bitcoin_tx *update_tx, * @funding_outpoint: The outpoint to be spend on chain * @eltoo_keyset: Set of keys to derive inner public key * @psbt_inner_pubkey: Inner pubkey for the state input - * @final_sig: Raw 65-bytes of signature to be put into witness + * @sig: bip340 signature to be put into witness */ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, const struct eltoo_keyset *eltoo_keyset, const struct pubkey *psbt_inner_pubkey, - u8 *final_sig); + const struct bip340sig *sig); /* Used to bind the update transaction to the non-funding outpoints * of the eltoo contract. This only occurs if invalidated update @@ -51,7 +51,7 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, * @invalidated_update_number: The locktime of the update transaction * which is having its outpoint spent by @update_tx * @psbt_inner_pubkey: Inner pubkey for the state input - * @final_sig: Raw 65-bytes of signature to put into witness + * @sig: bip340 signature to put into witness */ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, struct bitcoin_tx *settle_tx, @@ -60,7 +60,7 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, const u8 *invalidated_annex_hint, u32 invalidated_update_number, struct pubkey *psbt_inner_pubkey, - u8 *final_sig); + const struct bip340sig *sig); /** * unbound_update_tx: create (unsigned) update tx to spend a yet-to-decided ouutpoint diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 65b383239930..c158a2d96e0c 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -464,6 +464,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, struct wally_tx_output *direct_outputs[NUM_SIDES]; struct bitcoin_tx *settle_tx; struct partial_sig our_update_psig, their_update_psig; +// u8 *final_sig; /* Dummy fields since they're unused at time of channel creation */ struct partial_sig dummy_self_psig, dummy_other_psig; @@ -562,8 +563,9 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); - status_debug("partial signature req on tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", + status_debug("partial signature req on update tx %s, settlement tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", type_to_string(tmpctx, struct bitcoin_tx, *update_tx), + type_to_string(tmpctx, struct bitcoin_tx, settle_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey), type_to_string(tmpctx, struct pubkey, @@ -692,6 +694,19 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, status_failed(STATUS_FAIL_INTERNAL_ERROR, "Unable to set signature internally"); */ +// final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); +// memcpy(final_sig, sig.u8, sizeof(sig.u8)); +// /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ +// final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; + + /* Re-bind, add final script/tapscript info into PSBT */ +// bind_update_tx_to_funding_outpoint(update_tx, +// tx, +// &update_output, +// &eltoo_keyset, +// &inner_pubkey, +// final_sig); + peer_billboard(false, "Funding channel: opening negotiation succeeded"); return true; From a2ec97504ede25797750b3b0c64e63a2f808e0f0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 8 Sep 2022 12:36:42 -0400 Subject: [PATCH 168/283] onchaind explodes when it sees update tx, yay --- contrib/startup_regtest.sh | 4 ++-- openingd/eltoo_openingd.c | 28 +++++++++++++++------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 820a6c11b09c..62a12f760005 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & #"--dev-debugger=eltoo_openingd" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_openingd" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 @@ -126,7 +126,7 @@ start_nodes() { start_ln() { # Start bitcoind in the background test -f "$PATH_TO_BITCOIN/regtest/bitcoind.pid" || \ - bitcoind -regtest -txindex -fallbackfee=0.00000253 -daemon -daemonwait + $(pwd)/../bitcoin/src/bitcoind -regtest -txindex -fallbackfee=0.00000253 -daemon -daemonwait -trueoutputs=1 -annexcarrier=1 # Wait for it to start while ! bitcoin-cli -regtest ping 2> /tmp/null; do echo "awaiting bitcoind..." && sleep 1; done diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index c158a2d96e0c..7d97ac327858 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -464,7 +465,6 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, struct wally_tx_output *direct_outputs[NUM_SIDES]; struct bitcoin_tx *settle_tx; struct partial_sig our_update_psig, their_update_psig; -// u8 *final_sig; /* Dummy fields since they're unused at time of channel creation */ struct partial_sig dummy_self_psig, dummy_other_psig; @@ -686,6 +686,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, } /* We save their sig to our first update tx */ + + status_debug("Rebinding update transaction 0"); /* FIXME Store as taproot signature in PSBT once updated or should we just sneak it in same way for now? if (!psbt_input_set_signature((*update_tx)->psbt, 0, @@ -694,18 +696,18 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, status_failed(STATUS_FAIL_INTERNAL_ERROR, "Unable to set signature internally"); */ -// final_sig = tal_arr(tmpctx, u8, sizeof(sig.u8)+1); -// memcpy(final_sig, sig.u8, sizeof(sig.u8)); -// /* FIXME store signature in PSBT_IN_PARTIAL_SIG */ -// final_sig[tal_count(final_sig)-1] = SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE; - - /* Re-bind, add final script/tapscript info into PSBT */ -// bind_update_tx_to_funding_outpoint(update_tx, -// tx, -// &update_output, -// &eltoo_keyset, -// &inner_pubkey, -// final_sig); + /* For now: Re-bind, add final script/tapscript info into PSBT */ + bind_update_tx_to_funding_outpoint(*update_tx, + settle_tx, + &state->funding, + &state->channel->eltoo_keyset, + &state->channel->eltoo_keyset.inner_pubkey, + update_sig); + + /* For debugging, remove later */ + status_debug("Signed update transaction 0: %s", psbt_to_b64(NULL, (*update_tx)->psbt)); + + status_debug("Settle transaction 0: %s", psbt_to_b64(NULL, settle_tx->psbt)); peer_billboard(false, "Funding channel: opening negotiation succeeded"); From 0abd204f07317b601aa7378e288634d5301955a3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 8 Sep 2022 13:16:29 -0400 Subject: [PATCH 169/283] put obvioulsy bogus prevout in settlement tx instead of funding output(wrong) --- channeld/test/run-settle_tx.c | 4 +--- common/initial_eltoo_channel.c | 1 - common/initial_settlement_tx.c | 8 ++++++-- common/initial_settlement_tx.h | 2 -- contrib/startup_regtest.sh | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 22716f4feb96..ce491c834fee 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -57,7 +57,7 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -char regression_tx_hex[] = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a48848900000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4b4d868d7231ff3d15775dbd01acf0051b86eccd1f1139772222152b32986c4df0065cd1d"; +char regression_tx_hex[] = "02000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4b4d868d7231ff3d15775dbd01acf0051b86eccd1f1139772222152b32986c4df0065cd1d"; static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { @@ -546,7 +546,6 @@ static int test_invalid_update_tx(void) obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ tx = initial_settlement_tx(tmpctx, - &update_output, update_output_sats, shared_delay, &eltoo_keyset, @@ -713,7 +712,6 @@ static int test_initial_settlement_tx(void) obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ tx = initial_settlement_tx(tmpctx, - &update_output, update_output_sats, shared_delay, &eltoo_keyset, diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index c8929de553ec..76568617f3b2 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -93,7 +93,6 @@ struct bitcoin_tx *initial_settle_channel_tx(const tal_t *ctx, /* Note that funding prevout here is not quite right, but we'll re-bind at-chain time */ init_settle_tx = initial_settlement_tx(ctx, - &channel->funding, channel->funding_sats, channel->config->shared_delay, &channel->eltoo_keyset, diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 3e977b7ae376..edfe0f6cdbac 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -115,7 +115,6 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, - const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, u32 shared_delay, const struct eltoo_keyset *eltoo_keyset, @@ -136,6 +135,11 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, struct pubkey inner_pubkey; secp256k1_musig_keyagg_cache keyagg_cache; + /* PSBTs insist that a utxo is "real", insert garbage so we have value later */ + struct bitcoin_outpoint fake_outpoint; + memset(fake_outpoint.txid.shad.sha.u.u8, 0xff, sizeof(fake_outpoint.txid.shad.sha.u.u8)); + fake_outpoint.n = 0; + /* For MuSig aggregation for outputs */ pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); @@ -250,7 +254,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * * `txin[0]` script bytes: 0 */ - add_settlement_input(tx, update_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); + add_settlement_input(tx, &fake_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); /* Transaction is now ready for broadcast! */ diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index ce703dec49d9..54e299862cae 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -16,7 +16,6 @@ struct wally_tx_output; /** * initial_settlement_tx: create (unsigned) update tx to spend the first update tx * @ctx: context to allocate transaction and @htlc_map from. - * @update_outpoint, @update_outpoint_sats: funding outpoint and amount * @shared_delay: delay before this settlement transaction can be included in a block * @eltoo_keyset: keys for the update and settlement outputs. * @dust_limit: dust limit below which to trim outputs. @@ -27,7 +26,6 @@ struct wally_tx_output; * */ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, - const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, u32 shared_delay, const struct eltoo_keyset *eltoo_keyset, diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 62a12f760005..07621d9d9524 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_openingd" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & #"--dev-debugger=eltoo_openingd" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 From 9bb41de43960c586b10cc1a9dbcdf78aaaa41e26 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 8 Sep 2022 16:29:41 -0400 Subject: [PATCH 170/283] eltoo CHANNELD_NORMAL achieved --- contrib/startup_regtest.sh | 5 ++-- lightningd/channel_control.c | 46 +++++++++++++++++++++++++++++++++--- lightningd/channel_control.h | 3 +++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 07621d9d9524..804c682b3d0b 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & #"--dev-debugger=eltoo_openingd" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_channeld" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 @@ -157,7 +157,8 @@ setup_ln() { bt-cli generatetoaddress 101 $btcaddr l1-cli connect $l2id@localhost:7272 sleep 5 - l1-cli fundchannel $l2id 10000 + l1-cli fundchannel $l2id 10000 normal false + bt-cli generatetoaddress 6 $btcaddr } stop_nodes() { diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 2b40a3d142dd..39bc23975dd0 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -206,6 +206,20 @@ static void lockin_complete(struct channel *channel) channel_record_open(channel); } +bool channel_on_funding_locked_eltoo(struct channel *channel) +{ + if (channel->remote_funding_locked) { + channel_internal_error(channel, + "channel_got_funding_locked_eltoo twice"); + return false; + } + + log_debug(channel->log, "Got funding_locked_eltoo"); + channel->remote_funding_locked = true; + + return true; +} + bool channel_on_funding_locked(struct channel *channel, struct pubkey *next_per_commitment_point) { @@ -222,6 +236,32 @@ bool channel_on_funding_locked(struct channel *channel, return true; } +/* We were informed by channeld that it announced the channel and sent + * an update, so we can now start sending a node_announcement. The + * first step is to build the provisional announcement and ask the HSM + * to sign it. */ + +static void peer_got_funding_locked_eltoo(struct channel *channel, const u8 *msg) +{ + struct pubkey next_per_commitment_point; + + if (!fromwire_channeld_got_funding_locked_eltoo(msg)) { + channel_internal_error(channel, + "bad channel_got_funding_locked %s", + tal_hex(channel, msg)); + return; + } + + if (!channel_on_funding_locked(channel, &next_per_commitment_point)) + return; + + if (channel->scid) + lockin_complete(channel); + else + /* Remember that we got the lockin */ + wallet_channel_save(channel->peer->ld->wallet, channel); +} + /* We were informed by channeld that it announced the channel and sent * an update, so we can now start sending a node_announcement. The * first step is to build the provisional announcement and ask the HSM @@ -517,6 +557,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_GOT_FUNDING_LOCKED: peer_got_funding_locked(sd->channel, msg); break; + case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: + peer_got_funding_locked_eltoo(sd->channel, msg); + break; case WIRE_CHANNELD_GOT_ANNOUNCEMENT: peer_got_announcement(sd->channel, msg); break; @@ -548,9 +591,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: handle_local_private_channel(sd->channel, msg); break; - case WIRE_CHANNELD_GOT_FUNDING_LOCKED_ELTOO: - /* FIXME Handle this */ - break; case WIRE_CHANNELD_GOT_UPDATESIG: /* FIXME handle this */ break; diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index 3239339b9698..c9f6f19bb43d 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -36,6 +36,9 @@ void channel_notify_new_block(struct lightningd *ld, struct command_result *cancel_channel_before_broadcast(struct command *cmd, struct peer *peer); +/* Update the channel info on funding locked eltoo*/ +bool channel_on_funding_locked_eltoo(struct channel *channel); + /* Update the channel info on funding locked */ bool channel_on_funding_locked(struct channel *channel, struct pubkey *next_per_commitment_point); From 4c849039a7182941f48b64041a4461ac70b8f97a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 12 Sep 2022 14:35:10 -0400 Subject: [PATCH 171/283] dev-debgger causing msg issues, working on htlc --- channeld/eltoo_channeld.c | 32 ++++++++++++++++++++++++++++++-- channeld/eltoo_full_channel.c | 6 +++--- contrib/startup_regtest.sh | 8 ++++---- lightningd/chaintopology.c | 12 +++++++----- lightningd/channel_control.c | 11 +++++++++-- lightningd/subd.c | 4 ++++ 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index f3ad46271594..17c6aae68964 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1913,6 +1913,28 @@ static void handle_dev_memleak(struct eltoo_peer *peer, const u8 *msg) found_leak))); } +/* Unused for now, just take message off wire */ +static void handle_feerates(struct eltoo_peer *peer, const u8 *inmsg) +{ + u32 dummy_feerate; + + if (!fromwire_channeld_feerates(inmsg, &dummy_feerate, + &dummy_feerate, + &dummy_feerate, + &dummy_feerate)) + master_badmsg(WIRE_CHANNELD_FEERATES, inmsg); +} + +/* Unused for now, just take message off wire */ +static void handle_blockheight(struct eltoo_peer *peer, const u8 *inmsg) +{ + u32 blockheight; + + if (!fromwire_channeld_blockheight(inmsg, &blockheight)) + master_badmsg(WIRE_CHANNELD_BLOCKHEIGHT, inmsg); +} + + #if EXPERIMENTAL_FEATURES static void handle_dev_quiesce(struct eltoo_peer *peer, const u8 *msg) { @@ -1944,10 +1966,10 @@ static void req_in(struct eltoo_peer *peer, const u8 *msg) handle_offer_htlc(peer, msg); return; case WIRE_CHANNELD_FEERATES: - /* FIXME handle illegal messages */ + handle_feerates(peer, msg); return; case WIRE_CHANNELD_BLOCKHEIGHT: - /* FIXME handle illegal messages */ + handle_blockheight(peer, msg); return; case WIRE_CHANNELD_FULFILL_HTLC: if (handle_master_request_later(peer, msg)) @@ -2287,6 +2309,8 @@ int main(int argc, char *argv[]) tptr = &timeout; } + + status_debug("***SELECT***"); if (select(nfds, &rfds, NULL, NULL, tptr) < 0) { /* Signals OK, eg. SIGUSR1 */ if (errno == EINTR) @@ -2294,6 +2318,7 @@ int main(int argc, char *argv[]) status_failed(STATUS_FAIL_INTERNAL_ERROR, "select failed: %s", strerror(errno)); } + status_debug("***UNSELECT***"); if (FD_ISSET(MASTER_FD, &rfds)) { msg = wire_sync_read(tmpctx, MASTER_FD); @@ -2302,6 +2327,9 @@ int main(int argc, char *argv[]) status_failed(STATUS_FAIL_MASTER_IO, "Can't read command: %s", strerror(errno)); + status_debug("Dealing with %s", + channeld_wire_name( + fromwire_peektype(msg))); req_in(peer, msg); } else if (FD_ISSET(peer->pps->peer_fd, &rfds)) { /* This could take forever, but who cares? */ diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 5962cd5b85bc..17d7cc7f1bd1 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -268,7 +268,7 @@ struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, /* We only fill out witness data for update transactions for onchain events */ txs[0] = unbound_update_tx(ctx, - txs[0], + txs[1], channel->funding_sats, &channel->eltoo_keyset.inner_pubkey); @@ -279,9 +279,9 @@ struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, /* Set the remote/local pubkeys on the update tx psbt FIXME add inner pubkey when possible */ psbt_input_add_pubkey(txs[0]->psbt, 0, - &channel->funding_pubkey[side]); + &channel->eltoo_keyset.self_funding_key); psbt_input_add_pubkey(txs[0]->psbt, 0, - &channel->funding_pubkey[!side]); + &channel->eltoo_keyset.other_funding_key); tal_free(committed); return txs; diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 804c682b3d0b..fa66bf3a1326 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -94,8 +94,8 @@ start_nodes() { if $LIGHTNINGD --help | grep -q dev-fast-gossip; then cat <<- EOF >> "/tmp/l$i-$network/config" dev-fast-gossip - dev-bitcoind-poll=5 experimental-dual-fund + #dev-bitcoind-poll=120 funder-policy=match funder-policy-mod=100 funder-min-their-funding=10000 @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_channeld" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & #"--dev-debugger=eltoo_channeld" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 @@ -154,11 +154,11 @@ setup_ln() { bt-cli loadwallet "default" btcaddr=$(bt-cli getnewaddress) bt-cli sendtoaddress $l1addr 1 - bt-cli generatetoaddress 101 $btcaddr l1-cli connect $l2id@localhost:7272 + bt-cli generatetoaddress 101 $btcaddr sleep 5 l1-cli fundchannel $l2id 10000 normal false - bt-cli generatetoaddress 6 $btcaddr + bt-cli generatetoaddress 7 $btcaddr } stop_nodes() { diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index f965ae90c587..2d0002dc8f29 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -366,7 +366,7 @@ static void update_feerates(struct bitcoind *bitcoind, * 2 minutes. The following will do that in a polling interval * independent manner. */ double alpha = 1 - pow(0.1,(double)topo->poll_seconds / 120); - bool feerate_changed = false; + bool notify_feerate_changed = false; for (size_t i = 0; i < NUM_FEERATES; i++) { u32 feerate = satoshi_per_kw[i]; @@ -380,7 +380,7 @@ static void update_feerates(struct bitcoind *bitcoind, /* Initial smoothed feerate is the polled feerate */ if (!old_feerates[i]) { - feerate_changed = true; + notify_feerate_changed = true; old_feerates[i] = feerate; init_feerate_history(topo, i, feerate); @@ -388,8 +388,6 @@ static void update_feerates(struct bitcoind *bitcoind, "Smoothed feerate estimate for %s initialized to polled estimate %u", feerate_name(i), feerate); } else { - if (feerate != old_feerates[i]) - feerate_changed = true; add_feerate_history(topo, i, feerate); } @@ -418,6 +416,10 @@ static void update_feerates(struct bitcoind *bitcoind, feerate, topo->feerate[i]); } topo->feerate[i] = feerate; + + /* After adjustment, If any entry doesn't match prior reported, report all */ + if (feerate != old_feerates[i]) + notify_feerate_changed = true; } if (topo->feerate_uninitialized) { @@ -427,7 +429,7 @@ static void update_feerates(struct bitcoind *bitcoind, maybe_completed_init(topo); } - if (feerate_changed) + if (notify_feerate_changed) notify_feerate_change(bitcoind->ld); next_updatefee_timer(topo); diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 39bc23975dd0..73258a8f2be2 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -34,6 +34,9 @@ static void update_feerates(struct lightningd *ld, struct channel *channel) if (!feerate) return; + /* FIXME testing turning off feerates... */ +// return; + log_debug(ld->log, "update_feerates: feerate = %u, min=%u, max=%u, penalty=%u", feerate, @@ -594,12 +597,16 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_GOT_UPDATESIG: /* FIXME handle this */ break; + case WIRE_CHANNELD_SENDING_UPDATESIG: + /* FIXME handle this */ + break; + case WIRE_CHANNELD_GOT_ACK: + /* FIXME handle this */ + break; case WIRE_CHANNELD_INIT_ELTOO: case WIRE_CHANNELD_GOT_UPDATESIG_REPLY: - case WIRE_CHANNELD_GOT_ACK: case WIRE_CHANNELD_GOT_ACK_REPLY: case WIRE_CHANNELD_GOT_SHUTDOWN_ELTOO: - case WIRE_CHANNELD_SENDING_UPDATESIG: case WIRE_CHANNELD_SENDING_UPDATESIG_REPLY: #if EXPERIMENTAL_FEATURES case WIRE_CHANNELD_UPGRADED: diff --git a/lightningd/subd.c b/lightningd/subd.c index 80b5aa00cbd2..b792a33b33c5 100644 --- a/lightningd/subd.c +++ b/lightningd/subd.c @@ -665,6 +665,7 @@ static struct io_plan *msg_send_next(struct io_conn *conn, struct subd *sd) { const u8 *msg; int fd; + u16 type; /* Don't send if we haven't read version! */ if (!sd->rcvd_version) @@ -675,11 +676,14 @@ static struct io_plan *msg_send_next(struct io_conn *conn, struct subd *sd) if (!msg) return msg_queue_wait(conn, sd->outq, msg_send_next, sd); + type = fromwire_peektype(msg); + fd = msg_extract_fd(sd->outq, msg); if (fd >= 0) { tal_free(msg); return io_send_fd(conn, fd, true, msg_send_next, sd); } + log_debug(sd->log, "TYPE: %u, FD: %d", type, fd); return io_write_wire(conn, take(msg), msg_send_next, sd); } From adf8dd0aecb39d8d3c76dbc003225d4edf25e054 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 13 Sep 2022 13:15:31 -0400 Subject: [PATCH 172/283] Rework what data is passed from opening to channel... explosions surely --- contrib/startup_regtest.sh | 6 +- db/bindings.c | 28 +++++++ db/bindings.h | 6 ++ lightningd/channel.c | 17 +++- lightningd/channel.h | 15 +++- lightningd/channel_control.c | 6 +- lightningd/opening_control.c | 77 +++++++++++++---- openingd/eltoo_openingd.c | 136 ++++++++++++++++++------------- openingd/eltoo_openingd_wire.csv | 21 +++-- wallet/test/run-wallet.c | 7 +- wallet/wallet.c | 23 +++++- 11 files changed, 248 insertions(+), 94 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index fa66bf3a1326..791657c45de8 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -95,7 +95,7 @@ start_nodes() { cat <<- EOF >> "/tmp/l$i-$network/config" dev-fast-gossip experimental-dual-fund - #dev-bitcoind-poll=120 + dev-bitcoind-poll=5 funder-policy=match funder-policy-mod=100 funder-min-their-funding=10000 @@ -155,10 +155,10 @@ setup_ln() { btcaddr=$(bt-cli getnewaddress) bt-cli sendtoaddress $l1addr 1 l1-cli connect $l2id@localhost:7272 - bt-cli generatetoaddress 101 $btcaddr + bt-cli generatetoaddress 6 $btcaddr sleep 5 l1-cli fundchannel $l2id 10000 normal false - bt-cli generatetoaddress 7 $btcaddr + bt-cli generatetoaddress 6 $btcaddr } stop_nodes() { diff --git a/db/bindings.c b/db/bindings.c index df8b3827c2df..4fc4ea8b88a5 100644 --- a/db/bindings.c +++ b/db/bindings.c @@ -188,6 +188,34 @@ void db_bind_signature(struct db_stmt *stmt, int col, db_bind_blob(stmt, col, buf, 64); } +void db_bind_partial_sig(struct db_stmt *stmt, int col, + const struct partial_sig *psig) +{ + u8 *buf = tal_arr(stmt, u8, 32); + int ret = secp256k1_musig_partial_sig_serialize(secp256k1_ctx, + buf, &psig->p_sig); + assert(ret == 1); + db_bind_blob(stmt, col, buf, 32); +} + +void db_bind_musig_session(struct db_stmt *stmt, int col, + const struct musig_session *session) +{ + u8 *buf = tal_arr(stmt, u8, 133); + memcpy(buf, session->session.data, 133); + db_bind_blob(stmt, col, buf, 133); +} + +void db_bind_musig_nonce(struct db_stmt *stmt, int col, + const struct nonce *nonce) +{ + u8 *buf = tal_arr(stmt, u8, 66); + int ret = secp256k1_musig_pubnonce_serialize(secp256k1_ctx, + buf, &nonce->nonce); + assert(ret == 1); + db_bind_blob(stmt, col, buf, 66); +} + void db_bind_timeabs(struct db_stmt *stmt, int col, struct timeabs t) { u64 timestamp = t.ts.tv_nsec + (((u64) t.ts.tv_sec) * ((u64) NSEC_IN_SEC)); diff --git a/db/bindings.h b/db/bindings.h index 298dc6d4838d..74db477d8396 100644 --- a/db/bindings.h +++ b/db/bindings.h @@ -43,6 +43,12 @@ void db_bind_short_channel_id_arr(struct db_stmt *stmt, int col, const struct short_channel_id *id); void db_bind_signature(struct db_stmt *stmt, int col, const secp256k1_ecdsa_signature *sig); +void db_bind_partial_sig(struct db_stmt *stmt, int col, + const struct partial_sig *psig); +void db_bind_musig_session(struct db_stmt *stmt, int col, + const struct musig_session *session); +void db_bind_musig_nonce(struct db_stmt *stmt, int col, + const struct nonce *nonce); void db_bind_timeabs(struct db_stmt *stmt, int col, struct timeabs t); void db_bind_tx(struct db_stmt *stmt, int col, const struct wally_tx *tx); void db_bind_psbt(struct db_stmt *stmt, int col, const struct wally_psbt *psbt); diff --git a/lightningd/channel.c b/lightningd/channel.c index d9f7fdff5529..123c0ba2dedd 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -394,7 +394,12 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u16 lease_chan_max_ppt, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, - struct bip340sig *last_update_sig) + struct bitcoin_tx *settle_tx, + struct partial_sig *their_psig, + struct partial_sig *our_psig, + struct musig_session *session, + struct nonce *their_next_nonce, + struct nonce *our_next_nonce) { struct channel *channel = tal(peer->ld, struct channel); struct amount_msat htlc_min, htlc_max; @@ -448,7 +453,15 @@ struct channel *new_channel(struct peer *peer, u64 dbid, if (last_sig) { channel->last_sig = *last_sig; } else { - channel->last_update_sig = *last_update_sig; + /* If we're not using ecdsa, we're doing eltoo... */ + assert(settle_tx); + channel->settle_tx = tal_steal(channel, settle_tx); + channel->settle_tx->chainparams = chainparams; + channel->eltoo_keyset.other_psig = *their_psig; + channel->eltoo_keyset.self_psig = *our_psig; + channel->eltoo_keyset.session = *session; + channel->eltoo_keyset.other_next_nonce = *their_next_nonce; + channel->eltoo_keyset.self_next_nonce = *our_next_nonce; } channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs); channel->channel_info = *channel_info; diff --git a/lightningd/channel.h b/lightningd/channel.h index 2b96c4966b91..35b0f12e45f6 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -3,6 +3,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -147,11 +148,12 @@ struct channel { struct bitcoin_tx *last_tx; enum wallet_tx_type last_tx_type; struct bitcoin_signature last_sig; - struct bip340sig last_update_sig; /* Eltoo only */ - struct partial_sig their_last_psig, our_last_psig; - struct musig_session session; const struct bitcoin_signature *last_htlc_sigs; + /* Eltoo-only fields */ + struct bitcoin_tx *settle_tx; + struct eltoo_keyset eltoo_keyset; + /* Keys for channel */ struct channel_info channel_info; @@ -323,7 +325,12 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u16 lease_chan_max_ppt, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, - struct bip340sig *update_sig); + struct bitcoin_tx *settle_tx, + struct partial_sig *their_psig, + struct partial_sig *our_psig, + struct musig_session *session, + struct nonce *their_next_nonce, + struct nonce *our_next_nonce); /* new_inflight - Create a new channel_inflight for a channel */ struct channel_inflight * diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 73258a8f2be2..75d8679e4adf 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -739,9 +739,9 @@ void peer_start_eltoo_channeld(struct channel *channel, channel->minimum_depth, &channel->our_config, &channel->channel_info.their_config, - &channel->their_last_psig, - &channel->our_last_psig, - &channel->session, + &channel->eltoo_keyset.other_psig, + &channel->eltoo_keyset.self_psig, + &channel->eltoo_keyset.session, &channel->channel_info.remote_fundingkey, &channel->channel_info.remote_fundingkey, /* &channel->channel_info.theirbase.payment,*/ diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 83a9ca876fe7..c5ad25d7f577 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -93,7 +93,12 @@ wallet_commit_channel(struct lightningd *ld, const u8 *our_upfront_shutdown_script, const u8 *remote_upfront_shutdown_script, const struct channel_type *type, - struct bip340sig *update_sig) + struct bitcoin_tx *settle_tx, + struct partial_sig *their_psig, + struct partial_sig *our_psig, + struct musig_session *session, + struct nonce *their_next_nonce, + struct nonce *our_next_nonce) { struct channel *channel; struct amount_msat our_msat; @@ -216,7 +221,12 @@ wallet_commit_channel(struct lightningd *ld, 0, NULL, 0, 0, /* No leases on v1s */ ld->config.htlc_minimum_msat, ld->config.htlc_maximum_msat, - update_sig); + settle_tx, + their_psig, + our_psig, + session, + their_next_nonce, + our_next_nonce); /* Now we finally put it in the database. */ wallet_channel_insert(ld->wallet, channel); @@ -351,13 +361,15 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, struct channel_info channel_info; struct channel_id cid; struct bitcoin_outpoint funding; - struct bip340sig first_update_sig; - struct bitcoin_tx *update_tx; + struct bitcoin_tx *update_tx, *settle_tx; struct channel *channel; struct lightningd *ld = openingd->ld; u8 *remote_upfront_shutdown_script; struct peer_fd *peer_fd; struct channel_type *type; + struct partial_sig their_psig, our_psig; + struct musig_session session; + struct nonce their_next_nonce, our_next_nonce; /* This is a new channel_info.their_config so set its ID to 0 */ channel_info.their_config.id = 0; @@ -365,10 +377,15 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, if (!fromwire_openingd_eltoo_funder_reply(resp, resp, &channel_info.their_config, &update_tx, - &first_update_sig, + &settle_tx, &fc->uc->minimum_depth, &channel_info.remote_fundingkey, &channel_info.theirbase.payment, + &their_psig, + &our_psig, + &session, + &their_next_nonce, + &our_next_nonce, &funding, &remote_upfront_shutdown_script, &type)) { @@ -410,7 +427,12 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, fc->our_upfront_shutdown_script, remote_upfront_shutdown_script, type, - &first_update_sig); + settle_tx, + &their_psig, + &our_psig, + &session, + &their_next_nonce, + &our_next_nonce); if (!channel) { was_pending(command_fail(fc->cmd, LIGHTNINGD, "Key generation failure")); @@ -501,7 +523,12 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, fc->our_upfront_shutdown_script, remote_upfront_shutdown_script, type, - NULL /* update_sig */); + NULL /* settle_tx */, + NULL /* their_psig */, + NULL /* our_psig */, + NULL /* session */, + NULL /* their_next_nonce */, + NULL /* our_next_nonce */); if (!channel) { was_pending(command_fail(fc->cmd, LIGHTNINGD, "Key generation failure")); @@ -529,8 +556,7 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, { const u8 *fwd_msg; struct channel_info channel_info; - struct bip340sig first_update_sig; - struct bitcoin_tx *settle_tx; + struct bitcoin_tx *update_tx, *settle_tx; struct channel_id cid; struct lightningd *ld = openingd->ld; struct bitcoin_outpoint funding; @@ -542,6 +568,10 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, struct peer_fd *peer_fd; struct channel_type *type; + struct partial_sig their_psig, our_psig; + struct musig_session session; + struct nonce their_next_nonce, our_next_nonce; + log_debug(uc->log, "Got opening_eltoo_fundee_finish_response"); /* This is a new channel_info.their_config, set its ID to 0 */ @@ -549,13 +579,17 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, peer_fd = new_peer_fd_arr(tmpctx, fds); - /* FIXME is this really the right fields to send? */ if (!fromwire_openingd_eltoo_fundee(tmpctx, reply, &channel_info.their_config, - &settle_tx, - &first_update_sig, + &update_tx, + &settle_tx, &channel_info.remote_fundingkey, &channel_info.theirbase.payment, + &their_psig, + &our_psig, + &session, + &their_next_nonce, + &our_next_nonce, &funding, &funding_sats, &push, @@ -575,12 +609,14 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, /* We make sure other basepoints are valid * even if unused... * FIXME wallet db gets upset if I don't do this due to statement construction... */ + /* FIXME Just copy by value? */ memcpy(&channel_info.theirbase.revocation, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); memcpy(&channel_info.theirbase.htlc, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); memcpy(&channel_info.theirbase.delayed_payment, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); memcpy(&channel_info.remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); memcpy(&channel_info.old_remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); + update_tx->chainparams = chainparams; settle_tx->chainparams = chainparams; derive_channel_id(&cid, &funding); @@ -588,7 +624,7 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, /* Consumes uc */ channel = wallet_commit_channel(ld, uc, &cid, - settle_tx, + update_tx, NULL /* remote_commit_sig */, &funding, funding_sats, @@ -599,7 +635,13 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, local_upfront_shutdown_script, remote_upfront_shutdown_script, type, - &first_update_sig); + settle_tx, + &their_psig, + &our_psig, + &session, + &their_next_nonce, + &our_next_nonce); + if (!channel) { uncommitted_channel_disconnect(uc, LOG_BROKEN, "Commit channel failed"); @@ -704,7 +746,12 @@ static void opening_fundee_finished(struct subd *openingd, local_upfront_shutdown_script, remote_upfront_shutdown_script, type, - NULL /* update_sig */); + NULL /* settle_tx */, + NULL /* their_psig */, + NULL /* our_psig */, + NULL /* session */, + NULL /* their_next_nonce */, + NULL /* our_next_nonce */); if (!channel) { uncommitted_channel_disconnect(uc, LOG_BROKEN, "Commit channel failed"); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 7d97ac327858..73020a464332 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -71,10 +71,6 @@ struct eltoo_state { struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; - /* FIXME This seems necesssary for opening... move all keys here? - also need to "forward" the nonce for normal channel operation */ - struct eltoo_keyset eltoo_keyset; - /* Initially temporary, then final channel id. */ struct channel_id channel_id; @@ -330,7 +326,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &state->eltoo_keyset.self_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->channel->eltoo_keyset.self_next_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -352,7 +348,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->our_funding_pubkey, &state->our_settlement_pubkey, /* FIXME is this set?? */ channel_flags, - &state->eltoo_keyset.self_next_nonce, + &state->channel->eltoo_keyset.self_next_nonce, open_tlvs); peer_write(state->pps, take(msg)); @@ -382,7 +378,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->remoteconf.max_accepted_htlcs, &state->their_funding_pubkey, &state->their_settlement_pubkey, - &state->eltoo_keyset.other_next_nonce, + &state->channel->eltoo_keyset.other_next_nonce, &accept_tlvs)) { peer_failed_err(state->pps, &state->channel_id, @@ -456,15 +452,14 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) static bool funder_finalize_channel_setup(struct eltoo_state *state, struct amount_msat local_msat, - struct bip340sig *update_sig, - struct bitcoin_tx **update_tx) + struct bitcoin_tx **update_tx, + struct bitcoin_tx **settle_tx) { u8 *msg; struct channel_id id_in; struct channel_id cid; struct wally_tx_output *direct_outputs[NUM_SIDES]; - struct bitcoin_tx *settle_tx; - struct partial_sig our_update_psig, their_update_psig; + struct bip340sig update_sig; /* Dummy fields since they're unused at time of channel creation */ struct partial_sig dummy_self_psig, dummy_other_psig; @@ -536,15 +531,15 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * peer's signature, via `funding_signed`, it will broadcast the funding * transaction. */ - settle_tx = initial_settle_channel_tx(state, state->channel, + *settle_tx = initial_settle_channel_tx(state, state->channel, direct_outputs); - if (!settle_tx) { + if (!*settle_tx) { negotiation_failed(state, "Could not make settle tx???"); return false; } - *update_tx = initial_update_channel_tx(state, settle_tx, state->channel); + *update_tx = initial_update_channel_tx(state, *settle_tx, state->channel); if (!*update_tx) { negotiation_failed(state, @@ -558,51 +553,52 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, msg = towire_hsmd_psign_update_tx(NULL, &state->channel_id, *update_tx, - settle_tx, + *settle_tx, &state->their_funding_pubkey, - &state->eltoo_keyset.other_next_nonce); + &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); status_debug("partial signature req on update tx %s, settlement tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", type_to_string(tmpctx, struct bitcoin_tx, *update_tx), - type_to_string(tmpctx, struct bitcoin_tx, settle_tx), + type_to_string(tmpctx, struct bitcoin_tx, *settle_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey), type_to_string(tmpctx, struct pubkey, &state->their_funding_pubkey), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.self_next_nonce), + &state->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.other_next_nonce)); + &state->channel->eltoo_keyset.other_next_nonce)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce, &state->eltoo_keyset.inner_pubkey)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &state->channel->eltoo_keyset.self_psig, + &state->channel->eltoo_keyset.session, &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* You can tell this has been a problem before, since there's a debug * message here: */ status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", - type_to_string(tmpctx, struct partial_sig, &our_update_psig), + type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.self_psig), type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey), type_to_string(tmpctx, struct pubkey, &state->their_funding_pubkey), type_to_string(tmpctx, struct pubkey, - &state->eltoo_keyset.inner_pubkey), + &state->channel->eltoo_keyset.inner_pubkey), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.self_next_nonce), + &state->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.other_next_nonce)); + &state->channel->eltoo_keyset.other_next_nonce)); /* Now we give our peer the partial signature for the first update * transaction. */ msg = towire_funding_created_eltoo(state, &state->channel_id, &state->funding.txid, state->funding.n, - &our_update_psig, - &state->eltoo_keyset.self_next_nonce); + &state->channel->eltoo_keyset.self_psig, + &state->channel->eltoo_keyset.self_next_nonce); peer_write(state->pps, msg); /* BOLT #2: @@ -624,7 +620,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!msg) return false; - if (!fromwire_funding_signed_eltoo(msg, &id_in, &their_update_psig, &state->eltoo_keyset.other_next_nonce)) + if (!fromwire_funding_signed_eltoo(msg, &id_in, &state->channel->eltoo_keyset.other_psig, &state->channel->eltoo_keyset.other_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); /* BOLT #2: @@ -672,15 +668,15 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ msg = towire_hsmd_combine_psig(NULL, &state->channel_id, - &our_update_psig, - &their_update_psig, - &state->eltoo_keyset.session, + &state->channel->eltoo_keyset.self_psig, + &state->channel->eltoo_keyset.other_psig, + &state->channel->eltoo_keyset.session, *update_tx, - settle_tx, - &state->eltoo_keyset.inner_pubkey); + *settle_tx, + &state->channel->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_combine_psig_reply(msg, update_sig)) { + if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { status_failed(STATUS_FAIL_HSM_IO, "Bad combine_psig_reply_reply %s", tal_hex(tmpctx, msg)); } @@ -698,16 +694,17 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, */ /* For now: Re-bind, add final script/tapscript info into PSBT */ bind_update_tx_to_funding_outpoint(*update_tx, - settle_tx, + *settle_tx, &state->funding, &state->channel->eltoo_keyset, &state->channel->eltoo_keyset.inner_pubkey, - update_sig); + &update_sig); + /* For debugging, remove later */ status_debug("Signed update transaction 0: %s", psbt_to_b64(NULL, (*update_tx)->psbt)); - status_debug("Settle transaction 0: %s", psbt_to_b64(NULL, settle_tx->psbt)); + status_debug("Settle transaction 0: %s", psbt_to_b64(NULL, (*settle_tx)->psbt)); peer_billboard(false, "Funding channel: opening negotiation succeeded"); @@ -716,9 +713,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, static u8 *funder_channel_complete(struct eltoo_state *state) { - /* Remote commitment tx */ - struct bitcoin_tx *tx; - struct bip340sig sig; + /* These transactions are ready to broadcast once returned(minus fees!) */ + struct bitcoin_tx *update_tx, *settle_tx; struct amount_msat local_msat; /* Update the billboard about what we're doing*/ @@ -736,16 +732,21 @@ static u8 *funder_channel_complete(struct eltoo_state *state) type_to_string(tmpctx, struct amount_sat, &state->funding_sats)); - if (!funder_finalize_channel_setup(state, local_msat, &sig, &tx)) + if (!funder_finalize_channel_setup(state, local_msat, &update_tx, &settle_tx)) return NULL; return towire_openingd_eltoo_funder_reply(state, &state->remoteconf, - tx, - &sig, + update_tx, + settle_tx, state->minimum_depth, - &state->their_funding_pubkey, - &state->their_settlement_pubkey, + &state->channel->eltoo_keyset.other_funding_key, + &state->channel->eltoo_keyset.other_settle_key, + &state->channel->eltoo_keyset.other_psig, + &state->channel->eltoo_keyset.self_psig, + &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.other_next_nonce, + &state->channel->eltoo_keyset.self_next_nonce, &state->funding, state->upfront_shutdown_script[REMOTE], state->channel_type); @@ -765,13 +766,15 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; - struct partial_sig our_update_psig, their_update_psig; + struct partial_sig their_update_psig; /* These never leave openingd, keep local. funding_* nonces go in keyset and propagated * to eltoo_channeld! */ struct nonce their_opening_nonce, our_opening_nonce; + /* Stored here before channel struct is made, then copied in */ + struct nonce their_second_nonce; /* Dummy fields since they're unused at time of channel creation */ - struct partial_sig dummy_self_psig, dummy_other_psig; + struct partial_sig dummy_self_psig; struct musig_session dummy_session; /* BOLT #2: @@ -950,7 +953,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->funding.txid, &funding_txout, &their_update_psig, - &state->eltoo_keyset.other_next_nonce)) + &their_second_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); /* We only allow 16 bits for this on the wire. */ @@ -1002,12 +1005,13 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->our_settlement_pubkey, &state->their_settlement_pubkey, &dummy_self_psig, - &dummy_other_psig, + &their_update_psig, &dummy_session, state->channel_type, feature_offered(state->their_features, OPT_LARGE_CHANNELS), REMOTE); + /* We don't expect this to fail, but it does do some additional * internal sanity checks. */ if (!state->channel) @@ -1086,33 +1090,35 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) msg = wire_sync_read(tmpctx, HSM_FD); /* Reply puts next nonce into keyset and xmitted with funding_signed_eltoo */ - if (!fromwire_hsmd_psign_update_tx_reply(msg, &our_update_psig, &state->eltoo_keyset.session, &state->eltoo_keyset.self_next_nonce, &state->eltoo_keyset.inner_pubkey)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, + &state->channel->eltoo_keyset.self_psig, &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", - type_to_string(tmpctx, struct partial_sig, &our_update_psig), + type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.self_psig), type_to_string(tmpctx, struct bitcoin_tx, update_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey), type_to_string(tmpctx, struct pubkey, &state->their_funding_pubkey), type_to_string(tmpctx, struct pubkey, - &state->eltoo_keyset.inner_pubkey), + &state->channel->eltoo_keyset.inner_pubkey), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.self_next_nonce), + &state->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, - &state->eltoo_keyset.other_next_nonce)); + &state->channel->eltoo_keyset.other_next_nonce)); /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ msg = towire_hsmd_combine_psig(NULL, &state->channel_id, - &our_update_psig, + &state->channel->eltoo_keyset.self_psig, &their_update_psig, - &state->eltoo_keyset.session, + &state->channel->eltoo_keyset.session, update_tx, settle_tx, - &state->eltoo_keyset.inner_pubkey); + &state->channel->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { @@ -1122,14 +1128,28 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ - msg = towire_funding_signed_eltoo(state, &state->channel_id, &our_update_psig, &state->eltoo_keyset.self_next_nonce); + msg = towire_funding_signed_eltoo(state, &state->channel_id, &state->channel->eltoo_keyset.self_psig, &state->channel->eltoo_keyset.self_next_nonce); + + /* Stick full signature into tx, ready for brodcast(minus fees) */ + bind_update_tx_to_funding_outpoint(update_tx, + settle_tx, + &state->funding, + &state->channel->eltoo_keyset, + &state->channel->eltoo_keyset.inner_pubkey, + &update_sig); + /* FIXME Report everything including both next nonces ala openingd_eltoo_funder_reply */ return towire_openingd_eltoo_fundee(state, &state->remoteconf, update_tx, - &update_sig, + settle_tx, &state->their_funding_pubkey, &state->their_settlement_pubkey, + &state->channel->eltoo_keyset.other_psig, + &state->channel->eltoo_keyset.self_psig, + &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.other_next_nonce, + &state->channel->eltoo_keyset.self_next_nonce, &state->funding, state->funding_sats, state->push_msat, diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv index a7cbdc6c64f7..1fb50b3b7879 100644 --- a/openingd/eltoo_openingd_wire.csv +++ b/openingd/eltoo_openingd_wire.csv @@ -28,14 +28,20 @@ msgdata,openingd_eltoo_init,dev_temporary_channel_id,?byte,32 #include # Openingd->master: we've successfully offered channel. -# This gives their psig, means we can broadcast tx: we're done. +# Although we have final txs in-hand, we send all signing info +# to recover channel on reestablishment msgtype,openingd_eltoo_funder_reply,6601 msgdata,openingd_eltoo_funder_reply,their_config,channel_config, -msgdata,openingd_eltoo_funder_reply,first_commit,bitcoin_tx, -msgdata,openingd_eltoo_funder_reply,first_update_sig,bip340sig, +msgdata,openingd_eltoo_funder_reply,first_update,bitcoin_tx, +msgdata,openingd_eltoo_funder_reply,first_settle,bitcoin_tx, msgdata,openingd_eltoo_funder_reply,minimum_depth,u32, msgdata,openingd_eltoo_funder_reply,remote_funding_key,pubkey, msgdata,openingd_eltoo_funder_reply,remote_settlement_key,pubkey, +msgdata,openingd_eltoo_funder_reply,other_psig,partial_sig, +msgdata,openingd_eltoo_funder_reply,self_psig,partial_sig, +msgdata,openingd_eltoo_funder_reply,session,musig_session, +msgdata,openingd_eltoo_funder_reply,their_next_nonce,nonce, +msgdata,openingd_eltoo_funder_reply,our_next_nonce,nonce, msgdata,openingd_eltoo_funder_reply,funding,bitcoin_outpoint, msgdata,openingd_eltoo_funder_reply,shutdown_len,u16, msgdata,openingd_eltoo_funder_reply,shutdown_scriptpubkey,u8,shutdown_len @@ -77,10 +83,15 @@ msgdata,openingd_eltoo_failed,reason,wirestring, # This gives their txid and info, means we can send funding_signed: we're done. msgtype,openingd_eltoo_fundee,6503 msgdata,openingd_eltoo_fundee,their_config,channel_config, -msgdata,openingd_eltoo_fundee,first_settlement,bitcoin_tx, -msgdata,openingd_eltoo_fundee,first_update_sig,bip340sig, +msgdata,openingd_eltoo_fundee,first_update,bitcoin_tx, +msgdata,openingd_eltoo_fundee,first_settle,bitcoin_tx, msgdata,openingd_eltoo_fundee,remote_fundingkey,pubkey, msgdata,openingd_eltoo_fundee,remote_settlekey,pubkey, +msgdata,openingd_eltoo_fundee,other_psig,partial_sig, +msgdata,openingd_eltoo_fundee,self_psig,partial_sig, +msgdata,openingd_eltoo_fundee,session,musig_session, +msgdata,openingd_eltoo_fundee,their_next_nonce,nonce, +msgdata,openingd_eltoo_fundee,our_next_nonce,nonce, msgdata,openingd_eltoo_fundee,funding,bitcoin_outpoint, msgdata,openingd_eltoo_fundee,funding_satoshis,amount_sat, msgdata,openingd_eltoo_fundee,push_msat,amount_msat, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index ad291c0f78f2..725038ced805 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1628,7 +1628,12 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) 7777, 22, AMOUNT_MSAT(0), AMOUNT_MSAT(-1ULL), - NULL /* last_update_sig */); + NULL /* settle_tx */, + NULL /* their_psig */, + NULL /* our_psig */, + NULL /* session */, + NULL /* their_next_nonce */, + NULL /* our_next_nonce */); db_begin_transaction(w->db); CHECK(!wallet_err); wallet_channel_insert(w, chan); diff --git a/wallet/wallet.c b/wallet/wallet.c index 0ebe9b57f4b0..3afd13e66e2f 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1486,7 +1486,12 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm lease_chan_max_ppt, htlc_minimum_msat, htlc_maximum_msat, - NULL /* FIXME last_update_sig */); + NULL /* FIXME settle_tx */, + NULL /* FIXME their_psig */, + NULL /* FIXME our_psig */, + NULL /* FIXME session */, + NULL /* FIXME their_next_nonce */, + NULL /* FIXME our_next_nonce */); if (!wallet_channel_load_inflights(w, chan)) { tal_free(chan); @@ -1866,7 +1871,13 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " lease_chan_max_ppt=?," // 41 " htlc_minimum_msat=?," // 42 " htlc_maximum_msat=?" // 43 - " WHERE id=?")); // 44 + " settle_tx=?" // 44 + " their_psig=?" // 45 + " our_psig=?" // 46 + " musig_session=?" // 47 + " their_next_nonce=?" // 48 + " our_next_nonce=?" // 49 + " WHERE id=?")); // 50 db_bind_u64(stmt, 0, chan->their_shachain.id); if (chan->scid) db_bind_short_channel_id(stmt, 1, chan->scid); @@ -1931,7 +1942,13 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) } db_bind_amount_msat(stmt, 42, &chan->htlc_minimum_msat); db_bind_amount_msat(stmt, 43, &chan->htlc_maximum_msat); - db_bind_u64(stmt, 44, chan->dbid); + db_bind_psbt(stmt, 44, chan->settle_tx->psbt); + db_bind_partial_sig(stmt, 45, &chan->eltoo_keyset.other_psig); + db_bind_partial_sig(stmt, 46, &chan->eltoo_keyset.self_psig); + db_bind_musig_session(stmt, 47, &chan->eltoo_keyset.session); + db_bind_musig_nonce(stmt, 48, &chan->eltoo_keyset.other_next_nonce); + db_bind_musig_nonce(stmt, 49, &chan->eltoo_keyset.self_next_nonce); + db_bind_u64(stmt, 50, chan->dbid); db_exec_prepared_v2(take(stmt)); wallet_channel_config_save(w, &chan->channel_info.their_config); From a18487772bbc523e9cd8fcc767b00bc8d13cde08 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 13 Sep 2022 16:17:36 -0400 Subject: [PATCH 173/283] Back to where I was before with paying invoice broken --- openingd/eltoo_openingd.c | 33 +++++++++++++++++++++------------ wallet/db.c | 8 ++++++++ wallet/wallet.c | 12 ++++++------ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 73020a464332..c937235f3c84 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -71,6 +71,9 @@ struct eltoo_state { struct pubkey their_funding_pubkey; struct pubkey their_settlement_pubkey; + /* Storage for nonces to be used in funding_*_eltoo */ + struct nonce our_init_nonce, their_init_nonce; + /* Initially temporary, then final channel id. */ struct channel_id channel_id; @@ -326,7 +329,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &state->channel->eltoo_keyset.self_next_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->our_init_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -348,7 +351,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->our_funding_pubkey, &state->our_settlement_pubkey, /* FIXME is this set?? */ channel_flags, - &state->channel->eltoo_keyset.self_next_nonce, + &state->our_init_nonce, open_tlvs); peer_write(state->pps, take(msg)); @@ -378,7 +381,7 @@ static u8 *funder_channel_start(struct eltoo_state *state, u8 channel_flags) &state->remoteconf.max_accepted_htlcs, &state->their_funding_pubkey, &state->their_settlement_pubkey, - &state->channel->eltoo_keyset.other_next_nonce, + &state->their_init_nonce, &accept_tlvs)) { peer_failed_err(state->pps, &state->channel_id, @@ -515,6 +518,11 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, OPT_LARGE_CHANNELS), /* Opener is local */ LOCAL); + + /* Move initial nonces into place FIXME pass into new_initial_eltoo_channel? */ + state->channel->eltoo_keyset.other_next_nonce = state->their_init_nonce; + state->channel->eltoo_keyset.self_next_nonce = state->our_init_nonce; + /* We were supposed to do enough checks above, but just in case, * new_initial_channel will fail to create absurd channels */ if (!state->channel) @@ -767,9 +775,6 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct partial_sig their_update_psig; - /* These never leave openingd, keep local. funding_* nonces go in keyset and propagated - * to eltoo_channeld! */ - struct nonce their_opening_nonce, our_opening_nonce; /* Stored here before channel struct is made, then copied in */ struct nonce their_second_nonce; @@ -797,7 +802,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->their_funding_pubkey, &state->their_settlement_pubkey, &channel_flags, - &their_opening_nonce, + &state->their_init_nonce, &open_tlvs)) peer_failed_err(state->pps, &state->channel_id, @@ -917,7 +922,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &our_opening_nonce)) { + if (!fromwire_hsmd_gen_nonce_reply(msg, &state->our_init_nonce)) { peer_failed_err(state->pps, &state->channel_id, "Failed to get nonce for channel: %s", tal_hex(msg, msg)); @@ -935,7 +940,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->localconf.max_accepted_htlcs, &state->our_funding_pubkey, &state->our_settlement_pubkey, - &our_opening_nonce, + &state->our_init_nonce, accept_tlvs); peer_write(state->pps, take(msg)); @@ -1012,6 +1017,10 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) OPT_LARGE_CHANNELS), REMOTE); + /* Move initial nonces into place FIXME pass into new_initial_eltoo_channel? */ + state->channel->eltoo_keyset.other_next_nonce = state->their_init_nonce; + state->channel->eltoo_keyset.self_next_nonce = state->our_init_nonce; + /* We don't expect this to fail, but it does do some additional * internal sanity checks. */ if (!state->channel) @@ -1074,7 +1083,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) update_tx, settle_tx, &state->their_funding_pubkey, - &their_opening_nonce); + &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); status_debug("partial signature req on tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", @@ -1084,9 +1093,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) type_to_string(tmpctx, struct pubkey, &state->their_funding_pubkey), type_to_string(tmpctx, struct nonce, - &our_opening_nonce), + &state->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, - &their_opening_nonce)); + &state->channel->eltoo_keyset.other_next_nonce)); msg = wire_sync_read(tmpctx, HSM_FD); /* Reply puts next nonce into keyset and xmitted with funding_signed_eltoo */ diff --git a/wallet/db.c b/wallet/db.c index 3fb617a89dab..160b9b7b041e 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -141,6 +141,14 @@ static struct migration dbmigrations[] = { " last_sig BLOB," " closing_fee_received INTEGER," " closing_sig_received BLOB," + /* START Eltoo stuff*/ + " settle_tx BLOB," + " their_psig BLOB," + " our_psig BLOB," + " musig_session BLOB," + " their_next_nonce BLOB," + " our_next_nonce BLOB," + /* END Eltoo stuff */ " PRIMARY KEY (id)" ");"), NULL}, diff --git a/wallet/wallet.c b/wallet/wallet.c index 3afd13e66e2f..5c9f798d1cdc 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1870,12 +1870,12 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " lease_chan_max_msat=?," // 40 " lease_chan_max_ppt=?," // 41 " htlc_minimum_msat=?," // 42 - " htlc_maximum_msat=?" // 43 - " settle_tx=?" // 44 - " their_psig=?" // 45 - " our_psig=?" // 46 - " musig_session=?" // 47 - " their_next_nonce=?" // 48 + " htlc_maximum_msat=?," // 43 + " settle_tx=?," // 44 + " their_psig=?," // 45 + " our_psig=?," // 46 + " musig_session=?," // 47 + " their_next_nonce=?," // 48 " our_next_nonce=?" // 49 " WHERE id=?")); // 50 db_bind_u64(stmt, 0, chan->their_shachain.id); From 2e6e14799125de29162f23ff10eb97c01404c7d8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 14 Sep 2022 10:33:21 -0400 Subject: [PATCH 174/283] Try to move htlc resolution forward --- channeld/channeld_wire.csv | 2 + channeld/eltoo_channeld.c | 7 ++++ lightningd/channel_control.c | 8 ++-- lightningd/peer_htlcs.c | 73 ++++++++++++++++++++++++++++++++++++ lightningd/peer_htlcs.h | 4 ++ 5 files changed, 91 insertions(+), 3 deletions(-) diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index fd023132d4d6..b836649eef67 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -291,6 +291,8 @@ msgdata,channeld_init_eltoo,their_config,channel_config, msgdata,channeld_init_eltoo,their_update_psig,partial_sig, msgdata,channeld_init_eltoo,our_update_psig,partial_sig, msgdata,channeld_init_eltoo,session,musig_session, +msgdata,channeld_init_eltoo,their_next_nonce,nonce, +msgdata,channeld_init_eltoo,our_next_nonce,nonce, msgdata,channeld_init_eltoo,their_funding_pubkey,pubkey, msgdata,channeld_init_eltoo,their_settle_pubkey,pubkey, msgdata,channeld_init_eltoo,opener,enum side, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 17c6aae68964..89fa925769a1 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -2057,6 +2057,7 @@ static void init_channel(struct eltoo_peer *peer) struct pubkey funding_pubkey[NUM_SIDES]; struct pubkey settle_pubkey[NUM_SIDES]; struct partial_sig psigs[NUM_SIDES]; + struct nonce nonces[NUM_SIDES]; struct musig_session session; struct channel_config conf[NUM_SIDES]; struct bitcoin_outpoint funding; @@ -2092,6 +2093,8 @@ static void init_channel(struct eltoo_peer *peer) &psigs[REMOTE], &psigs[LOCAL], &session, + &nonces[REMOTE], + &nonces[LOCAL], &funding_pubkey[REMOTE], &settle_pubkey[REMOTE], &opener, @@ -2190,6 +2193,10 @@ static void init_channel(struct eltoo_peer *peer) OPT_LARGE_CHANNELS), opener); + /* FIXME new_full_eltoo_channel should take the nonces... */ + peer->channel->eltoo_keyset.other_next_nonce = nonces[REMOTE]; + peer->channel->eltoo_keyset.self_next_nonce = nonces[LOCAL]; + if (!channel_force_htlcs(peer->channel, cast_const2(const struct existing_htlc **, htlcs))) status_failed(STATUS_FAIL_INTERNAL_ERROR, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 75d8679e4adf..56ffdaa98b33 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -595,13 +595,13 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) handle_local_private_channel(sd->channel, msg); break; case WIRE_CHANNELD_GOT_UPDATESIG: - /* FIXME handle this */ + peer_got_updatesig(sd->channel, msg); break; case WIRE_CHANNELD_SENDING_UPDATESIG: - /* FIXME handle this */ + peer_sending_updatesig(sd->channel, msg); break; case WIRE_CHANNELD_GOT_ACK: - /* FIXME handle this */ + peer_got_ack(sd->channel, msg); break; case WIRE_CHANNELD_INIT_ELTOO: case WIRE_CHANNELD_GOT_UPDATESIG_REPLY: @@ -742,6 +742,8 @@ void peer_start_eltoo_channeld(struct channel *channel, &channel->eltoo_keyset.other_psig, &channel->eltoo_keyset.self_psig, &channel->eltoo_keyset.session, + &channel->eltoo_keyset.other_next_nonce, + &channel->eltoo_keyset.self_next_nonce, &channel->channel_info.remote_fundingkey, &channel->channel_info.remote_fundingkey, /* &channel->channel_info.theirbase.payment,*/ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 763ce23a4fb1..f58dd54e8bcc 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1877,6 +1877,79 @@ static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) channel->min_possible_feerate = feerate; } +void peer_got_updatesig(struct channel *channel, const u8 *msg) +{ + abort(); +} + +void peer_got_ack(struct channel *channel, const u8 *msg) +{ + abort(); +} + +void peer_sending_updatesig(struct channel *channel, const u8 *msg) +{ + u64 update_num; + struct changed_htlc *changed_htlcs; + size_t i, maxid = 0, num_local_added = 0; + struct lightningd *ld = channel->peer->ld; + + /* These are unused currently... */ + struct partial_sig our_update_psig; + struct musig_session session; + + if (!fromwire_channeld_sending_updatesig(msg, msg, + &update_num, + &changed_htlcs, + &our_update_psig, &session)) { + channel_internal_error(channel, "bad channel_sending_updatesig %s", + tal_hex(channel, msg)); + return; + } + + for (i = 0; i < tal_count(changed_htlcs); i++) { + if (!changed_htlc(channel, changed_htlcs + i)) { + channel_internal_error(channel, + "channel_sending_commitsig: update failed"); + return; + } + + /* While we're here, sanity check added ones are in + * ascending order. */ + if (changed_htlcs[i].newstate == SENT_ADD_COMMIT) { + num_local_added++; + if (changed_htlcs[i].id > maxid) + maxid = changed_htlcs[i].id; + } + } + + if (num_local_added != 0) { + if (maxid != channel->next_htlc_id + num_local_added - 1) { + channel_internal_error(channel, + "channel_sending_updatesig:" + " Added %"PRIu64", maxid now %"PRIu64 + " from %"PRIu64, + num_local_added, maxid, channel->next_htlc_id); + return; + } + channel->next_htlc_id += num_local_added; + } + + if (!peer_save_commitsig_sent(channel, update_num)) + return; + + /* Last was commit. FIXME do we want to reuse these fields? maybe? */ + channel->last_was_revoke = false; + tal_free(channel->last_sent_commit); + channel->last_sent_commit = tal_steal(channel, changed_htlcs); + wallet_channel_save(ld->wallet, channel); + + /* Tell it we've got it, and to go ahead. */ + subd_send_msg(channel->owner, + take(towire_channeld_sending_updatesig_reply(msg))); +} + + void peer_sending_commitsig(struct channel *channel, const u8 *msg) { u64 commitnum; diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 1bcef7bb3502..5cd04581ece9 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -36,6 +36,10 @@ void peer_sending_commitsig(struct channel *channel, const u8 *msg); void peer_got_commitsig(struct channel *channel, const u8 *msg); void peer_got_revoke(struct channel *channel, const u8 *msg); +void peer_sending_updatesig(struct channel *channel, const u8 *msg); +void peer_got_updatesig(struct channel *channel, const u8 *msg); +void peer_got_ack(struct channel *channel, const u8 *msg); + void update_per_commit_point(struct channel *channel, const struct pubkey *per_commitment_point); From 18b26eae343966f2da928c74d0aa397174c31557 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 14 Sep 2022 15:38:34 -0400 Subject: [PATCH 175/283] Getting all the way to ACK construction --- channeld/eltoo_channeld.c | 70 ++++++++++++++++++++- channeld/eltoo_full_channel.c | 32 +++++----- channeld/settle_tx.c | 8 +++ common/initial_channel.h | 1 + common/initial_eltoo_channel.c | 1 - common/initial_settlement_tx.c | 2 +- contrib/startup_regtest.sh | 2 + hsmd/libhsmd.c | 18 +++++- lightningd/channel_control.c | 3 +- lightningd/test/run-invoice-select-inchan.c | 3 - openingd/eltoo_openingd.c | 53 +++++++++++----- wallet/test/run-wallet.c | 6 ++ 12 files changed, 159 insertions(+), 40 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 89fa925769a1..d68626b5a392 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -833,7 +833,7 @@ static void send_update(struct eltoo_peer *peer) update_and_settle_txs = eltoo_channel_txs(tmpctx, &htlc_map, direct_outputs, peer->channel, - peer->next_index, REMOTE); + peer->next_index, LOCAL); msg = towire_hsmd_psign_update_tx(tmpctx, &peer->channel_id, @@ -842,12 +842,43 @@ static void send_update(struct eltoo_peer *peer) &peer->channel->eltoo_keyset.other_funding_key, &peer->channel->eltoo_keyset.other_next_nonce); + status_debug("partial signature req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce)); + hsmd_msg = hsm_req(tmpctx, take(msg)); if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Reading psign_update_tx reply: %s", tal_hex(tmpctx, msg)); + /* We don't learn their new nonce until we get ACK... */ + status_debug("partial signature %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, OLD their nonce %s", + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce)); + #if DEVELOPER if (peer->dev_disable_commit) { (*peer->dev_disable_commit)--; @@ -1018,6 +1049,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) struct bitcoin_tx **update_and_settle_txs; struct bip340sig update_sig; const struct htlc **htlc_map, **changed_htlcs; + struct nonce their_next_nonce; changed_htlcs = tal_arr(msg, const struct htlc *, 0); /* Does our counterparty offer any changes? */ @@ -1037,7 +1069,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) } if (!fromwire_update_signed(msg, - &channel_id, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) + &channel_id, &peer->channel->eltoo_keyset.other_psig, &their_next_nonce)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad update_signed %s", tal_hex(msg, msg)); @@ -1055,12 +1087,46 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) update_and_settle_txs[1], &peer->channel->eltoo_keyset.other_funding_key, &peer->channel->eltoo_keyset.other_next_nonce); + + status_debug("partial signature req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce)); + + /* Slide their newest nonce into place after consuming it above */ + peer->channel->eltoo_keyset.other_next_nonce = their_next_nonce; + wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); + status_debug("partial signature %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), + type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce)); + /* Before replying, make sure signature is correct */ msg = towire_hsmd_combine_psig(NULL, &peer->channel_id, diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 17d7cc7f1bd1..6692e0583937 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -247,23 +247,25 @@ struct bitcoin_tx **eltoo_channel_txs(const tal_t *ctx, struct wally_tx_output *direct_outputs[NUM_SIDES], const struct channel *channel, u64 update_number, - enum side side) + enum side side) /* FIXME remove */ { + assert(side == LOCAL); struct bitcoin_tx **txs; const struct htlc **committed; /* Figure out what @side will already be committed to. */ - gather_htlcs(ctx, channel, side, &committed, NULL, NULL); + /* FIXME how does "side" work here? We're doing both sides. */ + gather_htlcs(ctx, channel, LOCAL, &committed, NULL, NULL); txs = tal_arr(ctx, struct bitcoin_tx *, 2); /* settle txn has finalized witness data, just needs prevout rebinding */ txs[1] = settle_tx( ctx, &channel->funding, channel->funding_sats, - channel->config[side].shared_delay, + channel->config[LOCAL].shared_delay, &channel->eltoo_keyset, - channel->config[side].dust_limit, channel->view[side].owed[side], - channel->view[side].owed[!side], committed, htlcmap, direct_outputs, + channel->config[LOCAL].dust_limit, channel->view[LOCAL].owed[LOCAL], + channel->view[LOCAL].owed[REMOTE], committed, htlcmap, direct_outputs, update_number); /* We only fill out witness data for update transactions for onchain events */ @@ -611,10 +613,10 @@ enum channel_remove_err channel_fail_htlc(struct channel *channel, static void htlc_incstate(struct channel *channel, struct htlc *htlc, - enum side sidechanged, struct balance owed[NUM_SIDES]) { int preflags, postflags; + enum side sidechanged = LOCAL; const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED); status_debug("htlc %"PRIu64": %s->%s", htlc->id, @@ -651,7 +653,7 @@ static void htlc_incstate(struct channel *channel, /* Returns flags which were changed. */ static int change_htlcs(struct channel *channel, - enum side sidechanged, + // FIXME not needed? enum side sidechanged, const enum htlc_state *htlc_states, size_t n_hstates, const struct htlc ***htlcs, @@ -664,14 +666,14 @@ static int change_htlcs(struct channel *channel, struct balance owed[NUM_SIDES]; for (i = 0; i < NUM_SIDES; i++) - to_balance(&owed[i], channel->view[sidechanged].owed[i]); + to_balance(&owed[i], channel->view[LOCAL].owed[i]); for (h = htlc_map_first(channel->htlcs, &it); h; h = htlc_map_next(channel->htlcs, &it)) { for (i = 0; i < n_hstates; i++) { if (h->state == htlc_states[i]) { - htlc_incstate(channel, h, sidechanged, owed); + htlc_incstate(channel, h, owed); dump_htlc(h, prefix); htlc_arr_append(htlcs, h); cflags |= (eltoo_htlc_state_flags(htlc_states[i]) @@ -681,13 +683,13 @@ static int change_htlcs(struct channel *channel, } for (i = 0; i < NUM_SIDES; i++) { - if (!balance_ok(&owed[i], &channel->view[sidechanged].owed[i])) { + if (!balance_ok(&owed[i], &channel->view[LOCAL].owed[i])) { status_failed(STATUS_FAIL_INTERNAL_ERROR, "%s: %s balance underflow: %s -> %"PRId64, - side_to_str(sidechanged), + side_to_str(LOCAL), side_to_str(i), type_to_string(tmpctx, struct amount_msat, - &channel->view[sidechanged].owed[i]), + &channel->view[LOCAL].owed[i]), owed[i].msat); } } @@ -703,7 +705,7 @@ bool channel_sending_update(struct channel *channel, SENT_REMOVE_HTLC }; status_debug("Trying update"); - change = change_htlcs(channel, REMOTE, states, ARRAY_SIZE(states), + change = change_htlcs(channel, states, ARRAY_SIZE(states), htlcs, "sending_commit"); if (!change) return false; @@ -719,7 +721,7 @@ bool channel_rcvd_update_sign_ack(struct channel *channel, SENT_REMOVE_UPDATE }; status_debug("Received update_sign_ack"); - change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), + change = change_htlcs(channel, states, ARRAY_SIZE(states), htlcs, "rcvd_update_sign_ack"); /* FIXME what should this be? ... Their ack can queue changes on our side. */ @@ -735,7 +737,7 @@ bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs) RCVD_REMOVE_UPDATE }; status_debug("Received Update"); - change = change_htlcs(channel, LOCAL, states, ARRAY_SIZE(states), + change = change_htlcs(channel, states, ARRAY_SIZE(states), htlcs, "rcvd_update"); if (!change) return false; diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 2ffb778dd5cb..a91e35d2f740 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -7,6 +7,8 @@ #include #include +#include + #ifndef SUPERVERBOSE #define SUPERVERBOSE(...) #endif @@ -106,6 +108,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, struct wally_tx_output *direct_outputs[NUM_SIDES], u64 obscured_update_number) { + printf("SELF PAY: %lu, OTHER PAY: %lu\n", self_pay.millisatoshis, other_pay.millisatoshis); struct amount_msat total_pay; struct bitcoin_tx *tx; size_t i, n, num_untrimmed; @@ -128,6 +131,11 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); + printf("self update key: %s\n", tal_hexstr(ctx, &eltoo_keyset->self_funding_key, 33)); + printf("other update key: %s\n", tal_hexstr(ctx, &eltoo_keyset->other_funding_key, 33)); + printf("self settle key: %s\n", tal_hexstr(ctx, &eltoo_keyset->self_settle_key, 33)); + printf("other settle key: %s\n", tal_hexstr(ctx, &eltoo_keyset->other_settle_key, 33)); + /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, &keyagg_cache, diff --git a/common/initial_channel.h b/common/initial_channel.h index 61943ecaabaa..932cf64fa50f 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -61,6 +61,7 @@ struct channel { struct height_states *blockheight_states; /* What it looks like to each side. */ + /* FIXME for eltoo, treating only LOCAL side as used... for now? */ struct channel_view view[NUM_SIDES]; /* Features which apply to this channel. */ diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index 76568617f3b2..ca7f6cd0a588 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -51,7 +51,6 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, channel->eltoo_keyset.other_funding_key = *remote_funding_pubkey; channel->eltoo_keyset.self_settle_key = *local_settle_pubkey; channel->eltoo_keyset.other_settle_key = *remote_settle_pubkey; - channel->eltoo_keyset.other_settle_key = *remote_settle_pubkey; channel->eltoo_keyset.self_psig = *self_psig; channel->eltoo_keyset.other_psig = *other_psig; channel->eltoo_keyset.session = *session; diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index edfe0f6cdbac..16d515162a2c 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -33,7 +33,7 @@ int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *elto pubkey_ptrs[1] = &eltoo_keyset->other_funding_key; tapleaf_scripts[0] = bitcoin_tapscript_to_node(tmpctx, receiver_pubkey); - SUPERVERBOSE("SELF TO NODE: %s\n", tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); + printf("RECEIVER: %u, RECEIVER(SETTLE) PUBKEY: %s, SELF TO NODE: %s\n", receiver, tal_hexstr(tmpctx, receiver_pubkey, 33), tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); bipmusig_finalize_keys(&taproot_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out.u.u8); diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 791657c45de8..a88934200947 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -159,6 +159,8 @@ setup_ln() { sleep 5 l1-cli fundchannel $l2id 10000 normal false bt-cli generatetoaddress 6 $btcaddr + invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) + l1-cli pay $invoice } stop_nodes() { diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 51bf7e88fa67..580da9eee520 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -17,6 +17,8 @@ #include #include +#include + #if DEVELOPER /* If they specify --dev-force-privkey it ends up in here. */ struct privkey *dev_force_privkey; @@ -1383,6 +1385,7 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) const secp256k1_musig_partial_sig *p_sig_ptrs[2]; struct musig_session session; + int i; if (!fromwire_hsmd_combine_psig(tmpctx, msg_in, &channel_id, &p_sig_1, @@ -1399,7 +1402,12 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) annex = make_eltoo_annex(tmpctx, settle_tx); bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &hash_out); - + printf("validate taproot Sighash: "); + for (i = 0; i < 32; i++) + { + printf("%02X", hash_out.sha.u.u8[i]); + } + printf("\n"); if (!bipmusig_partial_sigs_combine_verify(p_sig_ptrs, /* num_signers */ 2, @@ -1437,6 +1445,8 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) u8 *annex; struct sha256_double hash_out; + int i; + if (!fromwire_hsmd_psign_update_tx(tmpctx, msg_in, &channel_id, &update_tx, @@ -1472,6 +1482,12 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) /* n_pubkeys */ 2); bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &hash_out); + printf("sign taproot Sighash: "); + for (i = 0; i < 32; i++) + { + printf("%02X", hash_out.sha.u.u8[i]); + } + printf("\n"); pubnonce_ptrs[0] = &remote_nonce.nonce; pubnonce_ptrs[1] = &secretstuff.pub_nonce.nonce; diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 56ffdaa98b33..12befba6627d 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -745,8 +745,7 @@ void peer_start_eltoo_channeld(struct channel *channel, &channel->eltoo_keyset.other_next_nonce, &channel->eltoo_keyset.self_next_nonce, &channel->channel_info.remote_fundingkey, - &channel->channel_info.remote_fundingkey, -/* &channel->channel_info.theirbase.payment,*/ + &channel->channel_info.theirbase.payment, /* their_settle_pubkey */ channel->opener, channel->feerate_base, channel->feerate_ppm, diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 81c6f043863f..382861851820 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -88,9 +88,6 @@ struct htlc_out *channel_has_htlc_out(struct channel *channel UNNEEDED) struct channel_inflight *channel_inflight_find(struct channel *channel UNNEEDED, const struct bitcoin_txid *txid UNNEEDED) { fprintf(stderr, "channel_inflight_find called!\n"); abort(); } -/* Generated stub for channel_internal_error */ -void channel_internal_error(struct channel *channel UNNEEDED, const char *fmt UNNEEDED, ...) -{ fprintf(stderr, "channel_internal_error called!\n"); abort(); } /* Generated stub for channel_last_funding_feerate */ u32 channel_last_funding_feerate(const struct channel *channel UNNEEDED) { fprintf(stderr, "channel_last_funding_feerate called!\n"); abort(); } diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index c937235f3c84..8cdcba88071d 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -566,17 +566,21 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); - status_debug("partial signature req on update tx %s, settlement tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", + status_debug("partial signature req on update tx %s, settlement tx %s, using our keys %s:%s, their keys %s:%s, our nonce %s, their nonce %s", type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct bitcoin_tx, *settle_tx), type_to_string(tmpctx, struct pubkey, - &state->our_funding_pubkey), + &state->channel->eltoo_keyset.self_funding_key), type_to_string(tmpctx, struct pubkey, - &state->their_funding_pubkey), - type_to_string(tmpctx, struct nonce, - &state->channel->eltoo_keyset.self_next_nonce), - type_to_string(tmpctx, struct nonce, - &state->channel->eltoo_keyset.other_next_nonce)); + &state->channel->eltoo_keyset.self_settle_key), + type_to_string(tmpctx, struct pubkey, + &state->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &state->channel->eltoo_keyset.other_settle_key), + type_to_string(tmpctx, struct nonce, + &state->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &state->channel->eltoo_keyset.other_next_nonce)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_psign_update_tx_reply(msg, &state->channel->eltoo_keyset.self_psig, @@ -586,7 +590,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /* You can tell this has been a problem before, since there's a debug * message here: */ - status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", + status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, OLD their nonce %s", type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.self_psig), type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct pubkey, @@ -631,6 +635,13 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!fromwire_funding_signed_eltoo(msg, &id_in, &state->channel->eltoo_keyset.other_psig, &state->channel->eltoo_keyset.other_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); + + status_debug("NEW nonce from self: %s NEW nonce from peer: %s", + type_to_string(tmpctx, struct nonce, + &state->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &state->channel->eltoo_keyset.other_next_nonce)); + /* BOLT #2: * * This message introduces the `channel_id` to identify the channel. @@ -1086,12 +1097,16 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->channel->eltoo_keyset.other_next_nonce); wire_sync_write(HSM_FD, take(msg)); - status_debug("partial signature req on tx %s, using our key %s, their key %s, our nonce %s, their nonce %s", + status_debug("partial signature req on tx %s, using our keys %s:%s, their keys %s:%s, our nonce %s, their nonce %s", type_to_string(tmpctx, struct bitcoin_tx, update_tx), type_to_string(tmpctx, struct pubkey, - &state->our_funding_pubkey), + &state->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &state->channel->eltoo_keyset.self_settle_key), + type_to_string(tmpctx, struct pubkey, + &state->channel->eltoo_keyset.other_funding_key), type_to_string(tmpctx, struct pubkey, - &state->their_funding_pubkey), + &state->channel->eltoo_keyset.other_settle_key), type_to_string(tmpctx, struct nonce, &state->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, @@ -1105,13 +1120,21 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); - status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", + /* We have our second nonce thanks to above, now copy their second nonce into place + so it makes it to the actual channel */ + state->channel->eltoo_keyset.other_next_nonce = their_second_nonce; + + status_debug("partial signature %s on tx %s using our keys %s:%s, their keys %s:%s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.self_psig), type_to_string(tmpctx, struct bitcoin_tx, update_tx), - type_to_string(tmpctx, struct pubkey, - &state->our_funding_pubkey), type_to_string(tmpctx, struct pubkey, - &state->their_funding_pubkey), + &state->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &state->channel->eltoo_keyset.self_settle_key), + type_to_string(tmpctx, struct pubkey, + &state->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &state->channel->eltoo_keyset.other_settle_key), type_to_string(tmpctx, struct pubkey, &state->channel->eltoo_keyset.inner_pubkey), type_to_string(tmpctx, struct nonce, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 725038ced805..e5729037e8fd 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -148,6 +148,9 @@ bool fromwire_channeld_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p /* Generated stub for fromwire_channeld_sending_commitsig */ bool fromwire_channeld_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct penalty_base **pbase UNNEEDED, struct fee_states **fee_states UNNEEDED, struct height_states **blockheight_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_signature *commit_sig UNNEEDED, struct bitcoin_signature **htlc_sigs UNNEEDED) { fprintf(stderr, "fromwire_channeld_sending_commitsig called!\n"); abort(); } +/* Generated stub for fromwire_channeld_sending_updatesig */ +bool fromwire_channeld_sending_updatesig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *update_num UNNEEDED, struct changed_htlc **changed UNNEEDED, struct partial_sig *our_update_p_sig UNNEEDED, struct musig_session *session UNNEEDED) +{ fprintf(stderr, "fromwire_channeld_sending_updatesig called!\n"); abort(); } /* Generated stub for fromwire_connectd_peer_active */ bool fromwire_connectd_peer_active(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, u16 **msgtype UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_active called!\n"); abort(); } @@ -746,6 +749,9 @@ u8 *towire_channeld_offer_htlc(const tal_t *ctx UNNEEDED, struct amount_msat amo /* Generated stub for towire_channeld_sending_commitsig_reply */ u8 *towire_channeld_sending_commitsig_reply(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channeld_sending_commitsig_reply called!\n"); abort(); } +/* Generated stub for towire_channeld_sending_updatesig_reply */ +u8 *towire_channeld_sending_updatesig_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channeld_sending_updatesig_reply called!\n"); abort(); } /* Generated stub for towire_connectd_peer_final_msg */ u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "towire_connectd_peer_final_msg called!\n"); abort(); } From 410aae9e0edfb8720f02ec994f2da42d59bc5f17 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Sep 2022 12:54:46 -0400 Subject: [PATCH 176/283] Push forward on responding to updatesig --- channeld/eltoo_channeld.c | 10 +-- lightningd/channel.c | 25 ++++++- lightningd/channel.h | 12 ++- lightningd/channel_control.c | 2 + lightningd/peer_htlcs.c | 139 +++++++++++++++++++++++++++++++++-- wallet/db.c | 8 +- wallet/test/run-wallet.c | 6 ++ wallet/wallet.c | 18 ++--- 8 files changed, 194 insertions(+), 26 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index d68626b5a392..23cecd83b181 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -991,8 +991,7 @@ static void send_update_sign_ack(struct eltoo_peer *peer, const struct partial_sig *their_update_psig, const struct musig_session *session, const struct bitcoin_tx *update_tx, - const struct bitcoin_tx *settle_tx, - const struct nonce *our_next_nonce) + const struct bitcoin_tx *settle_tx) { struct changed_htlc *changed; struct fulfilled_htlc *fulfilled; @@ -1143,15 +1142,16 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); } - /* Tell master about this exchange, then the peer */ + /* Tell master about this exchange, then the peer. + Note: We do not persist nonces, as they will not outlive + a single connection to peer! */ send_update_sign_ack(peer, changed_htlcs, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.session, update_and_settle_txs[0], - update_and_settle_txs[1], - &peer->channel->eltoo_keyset.self_next_nonce); + update_and_settle_txs[1]); /* We may now be quiescent on our side. */ maybe_send_stfu(peer); diff --git a/lightningd/channel.c b/lightningd/channel.c index 123c0ba2dedd..cc32a093e955 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -455,8 +455,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, } else { /* If we're not using ecdsa, we're doing eltoo... */ assert(settle_tx); - channel->settle_tx = tal_steal(channel, settle_tx); - channel->settle_tx->chainparams = chainparams; + channel->last_settle_tx = tal_steal(channel, settle_tx); + channel->last_settle_tx->chainparams = chainparams; channel->eltoo_keyset.other_psig = *their_psig; channel->eltoo_keyset.self_psig = *our_psig; channel->eltoo_keyset.session = *session; @@ -690,6 +690,27 @@ void channel_set_last_tx(struct channel *channel, channel->last_tx_type = txtypes; } +void channel_set_last_eltoo_txs(struct channel *channel, + struct bitcoin_tx *update_tx, + struct bitcoin_tx *settle_tx, + struct partial_sig *their_psig, + struct partial_sig *our_psig, + struct musig_session *session, + enum wallet_tx_type txtypes) +{ + assert(update_tx->chainparams); + assert(settle_tx->chainparams); + tal_free(channel->last_tx); + channel->last_tx = tal_steal(channel, update_tx); + channel->last_tx_type = txtypes; + tal_free(channel->last_settle_tx); + channel->last_settle_tx = tal_steal(channel, settle_tx); + + channel->eltoo_keyset.other_psig = *their_psig; + channel->eltoo_keyset.self_psig = *their_psig; + channel->eltoo_keyset.session = *session; +} + void channel_set_state(struct channel *channel, enum channel_state old_state, enum channel_state state, diff --git a/lightningd/channel.h b/lightningd/channel.h index 35b0f12e45f6..c50249ff6977 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -151,7 +151,9 @@ struct channel { const struct bitcoin_signature *last_htlc_sigs; /* Eltoo-only fields */ - struct bitcoin_tx *settle_tx; + /* last_tx aka last_update_tx */ + struct bitcoin_tx *last_settle_tx; + /* Stores "last" psigs, session */ struct eltoo_keyset eltoo_keyset; /* Keys for channel */ @@ -420,6 +422,14 @@ struct channel *find_channel_by_id(const struct peer *peer, struct channel *find_channel_by_scid(const struct peer *peer, const struct short_channel_id *scid); +void channel_set_last_eltoo_txs(struct channel *channel, + struct bitcoin_tx *update_tx, + struct bitcoin_tx *settle_tx, + struct partial_sig *their_psig, + struct partial_sig *our_psig, + struct musig_session *session, + enum wallet_tx_type type); + void channel_set_last_tx(struct channel *channel, struct bitcoin_tx *tx, const struct bitcoin_signature *sig, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 12befba6627d..8bf1988c1a2f 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -595,12 +595,14 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) handle_local_private_channel(sd->channel, msg); break; case WIRE_CHANNELD_GOT_UPDATESIG: + /* FIXME not implemented */ peer_got_updatesig(sd->channel, msg); break; case WIRE_CHANNELD_SENDING_UPDATESIG: peer_sending_updatesig(sd->channel, msg); break; case WIRE_CHANNELD_GOT_ACK: + /* FIXME not implemented */ peer_got_ack(sd->channel, msg); break; case WIRE_CHANNELD_INIT_ELTOO: diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index f58dd54e8bcc..3567762b0245 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1826,6 +1826,31 @@ static bool valid_commitment_tx(struct channel *channel, return true; } +static bool peer_save_updatesig_received(struct channel *channel, u64 update_num, + struct bitcoin_tx *update_tx, + struct bitcoin_tx *settle_tx, + struct partial_sig *their_psig, + struct partial_sig *our_psig, + struct musig_session *session) +{ + if (update_num != channel->next_index[LOCAL]) { + channel_internal_error(channel, + "channel_got_updatesig: expected update_num %"PRIu64 + " got %"PRIu64, + channel->next_index[LOCAL], update_num); + return false; + } + + /* FIXME ? Basic sanity check */ + + channel->next_index[LOCAL]++; + + /* Update transactions before saving to db */ + channel_set_last_eltoo_txs(channel, update_tx, settle_tx, their_psig, our_psig, session, TX_CHANNEL_UNILATERAL); + + return true; +} + static bool peer_save_commitsig_received(struct channel *channel, u64 commitnum, struct bitcoin_tx *tx, const struct bitcoin_signature *commit_sig) @@ -1877,11 +1902,6 @@ static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) channel->min_possible_feerate = feerate; } -void peer_got_updatesig(struct channel *channel, const u8 *msg) -{ - abort(); -} - void peer_got_ack(struct channel *channel, const u8 *msg) { abort(); @@ -2141,6 +2161,13 @@ struct deferred_commitsig { const u8 *msg; }; +static void retry_deferred_updatesig(struct chain_topology *topo, + struct deferred_commitsig *d) +{ + peer_got_updatesig(d->channel, d->msg); + tal_free(d); +} + static void retry_deferred_commitsig(struct chain_topology *topo, struct deferred_commitsig *d) { @@ -2148,6 +2175,108 @@ static void retry_deferred_commitsig(struct chain_topology *topo, tal_free(d); } +void peer_got_updatesig(struct channel *channel, const u8 *msg) +{ + u32 update_num; + struct partial_sig our_psig, their_psig; + struct musig_session session; + struct added_htlc *added; + struct fulfilled_htlc *fulfilled; + struct failed_htlc **failed; + struct changed_htlc *changed; + struct bitcoin_tx *update_tx, *settle_tx; + size_t i; + struct lightningd *ld = channel->peer->ld; + + if (!fromwire_channeld_got_updatesig(msg, msg, + &update_num, + &our_psig, + &their_psig, + &session, + &added, + &fulfilled, + &failed, + &changed, + &update_tx, + &settle_tx)) { + channel_internal_error(channel, + "bad fromwire_channeld_got_commitsig %s", + tal_hex(channel, msg)); + return; + } + + /* If we're not synced with bitcoin network, we can't accept + * any new HTLCs. We stall at this point, in the hope that it + * won't take long! */ + if (added && !topology_synced(ld->topology)) { + struct deferred_commitsig *d; + + log_unusual(channel->log, + "Deferring incoming commit until we sync"); + + /* If subdaemon dies, we want to forget this. */ + d = tal(channel->owner, struct deferred_commitsig); + d->channel = channel; + d->msg = tal_dup_talarr(d, u8, msg); + topology_add_sync_waiter(d, ld->topology, + retry_deferred_updatesig, d); + return; + } + + update_tx->chainparams = chainparams; + settle_tx->chainparams = chainparams; + + log_debug(channel->log, + "got updatesig %"PRIu32 + ": %zu added, %zu fulfilled, %zu failed, %zu changed", + update_num, + tal_count(added), tal_count(fulfilled), + tal_count(failed), tal_count(changed)); + + /* New HTLCs */ + for (i = 0; i < tal_count(added); i++) { + if (!channel_added_their_htlc(channel, &added[i])) + return; + } + + /* Save information now for fulfilled & failed HTLCs */ + for (i = 0; i < tal_count(fulfilled); i++) { + if (!peer_fulfilled_our_htlc(channel, &fulfilled[i])) + return; + } + + for (i = 0; i < tal_count(failed); i++) { + if (!peer_failed_our_htlc(channel, failed[i])) + return; + } + + for (i = 0; i < tal_count(changed); i++) { + if (!changed_htlc(channel, &changed[i])) { + channel_internal_error(channel, + "got_commitsig: update failed"); + return; + } + } + + /* Since we're about to send revoke, bump state again. */ + /* FIXME do we need something like this? + if (!peer_sending_revocation(channel, added, fulfilled, failed, changed)) + return; + */ + + /* Stores fully signed transactions, and partial sigs for reestablishment! */ + if (!peer_save_updatesig_received(channel, update_num, update_tx, settle_tx, &their_psig, &our_psig, &session)) + return; + + /* Now save to db */ + wallet_channel_save(ld->wallet, channel); + + /* Tell it we've committed, and to go ahead with ACK. */ + msg = towire_channeld_got_updatesig_reply(msg); + subd_send_msg(channel->owner, take(msg)); +} + + /* This also implies we're sending revocation */ void peer_got_commitsig(struct channel *channel, const u8 *msg) { diff --git a/wallet/db.c b/wallet/db.c index 160b9b7b041e..4f89fa3cae33 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -142,10 +142,10 @@ static struct migration dbmigrations[] = { " closing_fee_received INTEGER," " closing_sig_received BLOB," /* START Eltoo stuff*/ - " settle_tx BLOB," - " their_psig BLOB," - " our_psig BLOB," - " musig_session BLOB," + " last_settle_tx BLOB," + " last_their_psig BLOB," + " last_our_psig BLOB," + " last_session BLOB," " their_next_nonce BLOB," " our_next_nonce BLOB," /* END Eltoo stuff */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index e5729037e8fd..62c92d032eaa 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -142,6 +142,9 @@ bool fromwire_channeld_got_commitsig(const tal_t *ctx UNNEEDED, const void *p UN /* Generated stub for fromwire_channeld_got_revoke */ bool fromwire_channeld_got_revoke(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *revokenum UNNEEDED, struct secret *per_commitment_secret UNNEEDED, struct pubkey *next_per_commit_point UNNEEDED, struct fee_states **fee_states UNNEEDED, struct height_states **blockheight_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct penalty_base **pbase UNNEEDED, struct bitcoin_tx **penalty_tx UNNEEDED) { fprintf(stderr, "fromwire_channeld_got_revoke called!\n"); abort(); } +/* Generated stub for fromwire_channeld_got_updatesig */ +bool fromwire_channeld_got_updatesig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u32 *update_num UNNEEDED, struct partial_sig *our_p_sig UNNEEDED, struct partial_sig *their_p_sig UNNEEDED, struct musig_session *session UNNEEDED, struct added_htlc **added UNNEEDED, struct fulfilled_htlc **fulfilled UNNEEDED, struct failed_htlc ***failed UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_tx **update_tx UNNEEDED, struct bitcoin_tx **settle_tx UNNEEDED) +{ fprintf(stderr, "fromwire_channeld_got_updatesig called!\n"); abort(); } /* Generated stub for fromwire_channeld_offer_htlc_reply */ bool fromwire_channeld_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *id UNNEEDED, u8 **failuremsg UNNEEDED, wirestring **failurestr UNNEEDED) { fprintf(stderr, "fromwire_channeld_offer_htlc_reply called!\n"); abort(); } @@ -743,6 +746,9 @@ u8 *towire_channeld_got_commitsig_reply(const tal_t *ctx UNNEEDED) /* Generated stub for towire_channeld_got_revoke_reply */ u8 *towire_channeld_got_revoke_reply(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channeld_got_revoke_reply called!\n"); abort(); } +/* Generated stub for towire_channeld_got_updatesig_reply */ +u8 *towire_channeld_got_updatesig_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channeld_got_updatesig_reply called!\n"); abort(); } /* Generated stub for towire_channeld_offer_htlc */ u8 *towire_channeld_offer_htlc(const tal_t *ctx UNNEEDED, struct amount_msat amount_msat UNNEEDED, u32 cltv_expiry UNNEEDED, const struct sha256 *payment_hash UNNEEDED, const u8 onion_routing_packet[1366] UNNEEDED, const struct pubkey *blinding UNNEEDED) { fprintf(stderr, "towire_channeld_offer_htlc called!\n"); abort(); } diff --git a/wallet/wallet.c b/wallet/wallet.c index 5c9f798d1cdc..d5fda360f880 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1486,10 +1486,10 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm lease_chan_max_ppt, htlc_minimum_msat, htlc_maximum_msat, - NULL /* FIXME settle_tx */, - NULL /* FIXME their_psig */, - NULL /* FIXME our_psig */, - NULL /* FIXME session */, + NULL /* FIXME last_settle_tx */, + NULL /* FIXME last_their_psig */, + NULL /* FIXME last_our_psig */, + NULL /* FIXME last_session */, NULL /* FIXME their_next_nonce */, NULL /* FIXME our_next_nonce */); @@ -1871,10 +1871,10 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " lease_chan_max_ppt=?," // 41 " htlc_minimum_msat=?," // 42 " htlc_maximum_msat=?," // 43 - " settle_tx=?," // 44 - " their_psig=?," // 45 - " our_psig=?," // 46 - " musig_session=?," // 47 + " last_settle_tx=?," // 44 + " last_their_psig=?," // 45 + " last_our_psig=?," // 46 + " last_session=?," // 47 " their_next_nonce=?," // 48 " our_next_nonce=?" // 49 " WHERE id=?")); // 50 @@ -1942,7 +1942,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) } db_bind_amount_msat(stmt, 42, &chan->htlc_minimum_msat); db_bind_amount_msat(stmt, 43, &chan->htlc_maximum_msat); - db_bind_psbt(stmt, 44, chan->settle_tx->psbt); + db_bind_psbt(stmt, 44, chan->last_settle_tx->psbt); db_bind_partial_sig(stmt, 45, &chan->eltoo_keyset.other_psig); db_bind_partial_sig(stmt, 46, &chan->eltoo_keyset.self_psig); db_bind_musig_session(stmt, 47, &chan->eltoo_keyset.session); From 3ab2be0fa6a2d518e2c3505eea6d2c9a4a6d010d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Sep 2022 14:36:01 -0400 Subject: [PATCH 177/283] ACK being received, stalling after --- bitcoin/signature.c | 11 ++++++-- bitcoin/signature.h | 1 + channeld/channeld_wire.csv | 4 ++- channeld/eltoo_channeld.c | 49 +++++++++++++++++++++++++----------- common/initial_channel.h | 4 +++ common/type_to_string.h | 1 + hsmd/libhsmd.c | 1 - lightningd/channel_control.c | 2 -- lightningd/peer_htlcs.c | 12 ++++++++- wallet/test/run-wallet.c | 3 +++ 10 files changed, 66 insertions(+), 22 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index b4d0c5e30a39..18edbf956e6d 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -723,13 +723,13 @@ REGISTER_TYPE_TO_HEXSTR(partial_sig); void towire_musig_session(u8 **pptr, const struct musig_session *session) { /* No proper serialization/parsing supplied, we're just copying bytes */ - towire_u8_array(pptr, session->session.data, 133); + towire_u8_array(pptr, session->session.data, sizeof(session->session.data)); } void fromwire_musig_session(const u8 **cursor, size_t *max, struct musig_session *session){ /* No proper serialization/parsing supplied, we're just copying bytes */ - if (!fromwire(cursor, max, session->session.data, 133)) + if (!fromwire(cursor, max, session->session.data, sizeof(session->session.data))) return; } @@ -740,6 +740,13 @@ char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig) REGISTER_TYPE_TO_HEXSTR(bip340sig); +char *fmt_musig_session(const tal_t *ctx, const struct musig_session *musig_session) +{ + return tal_hexstr(ctx, musig_session->session.data, sizeof(musig_session->session.data)); +} + +REGISTER_TYPE_TO_HEXSTR(musig_session); + /* BIP-340: * * This proposal suggests to include the tag by prefixing the hashed diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 0aaae1046642..9705c042077c 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -326,6 +326,7 @@ void fromwire_musig_session(const u8 **cursor, size_t *max, char *fmt_signature(const tal_t *ctx, const secp256k1_ecdsa_signature *sig); char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig); char *fmt_partial_sig(const tal_t *ctx, const struct partial_sig *psig); +char *fmt_musig_session(const tal_t *ctx, const struct musig_session *session); /* For caller convenience, we hand in tag in parts (any can be "") */ void bip340_sighash_init(struct sha256_ctx *sctx, diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index b836649eef67..c56021677889 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -371,7 +371,9 @@ msgdata,channeld_got_ack,updatenum,u64, # RCVD_ADD_ACK, RCVD_REMOVE_ACK msgdata,channeld_got_ack,num_changed,u16, msgdata,channeld_got_ack,changed,changed_htlc,num_changed -msgdata,channeld_got_ack,update_sig,bip340sig, +msgdata,channeld_got_ack,their_psig,partial_sig, +msgdata,channeld_got_ack,our_psig,partial_sig, +msgdata,channeld_got_ack,session,musig_session, # Wait for reply, to make sure it's on disk before we continue # (eg. if we sent another commitment_signed, that would implicitly ack). msgtype,channeld_got_ack_reply,1182 diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 23cecd83b181..69281837cf58 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -864,7 +864,7 @@ static void send_update(struct eltoo_peer *peer) tal_hex(tmpctx, msg)); /* We don't learn their new nonce until we get ACK... */ - status_debug("partial signature %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, OLD their nonce %s", + status_debug("partial signature %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, OLD their nonce %s, session %s", type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), @@ -877,7 +877,13 @@ static void send_update(struct eltoo_peer *peer) type_to_string(tmpctx, struct nonce, &peer->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, - &peer->channel->eltoo_keyset.other_next_nonce)); + &peer->channel->eltoo_keyset.other_next_nonce), + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.session)); + + /* Cache half-signed tx, for finalization when ACK comes back */ + /* FIXME delete older first */ + peer->channel->last_unsigned_update = tal_steal(peer->channel, update_and_settle_txs[0]); + peer->channel->last_unsigned_settle = tal_steal(peer->channel, update_and_settle_txs[1]); #if DEVELOPER if (peer->dev_disable_commit) { @@ -1111,8 +1117,9 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); - status_debug("partial signature %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", + status_debug("partial signature combine our_psig %s their_psig %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s, session %s", type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.other_psig), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), type_to_string(tmpctx, struct pubkey, @@ -1124,7 +1131,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) type_to_string(tmpctx, struct nonce, &peer->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, - &peer->channel->eltoo_keyset.other_next_nonce)); + &peer->channel->eltoo_keyset.other_next_nonce), + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.session)); /* Before replying, make sure signature is correct */ msg = towire_hsmd_combine_psig(NULL, @@ -1161,7 +1169,9 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) static u8 *got_signed_ack_msg(struct eltoo_peer *peer, u64 update_num, const struct htlc **changed_htlcs, - const struct bip340sig *update_sig) + const struct partial_sig *their_psig, + const struct partial_sig *our_psig, + const struct musig_session *session) { u8 *msg; struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); @@ -1180,7 +1190,7 @@ static u8 *got_signed_ack_msg(struct eltoo_peer *peer, } msg = towire_channeld_got_ack(peer, update_num, - changed, update_sig); + changed, their_psig, our_psig, session); return msg; } @@ -1191,8 +1201,6 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) const u8 *comb_msg; struct bip340sig update_sig; const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); - struct bitcoin_tx **update_and_settle_txs; - const struct htlc **htlc_map; if (!fromwire_update_signed_ack(msg, &channel_id, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) { @@ -1200,20 +1208,30 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) "Bad update_signed_ack %s", tal_hex(msg, msg)); } - /* We shouldn't allow any updates until we complete this round, so reconstruct latest tx */ - update_and_settle_txs = eltoo_channel_txs(tmpctx, &htlc_map, /* direct_outputs */ NULL, - peer->channel, - peer->next_index, REMOTE); + status_debug("partial signature combine req on update tx %s, settle tx %s, our_psig: %s," + " their_psig: %s, session %s, OLD our nonce %s, OLD their nonce %s", + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_unsigned_update), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_unsigned_settle), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.other_psig), + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.session), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce)); + /* This ACK should be for the transaction we sent them in update_signed, used cached */ comb_msg = towire_hsmd_combine_psig(tmpctx, &channel_id, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.session, - update_and_settle_txs[0], - update_and_settle_txs[1], + peer->channel->last_unsigned_update, + peer->channel->last_unsigned_settle, &peer->channel->eltoo_keyset.inner_pubkey); + wire_sync_write(HSM_FD, take(comb_msg)); + comb_msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(comb_msg, &update_sig)) status_failed(STATUS_FAIL_HSM_IO, @@ -1231,7 +1249,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) /* Tell master about things this locks in(and final signature), wait for response */ msg = got_signed_ack_msg(peer, peer->next_index++, - changed_htlcs, &update_sig); + changed_htlcs, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.self_psig, + &peer->channel->eltoo_keyset.session); master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNELD_GOT_ACK_REPLY); diff --git a/common/initial_channel.h b/common/initial_channel.h index 932cf64fa50f..7774ce8d2aeb 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -81,6 +81,10 @@ struct channel { /* Mask for obscuring the encoding of the update number. */ u64 update_number_obscurer; + /* Cached transactions waiting for counter-sign via `update_signed_ack` */ + struct bitcoin_tx *last_unsigned_update; + struct bitcoin_tx *last_unsigned_settle; + /* End Eltoo fields*/ }; diff --git a/common/type_to_string.h b/common/type_to_string.h index e1e6f686808f..c6bd1c9d5510 100644 --- a/common/type_to_string.h +++ b/common/type_to_string.h @@ -32,6 +32,7 @@ union printable_types { const struct bip340sig *bip340sig; const struct nonce *nonce; const struct partial_sig *partial_sig; + const struct musig_session *musig_session; const struct channel *channel; const struct amount_msat *amount_msat; const struct amount_sat *amount_sat; diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 580da9eee520..75831c6498c5 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1418,7 +1418,6 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) /* FIXME better complaint from hsmd */ return hsmd_status_malformed_request(c, msg_in); } - return towire_hsmd_combine_psig_reply(NULL, &sig); } diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 8bf1988c1a2f..12befba6627d 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -595,14 +595,12 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) handle_local_private_channel(sd->channel, msg); break; case WIRE_CHANNELD_GOT_UPDATESIG: - /* FIXME not implemented */ peer_got_updatesig(sd->channel, msg); break; case WIRE_CHANNELD_SENDING_UPDATESIG: peer_sending_updatesig(sd->channel, msg); break; case WIRE_CHANNELD_GOT_ACK: - /* FIXME not implemented */ peer_got_ack(sd->channel, msg); break; case WIRE_CHANNELD_INIT_ELTOO: diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 3567762b0245..db4d7f8cf01d 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1904,7 +1904,17 @@ static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) void peer_got_ack(struct channel *channel, const u8 *msg) { - abort(); + u64 update_num; + struct changed_htlc *changed_htlcs; + struct partial_sig their_psig, our_psig; + struct musig_session session; + if (!fromwire_channeld_got_ack(msg, msg, &update_num, &changed_htlcs, &their_psig, &our_psig, &session)) { + channel_internal_error(channel, "bad channel_sending_updatesig_ack %s", + tal_hex(channel, msg)); + return; + } + + /* FIXME good to go... turn taking stuff goes here...? */ } void peer_sending_updatesig(struct channel *channel, const u8 *msg) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 62c92d032eaa..a074798730fe 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -136,6 +136,9 @@ void fatal(const char *fmt UNNEEDED, ...) /* Generated stub for fromwire_channeld_dev_memleak_reply */ bool fromwire_channeld_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED) { fprintf(stderr, "fromwire_channeld_dev_memleak_reply called!\n"); abort(); } +/* Generated stub for fromwire_channeld_got_ack */ +bool fromwire_channeld_got_ack(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *updatenum UNNEEDED, struct changed_htlc **changed UNNEEDED, struct partial_sig *their_psig UNNEEDED, struct partial_sig *our_psig UNNEEDED, struct musig_session *session UNNEEDED) +{ fprintf(stderr, "fromwire_channeld_got_ack called!\n"); abort(); } /* Generated stub for fromwire_channeld_got_commitsig */ bool fromwire_channeld_got_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct fee_states **fee_states UNNEEDED, struct height_states **blockheight_states UNNEEDED, struct bitcoin_signature *signature UNNEEDED, struct bitcoin_signature **htlc_signature UNNEEDED, struct added_htlc **added UNNEEDED, struct fulfilled_htlc **fulfilled UNNEEDED, struct failed_htlc ***failed UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_tx **tx UNNEEDED) { fprintf(stderr, "fromwire_channeld_got_commitsig called!\n"); abort(); } From 9c23b7d8dfc5d1eb0293058f4c097cbfd14b0f66 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Sep 2022 17:07:04 -0400 Subject: [PATCH 178/283] Some more ACK handling --- channeld/eltoo_channeld.c | 4 ++ lightningd/peer_htlcs.c | 82 +++++++++++++++++++++++++++++++++++++-- wallet/test/run-wallet.c | 3 ++ 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 69281837cf58..8bf02b20f1ff 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1078,6 +1078,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) peer_failed_warn(peer->pps, &peer->channel_id, "Bad update_signed %s", tal_hex(msg, msg)); + peer->updates_received++; + status_debug("Received update_sig"); update_and_settle_txs = @@ -1208,6 +1210,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) "Bad update_signed_ack %s", tal_hex(msg, msg)); } + peer->updates_received++; + status_debug("partial signature combine req on update tx %s, settle tx %s, our_psig: %s," " their_psig: %s, session %s, OLD our nonce %s, OLD their nonce %s", type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_unsigned_update), diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index db4d7f8cf01d..5df56c663799 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1904,17 +1904,93 @@ static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) void peer_got_ack(struct channel *channel, const u8 *msg) { + enum onion_wire *badonions; + u8 **failmsgs; + size_t i; + struct lightningd *ld = channel->peer->ld; u64 update_num; - struct changed_htlc *changed_htlcs; + struct changed_htlc *changed; struct partial_sig their_psig, our_psig; struct musig_session session; - if (!fromwire_channeld_got_ack(msg, msg, &update_num, &changed_htlcs, &their_psig, &our_psig, &session)) { + if (!fromwire_channeld_got_ack(msg, msg, &update_num, &changed, &their_psig, &our_psig, &session)) { channel_internal_error(channel, "bad channel_sending_updatesig_ack %s", tal_hex(channel, msg)); return; } - /* FIXME good to go... turn taking stuff goes here...? */ + log_debug(channel->log, + "got ack %"PRIu64": %zu changed", + update_num, tal_count(changed)); + + + /* Save any immediate failures for after we reply. */ + badonions = tal_arrz(msg, enum onion_wire, tal_count(changed)); + failmsgs = tal_arrz(msg, u8 *, tal_count(changed)); + for (i = 0; i < tal_count(changed); i++) { + /* If we're doing final accept, we need to forward */ + if (changed[i].newstate == SENT_ADD_ACK) { + peer_accepted_htlc(failmsgs, + channel, changed[i].id, false, + &badonions[i], &failmsgs[i]); + } else { + if (!changed_htlc(channel, &changed[i])) { + channel_internal_error(channel, + "got_revoke: update failed"); + return; + } + } + } + + if (update_num >= (1ULL << 48)) { + channel_internal_error(channel, "got_ack: too many txs %"PRIu64, + update_num); + return; + } + + + /* FIXME check if update_num is right? */ + + log_debug(channel->log, "Responding with CHANNEL_GOT_ACK_REPLY"); + subd_send_msg(channel->owner, + take(towire_channeld_got_ack_reply(msg))); + + + /* Now, any HTLCs we need to immediately fail? */ + for (i = 0; i < tal_count(changed); i++) { + struct htlc_in *hin; + + if (badonions[i]) { + hin = find_htlc_in(&ld->htlcs_in, channel, + changed[i].id); + local_fail_in_htlc_badonion(hin, badonions[i]); + } else if (failmsgs[i]) { + hin = find_htlc_in(&ld->htlcs_in, channel, + changed[i].id); + local_fail_in_htlc(hin, failmsgs[i]); + } else + continue; + + // in fact, now we don't know if this htlc is a forward or localpay! + wallet_forwarded_payment_add(ld->wallet, + hin, FORWARD_STYLE_UNKNOWN, NULL, NULL, + FORWARD_LOCAL_FAILED, + badonions[i] ? badonions[i] + : fromwire_peektype(failmsgs[i])); + } + wallet_channel_save(ld->wallet, channel); + + /* FIXME ??? + if (penalty_tx == NULL) + return; + + payload = tal(tmpctx, struct commitment_revocation_payload); + payload->commitment_txid = pbase->txid; + payload->penalty_tx = tal_steal(payload, penalty_tx); + payload->wallet = ld->wallet; + payload->channel_dbid = channel->dbid; + payload->commitnum = pbase->commitment_num; + payload->channel_id = channel->cid; + plugin_hook_call_commitment_revocation(ld, payload); */ } void peer_sending_updatesig(struct channel *channel, const u8 *msg) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index a074798730fe..a7efcfd075bc 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -743,6 +743,9 @@ u8 *towire_channeld_fail_htlc(const tal_t *ctx UNNEEDED, const struct failed_htl /* Generated stub for towire_channeld_fulfill_htlc */ u8 *towire_channeld_fulfill_htlc(const tal_t *ctx UNNEEDED, const struct fulfilled_htlc *fulfilled_htlc UNNEEDED) { fprintf(stderr, "towire_channeld_fulfill_htlc called!\n"); abort(); } +/* Generated stub for towire_channeld_got_ack_reply */ +u8 *towire_channeld_got_ack_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channeld_got_ack_reply called!\n"); abort(); } /* Generated stub for towire_channeld_got_commitsig_reply */ u8 *towire_channeld_got_commitsig_reply(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channeld_got_commitsig_reply called!\n"); abort(); } From b82df528f6d89ee24f8dccdd6b5dc08f40a611c8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 16 Sep 2022 21:11:45 -0400 Subject: [PATCH 179/283] Checkin HTLC work, MuSig for htlc removal failing --- channeld/channeld_wire.csv | 3 +- channeld/eltoo_channeld.c | 3 +- channeld/eltoo_full_channel.c | 21 +++-- lightningd/htlc_end.c | 5 +- lightningd/peer_htlcs.c | 168 ++++++++++++++++++---------------- 5 files changed, 111 insertions(+), 89 deletions(-) diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index c56021677889..985e7ef6d9e9 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -343,7 +343,7 @@ msgdata,channeld_init_eltoo,channel_update,u8,channel_update_len # When we receive funding_locked. msgtype,channeld_got_funding_locked_eltoo,1079 -# When we have a update_signed message, tell master to remember. +# When we have a update_signed message and are going to ACK, tell master to remember. msgtype,channeld_got_updatesig,1081 msgdata,channeld_got_updatesig,update_num,u32, msgdata,channeld_got_updatesig,our_p_sig,partial_sig, @@ -395,4 +395,3 @@ msgdata,channeld_sending_updatesig,session,musig_session, # Wait for reply, to make sure it's on disk before we send commit. msgtype,channeld_sending_updatesig_reply,1180 - diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 8bf02b20f1ff..6c9414429302 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1046,6 +1046,7 @@ static void send_update_sign_ack(struct eltoo_peer *peer, /* Now we can finally send update_signed_ack to peer */ peer_write(peer->pps, take(msg)); + } static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) @@ -1252,7 +1253,7 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) } /* Tell master about things this locks in(and final signature), wait for response */ - msg = got_signed_ack_msg(peer, peer->next_index++, + msg = got_signed_ack_msg(peer, peer->next_index, changed_htlcs, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session); master_wait_sync_reply(tmpctx, peer, take(msg), diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 6692e0583937..3c86b7cca203 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -535,7 +535,7 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, * `error` and fail the channel. */ if (!eltoo_htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { - status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", + status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s, uncommitted", htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_UNCOMMITTED; } @@ -551,12 +551,18 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, * - MUST NOT send an `update_fulfill_htlc`, `update_fail_htlc`, or * `update_fail_malformed_htlc`. */ - if (htlc->state == RCVD_ADD_ACK) + /* RCVD_ADD_COMMIT == RCVD_ADD_UPDATE is irrevocable */ + /* FIXME really gotta think about these transitions.... */ + if (htlc->state == RCVD_ADD_ACK /* RCVD_ADD_REVOCATION */) htlc->state = RCVD_REMOVE_HTLC; - else if (htlc->state == SENT_ADD_ACK) - htlc->state = SENT_REMOVE_HTLC; +// else if (htlc->state == SENT_ADD_ACK) +// htlc->state = SENT_REMOVE_HTLC; + else if (htlc->state == RCVD_ADD_UPDATE) + htlc->state = SENT_REMOVE_HTLC; + else if (htlc->state == SENT_ADD_UPDATE) + htlc->state = RCVD_REMOVE_HTLC; else { - status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s", + status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s, not irrevocable", htlc->id, htlc_state_name(htlc->state)); return CHANNEL_ERR_HTLC_NOT_IRREVOCABLE; } @@ -675,6 +681,7 @@ static int change_htlcs(struct channel *channel, if (h->state == htlc_states[i]) { htlc_incstate(channel, h, owed); dump_htlc(h, prefix); + /* Adds to changed htlcs */ htlc_arr_append(htlcs, h); cflags |= (eltoo_htlc_state_flags(htlc_states[i]) ^ eltoo_htlc_state_flags(h->state)); @@ -701,11 +708,11 @@ bool channel_sending_update(struct channel *channel, const struct htlc ***htlcs) { int change; - const enum htlc_state states[] = { SENT_ADD_HTLC, + const enum htlc_state states_to_inc[] = { SENT_ADD_HTLC, SENT_REMOVE_HTLC }; status_debug("Trying update"); - change = change_htlcs(channel, states, ARRAY_SIZE(states), + change = change_htlcs(channel, states_to_inc, ARRAY_SIZE(states_to_inc), htlcs, "sending_commit"); if (!change) return false; diff --git a/lightningd/htlc_end.c b/lightningd/htlc_end.c index d9a80ac1b50b..8445f0ae7fb7 100644 --- a/lightningd/htlc_end.c +++ b/lightningd/htlc_end.c @@ -107,8 +107,9 @@ struct htlc_in *htlc_in_check(const struct htlc_in *hin, const char *abortstr) /* Can't have a resolution while still being added. */ if (hin->hstate >= RCVD_ADD_HTLC && hin->hstate <= RCVD_ADD_ACK_REVOCATION) { - if (hin->preimage) - return corrupt(abortstr, "Still adding, has preimage"); + /* FIXME This is fine for eltoo. Figure out proper switching for it */ + //if (hin->preimage) + // return corrupt(abortstr, "Still adding, has preimage"); if (hin->failonion) return corrupt(abortstr, "Still adding, has failmsg"); if (hin->badonion) diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 5df56c663799..9c8eb01b41b6 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -34,13 +34,23 @@ static bool state_update_ok(struct channel *channel, u64 htlc_id, const char *dir) { enum htlc_state expected = oldstate + 1; + /* FIXME better switch */ + bool is_eltoo = channel->last_settle_tx; /* We never get told about RCVD_REMOVE_HTLC, so skip over that * (we initialize in SENT_ADD_HTLC / RCVD_ADD_COMMIT, so those * work). */ - if (expected == RCVD_REMOVE_HTLC) + if ((!is_eltoo && expected == RCVD_REMOVE_HTLC) + || (is_eltoo && expected == RCVD_ADD_ACK_COMMIT)) expected = RCVD_REMOVE_COMMIT; + /* Jump over two unused states */ + if (is_eltoo && expected == SENT_ADD_ACK_COMMIT) + expected = SENT_REMOVE_HTLC; + +/* +HTLC in 0 invalid update SENT_ADD_REVOCATION->SEN +T_REMOVE_HTLC*/ if (newstate != expected) { channel_internal_error(channel, "HTLC %s %"PRIu64" invalid update %s->%s", @@ -321,8 +331,10 @@ void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage) u8 *msg; struct channel *channel = hin->key.channel; struct wallet *wallet = channel->peer->ld->wallet; + /* FIXME: Better switch on eltoo behavior... or just move SENT_ADD_ACK to RCVD_ADD_ACK_REVOCATION and jump? */ + enum htlc_state final_state = channel->last_settle_tx ? SENT_ADD_ACK : RCVD_ADD_ACK_REVOCATION; - if (hin->hstate != RCVD_ADD_ACK_REVOCATION) { + if (hin->hstate != final_state) { log_debug(channel->log, "HTLC fulfilled, but not ready any more (%s).", htlc_state_name(hin->hstate)); @@ -1174,6 +1186,8 @@ static bool peer_accepted_htlc(const tal_t *ctx, struct onionpacket *op; struct lightningd *ld = channel->peer->ld; struct htlc_accepted_hook_payload *hook_payload; + /* FIXME Need better switch/field to check if eltoo... */ + enum htlc_state new_state = channel->last_settle_tx ? SENT_ADD_ACK : RCVD_ADD_ACK_REVOCATION; *failmsg = NULL; *badonion = 0; @@ -1186,14 +1200,14 @@ static bool peer_accepted_htlc(const tal_t *ctx, goto fail; } - if (hin->fail_immediate && htlc_in_update_state(channel, hin, RCVD_ADD_ACK_REVOCATION)) { + if (hin->fail_immediate && htlc_in_update_state(channel, hin, new_state)) { log_debug(channel->log, "failing immediately, as requested"); /* Failing the htlc, typically done because of htlc dust */ *failmsg = towire_temporary_node_failure(ctx); goto fail; } - if (!replay && !htlc_in_update_state(channel, hin, RCVD_ADD_ACK_REVOCATION)) { + if (!replay && !htlc_in_update_state(channel, hin, new_state)) { *failmsg = towire_temporary_node_failure(ctx); goto fail; } @@ -1894,6 +1908,26 @@ static bool peer_save_commitsig_sent(struct channel *channel, u64 commitnum) return true; } +/* Only difference is incrementing local next_index, since there's only 1 */ +static bool peer_save_updatesig_sent(struct channel *channel, u64 update_num) +{ + struct lightningd *ld = channel->peer->ld; + + if (update_num != channel->next_index[LOCAL]) { + channel_internal_error(channel, + "channel_sent_updatesig: expected update_num %"PRIu64 + " got %"PRIu64, + channel->next_index[REMOTE], update_num); + return false; + } + + channel->next_index[LOCAL]++; + + /* FIXME: Save to database, with sig and HTLCs. */ + wallet_channel_save(ld->wallet, channel); + return true; +} + static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) { if (feerate > channel->max_possible_feerate) @@ -1904,10 +1938,6 @@ static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) void peer_got_ack(struct channel *channel, const u8 *msg) { - enum onion_wire *badonions; - u8 **failmsgs; - size_t i; - struct lightningd *ld = channel->peer->ld; u64 update_num; struct changed_htlc *changed; struct partial_sig their_psig, our_psig; @@ -1922,75 +1952,12 @@ void peer_got_ack(struct channel *channel, const u8 *msg) "got ack %"PRIu64": %zu changed", update_num, tal_count(changed)); + /* FIXME stash signing information, update state? */ - /* Save any immediate failures for after we reply. */ - badonions = tal_arrz(msg, enum onion_wire, tal_count(changed)); - failmsgs = tal_arrz(msg, u8 *, tal_count(changed)); - for (i = 0; i < tal_count(changed); i++) { - /* If we're doing final accept, we need to forward */ - if (changed[i].newstate == SENT_ADD_ACK) { - peer_accepted_htlc(failmsgs, - channel, changed[i].id, false, - &badonions[i], &failmsgs[i]); - } else { - if (!changed_htlc(channel, &changed[i])) { - channel_internal_error(channel, - "got_revoke: update failed"); - return; - } - } - } - - if (update_num >= (1ULL << 48)) { - channel_internal_error(channel, "got_ack: too many txs %"PRIu64, - update_num); - return; - } - - - /* FIXME check if update_num is right? */ - - log_debug(channel->log, "Responding with CHANNEL_GOT_ACK_REPLY"); + /* Tell it we've got it, and to go ahead. */ subd_send_msg(channel->owner, take(towire_channeld_got_ack_reply(msg))); - - /* Now, any HTLCs we need to immediately fail? */ - for (i = 0; i < tal_count(changed); i++) { - struct htlc_in *hin; - - if (badonions[i]) { - hin = find_htlc_in(&ld->htlcs_in, channel, - changed[i].id); - local_fail_in_htlc_badonion(hin, badonions[i]); - } else if (failmsgs[i]) { - hin = find_htlc_in(&ld->htlcs_in, channel, - changed[i].id); - local_fail_in_htlc(hin, failmsgs[i]); - } else - continue; - - // in fact, now we don't know if this htlc is a forward or localpay! - wallet_forwarded_payment_add(ld->wallet, - hin, FORWARD_STYLE_UNKNOWN, NULL, NULL, - FORWARD_LOCAL_FAILED, - badonions[i] ? badonions[i] - : fromwire_peektype(failmsgs[i])); - } - wallet_channel_save(ld->wallet, channel); - - /* FIXME ??? - if (penalty_tx == NULL) - return; - - payload = tal(tmpctx, struct commitment_revocation_payload); - payload->commitment_txid = pbase->txid; - payload->penalty_tx = tal_steal(payload, penalty_tx); - payload->wallet = ld->wallet; - payload->channel_dbid = channel->dbid; - payload->commitnum = pbase->commitment_num; - payload->channel_id = channel->cid; - plugin_hook_call_commitment_revocation(ld, payload); */ } void peer_sending_updatesig(struct channel *channel, const u8 *msg) @@ -2041,7 +2008,7 @@ void peer_sending_updatesig(struct channel *channel, const u8 *msg) channel->next_htlc_id += num_local_added; } - if (!peer_save_commitsig_sent(channel, update_num)) + if (!peer_save_updatesig_sent(channel, update_num)) return; /* Last was commit. FIXME do we want to reuse these fields? maybe? */ @@ -2269,10 +2236,13 @@ void peer_got_updatesig(struct channel *channel, const u8 *msg) struct added_htlc *added; struct fulfilled_htlc *fulfilled; struct failed_htlc **failed; - struct changed_htlc *changed; + struct changed_htlc *changed; /* Always empty? */ struct bitcoin_tx *update_tx, *settle_tx; size_t i; struct lightningd *ld = channel->peer->ld; + /* For forwarding/fulfillment */ + enum onion_wire *badonions; + u8 **failmsgs; if (!fromwire_channeld_got_updatesig(msg, msg, &update_num, @@ -2357,9 +2327,53 @@ void peer_got_updatesig(struct channel *channel, const u8 *msg) /* Now save to db */ wallet_channel_save(ld->wallet, channel); + /* FIXME We can now forward/fulfill! */ + + /* Save any immediate failures for after we reply. */ + badonions = tal_arrz(msg, enum onion_wire, tal_count(added)); + failmsgs = tal_arrz(msg, u8 *, tal_count(added)); + for (i = 0; i < tal_count(added); i++) { + /* If we're adding, we're accepting, we need to forward */ + peer_accepted_htlc(failmsgs, + channel, added[i].id, false, + &badonions[i], &failmsgs[i]); + } + + if (update_num >= (1ULL << 48)) { + channel_internal_error(channel, "got_ack: too many txs %"PRIu64, + update_num); + return; + } + + + /* FIXME check if update_num is right? */ + + /* Now, any HTLCs we need to immediately fail? */ + for (i = 0; i < tal_count(changed); i++) { + struct htlc_in *hin; + + if (badonions[i]) { + hin = find_htlc_in(&ld->htlcs_in, channel, + changed[i].id); + local_fail_in_htlc_badonion(hin, badonions[i]); + } else if (failmsgs[i]) { + hin = find_htlc_in(&ld->htlcs_in, channel, + changed[i].id); + local_fail_in_htlc(hin, failmsgs[i]); + } else + continue; + + // in fact, now we don't know if this htlc is a forward or localpay! + wallet_forwarded_payment_add(ld->wallet, + hin, FORWARD_STYLE_UNKNOWN, NULL, NULL, + FORWARD_LOCAL_FAILED, + badonions[i] ? badonions[i] + : fromwire_peektype(failmsgs[i])); + } + wallet_channel_save(ld->wallet, channel); + /* Tell it we've committed, and to go ahead with ACK. */ - msg = towire_channeld_got_updatesig_reply(msg); - subd_send_msg(channel->owner, take(msg)); + subd_send_msg(channel->owner, take(towire_channeld_got_updatesig_reply(msg))); } From 63a3671a3127c222dde8132e797986ba7bb7a3fd Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 19 Sep 2022 10:31:27 -0400 Subject: [PATCH 180/283] Trivial single payment is clearing --- channeld/eltoo_channeld.c | 5 +++-- channeld/eltoo_full_channel.c | 30 ++++++++++++++---------------- lightningd/peer_htlcs.c | 28 +++++++++++++++++++++------- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 6c9414429302..fca37c8b6324 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -982,7 +982,8 @@ static void marshall_htlc_info(const tal_t *ctx, } else { struct changed_htlc c; assert(htlc->state == RCVD_REMOVE_ACK - || htlc->state == RCVD_ADD_ACK); + || htlc->state == RCVD_ADD_ACK + || htlc->state == SENT_REMOVE_REVOCATION /* SENT_REMOVE_ACK */); c.id = htlc->id; c.newstate = htlc->state; @@ -1183,7 +1184,7 @@ static u8 *got_signed_ack_msg(struct eltoo_peer *peer, struct changed_htlc c; const struct htlc *htlc = changed_htlcs[i]; - status_debug("HTLC %"PRIu64"[%s] => %s", + status_debug("got_signed_ack HTLC %"PRIu64"[%s] => %s", htlc->id, side_to_str(htlc_owner(htlc)), htlc_state_name(htlc->state)); diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 3c86b7cca203..f9bfc1cdeb9c 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -720,6 +720,20 @@ bool channel_sending_update(struct channel *channel, return true; } +bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs) +{ + int change; + const enum htlc_state states[] = {RCVD_REMOVE_HTLC, + RCVD_ADD_HTLC}; + + status_debug("Received Update"); + change = change_htlcs(channel, states, ARRAY_SIZE(states), + htlcs, "rcvd_update"); + if (!change) + return false; + return true; +} + bool channel_rcvd_update_sign_ack(struct channel *channel, const struct htlc ***htlcs) { @@ -735,22 +749,6 @@ bool channel_rcvd_update_sign_ack(struct channel *channel, return (change & HTLC_LOCAL_F_PENDING); } -bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs) -{ - int change; - const enum htlc_state states[] = { RCVD_ADD_UPDATE, - RCVD_REMOVE_HTLC, - RCVD_ADD_HTLC, - RCVD_REMOVE_UPDATE }; - - status_debug("Received Update"); - change = change_htlcs(channel, states, ARRAY_SIZE(states), - htlcs, "rcvd_update"); - if (!change) - return false; - return true; -} - size_t num_channel_htlcs(const struct channel *channel) { struct htlc_map_iter it; diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 9c8eb01b41b6..af0c2956a29f 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -41,16 +41,15 @@ static bool state_update_ok(struct channel *channel, * (we initialize in SENT_ADD_HTLC / RCVD_ADD_COMMIT, so those * work). */ if ((!is_eltoo && expected == RCVD_REMOVE_HTLC) - || (is_eltoo && expected == RCVD_ADD_ACK_COMMIT)) + || (is_eltoo && expected == RCVD_ADD_ACK_COMMIT)) { expected = RCVD_REMOVE_COMMIT; + } /* Jump over two unused states */ - if (is_eltoo && expected == SENT_ADD_ACK_COMMIT) + if (is_eltoo && expected == SENT_ADD_ACK_COMMIT) { expected = SENT_REMOVE_HTLC; + } -/* -HTLC in 0 invalid update SENT_ADD_REVOCATION->SEN -T_REMOVE_HTLC*/ if (newstate != expected) { channel_internal_error(channel, "HTLC %s %"PRIu64" invalid update %s->%s", @@ -1942,6 +1941,9 @@ void peer_got_ack(struct channel *channel, const u8 *msg) struct changed_htlc *changed; struct partial_sig their_psig, our_psig; struct musig_session session; + int i; + struct lightningd *ld = channel->peer->ld; + if (!fromwire_channeld_got_ack(msg, msg, &update_num, &changed, &their_psig, &our_psig, &session)) { channel_internal_error(channel, "bad channel_sending_updatesig_ack %s", tal_hex(channel, msg)); @@ -1952,7 +1954,19 @@ void peer_got_ack(struct channel *channel, const u8 *msg) "got ack %"PRIu64": %zu changed", update_num, tal_count(changed)); - /* FIXME stash signing information, update state? */ + /* Update HTLC info to advance state */ + for (i = 0; i < tal_count(changed); i++) { + if (!changed_htlc(channel, changed + i)) { + channel_internal_error(channel, + "channel_got_ack: update failed"); + return; + } + } + + /* FIXME stash signing information, more state? */ + + /* write to db, then respond */ + wallet_channel_save(ld->wallet, channel); /* Tell it we've got it, and to go ahead. */ subd_send_msg(channel->owner, @@ -1983,7 +1997,7 @@ void peer_sending_updatesig(struct channel *channel, const u8 *msg) for (i = 0; i < tal_count(changed_htlcs); i++) { if (!changed_htlc(channel, changed_htlcs + i)) { channel_internal_error(channel, - "channel_sending_commitsig: update failed"); + "channel_sending_updatesig: update failed"); return; } From d8c36cedfdd8a743501f67e991a17380a33a3d46 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 20 Sep 2022 14:38:39 -0400 Subject: [PATCH 181/283] l2-cli now sees the htlc as resolving, working on l1-cli --- channeld/eltoo_channeld.c | 9 +++++++++ channeld/eltoo_full_channel.c | 25 +++++++++++++++++++++---- channeld/eltoo_full_channel.h | 9 +++++++++ common/htlc_state.h | 19 ++++++++++--------- lightningd/peer_htlcs.c | 26 +++++++++++++++----------- 5 files changed, 64 insertions(+), 24 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index fca37c8b6324..5fe52c15f8d7 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1048,6 +1048,8 @@ static void send_update_sign_ack(struct eltoo_peer *peer, /* Now we can finally send update_signed_ack to peer */ peer_write(peer->pps, take(msg)); + /* FIXME Update HTLC states to reflect this and tell master? */ + } static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) @@ -1154,6 +1156,13 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); } + + /* FIXME do we just bump on lightningd side? We are about to send an update, increment HTLCs to sent state + this was aping peer_sending_revocation + if (!channel_sending_sign_ack(peer->channel, &changed_htlcs)) { + status_debug("Failed to increment HTLC state after sending ACK..."); + }*/ + /* Tell master about this exchange, then the peer. Note: We do not persist nonces, as they will not outlive a single connection to peer! */ diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index f9bfc1cdeb9c..292adf2deead 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -624,18 +624,20 @@ static void htlc_incstate(struct channel *channel, int preflags, postflags; enum side sidechanged = LOCAL; const int committed_f = HTLC_FLAG(sidechanged, HTLC_F_COMMITTED); + /* We need to jump to real terminal state for eltoo, step 1(index 0) goes to 4 */ + int state_gap = (channel->config[LOCAL].is_eltoo && (htlc->state % 5 == 1)) ? 3 : 1; status_debug("htlc %"PRIu64": %s->%s", htlc->id, htlc_state_name(htlc->state), - htlc_state_name(htlc->state+1)); + htlc_state_name(htlc->state+state_gap)); preflags = eltoo_htlc_state_flags(htlc->state); - postflags = eltoo_htlc_state_flags(htlc->state + 1); + postflags = eltoo_htlc_state_flags(htlc->state + state_gap); /* You can't change sides. */ assert((preflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) == (postflags & (HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); - htlc->state++; + htlc->state += state_gap; /* If we've added or removed, adjust balances. */ if (!(preflags & committed_f) && (postflags & committed_f)) { @@ -713,7 +715,7 @@ bool channel_sending_update(struct channel *channel, status_debug("Trying update"); change = change_htlcs(channel, states_to_inc, ARRAY_SIZE(states_to_inc), - htlcs, "sending_commit"); + htlcs, "sending_update"); if (!change) return false; @@ -734,6 +736,21 @@ bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs) return true; } +/* +bool channel_sending_sign_ack(struct channel *channel, const struct htlc ***htlcs) +{ + int change; + const enum htlc_state states[] = {RCVD_REMOVE_UPDATE, + RCVD_ADD_UPDATE}; + + status_debug("Sending Signed ACK"); + change = change_htlcs(channel, states, ARRAY_SIZE(states), + htlcs, "sending_sign_ack"); + if (!change) + return false; +} +*/ + bool channel_rcvd_update_sign_ack(struct channel *channel, const struct htlc ***htlcs) { diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h index b666dbc145fd..47c946d230af 100644 --- a/channeld/eltoo_full_channel.h +++ b/channeld/eltoo_full_channel.h @@ -173,6 +173,15 @@ bool channel_rcvd_update_sign_ack(struct channel *channel, bool channel_rcvd_update(struct channel *channel, const struct htlc ***htlcs); +/** + * channel_sending_sign_ack: commit changed when sending ACK + * @channel: the channel + * @htlcs: initially-empty tal_arr() for htlcs which changed state. + * + */ +//bool channel_sending_sign_ack(struct channel *channel, +// const struct htlc ***htlcs): + /** * num_channel_htlcs: how many (live) HTLCs at all in channel? * @channel: the channel diff --git a/common/htlc_state.h b/common/htlc_state.h index 3a8dcaacf77f..5f08228093c3 100644 --- a/common/htlc_state.h +++ b/common/htlc_state.h @@ -38,23 +38,24 @@ enum htlc_state { HTLC_STATE_INVALID }; -/* Eltoo: Only first three states in htlc_state are used */ +/* Eltoo: Only first two amd last states in htlc_state are used */ /* SENT_ADD_HTLC is same*/ #define SENT_ADD_UPDATE (SENT_ADD_COMMIT) -#define RCVD_ADD_ACK (RCVD_ADD_REVOCATION) +#define RCVD_ADD_ACK (SENT_ADD_ACK_REVOCATION) -/* SENT_REMOVE_HTLC is same */ -#define SENT_REMOVE_UPDATE (SENT_REMOVE_COMMIT) -#define RCVD_REMOVE_ACK (RCVD_REMOVE_REVOCATION) +/* RCVD_REMOVE_HTLC is same */ +#define RCVD_REMOVE_UPDATE (RCVD_REMOVE_COMMIT) +#define SENT_REMOVE_ACK (RCVD_REMOVE_ACK_REVOCATION) /* RCVD_ADD_HTLC is same*/ #define RCVD_ADD_UPDATE (RCVD_ADD_COMMIT) -#define SENT_ADD_ACK (SENT_ADD_REVOCATION) +#define SENT_ADD_ACK (RCVD_ADD_ACK_REVOCATION) + +/* SENT_REMOVE_HTLC is same */ +#define SENT_REMOVE_UPDATE (SENT_REMOVE_COMMIT) +#define RCVD_REMOVE_ACK (SENT_REMOVE_ACK_REVOCATION) -/* RCVD_REMOVE_HTLC is same */ -#define RCVD_REMOVE_UPDATE (RCVD_REMOVE_COMMIT) -#define SENT_REMOVE_ACK (SENT_REMOVE_REVOCATION) /* HTLC_STATE_INVALID is same */ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index af0c2956a29f..f5169e2a8294 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -40,14 +40,13 @@ static bool state_update_ok(struct channel *channel, /* We never get told about RCVD_REMOVE_HTLC, so skip over that * (we initialize in SENT_ADD_HTLC / RCVD_ADD_COMMIT, so those * work). */ - if ((!is_eltoo && expected == RCVD_REMOVE_HTLC) - || (is_eltoo && expected == RCVD_ADD_ACK_COMMIT)) { - expected = RCVD_REMOVE_COMMIT; + if (expected == RCVD_REMOVE_HTLC) { + expected = RCVD_REMOVE_COMMIT; } - /* Jump over two unused states */ - if (is_eltoo && expected == SENT_ADD_ACK_COMMIT) { - expected = SENT_REMOVE_HTLC; + /* Jump over two eltoo-unused states to expect "terminal" state */ + if (is_eltoo && (expected % 5 == 2)) { + expected += 2; } if (newstate != expected) { @@ -1186,7 +1185,8 @@ static bool peer_accepted_htlc(const tal_t *ctx, struct lightningd *ld = channel->peer->ld; struct htlc_accepted_hook_payload *hook_payload; /* FIXME Need better switch/field to check if eltoo... */ - enum htlc_state new_state = channel->last_settle_tx ? SENT_ADD_ACK : RCVD_ADD_ACK_REVOCATION; + /* FIXME 2: Maybe we *do* want to jump to same state, then adjust "expected" as required */ + enum htlc_state new_state = RCVD_ADD_ACK_REVOCATION; *failmsg = NULL; *badonion = 0; @@ -1769,6 +1769,8 @@ static bool update_out_htlc(struct channel *channel, struct lightningd *ld = channel->peer->ld; struct htlc_out *hout; struct wallet_payment *payment; + /* FIXME better switch for eltoo behavior... */ + bool is_eltoo = channel->last_settle_tx; hout = find_htlc_out(&ld->htlcs_out, channel, id); if (!hout) { @@ -1809,7 +1811,9 @@ static bool update_out_htlc(struct channel *channel, tal_del_destructor(hout, destroy_hout_subd_died); hout->timeout = tal_free(hout->timeout); tal_steal(ld, hout); - } else if (newstate == RCVD_REMOVE_ACK_REVOCATION) { + } else if ((newstate == RCVD_REMOVE_ACK_REVOCATION) || + (is_eltoo && newstate == RCVD_REMOVE_UPDATE)) { + /* FIXME Need this code path to actually be hit */ remove_htlc_out(channel, hout); } return true; @@ -2328,9 +2332,9 @@ void peer_got_updatesig(struct channel *channel, const u8 *msg) } } - /* Since we're about to send revoke, bump state again. */ - /* FIXME do we need something like this? - if (!peer_sending_revocation(channel, added, fulfilled, failed, changed)) + /* Since we're about to send ACK, bump state again. */ + /* FIXME not sure we need this duplicated code, we're accepting below + if (!peer_sending_ack(channel, added, fulfilled, failed, changed)) return; */ From ff1e92c04e4a1e58ed7351d024c8318ea78be727 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 20 Sep 2022 15:24:59 -0400 Subject: [PATCH 182/283] HTLCs resolving in *both directions* --- lightningd/peer_htlcs.c | 74 +++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index f5169e2a8294..9041901cc0d1 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -43,9 +43,13 @@ static bool state_update_ok(struct channel *channel, if (expected == RCVD_REMOVE_HTLC) { expected = RCVD_REMOVE_COMMIT; } + // else if (is_eltoo && expected == RCVD_REMOVE_HTLC) { + // /* Jump one further for eltoo */ + // expected = SENT_REMOVE_ACK; + //} /* Jump over two eltoo-unused states to expect "terminal" state */ - if (is_eltoo && (expected % 5 == 2)) { + else if (is_eltoo && (expected % 5 == 2)) { expected += 2; } @@ -1345,6 +1349,28 @@ static void fulfill_our_htlc_out(struct channel *channel, struct htlc_out *hout, } } +/* FIXME only diff isi final state... +static bool peer_fulfilled_our_eltoo_htlc(struct channel *channel, + const struct fulfilled_htlc *fulfilled) +{ + struct lightningd *ld = channel->peer->ld; + struct htlc_out *hout; + + hout = find_htlc_out(&ld->htlcs_out, channel, fulfilled->id); + if (!hout) { + channel_internal_error(channel, + "fulfilled_our_htlc unknown htlc %"PRIu64, + fulfilled->id); + return false; + } + + if (!htlc_out_update_state(channel, hout, SENT_REMOVE_ACK)) + return false; + + fulfill_our_htlc_out(channel, hout, &fulfilled->payment_preimage); + return true; +}*/ + static bool peer_fulfilled_our_htlc(struct channel *channel, const struct fulfilled_htlc *fulfilled) { @@ -1769,8 +1795,6 @@ static bool update_out_htlc(struct channel *channel, struct lightningd *ld = channel->peer->ld; struct htlc_out *hout; struct wallet_payment *payment; - /* FIXME better switch for eltoo behavior... */ - bool is_eltoo = channel->last_settle_tx; hout = find_htlc_out(&ld->htlcs_out, channel, id); if (!hout) { @@ -1811,9 +1835,7 @@ static bool update_out_htlc(struct channel *channel, tal_del_destructor(hout, destroy_hout_subd_died); hout->timeout = tal_free(hout->timeout); tal_steal(ld, hout); - } else if ((newstate == RCVD_REMOVE_ACK_REVOCATION) || - (is_eltoo && newstate == RCVD_REMOVE_UPDATE)) { - /* FIXME Need this code path to actually be hit */ + } else if (newstate == RCVD_REMOVE_ACK_REVOCATION) { remove_htlc_out(channel, hout); } return true; @@ -2188,6 +2210,40 @@ static bool channel_added_their_htlc(struct channel *channel, return true; } +/* The peer doesn't tell us this separately, but logically it's a separate + * step to receiving updatesig */ +static bool peer_sending_ack(struct channel *channel, + struct fulfilled_htlc *fulfilled, + struct failed_htlc **failed, + struct changed_htlc *changed) +{ + size_t i; + + for (i = 0; i < tal_count(fulfilled); i++) { + if (!update_out_htlc(channel, fulfilled[i].id, + SENT_REMOVE_ACK)) + return false; + } + for (i = 0; i < tal_count(failed); i++) { + if (!update_out_htlc(channel, failed[i]->id, SENT_REMOVE_REVOCATION)) + return false; + } + for (i = 0; i < tal_count(changed); i++) { + if (changed[i].newstate == RCVD_ADD_ACK_COMMIT) { + if (!update_out_htlc(channel, changed[i].id, + SENT_ADD_ACK_REVOCATION)) + return false; + } else { + if (!update_in_htlc(channel, changed[i].id, + SENT_REMOVE_ACK_REVOCATION)) + return false; + } + } + + channel->last_was_revoke = true; + return true; +} + /* The peer doesn't tell us this separately, but logically it's a separate * step to receiving commitsig */ static bool peer_sending_revocation(struct channel *channel, @@ -2332,11 +2388,9 @@ void peer_got_updatesig(struct channel *channel, const u8 *msg) } } - /* Since we're about to send ACK, bump state again. */ - /* FIXME not sure we need this duplicated code, we're accepting below - if (!peer_sending_ack(channel, added, fulfilled, failed, changed)) + /* Since we're about to send ACK(and fulfilled a second ago), bump state again and delete complete htlcs. */ + if (!peer_sending_ack(channel, fulfilled, failed, changed)) return; - */ /* Stores fully signed transactions, and partial sigs for reestablishment! */ if (!peer_save_updatesig_received(channel, update_num, update_tx, settle_tx, &their_psig, &our_psig, &session)) From a0ab01d9d535b08965998d45f366aad962c2a873 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 20 Sep 2022 15:29:29 -0400 Subject: [PATCH 183/283] Comment out unknown things --- contrib/startup_regtest.sh | 10 ++++++++++ lightningd/peer_htlcs.c | 2 ++ 2 files changed, 12 insertions(+) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index a88934200947..fb33324c2dbb 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -161,6 +161,16 @@ setup_ln() { bt-cli generatetoaddress 6 $btcaddr invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice + + invoice=$(l2-cli invoice 10000 hi2 "test" | jq -r .bolt11) + l1-cli pay $invoice + + invoice=$(l2-cli invoice 1000000 hi3 "test" | jq -r .bolt11) + l1-cli pay $invoice + + sleep 0.5 + invoice=$(l1-cli invoice 1000000 hi! "test" | jq -r .bolt11) + l2-cli pay $invoice } stop_nodes() { diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 9041901cc0d1..cbcbe66cb5ca 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -2224,6 +2224,7 @@ static bool peer_sending_ack(struct channel *channel, SENT_REMOVE_ACK)) return false; } + /* FIXE no idea if this stuff is required for (i = 0; i < tal_count(failed); i++) { if (!update_out_htlc(channel, failed[i]->id, SENT_REMOVE_REVOCATION)) return false; @@ -2241,6 +2242,7 @@ static bool peer_sending_ack(struct channel *channel, } channel->last_was_revoke = true; +*/ return true; } From 32fb6ae924451a10c68a39f49d5b265fbff255fb Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 21 Sep 2022 10:51:05 -0400 Subject: [PATCH 184/283] Remove pubnonce storage from hsmd --- channeld/eltoo_channeld.c | 6 ++++-- contrib/startup_regtest.sh | 15 ++++++++++++++- hsmd/hsmd_wire.csv | 1 + hsmd/libhsmd.c | 17 +++++++++-------- openingd/eltoo_openingd.c | 6 ++++-- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 5fe52c15f8d7..cbd75973fe39 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -840,7 +840,8 @@ static void send_update(struct eltoo_peer *peer) update_and_settle_txs[0], update_and_settle_txs[1], &peer->channel->eltoo_keyset.other_funding_key, - &peer->channel->eltoo_keyset.other_next_nonce); + &peer->channel->eltoo_keyset.other_next_nonce, + &peer->channel->eltoo_keyset.self_next_nonce); status_debug("partial signature req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), @@ -1097,7 +1098,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) update_and_settle_txs[0], update_and_settle_txs[1], &peer->channel->eltoo_keyset.other_funding_key, - &peer->channel->eltoo_keyset.other_next_nonce); + &peer->channel->eltoo_keyset.other_next_nonce, + &peer->channel->eltoo_keyset.self_next_nonce); status_debug("partial signature req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index fb33324c2dbb..dd521789d88f 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -150,15 +150,21 @@ start_ln() { setup_ln() { l2id=$(l2-cli getinfo | jq -r .id) + #l3id=$(l3-cli getinfo | jq -r .id) l1addr=$(l1-cli newaddr | jq -r .bech32) + l2addr=$(l2-cli newaddr | jq -r .bech32) bt-cli loadwallet "default" btcaddr=$(bt-cli getnewaddress) bt-cli sendtoaddress $l1addr 1 + bt-cli sendtoaddress $l2addr 1 l1-cli connect $l2id@localhost:7272 + #l2-cli connect $l3id@localhost:7373 bt-cli generatetoaddress 6 $btcaddr sleep 5 l1-cli fundchannel $l2id 10000 normal false + #l2-cli fundchannel $l3id 10000 normal false bt-cli generatetoaddress 6 $btcaddr + invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice @@ -169,8 +175,15 @@ setup_ln() { l1-cli pay $invoice sleep 0.5 - invoice=$(l1-cli invoice 1000000 hi! "test" | jq -r .bolt11) + invoice=$(l1-cli invoice 500000 hi "test" | jq -r .bolt11) l2-cli pay $invoice + + + #invoice=$(l3-cli invoice 100000 hi "test" | jq -r .bolt11) + #l2-cli pay $invoice + + #invoice=$(l3-cli invoice 10000 hi "test" | jq -r .bolt11) + #l1-cli pay $invoice } stop_nodes() { diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 5e54948c568e..8eecc73fabe7 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -318,6 +318,7 @@ msgdata,hsmd_psign_update_tx,update_tx,bitcoin_tx, msgdata,hsmd_psign_update_tx,settle_tx,bitcoin_tx, msgdata,hsmd_psign_update_tx,remote_funding_key,pubkey, msgdata,hsmd_psign_update_tx,remote_nonce,nonce, +msgdata,hsmd_psign_update_tx,local_nonce,nonce, msgtype,hsmd_psign_update_tx_reply,162 msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 75831c6498c5..ee75a7fd64ff 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -40,7 +40,6 @@ struct { */ struct channel_id musig_channel; secp256k1_musig_secnonce sec_nonce; - struct nonce pub_nonce; } secretstuff; /* Have we initialized the secretstuff? */ @@ -802,6 +801,7 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, struct channel_id channel_id; struct secret channel_seed; struct secrets secrets; + struct nonce local_pub_nonce; if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) return hsmd_status_malformed_request(c, msg_in); @@ -813,12 +813,12 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, /* Fill and return own next_nonce FIXME add in more entropy */ bipmusig_gen_nonce(&secretstuff.sec_nonce, - &secretstuff.pub_nonce.nonce, + &local_pub_nonce.nonce, &secrets.funding_privkey, NULL /* keyagg_cache */, NULL /* msg32 */); - return towire_hsmd_gen_nonce_reply(NULL, &secretstuff.pub_nonce); + return towire_hsmd_gen_nonce_reply(NULL, &local_pub_nonce); } /*~ The client has asked us to extract the shared secret from an EC Diffie @@ -1432,7 +1432,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) struct bitcoin_tx *update_tx, *settle_tx; struct partial_sig p_sig; struct secrets secrets; - struct nonce remote_nonce; + struct nonce remote_nonce, local_nonce; struct channel_id channel_id; struct musig_session session; @@ -1451,7 +1451,8 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) &update_tx, &settle_tx, &remote_funding_pubkey, - &remote_nonce)) + &remote_nonce, + &local_nonce)) return hsmd_status_malformed_request(c, msg_in); update_tx->chainparams = c->chainparams; @@ -1489,7 +1490,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) printf("\n"); pubnonce_ptrs[0] = &remote_nonce.nonce; - pubnonce_ptrs[1] = &secretstuff.pub_nonce.nonce; + pubnonce_ptrs[1] = &local_nonce.nonce; /* FIXME assert we have secnonce already... though if we don't this call will already crash... */ @@ -1504,12 +1505,12 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) /* Refill and return own next_nonce, using RNG+extra stuff for more security */ bipmusig_gen_nonce(&secretstuff.sec_nonce, - &secretstuff.pub_nonce.nonce, + &local_nonce.nonce, &secrets.funding_privkey, &keyagg_cache, hash_out.sha.u.u8); - return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &secretstuff.pub_nonce, &inner_pubkey); + return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &local_nonce, &inner_pubkey); } diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 8cdcba88071d..f2c8916627eb 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -563,7 +563,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, *update_tx, *settle_tx, &state->their_funding_pubkey, - &state->channel->eltoo_keyset.other_next_nonce); + &state->channel->eltoo_keyset.other_next_nonce, + &state->channel->eltoo_keyset.self_next_nonce); wire_sync_write(HSM_FD, take(msg)); status_debug("partial signature req on update tx %s, settlement tx %s, using our keys %s:%s, their keys %s:%s, our nonce %s, their nonce %s", @@ -1094,7 +1095,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) update_tx, settle_tx, &state->their_funding_pubkey, - &state->channel->eltoo_keyset.other_next_nonce); + &state->channel->eltoo_keyset.other_next_nonce, + &state->channel->eltoo_keyset.self_next_nonce); wire_sync_write(HSM_FD, take(msg)); status_debug("partial signature req on tx %s, using our keys %s:%s, their keys %s:%s, our nonce %s, their nonce %s", From e5f33771fbaa0a9e55836c8e0ec6b6515ef2cb35 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 21 Sep 2022 14:54:59 -0400 Subject: [PATCH 185/283] Multichannel musig working? --- hsmd/hsmd.c | 2 + hsmd/hsmd_wire.csv | 10 +++- hsmd/libhsmd.c | 98 +++++++++++++++++++++++++++++++++------ hsmd/libhsmd.h | 3 ++ openingd/eltoo_openingd.c | 27 ++++++++++- 5 files changed, 123 insertions(+), 17 deletions(-) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 985c53617221..4f4de6116eae 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -672,6 +672,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: case WIRE_HSMD_GEN_NONCE: + case WIRE_HSMD_MIGRATE_NONCE: /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, @@ -706,6 +707,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: + case WIRE_HSMD_MIGRATE_NONCE_REPLY: return bad_req_fmt(conn, c, c->msg_in, "Received an incoming message of type %s, " "which is not a request", diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 8eecc73fabe7..9d9d6da0ebe3 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -347,10 +347,16 @@ msgdata,hsmd_combine_psig,inner_pubkey,pubkey, msgtype,hsmd_combine_psig_reply,192 msgdata,hsmd_combine_psig_reply,sig,bip340sig, -# Get musig public nonce for channel... FIXME channel_id completely -# ignored for now until storage model is figured +# Get musig public nonce for channel this is temporary id msgtype,hsmd_gen_nonce,96 msgdata,hsmd_gen_nonce,channel_id,channel_id, msgtype,hsmd_gen_nonce_reply,196 msgdata,hsmd_gen_nonce_reply,pubnonce,nonce, + +# Migrates over secret nonce as soon as channel id becomes stable +msgtype,hsmd_migrate_nonce,97 +msgdata,hsmd_migrate_nonce,temp_id,channel_id, +msgdata,hsmd_migrate_nonce,final_id,channel_id, + +msgtype,hsmd_migrate_nonce_reply,197 diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index ee75a7fd64ff..09337130cedd 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1,11 +1,14 @@ #include "config.h" #include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -26,20 +29,41 @@ struct privkey *dev_force_privkey; struct secret *dev_force_bip32_seed; #endif +struct musig_state { + struct channel_id channel_id; + secp256k1_musig_secnonce sec_nonce; +}; + +size_t channel_id_key(const struct channel_id *id) +{ + struct siphash24_ctx ctx; + siphash24_init(&ctx, siphash_seed()); + /* channel doesn't move while in this hash, so we just hash pointer. */ + siphash24_update(&ctx, id->id, sizeof(id->id)); + + return siphash24_done(&ctx); +} + +static inline const struct channel_id *keyof_musig_state(const struct musig_state *state) +{ + return &state->channel_id; +} + +static inline bool musig_state_eq(const struct musig_state *state, const struct channel_id *id) +{ + return channel_id_eq(&state->channel_id, id); +} + +HTABLE_DEFINE_TYPE(struct musig_state, keyof_musig_state, channel_id_key, musig_state_eq, + musig_state_map); + /*~ Nobody will ever find it here! hsm_secret is our root secret, the bip32 * tree and bolt12 payer_id keys are derived from that, and cached here. */ struct { struct secret hsm_secret; struct ext_key bip32; secp256k1_keypair bolt12; - /* - * FIXME HACK: We only support on eltoo channel, to avoid unbounded state. - * What's the best architecture to support unbounded numbers of channels? - * We're just going to blindly assume this is the nonce for the eltoo channel - * signature operation.... - */ - struct channel_id musig_channel; - secp256k1_musig_secnonce sec_nonce; + struct musig_state_map musig_map; } secretstuff; /* Have we initialized the secretstuff? */ @@ -111,6 +135,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_VALIDATE_COMMITMENT_TX: case WIRE_HSMD_VALIDATE_REVOCATION: case WIRE_HSMD_GEN_NONCE: + case WIRE_HSMD_MIGRATE_NONCE: case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_READY_ELTOO_CHANNEL: @@ -167,6 +192,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: + case WIRE_HSMD_MIGRATE_NONCE_REPLY: break; } return false; @@ -798,29 +824,61 @@ static u8 *handle_get_channel_basepoints(struct hsmd_client *c, static u8 *handle_gen_nonce(struct hsmd_client *c, const u8 *msg_in) { - struct channel_id channel_id; struct secret channel_seed; struct secrets secrets; struct nonce local_pub_nonce; + struct channel_id channel_id; + struct musig_state *new_musig_state; if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) return hsmd_status_malformed_request(c, msg_in); + /* Shouldn't need to be freed, aside from channel teardown */ + new_musig_state = tal(NULL, struct musig_state); + new_musig_state->channel_id = channel_id; + /* Generate privkey for additional nonce entropy */ get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, NULL, NULL, &secrets, NULL); - /* Fill and return own next_nonce FIXME add in more entropy */ - bipmusig_gen_nonce(&secretstuff.sec_nonce, + /* Fill and return own next_nonce */ + bipmusig_gen_nonce(&new_musig_state->sec_nonce, &local_pub_nonce.nonce, &secrets.funding_privkey, NULL /* keyagg_cache */, NULL /* msg32 */); + /* Store secret nonce in hash table */ + musig_state_map_add(&secretstuff.musig_map, new_musig_state); + return towire_hsmd_gen_nonce_reply(NULL, &local_pub_nonce); } +/* This is called after handle_gen_nonce, once channel id is permanently set */ +static u8 *handle_migrate_nonce(struct hsmd_client *c, + const u8 *msg_in) +{ + struct channel_id temp_id, perm_id; + struct musig_state *musig_lookup; + + if (!fromwire_hsmd_migrate_nonce(msg_in, &temp_id, &perm_id)) + return hsmd_status_malformed_request(c, msg_in); + + musig_lookup = musig_state_map_get(&secretstuff.musig_map, &temp_id); + if (!musig_lookup) { + return hsmd_status_bad_request_fmt(c, msg_in, + "Nonce for channel migration not found"); + } + + /* Update channel id, move keys */ + musig_lookup->channel_id = perm_id; + musig_state_map_add(&secretstuff.musig_map, musig_lookup); + musig_state_map_delkey(&secretstuff.musig_map, &temp_id); + + return towire_hsmd_migrate_nonce_reply(NULL); +} + /*~ The client has asked us to extract the shared secret from an EC Diffie * Hellman token. This doesn't leak any information, but requires the private * key, so the hsmd performs it. It's used to set up an encryption key for the @@ -1443,6 +1501,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; u8 *annex; struct sha256_double hash_out; + struct musig_state *musig_state_lookup; int i; @@ -1494,8 +1553,15 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) /* FIXME assert we have secnonce already... though if we don't this call will already crash... */ + /* Find secnonce in map */ + musig_state_lookup = musig_state_map_get(&secretstuff.musig_map, &channel_id); + if (!musig_state_lookup) { + return hsmd_status_bad_request(c, msg_in, + "No secret nonce found for this musig request"); + } + bipmusig_partial_sign(&secrets.funding_privkey, - &secretstuff.sec_nonce, + &musig_state_lookup->sec_nonce, pubnonce_ptrs, /* num_signers */ 2, &hash_out, @@ -1504,7 +1570,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) &p_sig.p_sig); /* Refill and return own next_nonce, using RNG+extra stuff for more security */ - bipmusig_gen_nonce(&secretstuff.sec_nonce, + bipmusig_gen_nonce(&musig_state_lookup->sec_nonce, &local_nonce.nonce, &secrets.funding_privkey, &keyagg_cache, @@ -1835,6 +1901,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, break; case WIRE_HSMD_GEN_NONCE: return handle_gen_nonce(client, msg); + case WIRE_HSMD_MIGRATE_NONCE: + return handle_migrate_nonce(client, msg); /* Eltoo stuff ends */ case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: @@ -1865,6 +1933,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: + case WIRE_HSMD_MIGRATE_NONCE_REPLY: break; } return hsmd_status_bad_request(client, msg, "Unknown request"); @@ -1985,6 +2054,9 @@ u8 *hsmd_init(struct secret hsm_secret, hsmd_status_failed(STATUS_FAIL_INTERNAL_ERROR, "Can't derive bolt12 keypair"); + /* Finally, initialize a hash table for music state, one entry per channel */ + musig_state_map_init(&secretstuff.musig_map); + /* Now we can consider ourselves initialized, and we won't get * upset if we get a non-init message. */ initialized = true; diff --git a/hsmd/libhsmd.h b/hsmd/libhsmd.h index 05d427cc9eea..36d3be75955a 100644 --- a/hsmd/libhsmd.h +++ b/hsmd/libhsmd.h @@ -89,4 +89,7 @@ void hsmd_status_failed(enum status_failreason code, bool hsmd_check_client_capabilities(struct hsmd_client *client, enum hsmd_wire t); +/* Hash function that just converts channel id into an int */ +size_t channel_id_key(const struct channel_id *id); + #endif /* LIGHTNING_HSMD_LIBHSMD_H */ diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index f2c8916627eb..abbdf5502e3d 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -498,6 +498,17 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * `channeld` which lives in channeld/full_channel. */ derive_channel_id(&cid, &state->funding); + /* Inform HSM we know of final channel id immediately before any attempts to sign */ + msg = towire_hsmd_migrate_nonce(NULL, + &state->channel_id, + &cid); + wire_sync_write(HSM_FD, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_migrate_nonce_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad migrate_nonce_reply %s", + tal_hex(tmpctx, msg)); + state->channel = new_initial_eltoo_channel(state, &cid, &state->funding, @@ -559,7 +570,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, * our funding key, it just needs the remote funding key to create the * tapscripts. */ msg = towire_hsmd_psign_update_tx(NULL, - &state->channel_id, + &cid, /* We track signature sessions via "final" channel id only */ *update_tx, *settle_tx, &state->their_funding_pubkey, @@ -1073,6 +1084,18 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) */ derive_channel_id(&state->channel_id, &state->funding); + /* Inform HSM we know of final channel id immediately before any attempts to sign */ + msg = towire_hsmd_migrate_nonce(NULL, + &id_in, /* temp id */ + &state->channel_id); + wire_sync_write(HSM_FD, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_migrate_nonce_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad migrate_nonce_reply %s", + tal_hex(tmpctx, msg)); + + /*~ We generate the `funding_signed` message here, since we have all * the data and it's only applicable in the fundee case. * @@ -1091,7 +1114,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* Make HSM sign it */ msg = towire_hsmd_psign_update_tx(NULL, - &state->channel_id, + &state->channel_id, /* Final channel_id just derived above */ update_tx, settle_tx, &state->their_funding_pubkey, From db30ca8746e4b5186c34a0a83a3ac7d9ba698791 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 21 Sep 2022 15:00:23 -0400 Subject: [PATCH 186/283] test script with three nodes going --- contrib/startup_regtest.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index dd521789d88f..0c969a19f171 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -150,7 +150,7 @@ start_ln() { setup_ln() { l2id=$(l2-cli getinfo | jq -r .id) - #l3id=$(l3-cli getinfo | jq -r .id) + l3id=$(l3-cli getinfo | jq -r .id) l1addr=$(l1-cli newaddr | jq -r .bech32) l2addr=$(l2-cli newaddr | jq -r .bech32) bt-cli loadwallet "default" @@ -158,11 +158,11 @@ setup_ln() { bt-cli sendtoaddress $l1addr 1 bt-cli sendtoaddress $l2addr 1 l1-cli connect $l2id@localhost:7272 - #l2-cli connect $l3id@localhost:7373 + l2-cli connect $l3id@localhost:7373 bt-cli generatetoaddress 6 $btcaddr sleep 5 l1-cli fundchannel $l2id 10000 normal false - #l2-cli fundchannel $l3id 10000 normal false + l2-cli fundchannel $l3id 10000 normal false bt-cli generatetoaddress 6 $btcaddr invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) @@ -182,7 +182,7 @@ setup_ln() { #invoice=$(l3-cli invoice 100000 hi "test" | jq -r .bolt11) #l2-cli pay $invoice - #invoice=$(l3-cli invoice 10000 hi "test" | jq -r .bolt11) + #invoice=$(l3-cli invoice 10000 hi2 "test" | jq -r .bolt11) #l1-cli pay $invoice } From 9de5672b9933ebc6623d320ca1981022d27266a3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 22 Sep 2022 11:28:12 -0400 Subject: [PATCH 187/283] single hop example working --- contrib/startup_regtest.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 0c969a19f171..298c242b8cbf 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & #"--dev-debugger=eltoo_channeld" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & # "--dev-debugger=" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 @@ -159,6 +159,7 @@ setup_ln() { bt-cli sendtoaddress $l2addr 1 l1-cli connect $l2id@localhost:7272 l2-cli connect $l3id@localhost:7373 + l1-cli connect $l3id@localhost:7373 bt-cli generatetoaddress 6 $btcaddr sleep 5 l1-cli fundchannel $l2id 10000 normal false @@ -179,11 +180,15 @@ setup_ln() { l2-cli pay $invoice - #invoice=$(l3-cli invoice 100000 hi "test" | jq -r .bolt11) - #l2-cli pay $invoice + invoice=$(l3-cli invoice 100000 hi "test" | jq -r .bolt11) + l2-cli pay $invoice + + # We aren't announcing channels, yet, we're considered a "dead + # end", so shove in routehint + l3scid=$(l3-cli listchannels | jq -r .channels[0].short_channel_id) - #invoice=$(l3-cli invoice 10000 hi2 "test" | jq -r .bolt11) - #l1-cli pay $invoice + invoice=$(l3-cli -k invoice msatoshi=10000 label=hi2 description="test" exposeprivatechannels="[${l3scid}]" | jq -r .bolt11) + l1-cli pay $invoice } stop_nodes() { From f1c696b02390426694afe508dbfbccf037a3d028 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 22 Sep 2022 12:05:10 -0400 Subject: [PATCH 188/283] Bit more logging for debugging --- contrib/startup_regtest.sh | 12 ++++++------ lightningd/peer_htlcs.c | 8 ++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 298c242b8cbf..540878f577c2 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -166,27 +166,27 @@ setup_ln() { l2-cli fundchannel $l3id 10000 normal false bt-cli generatetoaddress 6 $btcaddr + sleep 0.5 invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice - + sleep 0.5 invoice=$(l2-cli invoice 10000 hi2 "test" | jq -r .bolt11) l1-cli pay $invoice - + sleep 0.5 invoice=$(l2-cli invoice 1000000 hi3 "test" | jq -r .bolt11) l1-cli pay $invoice - sleep 0.5 invoice=$(l1-cli invoice 500000 hi "test" | jq -r .bolt11) l2-cli pay $invoice - - + sleep 0.5 invoice=$(l3-cli invoice 100000 hi "test" | jq -r .bolt11) l2-cli pay $invoice # We aren't announcing channels, yet, we're considered a "dead # end", so shove in routehint + sleep 0.5 l3scid=$(l3-cli listchannels | jq -r .channels[0].short_channel_id) - + echo $l3scid invoice=$(l3-cli -k invoice msatoshi=10000 label=hi2 description="test" exposeprivatechannels="[${l3scid}]" | jq -r .bolt11) l1-cli pay $invoice } diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index cbcbe66cb5ca..31131720af48 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1111,20 +1111,24 @@ htlc_accepted_hook_final(struct htlc_accepted_hook_payload *request STEALS) NULL, request->failtlvtype, request->failtlvpos))); } else if (rs->nextcase == ONION_FORWARD) { + log_debug(channel->log, + "Forwarding HTLC"); forward_htlc(hin, hin->cltv_expiry, request->payload->amt_to_forward, request->payload->outgoing_cltv, request->payload->forward_channel, serialize_onionpacket(tmpctx, rs->next), request->next_blinding); - } else + } else { + log_debug(channel->log, + "Handling HTLC locally"); handle_localpay(hin, request->payload->amt_to_forward, request->payload->outgoing_cltv, *request->payload->total_msat, request->payload->payment_secret, request->payload->payment_metadata); - + } tal_free(request); } From ea22144ac0790c773e81c8dbb324c067a448ff29 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 22 Sep 2022 17:14:11 -0400 Subject: [PATCH 189/283] Create eltoo_onchaind, need to auto-rebind update/settle tx still --- contrib/startup_regtest.sh | 22 ++++++ lightningd/onchain_control.c | 133 +++++++++++++++++++++++++++++++++++ lightningd/onchain_control.h | 4 ++ lightningd/peer_control.c | 2 +- onchaind/Makefile | 12 +++- onchaind/onchaind_wire.csv | 9 +++ 6 files changed, 179 insertions(+), 3 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 540878f577c2..3a4a82be7a7e 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -148,6 +148,28 @@ start_ln() { echo " bt-cli, stop_ln" } +onchain_ln() { + # Test eltoo_onchaind handling + l1addr=$(l1-cli newaddr | jq -r .bech32) + l2id=$(l2-cli getinfo | jq -r .id) + bt-cli loadwallet "default" + btcaddr=$(bt-cli getnewaddress) + bt-cli sendtoaddress $l1addr 1 + l1-cli connect $l2id@localhost:7272 + bt-cli generatetoaddress 6 $btcaddr + sleep 5 + l1-cli fundchannel $l2id 10000 normal false + bt-cli generatetoaddress 6 $btcaddr + sleep 2 + invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) + l1-cli pay $invoice + + UPDATE_HEX=FIXME get this from rpc endpoint with things re-bound + txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) + bt-cli prioritisetransaction $txid 0 100000000 + bt-cli sendrawtransaction $UPDATE_HEX +} + setup_ln() { l2id=$(l2-cli getinfo | jq -r .id) l3id=$(l3-cli getinfo | jq -r .id) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 1c22cc1b9627..f92ea8c8daeb 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -135,6 +135,30 @@ static void handle_onchain_init_reply(struct channel *channel, const u8 *msg) onchaind_tell_fulfill(channel); } +static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *msg) +{ + + /* FIXME any information required in reply? */ + if (!fromwire_eltoo_onchaind_init_reply(msg)) { + channel_internal_error(channel, "Invalid eltoo_onchaind_init_reply %s", + tal_hex(tmpctx, msg)); + return; + } + + /* FIXME: We may already be ONCHAIN state when we implement restart! */ + channel_set_state(channel, + FUNDING_SPEND_SEEN, + ONCHAIN, + REASON_UNKNOWN, + "Onchain init reply"); + + /* Send eltoo_onchaind any other mesages required */ + + /* Tell it about any preimages we know. */ + onchaind_tell_fulfill(channel); +} + + /** * Notify onchaind about the depth change of the watched tx. */ @@ -577,11 +601,55 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U case WIRE_ONCHAIND_DEV_MEMLEAK: case WIRE_ONCHAIND_DEV_MEMLEAK_REPLY: break; + /* These are illegal */ + case WIRE_ELTOO_ONCHAIND_INIT: + case WIRE_ELTOO_ONCHAIND_INIT_REPLY: + abort(); + } + + return 0; +} + +static unsigned int eltoo_onchain_msg(struct subd *sd, const u8 *msg, const int *fds UNUSED) +{ + enum onchaind_wire t = fromwire_peektype(msg); + + switch (t) { + case WIRE_ELTOO_ONCHAIND_INIT_REPLY: + handle_eltoo_onchain_init_reply(sd->channel, msg); + break; + + case WIRE_ONCHAIND_BROADCAST_TX: + case WIRE_ONCHAIND_UNWATCH_TX: + case WIRE_ONCHAIND_EXTRACTED_PREIMAGE: + case WIRE_ONCHAIND_MISSING_HTLC_OUTPUT: + case WIRE_ONCHAIND_HTLC_TIMEOUT: + case WIRE_ONCHAIND_ALL_IRREVOCABLY_RESOLVED: + case WIRE_ONCHAIND_ADD_UTXO: + case WIRE_ONCHAIND_ANNOTATE_TXIN: + case WIRE_ONCHAIND_ANNOTATE_TXOUT: + case WIRE_ONCHAIND_NOTIFY_COIN_MVT: + /* FIXME implement */ + abort(); + /* We send these, not receive them */ + case WIRE_ONCHAIND_INIT: + case WIRE_ONCHAIND_SPENT: + case WIRE_ONCHAIND_DEPTH: + case WIRE_ONCHAIND_HTLCS: + case WIRE_ONCHAIND_KNOWN_PREIMAGE: + case WIRE_ONCHAIND_DEV_MEMLEAK: + case WIRE_ONCHAIND_DEV_MEMLEAK_REPLY: + case WIRE_ELTOO_ONCHAIND_INIT: + break; + /* These are illegal */ + case WIRE_ONCHAIND_INIT_REPLY: + abort(); } return 0; } + /* Only error onchaind can get is if it dies. */ static void onchain_error(struct channel *channel, struct peer_fd *pps UNUSED, @@ -607,6 +675,10 @@ enum watch_result onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, u32 blockheight) { + if (channel->our_config.is_eltoo) { + return eltoo_onchaind_funding_spent(channel, tx, blockheight); + } + u8 *msg; struct bitcoin_txid our_last_txid; struct lightningd *ld = channel->peer->ld; @@ -762,6 +834,67 @@ enum watch_result onchaind_funding_spent(struct channel *channel, return KEEP_WATCHING; } +/* With a reorg, this can get called multiple times; each time we'll kill + * onchaind (like any other owner), and restart */ +enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, + const struct bitcoin_tx *tx, + u32 blockheight) +{ + u8 *msg; + struct lightningd *ld = channel->peer->ld; + int hsmfd; + enum state_change reason; + + /* use REASON_ONCHAIN or closer's reason, if known */ + reason = REASON_ONCHAIN; + if (channel->closer != NUM_SIDES) + reason = REASON_UNKNOWN; /* will use last cause as reason */ + + channel_fail_permanent(channel, reason, "Funding transaction spent"); + + /* We could come from almost any state. */ + /* NOTE(mschmoock) above comment is wrong, since we failed above! */ + channel_set_state(channel, + channel->state, + FUNDING_SPEND_SEEN, + reason, + "Onchain funding spend"); + + hsmfd = hsm_get_client_fd(ld, &channel->peer->id, + channel->dbid, + HSM_CAP_SIGN_ONCHAIN_TX + | HSM_CAP_COMMITMENT_POINT); + + + channel_set_owner(channel, new_channel_subd(channel, ld, + "lightning_eltoo_onchaind", + channel, + &channel->peer->id, + channel->log, false, + onchaind_wire_name, /* N.B. Reusing onchaind */ + eltoo_onchain_msg, + onchain_error, + channel_set_billboard, + take(&hsmfd), + NULL)); + + if (!channel->owner) { + log_broken(channel->log, "Could not subdaemon onchain: %s", + strerror(errno)); + return KEEP_WATCHING; + } + + /* Hello World :) */ + msg = towire_eltoo_onchaind_init(channel, + tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1)); + subd_send_msg(channel->owner, take(msg)); + + watch_tx_and_outputs(channel, tx); + + /* We keep watching until peer finally deleted, for reorgs. */ + return KEEP_WATCHING; +} + void onchaind_replay_channels(struct lightningd *ld) { u32 *onchaind_ids; diff --git a/lightningd/onchain_control.h b/lightningd/onchain_control.h index c0fe3d3b09dd..4936ad6bdd0f 100644 --- a/lightningd/onchain_control.h +++ b/lightningd/onchain_control.h @@ -11,6 +11,10 @@ enum watch_result onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, u32 blockheight); +enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, + const struct bitcoin_tx *tx, + u32 blockheight); + void onchaind_replay_channels(struct lightningd *ld); #endif /* LIGHTNING_LIGHTNINGD_ONCHAIN_CONTROL_H */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 6bf15996a372..5da0ce979804 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1651,7 +1651,7 @@ static enum watch_result funding_spent(struct channel *channel, wallet_channeltxs_add(channel->peer->ld->wallet, channel, WIRE_ONCHAIND_INIT, &txid, 0, block->height); - return onchaind_funding_spent(channel, tx, block->height); + return onchaind_funding_spent(channel, tx, block->height); } void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel) diff --git a/onchaind/Makefile b/onchaind/Makefile index 28c8b6a32f10..b1221bf2e83d 100644 --- a/onchaind/Makefile +++ b/onchaind/Makefile @@ -11,16 +11,23 @@ ONCHAIND_SRC := onchaind/onchaind.c \ onchaind/onchaind_wire.c \ onchaind/onchaind.c +ELTOO_ONCHAIND_SRC := onchaind/eltoo_onchaind.c \ + onchaind/onchaind_wiregen.c \ + onchaind/onchaind_wire.c \ + onchaind/onchain_types_names_gen.h: onchaind/onchain_types.h ccan/ccan/cdump/tools/cdump-enumstr ccan/ccan/cdump/tools/cdump-enumstr onchaind/onchain_types.h > $@ ONCHAIND_OBJS := $(ONCHAIND_SRC:.c=.o) $(ONCHAIND_OBJS): $(ONCHAIND_HEADERS) +ELTOO_ONCHAIND_OBJS := $(ELTOO_ONCHAIND_SRC:.c=.o) +$(ELTOO_ONCHAIND_OBJS): $(ONCHAIND_HEADERS) + # Make sure these depend on everything. -ALL_C_SOURCES += $(ONCHAIND_SRC) +ALL_C_SOURCES += $(ONCHAIND_SRC) $(ELTOO_ONCHAIND_SRC) ALL_C_HEADERS += $(ONCHAIND_HEADERS) -ALL_PROGRAMS += lightningd/lightning_onchaind +ALL_PROGRAMS += lightningd/lightning_onchaind lightningd/lightning_eltoo_onchaind # Here's what lightningd depends on LIGHTNINGD_CONTROL_HEADERS += \ @@ -69,5 +76,6 @@ ONCHAIND_COMMON_OBJS := \ common/wireaddr.o lightningd/lightning_onchaind: $(ONCHAIND_OBJS) $(WIRE_ONION_OBJS) $(ONCHAIND_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS) +lightningd/lightning_eltoo_onchaind: $(ELTOO_ONCHAIND_OBJS) $(WIRE_ONION_OBJS) $(ONCHAIND_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS) include onchaind/test/Makefile diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index e2dfd031620a..ed577f326050 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -139,3 +139,12 @@ msgdata,onchaind_annotate_txin,type,enum wallet_tx_type, msgtype,onchaind_notify_coin_mvt,5037 msgdata,onchaind_notify_coin_mvt,mvt,chain_coin_mvt, + +# Eltoo stuff following (Hello World for now) +msgtype,eltoo_onchaind_init,5061 +msgdata,eltoo_onchaind_init,tx_parts,tx_parts, + +# This says we're ready; give us htlcs and preimages. +msgtype,eltoo_onchaind_init_reply,5161 + + From 1ec83e7d7f8abcd2f520dd3128814eea6aca534a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 22 Sep 2022 17:28:28 -0400 Subject: [PATCH 190/283] Enough to trigger and explode the new subd --- channeld/eltoo_channeld.c | 1 - contrib/startup_regtest.sh | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index cbd75973fe39..ca830f5ba80b 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1246,7 +1246,6 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) peer->channel->last_unsigned_update, peer->channel->last_unsigned_settle, &peer->channel->eltoo_keyset.inner_pubkey); - wire_sync_write(HSM_FD, take(comb_msg)); comb_msg = wire_sync_read(tmpctx, HSM_FD); diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 3a4a82be7a7e..76ec3e5aae18 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -164,10 +164,13 @@ onchain_ln() { invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice - UPDATE_HEX=FIXME get this from rpc endpoint with things re-bound + # For now, grab first update tx that is fully signed in logs + # "Signed update transaction" and "Settle transaction 0" + # UPDATE_HEX=FIXME get this from rpc endpoint with things re-bound txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $UPDATE_HEX + bt-cli generatetoaddress 1 $btcaddr } setup_ln() { From 1aed83d381b25e79e630df721c152026c8d06853 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 26 Sep 2022 15:17:18 -0400 Subject: [PATCH 191/283] eltoo_onchaind is alive --- contrib/startup_regtest.sh | 6 ++++-- lightningd/lightningd.c | 4 +++- lightningd/onchain_control.c | 2 +- onchaind/onchaind_wire.csv | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 76ec3e5aae18..8937ab30e09d 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -109,7 +109,7 @@ start_nodes() { # Start the lightning nodes test -f "/tmp/l$i-$network/lightningd-$network.pid" || \ - "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" & # "--dev-debugger=" & + "$LIGHTNINGD" "--lightning-dir=/tmp/l$i-$network" "--dev-debugger=eltoo_onchaind" & # shellcheck disable=SC2139 disable=SC2086 alias l$i-cli="$LCLI --lightning-dir=/tmp/l$i-$network" # shellcheck disable=SC2139 disable=SC2086 @@ -160,13 +160,15 @@ onchain_ln() { sleep 5 l1-cli fundchannel $l2id 10000 normal false bt-cli generatetoaddress 6 $btcaddr - sleep 2 + sleep 5 invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice # For now, grab first update tx that is fully signed in logs # "Signed update transaction" and "Settle transaction 0" # UPDATE_HEX=FIXME get this from rpc endpoint with things re-bound + # UPDATE_PSBT=FIXME + UPDATE_HEX=$(bt-cli finalizepsbt $UPDATE_PSBT | jq -r .hex ) txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $UPDATE_HEX diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 882295e08d2b..0d2de4329b68 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -310,8 +310,10 @@ static const char *subdaemons[] = { "lightning_hsmd", "lightning_onchaind", "lightning_openingd", + // FIXME "lightning_eltoo_closingd", "lightning_eltoo_channeld", - "lightning_eltoo_openingd" + "lightning_eltoo_openingd", + "lightning_eltoo_onchaind" }; /* Return true if called with a recognized subdaemon e.g. "hsmd" */ diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index f92ea8c8daeb..9c76076a20df 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -885,7 +885,7 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, } /* Hello World :) */ - msg = towire_eltoo_onchaind_init(channel, + msg = towire_eltoo_onchaind_init(channel, chainparams, tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1)); subd_send_msg(channel->owner, take(msg)); diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index ed577f326050..479ec30c7e68 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -142,6 +142,7 @@ msgdata,onchaind_notify_coin_mvt,mvt,chain_coin_mvt, # Eltoo stuff following (Hello World for now) msgtype,eltoo_onchaind_init,5061 +msgdata,eltoo_onchaind_init,chainparams,chainparams, msgdata,eltoo_onchaind_init,tx_parts,tx_parts, # This says we're ready; give us htlcs and preimages. From 8c4159ec5451b2af0c4322ccd769caa585caf087 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 27 Sep 2022 11:23:19 -0400 Subject: [PATCH 192/283] Expose update/settle txs in rpc, propagate txs to onchaind --- contrib/startup_regtest.sh | 10 ++++------ lightningd/onchain_control.c | 5 ++++- lightningd/peer_control.c | 11 +++++++++++ onchaind/onchaind_wire.csv | 2 ++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 8937ab30e09d..54c460936815 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -163,12 +163,10 @@ onchain_ln() { sleep 5 invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice - - # For now, grab first update tx that is fully signed in logs - # "Signed update transaction" and "Settle transaction 0" - # UPDATE_HEX=FIXME get this from rpc endpoint with things re-bound - # UPDATE_PSBT=FIXME - UPDATE_HEX=$(bt-cli finalizepsbt $UPDATE_PSBT | jq -r .hex ) + sleep 0.2 + # Only funding tx is bound already, subsequent must be re-bound + UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) + SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_settle_tx ) txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $UPDATE_HEX diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 9c76076a20df..75b6fd64daf4 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -850,7 +850,10 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, if (channel->closer != NUM_SIDES) reason = REASON_UNKNOWN; /* will use last cause as reason */ + /* FIXME need to figure out what part of this to do vs delegate to onchaind... + currently this crashes hard trying to "sign and submit" last tx channel_fail_permanent(channel, reason, "Funding transaction spent"); + */ /* We could come from almost any state. */ /* NOTE(mschmoock) above comment is wrong, since we failed above! */ @@ -886,7 +889,7 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, /* Hello World :) */ msg = towire_eltoo_onchaind_init(channel, chainparams, - tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1)); + tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), channel->last_tx, channel->last_settle_tx); subd_send_msg(channel->owner, take(msg)); watch_tx_and_outputs(channel, tx); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 5da0ce979804..d0b58634f6fa 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -939,7 +939,18 @@ static void json_add_channel(struct lightningd *ld, "out_msatoshi_fulfilled", "out_fulfilled_msat"); + json_add_htlcs(ld, response, channel); + + /* FIXME add latest update_tx and settle_tx, ideally re-bound */ + if (channel->last_tx) { + json_add_tx(response, "last_update_tx", channel->last_tx); + } + + if (channel->last_settle_tx) { + json_add_tx(response, "last_settle_tx", channel->last_settle_tx); + } + json_object_end(response); } diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 479ec30c7e68..fa0f4abbe9ec 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -144,6 +144,8 @@ msgdata,onchaind_notify_coin_mvt,mvt,chain_coin_mvt, msgtype,eltoo_onchaind_init,5061 msgdata,eltoo_onchaind_init,chainparams,chainparams, msgdata,eltoo_onchaind_init,tx_parts,tx_parts, +msgdata,eltoo_onchaind_init,update_tx,bitcoin_tx, +msgdata,eltoo_onchaind_init,settle_tx,bitcoin_tx, # This says we're ready; give us htlcs and preimages. msgtype,eltoo_onchaind_init_reply,5161 From c75ac6c989454317296ff698a108c1ec5e3479e7 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 27 Sep 2022 15:55:23 -0400 Subject: [PATCH 193/283] RPC endpoint serving up funding-output-bound update/settle txs --- bitcoin/signature.c | 8 ++ bitcoin/signature.h | 12 +++ common/update_tx.c | 2 +- contrib/startup_regtest.sh | 10 ++- lightningd/Makefile | 1 + lightningd/channel.c | 2 +- lightningd/peer_control.c | 84 +++++++++++++++++++-- lightningd/test/run-invoice-select-inchan.c | 8 ++ wallet/test/run-wallet.c | 8 ++ 9 files changed, 126 insertions(+), 9 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 18edbf956e6d..a27d6e38d505 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -342,6 +342,14 @@ bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * co return secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &xonly_inner_pubkey); } +bool bipmusig_partial_sigs_combine(const secp256k1_musig_partial_sig * const *p_sigs, + size_t num_signers, + const secp256k1_musig_session *session, + struct bip340sig *sig) +{ + return secp256k1_musig_partial_sig_agg(secp256k1_ctx, sig->u8, session, p_sigs, num_signers); +} + void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, const u8 *script, enum sighash_type sighash_type, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 9705c042077c..1f7eeb539030 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -202,6 +202,18 @@ bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * co const struct sha256_double *hash, struct bip340sig *sig); +/** + * bipmusig_partial_sigs_combine - Same as bipmusig_partial_sigs_combine_verify but + * no verification. Should only be used on trusted data! + * @p_sigs: partial signatures to combine and validate + * @num_signers: number of partial signatures to combine + * @sig: final BIP340 signature to output + */ +bool bipmusig_partial_sigs_combine(const secp256k1_musig_partial_sig * const *p_sigs, + size_t num_signers, + const secp256k1_musig_session *session, + struct bip340sig *sig); + /** * check_signed_hash - check a raw secp256k1 signature. * @h: hash which was signed. diff --git a/common/update_tx.c b/common/update_tx.c index 2df22145d797..f08b19390097 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -124,7 +124,7 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, update_witness[0] = final_sig; update_witness[1] = update_tapscript[0]; update_witness[2] = compute_control_block(tmpctx, /* other_script */ NULL, /* annex_hint */ NULL, psbt_inner_pubkey, pubkey_parity(&taproot_pk)); - update_witness[3] = make_eltoo_annex(tmpctx, settle_tx);; + update_witness[3] = make_eltoo_annex(tmpctx, settle_tx); bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 54c460936815..9aa9adf1eece 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -164,13 +164,21 @@ onchain_ln() { invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice sleep 0.2 - # Only funding tx is bound already, subsequent must be re-bound + + # Should be bound to funding output! UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_settle_tx ) txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $UPDATE_HEX bt-cli generatetoaddress 1 $btcaddr + + # Settle tx can be broadcast after shared_delay + bt-cli generatetoaddress 6 $btcaddr + txid=$(bt-cli decoderawtransaction $SETTLE_HEX | jq -r .txid) + bt-cli prioritisetransaction $txid 0 100000000 + bt-cli sendrawtransaction $SETTLE_HEX + bt-cli generatetoaddress 1 $btcaddr } setup_ln() { diff --git a/lightningd/Makefile b/lightningd/Makefile index 8876dc55c929..31ca3f61a60a 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -125,6 +125,7 @@ LIGHTNINGD_COMMON_OBJS := \ common/status_wire.o \ common/timeout.o \ common/type_to_string.o \ + common/update_tx.o \ common/utils.o \ common/utxo.o \ common/version.o \ diff --git a/lightningd/channel.c b/lightningd/channel.c index cc32a093e955..3779bc592ca9 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -707,7 +707,7 @@ void channel_set_last_eltoo_txs(struct channel *channel, channel->last_settle_tx = tal_steal(channel, settle_tx); channel->eltoo_keyset.other_psig = *their_psig; - channel->eltoo_keyset.self_psig = *their_psig; + channel->eltoo_keyset.self_psig = *our_psig; channel->eltoo_keyset.session = *session; } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index d0b58634f6fa..ceaa1fc36121 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -942,13 +943,84 @@ static void json_add_channel(struct lightningd *ld, json_add_htlcs(ld, response, channel); - /* FIXME add latest update_tx and settle_tx, ideally re-bound */ - if (channel->last_tx) { - json_add_tx(response, "last_update_tx", channel->last_tx); - } - if (channel->last_settle_tx) { - json_add_tx(response, "last_settle_tx", channel->last_settle_tx); + if (channel->last_tx->wtx->locktime == 500000000) { + json_add_tx(response, "last_update_tx", channel->last_tx); + /* FIXME Settle tx needs to be re-bound still! Let's not do binding before realtime... */ + json_add_tx(response, "last_settle_tx", channel->last_settle_tx); + } else { + // Check if this is initial tx, if not, rebind and add sig + // Note that if txid changes(adding fee input), you need to rebind again! + u8 *p = tal_arr(tmpctx, u8, 0); + const u8 *p_start; + struct bitcoin_tx *bound_update_tx, *bound_settle_tx; + size_t p_len; + const secp256k1_musig_partial_sig * psig_ptrs[2]; + const struct pubkey * pubkey_ptrs[2]; + struct bip340sig sig; + int ok; + secp256k1_musig_keyagg_cache dummy_cache; + struct pubkey inner_pubkey; + struct eltoo_keyset keyset_copy; + struct bitcoin_txid txid; + + towire_bitcoin_tx(&p, channel->last_tx); + p_start = p; + p_len = tal_count(p); + bound_update_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); + assert(bound_update_tx); + + /* re-set and serialize settle tx next */ + p = tal_arr(tmpctx, u8, 0); + towire_bitcoin_tx(&p, channel->last_settle_tx); + p_start = p; + + p_len = tal_count(p); + bound_settle_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); + assert(bound_settle_tx); + + psig_ptrs[0] = &channel->eltoo_keyset.self_psig.p_sig; + psig_ptrs[1] = &channel->eltoo_keyset.other_psig.p_sig; + + /* FIXME channel->eltoo_keyset should be set at same time as these fields are */ + keyset_copy.self_funding_key = channel->local_funding_pubkey; + keyset_copy.other_funding_key = channel->channel_info.remote_fundingkey; + //channel->eltoo_keyset.self_funding_key = channel->channel_info.remote_fundingkey; + //channel->eltoo_keyset.other_funding_key = channel->channel_info.remote_fundingkey; + /* FIXME: inner_pubkey should be in PSBT, don't need to make key here */ + pubkey_ptrs[0] = &keyset_copy.self_funding_key; + pubkey_ptrs[1] = &keyset_copy.other_funding_key; + + ok = bipmusig_partial_sigs_combine(psig_ptrs, + 2 /* num_signers */, + &channel->eltoo_keyset.session.session, + &sig); + assert(ok); // Trusted data!!! + + bipmusig_inner_pubkey(&inner_pubkey, + &dummy_cache, + pubkey_ptrs, + 2 /* n_pubkeys */); + + /* FIXME pass in pubkeys, not keyset ... or get pubkeys from PSBT directly */ + bind_update_tx_to_funding_outpoint(bound_update_tx, + bound_settle_tx, + &channel->funding, + &keyset_copy, + &inner_pubkey, + &sig); + + /* Really direct txid surgery... libwally routine needed */ + bitcoin_txid(bound_update_tx, &txid); + memcpy(bound_settle_tx->wtx->inputs[0].txhash, &txid, 32); + + /* FIXME publish both bound and unbound versions */ + json_add_tx(response, "last_update_tx", bound_update_tx); + + json_add_tx(response, "last_settle_tx", bound_settle_tx); + + /* FIXME Deallocate copied txns? */ + } } json_object_end(response); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 382861851820..613ee71821da 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -14,6 +14,14 @@ bool deprecated_apis = false; struct channel *any_channel_by_scid(struct lightningd *ld UNNEEDED, const struct short_channel_id *scid UNNEEDED) { fprintf(stderr, "any_channel_by_scid called!\n"); abort(); } +/* Generated stub for bind_update_tx_to_funding_outpoint */ +void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, + const struct bitcoin_tx *settle_tx UNNEEDED, + const struct bitcoin_outpoint *funding_outpoint UNNEEDED, + const struct eltoo_keyset *eltoo_keyset UNNEEDED, + const struct pubkey *psbt_inner_pubkey UNNEEDED, + const struct bip340sig *sig UNNEEDED) +{ fprintf(stderr, "bind_update_tx_to_funding_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index a7efcfd075bc..3a1dddcdaa81 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -51,6 +51,14 @@ bool deprecated_apis = true; /* Generated stub for bigsize_put */ size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED) { fprintf(stderr, "bigsize_put called!\n"); abort(); } +/* Generated stub for bind_update_tx_to_funding_outpoint */ +void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, + const struct bitcoin_tx *settle_tx UNNEEDED, + const struct bitcoin_outpoint *funding_outpoint UNNEEDED, + const struct eltoo_keyset *eltoo_keyset UNNEEDED, + const struct pubkey *psbt_inner_pubkey UNNEEDED, + const struct bip340sig *sig UNNEEDED) +{ fprintf(stderr, "bind_update_tx_to_funding_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, From b77cbe951f682472a9694debb17e10d64919ee78 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 27 Sep 2022 16:00:25 -0400 Subject: [PATCH 194/283] add unbound versions as well --- lightningd/peer_control.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index ceaa1fc36121..eb5bf031b81b 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1019,6 +1019,11 @@ static void json_add_channel(struct lightningd *ld, json_add_tx(response, "last_settle_tx", bound_settle_tx); + json_add_tx(response, "unbound_update_tx", channel->last_tx); + + json_add_tx(response, "unbound_settle_tx", channel->last_settle_tx); + + /* FIXME Deallocate copied txns? */ } } From beb88a1c81d2f51c6aa8e8e7795e99b279e1ae6b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 27 Sep 2022 16:07:41 -0400 Subject: [PATCH 195/283] bind first settle transaction as well --- lightningd/peer_control.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index eb5bf031b81b..df62f79dc2cc 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -945,8 +945,11 @@ static void json_add_channel(struct lightningd *ld, if (channel->last_settle_tx) { if (channel->last_tx->wtx->locktime == 500000000) { + struct bitcoin_txid txid; json_add_tx(response, "last_update_tx", channel->last_tx); - /* FIXME Settle tx needs to be re-bound still! Let's not do binding before realtime... */ + /* Really direct txid surgery... libwally routine needed */ + bitcoin_txid(channel->last_tx, &txid); + memcpy(channel->last_settle_tx->wtx->inputs[0].txhash, &txid, 32); json_add_tx(response, "last_settle_tx", channel->last_settle_tx); } else { // Check if this is initial tx, if not, rebind and add sig From 811221f321d00df3f306c657d460363eab5cc724 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 28 Sep 2022 10:21:28 -0400 Subject: [PATCH 196/283] remove comment --- lightningd/peer_control.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index df62f79dc2cc..c098d9a49a9d 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1017,7 +1017,6 @@ static void json_add_channel(struct lightningd *ld, bitcoin_txid(bound_update_tx, &txid); memcpy(bound_settle_tx->wtx->inputs[0].txhash, &txid, 32); - /* FIXME publish both bound and unbound versions */ json_add_tx(response, "last_update_tx", bound_update_tx); json_add_tx(response, "last_settle_tx", bound_settle_tx); From a983fe1516602228d49dbe3399fb95c8c3c0560c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 28 Sep 2022 14:18:08 -0400 Subject: [PATCH 197/283] rework rebinding a bit --- channeld/test/run-settle_tx.c | 6 +-- common/update_tx.c | 17 ++++++-- common/update_tx.h | 18 ++++++-- contrib/startup_regtest.sh | 2 + lightningd/peer_control.c | 46 ++++++++++++++++----- lightningd/peer_control.h | 2 + lightningd/test/run-invoice-select-inchan.c | 13 ++++-- openingd/eltoo_openingd.c | 6 +-- wallet/test/run-wallet.c | 13 ++++-- 9 files changed, 92 insertions(+), 31 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index ce491c834fee..708c9f766877 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -581,7 +581,7 @@ static int test_invalid_update_tx(void) sig = musig_sign(update_tx, annex_0, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* Re-bind, add final script/tapscript info into PSBT */ - bind_update_tx_to_funding_outpoint(update_tx, + bind_tx_to_funding_outpoint(update_tx, tx, &update_output, &eltoo_keyset, @@ -625,7 +625,7 @@ static int test_invalid_update_tx(void) sig = musig_sign(update_tx_1_A, annex_1, &alice_funding_privkey, &bob_funding_privkey, &inner_pubkey, keyagg_cache); /* This can RBF the first update tx */ - bind_update_tx_to_funding_outpoint(update_tx_1_A, + bind_tx_to_funding_outpoint(update_tx_1_A, settle_tx_1, &update_output, &eltoo_keyset, @@ -752,7 +752,7 @@ static int test_initial_settlement_tx(void) /* We want to close the channel without cooperation... time to rebind and finalize */ /* Re-bind, add final script/tapscript info into PSBT */ - bind_update_tx_to_funding_outpoint(update_tx, + bind_tx_to_funding_outpoint(update_tx, tx, &update_output, &eltoo_keyset, diff --git a/common/update_tx.c b/common/update_tx.c index f08b19390097..9c9e180f61ca 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -62,8 +62,8 @@ void tx_add_unbound_input(struct bitcoin_tx *update_tx, struct amount_sat fundin assert(input_num == 0); } -void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, - const struct bitcoin_tx *settle_tx, +void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, + struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, const struct eltoo_keyset *eltoo_keyset, const struct pubkey *psbt_inner_pubkey, @@ -117,8 +117,6 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, /* scriptSig */ NULL, funding_sats, script_pubkey, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); assert(input_num == 0); - /* FIXME we can now rebind settle_tx's prevout */ - /* Witness stack, bottom to top: MuSig2 sig + tapscript + control block + Annex data */ update_witness = tal_arr(tmpctx, u8 *, 4); update_witness[0] = final_sig; @@ -128,6 +126,17 @@ void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } +void bind_settle_tx(const struct bitcoin_tx *update_tx, + int output_index, + struct bitcoin_tx *settle_tx) +{ + struct bitcoin_txid txid; + /* Really direct txid surgery... libwally routine better to modify PSBT input! */ + bitcoin_txid(update_tx, &txid); + assert(settle_tx->wtx->num_inputs == 1); /* We don't craft anything else */ + memcpy(settle_tx->wtx->inputs[0].txhash, &txid, 32); +} + void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *outpoint, diff --git a/common/update_tx.h b/common/update_tx.h index f345cc151501..6ebd79965035 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -21,8 +21,20 @@ void tx_add_unbound_input(struct bitcoin_tx *update_tx, struct amount_sat funding_sats, const struct pubkey *inner_pubkey); +/* Called just in time before broadcasting to spend expired + update output. + * @update_tx: the update transaction that has reached enough + * confirmations to spend via settle path + * @output_index: which output index is to be spent + * @settle_tx: the settlement transaction to rebind + **/ +void bind_settle_tx(const struct bitcoin_tx *update_tx, + int output_index, + struct bitcoin_tx *settle_tx); + /* Used to bind the update transaction to the funding outpoint - * of the eltoo contract. This is the expected (non-malicious) + * of the eltoo contract, and also re-binds the settle transaction. + * This is the expected (non-malicious) * failure mode of a channel. Also finalizes the witness data. * @update_tx: The transaction being re-binded * @settle_tx: The corresponding settlement transaction, also re-binded @@ -31,8 +43,8 @@ void tx_add_unbound_input(struct bitcoin_tx *update_tx, * @psbt_inner_pubkey: Inner pubkey for the state input * @sig: bip340 signature to be put into witness */ -void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, - const struct bitcoin_tx *settle_tx, +void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, + struct bitcoin_tx *settle_tx, const struct bitcoin_outpoint *funding_outpoint, const struct eltoo_keyset *eltoo_keyset, const struct pubkey *psbt_inner_pubkey, diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 9aa9adf1eece..7fd389f030e7 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -161,6 +161,8 @@ onchain_ln() { l1-cli fundchannel $l2id 10000 normal false bt-cli generatetoaddress 6 $btcaddr sleep 5 + FIRST_UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) + FIRST_SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_settle_tx ) invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice sleep 0.2 diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index c098d9a49a9d..d606557a2d03 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -232,6 +232,11 @@ static bool invalid_last_tx(const struct bitcoin_tx *tx) #endif } +static void eltoo_finalize_and_send_last(struct lightningd *ld) +{ + assert(ld); +} + static void sign_and_send_last(struct lightningd *ld, struct channel *channel, struct bitcoin_tx *last_tx, @@ -253,9 +258,32 @@ static void sign_and_send_last(struct lightningd *ld, remove_sig(last_tx); } +void eltoo_drop_to_chain(struct lightningd *ld, struct channel *channel, + bool cooperative) +{ + // Channel inflights aren't eltoo-aware... struct channel_inflight *inflight; + + /* FIXME We need to drop *every* commitment transaction to chain + if (!cooperative && !list_empty(&channel->inflights)) { + list_for_each(&channel->inflights, inflight, list) + sign_and_send_last(ld, channel, + inflight->last_tx, + &inflight->last_sig); + } else + */ + /* FIXME figure out interface */ + eltoo_finalize_and_send_last(ld); + + resolve_close_command(ld, channel, cooperative); +} + void drop_to_chain(struct lightningd *ld, struct channel *channel, bool cooperative) { + if (channel->our_config.is_eltoo) { + eltoo_drop_to_chain(ld, channel, cooperative); + return; + } struct channel_inflight *inflight; /* BOLT #2: * @@ -945,11 +973,10 @@ static void json_add_channel(struct lightningd *ld, if (channel->last_settle_tx) { if (channel->last_tx->wtx->locktime == 500000000) { - struct bitcoin_txid txid; + bind_settle_tx(channel->last_tx, + 0 /* output_index: we can't know for sure until update tx confirms... */, + channel->last_settle_tx); json_add_tx(response, "last_update_tx", channel->last_tx); - /* Really direct txid surgery... libwally routine needed */ - bitcoin_txid(channel->last_tx, &txid); - memcpy(channel->last_settle_tx->wtx->inputs[0].txhash, &txid, 32); json_add_tx(response, "last_settle_tx", channel->last_settle_tx); } else { // Check if this is initial tx, if not, rebind and add sig @@ -965,8 +992,6 @@ static void json_add_channel(struct lightningd *ld, secp256k1_musig_keyagg_cache dummy_cache; struct pubkey inner_pubkey; struct eltoo_keyset keyset_copy; - struct bitcoin_txid txid; - towire_bitcoin_tx(&p, channel->last_tx); p_start = p; p_len = tal_count(p); @@ -1006,16 +1031,17 @@ static void json_add_channel(struct lightningd *ld, 2 /* n_pubkeys */); /* FIXME pass in pubkeys, not keyset ... or get pubkeys from PSBT directly */ - bind_update_tx_to_funding_outpoint(bound_update_tx, + bind_tx_to_funding_outpoint(bound_update_tx, bound_settle_tx, &channel->funding, &keyset_copy, &inner_pubkey, &sig); - /* Really direct txid surgery... libwally routine needed */ - bitcoin_txid(bound_update_tx, &txid); - memcpy(bound_settle_tx->wtx->inputs[0].txhash, &txid, 32); + bind_settle_tx(bound_update_tx, + 0 /* output_index: we can't know for sure until update tx confirms, this is + for ease of use */, + bound_settle_tx); json_add_tx(response, "last_update_tx", bound_update_tx); diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 77037e17d74a..97000d0d682a 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -86,6 +86,8 @@ u8 *p2wpkh_for_keyidx(const tal_t *ctx, struct lightningd *ld, u64 keyidx); /* We've loaded peers from database, set them going. */ void setup_peers(struct lightningd *ld); +void eltoo_drop_to_chain(struct lightningd *ld, struct channel *channel, + bool cooperative); void drop_to_chain(struct lightningd *ld, struct channel *channel, bool cooperative); void channel_watch_funding(struct lightningd *ld, struct channel *channel); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 613ee71821da..0f3c76e64dec 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -14,14 +14,19 @@ bool deprecated_apis = false; struct channel *any_channel_by_scid(struct lightningd *ld UNNEEDED, const struct short_channel_id *scid UNNEEDED) { fprintf(stderr, "any_channel_by_scid called!\n"); abort(); } -/* Generated stub for bind_update_tx_to_funding_outpoint */ -void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, - const struct bitcoin_tx *settle_tx UNNEEDED, +/* Generated stub for bind_settle_tx */ +void bind_settle_tx(const struct bitcoin_tx *update_tx UNNEEDED, + int output_index UNNEEDED, + struct bitcoin_tx *settle_tx UNNEEDED) +{ fprintf(stderr, "bind_settle_tx called!\n"); abort(); } +/* Generated stub for bind_tx_to_funding_outpoint */ +void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, + struct bitcoin_tx *settle_tx UNNEEDED, const struct bitcoin_outpoint *funding_outpoint UNNEEDED, const struct eltoo_keyset *eltoo_keyset UNNEEDED, const struct pubkey *psbt_inner_pubkey UNNEEDED, const struct bip340sig *sig UNNEEDED) -{ fprintf(stderr, "bind_update_tx_to_funding_outpoint called!\n"); abort(); } +{ fprintf(stderr, "bind_tx_to_funding_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index abbdf5502e3d..ea8d9cbb1999 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -724,7 +724,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, "Unable to set signature internally"); */ /* For now: Re-bind, add final script/tapscript info into PSBT */ - bind_update_tx_to_funding_outpoint(*update_tx, + bind_tx_to_funding_outpoint(*update_tx, *settle_tx, &state->funding, &state->channel->eltoo_keyset, @@ -1188,14 +1188,14 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) msg = towire_funding_signed_eltoo(state, &state->channel_id, &state->channel->eltoo_keyset.self_psig, &state->channel->eltoo_keyset.self_next_nonce); /* Stick full signature into tx, ready for brodcast(minus fees) */ - bind_update_tx_to_funding_outpoint(update_tx, + /* FIXME binding should only be done last-minute */ + bind_tx_to_funding_outpoint(update_tx, settle_tx, &state->funding, &state->channel->eltoo_keyset, &state->channel->eltoo_keyset.inner_pubkey, &update_sig); - /* FIXME Report everything including both next nonces ala openingd_eltoo_funder_reply */ return towire_openingd_eltoo_fundee(state, &state->remoteconf, update_tx, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 3a1dddcdaa81..1e68077001ea 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -51,14 +51,19 @@ bool deprecated_apis = true; /* Generated stub for bigsize_put */ size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED) { fprintf(stderr, "bigsize_put called!\n"); abort(); } -/* Generated stub for bind_update_tx_to_funding_outpoint */ -void bind_update_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, - const struct bitcoin_tx *settle_tx UNNEEDED, +/* Generated stub for bind_settle_tx */ +void bind_settle_tx(const struct bitcoin_tx *update_tx UNNEEDED, + int output_index UNNEEDED, + struct bitcoin_tx *settle_tx UNNEEDED) +{ fprintf(stderr, "bind_settle_tx called!\n"); abort(); } +/* Generated stub for bind_tx_to_funding_outpoint */ +void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, + struct bitcoin_tx *settle_tx UNNEEDED, const struct bitcoin_outpoint *funding_outpoint UNNEEDED, const struct eltoo_keyset *eltoo_keyset UNNEEDED, const struct pubkey *psbt_inner_pubkey UNNEEDED, const struct bip340sig *sig UNNEEDED) -{ fprintf(stderr, "bind_update_tx_to_funding_outpoint called!\n"); abort(); } +{ fprintf(stderr, "bind_tx_to_funding_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, From bbed97da96584b3268445768a59d65e9975a7e2d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 28 Sep 2022 14:53:37 -0400 Subject: [PATCH 198/283] Implement bind_txs_to_funding_outpoint with sane interface for funding output spend scenario --- common/update_tx.c | 76 ++++++++++++++++ common/update_tx.h | 12 +++ contrib/startup_regtest.sh | 2 + lightningd/peer_control.c | 99 ++++----------------- lightningd/test/run-invoice-select-inchan.c | 18 ++-- openingd/eltoo_openingd.c | 25 +----- wallet/test/run-wallet.c | 18 ++-- 7 files changed, 128 insertions(+), 122 deletions(-) diff --git a/common/update_tx.c b/common/update_tx.c index 9c9e180f61ca..4f934141efea 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -210,6 +210,82 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } +struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx, + const struct bitcoin_outpoint *funding, + const struct bitcoin_tx *settle_tx, + const struct partial_sig *psig1, + const struct partial_sig *psig2, + const struct pubkey *funding_pubkey1, + const struct pubkey *funding_pubkey2, + const struct musig_session *session) +{ + struct bitcoin_tx **bound_update_and_settle_txs = tal_arr(tmpctx, struct bitcoin_tx *, 2); + + u8 *p = tal_arr(tmpctx, u8, 0); + const u8 *p_start; + struct bitcoin_tx *bound_update_tx, *bound_settle_tx; + size_t p_len; + const secp256k1_musig_partial_sig * psig_ptrs[2]; + const struct pubkey * pubkey_ptrs[2]; + struct bip340sig sig; + int ok; + secp256k1_musig_keyagg_cache dummy_cache; + struct pubkey inner_pubkey; + struct eltoo_keyset keyset_copy; + towire_bitcoin_tx(&p, update_tx); + p_start = p; + p_len = tal_count(p); + bound_update_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); + assert(bound_update_tx); + + /* re-set and serialize settle tx next */ + p = tal_arr(tmpctx, u8, 0); + towire_bitcoin_tx(&p, settle_tx); + p_start = p; + + p_len = tal_count(p); + bound_settle_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); + assert(bound_settle_tx); + + psig_ptrs[0] = &psig1->p_sig; + psig_ptrs[1] = &psig2->p_sig; + + keyset_copy.self_funding_key = *funding_pubkey1; + keyset_copy.other_funding_key = *funding_pubkey2; + /* FIXME: inner_pubkey should be in PSBT, don't need to make key here */ + pubkey_ptrs[0] = &keyset_copy.self_funding_key; + pubkey_ptrs[1] = &keyset_copy.other_funding_key; + + ok = bipmusig_partial_sigs_combine(psig_ptrs, + 2 /* num_signers */, + &session->session, + &sig); + assert(ok); // Trusted data!!! + + bipmusig_inner_pubkey(&inner_pubkey, + &dummy_cache, + pubkey_ptrs, + 2 /* n_pubkeys */); + + /* FIXME pass in pubkeys, not keyset ... or get pubkeys from PSBT directly */ + bind_tx_to_funding_outpoint(bound_update_tx, + bound_settle_tx, + funding, + &keyset_copy, + &inner_pubkey, + &sig); + + bind_settle_tx(bound_update_tx, + 0 /* output_index: we can't know for sure until update tx confirms, this is + for ease of use */, + bound_settle_tx); + + bound_update_and_settle_txs[0] = bound_update_tx; + bound_update_and_settle_txs[1] = bound_settle_tx; + + return bound_update_and_settle_txs; +} + struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, const struct bitcoin_tx *settle_tx, struct amount_sat funding_sats, diff --git a/common/update_tx.h b/common/update_tx.h index 6ebd79965035..24144007cb24 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -50,6 +50,18 @@ void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, const struct pubkey *psbt_inner_pubkey, const struct bip340sig *sig); +/* Wrapper for bind_tx_to_funding_outpoint and bind_settle_tx which + * clones the original transactions and returns final binded + * transactions: update then settle transactions */ +struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx, + const struct bitcoin_outpoint *funding, + const struct bitcoin_tx *settle_tx, + const struct partial_sig *psig1, + const struct partial_sig *psig2, + const struct pubkey *funding_pubkey1, + const struct pubkey *funding_pubkey2, + const struct musig_session *session); + /* Used to bind the update transaction to the non-funding outpoints * of the eltoo contract. This only occurs if invalidated update * transactions are published, e.g. faulty watchtower, or malicious diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 7fd389f030e7..b9607e9a96b0 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -163,6 +163,8 @@ onchain_ln() { sleep 5 FIRST_UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) FIRST_SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_settle_tx ) + FIRST_UNBOUND_UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].unbound_update_tx ) + FIRST_UNBOUND_SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].unbound_settle_tx ) invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice sleep 0.2 diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index d606557a2d03..5b0f842916f1 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -972,88 +972,23 @@ static void json_add_channel(struct lightningd *ld, json_add_htlcs(ld, response, channel); if (channel->last_settle_tx) { - if (channel->last_tx->wtx->locktime == 500000000) { - bind_settle_tx(channel->last_tx, - 0 /* output_index: we can't know for sure until update tx confirms... */, - channel->last_settle_tx); - json_add_tx(response, "last_update_tx", channel->last_tx); - json_add_tx(response, "last_settle_tx", channel->last_settle_tx); - } else { - // Check if this is initial tx, if not, rebind and add sig - // Note that if txid changes(adding fee input), you need to rebind again! - u8 *p = tal_arr(tmpctx, u8, 0); - const u8 *p_start; - struct bitcoin_tx *bound_update_tx, *bound_settle_tx; - size_t p_len; - const secp256k1_musig_partial_sig * psig_ptrs[2]; - const struct pubkey * pubkey_ptrs[2]; - struct bip340sig sig; - int ok; - secp256k1_musig_keyagg_cache dummy_cache; - struct pubkey inner_pubkey; - struct eltoo_keyset keyset_copy; - towire_bitcoin_tx(&p, channel->last_tx); - p_start = p; - p_len = tal_count(p); - bound_update_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); - assert(bound_update_tx); - - /* re-set and serialize settle tx next */ - p = tal_arr(tmpctx, u8, 0); - towire_bitcoin_tx(&p, channel->last_settle_tx); - p_start = p; - - p_len = tal_count(p); - bound_settle_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); - assert(bound_settle_tx); - - psig_ptrs[0] = &channel->eltoo_keyset.self_psig.p_sig; - psig_ptrs[1] = &channel->eltoo_keyset.other_psig.p_sig; - - /* FIXME channel->eltoo_keyset should be set at same time as these fields are */ - keyset_copy.self_funding_key = channel->local_funding_pubkey; - keyset_copy.other_funding_key = channel->channel_info.remote_fundingkey; - //channel->eltoo_keyset.self_funding_key = channel->channel_info.remote_fundingkey; - //channel->eltoo_keyset.other_funding_key = channel->channel_info.remote_fundingkey; - /* FIXME: inner_pubkey should be in PSBT, don't need to make key here */ - pubkey_ptrs[0] = &keyset_copy.self_funding_key; - pubkey_ptrs[1] = &keyset_copy.other_funding_key; - - ok = bipmusig_partial_sigs_combine(psig_ptrs, - 2 /* num_signers */, - &channel->eltoo_keyset.session.session, - &sig); - assert(ok); // Trusted data!!! - - bipmusig_inner_pubkey(&inner_pubkey, - &dummy_cache, - pubkey_ptrs, - 2 /* n_pubkeys */); - - /* FIXME pass in pubkeys, not keyset ... or get pubkeys from PSBT directly */ - bind_tx_to_funding_outpoint(bound_update_tx, - bound_settle_tx, - &channel->funding, - &keyset_copy, - &inner_pubkey, - &sig); - - bind_settle_tx(bound_update_tx, - 0 /* output_index: we can't know for sure until update tx confirms, this is - for ease of use */, - bound_settle_tx); - - json_add_tx(response, "last_update_tx", bound_update_tx); - - json_add_tx(response, "last_settle_tx", bound_settle_tx); - - json_add_tx(response, "unbound_update_tx", channel->last_tx); - - json_add_tx(response, "unbound_settle_tx", channel->last_settle_tx); - - - /* FIXME Deallocate copied txns? */ - } + struct bitcoin_tx **bound_update_and_settle_txs; + + /* Eltoo keyset should probably have all pubkeys... */ + bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->last_tx, + &channel->funding, + channel->last_settle_tx, + &channel->eltoo_keyset.self_psig, + &channel->eltoo_keyset.other_psig, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, + &channel->eltoo_keyset.session); + + json_add_tx(response, "last_update_tx", bound_update_and_settle_txs[0]); + json_add_tx(response, "last_settle_tx", bound_update_and_settle_txs[1]); + json_add_tx(response, "unbound_update_tx", channel->last_tx); + json_add_tx(response, "unbound_settle_tx", channel->last_settle_tx); + /* FIXME Deallocate copied txns? */ } json_object_end(response); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 0f3c76e64dec..4d86f110489c 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -19,14 +19,16 @@ void bind_settle_tx(const struct bitcoin_tx *update_tx UNNEEDED, int output_index UNNEEDED, struct bitcoin_tx *settle_tx UNNEEDED) { fprintf(stderr, "bind_settle_tx called!\n"); abort(); } -/* Generated stub for bind_tx_to_funding_outpoint */ -void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, - struct bitcoin_tx *settle_tx UNNEEDED, - const struct bitcoin_outpoint *funding_outpoint UNNEEDED, - const struct eltoo_keyset *eltoo_keyset UNNEEDED, - const struct pubkey *psbt_inner_pubkey UNNEEDED, - const struct bip340sig *sig UNNEEDED) -{ fprintf(stderr, "bind_tx_to_funding_outpoint called!\n"); abort(); } +/* Generated stub for bind_txs_to_funding_outpoint */ +struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, + const struct bitcoin_outpoint *funding UNNEEDED, + const struct bitcoin_tx *settle_tx UNNEEDED, + const struct partial_sig *psig1 UNNEEDED, + const struct partial_sig *psig2 UNNEEDED, + const struct pubkey *funding_pubkey1 UNNEEDED, + const struct pubkey *funding_pubkey2 UNNEEDED, + const struct musig_session *session UNNEEDED) +{ fprintf(stderr, "bind_txs_to_funding_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index ea8d9cbb1999..87ff768e242e 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -712,30 +712,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, "Bad combine_psig_reply_reply %s", tal_hex(tmpctx, msg)); } - /* We save their sig to our first update tx */ - - status_debug("Rebinding update transaction 0"); - /* FIXME Store as taproot signature in PSBT once updated - or should we just sneak it in same way for now? - if (!psbt_input_set_signature((*update_tx)->psbt, 0, - &state->their_funding_pubkey, - sig)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Unable to set signature internally"); - */ - /* For now: Re-bind, add final script/tapscript info into PSBT */ - bind_tx_to_funding_outpoint(*update_tx, - *settle_tx, - &state->funding, - &state->channel->eltoo_keyset, - &state->channel->eltoo_keyset.inner_pubkey, - &update_sig); - - - /* For debugging, remove later */ - status_debug("Signed update transaction 0: %s", psbt_to_b64(NULL, (*update_tx)->psbt)); - - status_debug("Settle transaction 0: %s", psbt_to_b64(NULL, (*settle_tx)->psbt)); + /* State is sent back to master later */ peer_billboard(false, "Funding channel: opening negotiation succeeded"); diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 1e68077001ea..9aabb815bac6 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -56,14 +56,16 @@ void bind_settle_tx(const struct bitcoin_tx *update_tx UNNEEDED, int output_index UNNEEDED, struct bitcoin_tx *settle_tx UNNEEDED) { fprintf(stderr, "bind_settle_tx called!\n"); abort(); } -/* Generated stub for bind_tx_to_funding_outpoint */ -void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx UNNEEDED, - struct bitcoin_tx *settle_tx UNNEEDED, - const struct bitcoin_outpoint *funding_outpoint UNNEEDED, - const struct eltoo_keyset *eltoo_keyset UNNEEDED, - const struct pubkey *psbt_inner_pubkey UNNEEDED, - const struct bip340sig *sig UNNEEDED) -{ fprintf(stderr, "bind_tx_to_funding_outpoint called!\n"); abort(); } +/* Generated stub for bind_txs_to_funding_outpoint */ +struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, + const struct bitcoin_outpoint *funding UNNEEDED, + const struct bitcoin_tx *settle_tx UNNEEDED, + const struct partial_sig *psig1 UNNEEDED, + const struct partial_sig *psig2 UNNEEDED, + const struct pubkey *funding_pubkey1 UNNEEDED, + const struct pubkey *funding_pubkey2 UNNEEDED, + const struct musig_session *session UNNEEDED) +{ fprintf(stderr, "bind_txs_to_funding_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, From 076229a35d27162e3e2cff9275bf2154aa39dcff Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 28 Sep 2022 15:10:00 -0400 Subject: [PATCH 199/283] lightning now fires off funding output bound update tx when channel fails --- contrib/startup_regtest.sh | 9 +++++---- lightningd/onchain_control.c | 4 +--- lightningd/peer_control.c | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index b9607e9a96b0..5ae113c1b90d 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -172,16 +172,17 @@ onchain_ln() { # Should be bound to funding output! UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_settle_tx ) - txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) + txid=$(bt-cli decoderawtransaction $FIRST_UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 - bt-cli sendrawtransaction $UPDATE_HEX + bt-cli sendrawtransaction $FIRST_UPDATE_HEX bt-cli generatetoaddress 1 $btcaddr - # Settle tx can be broadcast after shared_delay + # Settle tx can be broadcast after shared_delay, onchaind should + # be trying to spend the update tx output itself! bt-cli generatetoaddress 6 $btcaddr txid=$(bt-cli decoderawtransaction $SETTLE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 - bt-cli sendrawtransaction $SETTLE_HEX + bt-cli sendrawtransaction $FIRST_SETTLE_HEX bt-cli generatetoaddress 1 $btcaddr } diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 75b6fd64daf4..417dc3c7618d 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -850,10 +850,8 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, if (channel->closer != NUM_SIDES) reason = REASON_UNKNOWN; /* will use last cause as reason */ - /* FIXME need to figure out what part of this to do vs delegate to onchaind... - currently this crashes hard trying to "sign and submit" last tx + /* FIXME This submits and unfunded transaction :) Need to spend anchor */ channel_fail_permanent(channel, reason, "Funding transaction spent"); - */ /* We could come from almost any state. */ /* NOTE(mschmoock) above comment is wrong, since we failed above! */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 5b0f842916f1..8c93b2805281 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -232,8 +232,37 @@ static bool invalid_last_tx(const struct bitcoin_tx *tx) #endif } -static void eltoo_finalize_and_send_last(struct lightningd *ld) +static void eltoo_finalize_and_send_last(struct lightningd *ld, struct channel *channel) { + struct bitcoin_tx **bound_update_and_settle_txs; + struct bitcoin_txid txid; + + /* Eltoo keyset should probably have all pubkeys... */ + bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->last_tx, + &channel->funding, + channel->last_settle_tx, + &channel->eltoo_keyset.self_psig, + &channel->eltoo_keyset.other_psig, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, + &channel->eltoo_keyset.session); + + /* N.B. txid instability possible with eltoo, need to handle? */ + bitcoin_txid(bound_update_and_settle_txs[0], &txid); + + wallet_transaction_add(ld->wallet, bound_update_and_settle_txs[0]->wtx, 0, 0); + wallet_transaction_annotate(ld->wallet, &txid, + TX_CHANNEL_UNILATERAL /* FIXME What should this be anyways? */, + channel->dbid); + + /* Keep broadcasting until we say stop (can fail due to dup, + * if they beat us to the broadcast). */ + /* FIXME We need to add fees via anchor */ + broadcast_tx(ld->topology, channel, bound_update_and_settle_txs[0], NULL); + + /* FIXME maybe the roundtrip isn't needed... just rely on this subroutine */ + remove_sig(bound_update_and_settle_txs[0]); + assert(ld); } @@ -272,7 +301,7 @@ void eltoo_drop_to_chain(struct lightningd *ld, struct channel *channel, } else */ /* FIXME figure out interface */ - eltoo_finalize_and_send_last(ld); + eltoo_finalize_and_send_last(ld, channel); resolve_close_command(ld, channel, cooperative); } From df93b5676d9df533fb24f94e9b9ccf603290a44b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 28 Sep 2022 16:42:18 -0400 Subject: [PATCH 200/283] eltoo_onchaind: track funding output --- lightningd/onchain_control.c | 17 ++++++++++++----- lightningd/onchain_control.h | 3 +++ lightningd/peer_control.c | 4 ++-- lightningd/test/run-invoice-select-inchan.c | 6 +----- onchaind/onchaind_wire.csv | 4 +++- wallet/test/run-wallet.c | 6 +----- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 417dc3c7618d..b2457251d0bd 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -673,10 +673,12 @@ static void onchain_error(struct channel *channel, * onchaind (like any other owner), and restart */ enum watch_result onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, + size_t input_num, u32 blockheight) { if (channel->our_config.is_eltoo) { - return eltoo_onchaind_funding_spent(channel, tx, blockheight); + /* input_num is required due to ANYPREVOUT signature */ + return eltoo_onchaind_funding_spent(channel, tx, blockheight, input_num); } u8 *msg; @@ -838,6 +840,7 @@ enum watch_result onchaind_funding_spent(struct channel *channel, * onchaind (like any other owner), and restart */ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, + size_t input_num, u32 blockheight) { u8 *msg; @@ -885,9 +888,13 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, return KEEP_WATCHING; } - /* Hello World :) */ - msg = towire_eltoo_onchaind_init(channel, chainparams, - tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), channel->last_tx, channel->last_settle_tx); + msg = towire_eltoo_onchaind_init(channel, + chainparams, + channel->funding_sats, + tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), + input_num, + channel->last_tx, + channel->last_settle_tx); subd_send_msg(channel->owner, take(msg)); watch_tx_and_outputs(channel, tx); @@ -915,7 +922,7 @@ void onchaind_replay_channels(struct lightningd *ld) for (size_t j = 0; j < tal_count(txs); j++) { if (txs[j].type == WIRE_ONCHAIND_INIT) { - onchaind_funding_spent(chan, txs[j].tx, + onchaind_funding_spent(chan, txs[j].tx, txs[j].input_num, txs[j].blockheight); } else if (txs[j].type == WIRE_ONCHAIND_SPENT) { diff --git a/lightningd/onchain_control.h b/lightningd/onchain_control.h index 4936ad6bdd0f..08cc97646dd1 100644 --- a/lightningd/onchain_control.h +++ b/lightningd/onchain_control.h @@ -9,12 +9,15 @@ struct block; enum watch_result onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, + size_t input_num, u32 blockheight); enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, + size_t input_num, u32 blockheight); + void onchaind_replay_channels(struct lightningd *ld); #endif /* LIGHTNING_LIGHTNINGD_ONCHAIN_CONTROL_H */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 8c93b2805281..f062bcb75174 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1723,7 +1723,7 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, static enum watch_result funding_spent(struct channel *channel, const struct bitcoin_tx *tx, - size_t inputnum UNUSED, + size_t input_num, const struct block *block) { struct bitcoin_txid txid; @@ -1731,7 +1731,7 @@ static enum watch_result funding_spent(struct channel *channel, wallet_channeltxs_add(channel->peer->ld->wallet, channel, WIRE_ONCHAIND_INIT, &txid, 0, block->height); - return onchaind_funding_spent(channel, tx, block->height); + return onchaind_funding_spent(channel, tx, input_num, block->height); } void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel) diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 4d86f110489c..55a298fc4466 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -14,11 +14,6 @@ bool deprecated_apis = false; struct channel *any_channel_by_scid(struct lightningd *ld UNNEEDED, const struct short_channel_id *scid UNNEEDED) { fprintf(stderr, "any_channel_by_scid called!\n"); abort(); } -/* Generated stub for bind_settle_tx */ -void bind_settle_tx(const struct bitcoin_tx *update_tx UNNEEDED, - int output_index UNNEEDED, - struct bitcoin_tx *settle_tx UNNEEDED) -{ fprintf(stderr, "bind_settle_tx called!\n"); abort(); } /* Generated stub for bind_txs_to_funding_outpoint */ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, const struct bitcoin_outpoint *funding UNNEEDED, @@ -520,6 +515,7 @@ void notify_invoice_payment(struct lightningd *ld UNNEEDED, struct amount_msat a /* Generated stub for onchaind_funding_spent */ enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, + size_t input_num UNNEEDED, u32 blockheight UNNEEDED) { fprintf(stderr, "onchaind_funding_spent called!\n"); abort(); } /* Generated stub for param */ diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index fa0f4abbe9ec..f8270fe86299 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -140,10 +140,12 @@ msgdata,onchaind_annotate_txin,type,enum wallet_tx_type, msgtype,onchaind_notify_coin_mvt,5037 msgdata,onchaind_notify_coin_mvt,mvt,chain_coin_mvt, -# Eltoo stuff following (Hello World for now) +# Eltoo stuff following msgtype,eltoo_onchaind_init,5061 msgdata,eltoo_onchaind_init,chainparams,chainparams, +msgdata,eltoo_onchaind_init,funding_amount_satoshi,amount_sat, msgdata,eltoo_onchaind_init,tx_parts,tx_parts, +msgdata,eltoo_onchaind_init,input_num,u32, msgdata,eltoo_onchaind_init,update_tx,bitcoin_tx, msgdata,eltoo_onchaind_init,settle_tx,bitcoin_tx, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 9aabb815bac6..ba814685674b 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -51,11 +51,6 @@ bool deprecated_apis = true; /* Generated stub for bigsize_put */ size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED) { fprintf(stderr, "bigsize_put called!\n"); abort(); } -/* Generated stub for bind_settle_tx */ -void bind_settle_tx(const struct bitcoin_tx *update_tx UNNEEDED, - int output_index UNNEEDED, - struct bitcoin_tx *settle_tx UNNEEDED) -{ fprintf(stderr, "bind_settle_tx called!\n"); abort(); } /* Generated stub for bind_txs_to_funding_outpoint */ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, const struct bitcoin_outpoint *funding UNNEEDED, @@ -558,6 +553,7 @@ void notify_forward_event(struct lightningd *ld UNNEEDED, /* Generated stub for onchaind_funding_spent */ enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, + size_t input_num UNNEEDED, u32 blockheight UNNEEDED) { fprintf(stderr, "onchaind_funding_spent called!\n"); abort(); } /* Generated stub for onion_decode */ From 90063a1ea84e2164315cd32125f5db198d7b9841 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 28 Sep 2022 16:58:02 -0400 Subject: [PATCH 201/283] oops, add eltoo onchaind --- lightningd/onchain_control.c | 4 +- onchaind/eltoo_onchaind.c | 201 +++++++++++++++++++++++++++++++++++ onchaind/onchaind_wire.csv | 2 + 3 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 onchaind/eltoo_onchaind.c diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index b2457251d0bd..0b11ba27fc01 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -894,7 +894,9 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), input_num, channel->last_tx, - channel->last_settle_tx); + channel->last_settle_tx, + blockheight, + channel->our_msat); subd_send_msg(channel->owner, take(msg)); watch_tx_and_outputs(channel, tx); diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c new file mode 100644 index 000000000000..958d265feffa --- /dev/null +++ b/onchaind/eltoo_onchaind.c @@ -0,0 +1,201 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "onchain_types_names_gen.h" + +/* stdin == requests */ +#define REQ_FD STDIN_FILENO +#define HSM_FD 3 + +/* Our recorded channel balance at 'chain time' */ +static struct amount_msat our_msat; + +/* FIXME looks like a lot of copy/paste, revisit */ +struct tracked_output { + enum tx_type tx_type; + struct bitcoin_outpoint outpoint; + u32 tx_blockheight; + /* FIXME: Convert all depths to blocknums, then just get new blk msgs */ + u32 depth; + struct amount_sat sat; + enum output_type output_type; + + /* If it is an HTLC, this is set, wscript is non-NULL. */ + struct htlc_stub htlc; + const u8 *wscript; + + /* If it's an HTLC off our unilateral, this is their sig for htlc_tx */ + const struct bitcoin_signature *remote_htlc_sig; + + /* Our proposed solution (if any) */ + struct proposed_resolution *proposal; + + /* If it is resolved. */ + struct resolution *resolved; + + /* stashed so we can pass it along to the coin ledger */ + struct sha256 payment_hash; +}; + +static const char *tx_type_name(enum tx_type tx_type) +{ + size_t i; + + for (i = 0; enum_tx_type_names[i].name; i++) + if (enum_tx_type_names[i].v == tx_type) + return enum_tx_type_names[i].name; + return "unknown"; +} + +static const char *output_type_name(enum output_type output_type) +{ + size_t i; + + for (i = 0; enum_output_type_names[i].name; i++) + if (enum_output_type_names[i].v == output_type) + return enum_output_type_names[i].name; + return "unknown"; +} + +static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) +{ + wire_sync_write(REQ_FD, + take(towire_onchaind_notify_coin_mvt(NULL, mvt))); + + if (taken(mvt)) + tal_free(mvt); +} + +static struct tracked_output * +new_tracked_output(struct tracked_output ***outs, + const struct bitcoin_outpoint *outpoint, + u32 tx_blockheight, + enum tx_type tx_type, + struct amount_sat sat, + enum output_type output_type, + const struct htlc_stub *htlc, + const u8 *wscript, + const struct bitcoin_signature *remote_htlc_sig TAKES) +{ + struct tracked_output *out = tal(*outs, struct tracked_output); + + status_debug("Tracking output %s: %s/%s", + type_to_string(tmpctx, struct bitcoin_outpoint, outpoint), + tx_type_name(tx_type), + output_type_name(output_type)); + + out->tx_type = tx_type; + out->outpoint = *outpoint; + out->tx_blockheight = tx_blockheight; + out->depth = 0; + out->sat = sat; + out->output_type = output_type; + out->proposal = NULL; + out->resolved = NULL; + if (htlc) + out->htlc = *htlc; + out->wscript = tal_steal(out, wscript); + out->remote_htlc_sig = tal_dup_or_null(out, struct bitcoin_signature, + remote_htlc_sig); + + tal_arr_expand(outs, out); + + return out; +} + +int main(int argc, char *argv[]) +{ + setup_locale(); + + const tal_t *ctx = tal(NULL, char); + u8 *msg; + struct tx_parts *spending_tx; + struct bitcoin_tx *unbound_update_tx, *unbound_settle_tx; + struct tracked_output **outs; + struct bitcoin_outpoint funding; + u32 input_num; + struct amount_sat funding_sats; + u32 tx_blockheight; + + subdaemon_setup(argc, argv); + + status_setup_sync(REQ_FD); + + msg = wire_sync_read(tmpctx, REQ_FD); + if (!fromwire_eltoo_onchaind_init(tmpctx, + msg, + &chainparams, + &funding_sats, + &spending_tx, + &input_num, + &unbound_update_tx, + &unbound_settle_tx, + &tx_blockheight, + &our_msat)) { + master_badmsg(WIRE_ELTOO_ONCHAIND_INIT, msg); + } + + status_debug("lightningd_eltoo_onchaind is alive!"); + /* We need to keep tx around, but there's only one: not really a leak */ + tal_steal(ctx, notleak(spending_tx)); + tal_steal(ctx, notleak(unbound_update_tx)); + tal_steal(ctx, notleak(unbound_settle_tx)); + + status_debug("Unbound update and settle transactions to potentially broadcast: %s, %s", + type_to_string(tmpctx, struct bitcoin_tx, unbound_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, unbound_settle_tx)); + + /* These are the utxos we are interested in */ + outs = tal_arr(ctx, struct tracked_output *, 0); + + assert(tal_count(spending_tx->inputs) > input_num); + wally_tx_input_get_txid(spending_tx->inputs[0], &funding.txid); + funding.n = spending_tx->inputs[input_num]->index; + + /* Tracking funding output which is spent already */ + new_tracked_output(&outs, &funding, + 0, /* We don't care about funding blockheight */ + FUNDING_TRANSACTION, + funding_sats, + FUNDING_OUTPUT, NULL, NULL, NULL); + + /* Record funding output spent */ + send_coin_mvt(take(new_coin_channel_close(NULL, &spending_tx->txid, + &funding, tx_blockheight, + our_msat, + funding_sats, + tal_count(spending_tx->outputs)))); + + + /* FIXME Now that we see the transaction in block, and our latest versions, + re-bind our transactions and submit them to the mempool */ + + /* FIXME More stuff to come, sit and wait for a response that shouldn't come */ + msg = wire_sync_read(tmpctx, REQ_FD); + + /* We're done! */ + tal_free(ctx); + daemon_shutdown(); + + return 0; +} diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index f8270fe86299..577020809ed7 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -148,6 +148,8 @@ msgdata,eltoo_onchaind_init,tx_parts,tx_parts, msgdata,eltoo_onchaind_init,input_num,u32, msgdata,eltoo_onchaind_init,update_tx,bitcoin_tx, msgdata,eltoo_onchaind_init,settle_tx,bitcoin_tx, +msgdata,eltoo_onchaind_init,tx_blockheight,u32, +msgdata,eltoo_onchaind_init,our_msat,amount_msat, # This says we're ready; give us htlcs and preimages. msgtype,eltoo_onchaind_init_reply,5161 From 25becf23b85d621684b9111c2d1c0cb68554cc3a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 29 Sep 2022 17:05:42 -0400 Subject: [PATCH 202/283] Compiling with some close handling --- lightningd/onchain_control.c | 26 +- onchaind/eltoo_onchaind.c | 1565 ++++++++++++++++++++++++++++++++-- onchaind/onchaind_wire.csv | 10 +- 3 files changed, 1525 insertions(+), 76 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 0b11ba27fc01..645b4ab4217e 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -137,8 +137,10 @@ static void handle_onchain_init_reply(struct channel *channel, const u8 *msg) static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *msg) { + struct htlc_stub *stubs; + u64 commit_num = channel->last_tx->wtx->locktime; /* update_num */ - /* FIXME any information required in reply? */ + /* Signaling ready, send more data */ if (!fromwire_eltoo_onchaind_init_reply(msg)) { channel_internal_error(channel, "Invalid eltoo_onchaind_init_reply %s", tal_hex(tmpctx, msg)); @@ -152,7 +154,12 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m REASON_UNKNOWN, "Onchain init reply"); - /* Send eltoo_onchaind any other mesages required */ + /* Tell it about any relevant HTLCs + * FIXME (only one set for eltoo... we shouldn't be storing everything) */ + stubs = wallet_htlc_stubs(tmpctx, channel->peer->ld->wallet, channel, + commit_num); + msg = towire_eltoo_onchaind_htlcs(channel, stubs); + subd_send_msg(channel->owner, take(msg)); /* Tell it about any preimages we know. */ onchaind_tell_fulfill(channel); @@ -600,6 +607,7 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U case WIRE_ONCHAIND_KNOWN_PREIMAGE: case WIRE_ONCHAIND_DEV_MEMLEAK: case WIRE_ONCHAIND_DEV_MEMLEAK_REPLY: + case WIRE_ELTOO_ONCHAIND_HTLCS: break; /* These are illegal */ case WIRE_ELTOO_ONCHAIND_INIT: @@ -640,6 +648,7 @@ static unsigned int eltoo_onchain_msg(struct subd *sd, const u8 *msg, const int case WIRE_ONCHAIND_DEV_MEMLEAK: case WIRE_ONCHAIND_DEV_MEMLEAK_REPLY: case WIRE_ELTOO_ONCHAIND_INIT: + case WIRE_ELTOO_ONCHAIND_HTLCS: break; /* These are illegal */ case WIRE_ONCHAIND_INIT_REPLY: @@ -888,15 +897,26 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, return KEEP_WATCHING; } + channel_set_state(channel, + FUNDING_SPEND_SEEN, + ONCHAIN, + REASON_UNKNOWN, + "Onchain init reply"); + + /* Add HTLCs to init, since we know which HTLCs will be exposed */ msg = towire_eltoo_onchaind_init(channel, chainparams, channel->funding_sats, tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), + tx->wtx->locktime, input_num, channel->last_tx, channel->last_settle_tx, blockheight, - channel->our_msat); + channel->our_msat, + channel->shutdown_scriptpubkey[LOCAL], + channel->shutdown_scriptpubkey[REMOTE] +); subd_send_msg(channel->owner, take(msg)); watch_tx_and_outputs(channel, tx); diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 958d265feffa..3c5fe5adffcb 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -27,100 +27,1511 @@ #define REQ_FD STDIN_FILENO #define HSM_FD 3 +/* FIXME Everything copy/pasted bc static */ + +/* Required in various places: keys for commitment transaction. */ +static const struct keyset *keyset; + +/* IFF it's their commitment tx: HSM can't derive their per-commitment point! */ +static const struct pubkey *remote_per_commitment_point; + +/* The dust limit to use when we generate transactions. */ +static struct amount_sat dust_limit; + +/* The CSV delays for each side. */ +static u32 to_self_delay[NUM_SIDES]; + +/* Where we send money to (our wallet) */ +static u32 our_wallet_index; +static struct ext_key our_wallet_ext_key; +static struct pubkey our_wallet_pubkey; + +/* Their revocation secret (only if they cheated). */ +static const struct secret *remote_per_commitment_secret; + +/* When to tell master about HTLCs which are missing/timed out */ +static u32 reasonable_depth; + +/* The messages to send at that depth. */ +static u8 **missing_htlc_msgs; + +/* The messages which were sent to us before init_reply was processed. */ +static u8 **queued_msgs; + /* Our recorded channel balance at 'chain time' */ static struct amount_msat our_msat; -/* FIXME looks like a lot of copy/paste, revisit */ +/* The minimum relay feerate acceptable to the fullnode. */ +static u32 min_relay_feerate; + +/* If we broadcast a tx, or need a delay to resolve the output. */ +struct proposed_resolution { + /* This can be NULL if our proposal is to simply ignore it after depth */ + const struct bitcoin_tx *tx; + /* Non-zero if this is CSV-delayed. */ + u32 depth_required; + enum tx_type tx_type; +}; + +/* How it actually got resolved. */ +struct resolution { + struct bitcoin_txid txid; + unsigned int depth; + enum tx_type tx_type; +}; + struct tracked_output { - enum tx_type tx_type; - struct bitcoin_outpoint outpoint; - u32 tx_blockheight; - /* FIXME: Convert all depths to blocknums, then just get new blk msgs */ - u32 depth; - struct amount_sat sat; - enum output_type output_type; + enum tx_type tx_type; + struct bitcoin_outpoint outpoint; + u32 tx_blockheight; + /* FIXME: Convert all depths to blocknums, then just get new blk msgs */ + u32 depth; + struct amount_sat sat; + enum output_type output_type; - /* If it is an HTLC, this is set, wscript is non-NULL. */ - struct htlc_stub htlc; - const u8 *wscript; + /* If it is an HTLC, this is set, wscript is non-NULL. */ + struct htlc_stub htlc; + const u8 *wscript; - /* If it's an HTLC off our unilateral, this is their sig for htlc_tx */ - const struct bitcoin_signature *remote_htlc_sig; + /* If it's an HTLC off our unilateral, this is their sig for htlc_tx */ + const struct bitcoin_signature *remote_htlc_sig; - /* Our proposed solution (if any) */ - struct proposed_resolution *proposal; + /* Our proposed solution (if any) */ + struct proposed_resolution *proposal; - /* If it is resolved. */ - struct resolution *resolved; + /* If it is resolved. */ + struct resolution *resolved; - /* stashed so we can pass it along to the coin ledger */ - struct sha256 payment_hash; + /* stashed so we can pass it along to the coin ledger */ + struct sha256 payment_hash; }; static const char *tx_type_name(enum tx_type tx_type) { - size_t i; + size_t i; - for (i = 0; enum_tx_type_names[i].name; i++) - if (enum_tx_type_names[i].v == tx_type) - return enum_tx_type_names[i].name; - return "unknown"; + for (i = 0; enum_tx_type_names[i].name; i++) + if (enum_tx_type_names[i].v == tx_type) + return enum_tx_type_names[i].name; + return "unknown"; } static const char *output_type_name(enum output_type output_type) { - size_t i; + size_t i; - for (i = 0; enum_output_type_names[i].name; i++) - if (enum_output_type_names[i].v == output_type) - return enum_output_type_names[i].name; - return "unknown"; + for (i = 0; enum_output_type_names[i].name; i++) + if (enum_output_type_names[i].v == output_type) + return enum_output_type_names[i].name; + return "unknown"; +} + +/* helper to compare output script with our tal'd script */ +static bool wally_tx_output_scripteq(const struct wally_tx_output *out, + const u8 *script) +{ + return memeq(out->script, out->script_len, script, tal_bytelen(script)); } static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) { - wire_sync_write(REQ_FD, - take(towire_onchaind_notify_coin_mvt(NULL, mvt))); + wire_sync_write(REQ_FD, + take(towire_onchaind_notify_coin_mvt(NULL, mvt))); + + if (taken(mvt)) + tal_free(mvt); +} + +static void record_channel_withdrawal(const struct bitcoin_txid *tx_txid, + struct tracked_output *out, + u32 blockheight, + enum mvt_tag tag) +{ + send_coin_mvt(take(new_onchaind_withdraw(NULL, &out->outpoint, tx_txid, + blockheight, out->sat, tag))); +} + +static void record_external_spend(const struct bitcoin_txid *txid, + struct tracked_output *out, + u32 blockheight, + enum mvt_tag tag) +{ + send_coin_mvt(take(new_coin_external_spend(NULL, &out->outpoint, + txid, blockheight, + out->sat, tag))); +} + +static void record_external_output(const struct bitcoin_outpoint *out, + struct amount_sat amount, + u32 blockheight, + enum mvt_tag tag) +{ + send_coin_mvt(take(new_coin_external_deposit(NULL, out, blockheight, + amount, tag))); +} + +static void record_external_deposit(const struct tracked_output *out, + u32 blockheight, + enum mvt_tag tag) +{ + record_external_output(&out->outpoint, out->sat, blockheight, tag); +} + +static void record_mutual_close(const struct tx_parts *tx, + const u8 *remote_scriptpubkey, + u32 blockheight) +{ + /* FIXME: if we ever change how closes happen, this will + * need to be updated as there's no longer 1 output + * per peer */ + for (size_t i = 0; i < tal_count(tx->outputs); i++) { + struct bitcoin_outpoint out; + + if (!wally_tx_output_scripteq(tx->outputs[i], + remote_scriptpubkey)) + continue; + + out.n = i; + out.txid = tx->txid; + record_external_output(&out, + amount_sat(tx->outputs[i]->satoshi), + blockheight, + TO_THEM); + break; + } +} + + +static void record_channel_deposit(struct tracked_output *out, + u32 blockheight, enum mvt_tag tag) +{ + send_coin_mvt(take(new_onchaind_deposit(NULL, + &out->outpoint, + blockheight, out->sat, + tag))); +} + +static void record_to_us_htlc_fulfilled(struct tracked_output *out, + u32 blockheight) +{ + send_coin_mvt(take(new_onchain_htlc_deposit(NULL, + &out->outpoint, + blockheight, + out->sat, + &out->payment_hash))); +} + +static void record_to_them_htlc_fulfilled(struct tracked_output *out, + u32 blockheight) +{ + + send_coin_mvt(take(new_onchain_htlc_withdraw(NULL, + &out->outpoint, + blockheight, + out->sat, + &out->payment_hash))); +} + +static void record_ignored_wallet_deposit(struct tracked_output *out) +{ + struct bitcoin_outpoint outpoint; + + /* Every spend tx we construct has a single output. */ + bitcoin_txid(out->proposal->tx, &outpoint.txid); + outpoint.n = 0; + + enum mvt_tag tag = TO_WALLET; + if (out->tx_type == OUR_HTLC_TIMEOUT_TX + || out->tx_type == OUR_HTLC_SUCCESS_TX) + tag = HTLC_TX; + else if (out->tx_type == THEIR_REVOKED_UNILATERAL) + tag = PENALTY; + else if (out->tx_type == OUR_UNILATERAL + || out->tx_type == THEIR_UNILATERAL) { + if (out->output_type == OUR_HTLC) + tag = HTLC_TIMEOUT; + } + if (out->output_type == DELAYED_OUTPUT_TO_US) + tag = CHANNEL_TO_US; + + /* Record the in/out through the channel */ + record_channel_deposit(out, out->tx_blockheight, tag); + record_channel_withdrawal(&outpoint.txid, out, 0, IGNORED); +} + +static void record_coin_movements(struct tracked_output *out, + u32 blockheight, + const struct bitcoin_tx *tx, + const struct bitcoin_txid *txid) +{ + /* For 'timeout' htlcs, we re-record them as a deposit + * before we withdraw them again. When the channel closed, + * we reported this as withdrawn (since we didn't know the + * total amount of pending htlcs that are to-them). So + * we have to "deposit" it again before we withdraw it. + * This is just to make the channel account close out nicely + * AND so we can accurately calculate our on-chain fee burden */ + if (out->tx_type == OUR_HTLC_TIMEOUT_TX + || out->tx_type == OUR_HTLC_SUCCESS_TX) + record_channel_deposit(out, blockheight, HTLC_TX); + + if (out->resolved->tx_type == OUR_HTLC_TIMEOUT_TO_US) + record_channel_deposit(out, blockheight, HTLC_TIMEOUT); + + /* there is a case where we've fulfilled an htlc onchain, + * in which case we log a deposit to the channel */ + if (out->resolved->tx_type == THEIR_HTLC_FULFILL_TO_US + || out->resolved->tx_type == OUR_HTLC_SUCCESS_TX) + record_to_us_htlc_fulfilled(out, blockheight); + + /* If it's our to-us and our close, we publish *another* tx + * which spends the output when the timeout ends */ + if (out->tx_type == OUR_UNILATERAL) { + if (out->output_type == DELAYED_OUTPUT_TO_US) + record_channel_deposit(out, blockheight, CHANNEL_TO_US); + else if (out->output_type == OUR_HTLC) { + record_channel_deposit(out, blockheight, HTLC_TIMEOUT); + record_channel_withdrawal(txid, out, blockheight, HTLC_TIMEOUT); + } else if (out->output_type == THEIR_HTLC) + record_channel_withdrawal(txid, out, blockheight, HTLC_FULFILL); + } + + if (out->tx_type == THEIR_REVOKED_UNILATERAL + || out->resolved->tx_type == OUR_PENALTY_TX) + record_channel_deposit(out, blockheight, PENALTY); + + if (out->resolved->tx_type == OUR_DELAYED_RETURN_TO_WALLET + || out->resolved->tx_type == THEIR_HTLC_FULFILL_TO_US + || out->output_type == DELAYED_OUTPUT_TO_US + || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TO_US + || out->resolved->tx_type == OUR_PENALTY_TX) { + /* penalty rbf cases, the amount might be zero */ + if (amount_sat_zero(out->sat)) + record_channel_withdrawal(txid, out, blockheight, TO_MINER); + else + record_channel_withdrawal(txid, out, blockheight, TO_WALLET); + } +} + +static u8 *penalty_to_us(const tal_t *ctx, + struct bitcoin_tx *tx, + const u8 *wscript) +{ + return towire_hsmd_sign_penalty_to_us(ctx, remote_per_commitment_secret, + tx, wscript); +} + +/** replace_penalty_tx_to_us + * + * @brief creates a replacement TX for + * a given penalty tx. + * + * @param ctx - the context to allocate + * off of. + * @param hsm_sign_msg - function to construct + * the signing message to HSM. + * @param penalty_tx - the original + * penalty transaction. + * @param output_amount - the output + * amount to use instead of the + * original penalty transaction. + * If this amount is below the dust + * limit, the output is replaced with + * an `OP_RETURN` instead. + * + * @return the signed transaction. + */ +static struct bitcoin_tx * +replace_penalty_tx_to_us(const tal_t *ctx, + u8 *(*hsm_sign_msg)(const tal_t *ctx, + struct bitcoin_tx *tx, + const u8 *wscript), + const struct bitcoin_tx *penalty_tx, + struct amount_sat *output_amount) +{ + struct bitcoin_tx *tx; + + /* The penalty tx input. */ + const struct wally_tx_input *input; + /* Specs of the penalty tx input. */ + struct bitcoin_outpoint input_outpoint; + u8 *input_wscript; + u8 *input_element; + struct amount_sat input_amount; + + /* Signature from the HSM. */ + u8 *msg; + struct bitcoin_signature sig; + /* Witness we generate from the signature and other data. */ + u8 **witness; + + + /* Get the single input of the penalty tx. */ + input = &penalty_tx->wtx->inputs[0]; + /* Extract the input-side data. */ + bitcoin_tx_input_get_txid(penalty_tx, 0, &input_outpoint.txid); + input_outpoint.n = input->index; + input_wscript = tal_dup_arr(tmpctx, u8, + input->witness->items[2].witness, + input->witness->items[2].witness_len, + 0); + input_element = tal_dup_arr(tmpctx, u8, + input->witness->items[1].witness, + input->witness->items[1].witness_len, + 0); + input_amount = psbt_input_get_amount(penalty_tx->psbt, 0); + + /* Create the replacement. */ + tx = bitcoin_tx(ctx, chainparams, 1, 1, /*locktime*/ 0); + /* Reconstruct the input. */ + bitcoin_tx_add_input(tx, &input_outpoint, + BITCOIN_TX_RBF_SEQUENCE, + NULL, input_amount, NULL, input_wscript, NULL, NULL); + /* Reconstruct the output with a smaller amount. */ + if (amount_sat_greater(*output_amount, dust_limit)) { + bitcoin_tx_add_output(tx, + scriptpubkey_p2wpkh(tx, + &our_wallet_pubkey), + NULL, + *output_amount); + psbt_add_keypath_to_last_output(tx, our_wallet_index, &our_wallet_ext_key); + } else { + bitcoin_tx_add_output(tx, + scriptpubkey_opreturn_padded(tx), + NULL, + AMOUNT_SAT(0)); + *output_amount = AMOUNT_SAT(0); + } + + /* Finalize the transaction. */ + bitcoin_tx_finalize(tx); + + /* Ask HSM to sign it. */ + if (!wire_sync_write(HSM_FD, take(hsm_sign_msg(NULL, tx, + input_wscript)))) + status_failed(STATUS_FAIL_HSM_IO, "While feebumping penalty: writing sign request to hsm"); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!msg || !fromwire_hsmd_sign_tx_reply(msg, &sig)) + status_failed(STATUS_FAIL_HSM_IO, "While feebumping penalty: reading sign_tx_reply: %s", tal_hex(tmpctx, msg)); + + /* Install the witness with the signature. */ + witness = bitcoin_witness_sig_and_element(tx, &sig, + input_element, + tal_bytelen(input_element), + input_wscript); + bitcoin_tx_input_set_witness(tx, 0, take(witness)); + + return tx; +} + +/** min_rbf_bump + * + * @brief computes the minimum RBF bump required by + * BIP125, given an index. + * + * @desc BIP125 requires that an replacement transaction + * pay, not just the fee of the evicted transactions, + * but also the minimum relay fee for itself. + * This function assumes that previous RBF attempts + * paid exactly the return value for that attempt, on + * top of the initial transaction fee. + * It can serve as a baseline for other functions that + * compute a suggested fee: get whichever is higher, + * the fee this function suggests, or your own unique + * function. + * + * This function is provided as a common function that + * all RBF-bump computations can use. + * + * @param weight - the weight of the transaction you + * are RBFing. + * @param index - 0 makes no sense, 1 means this is + * the first RBF attempt, 2 means this is the 2nd + * RBF attempt, etc. + * + * @return the suggested total fee. + */ +static struct amount_sat min_rbf_bump(size_t weight, + size_t index) +{ + struct amount_sat min_relay_fee; + struct amount_sat min_rbf_bump; + + /* Compute the minimum relay fee for a transaction of the given + * weight. */ + min_relay_fee = amount_tx_fee(min_relay_feerate, weight); + + /* For every RBF attempt, we add the min-relay-fee. + * Or in other words, we multiply the min-relay-fee by the + * index number of the attempt. + */ + if (mul_overflows_u64(index, min_relay_fee.satoshis)) /* Raw: multiplication. */ + min_rbf_bump = AMOUNT_SAT(UINT64_MAX); + else + min_rbf_bump.satoshis = index * min_relay_fee.satoshis; /* Raw: multiplication. */ - if (taken(mvt)) - tal_free(mvt); + return min_rbf_bump; } +/** compute_penalty_output_amount + * + * @brief computes the appropriate output amount for a + * penalty transaction that spends a theft transaction + * that is already of a specific depth. + * + * @param initial_amount - the outout amount of the first + * penalty transaction. + * @param depth - the current depth of the theft + * transaction. + * @param max_depth - the maximum depth of the theft + * transaction, after which the theft transaction will + * succeed. + * @param weight - the weight of the first penalty + * transaction, in Sipa. + */ +static struct amount_sat +compute_penalty_output_amount(struct amount_sat initial_amount, + u32 depth, u32 max_depth, + size_t weight) +{ + struct amount_sat max_output_amount; + struct amount_sat output_amount; + struct amount_sat deducted_amount; + + assert(depth <= max_depth); + assert(depth > 0); + + /* The difference between initial_amount, and the fee suggested + * by min_rbf_bump, is the largest allowed output amount. + * + * depth = 1 is the first attempt, thus maps to the 0th RBF + * (i.e. the initial attempt that is not RBFed itself). + * We actually start to replace at depth = 2, so we use + * depth - 1 as the index for min_rbf_bump. + */ + if (!amount_sat_sub(&max_output_amount, + initial_amount, min_rbf_bump(weight, depth - 1))) + /* If min_rbf_bump is larger than the initial_amount, + * we should just donate the whole output as fee, + * meaning we get 0 output amount. + */ + return AMOUNT_SAT(0); + + /* Map the depth / max_depth into a number between 0->1. */ + double x = (double) depth / (double) max_depth; + /* Get the cube of the above position, resulting in a graph + * where the y is close to 0 up to less than halfway through, + * then quickly rises up to 1 as depth nears the max depth. + */ + double y = x * x * x; + /* Scale according to the initial_amount. */ + deducted_amount.satoshis = (u64) (y * initial_amount.satoshis); /* Raw: multiplication. */ + + /* output_amount = initial_amount - deducted_amount. */ + if (!amount_sat_sub(&output_amount, + initial_amount, deducted_amount)) + /* If underflow, force to 0. */ + output_amount = AMOUNT_SAT(0); + + /* If output exceeds max, return max. */ + if (amount_sat_less(max_output_amount, output_amount)) + return max_output_amount; + + return output_amount; +} + + static struct tracked_output * new_tracked_output(struct tracked_output ***outs, - const struct bitcoin_outpoint *outpoint, - u32 tx_blockheight, - enum tx_type tx_type, - struct amount_sat sat, - enum output_type output_type, - const struct htlc_stub *htlc, - const u8 *wscript, - const struct bitcoin_signature *remote_htlc_sig TAKES) -{ - struct tracked_output *out = tal(*outs, struct tracked_output); - - status_debug("Tracking output %s: %s/%s", - type_to_string(tmpctx, struct bitcoin_outpoint, outpoint), - tx_type_name(tx_type), - output_type_name(output_type)); - - out->tx_type = tx_type; - out->outpoint = *outpoint; - out->tx_blockheight = tx_blockheight; - out->depth = 0; - out->sat = sat; - out->output_type = output_type; - out->proposal = NULL; - out->resolved = NULL; - if (htlc) - out->htlc = *htlc; - out->wscript = tal_steal(out, wscript); - out->remote_htlc_sig = tal_dup_or_null(out, struct bitcoin_signature, - remote_htlc_sig); - - tal_arr_expand(outs, out); - - return out; + const struct bitcoin_outpoint *outpoint, + u32 tx_blockheight, + enum tx_type tx_type, + struct amount_sat sat, + enum output_type output_type, + const struct htlc_stub *htlc, + const u8 *wscript, + const struct bitcoin_signature *remote_htlc_sig TAKES) +{ + struct tracked_output *out = tal(*outs, struct tracked_output); + + status_debug("Tracking output %s: %s/%s", + type_to_string(tmpctx, struct bitcoin_outpoint, outpoint), + tx_type_name(tx_type), + output_type_name(output_type)); + + out->tx_type = tx_type; + out->outpoint = *outpoint; + out->tx_blockheight = tx_blockheight; + out->depth = 0; + out->sat = sat; + out->output_type = output_type; + out->proposal = NULL; + out->resolved = NULL; + if (htlc) + out->htlc = *htlc; + out->wscript = tal_steal(out, wscript); + out->remote_htlc_sig = tal_dup_or_null(out, struct bitcoin_signature, + remote_htlc_sig); + + tal_arr_expand(outs, out); + + return out; +} + +static void ignore_output(struct tracked_output *out) +{ + status_debug("Ignoring output %s: %s/%s", + type_to_string(tmpctx, struct bitcoin_outpoint, + &out->outpoint), + tx_type_name(out->tx_type), + output_type_name(out->output_type)); + + out->resolved = tal(out, struct resolution); + out->resolved->txid = out->outpoint.txid; + out->resolved->depth = 0; + out->resolved->tx_type = SELF; +} + +static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum tx_type t) +{ + switch (t) { + case FUNDING_TRANSACTION: + return TX_CHANNEL_FUNDING; + case MUTUAL_CLOSE: + return TX_CHANNEL_CLOSE; + case OUR_UNILATERAL: + return TX_CHANNEL_UNILATERAL; + case THEIR_HTLC_FULFILL_TO_US: + case OUR_HTLC_SUCCESS_TX: + return TX_CHANNEL_HTLC_SUCCESS; + case OUR_HTLC_TIMEOUT_TO_US: + case OUR_HTLC_TIMEOUT_TX: + return TX_CHANNEL_HTLC_TIMEOUT; + case OUR_DELAYED_RETURN_TO_WALLET: + case SELF: + return TX_CHANNEL_SWEEP; + case OUR_PENALTY_TX: + return TX_CHANNEL_PENALTY; + case THEIR_DELAYED_CHEAT: + return TX_CHANNEL_CHEAT | TX_THEIRS; + case THEIR_UNILATERAL: + case UNKNOWN_UNILATERAL: + case THEIR_REVOKED_UNILATERAL: + return TX_CHANNEL_UNILATERAL | TX_THEIRS; + case THEIR_HTLC_TIMEOUT_TO_THEM: + return TX_CHANNEL_HTLC_TIMEOUT | TX_THEIRS; + case OUR_HTLC_FULFILL_TO_THEM: + return TX_CHANNEL_HTLC_SUCCESS | TX_THEIRS; + case IGNORING_TINY_PAYMENT: + case UNKNOWN_TXTYPE: + return TX_UNKNOWN; + } + abort(); +} + +/** proposal_is_rbfable + * + * @brief returns true if the given proposal + * would be RBFed if the output it is tracking + * increases in depth without being spent. + */ +static bool proposal_is_rbfable(const struct proposed_resolution *proposal) +{ + /* Future onchain resolutions, such as anchored commitments, might + * want to RBF as well. + */ + return proposal->tx_type == OUR_PENALTY_TX; +} + +/** proposal_should_rbf + * + * @brief the given output just increased its depth, + * so the proposal for it should be RBFed and + * rebroadcast. + * + * @desc precondition: the given output must have an + * rbfable proposal as per `proposal_is_rbfable`. + */ +static void proposal_should_rbf(struct tracked_output *out) +{ + struct bitcoin_tx *tx = NULL; + u32 depth; + + assert(out->proposal); + assert(proposal_is_rbfable(out->proposal)); + + depth = out->depth; + + /* Do not RBF at depth 1. + * + * Since we react to *onchain* events, whatever proposal we made, + * the output for that proposal is already at depth 1. + * + * Since our initial proposal was broadcasted with the output at + * depth 1, we should not RBF until a new block arrives, which is + * at depth 2. + */ + if (depth <= 1) + return; + + if (out->proposal->tx_type == OUR_PENALTY_TX) { + u32 max_depth = to_self_delay[REMOTE]; + u32 my_depth = depth; + size_t weight = bitcoin_tx_weight(out->proposal->tx); + struct amount_sat initial_amount; + struct amount_sat new_amount; + + if (max_depth >= 1) + max_depth -= 1; + if (my_depth >= max_depth) + my_depth = max_depth; + + bitcoin_tx_output_get_amount_sat(out->proposal->tx, 0, + &initial_amount); + + /* Compute the new output amount for the RBF. */ + new_amount = compute_penalty_output_amount(initial_amount, + my_depth, max_depth, + weight); + assert(amount_sat_less_eq(new_amount, initial_amount)); + /* Recreate the penalty tx. */ + tx = replace_penalty_tx_to_us(tmpctx, + &penalty_to_us, + out->proposal->tx, &new_amount); + + /* We also update the output's value, so our accounting + * is correct. */ + out->sat = new_amount; + + status_debug("Created RBF OUR_PENALTY_TX with output %s " + "(originally %s) for depth %"PRIu32"/%"PRIu32".", + type_to_string(tmpctx, struct amount_sat, + &new_amount), + type_to_string(tmpctx, struct amount_sat, + &initial_amount), + depth, to_self_delay[LOCAL]); + } + /* Add other RBF-able proposals here. */ + + /* Broadcast the transaction. */ + if (tx) { + enum wallet_tx_type wtt; + + status_debug("Broadcasting RBF %s (%s) to resolve %s/%s " + "depth=%"PRIu32"", + tx_type_name(out->proposal->tx_type), + type_to_string(tmpctx, struct bitcoin_tx, tx), + tx_type_name(out->tx_type), + output_type_name(out->output_type), + depth); + + wtt = onchain_txtype_to_wallet_txtype(out->proposal->tx_type); + wire_sync_write(REQ_FD, + take(towire_onchaind_broadcast_tx(NULL, tx, + wtt, + true))); + } +} + +static void proposal_meets_depth(struct tracked_output *out) +{ + bool is_rbf = false; + + /* If we simply wanted to ignore it after some depth */ + if (!out->proposal->tx) { + ignore_output(out); + + if (out->proposal->tx_type == THEIR_HTLC_TIMEOUT_TO_THEM) + record_external_deposit(out, out->tx_blockheight, + HTLC_TIMEOUT); + + return; + } + + status_debug("Broadcasting %s (%s) to resolve %s/%s", + tx_type_name(out->proposal->tx_type), + type_to_string(tmpctx, struct bitcoin_tx, out->proposal->tx), + tx_type_name(out->tx_type), + output_type_name(out->output_type)); + + if (out->proposal) + /* Our own penalty transactions are going to be RBFed. */ + is_rbf = proposal_is_rbfable(out->proposal); + + wire_sync_write( + REQ_FD, + take(towire_onchaind_broadcast_tx( + NULL, out->proposal->tx, + onchain_txtype_to_wallet_txtype(out->proposal->tx_type), + is_rbf))); + + /* Don't wait for this if we're ignoring the tiny payment. */ + if (out->proposal->tx_type == IGNORING_TINY_PAYMENT) { + ignore_output(out); + record_ignored_wallet_deposit(out); + } + + /* Otherwise we will get a callback when it's in a block. */ +} + +static bool is_valid_sig(const u8 *e) +{ + struct bitcoin_signature sig; + return signature_from_der(e, tal_count(e), &sig); +} + +/* We ignore things which look like signatures. */ +static bool input_similar(const struct wally_tx_input *i1, + const struct wally_tx_input *i2) +{ + u8 *s1, *s2; + + if (!memeq(i1->txhash, WALLY_TXHASH_LEN, i2->txhash, WALLY_TXHASH_LEN)) + return false; + + if (i1->index != i2->index) + return false; + + if (!scripteq(i1->script, i2->script)) + return false; + + if (i1->sequence != i2->sequence) + return false; + + if (i1->witness->num_items != i2->witness->num_items) + return false; + + for (size_t i = 0; i < i1->witness->num_items; i++) { + /* Need to wrap these in `tal_arr`s since the primitives + * except to be able to call tal_bytelen on them */ + s1 = tal_dup_arr(tmpctx, u8, i1->witness->items[i].witness, + i1->witness->items[i].witness_len, 0); + s2 = tal_dup_arr(tmpctx, u8, i2->witness->items[i].witness, + i2->witness->items[i].witness_len, 0); + + if (scripteq(s1, s2)) + continue; + + if (is_valid_sig(s1) && is_valid_sig(s2)) + continue; + return false; + } + + return true; +} + +/* This simple case: true if this was resolved by our proposal. */ +static bool resolved_by_proposal(struct tracked_output *out, + const struct tx_parts *tx_parts) +{ + /* If there's no TX associated, it's not us. */ + if (!out->proposal->tx) + return false; + + /* Our proposal can change as feerates change. Input + * comparison (ignoring signatures) works pretty well. */ + if (tal_count(tx_parts->inputs) != out->proposal->tx->wtx->num_inputs) + return false; + + for (size_t i = 0; i < tal_count(tx_parts->inputs); i++) { + if (!input_similar(tx_parts->inputs[i], + &out->proposal->tx->wtx->inputs[i])) + return false; + } + + out->resolved = tal(out, struct resolution); + out->resolved->txid = tx_parts->txid; + status_debug("Resolved %s/%s by our proposal %s (%s)", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + tx_type_name(out->proposal->tx_type), + type_to_string(tmpctx, struct bitcoin_txid, + &out->resolved->txid)); + + out->resolved->depth = 0; + out->resolved->tx_type = out->proposal->tx_type; + return true; +} + +/* Otherwise, we figure out what happened and then call this. */ +static void resolved_by_other(struct tracked_output *out, + const struct bitcoin_txid *txid, + enum tx_type tx_type) +{ + out->resolved = tal(out, struct resolution); + out->resolved->txid = *txid; + out->resolved->depth = 0; + out->resolved->tx_type = tx_type; + + status_debug("Resolved %s/%s by %s (%s)", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + tx_type_name(tx_type), + type_to_string(tmpctx, struct bitcoin_txid, txid)); +} + +static void unknown_spend(struct tracked_output *out, + const struct tx_parts *tx_parts) +{ + out->resolved = tal(out, struct resolution); + out->resolved->txid = tx_parts->txid; + out->resolved->depth = 0; + out->resolved->tx_type = UNKNOWN_TXTYPE; + + status_broken("Unknown spend of %s/%s by %s", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + type_to_string(tmpctx, struct bitcoin_txid, + &tx_parts->txid)); +} + +static bool is_mutual_close(u32 locktime) +{ + /* If we mask update number, this needs to change */ + return locktime == 500000000; +} + +/* BOLT #5: + * + * Outputs that are *resolved* are considered *irrevocably resolved* + * once the remote's *resolving* transaction is included in a block at least 100 + * deep, on the most-work blockchain. + */ +static size_t num_not_irrevocably_resolved(struct tracked_output **outs) +{ + size_t i, num = 0; + + for (i = 0; i < tal_count(outs); i++) { + if (!outs[i]->resolved || outs[i]->resolved->depth < 100) + num++; + } + return num; +} + +static u32 prop_blockheight(const struct tracked_output *out) +{ + return out->tx_blockheight + out->proposal->depth_required; +} + +static void billboard_update(struct tracked_output **outs) +{ + const struct tracked_output *best = NULL; + + /* Highest priority is to report on proposals we have */ + for (size_t i = 0; i < tal_count(outs); i++) { + if (!outs[i]->proposal || outs[i]->resolved) + continue; + if (!best || prop_blockheight(outs[i]) < prop_blockheight(best)) + best = outs[i]; + } + + if (best) { + /* If we've broadcast and not seen yet, this happens */ + if (best->proposal->depth_required <= best->depth) { + peer_billboard(false, + "%u outputs unresolved: waiting confirmation that we spent %s (%s) using %s", + num_not_irrevocably_resolved(outs), + output_type_name(best->output_type), + type_to_string(tmpctx, + struct bitcoin_outpoint, + &best->outpoint), + tx_type_name(best->proposal->tx_type)); + } else { + peer_billboard(false, + "%u outputs unresolved: in %u blocks will spend %s (%s) using %s", + num_not_irrevocably_resolved(outs), + best->proposal->depth_required - best->depth, + output_type_name(best->output_type), + type_to_string(tmpctx, + struct bitcoin_outpoint, + &best->outpoint), + tx_type_name(best->proposal->tx_type)); + } + return; + } + + /* Now, just report on the last thing we're waiting out. */ + for (size_t i = 0; i < tal_count(outs); i++) { + /* FIXME: Can this happen? No proposal, no resolution? */ + if (!outs[i]->resolved) + continue; + if (!best || outs[i]->resolved->depth < best->resolved->depth) + best = outs[i]; + } + + if (best) { + peer_billboard(false, + "All outputs resolved:" + " waiting %u more blocks before forgetting" + " channel", + best->resolved->depth < 100 + ? 100 - best->resolved->depth : 0); + return; + } + + /* Not sure this can happen, but take last one (there must be one!) */ + best = outs[tal_count(outs)-1]; + peer_billboard(false, "%u outputs unresolved: %s is one (depth %u)", + num_not_irrevocably_resolved(outs), + output_type_name(best->output_type), best->depth); +} + +static void unwatch_txid(const struct bitcoin_txid *txid) +{ + u8 *msg; + + msg = towire_onchaind_unwatch_tx(NULL, txid); + wire_sync_write(REQ_FD, take(msg)); +} + +static void handle_htlc_onchain_fulfill(struct tracked_output *out, + const struct tx_parts *tx_parts, + const struct bitcoin_outpoint *htlc_outpoint) +{ + const struct wally_tx_witness_item *preimage_item; + struct preimage preimage; + struct sha256 sha; + struct ripemd160 ripemd; + + /* Our HTLC, they filled (must be an HTLC-success tx). */ + if (out->tx_type == THEIR_UNILATERAL + || out->tx_type == THEIR_REVOKED_UNILATERAL) { + /* BOLT #3: + * + * ## HTLC-Timeout and HTLC-Success Transactions + * + * ... `txin[0]` witness stack: `0 + * ` for HTLC-success + */ + if (tx_parts->inputs[htlc_outpoint->n]->witness->num_items != 5) /* +1 for wscript */ + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "%s/%s spent with weird witness %zu", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + tx_parts->inputs[htlc_outpoint->n]->witness->num_items); + + preimage_item = &tx_parts->inputs[htlc_outpoint->n]->witness->items[3]; + } else if (out->tx_type == OUR_UNILATERAL) { + /* BOLT #3: + * + * The remote node can redeem the HTLC with the witness: + * + * + */ + if (tx_parts->inputs[htlc_outpoint->n]->witness->num_items != 3) /* +1 for wscript */ + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "%s/%s spent with weird witness %zu", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + tx_parts->inputs[htlc_outpoint->n]->witness->num_items); + + preimage_item = &tx_parts->inputs[htlc_outpoint->n]->witness->items[1]; + } else + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "onchain_fulfill for %s/%s?", + tx_type_name(out->tx_type), + output_type_name(out->output_type)); + + /* cppcheck-suppress uninitvar - doesn't know status_failed exits? */ + if (preimage_item->witness_len != sizeof(preimage)) { + /* It's possible something terrible happened and we broadcast + * an old commitment state, which they're now cleaning up. + * + * We stumble along. + */ + if (out->tx_type == OUR_UNILATERAL + && preimage_item->witness_len == PUBKEY_CMPR_LEN) { + status_unusual("Our cheat attempt failed, they're " + "taking our htlc out (%s)", + type_to_string(tmpctx, struct amount_sat, + &out->sat)); + return; + } + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "%s/%s spent with bad witness length %zu", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + preimage_item->witness_len); + } + memcpy(&preimage, preimage_item->witness, sizeof(preimage)); + sha256(&sha, &preimage, sizeof(preimage)); + ripemd160(&ripemd, &sha, sizeof(sha)); + + if (!ripemd160_eq(&ripemd, &out->htlc.ripemd)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "%s/%s spent with bad preimage %s (ripemd not %s)", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + type_to_string(tmpctx, struct preimage, &preimage), + type_to_string(tmpctx, struct ripemd160, + &out->htlc.ripemd)); + + /* we stash the payment_hash into the tracking_output so we + * can pass it along, if needbe, to the coin movement tracker */ + out->payment_hash = sha; + + /* Tell master we found a preimage. */ + status_debug("%s/%s gave us preimage %s", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + type_to_string(tmpctx, struct preimage, &preimage)); + wire_sync_write(REQ_FD, + take(towire_onchaind_extracted_preimage(NULL, + &preimage))); +} + +static void onchain_annotate_txout(const struct bitcoin_outpoint *outpoint, + enum wallet_tx_type type) +{ + wire_sync_write(REQ_FD, take(towire_onchaind_annotate_txout( + tmpctx, outpoint, type))); +} + +static void onchain_annotate_txin(const struct bitcoin_txid *txid, u32 innum, + enum wallet_tx_type type) +{ + wire_sync_write(REQ_FD, take(towire_onchaind_annotate_txin( + tmpctx, txid, innum, type))); +} + +/* An output has been spent: see if it resolves something we care about. */ +static void output_spent(struct tracked_output ***outs, + const struct tx_parts *tx_parts, + u32 input_num, + u32 tx_blockheight) +{ + for (size_t i = 0; i < tal_count(*outs); i++) { + struct tracked_output *out = (*outs)[i]; + struct bitcoin_outpoint htlc_outpoint; + + if (out->resolved) + continue; + + if (!wally_tx_input_spends(tx_parts->inputs[input_num], + &out->outpoint)) + continue; + + /* Was this our resolution? */ + if (resolved_by_proposal(out, tx_parts)) { + /* If it's our htlc tx, we need to resolve that, too. */ + /* FIXME we can spend htlc immediately? + if (out->resolved->tx_type == OUR_HTLC_SUCCESS_TX + || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX) + resolve_htlc_tx(outs, i, tx_parts, input_num, + tx_blockheight);*/ + + record_coin_movements(out, tx_blockheight, + out->proposal->tx, + &tx_parts->txid); + return; + } + + htlc_outpoint.txid = tx_parts->txid; + htlc_outpoint.n = input_num; + + switch (out->output_type) { + case OUTPUT_TO_US: + case DELAYED_OUTPUT_TO_US: + unknown_spend(out, tx_parts); + record_external_deposit(out, tx_blockheight, PENALIZED); + break; + + case THEIR_HTLC: + record_external_deposit(out, out->tx_blockheight, + HTLC_TIMEOUT); + record_external_spend(&tx_parts->txid, out, + tx_blockheight, HTLC_TIMEOUT); + + if (out->tx_type == THEIR_REVOKED_UNILATERAL) { + /* FIXME impossible state, no such thing as revoked */ + /* we've actually got a 'new' output here */ + } else { + /* We ignore this timeout tx, since we should + * resolve by ignoring once we reach depth. */ + onchain_annotate_txout( + &htlc_outpoint, + TX_CHANNEL_HTLC_TIMEOUT | TX_THEIRS); + } + break; + + case OUR_HTLC: + /* The only way they can spend this: fulfill; even + * if it's revoked: */ + /* BOLT #5: + * + * ## HTLC Output Handling: Local Commitment, Local Offers + *... + * - MUST extract the payment preimage from the + * transaction input witness. + *... + * ## HTLC Output Handling: Remote Commitment, Local Offers + *... + * - MUST extract the payment preimage from the + * HTLC-success transaction input witness. + */ + handle_htlc_onchain_fulfill(out, tx_parts, + &htlc_outpoint); + + record_to_them_htlc_fulfilled(out, tx_blockheight); + record_external_spend(&tx_parts->txid, out, + tx_blockheight, HTLC_FULFILL); + + if (out->tx_type == THEIR_REVOKED_UNILATERAL) { + /* FIXME no such thing as revoked */ + } else { + /* BOLT #5: + * + * ## HTLC Output Handling: Local Commitment, + * Local Offers + *... + * - if the commitment transaction HTLC output + * is spent using the payment preimage, the + * output is considered *irrevocably resolved* + */ + ignore_output(out); + + onchain_annotate_txout( + &htlc_outpoint, + TX_CHANNEL_HTLC_SUCCESS | TX_THEIRS); + } + break; + + case FUNDING_OUTPUT: + /* Master should be restarting us, as this implies + * that our old tx was unspent. */ + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Funding output spent again!"); + + case DELAYED_CHEAT_OUTPUT_TO_THEM: + /* They successfully spent a delayed revoked output */ + resolved_by_other(out, &tx_parts->txid, + THEIR_DELAYED_CHEAT); + + record_external_deposit(out, tx_blockheight, STOLEN); + break; + /* Um, we don't track these! */ + case OUTPUT_TO_THEM: + case DELAYED_OUTPUT_TO_THEM: + case ELEMENTS_FEE: + case ANCHOR_TO_US: + case ANCHOR_TO_THEM: + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tracked spend of %s/%s?", + tx_type_name(out->tx_type), + output_type_name(out->output_type)); + } + return; + } + + struct bitcoin_txid txid; + wally_tx_input_get_txid(tx_parts->inputs[input_num], &txid); + /* Not interesting to us, so unwatch the tx and all its outputs */ + status_debug("Notified about tx %s output %u spend, but we don't care", + type_to_string(tmpctx, struct bitcoin_txid, &txid), + tx_parts->inputs[input_num]->index); + + unwatch_txid(&tx_parts->txid); +} + +static void update_resolution_depth(struct tracked_output *out, u32 depth) +{ + bool reached_reasonable_depth; + + status_debug("%s/%s->%s depth %u", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + tx_type_name(out->resolved->tx_type), + depth); + + /* We only set this once. */ + reached_reasonable_depth = (out->resolved->depth < reasonable_depth + && depth >= reasonable_depth); + + /* BOLT #5: + * + * - if the commitment transaction HTLC output has *timed out* and + * hasn't been *resolved*: + * - MUST *resolve* the output by spending it using the HTLC-timeout + * transaction. + * - once the resolving transaction has reached reasonable depth: + * - MUST fail the corresponding incoming HTLC (if any). + */ + if ((out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX + || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TO_US) + && reached_reasonable_depth) { + u8 *msg; + status_debug("%s/%s reached reasonable depth %u", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + depth); + msg = towire_onchaind_htlc_timeout(out, &out->htlc); + wire_sync_write(REQ_FD, take(msg)); + } + out->resolved->depth = depth; +} + +static void tx_new_depth(struct tracked_output **outs, + const struct bitcoin_txid *txid, u32 depth) +{ + size_t i; + + /* Special handling for commitment tx reaching depth */ + if (bitcoin_txid_eq(&outs[0]->resolved->txid, txid) + && depth >= reasonable_depth + && missing_htlc_msgs) { + status_debug("Sending %zu missing htlc messages", + tal_count(missing_htlc_msgs)); + for (i = 0; i < tal_count(missing_htlc_msgs); i++) + wire_sync_write(REQ_FD, missing_htlc_msgs[i]); + /* Don't do it again. */ + missing_htlc_msgs = tal_free(missing_htlc_msgs); + } + + for (i = 0; i < tal_count(outs); i++) { + /* Update output depth. */ + if (bitcoin_txid_eq(&outs[i]->outpoint.txid, txid)) + outs[i]->depth = depth; + + /* Is this tx resolving an output? */ + if (outs[i]->resolved) { + if (bitcoin_txid_eq(&outs[i]->resolved->txid, txid)) { + update_resolution_depth(outs[i], depth); + } + continue; + } + + /* Otherwise, is this something we have a pending + * resolution for? */ + if (outs[i]->proposal + && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) + && depth >= outs[i]->proposal->depth_required) { + proposal_meets_depth(outs[i]); + } + + /* Otherwise, is this an output whose proposed resolution + * we should RBF? */ + if (outs[i]->proposal + && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) + && proposal_is_rbfable(outs[i]->proposal)) + proposal_should_rbf(outs[i]); + } +} + +/* BOLT #XX: + * FIXME add BOLT text + */ +/* Master makes sure we only get told preimages once other node is committed. */ +static void eltoo_handle_preimage(struct tracked_output **outs, + const struct preimage *preimage) +{ + size_t i; + struct sha256 sha; + struct ripemd160 ripemd; + + sha256(&sha, preimage, sizeof(*preimage)); + ripemd160(&ripemd, &sha, sizeof(sha)); + + for (i = 0; i < tal_count(outs); i++) { + if (outs[i]->output_type != THEIR_HTLC) + continue; + + if (!ripemd160_eq(&outs[i]->htlc.ripemd, &ripemd)) + continue; + + /* Too late? */ + if (outs[i]->resolved) { + status_broken("HTLC already resolved by %s" + " when we found preimage", + tx_type_name(outs[i]->resolved->tx_type)); + return; + } + + /* stash the payment_hash so we can track this coin movement */ + outs[i]->payment_hash = sha; + + /* Discard any previous resolution. Could be a timeout, + * could be due to multiple identical rhashes in tx. */ + outs[i]->proposal = tal_free(outs[i]->proposal); + + /* FIXME Actually do something with them by looking for an output I can spend immediately */ + } +} + +#if DEVELOPER +static void memleak_remove_globals(struct htable *memtable, const tal_t *topctx) +{ + if (keyset) + memleak_remove_region(memtable, keyset, sizeof(*keyset)); + memleak_remove_pointer(memtable, remote_per_commitment_point); + memleak_remove_pointer(memtable, remote_per_commitment_secret); + memleak_remove_pointer(memtable, topctx); + memleak_remove_region(memtable, + missing_htlc_msgs, tal_bytelen(missing_htlc_msgs)); + memleak_remove_region(memtable, + queued_msgs, tal_bytelen(queued_msgs)); +} + +static bool handle_dev_memleak(struct tracked_output **outs, const u8 *msg) +{ + struct htable *memtable; + bool found_leak; + + if (!fromwire_onchaind_dev_memleak(msg)) + return false; + + memtable = memleak_find_allocations(tmpctx, msg, msg); + /* Top-level context is parent of outs */ + memleak_remove_globals(memtable, tal_parent(outs)); + memleak_remove_region(memtable, outs, tal_bytelen(outs)); + + found_leak = dump_memleak(memtable, memleak_status_broken); + wire_sync_write(REQ_FD, + take(towire_onchaind_dev_memleak_reply(NULL, + found_leak))); + return true; +} +#else +static bool handle_dev_memleak(struct tracked_output **outs, const u8 *msg) +{ + return false; +} +#endif /* !DEVELOPER */ + +/* BOLT #5: + * + * A node: + * - once it has broadcast a funding transaction OR sent a commitment signature + * for a commitment transaction that contains an HTLC output: + * - until all outputs are *irrevocably resolved*: + * - MUST monitor the blockchain for transactions that spend any output that + * is NOT *irrevocably resolved*. + */ +static void wait_for_resolved(struct tracked_output **outs) +{ + billboard_update(outs); + + while (num_not_irrevocably_resolved(outs) != 0) { + u8 *msg; + struct bitcoin_txid txid; + u32 input_num, depth, tx_blockheight; + struct preimage preimage; + struct tx_parts *tx_parts; + + if (tal_count(queued_msgs)) { + msg = tal_steal(outs, queued_msgs[0]); + tal_arr_remove(&queued_msgs, 0); + } else + msg = wire_sync_read(outs, REQ_FD); + + status_debug("Got new message %s", + onchaind_wire_name(fromwire_peektype(msg))); + + if (fromwire_onchaind_depth(msg, &txid, &depth)) + tx_new_depth(outs, &txid, depth); + else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num, + &tx_blockheight)) { + output_spent(&outs, tx_parts, input_num, tx_blockheight); + } else if (fromwire_onchaind_known_preimage(msg, &preimage)) + eltoo_handle_preimage(outs, &preimage); + else if (!handle_dev_memleak(outs, msg)) + master_badmsg(-1, msg); + + billboard_update(outs); + tal_free(msg); + clean_tmpctx(); + } + + wire_sync_write(REQ_FD, + take(towire_onchaind_all_irrevocably_resolved(outs))); +} + +struct htlcs_info { + struct htlc_stub *htlcs; + /* FIXME remove? */ + bool *tell_if_missing; + bool *tell_immediately; +}; + +struct htlc_with_tells { + struct htlc_stub htlc; + /* FIXME remove? */ + bool tell_if_missing, tell_immediately; +}; + +static int cmp_htlc_with_tells_cltv(const struct htlc_with_tells *a, + const struct htlc_with_tells *b, void *unused) +{ + if (a->htlc.cltv_expiry < b->htlc.cltv_expiry) + return -1; + else if (a->htlc.cltv_expiry > b->htlc.cltv_expiry) + return 1; + return 0; +} + +static struct htlcs_info *eltoo_init_reply(const tal_t *ctx, const char *what) +{ + struct htlcs_info *htlcs_info = tal(ctx, struct htlcs_info); + u8 *msg; + struct htlc_with_tells *htlcs; + + /* Send init_reply first, so billboard gets credited to ONCHAIND */ + wire_sync_write(REQ_FD, + take(towire_eltoo_onchaind_init_reply(NULL))); + + peer_billboard(true, what); + + /* Read in htlcs */ + for (;;) { + msg = wire_sync_read(queued_msgs, REQ_FD); + if (fromwire_eltoo_onchaind_htlcs(tmpctx, msg, + &htlcs_info->htlcs)) { + tal_free(msg); + break; + } + + /* Process later */ + tal_arr_expand(&queued_msgs, msg); + } + + /* One convenient structure, so we sort them together! */ + htlcs = tal_arr(tmpctx, struct htlc_with_tells, tal_count(htlcs_info->htlcs)); + for (size_t i = 0; i < tal_count(htlcs); i++) { + htlcs[i].htlc = htlcs_info->htlcs[i]; + } + + /* Sort by CLTV, so matches are in CLTV order (and easy to skip dups) */ + asort(htlcs, tal_count(htlcs), cmp_htlc_with_tells_cltv, NULL); + + /* Now put them back (prev were allocated off tmpctx) */ + htlcs_info->htlcs = tal_arr(htlcs_info, struct htlc_stub, tal_count(htlcs)); + for (size_t i = 0; i < tal_count(htlcs); i++) { + htlcs_info->htlcs[i] = htlcs[i].htlc; + } + + return htlcs_info; +} + +/* This is not directly copied and pasted */ +static void eltoo_handle_mutual_close(struct tracked_output **outs, + const struct tx_parts *tx, + size_t input_num) +{ + /* In this case, we don't care about htlcs: there are none. */ + eltoo_init_reply(tmpctx, "Tracking mutual close transaction"); + + /* Annotate the first input as close. We can currently only have a + * single input for these. */ + onchain_annotate_txin(&tx->txid, input_num, TX_CHANNEL_CLOSE); + + /* BOLT #5: + * + * A closing transaction *resolves* the funding transaction output. + * + * In the case of a mutual close, a node need not do anything else, as it has + * already agreed to the output, which is sent to its specified `scriptpubkey` + */ + resolved_by_other(outs[0], &tx->txid, MUTUAL_CLOSE); + wait_for_resolved(outs); } int main(int argc, char *argv[]) @@ -135,7 +1546,8 @@ int main(int argc, char *argv[]) struct bitcoin_outpoint funding; u32 input_num; struct amount_sat funding_sats; - u32 tx_blockheight; + u32 locktime, tx_blockheight; + u8 *scriptpubkey[NUM_SIDES]; subdaemon_setup(argc, argv); @@ -147,11 +1559,14 @@ int main(int argc, char *argv[]) &chainparams, &funding_sats, &spending_tx, + &locktime, &input_num, &unbound_update_tx, &unbound_settle_tx, &tx_blockheight, - &our_msat)) { + &our_msat, + &scriptpubkey[LOCAL], + &scriptpubkey[REMOTE])) { master_badmsg(WIRE_ELTOO_ONCHAIND_INIT, msg); } @@ -186,14 +1601,20 @@ int main(int argc, char *argv[]) funding_sats, tal_count(spending_tx->outputs)))); + if (is_mutual_close(locktime)) { + status_debug("Handling mutual close!"); + record_mutual_close(spending_tx, scriptpubkey[REMOTE], + tx_blockheight); + eltoo_handle_mutual_close(outs, spending_tx, input_num); + } else { + status_debug("NI: Handling unilateral close!"); + /* FIXME commit_num should just be our latest tx, since we only need latest */ + } /* FIXME Now that we see the transaction in block, and our latest versions, re-bind our transactions and submit them to the mempool */ - /* FIXME More stuff to come, sit and wait for a response that shouldn't come */ - msg = wire_sync_read(tmpctx, REQ_FD); - - /* We're done! */ + /* We're done! */ tal_free(ctx); daemon_shutdown(); diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 577020809ed7..e9af86dc82ce 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -145,13 +145,21 @@ msgtype,eltoo_onchaind_init,5061 msgdata,eltoo_onchaind_init,chainparams,chainparams, msgdata,eltoo_onchaind_init,funding_amount_satoshi,amount_sat, msgdata,eltoo_onchaind_init,tx_parts,tx_parts, +msgdata,eltoo_onchaind_init,locktime,u32, msgdata,eltoo_onchaind_init,input_num,u32, msgdata,eltoo_onchaind_init,update_tx,bitcoin_tx, msgdata,eltoo_onchaind_init,settle_tx,bitcoin_tx, msgdata,eltoo_onchaind_init,tx_blockheight,u32, msgdata,eltoo_onchaind_init,our_msat,amount_msat, +msgdata,eltoo_onchaind_init,local_scriptpubkey_len,u16, +msgdata,eltoo_onchaind_init,local_scriptpubkey,u8,local_scriptpubkey_len +msgdata,eltoo_onchaind_init,remote_scriptpubkey_len,u16, +msgdata,eltoo_onchaind_init,remote_scriptpubkey,u8,remote_scriptpubkey_len # This says we're ready; give us htlcs and preimages. msgtype,eltoo_onchaind_init_reply,5161 - +# Same pattern of messages for simplicity, without unused things +msgtype,eltoo_onchaind_htlcs,5062 +msgdata,eltoo_onchaind_htlcs,num_htlcs,u32, +msgdata,eltoo_onchaind_htlcs,htlc,htlc_stub,num_htlcs From a3cdbfdbe203eb1550aef8408af55dfd40364ec5 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 30 Sep 2022 11:27:40 -0400 Subject: [PATCH 203/283] Stick closer to the legacy flow for now --- lightningd/onchain_control.c | 20 +++++++++++++++----- onchaind/eltoo_onchaind.c | 32 ++++++++++++++++++++------------ onchaind/onchaind_wire.csv | 5 ----- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 645b4ab4217e..7c6b3931efde 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -135,10 +135,15 @@ static void handle_onchain_init_reply(struct channel *channel, const u8 *msg) onchaind_tell_fulfill(channel); } +/* Only change here is fromwire_eltoo_onchaind_init_reply without commit_num + and FIXME in the future we will grab the O(1) HTLC records for latest tx rather + than the growing HTLC db. We can probably drop the "tell" stuff? */ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *msg) { struct htlc_stub *stubs; - u64 commit_num = channel->last_tx->wtx->locktime; /* update_num */ + bool *tell, *tell_immediate; + /* We are only interested in latest HTLCs, the ones we will recall */ + u64 commit_num = channel->last_tx->wtx->locktime; /* Signaling ready, send more data */ if (!fromwire_eltoo_onchaind_init_reply(msg)) { @@ -158,14 +163,21 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m * FIXME (only one set for eltoo... we shouldn't be storing everything) */ stubs = wallet_htlc_stubs(tmpctx, channel->peer->ld->wallet, channel, commit_num); - msg = towire_eltoo_onchaind_htlcs(channel, stubs); + tell = tal_arr(stubs, bool, tal_count(stubs)); + tell_immediate = tal_arr(stubs, bool, tal_count(stubs)); + + for (size_t i = 0; i < tal_count(stubs); i++) { + tell[i] = tell_if_missing(channel, &stubs[i], + &tell_immediate[i]); + } + msg = towire_onchaind_htlcs(channel, stubs, tell, tell_immediate); + subd_send_msg(channel->owner, take(msg)); /* Tell it about any preimages we know. */ onchaind_tell_fulfill(channel); } - /** * Notify onchaind about the depth change of the watched tx. */ @@ -607,7 +619,6 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U case WIRE_ONCHAIND_KNOWN_PREIMAGE: case WIRE_ONCHAIND_DEV_MEMLEAK: case WIRE_ONCHAIND_DEV_MEMLEAK_REPLY: - case WIRE_ELTOO_ONCHAIND_HTLCS: break; /* These are illegal */ case WIRE_ELTOO_ONCHAIND_INIT: @@ -648,7 +659,6 @@ static unsigned int eltoo_onchain_msg(struct subd *sd, const u8 *msg, const int case WIRE_ONCHAIND_DEV_MEMLEAK: case WIRE_ONCHAIND_DEV_MEMLEAK_REPLY: case WIRE_ELTOO_ONCHAIND_INIT: - case WIRE_ELTOO_ONCHAIND_HTLCS: break; /* These are illegal */ case WIRE_ONCHAIND_INIT_REPLY: diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 3c5fe5adffcb..0bdb8ce77847 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -27,7 +27,7 @@ #define REQ_FD STDIN_FILENO #define HSM_FD 3 -/* FIXME Everything copy/pasted bc static */ +/* FIXME Everything copy/pasted bc static. Deduplicate later */ /* Required in various places: keys for commitment transaction. */ static const struct keyset *keyset; @@ -1095,6 +1095,7 @@ static void onchain_annotate_txin(const struct bitcoin_txid *txid, u32 innum, } /* An output has been spent: see if it resolves something we care about. */ +/* FIXME FRIDAY: work through this tracking logic */ static void output_spent(struct tracked_output ***outs, const struct tx_parts *tx_parts, u32 input_num, @@ -1447,14 +1448,12 @@ static void wait_for_resolved(struct tracked_output **outs) struct htlcs_info { struct htlc_stub *htlcs; - /* FIXME remove? */ bool *tell_if_missing; bool *tell_immediately; }; struct htlc_with_tells { struct htlc_stub htlc; - /* FIXME remove? */ bool tell_if_missing, tell_immediately; }; @@ -1468,23 +1467,26 @@ static int cmp_htlc_with_tells_cltv(const struct htlc_with_tells *a, return 0; } +/* sends eltoo reply to be handled properly, otherwise the same */ static struct htlcs_info *eltoo_init_reply(const tal_t *ctx, const char *what) { struct htlcs_info *htlcs_info = tal(ctx, struct htlcs_info); u8 *msg; struct htlc_with_tells *htlcs; - + /* Send init_reply first, so billboard gets credited to ONCHAIND */ wire_sync_write(REQ_FD, take(towire_eltoo_onchaind_init_reply(NULL))); - + peer_billboard(true, what); - + /* Read in htlcs */ for (;;) { msg = wire_sync_read(queued_msgs, REQ_FD); - if (fromwire_eltoo_onchaind_htlcs(tmpctx, msg, - &htlcs_info->htlcs)) { + if (fromwire_onchaind_htlcs(tmpctx, msg, + &htlcs_info->htlcs, + &htlcs_info->tell_if_missing, + &htlcs_info->tell_immediately)) { tal_free(msg); break; } @@ -1492,20 +1494,26 @@ static struct htlcs_info *eltoo_init_reply(const tal_t *ctx, const char *what) /* Process later */ tal_arr_expand(&queued_msgs, msg); } - + /* One convenient structure, so we sort them together! */ htlcs = tal_arr(tmpctx, struct htlc_with_tells, tal_count(htlcs_info->htlcs)); for (size_t i = 0; i < tal_count(htlcs); i++) { htlcs[i].htlc = htlcs_info->htlcs[i]; - } - + htlcs[i].tell_if_missing = htlcs_info->tell_if_missing[i]; + htlcs[i].tell_immediately = htlcs_info->tell_immediately[i]; + } + /* Sort by CLTV, so matches are in CLTV order (and easy to skip dups) */ asort(htlcs, tal_count(htlcs), cmp_htlc_with_tells_cltv, NULL); - + /* Now put them back (prev were allocated off tmpctx) */ htlcs_info->htlcs = tal_arr(htlcs_info, struct htlc_stub, tal_count(htlcs)); + htlcs_info->tell_if_missing = tal_arr(htlcs_info, bool, tal_count(htlcs)); + htlcs_info->tell_immediately = tal_arr(htlcs_info, bool, tal_count(htlcs)); for (size_t i = 0; i < tal_count(htlcs); i++) { htlcs_info->htlcs[i] = htlcs[i].htlc; + htlcs_info->tell_if_missing[i] = htlcs[i].tell_if_missing; + htlcs_info->tell_immediately[i] = htlcs[i].tell_immediately; } return htlcs_info; diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index e9af86dc82ce..87d15c1ecd4c 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -158,8 +158,3 @@ msgdata,eltoo_onchaind_init,remote_scriptpubkey,u8,remote_scriptpubkey_len # This says we're ready; give us htlcs and preimages. msgtype,eltoo_onchaind_init_reply,5161 - -# Same pattern of messages for simplicity, without unused things -msgtype,eltoo_onchaind_htlcs,5062 -msgdata,eltoo_onchaind_htlcs,num_htlcs,u32, -msgdata,eltoo_onchaind_htlcs,htlc,htlc_stub,num_htlcs From dfa5c29c79534ec70d9721fcdf9ea7a7f697989a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 30 Sep 2022 15:10:28 -0400 Subject: [PATCH 204/283] Stuff crashing because I'm not handling eltoo_onchaind responses... --- contrib/startup_regtest.sh | 2 +- lightningd/onchain_control.c | 11 ++--- lightningd/onchain_control.h | 2 - lightningd/peer_control.c | 4 +- lightningd/test/run-invoice-select-inchan.c | 1 - onchaind/eltoo_onchaind.c | 52 ++++++++++++++------- onchaind/onchaind_wire.csv | 2 +- wallet/test/run-wallet.c | 1 - 8 files changed, 42 insertions(+), 33 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 5ae113c1b90d..cf8ce2a06c80 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -180,7 +180,7 @@ onchain_ln() { # Settle tx can be broadcast after shared_delay, onchaind should # be trying to spend the update tx output itself! bt-cli generatetoaddress 6 $btcaddr - txid=$(bt-cli decoderawtransaction $SETTLE_HEX | jq -r .txid) + txid=$(bt-cli decoderawtransaction $FIRST_SETTLE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $FIRST_SETTLE_HEX bt-cli generatetoaddress 1 $btcaddr diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 7c6b3931efde..2a506d902744 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -692,12 +692,10 @@ static void onchain_error(struct channel *channel, * onchaind (like any other owner), and restart */ enum watch_result onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, - size_t input_num, u32 blockheight) { if (channel->our_config.is_eltoo) { - /* input_num is required due to ANYPREVOUT signature */ - return eltoo_onchaind_funding_spent(channel, tx, blockheight, input_num); + return eltoo_onchaind_funding_spent(channel, tx, blockheight); } u8 *msg; @@ -859,7 +857,6 @@ enum watch_result onchaind_funding_spent(struct channel *channel, * onchaind (like any other owner), and restart */ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, - size_t input_num, u32 blockheight) { u8 *msg; @@ -916,10 +913,10 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, /* Add HTLCs to init, since we know which HTLCs will be exposed */ msg = towire_eltoo_onchaind_init(channel, chainparams, + &channel->funding, channel->funding_sats, tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), tx->wtx->locktime, - input_num, channel->last_tx, channel->last_settle_tx, blockheight, @@ -954,12 +951,12 @@ void onchaind_replay_channels(struct lightningd *ld) for (size_t j = 0; j < tal_count(txs); j++) { if (txs[j].type == WIRE_ONCHAIND_INIT) { - onchaind_funding_spent(chan, txs[j].tx, txs[j].input_num, + onchaind_funding_spent(chan, txs[j].tx, txs[j].blockheight); } else if (txs[j].type == WIRE_ONCHAIND_SPENT) { onchain_txo_spent(chan, txs[j].tx, - txs[j].input_num, + txs[j].input_num, txs[j].blockheight); } else if (txs[j].type == WIRE_ONCHAIND_DEPTH) { diff --git a/lightningd/onchain_control.h b/lightningd/onchain_control.h index 08cc97646dd1..a0cc333457c5 100644 --- a/lightningd/onchain_control.h +++ b/lightningd/onchain_control.h @@ -9,12 +9,10 @@ struct block; enum watch_result onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, - size_t input_num, u32 blockheight); enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, const struct bitcoin_tx *tx, - size_t input_num, u32 blockheight); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index f062bcb75174..8192143e533a 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1723,7 +1723,7 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, static enum watch_result funding_spent(struct channel *channel, const struct bitcoin_tx *tx, - size_t input_num, + size_t input_num UNUSED, const struct block *block) { struct bitcoin_txid txid; @@ -1731,7 +1731,7 @@ static enum watch_result funding_spent(struct channel *channel, wallet_channeltxs_add(channel->peer->ld->wallet, channel, WIRE_ONCHAIND_INIT, &txid, 0, block->height); - return onchaind_funding_spent(channel, tx, input_num, block->height); + return onchaind_funding_spent(channel, tx, block->height); } void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel) diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 55a298fc4466..d1d7a44ce44c 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -515,7 +515,6 @@ void notify_invoice_payment(struct lightningd *ld UNNEEDED, struct amount_msat a /* Generated stub for onchaind_funding_spent */ enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, - size_t input_num UNNEEDED, u32 blockheight UNNEEDED) { fprintf(stderr, "onchaind_funding_spent called!\n"); abort(); } /* Generated stub for param */ diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 0bdb8ce77847..d9cfdf518f4a 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1519,17 +1519,25 @@ static struct htlcs_info *eltoo_init_reply(const tal_t *ctx, const char *what) return htlcs_info; } -/* This is not directly copied and pasted */ static void eltoo_handle_mutual_close(struct tracked_output **outs, - const struct tx_parts *tx, - size_t input_num) + const struct tx_parts *tx) { + int i; + /* In this case, we don't care about htlcs: there are none. */ eltoo_init_reply(tmpctx, "Tracking mutual close transaction"); - /* Annotate the first input as close. We can currently only have a + /* Annotate the input that matches the funding outpoint as close. We can currently only have a * single input for these. */ - onchain_annotate_txin(&tx->txid, input_num, TX_CHANNEL_CLOSE); + for (i=0; iinputs); i++) { + if (tx->inputs[i]->index == outs[0]->outpoint.n && + !memcmp(tx->inputs[i]->txhash, &outs[0]->outpoint.txid, 32)) { + break; + } + } + assert(i != tal_count(tx->inputs)); + + onchain_annotate_txin(&tx->txid, i, TX_CHANNEL_CLOSE); /* BOLT #5: * @@ -1552,7 +1560,6 @@ int main(int argc, char *argv[]) struct bitcoin_tx *unbound_update_tx, *unbound_settle_tx; struct tracked_output **outs; struct bitcoin_outpoint funding; - u32 input_num; struct amount_sat funding_sats; u32 locktime, tx_blockheight; u8 *scriptpubkey[NUM_SIDES]; @@ -1565,10 +1572,10 @@ int main(int argc, char *argv[]) if (!fromwire_eltoo_onchaind_init(tmpctx, msg, &chainparams, + &funding, &funding_sats, &spending_tx, &locktime, - &input_num, &unbound_update_tx, &unbound_settle_tx, &tx_blockheight, @@ -1591,10 +1598,6 @@ int main(int argc, char *argv[]) /* These are the utxos we are interested in */ outs = tal_arr(ctx, struct tracked_output *, 0); - assert(tal_count(spending_tx->inputs) > input_num); - wally_tx_input_get_txid(spending_tx->inputs[0], &funding.txid); - funding.n = spending_tx->inputs[input_num]->index; - /* Tracking funding output which is spent already */ new_tracked_output(&outs, &funding, 0, /* We don't care about funding blockheight */ @@ -1613,16 +1616,29 @@ int main(int argc, char *argv[]) status_debug("Handling mutual close!"); record_mutual_close(spending_tx, scriptpubkey[REMOTE], tx_blockheight); - eltoo_handle_mutual_close(outs, spending_tx, input_num); + eltoo_handle_mutual_close(outs, spending_tx); } else { - status_debug("NI: Handling unilateral close!"); - /* FIXME commit_num should just be our latest tx, since we only need latest */ + status_debug("Handling unilateral close!"); + if (locktime > unbound_update_tx->wtx->locktime) { + status_debug("Uh-oh, please be nice Mr Counterparty :("); + /* Might as well track the state output, see if it ends up in a settlement tx + * So `to_node` values can be harvested, HTLCs rescued OOB with counterparty's help? + */ + } else if (locktime == unbound_update_tx->wtx->locktime) { + status_debug("Unilateral close of last state detected"); + /* Someday we could maybe negotiate with peer to life back into channel + * For now we just deal with it by submitting settle transaction. + * If we know it's counter-party, maybe they'll pay for us :) + * or maybe we paid a watchtower already... + * + * Either way, this also happens in the "cheating" below, and we handle this identically. + */ + } else { + status_debug("Cheater!"); + } } - /* FIXME Now that we see the transaction in block, and our latest versions, - re-bind our transactions and submit them to the mempool */ - - /* We're done! */ + /* We're done! */ tal_free(ctx); daemon_shutdown(); diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 87d15c1ecd4c..8faf07c9ca8a 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -143,10 +143,10 @@ msgdata,onchaind_notify_coin_mvt,mvt,chain_coin_mvt, # Eltoo stuff following msgtype,eltoo_onchaind_init,5061 msgdata,eltoo_onchaind_init,chainparams,chainparams, +msgdata,eltoo_onchaind_init,funding_outpoint,bitcoin_outpoint, msgdata,eltoo_onchaind_init,funding_amount_satoshi,amount_sat, msgdata,eltoo_onchaind_init,tx_parts,tx_parts, msgdata,eltoo_onchaind_init,locktime,u32, -msgdata,eltoo_onchaind_init,input_num,u32, msgdata,eltoo_onchaind_init,update_tx,bitcoin_tx, msgdata,eltoo_onchaind_init,settle_tx,bitcoin_tx, msgdata,eltoo_onchaind_init,tx_blockheight,u32, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index ba814685674b..889743686ecf 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -553,7 +553,6 @@ void notify_forward_event(struct lightningd *ld UNNEEDED, /* Generated stub for onchaind_funding_spent */ enum watch_result onchaind_funding_spent(struct channel *channel UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, - size_t input_num UNNEEDED, u32 blockheight UNNEEDED) { fprintf(stderr, "onchaind_funding_spent called!\n"); abort(); } /* Generated stub for onion_decode */ From 32229da8944e7493600ef46d9d25213855440cfe Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 17 Oct 2022 16:48:35 -0400 Subject: [PATCH 205/283] Start handling a bunch more messages --- lightningd/onchain_control.c | 33 ++- onchaind/eltoo_onchaind.c | 507 ++++++++++------------------------- onchaind/onchain_types.h | 42 ++- 3 files changed, 205 insertions(+), 377 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 2a506d902744..4385b1dc850a 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -629,25 +629,44 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U return 0; } +/* FIXME if init is the only difference let's de-duplicate */ static unsigned int eltoo_onchain_msg(struct subd *sd, const u8 *msg, const int *fds UNUSED) { enum onchaind_wire t = fromwire_peektype(msg); switch (t) { + /* Only things changed... */ case WIRE_ELTOO_ONCHAIND_INIT_REPLY: handle_eltoo_onchain_init_reply(sd->channel, msg); break; - + /* End Eltoo-related changes */ + case WIRE_ONCHAIND_ALL_IRREVOCABLY_RESOLVED: + handle_irrevocably_resolved(sd->channel, msg); + break; + case WIRE_ONCHAIND_NOTIFY_COIN_MVT: + handle_onchain_log_coin_move(sd->channel, msg); + break; case WIRE_ONCHAIND_BROADCAST_TX: - case WIRE_ONCHAIND_UNWATCH_TX: + handle_onchain_broadcast_tx(sd->channel, msg); + break; + case WIRE_ONCHAIND_UNWATCH_TX: + handle_onchain_unwatch_tx(sd->channel, msg); + break; + case WIRE_ONCHAIND_ANNOTATE_TXIN: + onchain_annotate_txin(sd->channel, msg); + break; + case WIRE_ONCHAIND_ANNOTATE_TXOUT: + onchain_annotate_txout(sd->channel, msg); + break; + case WIRE_ONCHAIND_HTLC_TIMEOUT: + /* FIXME what needs to change for handling? */ + handle_onchain_htlc_timeout(sd->channel, msg); + break; case WIRE_ONCHAIND_EXTRACTED_PREIMAGE: + handle_extracted_preimage(sd->channel, msg); + break; case WIRE_ONCHAIND_MISSING_HTLC_OUTPUT: - case WIRE_ONCHAIND_HTLC_TIMEOUT: - case WIRE_ONCHAIND_ALL_IRREVOCABLY_RESOLVED: case WIRE_ONCHAIND_ADD_UTXO: - case WIRE_ONCHAIND_ANNOTATE_TXIN: - case WIRE_ONCHAIND_ANNOTATE_TXOUT: - case WIRE_ONCHAIND_NOTIFY_COIN_MVT: /* FIXME implement */ abort(); /* We send these, not receive them */ diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index d9cfdf518f4a..b7aa82a73811 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -77,11 +77,11 @@ struct proposed_resolution { struct resolution { struct bitcoin_txid txid; unsigned int depth; - enum tx_type tx_type; + enum eltoo_tx_type tx_type; }; struct tracked_output { - enum tx_type tx_type; + enum eltoo_tx_type tx_type; struct bitcoin_outpoint outpoint; u32 tx_blockheight; /* FIXME: Convert all depths to blocknums, then just get new blk msgs */ @@ -126,13 +126,6 @@ static const char *output_type_name(enum output_type output_type) return "unknown"; } -/* helper to compare output script with our tal'd script */ -static bool wally_tx_output_scripteq(const struct wally_tx_output *out, - const u8 *script) -{ - return memeq(out->script, out->script_len, script, tal_bytelen(script)); -} - static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) { wire_sync_write(REQ_FD, @@ -142,177 +135,6 @@ static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) tal_free(mvt); } -static void record_channel_withdrawal(const struct bitcoin_txid *tx_txid, - struct tracked_output *out, - u32 blockheight, - enum mvt_tag tag) -{ - send_coin_mvt(take(new_onchaind_withdraw(NULL, &out->outpoint, tx_txid, - blockheight, out->sat, tag))); -} - -static void record_external_spend(const struct bitcoin_txid *txid, - struct tracked_output *out, - u32 blockheight, - enum mvt_tag tag) -{ - send_coin_mvt(take(new_coin_external_spend(NULL, &out->outpoint, - txid, blockheight, - out->sat, tag))); -} - -static void record_external_output(const struct bitcoin_outpoint *out, - struct amount_sat amount, - u32 blockheight, - enum mvt_tag tag) -{ - send_coin_mvt(take(new_coin_external_deposit(NULL, out, blockheight, - amount, tag))); -} - -static void record_external_deposit(const struct tracked_output *out, - u32 blockheight, - enum mvt_tag tag) -{ - record_external_output(&out->outpoint, out->sat, blockheight, tag); -} - -static void record_mutual_close(const struct tx_parts *tx, - const u8 *remote_scriptpubkey, - u32 blockheight) -{ - /* FIXME: if we ever change how closes happen, this will - * need to be updated as there's no longer 1 output - * per peer */ - for (size_t i = 0; i < tal_count(tx->outputs); i++) { - struct bitcoin_outpoint out; - - if (!wally_tx_output_scripteq(tx->outputs[i], - remote_scriptpubkey)) - continue; - - out.n = i; - out.txid = tx->txid; - record_external_output(&out, - amount_sat(tx->outputs[i]->satoshi), - blockheight, - TO_THEM); - break; - } -} - - -static void record_channel_deposit(struct tracked_output *out, - u32 blockheight, enum mvt_tag tag) -{ - send_coin_mvt(take(new_onchaind_deposit(NULL, - &out->outpoint, - blockheight, out->sat, - tag))); -} - -static void record_to_us_htlc_fulfilled(struct tracked_output *out, - u32 blockheight) -{ - send_coin_mvt(take(new_onchain_htlc_deposit(NULL, - &out->outpoint, - blockheight, - out->sat, - &out->payment_hash))); -} - -static void record_to_them_htlc_fulfilled(struct tracked_output *out, - u32 blockheight) -{ - - send_coin_mvt(take(new_onchain_htlc_withdraw(NULL, - &out->outpoint, - blockheight, - out->sat, - &out->payment_hash))); -} - -static void record_ignored_wallet_deposit(struct tracked_output *out) -{ - struct bitcoin_outpoint outpoint; - - /* Every spend tx we construct has a single output. */ - bitcoin_txid(out->proposal->tx, &outpoint.txid); - outpoint.n = 0; - - enum mvt_tag tag = TO_WALLET; - if (out->tx_type == OUR_HTLC_TIMEOUT_TX - || out->tx_type == OUR_HTLC_SUCCESS_TX) - tag = HTLC_TX; - else if (out->tx_type == THEIR_REVOKED_UNILATERAL) - tag = PENALTY; - else if (out->tx_type == OUR_UNILATERAL - || out->tx_type == THEIR_UNILATERAL) { - if (out->output_type == OUR_HTLC) - tag = HTLC_TIMEOUT; - } - if (out->output_type == DELAYED_OUTPUT_TO_US) - tag = CHANNEL_TO_US; - - /* Record the in/out through the channel */ - record_channel_deposit(out, out->tx_blockheight, tag); - record_channel_withdrawal(&outpoint.txid, out, 0, IGNORED); -} - -static void record_coin_movements(struct tracked_output *out, - u32 blockheight, - const struct bitcoin_tx *tx, - const struct bitcoin_txid *txid) -{ - /* For 'timeout' htlcs, we re-record them as a deposit - * before we withdraw them again. When the channel closed, - * we reported this as withdrawn (since we didn't know the - * total amount of pending htlcs that are to-them). So - * we have to "deposit" it again before we withdraw it. - * This is just to make the channel account close out nicely - * AND so we can accurately calculate our on-chain fee burden */ - if (out->tx_type == OUR_HTLC_TIMEOUT_TX - || out->tx_type == OUR_HTLC_SUCCESS_TX) - record_channel_deposit(out, blockheight, HTLC_TX); - - if (out->resolved->tx_type == OUR_HTLC_TIMEOUT_TO_US) - record_channel_deposit(out, blockheight, HTLC_TIMEOUT); - - /* there is a case where we've fulfilled an htlc onchain, - * in which case we log a deposit to the channel */ - if (out->resolved->tx_type == THEIR_HTLC_FULFILL_TO_US - || out->resolved->tx_type == OUR_HTLC_SUCCESS_TX) - record_to_us_htlc_fulfilled(out, blockheight); - - /* If it's our to-us and our close, we publish *another* tx - * which spends the output when the timeout ends */ - if (out->tx_type == OUR_UNILATERAL) { - if (out->output_type == DELAYED_OUTPUT_TO_US) - record_channel_deposit(out, blockheight, CHANNEL_TO_US); - else if (out->output_type == OUR_HTLC) { - record_channel_deposit(out, blockheight, HTLC_TIMEOUT); - record_channel_withdrawal(txid, out, blockheight, HTLC_TIMEOUT); - } else if (out->output_type == THEIR_HTLC) - record_channel_withdrawal(txid, out, blockheight, HTLC_FULFILL); - } - - if (out->tx_type == THEIR_REVOKED_UNILATERAL - || out->resolved->tx_type == OUR_PENALTY_TX) - record_channel_deposit(out, blockheight, PENALTY); - - if (out->resolved->tx_type == OUR_DELAYED_RETURN_TO_WALLET - || out->resolved->tx_type == THEIR_HTLC_FULFILL_TO_US - || out->output_type == DELAYED_OUTPUT_TO_US - || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TO_US - || out->resolved->tx_type == OUR_PENALTY_TX) { - /* penalty rbf cases, the amount might be zero */ - if (amount_sat_zero(out->sat)) - record_channel_withdrawal(txid, out, blockheight, TO_MINER); - else - record_channel_withdrawal(txid, out, blockheight, TO_WALLET); - } -} - static u8 *penalty_to_us(const tal_t *ctx, struct bitcoin_tx *tx, const u8 *wscript) @@ -545,7 +367,7 @@ static struct tracked_output * new_tracked_output(struct tracked_output ***outs, const struct bitcoin_outpoint *outpoint, u32 tx_blockheight, - enum tx_type tx_type, + enum eltoo_tx_type tx_type, struct amount_sat sat, enum output_type output_type, const struct htlc_stub *htlc, @@ -741,10 +563,6 @@ static void proposal_meets_depth(struct tracked_output *out) if (!out->proposal->tx) { ignore_output(out); - if (out->proposal->tx_type == THEIR_HTLC_TIMEOUT_TO_THEM) - record_external_deposit(out, out->tx_blockheight, - HTLC_TIMEOUT); - return; } @@ -768,7 +586,6 @@ static void proposal_meets_depth(struct tracked_output *out) /* Don't wait for this if we're ignoring the tiny payment. */ if (out->proposal->tx_type == IGNORING_TINY_PAYMENT) { ignore_output(out); - record_ignored_wallet_deposit(out); } /* Otherwise we will get a callback when it's in a block. */ @@ -856,7 +673,7 @@ static bool resolved_by_proposal(struct tracked_output *out, /* Otherwise, we figure out what happened and then call this. */ static void resolved_by_other(struct tracked_output *out, const struct bitcoin_txid *txid, - enum tx_type tx_type) + enum eltoo_tx_type tx_type) { out->resolved = tal(out, struct resolution); out->resolved->txid = *txid; @@ -870,21 +687,6 @@ static void resolved_by_other(struct tracked_output *out, type_to_string(tmpctx, struct bitcoin_txid, txid)); } -static void unknown_spend(struct tracked_output *out, - const struct tx_parts *tx_parts) -{ - out->resolved = tal(out, struct resolution); - out->resolved->txid = tx_parts->txid; - out->resolved->depth = 0; - out->resolved->tx_type = UNKNOWN_TXTYPE; - - status_broken("Unknown spend of %s/%s by %s", - tx_type_name(out->tx_type), - output_type_name(out->output_type), - type_to_string(tmpctx, struct bitcoin_txid, - &tx_parts->txid)); -} - static bool is_mutual_close(u32 locktime) { /* If we mask update number, this needs to change */ @@ -984,7 +786,7 @@ static void unwatch_txid(const struct bitcoin_txid *txid) wire_sync_write(REQ_FD, take(msg)); } -static void handle_htlc_onchain_fulfill(struct tracked_output *out, +static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, const struct tx_parts *tx_parts, const struct bitcoin_outpoint *htlc_outpoint) { @@ -994,37 +796,21 @@ static void handle_htlc_onchain_fulfill(struct tracked_output *out, struct ripemd160 ripemd; /* Our HTLC, they filled (must be an HTLC-success tx). */ - if (out->tx_type == THEIR_UNILATERAL - || out->tx_type == THEIR_REVOKED_UNILATERAL) { - /* BOLT #3: - * - * ## HTLC-Timeout and HTLC-Success Transactions - * - * ... `txin[0]` witness stack: `0 - * ` for HTLC-success - */ - if (tx_parts->inputs[htlc_outpoint->n]->witness->num_items != 5) /* +1 for wscript */ - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "%s/%s spent with weird witness %zu", - tx_type_name(out->tx_type), - output_type_name(out->output_type), - tx_parts->inputs[htlc_outpoint->n]->witness->num_items); - - preimage_item = &tx_parts->inputs[htlc_outpoint->n]->witness->items[3]; - } else if (out->tx_type == OUR_UNILATERAL) { - /* BOLT #3: - * - * The remote node can redeem the HTLC with the witness: - * - * - */ - if (tx_parts->inputs[htlc_outpoint->n]->witness->num_items != 3) /* +1 for wscript */ + if (out->tx_type == ELTOO_SETTLE + || out->tx_type == ELTOO_INVALIDATED_SETTLE) { + /* BOLTXX + * The recipient node can redeem the HTLC with the witness: + * + * + */ + if (tx_parts->inputs[htlc_outpoint->n]->witness->num_items != 4) /* +2 for script/control block */ status_failed(STATUS_FAIL_INTERNAL_ERROR, "%s/%s spent with weird witness %zu", tx_type_name(out->tx_type), output_type_name(out->output_type), tx_parts->inputs[htlc_outpoint->n]->witness->num_items); + /* FIXME figure out proper index */ preimage_item = &tx_parts->inputs[htlc_outpoint->n]->witness->items[1]; } else status_failed(STATUS_FAIL_INTERNAL_ERROR, @@ -1032,27 +818,6 @@ static void handle_htlc_onchain_fulfill(struct tracked_output *out, tx_type_name(out->tx_type), output_type_name(out->output_type)); - /* cppcheck-suppress uninitvar - doesn't know status_failed exits? */ - if (preimage_item->witness_len != sizeof(preimage)) { - /* It's possible something terrible happened and we broadcast - * an old commitment state, which they're now cleaning up. - * - * We stumble along. - */ - if (out->tx_type == OUR_UNILATERAL - && preimage_item->witness_len == PUBKEY_CMPR_LEN) { - status_unusual("Our cheat attempt failed, they're " - "taking our htlc out (%s)", - type_to_string(tmpctx, struct amount_sat, - &out->sat)); - return; - } - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "%s/%s spent with bad witness length %zu", - tx_type_name(out->tx_type), - output_type_name(out->output_type), - preimage_item->witness_len); - } memcpy(&preimage, preimage_item->witness, sizeof(preimage)); sha256(&sha, &preimage, sizeof(preimage)); ripemd160(&ripemd, &sha, sizeof(sha)); @@ -1095,7 +860,6 @@ static void onchain_annotate_txin(const struct bitcoin_txid *txid, u32 innum, } /* An output has been spent: see if it resolves something we care about. */ -/* FIXME FRIDAY: work through this tracking logic */ static void output_spent(struct tracked_output ***outs, const struct tx_parts *tx_parts, u32 input_num, @@ -1114,16 +878,6 @@ static void output_spent(struct tracked_output ***outs, /* Was this our resolution? */ if (resolved_by_proposal(out, tx_parts)) { - /* If it's our htlc tx, we need to resolve that, too. */ - /* FIXME we can spend htlc immediately? - if (out->resolved->tx_type == OUR_HTLC_SUCCESS_TX - || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX) - resolve_htlc_tx(outs, i, tx_parts, input_num, - tx_blockheight);*/ - - record_coin_movements(out, tx_blockheight, - out->proposal->tx, - &tx_parts->txid); return; } @@ -1132,69 +886,44 @@ static void output_spent(struct tracked_output ***outs, switch (out->output_type) { case OUTPUT_TO_US: + /* FIXME I'm gonna call this the state output, post-funding */ + /* There is no delayed to us... it just goes into our wallet case DELAYED_OUTPUT_TO_US: unknown_spend(out, tx_parts); - record_external_deposit(out, tx_blockheight, PENALIZED); break; - + */ case THEIR_HTLC: - record_external_deposit(out, out->tx_blockheight, - HTLC_TIMEOUT); - record_external_spend(&tx_parts->txid, out, - tx_blockheight, HTLC_TIMEOUT); - - if (out->tx_type == THEIR_REVOKED_UNILATERAL) { - /* FIXME impossible state, no such thing as revoked */ - /* we've actually got a 'new' output here */ - } else { - /* We ignore this timeout tx, since we should - * resolve by ignoring once we reach depth. */ - onchain_annotate_txout( - &htlc_outpoint, - TX_CHANNEL_HTLC_TIMEOUT | TX_THEIRS); - } + /* We ignore this timeout tx, since we should + * resolve by ignoring once we reach depth. */ + onchain_annotate_txout( + &htlc_outpoint, + TX_CHANNEL_HTLC_TIMEOUT | TX_THEIRS); break; case OUR_HTLC: /* The only way they can spend this: fulfill; even * if it's revoked: */ - /* BOLT #5: - * - * ## HTLC Output Handling: Local Commitment, Local Offers - *... - * - MUST extract the payment preimage from the - * transaction input witness. - *... - * ## HTLC Output Handling: Remote Commitment, Local Offers - *... - * - MUST extract the payment preimage from the - * HTLC-success transaction input witness. - */ - handle_htlc_onchain_fulfill(out, tx_parts, + handle_eltoo_htlc_onchain_fulfill(out, tx_parts, &htlc_outpoint); - record_to_them_htlc_fulfilled(out, tx_blockheight); - record_external_spend(&tx_parts->txid, out, - tx_blockheight, HTLC_FULFILL); - - if (out->tx_type == THEIR_REVOKED_UNILATERAL) { - /* FIXME no such thing as revoked */ - } else { - /* BOLT #5: - * - * ## HTLC Output Handling: Local Commitment, - * Local Offers - *... - * - if the commitment transaction HTLC output - * is spent using the payment preimage, the - * output is considered *irrevocably resolved* - */ - ignore_output(out); - - onchain_annotate_txout( - &htlc_outpoint, - TX_CHANNEL_HTLC_SUCCESS | TX_THEIRS); - } + /* FIXME this is impossible, commenting out */ +// if (out->tx_type == THEIR_REVOKED_UNILATERAL) { +// } else { + /* BOLT #5: + * + * ## HTLC Output Handling: Local Commitment, + * Local Offers + *... + * - if the commitment transaction HTLC output + * is spent using the payment preimage, the + * output is considered *irrevocably resolved* + */ + ignore_output(out); + + onchain_annotate_txout( + &htlc_outpoint, + TX_CHANNEL_HTLC_SUCCESS | TX_THEIRS); +// } break; case FUNDING_OUTPUT: @@ -1202,17 +931,11 @@ static void output_spent(struct tracked_output ***outs, * that our old tx was unspent. */ status_failed(STATUS_FAIL_INTERNAL_ERROR, "Funding output spent again!"); - - case DELAYED_CHEAT_OUTPUT_TO_THEM: - /* They successfully spent a delayed revoked output */ - resolved_by_other(out, &tx_parts->txid, - THEIR_DELAYED_CHEAT); - - record_external_deposit(out, tx_blockheight, STOLEN); - break; /* Um, we don't track these! */ case OUTPUT_TO_THEM: case DELAYED_OUTPUT_TO_THEM: + case DELAYED_CHEAT_OUTPUT_TO_THEM: + case DELAYED_OUTPUT_TO_US: case ELEMENTS_FEE: case ANCHOR_TO_US: case ANCHOR_TO_THEM: @@ -1248,18 +971,19 @@ static void update_resolution_depth(struct tracked_output *out, u32 depth) reached_reasonable_depth = (out->resolved->depth < reasonable_depth && depth >= reasonable_depth); - /* BOLT #5: - * - * - if the commitment transaction HTLC output has *timed out* and - * hasn't been *resolved*: - * - MUST *resolve* the output by spending it using the HTLC-timeout - * transaction. - * - once the resolving transaction has reached reasonable depth: - * - MUST fail the corresponding incoming HTLC (if any). - */ - if ((out->resolved->tx_type == OUR_HTLC_TIMEOUT_TX - || out->resolved->tx_type == OUR_HTLC_TIMEOUT_TO_US) - && reached_reasonable_depth) { + /* BOLT #XX: + * + * - if the settlement transaction HTLC output has *timed out* and hasn't been + * *resolved*: + * - MUST *resolve* the output by spending it using their own `settlement_pubkey` to + * any address deemed necessary. + * - once the resolving transaction has reached reasonable depth: + * - MUST fail the corresponding incoming HTLC (if any). + * - for any committed HTLC that has been trimmed: + * - once the update transaction that spent the funding output has reached reasonable depth: + * - MUST fail the corresponding incoming HTLC (if any). + */ + if (out->resolved->tx_type == ELTOO_SWEEP && reached_reasonable_depth) { u8 *msg; status_debug("%s/%s reached reasonable depth %u", tx_type_name(out->tx_type), @@ -1271,22 +995,29 @@ static void update_resolution_depth(struct tracked_output *out, u32 depth) out->resolved->depth = depth; } -static void tx_new_depth(struct tracked_output **outs, +static void eltoo_tx_new_depth(struct tracked_output **outs, const struct bitcoin_txid *txid, u32 depth) { size_t i; - /* Special handling for commitment tx reaching depth */ - if (bitcoin_txid_eq(&outs[0]->resolved->txid, txid) - && depth >= reasonable_depth - && missing_htlc_msgs) { - status_debug("Sending %zu missing htlc messages", - tal_count(missing_htlc_msgs)); - for (i = 0; i < tal_count(missing_htlc_msgs); i++) - wire_sync_write(REQ_FD, missing_htlc_msgs[i]); - /* Don't do it again. */ - missing_htlc_msgs = tal_free(missing_htlc_msgs); - } + /* FIXME React to final update tx getting shared_delay old */ + + /* FIXME React to settlement transaction being mined */ + + /* Special handling for funding-spending update tx reaching depth */ + /* FIXME re-add note_missing_htlcs for TRIMMED ONLY here... should this b + * done immediately, not at "reasonable depth"? + */ + if (bitcoin_txid_eq(&outs[0]->resolved->txid, txid) + && depth >= reasonable_depth + && missing_htlc_msgs) { + status_debug("Sending %zu missing htlc messages", + tal_count(missing_htlc_msgs)); + for (i = 0; i < tal_count(missing_htlc_msgs); i++) + wire_sync_write(REQ_FD, missing_htlc_msgs[i]); + /* Don't do it again. */ + missing_htlc_msgs = tal_free(missing_htlc_msgs); + } for (i = 0; i < tal_count(outs); i++) { /* Update output depth. */ @@ -1305,7 +1036,9 @@ static void tx_new_depth(struct tracked_output **outs, * resolution for? */ if (outs[i]->proposal && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) - && depth >= outs[i]->proposal->depth_required) { + && depth >= outs[i]->proposal->depth_required) { + /* ELTOO: We don't need any delays anywhere */ + assert(outs[i]->proposal->depth_required == 0); proposal_meets_depth(outs[i]); } @@ -1354,7 +1087,7 @@ static void eltoo_handle_preimage(struct tracked_output **outs, * could be due to multiple identical rhashes in tx. */ outs[i]->proposal = tal_free(outs[i]->proposal); - /* FIXME Actually do something with them by looking for an output I can spend immediately */ + /* FIXME now that we know this output exists, we should resolve it */ } } @@ -1398,15 +1131,6 @@ static bool handle_dev_memleak(struct tracked_output **outs, const u8 *msg) } #endif /* !DEVELOPER */ -/* BOLT #5: - * - * A node: - * - once it has broadcast a funding transaction OR sent a commitment signature - * for a commitment transaction that contains an HTLC output: - * - until all outputs are *irrevocably resolved*: - * - MUST monitor the blockchain for transactions that spend any output that - * is NOT *irrevocably resolved*. - */ static void wait_for_resolved(struct tracked_output **outs) { billboard_update(outs); @@ -1427,12 +1151,16 @@ static void wait_for_resolved(struct tracked_output **outs) status_debug("Got new message %s", onchaind_wire_name(fromwire_peektype(msg))); - if (fromwire_onchaind_depth(msg, &txid, &depth)) - tx_new_depth(outs, &txid, depth); + if (fromwire_onchaind_depth(msg, &txid, &depth)) { + eltoo_tx_new_depth(outs, &txid, depth); + } else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num, &tx_blockheight)) { + /* FIXME walk through logic with someone who knows what's going on */ output_spent(&outs, tx_parts, input_num, tx_blockheight); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) + /* FIXME Somehow we should be watching out settlement outputs + even if they haven't entered utxo set. */ eltoo_handle_preimage(outs, &preimage); else if (!handle_dev_memleak(outs, msg)) master_badmsg(-1, msg); @@ -1519,14 +1247,10 @@ static struct htlcs_info *eltoo_init_reply(const tal_t *ctx, const char *what) return htlcs_info; } -static void eltoo_handle_mutual_close(struct tracked_output **outs, - const struct tx_parts *tx) +/* We always assume funding input is first index in outs */ +static int funding_input_num(struct tracked_output **outs, const struct tx_parts *tx) { int i; - - /* In this case, we don't care about htlcs: there are none. */ - eltoo_init_reply(tmpctx, "Tracking mutual close transaction"); - /* Annotate the input that matches the funding outpoint as close. We can currently only have a * single input for these. */ for (i=0; iinputs); i++) { @@ -1536,8 +1260,17 @@ static void eltoo_handle_mutual_close(struct tracked_output **outs, } } assert(i != tal_count(tx->inputs)); + return i; +} - onchain_annotate_txin(&tx->txid, i, TX_CHANNEL_CLOSE); +static void eltoo_handle_mutual_close(struct tracked_output **outs, + const struct tx_parts *tx) +{ + + /* In this case, we don't care about htlcs: there are none. */ + eltoo_init_reply(tmpctx, "Tracking mutual close transaction"); + + onchain_annotate_txin(&tx->txid, funding_input_num(outs, tx), TX_CHANNEL_CLOSE); /* BOLT #5: * @@ -1550,6 +1283,41 @@ static void eltoo_handle_mutual_close(struct tracked_output **outs, wait_for_resolved(outs); } +static void handle_latest_update(const struct tx_parts *tx, + u32 tx_blockheight, + struct tracked_output **outs) +{ + struct htlcs_info *htlcs_info; + struct bitcoin_outpoint outpoint; + struct amount_asset asset; + struct amount_sat amt; + /* State output will match index */ + int state_index = funding_input_num(outs, tx); + + outpoint.txid = tx->txid; + outpoint.n = state_index; + + asset = wally_tx_output_get_amount(tx->outputs[state_index]); + amt = amount_asset_to_sat(&asset); + + htlcs_info = eltoo_init_reply(tmpctx, "Tracking latest update transaction"); + /* FIXME do something with htlcs_info ? */ + assert(htlcs_info); + onchain_annotate_txin(&tx->txid, state_index, TX_CHANNEL_UNILATERAL); + + resolved_by_other(outs[0], &tx->txid, UPDATE); + + new_tracked_output(&outs, + &outpoint, tx_blockheight, + UPDATE, + amt, + DELAYED_OUTPUT_TO_US, + NULL /* htlc */, NULL /* wscript */, NULL /* remote_htlc_sig */); + + /* Wait until we get shared_delay confirms for this output */ + wait_for_resolved(outs); +} + int main(int argc, char *argv[]) { setup_locale(); @@ -1585,6 +1353,9 @@ int main(int argc, char *argv[]) master_badmsg(WIRE_ELTOO_ONCHAIND_INIT, msg); } + // It's not configurable for ln-penalty, just set it here? + reasonable_depth = 3; + status_debug("lightningd_eltoo_onchaind is alive!"); /* We need to keep tx around, but there's only one: not really a leak */ tal_steal(ctx, notleak(spending_tx)); @@ -1614,16 +1385,15 @@ int main(int argc, char *argv[]) if (is_mutual_close(locktime)) { status_debug("Handling mutual close!"); - record_mutual_close(spending_tx, scriptpubkey[REMOTE], - tx_blockheight); eltoo_handle_mutual_close(outs, spending_tx); } else { status_debug("Handling unilateral close!"); if (locktime > unbound_update_tx->wtx->locktime) { - status_debug("Uh-oh, please be nice Mr Counterparty :("); /* Might as well track the state output, see if it ends up in a settlement tx - * So `to_node` values can be harvested, HTLCs rescued OOB with counterparty's help? + * So `to_node` values can be harvested, HTLCs rescued with counterparty's help? + * Or we should immediately report all HTLCs as missing, failing these? */ + status_debug("Uh-oh, please be nice Mr Counterparty :("); } else if (locktime == unbound_update_tx->wtx->locktime) { status_debug("Unilateral close of last state detected"); /* Someday we could maybe negotiate with peer to life back into channel @@ -1633,6 +1403,7 @@ int main(int argc, char *argv[]) * * Either way, this also happens in the "cheating" below, and we handle this identically. */ + handle_latest_update(spending_tx, tx_blockheight, outs); } else { status_debug("Cheater!"); } diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index 3e1e874f90d5..c8cba6e3f5a6 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -51,6 +51,44 @@ enum tx_type { UNKNOWN_TXTYPE }; +/* Different transactions we care about. */ +enum eltoo_tx_type { + /* The initial 2 of 2 funding transaction */ + ELTOO_FUNDING_TRANSACTION, + + /* A mutual close: spends funding */ + ELTOO_MUTUAL_CLOSE, + + /* Unknown unilateral (presumably theirs): spends funding */ + ELTOO_UPDATE, + + /* Old unilateral: spends funding */ + ELTOO_INVALIDATED_UPDATE, + + /* Latest settlement transaction */ + ELTOO_SETTLE, + + /* Invalidated settlement transaction + * Balance output goes straight into wallet, + * all HTLCs have been forgotten. + */ + ELTOO_INVALIDATED_SETTLE, + + /* Sweep of outputs from settlement tx */ + ELTOO_SWEEP, + + /* FIXME should I have more types? */ + + /* Amount too small, we're just spending it to close UTXO */ + ELTOO_IGNORING_TINY_PAYMENT, + + /* Special type for marking outputs as resolved by self. */ + ELTOO_SELF, + + /* Shouldn't happen. */ + ELTOO_UNKNOWN_TXTYPE +}; + /* Different output types. */ enum output_type { /* FUNDING_TRANSACTION */ @@ -64,7 +102,7 @@ enum output_type { DELAYED_CHEAT_OUTPUT_TO_THEM, /* OUR_UNILATERAL, or OUR_HTLC_TIMEOUT_TX */ - DELAYED_OUTPUT_TO_US, + DELAYED_OUTPUT_TO_US, /* Eltoo: state output */ OUTPUT_TO_THEM, /* HTLC outputs: their offers and our offers */ @@ -75,7 +113,7 @@ enum output_type { ELEMENTS_FEE, /* Anchor outputs for option_anchor_outputs */ - ANCHOR_TO_US, + ANCHOR_TO_US, /* Eltoo: ephemeral anchor */ ANCHOR_TO_THEM, }; From f8bef22f28e98a05504d4c69e404280f634953a3 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 14 Nov 2022 10:43:10 -0500 Subject: [PATCH 206/283] Send committed but not completed transactions to lightningd --- channeld/channeld_wire.csv | 3 +++ channeld/eltoo_channeld.c | 25 +++++++++++++++---------- common/initial_channel.h | 4 ++-- lightningd/peer_htlcs.c | 7 ++++++- wallet/test/run-wallet.c | 2 +- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 985e7ef6d9e9..3e50ddeaa1ad 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -392,6 +392,9 @@ msgdata,channeld_sending_updatesig,num_changed,u16, msgdata,channeld_sending_updatesig,changed,changed_htlc,num_changed msgdata,channeld_sending_updatesig,our_update_p_sig,partial_sig, msgdata,channeld_sending_updatesig,session,musig_session, +# Committed but not yet completed +msgdata,channeld_sending_updatesig,update_tx,bitcoin_tx, +msgdata,channeld_sending_updatesig,settle_tx,bitcoin_tx, # Wait for reply, to make sure it's on disk before we send commit. msgtype,channeld_sending_updatesig_reply,1180 diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index ca830f5ba80b..6e44e21889a0 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -661,16 +661,18 @@ static u8 *sending_updatesig_msg(const tal_t *ctx, u64 update_index, const struct htlc **changed_htlcs, const struct partial_sig *our_update_psig, - const struct musig_session *session) + const struct musig_session *session, + const struct bitcoin_tx *committed_update_tx, + const struct bitcoin_tx *committed_settle_tx) { struct changed_htlc *changed; u8 *msg; /* We tell master what (of our) HTLCs we will be - * committed to. */ + * committed to, and of unfinished partial signtures. */ changed = changed_htlc_arr(tmpctx, changed_htlcs); msg = towire_channeld_sending_updatesig(ctx, update_index, - changed, our_update_psig, session); + changed, our_update_psig, session, committed_update_tx, committed_settle_tx); return msg; } @@ -883,8 +885,9 @@ static void send_update(struct eltoo_peer *peer) /* Cache half-signed tx, for finalization when ACK comes back */ /* FIXME delete older first */ - peer->channel->last_unsigned_update = tal_steal(peer->channel, update_and_settle_txs[0]); - peer->channel->last_unsigned_settle = tal_steal(peer->channel, update_and_settle_txs[1]); + /* FIXME these have to be persisted for safety!!! They can appear at any time */ + peer->channel->last_committed_update = tal_steal(peer->channel, update_and_settle_txs[0]); + peer->channel->last_committed_settle = tal_steal(peer->channel, update_and_settle_txs[1]); #if DEVELOPER if (peer->dev_disable_commit) { @@ -899,7 +902,9 @@ static void send_update(struct eltoo_peer *peer) msg = sending_updatesig_msg(NULL, peer->next_index, changed_htlcs, &peer->channel->eltoo_keyset.self_psig, - &peer->channel->eltoo_keyset.session); + &peer->channel->eltoo_keyset.session, + peer->channel->last_committed_update, + peer->channel->last_committed_update); /* Message is empty; receiving it is the point. */ master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNELD_SENDING_UPDATESIG_REPLY); @@ -1227,8 +1232,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) status_debug("partial signature combine req on update tx %s, settle tx %s, our_psig: %s," " their_psig: %s, session %s, OLD our nonce %s, OLD their nonce %s", - type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_unsigned_update), - type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_unsigned_settle), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_committed_update), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_committed_settle), type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.other_psig), type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.session), @@ -1243,8 +1248,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.session, - peer->channel->last_unsigned_update, - peer->channel->last_unsigned_settle, + peer->channel->last_committed_update, + peer->channel->last_committed_settle, &peer->channel->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(comb_msg)); comb_msg = wire_sync_read(tmpctx, HSM_FD); diff --git a/common/initial_channel.h b/common/initial_channel.h index 7774ce8d2aeb..0811d34273b0 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -82,8 +82,8 @@ struct channel { u64 update_number_obscurer; /* Cached transactions waiting for counter-sign via `update_signed_ack` */ - struct bitcoin_tx *last_unsigned_update; - struct bitcoin_tx *last_unsigned_settle; + struct bitcoin_tx *last_committed_update; + struct bitcoin_tx *last_committed_settle; /* End Eltoo fields*/ diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 31131720af48..bee4670e6fae 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -2014,11 +2014,16 @@ void peer_sending_updatesig(struct channel *channel, const u8 *msg) /* These are unused currently... */ struct partial_sig our_update_psig; struct musig_session session; + struct bitcoin_tx *committed_update_tx; + struct bitcoin_tx *committed_settle_tx; if (!fromwire_channeld_sending_updatesig(msg, msg, &update_num, &changed_htlcs, - &our_update_psig, &session)) { + &our_update_psig, + &session, + &committed_update_tx, + &committed_settle_tx)) { channel_internal_error(channel, "bad channel_sending_updatesig %s", tal_hex(channel, msg)); return; diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 889743686ecf..bfe1d14faab3 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -165,7 +165,7 @@ bool fromwire_channeld_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p bool fromwire_channeld_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct penalty_base **pbase UNNEEDED, struct fee_states **fee_states UNNEEDED, struct height_states **blockheight_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_signature *commit_sig UNNEEDED, struct bitcoin_signature **htlc_sigs UNNEEDED) { fprintf(stderr, "fromwire_channeld_sending_commitsig called!\n"); abort(); } /* Generated stub for fromwire_channeld_sending_updatesig */ -bool fromwire_channeld_sending_updatesig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *update_num UNNEEDED, struct changed_htlc **changed UNNEEDED, struct partial_sig *our_update_p_sig UNNEEDED, struct musig_session *session UNNEEDED) +bool fromwire_channeld_sending_updatesig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *update_num UNNEEDED, struct changed_htlc **changed UNNEEDED, struct partial_sig *our_update_p_sig UNNEEDED, struct musig_session *session UNNEEDED, struct bitcoin_tx **update_tx UNNEEDED, struct bitcoin_tx **settle_tx UNNEEDED) { fprintf(stderr, "fromwire_channeld_sending_updatesig called!\n"); abort(); } /* Generated stub for fromwire_connectd_peer_active */ bool fromwire_connectd_peer_active(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, u16 **msgtype UNNEEDED, struct channel_id *channel_id UNNEEDED) From 0ac56c52b3cde42838a36c9a666ca02bfab010b8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 14 Nov 2022 16:28:09 -0500 Subject: [PATCH 207/283] moved around tx signing state to aid support for committed but not complete states --- channeld/channeld_wire.csv | 3 ++ channeld/eltoo_channeld.c | 90 +++++++++++++++++++--------------- channeld/eltoo_full_channel.c | 10 ++-- channeld/eltoo_full_channel.h | 10 ++-- common/initial_eltoo_channel.c | 11 ++--- common/initial_eltoo_channel.h | 10 ++-- common/keyset.h | 16 +++++- lightningd/channel.c | 16 +++--- lightningd/channel.h | 5 +- lightningd/channel_control.c | 9 ++-- lightningd/opening_control.c | 49 ++++++++---------- lightningd/peer_control.c | 12 ++--- openingd/eltoo_openingd.c | 67 +++++++++++++------------ wallet/test/run-wallet.c | 5 +- wallet/wallet.c | 11 ++--- 15 files changed, 168 insertions(+), 156 deletions(-) diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 3e50ddeaa1ad..c5998fdaa409 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -291,6 +291,9 @@ msgdata,channeld_init_eltoo,their_config,channel_config, msgdata,channeld_init_eltoo,their_update_psig,partial_sig, msgdata,channeld_init_eltoo,our_update_psig,partial_sig, msgdata,channeld_init_eltoo,session,musig_session, +msgdata,channeld_init_eltoo,their_committed_psig,partial_sig, +msgdata,channeld_init_eltoo,our_committed_psig,partial_sig, +msgdata,channeld_init_eltoo,committed_session,musig_session, msgdata,channeld_init_eltoo,their_next_nonce,nonce, msgdata,channeld_init_eltoo,our_next_nonce,nonce, msgdata,channeld_init_eltoo,their_funding_pubkey,pubkey, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 6e44e21889a0..4ca3292bf339 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -846,7 +846,7 @@ static void send_update(struct eltoo_peer *peer) &peer->channel->eltoo_keyset.self_next_nonce); status_debug("partial signature req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", - type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), type_to_string(tmpctx, struct pubkey, @@ -861,14 +861,14 @@ static void send_update(struct eltoo_peer *peer) &peer->channel->eltoo_keyset.other_next_nonce)); hsmd_msg = hsm_req(tmpctx, take(msg)); - if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) + if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Reading psign_update_tx reply: %s", tal_hex(tmpctx, msg)); /* We don't learn their new nonce until we get ACK... */ status_debug("partial signature %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, OLD their nonce %s, session %s", - type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), type_to_string(tmpctx, struct pubkey, @@ -881,13 +881,16 @@ static void send_update(struct eltoo_peer *peer) &peer->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, &peer->channel->eltoo_keyset.other_next_nonce), - type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.session)); + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session)); /* Cache half-signed tx, for finalization when ACK comes back */ /* FIXME delete older first */ /* FIXME these have to be persisted for safety!!! They can appear at any time */ peer->channel->last_committed_update = tal_steal(peer->channel, update_and_settle_txs[0]); peer->channel->last_committed_settle = tal_steal(peer->channel, update_and_settle_txs[1]); + /* FIXME switch over to using this */ + peer->channel->eltoo_keyset.last_committed_state.update_tx = peer->channel->last_committed_update; + peer->channel->eltoo_keyset.last_committed_state.settle_tx = peer->channel->last_committed_settle; #if DEVELOPER if (peer->dev_disable_commit) { @@ -901,8 +904,8 @@ static void send_update(struct eltoo_peer *peer) /* Tell master to save this next commit to database, then wait. */ msg = sending_updatesig_msg(NULL, peer->next_index, changed_htlcs, - &peer->channel->eltoo_keyset.self_psig, - &peer->channel->eltoo_keyset.session, + &peer->channel->eltoo_keyset.last_committed_state.self_psig, + &peer->channel->eltoo_keyset.last_committed_state.session, peer->channel->last_committed_update, peer->channel->last_committed_update); /* Message is empty; receiving it is the point. */ @@ -914,7 +917,7 @@ static void send_update(struct eltoo_peer *peer) peer->next_index++; msg = towire_update_signed(NULL, &peer->channel_id, - &peer->channel->eltoo_keyset.self_psig, + &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.self_next_nonce); peer_write(peer->pps, take(msg)); @@ -937,9 +940,11 @@ static void start_update_timer(struct eltoo_peer *peer) send_update, peer); } -static u8 *make_update_signed_ack_msg(const struct eltoo_peer *peer) +static u8 *make_update_signed_ack_msg(const struct eltoo_peer *peer, + const struct partial_sig *our_update_psig, + const struct nonce *next_nonce) { - return towire_update_signed_ack(peer, &peer->channel_id, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.self_next_nonce); + return towire_update_signed_ack(peer, &peer->channel_id, our_update_psig, next_nonce); } /* Convert changed htlcs into parts which lightningd expects. */ @@ -1022,7 +1027,7 @@ static void send_update_sign_ack(struct eltoo_peer *peer, &failed, &added); - msg = make_update_signed_ack_msg(peer); + msg = make_update_signed_ack_msg(peer, our_update_psig, &peer->channel->eltoo_keyset.self_next_nonce); /* From now on we apply changes to the next commitment */ peer->next_index++; @@ -1084,7 +1089,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) } if (!fromwire_update_signed(msg, - &channel_id, &peer->channel->eltoo_keyset.other_psig, &their_next_nonce)) + &channel_id, &peer->channel->eltoo_keyset.last_committed_state.other_psig, &their_next_nonce)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad update_signed %s", tal_hex(msg, msg)); @@ -1107,7 +1112,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.self_next_nonce); status_debug("partial signature req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", - type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), type_to_string(tmpctx, struct pubkey, @@ -1126,13 +1131,13 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.self_psig, &peer->channel->eltoo_keyset.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); status_debug("partial signature combine our_psig %s their_psig %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s, session %s", - type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), - type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.other_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.other_psig), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), type_to_string(tmpctx, struct pubkey, @@ -1145,14 +1150,14 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, &peer->channel->eltoo_keyset.other_next_nonce), - type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.session)); + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session)); /* Before replying, make sure signature is correct */ msg = towire_hsmd_combine_psig(NULL, &peer->channel_id, - &peer->channel->eltoo_keyset.self_psig, - &peer->channel->eltoo_keyset.other_psig, - &peer->channel->eltoo_keyset.session, + &peer->channel->eltoo_keyset.last_committed_state.self_psig, + &peer->channel->eltoo_keyset.last_committed_state.other_psig, + &peer->channel->eltoo_keyset.last_committed_state.session, update_and_settle_txs[0], update_and_settle_txs[1], &peer->channel->eltoo_keyset.inner_pubkey); @@ -1163,6 +1168,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); } + /* Now that we've checked the update, migrate all signing state from last_committed_state to last_complete_state */ + peer->channel->eltoo_keyset.last_complete_state = peer->channel->eltoo_keyset.last_committed_state; /* FIXME do we just bump on lightningd side? We are about to send an update, increment HTLCs to sent state this was aping peer_sending_revocation @@ -1175,9 +1182,9 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) a single connection to peer! */ send_update_sign_ack(peer, changed_htlcs, - &peer->channel->eltoo_keyset.self_psig, - &peer->channel->eltoo_keyset.other_psig, - &peer->channel->eltoo_keyset.session, + &peer->channel->eltoo_keyset.last_complete_state.self_psig, + &peer->channel->eltoo_keyset.last_complete_state.other_psig, + &peer->channel->eltoo_keyset.last_complete_state.session, update_and_settle_txs[0], update_and_settle_txs[1]); @@ -1222,7 +1229,7 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) struct bip340sig update_sig; const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); - if (!fromwire_update_signed_ack(msg, &channel_id, &peer->channel->eltoo_keyset.other_psig, + if (!fromwire_update_signed_ack(msg, &channel_id, &peer->channel->eltoo_keyset.last_committed_state.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) { peer_failed_warn(peer->pps, &peer->channel_id, "Bad update_signed_ack %s", tal_hex(msg, msg)); @@ -1234,9 +1241,9 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) " their_psig: %s, session %s, OLD our nonce %s, OLD their nonce %s", type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_committed_update), type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_committed_settle), - type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.self_psig), - type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.other_psig), - type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.session), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.other_psig), + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session), type_to_string(tmpctx, struct nonce, &peer->channel->eltoo_keyset.self_next_nonce), type_to_string(tmpctx, struct nonce, @@ -1245,9 +1252,9 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) /* This ACK should be for the transaction we sent them in update_signed, used cached */ comb_msg = towire_hsmd_combine_psig(tmpctx, &channel_id, - &peer->channel->eltoo_keyset.self_psig, - &peer->channel->eltoo_keyset.other_psig, - &peer->channel->eltoo_keyset.session, + &peer->channel->eltoo_keyset.last_committed_state.self_psig, + &peer->channel->eltoo_keyset.last_committed_state.other_psig, + &peer->channel->eltoo_keyset.last_committed_state.session, peer->channel->last_committed_update, peer->channel->last_committed_settle, &peer->channel->eltoo_keyset.inner_pubkey); @@ -1259,6 +1266,9 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) "Bad hsmd_combine_psig_reply: %s", tal_hex(tmpctx, comb_msg)); + /* Update looks good, move completed state over */ + peer->channel->eltoo_keyset.last_complete_state = peer->channel->eltoo_keyset.last_committed_state; + /* We start timer even if this returns false: we might have delayed * commit because we were waiting for this! */ if (channel_rcvd_update_sign_ack(peer->channel, &changed_htlcs)) { @@ -1270,8 +1280,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) /* Tell master about things this locks in(and final signature), wait for response */ msg = got_signed_ack_msg(peer, peer->next_index, - changed_htlcs, &peer->channel->eltoo_keyset.other_psig, &peer->channel->eltoo_keyset.self_psig, - &peer->channel->eltoo_keyset.session); + changed_htlcs, &peer->channel->eltoo_keyset.last_complete_state.other_psig, &peer->channel->eltoo_keyset.last_complete_state.self_psig, + &peer->channel->eltoo_keyset.last_complete_state.session); master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNELD_GOT_ACK_REPLY); @@ -2162,9 +2172,9 @@ static void init_channel(struct eltoo_peer *peer) struct amount_msat local_msat; struct pubkey funding_pubkey[NUM_SIDES]; struct pubkey settle_pubkey[NUM_SIDES]; - struct partial_sig psigs[NUM_SIDES]; + struct eltoo_sign complete_state; + struct eltoo_sign committed_state; struct nonce nonces[NUM_SIDES]; - struct musig_session session; struct channel_config conf[NUM_SIDES]; struct bitcoin_outpoint funding; enum side opener; @@ -2196,9 +2206,12 @@ static void init_channel(struct eltoo_peer *peer) &funding_sats, &minimum_depth, &conf[LOCAL], &conf[REMOTE], - &psigs[REMOTE], - &psigs[LOCAL], - &session, + &complete_state.other_psig, + &complete_state.self_psig, + &complete_state.session, + &committed_state.other_psig, + &committed_state.self_psig, + &committed_state.session, &nonces[REMOTE], &nonces[LOCAL], &funding_pubkey[REMOTE], @@ -2291,9 +2304,8 @@ static void init_channel(struct eltoo_peer *peer) &funding_pubkey[REMOTE], &settle_pubkey[LOCAL], &settle_pubkey[REMOTE], - &psigs[LOCAL], - &psigs[REMOTE], - &session, + &complete_state, + &committed_state, take(channel_type), feature_offered(peer->their_features, OPT_LARGE_CHANNELS), diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c index 292adf2deead..9e969f11addc 100644 --- a/channeld/eltoo_full_channel.c +++ b/channeld/eltoo_full_channel.c @@ -95,9 +95,8 @@ struct channel *new_full_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, - const struct partial_sig *self_psig, - const struct partial_sig *other_psig, - const struct musig_session *session, + const struct eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, const struct channel_type *type TAKES, bool option_wumbo, enum side opener) @@ -113,9 +112,8 @@ struct channel *new_full_eltoo_channel(const tal_t *ctx, remote_funding_pubkey, local_settle_pubkey, remote_settle_pubkey, - self_psig, - other_psig, - session, + complete_state, + committed_state, type, option_wumbo, opener); diff --git a/channeld/eltoo_full_channel.h b/channeld/eltoo_full_channel.h index 47c946d230af..efde7169b241 100644 --- a/channeld/eltoo_full_channel.h +++ b/channeld/eltoo_full_channel.h @@ -24,9 +24,8 @@ struct existing_htlc; * @remote_fundingkey: remote funding key * @local_settle_pubkey: local settlement key * @remote_settle_pubkey: remote settlement key - * @self_psig: local partial signature for reestablishment only - * @other_psig: remote partial signature for reestablishment only - * @session: musig session for reestablishment only + * @complete_state: MuSig signing state for sessions that are complete + * @committed_state: MuSig signing state for incomplete sessions * @type: type for this channel * @option_wumbo: large channel negotiated. * @opener: which side initiated it. @@ -45,9 +44,8 @@ struct channel *new_full_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, - const struct partial_sig *self_psig, - const struct partial_sig *other_psig, - const struct musig_session *session, + const struct eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, const struct channel_type *type TAKES, bool option_wumbo, enum side opener); diff --git a/common/initial_eltoo_channel.c b/common/initial_eltoo_channel.c index ca7f6cd0a588..7e3fab70a748 100644 --- a/common/initial_eltoo_channel.c +++ b/common/initial_eltoo_channel.c @@ -24,9 +24,8 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, - const struct partial_sig *self_psig, - const struct partial_sig *other_psig, - const struct musig_session *session, + const struct eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, const struct channel_type *type TAKES, bool option_wumbo, enum side opener) @@ -51,10 +50,8 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, channel->eltoo_keyset.other_funding_key = *remote_funding_pubkey; channel->eltoo_keyset.self_settle_key = *local_settle_pubkey; channel->eltoo_keyset.other_settle_key = *remote_settle_pubkey; - channel->eltoo_keyset.self_psig = *self_psig; - channel->eltoo_keyset.other_psig = *other_psig; - channel->eltoo_keyset.session = *session; - + channel->eltoo_keyset.last_complete_state = *complete_state; + channel->eltoo_keyset.last_committed_state = *committed_state; channel->htlcs = NULL; pubkey_ptrs[0] = local_funding_pubkey; diff --git a/common/initial_eltoo_channel.h b/common/initial_eltoo_channel.h index 61fda747f72d..1d7f07eeeb12 100644 --- a/common/initial_eltoo_channel.h +++ b/common/initial_eltoo_channel.h @@ -30,9 +30,8 @@ struct fulfilled_htlc; * @remote_funding_pubkey: remote funding key * @local_settle_pubkey: local settlement key * @remote_settle_key: remote settlement key - * @self_psig: local partial signature for reestablishment only - * @other_psig: remote partial signature for reestablishment only - * @session: musig session for reestablishment only + * @complete_state: MuSig signing state for which we have all sigs + * @committed_sate: MuSig signing state for which we have incomplete sigs * @type: type for this channel * @option_wumbo: has peer currently negotiated wumbo? * @opener: which side initiated it. @@ -51,9 +50,8 @@ struct channel *new_initial_eltoo_channel(const tal_t *ctx, const struct pubkey *remote_funding_pubkey, const struct pubkey *local_settle_pubkey, const struct pubkey *remote_settle_pubkey, - const struct partial_sig *self_psig, - const struct partial_sig *other_psig, - const struct musig_session *session, + const struct eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, const struct channel_type *type TAKES, bool option_wumbo, enum side opener); diff --git a/common/keyset.h b/common/keyset.h index db44b60cce7b..2cecab63c519 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -14,6 +14,14 @@ struct keyset { struct pubkey self_payment_key, other_payment_key; }; +/* Holds all information for a particular state being signed */ +struct eltoo_sign { + struct bitcoin_tx *update_tx; + struct bitcoin_tx *settle_tx; + struct partial_sig self_psig, other_psig; + struct musig_session session; +}; + /* Keys needed to derive a particular update/settlement tx pair. */ struct eltoo_keyset { struct pubkey self_settle_key, other_settle_key; @@ -22,8 +30,12 @@ struct eltoo_keyset { non-empty once partial sig created locally! */ struct pubkey inner_pubkey; struct nonce self_next_nonce, other_next_nonce; - struct partial_sig self_psig, other_psig; - struct musig_session session; + /* State we can go to chain with at any point. */ + struct eltoo_sign last_complete_state; + /* State we have committed to but have incomplete signatures for. + * This may be used in channel reestablishment or for reacting + to the appearance of the state on-chain. */ + struct eltoo_sign last_committed_state; }; /* Self == owner of commitment tx, other == non-owner. */ diff --git a/lightningd/channel.c b/lightningd/channel.c index 3779bc592ca9..1e9af0ffb05e 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -395,9 +395,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, struct bitcoin_tx *settle_tx, - struct partial_sig *their_psig, - struct partial_sig *our_psig, - struct musig_session *session, + struct eltoo_sign *last_committed_state, + struct eltoo_sign *last_complete_state, struct nonce *their_next_nonce, struct nonce *our_next_nonce) { @@ -457,9 +456,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, assert(settle_tx); channel->last_settle_tx = tal_steal(channel, settle_tx); channel->last_settle_tx->chainparams = chainparams; - channel->eltoo_keyset.other_psig = *their_psig; - channel->eltoo_keyset.self_psig = *our_psig; - channel->eltoo_keyset.session = *session; + channel->eltoo_keyset.last_committed_state = *last_committed_state; + channel->eltoo_keyset.last_complete_state = *last_complete_state; channel->eltoo_keyset.other_next_nonce = *their_next_nonce; channel->eltoo_keyset.self_next_nonce = *our_next_nonce; } @@ -706,9 +704,9 @@ void channel_set_last_eltoo_txs(struct channel *channel, tal_free(channel->last_settle_tx); channel->last_settle_tx = tal_steal(channel, settle_tx); - channel->eltoo_keyset.other_psig = *their_psig; - channel->eltoo_keyset.self_psig = *our_psig; - channel->eltoo_keyset.session = *session; + channel->eltoo_keyset.last_committed_state.other_psig = *their_psig; + channel->eltoo_keyset.last_committed_state.self_psig = *our_psig; + channel->eltoo_keyset.last_committed_state.session = *session; } void channel_set_state(struct channel *channel, diff --git a/lightningd/channel.h b/lightningd/channel.h index c50249ff6977..e894a4365d1a 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -328,9 +328,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, struct bitcoin_tx *settle_tx, - struct partial_sig *their_psig, - struct partial_sig *our_psig, - struct musig_session *session, + struct eltoo_sign *last_committed_state, + struct eltoo_sign *last_complete_state, struct nonce *their_next_nonce, struct nonce *our_next_nonce); diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 12befba6627d..1a91606e66f4 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -739,9 +739,12 @@ void peer_start_eltoo_channeld(struct channel *channel, channel->minimum_depth, &channel->our_config, &channel->channel_info.their_config, - &channel->eltoo_keyset.other_psig, - &channel->eltoo_keyset.self_psig, - &channel->eltoo_keyset.session, + &channel->eltoo_keyset.last_complete_state.other_psig, + &channel->eltoo_keyset.last_complete_state.self_psig, + &channel->eltoo_keyset.last_complete_state.session, + &channel->eltoo_keyset.last_committed_state.other_psig, + &channel->eltoo_keyset.last_committed_state.self_psig, + &channel->eltoo_keyset.last_committed_state.session, &channel->eltoo_keyset.other_next_nonce, &channel->eltoo_keyset.self_next_nonce, &channel->channel_info.remote_fundingkey, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index c5ad25d7f577..60706a13d461 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -94,9 +94,8 @@ wallet_commit_channel(struct lightningd *ld, const u8 *remote_upfront_shutdown_script, const struct channel_type *type, struct bitcoin_tx *settle_tx, - struct partial_sig *their_psig, - struct partial_sig *our_psig, - struct musig_session *session, + struct eltoo_sign *complete_state, + struct eltoo_sign *committed_state, struct nonce *their_next_nonce, struct nonce *our_next_nonce) { @@ -222,9 +221,8 @@ wallet_commit_channel(struct lightningd *ld, ld->config.htlc_minimum_msat, ld->config.htlc_maximum_msat, settle_tx, - their_psig, - our_psig, - session, + complete_state, + committed_state, their_next_nonce, our_next_nonce); @@ -367,8 +365,8 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, u8 *remote_upfront_shutdown_script; struct peer_fd *peer_fd; struct channel_type *type; - struct partial_sig their_psig, our_psig; - struct musig_session session; + /* Committed state is blank */ + struct eltoo_sign complete_state, dummy_committed_state; struct nonce their_next_nonce, our_next_nonce; /* This is a new channel_info.their_config so set its ID to 0 */ @@ -381,9 +379,9 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, &fc->uc->minimum_depth, &channel_info.remote_fundingkey, &channel_info.theirbase.payment, - &their_psig, - &our_psig, - &session, + &complete_state.other_psig, + &complete_state.self_psig, + &complete_state.session, &their_next_nonce, &our_next_nonce, &funding, @@ -428,9 +426,8 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, remote_upfront_shutdown_script, type, settle_tx, - &their_psig, - &our_psig, - &session, + &complete_state, + &dummy_committed_state, &their_next_nonce, &our_next_nonce); if (!channel) { @@ -524,9 +521,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, remote_upfront_shutdown_script, type, NULL /* settle_tx */, - NULL /* their_psig */, - NULL /* our_psig */, - NULL /* session */, + NULL /* complete_state */, + NULL /* committed_state */, NULL /* their_next_nonce */, NULL /* our_next_nonce */); if (!channel) { @@ -568,8 +564,7 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, struct peer_fd *peer_fd; struct channel_type *type; - struct partial_sig their_psig, our_psig; - struct musig_session session; + struct eltoo_sign complete_state, dummy_committed_state; struct nonce their_next_nonce, our_next_nonce; log_debug(uc->log, "Got opening_eltoo_fundee_finish_response"); @@ -585,9 +580,9 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, &settle_tx, &channel_info.remote_fundingkey, &channel_info.theirbase.payment, - &their_psig, - &our_psig, - &session, + &complete_state.other_psig, + &complete_state.self_psig, + &complete_state.session, &their_next_nonce, &our_next_nonce, &funding, @@ -636,9 +631,8 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, remote_upfront_shutdown_script, type, settle_tx, - &their_psig, - &our_psig, - &session, + &complete_state, + &dummy_committed_state, &their_next_nonce, &our_next_nonce); @@ -747,9 +741,8 @@ static void opening_fundee_finished(struct subd *openingd, remote_upfront_shutdown_script, type, NULL /* settle_tx */, - NULL /* their_psig */, - NULL /* our_psig */, - NULL /* session */, + NULL /* complete_state */, + NULL /* committed_state */, NULL /* their_next_nonce */, NULL /* our_next_nonce */); if (!channel) { diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 8192143e533a..f49ecde1309b 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -241,11 +241,11 @@ static void eltoo_finalize_and_send_last(struct lightningd *ld, struct channel * bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->last_tx, &channel->funding, channel->last_settle_tx, - &channel->eltoo_keyset.self_psig, - &channel->eltoo_keyset.other_psig, + &channel->eltoo_keyset.last_complete_state.self_psig, + &channel->eltoo_keyset.last_complete_state.other_psig, &channel->local_funding_pubkey, &channel->channel_info.remote_fundingkey, - &channel->eltoo_keyset.session); + &channel->eltoo_keyset.last_complete_state.session); /* N.B. txid instability possible with eltoo, need to handle? */ bitcoin_txid(bound_update_and_settle_txs[0], &txid); @@ -1007,11 +1007,11 @@ static void json_add_channel(struct lightningd *ld, bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->last_tx, &channel->funding, channel->last_settle_tx, - &channel->eltoo_keyset.self_psig, - &channel->eltoo_keyset.other_psig, + &channel->eltoo_keyset.last_complete_state.self_psig, + &channel->eltoo_keyset.last_complete_state.other_psig, &channel->local_funding_pubkey, &channel->channel_info.remote_fundingkey, - &channel->eltoo_keyset.session); + &channel->eltoo_keyset.last_complete_state.session); json_add_tx(response, "last_update_tx", bound_update_and_settle_txs[0]); json_add_tx(response, "last_settle_tx", bound_update_and_settle_txs[1]); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index 87ff768e242e..d93b5cd56a8d 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -465,8 +465,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, struct bip340sig update_sig; /* Dummy fields since they're unused at time of channel creation */ - struct partial_sig dummy_self_psig, dummy_other_psig; - struct musig_session dummy_session; + struct eltoo_sign dummy_complete_state; + struct eltoo_sign dummy_committed_state; /*~ Channel is ready; Report the channel parameters to the signer. */ msg = towire_hsmd_ready_eltoo_channel(NULL, @@ -521,9 +521,8 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->their_funding_pubkey, &state->our_settlement_pubkey, &state->their_settlement_pubkey, - &dummy_self_psig, - &dummy_other_psig, - &dummy_session, + &dummy_complete_state, + &dummy_committed_state, state->channel_type, feature_offered(state->their_features, OPT_LARGE_CHANNELS), @@ -595,15 +594,15 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, &state->channel->eltoo_keyset.other_next_nonce)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &state->channel->eltoo_keyset.self_psig, - &state->channel->eltoo_keyset.session, &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &state->channel->eltoo_keyset.last_committed_state.self_psig, + &state->channel->eltoo_keyset.last_committed_state.session, &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); /* You can tell this has been a problem before, since there's a debug * message here: */ status_debug("partial signature %s on tx %s using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, OLD their nonce %s", - type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.last_committed_state.self_psig), type_to_string(tmpctx, struct bitcoin_tx, *update_tx), type_to_string(tmpctx, struct pubkey, &state->our_funding_pubkey), @@ -621,7 +620,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, msg = towire_funding_created_eltoo(state, &state->channel_id, &state->funding.txid, state->funding.n, - &state->channel->eltoo_keyset.self_psig, + &state->channel->eltoo_keyset.last_committed_state.self_psig, &state->channel->eltoo_keyset.self_next_nonce); peer_write(state->pps, msg); @@ -644,7 +643,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, if (!msg) return false; - if (!fromwire_funding_signed_eltoo(msg, &id_in, &state->channel->eltoo_keyset.other_psig, &state->channel->eltoo_keyset.other_next_nonce)) + if (!fromwire_funding_signed_eltoo(msg, &id_in, &state->channel->eltoo_keyset.last_committed_state.other_psig, &state->channel->eltoo_keyset.other_next_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_signed_eltoo: %s", tal_hex(msg, msg)); @@ -699,9 +698,9 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ msg = towire_hsmd_combine_psig(NULL, &state->channel_id, - &state->channel->eltoo_keyset.self_psig, - &state->channel->eltoo_keyset.other_psig, - &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.last_committed_state.self_psig, + &state->channel->eltoo_keyset.last_committed_state.other_psig, + &state->channel->eltoo_keyset.last_committed_state.session, *update_tx, *settle_tx, &state->channel->eltoo_keyset.inner_pubkey); @@ -712,6 +711,9 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, "Bad combine_psig_reply_reply %s", tal_hex(tmpctx, msg)); } + /* Update succeeded, migrate over signing state from last_committed_state to last_complete_state */ + state->channel->eltoo_keyset.last_complete_state = state->channel->eltoo_keyset.last_committed_state; + /* State is sent back to master later */ peer_billboard(false, "Funding channel: opening negotiation succeeded"); @@ -750,9 +752,9 @@ static u8 *funder_channel_complete(struct eltoo_state *state) state->minimum_depth, &state->channel->eltoo_keyset.other_funding_key, &state->channel->eltoo_keyset.other_settle_key, - &state->channel->eltoo_keyset.other_psig, - &state->channel->eltoo_keyset.self_psig, - &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.last_complete_state.other_psig, + &state->channel->eltoo_keyset.last_complete_state.self_psig, + &state->channel->eltoo_keyset.last_complete_state.session, &state->channel->eltoo_keyset.other_next_nonce, &state->channel->eltoo_keyset.self_next_nonce, &state->funding, @@ -774,13 +776,13 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; struct tlv_open_channel_eltoo_tlvs *open_tlvs; struct wally_tx_output *direct_outputs[NUM_SIDES]; - struct partial_sig their_update_psig; /* Stored here before channel struct is made, then copied in */ struct nonce their_second_nonce; /* Dummy fields since they're unused at time of channel creation */ - struct partial_sig dummy_self_psig; - struct musig_session dummy_session; + struct eltoo_sign dummy_complete_state; + + struct eltoo_sign committed_state; /* BOLT #2: * @@ -957,7 +959,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) if (!fromwire_funding_created_eltoo(msg, &id_in, &state->funding.txid, &funding_txout, - &their_update_psig, + &committed_state.other_psig, &their_second_nonce)) peer_failed_err(state->pps, &state->channel_id, "Parsing funding_created"); @@ -1009,9 +1011,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) &state->their_funding_pubkey, &state->our_settlement_pubkey, &state->their_settlement_pubkey, - &dummy_self_psig, - &their_update_psig, - &dummy_session, + &dummy_complete_state, + &committed_state, state->channel_type, feature_offered(state->their_features, OPT_LARGE_CHANNELS), @@ -1117,7 +1118,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) msg = wire_sync_read(tmpctx, HSM_FD); /* Reply puts next nonce into keyset and xmitted with funding_signed_eltoo */ if (!fromwire_hsmd_psign_update_tx_reply(msg, - &state->channel->eltoo_keyset.self_psig, &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.last_committed_state.self_psig, &state->channel->eltoo_keyset.last_committed_state.session, &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -1127,7 +1128,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) state->channel->eltoo_keyset.other_next_nonce = their_second_nonce; status_debug("partial signature %s on tx %s using our keys %s:%s, their keys %s:%s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s", - type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.self_psig), + type_to_string(tmpctx, struct partial_sig, &state->channel->eltoo_keyset.last_committed_state.self_psig), type_to_string(tmpctx, struct bitcoin_tx, update_tx), type_to_string(tmpctx, struct pubkey, &state->channel->eltoo_keyset.self_funding_key), @@ -1147,9 +1148,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* Now that it's signed by both sides, we check if it's valid signature, get full sig back */ msg = towire_hsmd_combine_psig(NULL, &state->channel_id, - &state->channel->eltoo_keyset.self_psig, - &their_update_psig, - &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.last_committed_state.self_psig, + &state->channel->eltoo_keyset.last_committed_state.other_psig, + &state->channel->eltoo_keyset.last_committed_state.session, update_tx, settle_tx, &state->channel->eltoo_keyset.inner_pubkey); @@ -1160,9 +1161,11 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) "Bad combine_psig_reply %s", tal_hex(tmpctx, msg)); } + /* FIXME Now that state is complete, move signing state over from last_committed_state to last_complete_state */ + /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ - msg = towire_funding_signed_eltoo(state, &state->channel_id, &state->channel->eltoo_keyset.self_psig, &state->channel->eltoo_keyset.self_next_nonce); + msg = towire_funding_signed_eltoo(state, &state->channel_id, &state->channel->eltoo_keyset.last_complete_state.self_psig, &state->channel->eltoo_keyset.self_next_nonce); /* Stick full signature into tx, ready for brodcast(minus fees) */ /* FIXME binding should only be done last-minute */ @@ -1179,9 +1182,9 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) settle_tx, &state->their_funding_pubkey, &state->their_settlement_pubkey, - &state->channel->eltoo_keyset.other_psig, - &state->channel->eltoo_keyset.self_psig, - &state->channel->eltoo_keyset.session, + &state->channel->eltoo_keyset.last_complete_state.other_psig, + &state->channel->eltoo_keyset.last_complete_state.self_psig, + &state->channel->eltoo_keyset.last_complete_state.session, &state->channel->eltoo_keyset.other_next_nonce, &state->channel->eltoo_keyset.self_next_nonce, &state->funding, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index bfe1d14faab3..e7729e93062a 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1657,9 +1657,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) AMOUNT_MSAT(0), AMOUNT_MSAT(-1ULL), NULL /* settle_tx */, - NULL /* their_psig */, - NULL /* our_psig */, - NULL /* session */, + NULL /* complete_state */, + NULL /* committed_state */, NULL /* their_next_nonce */, NULL /* our_next_nonce */); db_begin_transaction(w->db); diff --git a/wallet/wallet.c b/wallet/wallet.c index d5fda360f880..94aefff046e7 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1487,9 +1487,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm htlc_minimum_msat, htlc_maximum_msat, NULL /* FIXME last_settle_tx */, - NULL /* FIXME last_their_psig */, - NULL /* FIXME last_our_psig */, - NULL /* FIXME last_session */, + NULL /* FIXME last_committed_state */, + NULL /* FIXME last_complete_state */, NULL /* FIXME their_next_nonce */, NULL /* FIXME our_next_nonce */); @@ -1943,9 +1942,9 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) db_bind_amount_msat(stmt, 42, &chan->htlc_minimum_msat); db_bind_amount_msat(stmt, 43, &chan->htlc_maximum_msat); db_bind_psbt(stmt, 44, chan->last_settle_tx->psbt); - db_bind_partial_sig(stmt, 45, &chan->eltoo_keyset.other_psig); - db_bind_partial_sig(stmt, 46, &chan->eltoo_keyset.self_psig); - db_bind_musig_session(stmt, 47, &chan->eltoo_keyset.session); + db_bind_partial_sig(stmt, 45, &chan->eltoo_keyset.last_complete_state.other_psig); + db_bind_partial_sig(stmt, 46, &chan->eltoo_keyset.last_complete_state.self_psig); + db_bind_musig_session(stmt, 47, &chan->eltoo_keyset.last_complete_state.session); db_bind_musig_nonce(stmt, 48, &chan->eltoo_keyset.other_next_nonce); db_bind_musig_nonce(stmt, 49, &chan->eltoo_keyset.self_next_nonce); db_bind_u64(stmt, 50, chan->dbid); From 9cbe577a145d5b15e48006eed4c1f5cfebaf3d3a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 15 Nov 2022 10:18:11 -0500 Subject: [PATCH 208/283] f --- lightningd/channel.c | 11 ++++++----- lightningd/channel.h | 2 +- openingd/eltoo_openingd.c | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 1e9af0ffb05e..5dc52e870c14 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -395,8 +395,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, struct bitcoin_tx *settle_tx, - struct eltoo_sign *last_committed_state, struct eltoo_sign *last_complete_state, + struct eltoo_sign *last_committed_state, struct nonce *their_next_nonce, struct nonce *our_next_nonce) { @@ -456,8 +456,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, assert(settle_tx); channel->last_settle_tx = tal_steal(channel, settle_tx); channel->last_settle_tx->chainparams = chainparams; - channel->eltoo_keyset.last_committed_state = *last_committed_state; channel->eltoo_keyset.last_complete_state = *last_complete_state; + channel->eltoo_keyset.last_committed_state = *last_committed_state; channel->eltoo_keyset.other_next_nonce = *their_next_nonce; channel->eltoo_keyset.self_next_nonce = *our_next_nonce; } @@ -704,9 +704,10 @@ void channel_set_last_eltoo_txs(struct channel *channel, tal_free(channel->last_settle_tx); channel->last_settle_tx = tal_steal(channel, settle_tx); - channel->eltoo_keyset.last_committed_state.other_psig = *their_psig; - channel->eltoo_keyset.last_committed_state.self_psig = *our_psig; - channel->eltoo_keyset.last_committed_state.session = *session; + /* Since we have the complete set, it's complete, not "committed" */ + channel->eltoo_keyset.last_complete_state.other_psig = *their_psig; + channel->eltoo_keyset.last_complete_state.self_psig = *our_psig; + channel->eltoo_keyset.last_complete_state.session = *session; } void channel_set_state(struct channel *channel, diff --git a/lightningd/channel.h b/lightningd/channel.h index e894a4365d1a..d06c76ef243e 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -328,8 +328,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, struct bitcoin_tx *settle_tx, - struct eltoo_sign *last_committed_state, struct eltoo_sign *last_complete_state, + struct eltoo_sign *last_committed_state, struct nonce *their_next_nonce, struct nonce *our_next_nonce); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index d93b5cd56a8d..d34146ae7c86 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -1161,7 +1161,8 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) "Bad combine_psig_reply %s", tal_hex(tmpctx, msg)); } - /* FIXME Now that state is complete, move signing state over from last_committed_state to last_complete_state */ + /* Update succeeded, migrate over signing state from last_committed_state to last_complete_state */ + state->channel->eltoo_keyset.last_complete_state = state->channel->eltoo_keyset.last_committed_state; /* We don't send this ourselves: channeld does, because master needs * to save state to disk before doing so. */ From 02056a126db2c8ee59ab1412ad4ff350f6a842a8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 16 Nov 2022 16:11:33 -0500 Subject: [PATCH 209/283] pass around committed state all the way to onchaind --- channeld/eltoo_channeld.c | 23 ++++++------- common/initial_channel.h | 6 +--- common/keyset.h | 8 +++-- lightningd/channel.c | 50 ++++++++++++++++++++-------- lightningd/channel.h | 7 ++-- lightningd/onchain_control.c | 6 ++-- lightningd/opening_control.c | 61 ++++++++++++++++++++++------------ lightningd/peer_control.c | 22 +++++++------ lightningd/peer_htlcs.c | 6 ++-- onchaind/eltoo_onchaind.c | 45 +++++++++++++++++++------- onchaind/onchaind_wire.csv | 6 ++-- wallet/db.c | 14 +++++--- wallet/test/run-wallet.c | 5 ++- wallet/wallet.c | 63 ++++++++++++++++++++++++++---------- 14 files changed, 213 insertions(+), 109 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 4ca3292bf339..53e9f6866e7f 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -884,13 +884,10 @@ static void send_update(struct eltoo_peer *peer) type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session)); /* Cache half-signed tx, for finalization when ACK comes back */ - /* FIXME delete older first */ - /* FIXME these have to be persisted for safety!!! They can appear at any time */ - peer->channel->last_committed_update = tal_steal(peer->channel, update_and_settle_txs[0]); - peer->channel->last_committed_settle = tal_steal(peer->channel, update_and_settle_txs[1]); - /* FIXME switch over to using this */ - peer->channel->eltoo_keyset.last_committed_state.update_tx = peer->channel->last_committed_update; - peer->channel->eltoo_keyset.last_committed_state.settle_tx = peer->channel->last_committed_settle; + tal_free(peer->channel->eltoo_keyset.committed_update_tx); + tal_free(peer->channel->eltoo_keyset.committed_settle_tx); + peer->channel->eltoo_keyset.committed_update_tx = tal_steal(peer->channel, update_and_settle_txs[0]); + peer->channel->eltoo_keyset.committed_settle_tx = tal_steal(peer->channel, update_and_settle_txs[1]); #if DEVELOPER if (peer->dev_disable_commit) { @@ -906,8 +903,8 @@ static void send_update(struct eltoo_peer *peer) changed_htlcs, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, - peer->channel->last_committed_update, - peer->channel->last_committed_update); + peer->channel->eltoo_keyset.committed_update_tx, + peer->channel->eltoo_keyset.committed_settle_tx); /* Message is empty; receiving it is the point. */ master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNELD_SENDING_UPDATESIG_REPLY); @@ -1239,8 +1236,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) status_debug("partial signature combine req on update tx %s, settle tx %s, our_psig: %s," " their_psig: %s, session %s, OLD our nonce %s, OLD their nonce %s", - type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_committed_update), - type_to_string(tmpctx, struct bitcoin_tx, peer->channel->last_committed_settle), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_settle_tx), type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.other_psig), type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session), @@ -1255,8 +1252,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.other_psig, &peer->channel->eltoo_keyset.last_committed_state.session, - peer->channel->last_committed_update, - peer->channel->last_committed_settle, + peer->channel->eltoo_keyset.committed_update_tx, + peer->channel->eltoo_keyset.committed_settle_tx, &peer->channel->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(comb_msg)); comb_msg = wire_sync_read(tmpctx, HSM_FD); diff --git a/common/initial_channel.h b/common/initial_channel.h index 0811d34273b0..440abb54c9c2 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -75,16 +75,12 @@ struct channel { /* Eltoo fields below */ - /* Keys and signing state used for the lifetime of the channel */ + /* Keys, tx, and signing state used for the lifetime of the channel */ struct eltoo_keyset eltoo_keyset; /* Mask for obscuring the encoding of the update number. */ u64 update_number_obscurer; - /* Cached transactions waiting for counter-sign via `update_signed_ack` */ - struct bitcoin_tx *last_committed_update; - struct bitcoin_tx *last_committed_settle; - /* End Eltoo fields*/ }; diff --git a/common/keyset.h b/common/keyset.h index 2cecab63c519..087715f8646a 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -16,8 +16,6 @@ struct keyset { /* Holds all information for a particular state being signed */ struct eltoo_sign { - struct bitcoin_tx *update_tx; - struct bitcoin_tx *settle_tx; struct partial_sig self_psig, other_psig; struct musig_session session; }; @@ -32,10 +30,16 @@ struct eltoo_keyset { struct nonce self_next_nonce, other_next_nonce; /* State we can go to chain with at any point. */ struct eltoo_sign last_complete_state; + /* Will be stolen, so needs to be not copied directly with other state */ + struct bitcoin_tx *complete_update_tx; + struct bitcoin_tx *complete_settle_tx; /* State we have committed to but have incomplete signatures for. * This may be used in channel reestablishment or for reacting to the appearance of the state on-chain. */ struct eltoo_sign last_committed_state; + /* Will be stolen, so needs to be not copied directly with other state */ + struct bitcoin_tx *committed_update_tx; + struct bitcoin_tx *committed_settle_tx; }; /* Self == owner of commitment tx, other == non-owner. */ diff --git a/lightningd/channel.c b/lightningd/channel.c index 5dc52e870c14..d0323d29ffff 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -356,7 +356,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, struct amount_msat our_msat, struct amount_msat msat_to_us_min, struct amount_msat msat_to_us_max, - /* Stolen */ + /* NULL or stolen */ struct bitcoin_tx *last_tx, const struct bitcoin_signature *last_sig, /* NULL or stolen */ @@ -394,9 +394,13 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u16 lease_chan_max_ppt, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, - struct bitcoin_tx *settle_tx, + /* NULL or stolen */ struct eltoo_sign *last_complete_state, + struct bitcoin_tx *complete_update_tx, + struct bitcoin_tx *complete_settle_tx, struct eltoo_sign *last_committed_state, + struct bitcoin_tx *committed_update_tx, + struct bitcoin_tx *committed_settle_tx, struct nonce *their_next_nonce, struct nonce *our_next_nonce) { @@ -446,18 +450,38 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->our_msat = our_msat; channel->msat_to_us_min = msat_to_us_min; channel->msat_to_us_max = msat_to_us_max; - channel->last_tx = tal_steal(channel, last_tx); - channel->last_tx->chainparams = chainparams; - channel->last_tx_type = TX_UNKNOWN; + if (last_tx) { + channel->last_tx = tal_steal(channel, last_tx); + channel->last_tx->chainparams = chainparams; + channel->last_tx_type = TX_UNKNOWN; + } if (last_sig) { channel->last_sig = *last_sig; } else { /* If we're not using ecdsa, we're doing eltoo... */ - assert(settle_tx); - channel->last_settle_tx = tal_steal(channel, settle_tx); - channel->last_settle_tx->chainparams = chainparams; channel->eltoo_keyset.last_complete_state = *last_complete_state; channel->eltoo_keyset.last_committed_state = *last_committed_state; + + /* Migrate over potentially 4 transactions*/ + channel->eltoo_keyset.complete_update_tx = tal_steal(channel, complete_update_tx); + channel->eltoo_keyset.complete_settle_tx = tal_steal(channel, complete_settle_tx); + channel->eltoo_keyset.committed_update_tx = tal_steal(channel, committed_update_tx); + channel->eltoo_keyset.committed_settle_tx = tal_steal(channel, committed_settle_tx); + + /* Should caller handle this instead? */ + if (complete_update_tx) { + channel->eltoo_keyset.complete_update_tx->chainparams = chainparams; + } + if (complete_settle_tx) { + channel->eltoo_keyset.complete_settle_tx->chainparams = chainparams; + } + if (committed_update_tx) { + channel->eltoo_keyset.committed_update_tx->chainparams = chainparams; + } + if (committed_settle_tx) { + channel->eltoo_keyset.committed_settle_tx->chainparams = chainparams; + } + channel->eltoo_keyset.other_next_nonce = *their_next_nonce; channel->eltoo_keyset.self_next_nonce = *our_next_nonce; } @@ -696,15 +720,15 @@ void channel_set_last_eltoo_txs(struct channel *channel, struct musig_session *session, enum wallet_tx_type txtypes) { + /* Since we have the complete set, it's complete, not "committed" */ assert(update_tx->chainparams); assert(settle_tx->chainparams); - tal_free(channel->last_tx); - channel->last_tx = tal_steal(channel, update_tx); + tal_free(channel->eltoo_keyset.complete_update_tx); + channel->eltoo_keyset.complete_update_tx = tal_steal(channel, update_tx); channel->last_tx_type = txtypes; - tal_free(channel->last_settle_tx); - channel->last_settle_tx = tal_steal(channel, settle_tx); + tal_free(channel->eltoo_keyset.complete_settle_tx); + channel->eltoo_keyset.complete_settle_tx = tal_steal(channel, settle_tx); - /* Since we have the complete set, it's complete, not "committed" */ channel->eltoo_keyset.last_complete_state.other_psig = *their_psig; channel->eltoo_keyset.last_complete_state.self_psig = *our_psig; channel->eltoo_keyset.last_complete_state.session = *session; diff --git a/lightningd/channel.h b/lightningd/channel.h index d06c76ef243e..6129b83bf053 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -151,8 +151,6 @@ struct channel { const struct bitcoin_signature *last_htlc_sigs; /* Eltoo-only fields */ - /* last_tx aka last_update_tx */ - struct bitcoin_tx *last_settle_tx; /* Stores "last" psigs, session */ struct eltoo_keyset eltoo_keyset; @@ -327,9 +325,12 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u16 lease_chan_max_ppt, struct amount_msat htlc_minimum_msat, struct amount_msat htlc_maximum_msat, - struct bitcoin_tx *settle_tx, struct eltoo_sign *last_complete_state, + struct bitcoin_tx *complete_update_tx, + struct bitcoin_tx *complete_settle_tx, struct eltoo_sign *last_committed_state, + struct bitcoin_tx *committed_update_tx, + struct bitcoin_tx *committed_settle_tx, struct nonce *their_next_nonce, struct nonce *our_next_nonce); diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 4385b1dc850a..b2300854ea7a 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -936,8 +936,10 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, channel->funding_sats, tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), tx->wtx->locktime, - channel->last_tx, - channel->last_settle_tx, + channel->eltoo_keyset.complete_update_tx, + channel->eltoo_keyset.complete_settle_tx, + channel->eltoo_keyset.committed_update_tx, + channel->eltoo_keyset.committed_settle_tx, blockheight, channel->our_msat, channel->shutdown_scriptpubkey[LOCAL], diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 60706a13d461..8e714cc2776c 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -93,9 +93,12 @@ wallet_commit_channel(struct lightningd *ld, const u8 *our_upfront_shutdown_script, const u8 *remote_upfront_shutdown_script, const struct channel_type *type, - struct bitcoin_tx *settle_tx, struct eltoo_sign *complete_state, + struct bitcoin_tx *complete_update_tx, + struct bitcoin_tx *complete_settle_tx, struct eltoo_sign *committed_state, + struct bitcoin_tx *committed_update_tx, + struct bitcoin_tx *committed_settle_tx, struct nonce *their_next_nonce, struct nonce *our_next_nonce) { @@ -220,9 +223,12 @@ wallet_commit_channel(struct lightningd *ld, 0, NULL, 0, 0, /* No leases on v1s */ ld->config.htlc_minimum_msat, ld->config.htlc_maximum_msat, - settle_tx, complete_state, + complete_update_tx, + complete_settle_tx, committed_state, + committed_update_tx, + committed_settle_tx, their_next_nonce, our_next_nonce); @@ -359,14 +365,14 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, struct channel_info channel_info; struct channel_id cid; struct bitcoin_outpoint funding; - struct bitcoin_tx *update_tx, *settle_tx; struct channel *channel; struct lightningd *ld = openingd->ld; u8 *remote_upfront_shutdown_script; struct peer_fd *peer_fd; struct channel_type *type; /* Committed state is blank */ - struct eltoo_sign complete_state, dummy_committed_state; + struct eltoo_sign complete_state, empty_committed_state; + struct bitcoin_tx *complete_update_tx, *complete_settle_tx; struct nonce their_next_nonce, our_next_nonce; /* This is a new channel_info.their_config so set its ID to 0 */ @@ -374,8 +380,8 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, if (!fromwire_openingd_eltoo_funder_reply(resp, resp, &channel_info.their_config, - &update_tx, - &settle_tx, + &complete_update_tx, + &complete_settle_tx, &fc->uc->minimum_depth, &channel_info.remote_fundingkey, &channel_info.theirbase.payment, @@ -395,7 +401,8 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, tal_hex(fc->cmd, resp))); goto cleanup; } - update_tx->chainparams = chainparams; + complete_update_tx->chainparams = chainparams; + complete_settle_tx->chainparams = chainparams; /* We make sure other basepoints are valid * even if unused... @@ -414,7 +421,7 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, /* Steals fields from uc */ channel = wallet_commit_channel(ld, fc->uc, &cid, - update_tx, + NULL /* last_tx */, NULL /* remote_commit_sig */, &funding, fc->funding_sats, @@ -425,9 +432,12 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, fc->our_upfront_shutdown_script, remote_upfront_shutdown_script, type, - settle_tx, &complete_state, - &dummy_committed_state, + complete_update_tx, + complete_settle_tx, + &empty_committed_state, + NULL /* committed_update_tx */, + NULL /* committed_settle_tx */, &their_next_nonce, &our_next_nonce); if (!channel) { @@ -520,9 +530,12 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, fc->our_upfront_shutdown_script, remote_upfront_shutdown_script, type, - NULL /* settle_tx */, NULL /* complete_state */, + NULL /* complete_update_tx */, + NULL /* complete_settle_tx */, NULL /* committed_state */, + NULL /* committed_update_tx */, + NULL /* committed_settle_tx */, NULL /* their_next_nonce */, NULL /* our_next_nonce */); if (!channel) { @@ -552,7 +565,6 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, { const u8 *fwd_msg; struct channel_info channel_info; - struct bitcoin_tx *update_tx, *settle_tx; struct channel_id cid; struct lightningd *ld = openingd->ld; struct bitcoin_outpoint funding; @@ -564,7 +576,8 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, struct peer_fd *peer_fd; struct channel_type *type; - struct eltoo_sign complete_state, dummy_committed_state; + struct eltoo_sign complete_state, empty_committed_state; + struct bitcoin_tx *complete_update_tx, *complete_settle_tx; struct nonce their_next_nonce, our_next_nonce; log_debug(uc->log, "Got opening_eltoo_fundee_finish_response"); @@ -576,8 +589,8 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, if (!fromwire_openingd_eltoo_fundee(tmpctx, reply, &channel_info.their_config, - &update_tx, - &settle_tx, + &complete_update_tx, + &complete_settle_tx, &channel_info.remote_fundingkey, &channel_info.theirbase.payment, &complete_state.other_psig, @@ -611,15 +624,15 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, memcpy(&channel_info.remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); memcpy(&channel_info.old_remote_per_commit, &channel_info.theirbase.payment, sizeof(channel_info.theirbase.payment)); - update_tx->chainparams = chainparams; - settle_tx->chainparams = chainparams; + complete_update_tx->chainparams = chainparams; + complete_settle_tx->chainparams = chainparams; derive_channel_id(&cid, &funding); /* Consumes uc */ channel = wallet_commit_channel(ld, uc, &cid, - update_tx, + NULL /* remote_commit */, NULL /* remote_commit_sig */, &funding, funding_sats, @@ -630,9 +643,12 @@ static void opening_eltoo_fundee_finished(struct subd *openingd, local_upfront_shutdown_script, remote_upfront_shutdown_script, type, - settle_tx, &complete_state, - &dummy_committed_state, + complete_update_tx, + complete_settle_tx, + &empty_committed_state, + NULL /* committed_update_tx */, + NULL /* committed_settle_tx */, &their_next_nonce, &our_next_nonce); @@ -740,9 +756,12 @@ static void opening_fundee_finished(struct subd *openingd, local_upfront_shutdown_script, remote_upfront_shutdown_script, type, - NULL /* settle_tx */, NULL /* complete_state */, + NULL /* complete_update_tx */, + NULL /* complete_settle_tx */, NULL /* committed_state */, + NULL /* committed_update_tx */, + NULL /* committed_settle_tx */, NULL /* their_next_nonce */, NULL /* our_next_nonce */); if (!channel) { diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index f49ecde1309b..7d78542596ca 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -238,9 +238,9 @@ static void eltoo_finalize_and_send_last(struct lightningd *ld, struct channel * struct bitcoin_txid txid; /* Eltoo keyset should probably have all pubkeys... */ - bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->last_tx, + bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->eltoo_keyset.complete_update_tx, &channel->funding, - channel->last_settle_tx, + channel->eltoo_keyset.complete_settle_tx, &channel->eltoo_keyset.last_complete_state.self_psig, &channel->eltoo_keyset.last_complete_state.other_psig, &channel->local_funding_pubkey, @@ -692,7 +692,7 @@ static void json_add_channel(struct lightningd *ld, json_object_start(response, key); json_add_string(response, "state", channel_state_name(channel)); - if (channel->last_tx && !invalid_last_tx(channel->last_tx)) { + if (!channel->our_config.is_eltoo && channel->last_tx && !invalid_last_tx(channel->last_tx)) { struct bitcoin_txid txid; bitcoin_txid(channel->last_tx, &txid); @@ -776,8 +776,10 @@ static void json_add_channel(struct lightningd *ld, "our_funding_msat", inflight->funding->our_funds); /* Add the expected commitment tx id also */ - bitcoin_txid(inflight->last_tx, &txid); - json_add_txid(response, "scratch_txid", &txid); + if (!channel->our_config.is_eltoo) { + bitcoin_txid(inflight->last_tx, &txid); + json_add_txid(response, "scratch_txid", &txid); + } json_object_end(response); } json_array_end(response); @@ -1000,13 +1002,13 @@ static void json_add_channel(struct lightningd *ld, json_add_htlcs(ld, response, channel); - if (channel->last_settle_tx) { + if (channel->our_config.is_eltoo) { struct bitcoin_tx **bound_update_and_settle_txs; /* Eltoo keyset should probably have all pubkeys... */ - bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->last_tx, + bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->eltoo_keyset.complete_update_tx, &channel->funding, - channel->last_settle_tx, + channel->eltoo_keyset.complete_settle_tx, &channel->eltoo_keyset.last_complete_state.self_psig, &channel->eltoo_keyset.last_complete_state.other_psig, &channel->local_funding_pubkey, @@ -1015,8 +1017,8 @@ static void json_add_channel(struct lightningd *ld, json_add_tx(response, "last_update_tx", bound_update_and_settle_txs[0]); json_add_tx(response, "last_settle_tx", bound_update_and_settle_txs[1]); - json_add_tx(response, "unbound_update_tx", channel->last_tx); - json_add_tx(response, "unbound_settle_tx", channel->last_settle_tx); + json_add_tx(response, "unbound_update_tx", channel->eltoo_keyset.complete_update_tx); + json_add_tx(response, "unbound_settle_tx", channel->eltoo_keyset.complete_settle_tx); /* FIXME Deallocate copied txns? */ } diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index bee4670e6fae..8c6b6455833f 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -34,8 +34,7 @@ static bool state_update_ok(struct channel *channel, u64 htlc_id, const char *dir) { enum htlc_state expected = oldstate + 1; - /* FIXME better switch */ - bool is_eltoo = channel->last_settle_tx; + bool is_eltoo = channel->our_config.is_eltoo; /* We never get told about RCVD_REMOVE_HTLC, so skip over that * (we initialize in SENT_ADD_HTLC / RCVD_ADD_COMMIT, so those @@ -333,8 +332,7 @@ void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage) u8 *msg; struct channel *channel = hin->key.channel; struct wallet *wallet = channel->peer->ld->wallet; - /* FIXME: Better switch on eltoo behavior... or just move SENT_ADD_ACK to RCVD_ADD_ACK_REVOCATION and jump? */ - enum htlc_state final_state = channel->last_settle_tx ? SENT_ADD_ACK : RCVD_ADD_ACK_REVOCATION; + enum htlc_state final_state = channel->our_config.is_eltoo ? SENT_ADD_ACK : RCVD_ADD_ACK_REVOCATION; if (hin->hstate != final_state) { log_debug(channel->log, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index b7aa82a73811..e6d88e3b9861 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1325,11 +1325,14 @@ int main(int argc, char *argv[]) const tal_t *ctx = tal(NULL, char); u8 *msg; struct tx_parts *spending_tx; - struct bitcoin_tx *unbound_update_tx, *unbound_settle_tx; + /* Full tx we have partial signatures for */ + struct bitcoin_tx *unbound_complete_update_tx, *unbound_complete_settle_tx; + /* Tx we do not have full signatures for, but may appear on-chain */ + struct bitcoin_tx *unbound_committed_update_tx, *unbound_committed_settle_tx; struct tracked_output **outs; struct bitcoin_outpoint funding; struct amount_sat funding_sats; - u32 locktime, tx_blockheight; + u32 locktime, tx_blockheight, max_known_version; u8 *scriptpubkey[NUM_SIDES]; subdaemon_setup(argc, argv); @@ -1344,8 +1347,10 @@ int main(int argc, char *argv[]) &funding_sats, &spending_tx, &locktime, - &unbound_update_tx, - &unbound_settle_tx, + &unbound_complete_update_tx, + &unbound_complete_settle_tx, + &unbound_committed_update_tx, + &unbound_committed_settle_tx, &tx_blockheight, &our_msat, &scriptpubkey[LOCAL], @@ -1357,14 +1362,22 @@ int main(int argc, char *argv[]) reasonable_depth = 3; status_debug("lightningd_eltoo_onchaind is alive!"); - /* We need to keep tx around, but there's only one: not really a leak */ + /* We need to keep tx around, but there's only a constant number: not really a leak */ tal_steal(ctx, notleak(spending_tx)); - tal_steal(ctx, notleak(unbound_update_tx)); - tal_steal(ctx, notleak(unbound_settle_tx)); + tal_steal(ctx, notleak(unbound_complete_update_tx)); + tal_steal(ctx, notleak(unbound_complete_settle_tx)); status_debug("Unbound update and settle transactions to potentially broadcast: %s, %s", - type_to_string(tmpctx, struct bitcoin_tx, unbound_update_tx), - type_to_string(tmpctx, struct bitcoin_tx, unbound_settle_tx)); + type_to_string(tmpctx, struct bitcoin_tx, unbound_complete_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, unbound_complete_settle_tx)); + + if (unbound_committed_update_tx) { + tal_steal(ctx, notleak(unbound_committed_update_tx)); + tal_steal(ctx, notleak(unbound_committed_settle_tx)); + status_debug("Unbound update and settle transactions committed but incomplete: %s, %s", + type_to_string(tmpctx, struct bitcoin_tx, unbound_committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, unbound_committed_settle_tx)); + } /* These are the utxos we are interested in */ outs = tal_arr(ctx, struct tracked_output *, 0); @@ -1383,19 +1396,27 @@ int main(int argc, char *argv[]) funding_sats, tal_count(spending_tx->outputs)))); + /* Committed state should be one step further max */ + max_known_version = unbound_complete_update_tx->wtx->locktime; + if (unbound_committed_update_tx) { + assert(unbound_complete_update_tx->wtx->locktime == unbound_committed_update_tx->wtx->locktime || + unbound_complete_update_tx->wtx->locktime == unbound_committed_update_tx->wtx->locktime + 1); + max_known_version = unbound_committed_update_tx->wtx->locktime; + } + if (is_mutual_close(locktime)) { status_debug("Handling mutual close!"); eltoo_handle_mutual_close(outs, spending_tx); } else { status_debug("Handling unilateral close!"); - if (locktime > unbound_update_tx->wtx->locktime) { + if (locktime > max_known_version) { /* Might as well track the state output, see if it ends up in a settlement tx * So `to_node` values can be harvested, HTLCs rescued with counterparty's help? * Or we should immediately report all HTLCs as missing, failing these? */ status_debug("Uh-oh, please be nice Mr Counterparty :("); - } else if (locktime == unbound_update_tx->wtx->locktime) { - status_debug("Unilateral close of last state detected"); + } else if (locktime == max_known_version) { + status_debug("Unilateral close of last known state detected"); /* Someday we could maybe negotiate with peer to life back into channel * For now we just deal with it by submitting settle transaction. * If we know it's counter-party, maybe they'll pay for us :) diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 8faf07c9ca8a..ce108556f469 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -147,8 +147,10 @@ msgdata,eltoo_onchaind_init,funding_outpoint,bitcoin_outpoint, msgdata,eltoo_onchaind_init,funding_amount_satoshi,amount_sat, msgdata,eltoo_onchaind_init,tx_parts,tx_parts, msgdata,eltoo_onchaind_init,locktime,u32, -msgdata,eltoo_onchaind_init,update_tx,bitcoin_tx, -msgdata,eltoo_onchaind_init,settle_tx,bitcoin_tx, +msgdata,eltoo_onchaind_init,complete_update_tx,bitcoin_tx, +msgdata,eltoo_onchaind_init,complete_settle_tx,bitcoin_tx, +msgdata,eltoo_onchaind_init,committed_update_tx,?bitcoin_tx, +msgdata,eltoo_onchaind_init,committed_settle_tx,?bitcoin_tx, msgdata,eltoo_onchaind_init,tx_blockheight,u32, msgdata,eltoo_onchaind_init,our_msat,amount_msat, msgdata,eltoo_onchaind_init,local_scriptpubkey_len,u16, diff --git a/wallet/db.c b/wallet/db.c index 4f89fa3cae33..79b8da31b5f1 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -142,10 +142,16 @@ static struct migration dbmigrations[] = { " closing_fee_received INTEGER," " closing_sig_received BLOB," /* START Eltoo stuff*/ - " last_settle_tx BLOB," - " last_their_psig BLOB," - " last_our_psig BLOB," - " last_session BLOB," + " last_complete_update_tx BLOB," + " last_complete_settle_tx BLOB," + " last_committed_update_tx BLOB," + " last_committed_settle_tx BLOB," + " last_complete_their_psig BLOB," + " last_complete_our_psig BLOB," + " last_complete_session BLOB," + " last_committed_their_psig BLOB," + " last_committed_our_psig BLOB," + " last_committed_session BLOB," " their_next_nonce BLOB," " our_next_nonce BLOB," /* END Eltoo stuff */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index e7729e93062a..982d2aee017d 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1656,9 +1656,12 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) 7777, 22, AMOUNT_MSAT(0), AMOUNT_MSAT(-1ULL), - NULL /* settle_tx */, NULL /* complete_state */, + NULL /* complete_update_tx */, + NULL /* complete_settle_tx */, NULL /* committed_state */, + NULL /* committed_update_tx */, + NULL /* committed_settle_tx */, NULL /* their_next_nonce */, NULL /* our_next_nonce */); db_begin_transaction(w->db); diff --git a/wallet/wallet.c b/wallet/wallet.c index 94aefff046e7..ac4dc9b190a1 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1486,9 +1486,12 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm lease_chan_max_ppt, htlc_minimum_msat, htlc_maximum_msat, - NULL /* FIXME last_settle_tx */, - NULL /* FIXME last_committed_state */, NULL /* FIXME last_complete_state */, + NULL /* FIXME complete_update_tx */, + NULL /* FIXME complete_settle_tx */, + NULL /* FIXME last_committed_state */, + NULL /* FIXME committed_update_tx */, + NULL /* FIXME committed_settle_tx */, NULL /* FIXME their_next_nonce */, NULL /* FIXME our_next_nonce */); @@ -1870,13 +1873,19 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " lease_chan_max_ppt=?," // 41 " htlc_minimum_msat=?," // 42 " htlc_maximum_msat=?," // 43 - " last_settle_tx=?," // 44 - " last_their_psig=?," // 45 - " last_our_psig=?," // 46 - " last_session=?," // 47 - " their_next_nonce=?," // 48 - " our_next_nonce=?" // 49 - " WHERE id=?")); // 50 + " last_complete_update_tx=?," // 44 + " last_complete_settle_tx=?," // 45 + " last_committed_update_tx=?," // 46 + " last_committed_settle_tx=?," // 47 + " last_complete_their_psig=?," // 48 + " last_complete_our_psig=?," // 49 + " last_complete_session=?," // 50 + " last_committed_their_psig=?," // 51 + " last_committed_our_psig=?," // 52 + " last_committed_session=?," // 53 + " their_next_nonce=?," // 54 + " our_next_nonce=?" // 55 + " WHERE id=?")); // 56 db_bind_u64(stmt, 0, chan->their_shachain.id); if (chan->scid) db_bind_short_channel_id(stmt, 1, chan->scid); @@ -1905,7 +1914,11 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) db_bind_talarr(stmt, 17, chan->shutdown_scriptpubkey[REMOTE]); db_bind_u64(stmt, 18, chan->final_key_idx); db_bind_u64(stmt, 19, chan->our_config.id); - db_bind_psbt(stmt, 20, chan->last_tx->psbt); + if (!chan->our_config.is_eltoo) { + db_bind_psbt(stmt, 20, chan->last_tx->psbt); + } else { + db_bind_null(stmt, 20); + } db_bind_signature(stmt, 21, &chan->last_sig.s); db_bind_int(stmt, 22, chan->last_was_revoke); db_bind_int(stmt, 23, chan->min_possible_feerate); @@ -1941,13 +1954,29 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) } db_bind_amount_msat(stmt, 42, &chan->htlc_minimum_msat); db_bind_amount_msat(stmt, 43, &chan->htlc_maximum_msat); - db_bind_psbt(stmt, 44, chan->last_settle_tx->psbt); - db_bind_partial_sig(stmt, 45, &chan->eltoo_keyset.last_complete_state.other_psig); - db_bind_partial_sig(stmt, 46, &chan->eltoo_keyset.last_complete_state.self_psig); - db_bind_musig_session(stmt, 47, &chan->eltoo_keyset.last_complete_state.session); - db_bind_musig_nonce(stmt, 48, &chan->eltoo_keyset.other_next_nonce); - db_bind_musig_nonce(stmt, 49, &chan->eltoo_keyset.self_next_nonce); - db_bind_u64(stmt, 50, chan->dbid); + if (chan->eltoo_keyset.complete_update_tx) { + db_bind_psbt(stmt, 44, chan->eltoo_keyset.complete_update_tx->psbt); + db_bind_psbt(stmt, 45, chan->eltoo_keyset.complete_settle_tx->psbt); + } else { + db_bind_null(stmt, 44); + db_bind_null(stmt, 45); + } + if (chan->eltoo_keyset.committed_update_tx) { + db_bind_psbt(stmt, 46, chan->eltoo_keyset.committed_update_tx->psbt); + db_bind_psbt(stmt, 47, chan->eltoo_keyset.committed_settle_tx->psbt); + } else { + db_bind_null(stmt, 46); + db_bind_null(stmt, 47); + } + db_bind_partial_sig(stmt, 48, &chan->eltoo_keyset.last_complete_state.other_psig); + db_bind_partial_sig(stmt, 49, &chan->eltoo_keyset.last_complete_state.self_psig); + db_bind_musig_session(stmt, 50, &chan->eltoo_keyset.last_complete_state.session); + db_bind_partial_sig(stmt, 51, &chan->eltoo_keyset.last_committed_state.other_psig); + db_bind_partial_sig(stmt, 52, &chan->eltoo_keyset.last_committed_state.self_psig); + db_bind_musig_session(stmt, 53, &chan->eltoo_keyset.last_committed_state.session); + db_bind_musig_nonce(stmt, 54, &chan->eltoo_keyset.other_next_nonce); + db_bind_musig_nonce(stmt, 55, &chan->eltoo_keyset.self_next_nonce); + db_bind_u64(stmt, 56, chan->dbid); db_exec_prepared_v2(take(stmt)); wallet_channel_config_save(w, &chan->channel_info.their_config); From 2217e24ba3a73d94f126713b6a3499be9b339c0c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 17 Nov 2022 12:38:58 -0500 Subject: [PATCH 210/283] Wrong enum for ELTOO_UPDATE --- onchaind/eltoo_onchaind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index e6d88e3b9861..12f6412a4548 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1305,7 +1305,7 @@ static void handle_latest_update(const struct tx_parts *tx, assert(htlcs_info); onchain_annotate_txin(&tx->txid, state_index, TX_CHANNEL_UNILATERAL); - resolved_by_other(outs[0], &tx->txid, UPDATE); + resolved_by_other(outs[0], &tx->txid, ELTOO_UPDATE); new_tracked_output(&outs, &outpoint, tx_blockheight, From f52db64b16c583b6aa529a9e9fe124bbff4ac93e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 18 Nov 2022 12:53:08 -0500 Subject: [PATCH 211/283] Add binding of settlement tx for onchaind --- common/update_tx.c | 11 ++-- common/update_tx.h | 4 +- onchaind/Makefile | 1 + onchaind/eltoo_onchaind.c | 119 ++++++++++++++++++++++++-------------- onchaind/onchain_types.h | 2 +- 5 files changed, 86 insertions(+), 51 deletions(-) diff --git a/common/update_tx.c b/common/update_tx.c index 4f934141efea..6fb3cbb66fbc 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -126,15 +126,12 @@ void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } -void bind_settle_tx(const struct bitcoin_tx *update_tx, +void bind_settle_tx(const struct bitcoin_txid update_txid, int output_index, struct bitcoin_tx *settle_tx) { - struct bitcoin_txid txid; - /* Really direct txid surgery... libwally routine better to modify PSBT input! */ - bitcoin_txid(update_tx, &txid); assert(settle_tx->wtx->num_inputs == 1); /* We don't craft anything else */ - memcpy(settle_tx->wtx->inputs[0].txhash, &txid, 32); + memcpy(settle_tx->wtx->inputs[0].txhash, &update_txid, 32); } void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, @@ -232,6 +229,7 @@ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update secp256k1_musig_keyagg_cache dummy_cache; struct pubkey inner_pubkey; struct eltoo_keyset keyset_copy; + struct bitcoin_txid update_txid; towire_bitcoin_tx(&p, update_tx); p_start = p; p_len = tal_count(p); @@ -275,7 +273,8 @@ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update &inner_pubkey, &sig); - bind_settle_tx(bound_update_tx, + bitcoin_txid(bound_update_tx, &update_txid); + bind_settle_tx(update_txid, 0 /* output_index: we can't know for sure until update tx confirms, this is for ease of use */, bound_settle_tx); diff --git a/common/update_tx.h b/common/update_tx.h index 24144007cb24..3025e82229f0 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -23,12 +23,12 @@ void tx_add_unbound_input(struct bitcoin_tx *update_tx, /* Called just in time before broadcasting to spend expired update output. - * @update_tx: the update transaction that has reached enough + * @update_txix: the txid of the update transaction that has reached enough * confirmations to spend via settle path * @output_index: which output index is to be spent * @settle_tx: the settlement transaction to rebind **/ -void bind_settle_tx(const struct bitcoin_tx *update_tx, +void bind_settle_tx(const struct bitcoin_txid update_txid, int output_index, struct bitcoin_tx *settle_tx); diff --git a/onchaind/Makefile b/onchaind/Makefile index b1221bf2e83d..71549b02f117 100644 --- a/onchaind/Makefile +++ b/onchaind/Makefile @@ -70,6 +70,7 @@ ONCHAIND_COMMON_OBJS := \ common/subdaemon.o \ common/type_to_string.o \ common/utils.o \ + common/update_tx.o \ common/utxo.o \ common/version.o \ common/wallet.o \ diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 12f6412a4548..37b0cd546dd8 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -29,11 +30,14 @@ /* FIXME Everything copy/pasted bc static. Deduplicate later */ -/* Required in various places: keys for commitment transaction. */ -static const struct keyset *keyset; +/* Full tx we have partial signatures for */ +static struct bitcoin_tx *complete_update_tx, *complete_settle_tx; + +/* Tx we do not have full signatures for, but may appear on-chain */ +static struct bitcoin_tx *committed_update_tx, *committed_settle_tx; -/* IFF it's their commitment tx: HSM can't derive their per-commitment point! */ -static const struct pubkey *remote_per_commitment_point; +/* Required in various places: keys for commitment transaction. */ +static const struct eltoo_keyset *keyset; /* The dust limit to use when we generate transactions. */ static struct amount_sat dust_limit; @@ -778,6 +782,27 @@ static void billboard_update(struct tracked_output **outs) output_type_name(best->output_type), best->depth); } +static void propose_resolution(struct tracked_output *out, + const struct bitcoin_tx *tx, + unsigned int depth_required, + enum tx_type tx_type) +{ + status_debug("Propose handling %s/%s by %s (%s) after %u blocks", + tx_type_name(out->tx_type), + output_type_name(out->output_type), + tx_type_name(tx_type), + tx ? type_to_string(tmpctx, struct bitcoin_tx, tx):"IGNORING", + depth_required); + + out->proposal = tal(out, struct proposed_resolution); + out->proposal->tx = tal_steal(out->proposal, tx); + out->proposal->depth_required = depth_required; + out->proposal->tx_type = tx_type; + + if (depth_required == 0) + proposal_meets_depth(out); +} + static void unwatch_txid(const struct bitcoin_txid *txid) { u8 *msg; @@ -1096,8 +1121,6 @@ static void memleak_remove_globals(struct htable *memtable, const tal_t *topctx) { if (keyset) memleak_remove_region(memtable, keyset, sizeof(*keyset)); - memleak_remove_pointer(memtable, remote_per_commitment_point); - memleak_remove_pointer(memtable, remote_per_commitment_secret); memleak_remove_pointer(memtable, topctx); memleak_remove_region(memtable, missing_htlc_msgs, tal_bytelen(missing_htlc_msgs)); @@ -1153,14 +1176,13 @@ static void wait_for_resolved(struct tracked_output **outs) if (fromwire_onchaind_depth(msg, &txid, &depth)) { eltoo_tx_new_depth(outs, &txid, depth); - } - else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num, + } else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num, &tx_blockheight)) { /* FIXME walk through logic with someone who knows what's going on */ output_spent(&outs, tx_parts, input_num, tx_blockheight); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) - /* FIXME Somehow we should be watching out settlement outputs - even if they haven't entered utxo set. */ + /* We could be watching our settlement outputs + even if they haven't entered utxo set to use for CPFP. */ eltoo_handle_preimage(outs, &preimage); else if (!handle_dev_memleak(outs, msg)) master_badmsg(-1, msg); @@ -1285,12 +1307,15 @@ static void eltoo_handle_mutual_close(struct tracked_output **outs, static void handle_latest_update(const struct tx_parts *tx, u32 tx_blockheight, - struct tracked_output **outs) + struct tracked_output **outs, + u32 locktime) { struct htlcs_info *htlcs_info; struct bitcoin_outpoint outpoint; struct amount_asset asset; struct amount_sat amt; + struct tracked_output *out; + /* State output will match index */ int state_index = funding_input_num(outs, tx); @@ -1300,20 +1325,29 @@ static void handle_latest_update(const struct tx_parts *tx, asset = wally_tx_output_get_amount(tx->outputs[state_index]); amt = amount_asset_to_sat(&asset); - htlcs_info = eltoo_init_reply(tmpctx, "Tracking latest update transaction"); + htlcs_info = eltoo_init_reply(tmpctx, "Tracking final update transaction"); /* FIXME do something with htlcs_info ? */ assert(htlcs_info); onchain_annotate_txin(&tx->txid, state_index, TX_CHANNEL_UNILATERAL); resolved_by_other(outs[0], &tx->txid, ELTOO_UPDATE); - new_tracked_output(&outs, + out = new_tracked_output(&outs, &outpoint, tx_blockheight, UPDATE, amt, DELAYED_OUTPUT_TO_US, NULL /* htlc */, NULL /* wscript */, NULL /* remote_htlc_sig */); + /* Proposed resolution is the matching settlement tx */ + if (locktime == complete_update_tx->wtx->locktime) { + bind_settle_tx(tx->txid, state_index, complete_settle_tx); + propose_resolution(out, complete_settle_tx, complete_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); + } else { + bind_settle_tx(tx->txid, state_index, committed_settle_tx); + propose_resolution(out, committed_settle_tx, committed_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); + } + /* Wait until we get shared_delay confirms for this output */ wait_for_resolved(outs); } @@ -1325,10 +1359,6 @@ int main(int argc, char *argv[]) const tal_t *ctx = tal(NULL, char); u8 *msg; struct tx_parts *spending_tx; - /* Full tx we have partial signatures for */ - struct bitcoin_tx *unbound_complete_update_tx, *unbound_complete_settle_tx; - /* Tx we do not have full signatures for, but may appear on-chain */ - struct bitcoin_tx *unbound_committed_update_tx, *unbound_committed_settle_tx; struct tracked_output **outs; struct bitcoin_outpoint funding; struct amount_sat funding_sats; @@ -1347,10 +1377,11 @@ int main(int argc, char *argv[]) &funding_sats, &spending_tx, &locktime, - &unbound_complete_update_tx, - &unbound_complete_settle_tx, - &unbound_committed_update_tx, - &unbound_committed_settle_tx, + /* Transactions are global for ease of access */ + &complete_update_tx, + &complete_settle_tx, + &committed_update_tx, + &committed_settle_tx, &tx_blockheight, &our_msat, &scriptpubkey[LOCAL], @@ -1364,19 +1395,19 @@ int main(int argc, char *argv[]) status_debug("lightningd_eltoo_onchaind is alive!"); /* We need to keep tx around, but there's only a constant number: not really a leak */ tal_steal(ctx, notleak(spending_tx)); - tal_steal(ctx, notleak(unbound_complete_update_tx)); - tal_steal(ctx, notleak(unbound_complete_settle_tx)); + tal_steal(ctx, notleak(complete_update_tx)); + tal_steal(ctx, notleak(complete_settle_tx)); status_debug("Unbound update and settle transactions to potentially broadcast: %s, %s", - type_to_string(tmpctx, struct bitcoin_tx, unbound_complete_update_tx), - type_to_string(tmpctx, struct bitcoin_tx, unbound_complete_settle_tx)); + type_to_string(tmpctx, struct bitcoin_tx, complete_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, complete_settle_tx)); - if (unbound_committed_update_tx) { - tal_steal(ctx, notleak(unbound_committed_update_tx)); - tal_steal(ctx, notleak(unbound_committed_settle_tx)); + if (committed_update_tx) { + tal_steal(ctx, notleak(committed_update_tx)); + tal_steal(ctx, notleak(committed_settle_tx)); status_debug("Unbound update and settle transactions committed but incomplete: %s, %s", - type_to_string(tmpctx, struct bitcoin_tx, unbound_committed_update_tx), - type_to_string(tmpctx, struct bitcoin_tx, unbound_committed_settle_tx)); + type_to_string(tmpctx, struct bitcoin_tx, committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, committed_settle_tx)); } /* These are the utxos we are interested in */ @@ -1397,11 +1428,11 @@ int main(int argc, char *argv[]) tal_count(spending_tx->outputs)))); /* Committed state should be one step further max */ - max_known_version = unbound_complete_update_tx->wtx->locktime; - if (unbound_committed_update_tx) { - assert(unbound_complete_update_tx->wtx->locktime == unbound_committed_update_tx->wtx->locktime || - unbound_complete_update_tx->wtx->locktime == unbound_committed_update_tx->wtx->locktime + 1); - max_known_version = unbound_committed_update_tx->wtx->locktime; + max_known_version = complete_update_tx->wtx->locktime; + if (committed_update_tx) { + assert(complete_update_tx->wtx->locktime == committed_update_tx->wtx->locktime || + complete_update_tx->wtx->locktime == committed_update_tx->wtx->locktime + 1); + max_known_version = committed_update_tx->wtx->locktime; } if (is_mutual_close(locktime)) { @@ -1417,14 +1448,18 @@ int main(int argc, char *argv[]) status_debug("Uh-oh, please be nice Mr Counterparty :("); } else if (locktime == max_known_version) { status_debug("Unilateral close of last known state detected"); - /* Someday we could maybe negotiate with peer to life back into channel - * For now we just deal with it by submitting settle transaction. - * If we know it's counter-party, maybe they'll pay for us :) - * or maybe we paid a watchtower already... - * - * Either way, this also happens in the "cheating" below, and we handle this identically. + /* + * We are simply waiting for this particular update tx to mature + * before getting the settlement tx on chain and sweeping outputs. + */ + handle_latest_update(spending_tx, tx_blockheight, outs, locktime); + } else if (locktime == complete_update_tx->wtx->locktime) { + status_debug("Unilateral close of last complete state detected"); + /* + * It's possible this last transaction will be over-written + * by the committed state we don't have signatures for. */ - handle_latest_update(spending_tx, tx_blockheight, outs); + handle_latest_update(spending_tx, tx_blockheight, outs, locktime); } else { status_debug("Cheater!"); } diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index c8cba6e3f5a6..8594193161ea 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -59,7 +59,7 @@ enum eltoo_tx_type { /* A mutual close: spends funding */ ELTOO_MUTUAL_CLOSE, - /* Unknown unilateral (presumably theirs): spends funding */ + /* Latest unilateral: spends funding */ ELTOO_UPDATE, /* Old unilateral: spends funding */ From 98326e51b60ff01dedbb53e072b3b6fc0dd1e52b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 18 Nov 2022 13:07:20 -0500 Subject: [PATCH 212/283] Mutual close is locktime of 0 --- onchaind/eltoo_onchaind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 37b0cd546dd8..655bcf17221a 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -694,7 +694,7 @@ static void resolved_by_other(struct tracked_output *out, static bool is_mutual_close(u32 locktime) { /* If we mask update number, this needs to change */ - return locktime == 500000000; + return locktime == 0; } /* BOLT #5: From c604c4bc8d411cb3788908249abf88b95eb61c51 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 18 Nov 2022 13:55:30 -0500 Subject: [PATCH 213/283] migrate more over to eltoo --- onchaind/eltoo_onchaind.c | 354 +++----------------------------------- 1 file changed, 28 insertions(+), 326 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 655bcf17221a..cb1aad857055 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -39,20 +39,6 @@ static struct bitcoin_tx *committed_update_tx, *committed_settle_tx; /* Required in various places: keys for commitment transaction. */ static const struct eltoo_keyset *keyset; -/* The dust limit to use when we generate transactions. */ -static struct amount_sat dust_limit; - -/* The CSV delays for each side. */ -static u32 to_self_delay[NUM_SIDES]; - -/* Where we send money to (our wallet) */ -static u32 our_wallet_index; -static struct ext_key our_wallet_ext_key; -static struct pubkey our_wallet_pubkey; - -/* Their revocation secret (only if they cheated). */ -static const struct secret *remote_per_commitment_secret; - /* When to tell master about HTLCs which are missing/timed out */ static u32 reasonable_depth; @@ -65,16 +51,13 @@ static u8 **queued_msgs; /* Our recorded channel balance at 'chain time' */ static struct amount_msat our_msat; -/* The minimum relay feerate acceptable to the fullnode. */ -static u32 min_relay_feerate; - /* If we broadcast a tx, or need a delay to resolve the output. */ struct proposed_resolution { /* This can be NULL if our proposal is to simply ignore it after depth */ const struct bitcoin_tx *tx; /* Non-zero if this is CSV-delayed. */ u32 depth_required; - enum tx_type tx_type; + enum eltoo_tx_type tx_type; }; /* How it actually got resolved. */ @@ -139,234 +122,6 @@ static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) tal_free(mvt); } -static u8 *penalty_to_us(const tal_t *ctx, - struct bitcoin_tx *tx, - const u8 *wscript) -{ - return towire_hsmd_sign_penalty_to_us(ctx, remote_per_commitment_secret, - tx, wscript); -} - -/** replace_penalty_tx_to_us - * - * @brief creates a replacement TX for - * a given penalty tx. - * - * @param ctx - the context to allocate - * off of. - * @param hsm_sign_msg - function to construct - * the signing message to HSM. - * @param penalty_tx - the original - * penalty transaction. - * @param output_amount - the output - * amount to use instead of the - * original penalty transaction. - * If this amount is below the dust - * limit, the output is replaced with - * an `OP_RETURN` instead. - * - * @return the signed transaction. - */ -static struct bitcoin_tx * -replace_penalty_tx_to_us(const tal_t *ctx, - u8 *(*hsm_sign_msg)(const tal_t *ctx, - struct bitcoin_tx *tx, - const u8 *wscript), - const struct bitcoin_tx *penalty_tx, - struct amount_sat *output_amount) -{ - struct bitcoin_tx *tx; - - /* The penalty tx input. */ - const struct wally_tx_input *input; - /* Specs of the penalty tx input. */ - struct bitcoin_outpoint input_outpoint; - u8 *input_wscript; - u8 *input_element; - struct amount_sat input_amount; - - /* Signature from the HSM. */ - u8 *msg; - struct bitcoin_signature sig; - /* Witness we generate from the signature and other data. */ - u8 **witness; - - - /* Get the single input of the penalty tx. */ - input = &penalty_tx->wtx->inputs[0]; - /* Extract the input-side data. */ - bitcoin_tx_input_get_txid(penalty_tx, 0, &input_outpoint.txid); - input_outpoint.n = input->index; - input_wscript = tal_dup_arr(tmpctx, u8, - input->witness->items[2].witness, - input->witness->items[2].witness_len, - 0); - input_element = tal_dup_arr(tmpctx, u8, - input->witness->items[1].witness, - input->witness->items[1].witness_len, - 0); - input_amount = psbt_input_get_amount(penalty_tx->psbt, 0); - - /* Create the replacement. */ - tx = bitcoin_tx(ctx, chainparams, 1, 1, /*locktime*/ 0); - /* Reconstruct the input. */ - bitcoin_tx_add_input(tx, &input_outpoint, - BITCOIN_TX_RBF_SEQUENCE, - NULL, input_amount, NULL, input_wscript, NULL, NULL); - /* Reconstruct the output with a smaller amount. */ - if (amount_sat_greater(*output_amount, dust_limit)) { - bitcoin_tx_add_output(tx, - scriptpubkey_p2wpkh(tx, - &our_wallet_pubkey), - NULL, - *output_amount); - psbt_add_keypath_to_last_output(tx, our_wallet_index, &our_wallet_ext_key); - } else { - bitcoin_tx_add_output(tx, - scriptpubkey_opreturn_padded(tx), - NULL, - AMOUNT_SAT(0)); - *output_amount = AMOUNT_SAT(0); - } - - /* Finalize the transaction. */ - bitcoin_tx_finalize(tx); - - /* Ask HSM to sign it. */ - if (!wire_sync_write(HSM_FD, take(hsm_sign_msg(NULL, tx, - input_wscript)))) - status_failed(STATUS_FAIL_HSM_IO, "While feebumping penalty: writing sign request to hsm"); - msg = wire_sync_read(tmpctx, HSM_FD); - if (!msg || !fromwire_hsmd_sign_tx_reply(msg, &sig)) - status_failed(STATUS_FAIL_HSM_IO, "While feebumping penalty: reading sign_tx_reply: %s", tal_hex(tmpctx, msg)); - - /* Install the witness with the signature. */ - witness = bitcoin_witness_sig_and_element(tx, &sig, - input_element, - tal_bytelen(input_element), - input_wscript); - bitcoin_tx_input_set_witness(tx, 0, take(witness)); - - return tx; -} - -/** min_rbf_bump - * - * @brief computes the minimum RBF bump required by - * BIP125, given an index. - * - * @desc BIP125 requires that an replacement transaction - * pay, not just the fee of the evicted transactions, - * but also the minimum relay fee for itself. - * This function assumes that previous RBF attempts - * paid exactly the return value for that attempt, on - * top of the initial transaction fee. - * It can serve as a baseline for other functions that - * compute a suggested fee: get whichever is higher, - * the fee this function suggests, or your own unique - * function. - * - * This function is provided as a common function that - * all RBF-bump computations can use. - * - * @param weight - the weight of the transaction you - * are RBFing. - * @param index - 0 makes no sense, 1 means this is - * the first RBF attempt, 2 means this is the 2nd - * RBF attempt, etc. - * - * @return the suggested total fee. - */ -static struct amount_sat min_rbf_bump(size_t weight, - size_t index) -{ - struct amount_sat min_relay_fee; - struct amount_sat min_rbf_bump; - - /* Compute the minimum relay fee for a transaction of the given - * weight. */ - min_relay_fee = amount_tx_fee(min_relay_feerate, weight); - - /* For every RBF attempt, we add the min-relay-fee. - * Or in other words, we multiply the min-relay-fee by the - * index number of the attempt. - */ - if (mul_overflows_u64(index, min_relay_fee.satoshis)) /* Raw: multiplication. */ - min_rbf_bump = AMOUNT_SAT(UINT64_MAX); - else - min_rbf_bump.satoshis = index * min_relay_fee.satoshis; /* Raw: multiplication. */ - - return min_rbf_bump; -} - -/** compute_penalty_output_amount - * - * @brief computes the appropriate output amount for a - * penalty transaction that spends a theft transaction - * that is already of a specific depth. - * - * @param initial_amount - the outout amount of the first - * penalty transaction. - * @param depth - the current depth of the theft - * transaction. - * @param max_depth - the maximum depth of the theft - * transaction, after which the theft transaction will - * succeed. - * @param weight - the weight of the first penalty - * transaction, in Sipa. - */ -static struct amount_sat -compute_penalty_output_amount(struct amount_sat initial_amount, - u32 depth, u32 max_depth, - size_t weight) -{ - struct amount_sat max_output_amount; - struct amount_sat output_amount; - struct amount_sat deducted_amount; - - assert(depth <= max_depth); - assert(depth > 0); - - /* The difference between initial_amount, and the fee suggested - * by min_rbf_bump, is the largest allowed output amount. - * - * depth = 1 is the first attempt, thus maps to the 0th RBF - * (i.e. the initial attempt that is not RBFed itself). - * We actually start to replace at depth = 2, so we use - * depth - 1 as the index for min_rbf_bump. - */ - if (!amount_sat_sub(&max_output_amount, - initial_amount, min_rbf_bump(weight, depth - 1))) - /* If min_rbf_bump is larger than the initial_amount, - * we should just donate the whole output as fee, - * meaning we get 0 output amount. - */ - return AMOUNT_SAT(0); - - /* Map the depth / max_depth into a number between 0->1. */ - double x = (double) depth / (double) max_depth; - /* Get the cube of the above position, resulting in a graph - * where the y is close to 0 up to less than halfway through, - * then quickly rises up to 1 as depth nears the max depth. - */ - double y = x * x * x; - /* Scale according to the initial_amount. */ - deducted_amount.satoshis = (u64) (y * initial_amount.satoshis); /* Raw: multiplication. */ - - /* output_amount = initial_amount - deducted_amount. */ - if (!amount_sat_sub(&output_amount, - initial_amount, deducted_amount)) - /* If underflow, force to 0. */ - output_amount = AMOUNT_SAT(0); - - /* If output exceeds max, return max. */ - if (amount_sat_less(max_output_amount, output_amount)) - return max_output_amount; - - return output_amount; -} - - static struct tracked_output * new_tracked_output(struct tracked_output ***outs, const struct bitcoin_outpoint *outpoint, @@ -418,55 +173,40 @@ static void ignore_output(struct tracked_output *out) out->resolved->tx_type = SELF; } -static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum tx_type t) +static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum eltoo_tx_type t) { + /* FIXME put eltoo_tx_type into proper wallet_tx_type */ switch (t) { - case FUNDING_TRANSACTION: + case ELTOO_FUNDING_TRANSACTION: return TX_CHANNEL_FUNDING; - case MUTUAL_CLOSE: + case ELTOO_MUTUAL_CLOSE: return TX_CHANNEL_CLOSE; - case OUR_UNILATERAL: - return TX_CHANNEL_UNILATERAL; - case THEIR_HTLC_FULFILL_TO_US: - case OUR_HTLC_SUCCESS_TX: - return TX_CHANNEL_HTLC_SUCCESS; - case OUR_HTLC_TIMEOUT_TO_US: - case OUR_HTLC_TIMEOUT_TX: - return TX_CHANNEL_HTLC_TIMEOUT; - case OUR_DELAYED_RETURN_TO_WALLET: - case SELF: - return TX_CHANNEL_SWEEP; - case OUR_PENALTY_TX: - return TX_CHANNEL_PENALTY; - case THEIR_DELAYED_CHEAT: - return TX_CHANNEL_CHEAT | TX_THEIRS; - case THEIR_UNILATERAL: - case UNKNOWN_UNILATERAL: - case THEIR_REVOKED_UNILATERAL: - return TX_CHANNEL_UNILATERAL | TX_THEIRS; - case THEIR_HTLC_TIMEOUT_TO_THEM: - return TX_CHANNEL_HTLC_TIMEOUT | TX_THEIRS; - case OUR_HTLC_FULFILL_TO_THEM: - return TX_CHANNEL_HTLC_SUCCESS | TX_THEIRS; - case IGNORING_TINY_PAYMENT: - case UNKNOWN_TXTYPE: + case ELTOO_UPDATE: + case ELTOO_INVALIDATED_UPDATE: + case ELTOO_SETTLE: + case ELTOO_INVALIDATED_SETTLE: + case ELTOO_SWEEP: + case ELTOO_IGNORING_TINY_PAYMENT: + case ELTOO_SELF: + case ELTOO_UNKNOWN_TXTYPE: return TX_UNKNOWN; } abort(); } -/** proposal_is_rbfable +/** eltoo_proposal_is_rbfable * * @brief returns true if the given proposal * would be RBFed if the output it is tracking * increases in depth without being spent. */ -static bool proposal_is_rbfable(const struct proposed_resolution *proposal) +static bool eltoo_proposal_is_rbfable(const struct proposed_resolution *proposal) { - /* Future onchain resolutions, such as anchored commitments, might - * want to RBF as well. + /* We may fee bump anything time-sensitive */ - return proposal->tx_type == OUR_PENALTY_TX; + return proposal->tx_type == ELTOO_UPDATE || + proposal->tx_type == ELTOO_SETTLE || + proposal->tx_type == ELTOO_SWEEP; } /** proposal_should_rbf @@ -476,15 +216,15 @@ static bool proposal_is_rbfable(const struct proposed_resolution *proposal) * rebroadcast. * * @desc precondition: the given output must have an - * rbfable proposal as per `proposal_is_rbfable`. + * rbfable proposal as per `eltoo_proposal_is_rbfable`. */ -static void proposal_should_rbf(struct tracked_output *out) +static void eltoo_proposal_should_rbf(struct tracked_output *out) { struct bitcoin_tx *tx = NULL; u32 depth; assert(out->proposal); - assert(proposal_is_rbfable(out->proposal)); + assert(eltoo_proposal_is_rbfable(out->proposal)); depth = out->depth; @@ -500,43 +240,6 @@ static void proposal_should_rbf(struct tracked_output *out) if (depth <= 1) return; - if (out->proposal->tx_type == OUR_PENALTY_TX) { - u32 max_depth = to_self_delay[REMOTE]; - u32 my_depth = depth; - size_t weight = bitcoin_tx_weight(out->proposal->tx); - struct amount_sat initial_amount; - struct amount_sat new_amount; - - if (max_depth >= 1) - max_depth -= 1; - if (my_depth >= max_depth) - my_depth = max_depth; - - bitcoin_tx_output_get_amount_sat(out->proposal->tx, 0, - &initial_amount); - - /* Compute the new output amount for the RBF. */ - new_amount = compute_penalty_output_amount(initial_amount, - my_depth, max_depth, - weight); - assert(amount_sat_less_eq(new_amount, initial_amount)); - /* Recreate the penalty tx. */ - tx = replace_penalty_tx_to_us(tmpctx, - &penalty_to_us, - out->proposal->tx, &new_amount); - - /* We also update the output's value, so our accounting - * is correct. */ - out->sat = new_amount; - - status_debug("Created RBF OUR_PENALTY_TX with output %s " - "(originally %s) for depth %"PRIu32"/%"PRIu32".", - type_to_string(tmpctx, struct amount_sat, - &new_amount), - type_to_string(tmpctx, struct amount_sat, - &initial_amount), - depth, to_self_delay[LOCAL]); - } /* Add other RBF-able proposals here. */ /* Broadcast the transaction. */ @@ -577,9 +280,10 @@ static void proposal_meets_depth(struct tracked_output *out) output_type_name(out->output_type)); if (out->proposal) - /* Our own penalty transactions are going to be RBFed. */ - is_rbf = proposal_is_rbfable(out->proposal); + /* Any state transition we want is going to be package-RBFed. */ + is_rbf = eltoo_proposal_is_rbfable(out->proposal); + /* FIXME Figure out how fees are going to be paid via anchor */ wire_sync_write( REQ_FD, take(towire_onchaind_broadcast_tx( @@ -588,7 +292,7 @@ static void proposal_meets_depth(struct tracked_output *out) is_rbf))); /* Don't wait for this if we're ignoring the tiny payment. */ - if (out->proposal->tx_type == IGNORING_TINY_PAYMENT) { + if (out->proposal->tx_type == ELTOO_IGNORING_TINY_PAYMENT) { ignore_output(out); } @@ -1062,8 +766,6 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, if (outs[i]->proposal && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) && depth >= outs[i]->proposal->depth_required) { - /* ELTOO: We don't need any delays anywhere */ - assert(outs[i]->proposal->depth_required == 0); proposal_meets_depth(outs[i]); } @@ -1071,8 +773,8 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, * we should RBF? */ if (outs[i]->proposal && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) - && proposal_is_rbfable(outs[i]->proposal)) - proposal_should_rbf(outs[i]); + && eltoo_proposal_is_rbfable(outs[i]->proposal)) + eltoo_proposal_should_rbf(outs[i]); } } From 446cbee8e4aaa58f05241e21eaf8445122f30051 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 18 Nov 2022 14:14:44 -0500 Subject: [PATCH 214/283] fixup tx type --- onchaind/eltoo_onchaind.c | 67 ++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index cb1aad857055..49eb0354c1da 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -93,13 +93,13 @@ struct tracked_output { struct sha256 payment_hash; }; -static const char *tx_type_name(enum tx_type tx_type) +static const char *eltoo_tx_type_name(enum eltoo_tx_type tx_type) { size_t i; - for (i = 0; enum_tx_type_names[i].name; i++) - if (enum_tx_type_names[i].v == tx_type) - return enum_tx_type_names[i].name; + for (i = 0; enum_eltoo_tx_type_names[i].name; i++) + if (enum_eltoo_tx_type_names[i].v == tx_type) + return enum_eltoo_tx_type_names[i].name; return "unknown"; } @@ -137,7 +137,7 @@ new_tracked_output(struct tracked_output ***outs, status_debug("Tracking output %s: %s/%s", type_to_string(tmpctx, struct bitcoin_outpoint, outpoint), - tx_type_name(tx_type), + eltoo_tx_type_name(tx_type), output_type_name(output_type)); out->tx_type = tx_type; @@ -164,7 +164,7 @@ static void ignore_output(struct tracked_output *out) status_debug("Ignoring output %s: %s/%s", type_to_string(tmpctx, struct bitcoin_outpoint, &out->outpoint), - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type)); out->resolved = tal(out, struct resolution); @@ -248,9 +248,9 @@ static void eltoo_proposal_should_rbf(struct tracked_output *out) status_debug("Broadcasting RBF %s (%s) to resolve %s/%s " "depth=%"PRIu32"", - tx_type_name(out->proposal->tx_type), + eltoo_tx_type_name(out->proposal->tx_type), type_to_string(tmpctx, struct bitcoin_tx, tx), - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), depth); @@ -262,21 +262,20 @@ static void eltoo_proposal_should_rbf(struct tracked_output *out) } } -static void proposal_meets_depth(struct tracked_output *out) +static void eltoo_proposal_meets_depth(struct tracked_output *out) { bool is_rbf = false; - /* If we simply wanted to ignore it after some depth */ + /* If there's no proposal, we're not gonna do anything. */ if (!out->proposal->tx) { ignore_output(out); - return; } status_debug("Broadcasting %s (%s) to resolve %s/%s", - tx_type_name(out->proposal->tx_type), + eltoo_tx_type_name(out->proposal->tx_type), type_to_string(tmpctx, struct bitcoin_tx, out->proposal->tx), - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type)); if (out->proposal) @@ -367,9 +366,9 @@ static bool resolved_by_proposal(struct tracked_output *out, out->resolved = tal(out, struct resolution); out->resolved->txid = tx_parts->txid; status_debug("Resolved %s/%s by our proposal %s (%s)", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), - tx_type_name(out->proposal->tx_type), + eltoo_tx_type_name(out->proposal->tx_type), type_to_string(tmpctx, struct bitcoin_txid, &out->resolved->txid)); @@ -389,9 +388,9 @@ static void resolved_by_other(struct tracked_output *out, out->resolved->tx_type = tx_type; status_debug("Resolved %s/%s by %s (%s)", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), - tx_type_name(tx_type), + eltoo_tx_type_name(tx_type), type_to_string(tmpctx, struct bitcoin_txid, txid)); } @@ -445,7 +444,7 @@ static void billboard_update(struct tracked_output **outs) type_to_string(tmpctx, struct bitcoin_outpoint, &best->outpoint), - tx_type_name(best->proposal->tx_type)); + eltoo_tx_type_name(best->proposal->tx_type)); } else { peer_billboard(false, "%u outputs unresolved: in %u blocks will spend %s (%s) using %s", @@ -455,7 +454,7 @@ static void billboard_update(struct tracked_output **outs) type_to_string(tmpctx, struct bitcoin_outpoint, &best->outpoint), - tx_type_name(best->proposal->tx_type)); + eltoo_tx_type_name(best->proposal->tx_type)); } return; } @@ -492,9 +491,9 @@ static void propose_resolution(struct tracked_output *out, enum tx_type tx_type) { status_debug("Propose handling %s/%s by %s (%s) after %u blocks", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), - tx_type_name(tx_type), + eltoo_tx_type_name(tx_type), tx ? type_to_string(tmpctx, struct bitcoin_tx, tx):"IGNORING", depth_required); @@ -504,7 +503,7 @@ static void propose_resolution(struct tracked_output *out, out->proposal->tx_type = tx_type; if (depth_required == 0) - proposal_meets_depth(out); + eltoo_proposal_meets_depth(out); } static void unwatch_txid(const struct bitcoin_txid *txid) @@ -535,7 +534,7 @@ static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, if (tx_parts->inputs[htlc_outpoint->n]->witness->num_items != 4) /* +2 for script/control block */ status_failed(STATUS_FAIL_INTERNAL_ERROR, "%s/%s spent with weird witness %zu", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), tx_parts->inputs[htlc_outpoint->n]->witness->num_items); @@ -544,7 +543,7 @@ static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, } else status_failed(STATUS_FAIL_INTERNAL_ERROR, "onchain_fulfill for %s/%s?", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type)); memcpy(&preimage, preimage_item->witness, sizeof(preimage)); @@ -554,7 +553,7 @@ static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, if (!ripemd160_eq(&ripemd, &out->htlc.ripemd)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "%s/%s spent with bad preimage %s (ripemd not %s)", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), type_to_string(tmpctx, struct preimage, &preimage), type_to_string(tmpctx, struct ripemd160, @@ -566,7 +565,7 @@ static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, /* Tell master we found a preimage. */ status_debug("%s/%s gave us preimage %s", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), type_to_string(tmpctx, struct preimage, &preimage)); wire_sync_write(REQ_FD, @@ -670,7 +669,7 @@ static void output_spent(struct tracked_output ***outs, case ANCHOR_TO_THEM: status_failed(STATUS_FAIL_INTERNAL_ERROR, "Tracked spend of %s/%s?", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type)); } return; @@ -691,9 +690,9 @@ static void update_resolution_depth(struct tracked_output *out, u32 depth) bool reached_reasonable_depth; status_debug("%s/%s->%s depth %u", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), - tx_type_name(out->resolved->tx_type), + eltoo_tx_type_name(out->resolved->tx_type), depth); /* We only set this once. */ @@ -715,7 +714,7 @@ static void update_resolution_depth(struct tracked_output *out, u32 depth) if (out->resolved->tx_type == ELTOO_SWEEP && reached_reasonable_depth) { u8 *msg; status_debug("%s/%s reached reasonable depth %u", - tx_type_name(out->tx_type), + eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), depth); msg = towire_onchaind_htlc_timeout(out, &out->htlc); @@ -729,10 +728,6 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, { size_t i; - /* FIXME React to final update tx getting shared_delay old */ - - /* FIXME React to settlement transaction being mined */ - /* Special handling for funding-spending update tx reaching depth */ /* FIXME re-add note_missing_htlcs for TRIMMED ONLY here... should this b * done immediately, not at "reasonable depth"? @@ -766,7 +761,7 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, if (outs[i]->proposal && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) && depth >= outs[i]->proposal->depth_required) { - proposal_meets_depth(outs[i]); + eltoo_proposal_meets_depth(outs[i]); } /* Otherwise, is this an output whose proposed resolution @@ -803,7 +798,7 @@ static void eltoo_handle_preimage(struct tracked_output **outs, if (outs[i]->resolved) { status_broken("HTLC already resolved by %s" " when we found preimage", - tx_type_name(outs[i]->resolved->tx_type)); + eltoo_tx_type_name(outs[i]->resolved->tx_type)); return; } From e89dfdb544c5fe558cb3e4423558d87e8d8400ab Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 18 Nov 2022 16:02:36 -0500 Subject: [PATCH 215/283] Basic settlement broadcasting works --- contrib/startup_regtest.sh | 14 ++++++++++++++ lightningd/onchain_control.c | 34 +++++++++++++++++++++------------- onchaind/eltoo_onchaind.c | 3 +++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index cf8ce2a06c80..2c21fd3975ef 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -172,6 +172,20 @@ onchain_ln() { # Should be bound to funding output! UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_settle_tx ) + + ### THIS + + # Test for latest update hitting chain + txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) + bt-cli prioritisetransaction $txid 0 100000000 + txid=$(bt-cli decoderawtransaction $SETTLE_HEX | jq -r .txid) + bt-cli prioritisetransaction $txid 0 100000000 + bt-cli sendrawtransaction $UPDATE_HEX + bt-cli generatetoaddress 7 $btcaddr + + ### OR + + # Test for old update hitting chain txid=$(bt-cli decoderawtransaction $FIRST_UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $FIRST_UPDATE_HEX diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index b2300854ea7a..33d4e432cf79 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -143,7 +143,8 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m struct htlc_stub *stubs; bool *tell, *tell_immediate; /* We are only interested in latest HTLCs, the ones we will recall */ - u64 commit_num = channel->last_tx->wtx->locktime; + u64 complete_update_num = channel->eltoo_keyset.complete_update_tx->wtx->locktime; + // u64 committed_update_num = complete_update_num + 1; /* May not exist, that's ok */ /* Signaling ready, send more data */ if (!fromwire_eltoo_onchaind_init_reply(msg)) { @@ -154,15 +155,14 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m /* FIXME: We may already be ONCHAIN state when we implement restart! */ channel_set_state(channel, - FUNDING_SPEND_SEEN, - ONCHAIN, + FUNDING_SPEND_SEEN /* old_state */, + ONCHAIN /* state */, REASON_UNKNOWN, "Onchain init reply"); - /* Tell it about any relevant HTLCs - * FIXME (only one set for eltoo... we shouldn't be storing everything) */ + /* Tell it about any relevant HTLCs */ stubs = wallet_htlc_stubs(tmpctx, channel->peer->ld->wallet, channel, - commit_num); + complete_update_num); tell = tal_arr(stubs, bool, tal_count(stubs)); tell_immediate = tal_arr(stubs, bool, tal_count(stubs)); @@ -174,7 +174,21 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m subd_send_msg(channel->owner, take(msg)); - /* Tell it about any preimages we know. */ + /* FIXME Do the same steps again for committed htlcs, if they exist + stubs = wallet_htlc_stubs(tmpctx, channel->peer->ld->wallet, channel, + committed_update_num); + tell = tal_arr(stubs, bool, tal_count(stubs)); + tell_immediate = tal_arr(stubs, bool, tal_count(stubs)); + + for (size_t i = 0; i < tal_count(stubs); i++) { + tell[i] = tell_if_missing(channel, &stubs[i], + &tell_immediate[i]); + } + msg = towire_onchaind_htlcs(channel, stubs, tell, tell_immediate); + + subd_send_msg(channel->owner, take(msg)); */ + + /* Finally, ell it about any preimages we know. */ onchaind_tell_fulfill(channel); } @@ -923,12 +937,6 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, return KEEP_WATCHING; } - channel_set_state(channel, - FUNDING_SPEND_SEEN, - ONCHAIN, - REASON_UNKNOWN, - "Onchain init reply"); - /* Add HTLCs to init, since we know which HTLCs will be exposed */ msg = towire_eltoo_onchaind_init(channel, chainparams, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 49eb0354c1da..d97e0385bdf4 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1066,6 +1066,9 @@ int main(int argc, char *argv[]) status_setup_sync(REQ_FD); + missing_htlc_msgs = tal_arr(ctx, u8 *, 0); + queued_msgs = tal_arr(ctx, u8 *, 0); + msg = wire_sync_read(tmpctx, REQ_FD); if (!fromwire_eltoo_onchaind_init(tmpctx, msg, From 8eed3b68737534162e7defdb4545d2e52be667b8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 22 Nov 2022 13:59:57 -0500 Subject: [PATCH 216/283] Sync up tx format with BOLT, update handling --- bitcoin/script.c | 63 ++++---- bitcoin/script.h | 9 +- channeld/settle_tx.c | 2 +- common/initial_settlement_tx.c | 30 +--- common/initial_settlement_tx.h | 3 + lightningd/onchain_control.c | 6 +- onchaind/eltoo_onchaind.c | 254 +++++++++++++++++++++++++++++---- onchaind/onchaind_wire.csv | 4 + 8 files changed, 280 insertions(+), 91 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 055e6c41af69..9589269e2e55 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -540,6 +540,33 @@ bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr) return true; } +bool is_p2tr(const u8 *script, u8 *xonly_pubkey) +{ + size_t script_len = tal_count(script); + + if (script_len != BITCOIN_SCRIPTPUBKEY_P2TR_LEN) + return false; + if (script[0] != OP_1) + return false; + /* x-only pubkey */ + if (script[1] != OP_PUSHBYTES(32)) + return false; + if (xonly_pubkey) + memcpy(xonly_pubkey, script+2, 32); + return true; +} + +bool is_ephemeral_anchor(const u8 *script) +{ + size_t script_len = tal_count(script); + + if (script_len != 1) + return false; + if (script[0] != OP_1) + return false; + return true; +} + bool is_known_scripttype(const u8 *script) { return is_p2wpkh(script, NULL) || is_p2wsh(script, NULL) @@ -957,24 +984,6 @@ u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx) return script; } -u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_pubkey) -{ - u8 *script = tal_arr(ctx, u8, 0); - - /* BOLT #?? - * `tr(aggregated_key, EXPR_BALANCE)` - * - * where EXPR_BALANCE = - * - * 1 OP_CHECKSEQUENCEVERIFY settlement_pubkey OP_CHECKSIGVERIFY - */ - add_push_xonly_key(&script, settlement_pubkey); - add_op(&script, OP_CHECKSIGVERIFY); - add_number(&script, 1); - add_op(&script, OP_CHECKSEQUENCEVERIFY); - return script; -} - void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts) { int ok; @@ -1208,8 +1217,8 @@ u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settle { /* where EXPR_SUCCESS = * - * ` OP_CHECKSIGVERIFY OP_SIZE <32> OP_EQUALVERIFY OP_HASH160 - * OP_EQUALVERIFY 1 OP_CHECKSEQUENCEVERIFY` + * ` OP_CHECKSIGVERIFY OP_SIZE <20> OP_EQUALVERIFY OP_HASH160 +OP_EQUAL` */ u8 *script = tal_arr(ctx, u8, 0); add_push_xonly_key(&script, settlement_pubkey); @@ -1219,9 +1228,7 @@ u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settle add_op(&script, OP_EQUALVERIFY); add_op(&script, OP_HASH160); script_push_bytes(&script, invoice_hash, 20); - add_op(&script, OP_EQUALVERIFY); - add_number(&script, 1); - add_op(&script, OP_CHECKSEQUENCEVERIFY); + add_op(&script, OP_EQUAL); return script; } @@ -1229,16 +1236,12 @@ u8 *make_eltoo_htlc_timeout_script(const tal_t *ctx, const struct pubkey *settle { /* and EXPR_TIMEOUT = * - *` OP_CHECKLOCKTIMEVERIFY OP_VERIFY OP_CHECKSIGVERIFY 1 - * OP_CHECKSEQUENCEVERIFY` + * ` OP_CHECKSIGVERIFY N OP_CHECKLOCKTIMEVERIFY` */ u8 *script = tal_arr(ctx, u8, 0); - add_number(&script, htlc_timeout); - add_op(&script, OP_CHECKLOCKTIMEVERIFY); - add_op(&script, OP_VERIFY); add_push_xonly_key(&script, settlement_pubkey); add_op(&script, OP_CHECKSIGVERIFY); - add_number(&script, 1); - add_op(&script, OP_CHECKSEQUENCEVERIFY); + add_number(&script, htlc_timeout); + add_op(&script, OP_CHECKLOCKTIMEVERIFY); return script; } diff --git a/bitcoin/script.h b/bitcoin/script.h index 956f532750a6..a3093ba0695e 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -159,6 +159,12 @@ bool is_p2wsh(const u8 *script, struct sha256 *addr); /* Is this (version 0) pay to witness pubkey hash? (extract addr if not NULL) */ bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr); +/* Is this a taproot output? (exract xonly_pubkey bytes if not NULL) */ +bool is_p2tr(const u8 *script, u8 *xonly_pubkey); + +/* Is this output an ephemeral anchor? */ +bool is_ephemeral_anchor(const u8 *script); + /* Is this one of the four above script types? */ bool is_known_scripttype(const u8 *script); @@ -174,9 +180,6 @@ void script_push_bytes(u8 **scriptp, const void *mem, size_t len); /* "anyonecanspend" Ephemeral anchor outputs */ u8 *bitcoin_spk_ephemeral_anchor(const tal_t *ctx); -/* to_node balance output script with anti-pinning 1 block CSV */ -u8 *bitcoin_tapscript_to_node(const tal_t *ctx, const struct pubkey *settlement_pubkey); - /* Computes taproot merkle root from list of up to two scripts in depth 1 tree, in order */ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts); diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index a91e35d2f740..3c378224873b 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -77,7 +77,7 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, htlc_scripts[0] = make_eltoo_htlc_success_script(tx, receiver_pubkey, htlc->rhash.u.u8); htlc_scripts[1] = make_eltoo_htlc_timeout_script(tx, sender_pubkey, htlc->expiry.locktime); compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); - bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 1, + bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out); taproot_script = scriptpubkey_p2tr(tx, &taproot_pubkey); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 16d515162a2c..5df9e5805b00 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -14,33 +14,11 @@ int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *eltoo_keyset, struct amount_msat pay, enum side receiver) { - struct pubkey taproot_pk; - secp256k1_musig_keyagg_cache keyagg_cache; - struct sha256 tap_merkle_root; - struct sha256 tap_tweak_out; - u8 *tapleaf_scripts[1]; - struct pubkey const *receiver_pubkey; - struct pubkey const *pubkey_ptrs[2]; - struct amount_sat amount; - - if (receiver == LOCAL) { - receiver_pubkey = &eltoo_keyset->self_settle_key; - } else { - receiver_pubkey = &eltoo_keyset->other_settle_key; - } - - pubkey_ptrs[0] = &eltoo_keyset->self_funding_key; - pubkey_ptrs[1] = &eltoo_keyset->other_funding_key; - - tapleaf_scripts[0] = bitcoin_tapscript_to_node(tmpctx, receiver_pubkey); - printf("RECEIVER: %u, RECEIVER(SETTLE) PUBKEY: %s, SELF TO NODE: %s\n", receiver, tal_hexstr(tmpctx, receiver_pubkey, 33), tal_hexstr(tmpctx, tapleaf_scripts[0], tal_count(tapleaf_scripts[0]))); - compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 1); - bipmusig_finalize_keys(&taproot_pk, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out.u.u8); - - amount = amount_msat_to_sat_round_down(pay); return bitcoin_tx_add_output( - tx, scriptpubkey_p2tr(tmpctx, &taproot_pk), /* wscript */ NULL, amount /* FIXME pass in psbt fields for tap outputs */); + tx, scriptpubkey_p2tr(tmpctx, + receiver == LOCAL ? &eltoo_keyset->self_settle_key : &eltoo_keyset->other_settle_key), + /* wscript */ NULL, + amount_msat_to_sat_round_down(pay)); } void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h index 54e299862cae..7b77712c1df5 100644 --- a/common/initial_settlement_tx.h +++ b/common/initial_settlement_tx.h @@ -41,6 +41,9 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx); int tx_add_to_node_output(struct bitcoin_tx *tx, const struct eltoo_keyset *eltoo_keyset, struct amount_msat pay, enum side receiver); +/* Generate to_node spk based on keyset */ +u8 *compute_to_node_spk(const struct eltoo_keyset *eltoo_keyset, enum side receiver); + void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *update_outpoint, struct amount_sat update_outpoint_sats, u32 shared_delay, const struct pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]); #endif /* LIGHTNING_COMMON_INITIAL_SETTLEMENT_TX_H */ diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 33d4e432cf79..9bc45ac2ed9c 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -951,7 +951,11 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, blockheight, channel->our_msat, channel->shutdown_scriptpubkey[LOCAL], - channel->shutdown_scriptpubkey[REMOTE] + channel->shutdown_scriptpubkey[REMOTE], + &channel->eltoo_keyset.self_funding_key, + &channel->eltoo_keyset.other_funding_key, + &channel->eltoo_keyset.self_settle_key, + &channel->eltoo_keyset.other_settle_key ); subd_send_msg(channel->owner, take(msg)); diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index d97e0385bdf4..71f481364dc4 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -37,7 +37,7 @@ static struct bitcoin_tx *complete_update_tx, *complete_settle_tx; static struct bitcoin_tx *committed_update_tx, *committed_settle_tx; /* Required in various places: keys for commitment transaction. */ -static const struct eltoo_keyset *keyset; +static struct eltoo_keyset *keyset; /* When to tell master about HTLCs which are missing/timed out */ static u32 reasonable_depth; @@ -76,12 +76,10 @@ struct tracked_output { struct amount_sat sat; enum output_type output_type; - /* If it is an HTLC, this is set, wscript is non-NULL. */ + /* If it is an HTLC, this is set, tapscripts are non-NULL. */ struct htlc_stub htlc; - const u8 *wscript; - - /* If it's an HTLC off our unilateral, this is their sig for htlc_tx */ - const struct bitcoin_signature *remote_htlc_sig; + const u8 *htlc_success_tapscript; /* EXPR_SUCCESS */ + const u8 *htlc_timeout_tapscript; /* EXPR_TIMEOUT */ /* Our proposed solution (if any) */ struct proposed_resolution *proposal; @@ -122,6 +120,87 @@ static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) tal_free(mvt); } +static u8 **derive_htlc_success_scripts(const struct htlc_stub *htlcs, const struct pubkey *our_htlc_pubkey, const struct pubkey *their_htlc_pubkey) +{ + size_t i; + u8 **htlc_scripts = tal_arr(htlcs, u8 *, tal_count(htlcs)); + + for (i = 0; i < tal_count(htlcs); i++) { + htlc_scripts[i] = make_eltoo_htlc_success_script(htlc_scripts, + htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, + htlcs[i].ripemd.u.u8); + } + return htlc_scripts; +} + +static u8 **derive_htlc_timeout_scripts(const struct htlc_stub *htlcs, const struct pubkey *our_htlc_pubkey, const struct pubkey *their_htlc_pubkey) +{ + size_t i; + u8 **htlc_scripts = tal_arr(htlcs, u8 *, tal_count(htlcs)); + + for (i = 0; i < tal_count(htlcs); i++) { + htlc_scripts[i] = make_eltoo_htlc_timeout_script(htlc_scripts, + htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, + htlcs[i].cltv_expiry); + } + return htlc_scripts; +} + +/* They must all be in the same direction, since the scripts are different for + * each dir. Unless, of course, they've found a sha256 clash. */ +static enum side matches_direction(const size_t *matches, + const struct htlc_stub *htlcs) +{ + for (size_t i = 1; i < tal_count(matches); i++) { + assert(matches[i] < tal_count(htlcs)); + assert(htlcs[matches[i]].owner == htlcs[matches[i-1]].owner); + } + return htlcs[matches[0]].owner; +} + +/* Return tal_arr of htlc indexes. */ +static const size_t *eltoo_match_htlc_output(const tal_t *ctx, + const struct wally_tx_output *out, + u8 **htlc_success_scripts, + u8 **htlc_timeout_scripts) +{ + assert(tal_count(htlc_success_scripts) == tal_count(htlc_timeout_scripts)); + + size_t *matches = tal_arr(ctx, size_t, 0); + const u8 *script = tal_dup_arr(tmpctx, u8, out->script, out->script_len, + 0); + /* Must be a p2tr output */ + if (!is_p2tr(script, NULL)) + return matches; + + for (size_t i = 0; i < tal_count(htlc_success_scripts); i++) { + struct sha256 tap_merkle_root; + const struct pubkey *pubkey_ptrs[2]; + struct pubkey taproot_pubkey; + secp256k1_musig_keyagg_cache keyagg_cache; + unsigned char tap_tweak_out[32]; + u8 *htlc_scripts[2]; + u8 *taproot_script; + htlc_scripts[0] = htlc_success_scripts[i]; + htlc_scripts[1] = htlc_timeout_scripts[i]; + + pubkey_ptrs[0] = &keyset->self_settle_key; + pubkey_ptrs[1] = &keyset->other_settle_key; + + if (!htlc_success_scripts[i] || !htlc_timeout_scripts[i]) + continue; + + compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); + bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, + &tap_merkle_root, tap_tweak_out); + taproot_script = scriptpubkey_p2tr(ctx, &taproot_pubkey); + + if (memeq(taproot_script, tal_count(taproot_script), script, sizeof(script))) + tal_arr_expand(&matches, i); + } + return matches; +} + static struct tracked_output * new_tracked_output(struct tracked_output ***outs, const struct bitcoin_outpoint *outpoint, @@ -130,8 +209,8 @@ new_tracked_output(struct tracked_output ***outs, struct amount_sat sat, enum output_type output_type, const struct htlc_stub *htlc, - const u8 *wscript, - const struct bitcoin_signature *remote_htlc_sig TAKES) + const u8 *htlc_success_tapscript TAKES, + const u8 *htlc_timeout_tapscript TAKES) { struct tracked_output *out = tal(*outs, struct tracked_output); @@ -150,9 +229,8 @@ new_tracked_output(struct tracked_output ***outs, out->resolved = NULL; if (htlc) out->htlc = *htlc; - out->wscript = tal_steal(out, wscript); - out->remote_htlc_sig = tal_dup_or_null(out, struct bitcoin_signature, - remote_htlc_sig); + out->htlc_success_tapscript = tal_steal(out, htlc_success_tapscript); + out->htlc_timeout_tapscript = tal_steal(out, htlc_timeout_tapscript); tal_arr_expand(outs, out); @@ -587,11 +665,20 @@ static void onchain_annotate_txin(const struct bitcoin_txid *txid, u32 innum, tmpctx, txid, innum, type))); } +struct htlcs_info { + struct htlc_stub *htlcs; + bool *tell_if_missing; + bool *tell_immediately; +}; + /* An output has been spent: see if it resolves something we care about. */ static void output_spent(struct tracked_output ***outs, const struct tx_parts *tx_parts, u32 input_num, - u32 tx_blockheight) + u32 tx_blockheight, + u8 **htlc_success_scripts, + u8 **htlc_timeout_scripts, + struct htlcs_info *htlcs_info) { for (size_t i = 0; i < tal_count(*outs); i++) { struct tracked_output *out = (*outs)[i]; @@ -606,6 +693,75 @@ static void output_spent(struct tracked_output ***outs, /* Was this our resolution? */ if (resolved_by_proposal(out, tx_parts)) { + if (out->resolved->tx_type == ELTOO_SETTLE) { + /* Settlement transaction has 5 types of outputs it's looking for */ + for (size_t j = 0; j < tal_count(tx_parts->outputs); j++) { + struct wally_tx_output *settle_out = tx_parts->outputs[j]; + struct amount_sat satoshis = amount_sat(settle_out->satoshi); + /* (1) Ephemeral Anchor */ + if (is_ephemeral_anchor(settle_out->script)) { + /* Do we need to handle anchor? */ + continue; + } + const size_t *matches = eltoo_match_htlc_output(tmpctx, settle_out, htlc_success_scripts, htlc_timeout_scripts); + struct bitcoin_outpoint outpoint; + outpoint.txid = tx_parts->txid; + outpoint.n = j; + if (tal_count(matches) == 0) { + if (!is_p2tr(settle_out->script, NULL)) { + /* Everything should be taproot FIXME what do */ + abort(); + } + u8 *to_us = scriptpubkey_p2tr(tmpctx, &keyset->self_settle_key); + if (memcmp(settle_out->script, to_us, tal_count(to_us)) == 0) { + /* (2) `to_node` to us */ + new_tracked_output(outs, &outpoint, + tx_blockheight, + out->resolved->tx_type, + satoshis, + OUTPUT_TO_US /* output_type */, + NULL /* htlc */, + NULL /* htlc_success_tapscript */, + NULL /* htlc_timeout_tapscript */); + continue; + } + u8 *to_them = scriptpubkey_p2tr(tmpctx, &keyset->other_settle_key); + if (memcmp(settle_out->script, to_us, tal_count(to_them)) == 0) { + /* (3) `to_node` to them */ + new_tracked_output(outs, &outpoint, + tx_blockheight, + out->resolved->tx_type, + satoshis, + OUTPUT_TO_THEM /* output_type */, + NULL /* htlc */, + NULL /* htlc_success_tapscript */, + NULL /* htlc_timeout_tapscript */); + continue; + } + /* Update we don't recognise :( FIXME what do */ + abort(); + } else { + enum output_type htlc_type; + if (matches_direction(matches, htlcs_info->htlcs) == LOCAL) { + /* (4) HTLC to us */ + htlc_type = THEIR_HTLC; + } else { + /* (5) HTLC to them */ + htlc_type = OUR_HTLC; + } + new_tracked_output(outs, &outpoint, + tx_blockheight, + out->resolved->tx_type, + satoshis, + htlc_type /* output_type */, + &htlcs_info->htlcs[matches[0]] /* htlc */, + htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, + htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); + continue; + } + } + } + return; } @@ -851,10 +1007,48 @@ static bool handle_dev_memleak(struct tracked_output **outs, const u8 *msg) } #endif /* !DEVELOPER */ -static void wait_for_resolved(struct tracked_output **outs) +static void wait_for_mutual_resolved(struct tracked_output **outs) +{ + billboard_update(outs); + + while (num_not_irrevocably_resolved(outs) != 0) { + u8 *msg; + struct bitcoin_txid txid; + u32 depth; + + if (tal_count(queued_msgs)) { + msg = tal_steal(outs, queued_msgs[0]); + tal_arr_remove(&queued_msgs, 0); + } else + msg = wire_sync_read(outs, REQ_FD); + + status_debug("Got new message %s", + onchaind_wire_name(fromwire_peektype(msg))); + + /* Should only be getting updates on the funding output spend getting buried */ + if (fromwire_onchaind_depth(msg, &txid, &depth)) { + eltoo_tx_new_depth(outs, &txid, depth); + } else if (!handle_dev_memleak(outs, msg)) { + master_badmsg(-1, msg); + } + + billboard_update(outs); + tal_free(msg); + clean_tmpctx(); + } + + wire_sync_write(REQ_FD, + take(towire_onchaind_all_irrevocably_resolved(outs))); +} + +static void wait_for_resolved(struct tracked_output **outs, struct htlcs_info *htlcs_info) { billboard_update(outs); + /* Calculate all the HTLC scripts so we can match them */ + u8 **htlc_success_scripts = derive_htlc_success_scripts(htlcs_info->htlcs, &keyset->self_settle_key, &keyset->other_settle_key); + u8 **htlc_timeout_scripts = derive_htlc_timeout_scripts(htlcs_info->htlcs, &keyset->self_settle_key, &keyset->other_settle_key); + while (num_not_irrevocably_resolved(outs) != 0) { u8 *msg; struct bitcoin_txid txid; @@ -875,8 +1069,7 @@ static void wait_for_resolved(struct tracked_output **outs) eltoo_tx_new_depth(outs, &txid, depth); } else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num, &tx_blockheight)) { - /* FIXME walk through logic with someone who knows what's going on */ - output_spent(&outs, tx_parts, input_num, tx_blockheight); + output_spent(&outs, tx_parts, input_num, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) /* We could be watching our settlement outputs even if they haven't entered utxo set to use for CPFP. */ @@ -893,12 +1086,6 @@ static void wait_for_resolved(struct tracked_output **outs) take(towire_onchaind_all_irrevocably_resolved(outs))); } -struct htlcs_info { - struct htlc_stub *htlcs; - bool *tell_if_missing; - bool *tell_immediately; -}; - struct htlc_with_tells { struct htlc_stub htlc; bool tell_if_missing, tell_immediately; @@ -999,7 +1186,7 @@ static void eltoo_handle_mutual_close(struct tracked_output **outs, * already agreed to the output, which is sent to its specified `scriptpubkey` */ resolved_by_other(outs[0], &tx->txid, MUTUAL_CLOSE); - wait_for_resolved(outs); + wait_for_mutual_resolved(outs); } static void handle_latest_update(const struct tx_parts *tx, @@ -1023,18 +1210,17 @@ static void handle_latest_update(const struct tx_parts *tx, amt = amount_asset_to_sat(&asset); htlcs_info = eltoo_init_reply(tmpctx, "Tracking final update transaction"); - /* FIXME do something with htlcs_info ? */ - assert(htlcs_info); + onchain_annotate_txin(&tx->txid, state_index, TX_CHANNEL_UNILATERAL); resolved_by_other(outs[0], &tx->txid, ELTOO_UPDATE); out = new_tracked_output(&outs, &outpoint, tx_blockheight, - UPDATE, + ELTOO_UPDATE, amt, DELAYED_OUTPUT_TO_US, - NULL /* htlc */, NULL /* wscript */, NULL /* remote_htlc_sig */); + NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); /* Proposed resolution is the matching settlement tx */ if (locktime == complete_update_tx->wtx->locktime) { @@ -1045,8 +1231,10 @@ static void handle_latest_update(const struct tx_parts *tx, propose_resolution(out, committed_settle_tx, committed_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); } - /* Wait until we get shared_delay confirms for this output */ - wait_for_resolved(outs); + /* Run to completion since we don't fan out immediately in eltoo */ + wait_for_resolved(outs, htlcs_info); + + tal_free(htlcs_info); } int main(int argc, char *argv[]) @@ -1062,6 +1250,8 @@ int main(int argc, char *argv[]) u32 locktime, tx_blockheight, max_known_version; u8 *scriptpubkey[NUM_SIDES]; + keyset = tal(ctx, struct eltoo_keyset); + subdaemon_setup(argc, argv); status_setup_sync(REQ_FD); @@ -1085,7 +1275,11 @@ int main(int argc, char *argv[]) &tx_blockheight, &our_msat, &scriptpubkey[LOCAL], - &scriptpubkey[REMOTE])) { + &scriptpubkey[REMOTE], + &keyset->self_funding_key, + &keyset->other_funding_key, + &keyset->self_settle_key, + &keyset->other_settle_key)) { master_badmsg(WIRE_ELTOO_ONCHAIND_INIT, msg); } @@ -1118,7 +1312,7 @@ int main(int argc, char *argv[]) 0, /* We don't care about funding blockheight */ FUNDING_TRANSACTION, funding_sats, - FUNDING_OUTPUT, NULL, NULL, NULL); + FUNDING_OUTPUT, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); /* Record funding output spent */ send_coin_mvt(take(new_coin_channel_close(NULL, &spending_tx->txid, diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index ce108556f469..c83129eefcfd 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -157,6 +157,10 @@ msgdata,eltoo_onchaind_init,local_scriptpubkey_len,u16, msgdata,eltoo_onchaind_init,local_scriptpubkey,u8,local_scriptpubkey_len msgdata,eltoo_onchaind_init,remote_scriptpubkey_len,u16, msgdata,eltoo_onchaind_init,remote_scriptpubkey,u8,remote_scriptpubkey_len +msgdata,eltoo_onchaind_init,self_funding_key,pubkey, +msgdata,eltoo_onchaind_init,other_funding_key,pubkey, +msgdata,eltoo_onchaind_init,self_settle_key,pubkey, +msgdata,eltoo_onchaind_init,other_settle_key,pubkey, # This says we're ready; give us htlcs and preimages. msgtype,eltoo_onchaind_init_reply,5161 From cb6be2f458f84d56ad93a43a1eb0d7e20168cbc9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 22 Nov 2022 14:27:08 -0500 Subject: [PATCH 217/283] Propagate keys to eltoo onchaind --- lightningd/onchain_control.c | 8 ++++---- lightningd/opening_control.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 9bc45ac2ed9c..83cbd3f42fe0 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -952,10 +952,10 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, channel->our_msat, channel->shutdown_scriptpubkey[LOCAL], channel->shutdown_scriptpubkey[REMOTE], - &channel->eltoo_keyset.self_funding_key, - &channel->eltoo_keyset.other_funding_key, - &channel->eltoo_keyset.self_settle_key, - &channel->eltoo_keyset.other_settle_key + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, + &channel->local_basepoints.payment /* settlement key */, + &channel->channel_info.theirbase.payment /* settlement key */ ); subd_send_msg(channel->owner, take(msg)); diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 8e714cc2776c..199ace012ab9 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -384,7 +384,7 @@ static void opening_eltoo_funder_finished(struct subd *openingd, const u8 *resp, &complete_settle_tx, &fc->uc->minimum_depth, &channel_info.remote_fundingkey, - &channel_info.theirbase.payment, + &channel_info.theirbase.payment /* settlement key */, &complete_state.other_psig, &complete_state.self_psig, &complete_state.session, From 15de384c0cff08aae116abfee0eda2fc98bd35e2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 23 Nov 2022 15:50:24 -0500 Subject: [PATCH 218/283] Fixup state updates in lightningd, both eltoo_onchainds should match state now --- contrib/startup_regtest.sh | 2 +- lightningd/channel.c | 2 ++ lightningd/peer_htlcs.c | 30 +++++++++++++++++++++++++----- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 2c21fd3975ef..28e0cd3ece10 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -218,7 +218,7 @@ setup_ln() { l2-cli fundchannel $l3id 10000 normal false bt-cli generatetoaddress 6 $btcaddr - sleep 0.5 + sleep 2 invoice=$(l2-cli invoice 10000 hi "test" | jq -r .bolt11) l1-cli pay $invoice sleep 0.5 diff --git a/lightningd/channel.c b/lightningd/channel.c index d0323d29ffff..2a4d96c4e5e8 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -729,6 +729,8 @@ void channel_set_last_eltoo_txs(struct channel *channel, tal_free(channel->eltoo_keyset.complete_settle_tx); channel->eltoo_keyset.complete_settle_tx = tal_steal(channel, settle_tx); + /* FIXME We also clear out committed */ + channel->eltoo_keyset.last_complete_state.other_psig = *their_psig; channel->eltoo_keyset.last_complete_state.self_psig = *our_psig; channel->eltoo_keyset.last_complete_state.session = *session; diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 8c6b6455833f..fa99c31b8016 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1936,7 +1936,12 @@ static bool peer_save_commitsig_sent(struct channel *channel, u64 commitnum) } /* Only difference is incrementing local next_index, since there's only 1 */ -static bool peer_save_updatesig_sent(struct channel *channel, u64 update_num) +static bool peer_save_updatesig_sent(struct channel *channel, + u64 update_num, + struct partial_sig *our_psig, + struct musig_session *session, + struct bitcoin_tx *committed_update_tx TAKES, + struct bitcoin_tx *committed_settle_tx TAKES) { struct lightningd *ld = channel->peer->ld; @@ -1950,7 +1955,11 @@ static bool peer_save_updatesig_sent(struct channel *channel, u64 update_num) channel->next_index[LOCAL]++; - /* FIXME: Save to database, with sig and HTLCs. */ + channel->eltoo_keyset.last_committed_state.self_psig = *our_psig; + channel->eltoo_keyset.last_committed_state.session = *session; + channel->eltoo_keyset.committed_update_tx = tal_steal(channel, committed_update_tx); + channel->eltoo_keyset.committed_settle_tx = tal_steal(channel, committed_settle_tx); + wallet_channel_save(ld->wallet, channel); return true; } @@ -1991,7 +2000,18 @@ void peer_got_ack(struct channel *channel, const u8 *msg) } } - /* FIXME stash signing information, more state? */ + /* Write new complete state into channel before writing to db */ + tal_free(channel->eltoo_keyset.complete_update_tx); + tal_free(channel->eltoo_keyset.complete_settle_tx); + channel->eltoo_keyset.complete_update_tx = tal_steal(channel, channel->eltoo_keyset.committed_update_tx); + channel->eltoo_keyset.committed_update_tx = NULL; + channel->eltoo_keyset.complete_settle_tx = tal_steal(channel, channel->eltoo_keyset.committed_settle_tx); + channel->eltoo_keyset.committed_settle_tx = NULL; + channel->eltoo_keyset.last_complete_state.self_psig = channel->eltoo_keyset.last_committed_state.self_psig; + channel->eltoo_keyset.last_complete_state.other_psig = their_psig; + channel->eltoo_keyset.last_complete_state.session = session; + + /* And null out committed state */ /* write to db, then respond */ wallet_channel_save(ld->wallet, channel); @@ -2009,7 +2029,6 @@ void peer_sending_updatesig(struct channel *channel, const u8 *msg) size_t i, maxid = 0, num_local_added = 0; struct lightningd *ld = channel->peer->ld; - /* These are unused currently... */ struct partial_sig our_update_psig; struct musig_session session; struct bitcoin_tx *committed_update_tx; @@ -2055,7 +2074,8 @@ void peer_sending_updatesig(struct channel *channel, const u8 *msg) channel->next_htlc_id += num_local_added; } - if (!peer_save_updatesig_sent(channel, update_num)) + /* Add newest state to channel, then save to db */ + if (!peer_save_updatesig_sent(channel, update_num, &our_update_psig, &session, committed_update_tx, committed_settle_tx)) return; /* Last was commit. FIXME do we want to reuse these fields? maybe? */ From 33eef508cdf5c57c2e38a86fee59a59ef1f12096 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 23 Nov 2022 17:11:45 -0500 Subject: [PATCH 219/283] Fixup eltoo_onchaind lifetime of htlc scripts --- contrib/startup_regtest.sh | 3 +++ onchaind/eltoo_onchaind.c | 15 ++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 28e0cd3ece10..4fb5f3961803 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -182,6 +182,9 @@ onchain_ln() { bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $UPDATE_HEX bt-cli generatetoaddress 7 $btcaddr + sleep 1 + # settle tx should be pushed after next block + bt-cli generatetoaddress 1 $btcaddr ### OR diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 71f481364dc4..2a5ce8b854ff 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -120,10 +120,10 @@ static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) tal_free(mvt); } -static u8 **derive_htlc_success_scripts(const struct htlc_stub *htlcs, const struct pubkey *our_htlc_pubkey, const struct pubkey *their_htlc_pubkey) +static u8 **derive_htlc_success_scripts(const tal_t *ctx, const struct htlc_stub *htlcs, const struct pubkey *our_htlc_pubkey, const struct pubkey *their_htlc_pubkey) { size_t i; - u8 **htlc_scripts = tal_arr(htlcs, u8 *, tal_count(htlcs)); + u8 **htlc_scripts = tal_arr(ctx, u8 *, tal_count(htlcs)); for (i = 0; i < tal_count(htlcs); i++) { htlc_scripts[i] = make_eltoo_htlc_success_script(htlc_scripts, @@ -133,10 +133,10 @@ static u8 **derive_htlc_success_scripts(const struct htlc_stub *htlcs, const str return htlc_scripts; } -static u8 **derive_htlc_timeout_scripts(const struct htlc_stub *htlcs, const struct pubkey *our_htlc_pubkey, const struct pubkey *their_htlc_pubkey) +static u8 **derive_htlc_timeout_scripts(const tal_t *ctx, const struct htlc_stub *htlcs, const struct pubkey *our_htlc_pubkey, const struct pubkey *their_htlc_pubkey) { size_t i; - u8 **htlc_scripts = tal_arr(htlcs, u8 *, tal_count(htlcs)); + u8 **htlc_scripts = tal_arr(ctx, u8 *, tal_count(htlcs)); for (i = 0; i < tal_count(htlcs); i++) { htlc_scripts[i] = make_eltoo_htlc_timeout_script(htlc_scripts, @@ -164,7 +164,7 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, u8 **htlc_success_scripts, u8 **htlc_timeout_scripts) { - assert(tal_count(htlc_success_scripts) == tal_count(htlc_timeout_scripts)); +// wtf? assert(tal_count(htlc_success_scripts) == tal_count(htlc_timeout_scripts)); size_t *matches = tal_arr(ctx, size_t, 0); const u8 *script = tal_dup_arr(tmpctx, u8, out->script, out->script_len, @@ -680,6 +680,7 @@ static void output_spent(struct tracked_output ***outs, u8 **htlc_timeout_scripts, struct htlcs_info *htlcs_info) { + assert(tal_count(htlc_success_scripts) == tal_count(htlc_timeout_scripts)); for (size_t i = 0; i < tal_count(*outs); i++) { struct tracked_output *out = (*outs)[i]; struct bitcoin_outpoint htlc_outpoint; @@ -1046,8 +1047,8 @@ static void wait_for_resolved(struct tracked_output **outs, struct htlcs_info *h billboard_update(outs); /* Calculate all the HTLC scripts so we can match them */ - u8 **htlc_success_scripts = derive_htlc_success_scripts(htlcs_info->htlcs, &keyset->self_settle_key, &keyset->other_settle_key); - u8 **htlc_timeout_scripts = derive_htlc_timeout_scripts(htlcs_info->htlcs, &keyset->self_settle_key, &keyset->other_settle_key); + u8 **htlc_success_scripts = derive_htlc_success_scripts(outs, htlcs_info->htlcs, &keyset->self_settle_key, &keyset->other_settle_key); + u8 **htlc_timeout_scripts = derive_htlc_timeout_scripts(outs, htlcs_info->htlcs, &keyset->self_settle_key, &keyset->other_settle_key); while (num_not_irrevocably_resolved(outs) != 0) { u8 *msg; From f2d8ce71a9338cbaac235e036cd106068e1f845a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 28 Nov 2022 13:05:27 -0500 Subject: [PATCH 220/283] eltoo_onchaind resolves when no htlcs left --- onchaind/eltoo_onchaind.c | 158 ++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 67 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 2a5ce8b854ff..f4294c35d14f 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -237,6 +237,9 @@ new_tracked_output(struct tracked_output ***outs, return out; } +/* Marks a utxo as resolved. The utxo still needs to be buried >>==100 to be + * irrevocably resolved + */ static void ignore_output(struct tracked_output *out) { status_debug("Ignoring output %s: %s/%s", @@ -489,6 +492,7 @@ static size_t num_not_irrevocably_resolved(struct tracked_output **outs) size_t i, num = 0; for (i = 0; i < tal_count(outs); i++) { + /* FIXME If an output gets reorged out, what do we do? */ if (!outs[i]->resolved || outs[i]->resolved->depth < 100) num++; } @@ -671,6 +675,92 @@ struct htlcs_info { bool *tell_immediately; }; +static void track_settle_outputs(struct tracked_output ***outs, + const struct tx_parts *tx_parts, + u32 tx_blockheight, + u8 **htlc_success_scripts, + u8 **htlc_timeout_scripts, + struct htlcs_info *htlcs_info) +{ + /* Settlement transaction has 5 types of outputs it's looking for */ + for (size_t j = 0; j < tal_count(tx_parts->outputs); j++) { + struct wally_tx_output *settle_out = tx_parts->outputs[j]; + struct tracked_output *out; + struct amount_sat satoshis = amount_sat(settle_out->satoshi); + /* (1) Ephemeral Anchor */ + if (is_ephemeral_anchor(settle_out->script)) { + /* Anchor is lightningd's problem */ + continue; + } + const size_t *matches = eltoo_match_htlc_output(tmpctx, settle_out, htlc_success_scripts, htlc_timeout_scripts); + struct bitcoin_outpoint outpoint; + outpoint.txid = tx_parts->txid; + outpoint.n = j; + if (tal_count(matches) == 0) { + if (!is_p2tr(settle_out->script, NULL)) { + /* Everything should be taproot FIXME what do */ + abort(); + } + status_debug("Output script: %s", tal_hex(tmpctx, settle_out->script)); + u8 *to_us = scriptpubkey_p2tr(tmpctx, &keyset->self_settle_key); + status_debug("to_us script: %s", tal_hex(tmpctx, to_us)); + if (memcmp(settle_out->script, to_us, tal_count(to_us)) == 0) { + /* (2) `to_node` to us */ + //out = new_tracked_output(outs, &outpoint, + // tx_blockheight, + // ELTOO_SETTLE, + // satoshis, + // OUTPUT_TO_US /* output_type */, + // NULL /* htlc */, + // NULL /* htlc_success_tapscript */, + // NULL /* htlc_timeout_tapscript */); + /* No need to resolve or track it */ + //ignore_output(out); + continue; + } + u8 *to_them = scriptpubkey_p2tr(tmpctx, &keyset->other_settle_key); + status_debug("to_them script: %s", tal_hex(tmpctx, to_them)); + if (memcmp(settle_out->script, to_them, tal_count(to_them)) == 0) { + /* (3) `to_node` to them */ + //out = new_tracked_output(outs, &outpoint, + // tx_blockheight, + // ELTOO_SETTLE, + // satoshis, + // OUTPUT_TO_THEM /* output_type */, + // NULL /* htlc */, + // NULL /* htlc_success_tapscript */, + // NULL /* htlc_timeout_tapscript */); + /* No need to resolve it */ + //ignore_output(out); + continue; + } + /* Update we don't recognise :( FIXME what do */ + status_failed(STATUS_FAIL_INTERNAL_ERROR, "Couldn't match settlement output script to known output type"); + } else { + enum output_type htlc_type; + if (matches_direction(matches, htlcs_info->htlcs) == LOCAL) { + /* (4) HTLC to us */ + htlc_type = THEIR_HTLC; + } else { + /* (5) HTLC to them */ + htlc_type = OUR_HTLC; + } + /* FIXME we need to propose a resolution for this output */ + out = new_tracked_output(outs, &outpoint, + tx_blockheight, + ELTOO_SETTLE, + satoshis, + htlc_type /* output_type */, + &htlcs_info->htlcs[matches[0]] /* htlc */, + htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, + htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); + // FIXME resolve_our_htlc_ourcommit <--- do something like this which proposes resolution tx + assert(out); + continue; + } + } +} + /* An output has been spent: see if it resolves something we care about. */ static void output_spent(struct tracked_output ***outs, const struct tx_parts *tx_parts, @@ -695,74 +785,8 @@ static void output_spent(struct tracked_output ***outs, /* Was this our resolution? */ if (resolved_by_proposal(out, tx_parts)) { if (out->resolved->tx_type == ELTOO_SETTLE) { - /* Settlement transaction has 5 types of outputs it's looking for */ - for (size_t j = 0; j < tal_count(tx_parts->outputs); j++) { - struct wally_tx_output *settle_out = tx_parts->outputs[j]; - struct amount_sat satoshis = amount_sat(settle_out->satoshi); - /* (1) Ephemeral Anchor */ - if (is_ephemeral_anchor(settle_out->script)) { - /* Do we need to handle anchor? */ - continue; - } - const size_t *matches = eltoo_match_htlc_output(tmpctx, settle_out, htlc_success_scripts, htlc_timeout_scripts); - struct bitcoin_outpoint outpoint; - outpoint.txid = tx_parts->txid; - outpoint.n = j; - if (tal_count(matches) == 0) { - if (!is_p2tr(settle_out->script, NULL)) { - /* Everything should be taproot FIXME what do */ - abort(); - } - u8 *to_us = scriptpubkey_p2tr(tmpctx, &keyset->self_settle_key); - if (memcmp(settle_out->script, to_us, tal_count(to_us)) == 0) { - /* (2) `to_node` to us */ - new_tracked_output(outs, &outpoint, - tx_blockheight, - out->resolved->tx_type, - satoshis, - OUTPUT_TO_US /* output_type */, - NULL /* htlc */, - NULL /* htlc_success_tapscript */, - NULL /* htlc_timeout_tapscript */); - continue; - } - u8 *to_them = scriptpubkey_p2tr(tmpctx, &keyset->other_settle_key); - if (memcmp(settle_out->script, to_us, tal_count(to_them)) == 0) { - /* (3) `to_node` to them */ - new_tracked_output(outs, &outpoint, - tx_blockheight, - out->resolved->tx_type, - satoshis, - OUTPUT_TO_THEM /* output_type */, - NULL /* htlc */, - NULL /* htlc_success_tapscript */, - NULL /* htlc_timeout_tapscript */); - continue; - } - /* Update we don't recognise :( FIXME what do */ - abort(); - } else { - enum output_type htlc_type; - if (matches_direction(matches, htlcs_info->htlcs) == LOCAL) { - /* (4) HTLC to us */ - htlc_type = THEIR_HTLC; - } else { - /* (5) HTLC to them */ - htlc_type = OUR_HTLC; - } - new_tracked_output(outs, &outpoint, - tx_blockheight, - out->resolved->tx_type, - satoshis, - htlc_type /* output_type */, - &htlcs_info->htlcs[matches[0]] /* htlc */, - htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, - htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); - continue; - } - } + track_settle_outputs(outs, tx_parts, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); } - return; } From 1a01914979e589db833e330c55a1ce064fba56c5 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 30 Nov 2022 10:45:50 -0500 Subject: [PATCH 221/283] fixup unit test with updated tx format --- channeld/test/run-settle_tx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 708c9f766877..0bf59387221b 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -57,7 +57,7 @@ void towire_wireaddr(u8 **pptr UNNEEDED, const struct wireaddr *addr UNNEEDED) { fprintf(stderr, "towire_wireaddr called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ -char regression_tx_hex[] = "02000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000002a00000003000000000000000001511027000000000000225120c2f25ad5b139599cceb1ba1b330dfabe3e9298e4d14eec125d229536d532ef781ce80000000000002251202302f780a9d31218dbfd03f4d410ab0803995ed4795dc7963ea105b020de58ab026541a93aa6809e14e2196758dbdee73f4a077ea48e129716c79ff04592a9de15c76012e46d67acbe5882f524ecd72e4b40afba3ae3a13b3621513913813c3617ec94c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4b4d868d7231ff3d15775dbd01acf0051b86eccd1f1139772222152b32986c4df0065cd1d"; +char regression_tx_hex[] = "02000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000002a00000003000000000000000001511027000000000000225120466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f271ce80000000000002251204f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa02654196b83a7a213da9614e4ea004f03d8130ef9db83ef134725474c265a5d4e041f9f76134aa4133a3910e2fbc8906581f6e1679af46d6e45376aba0886fdf4196a7c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4b4d868d7231ff3d15775dbd01acf0051b86eccd1f1139772222152b32986c4df0065cd1d"; static char *fmt_bitcoin_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { @@ -785,7 +785,7 @@ static int test_htlc_output_creation(void) int ok; char *tap_hex; /* Ground truth generated elsewhere */ - char hex_script[] = "51201886a9f50222b126b010a811bb156cbd6572ba92282808f384e9af4a0849028d"; + char hex_script[] = "5120d6df6951e80e3ba3f0b3dd900263e31d93cbfdb4c74d302aa6a8957f2784adb9"; settlement_privkey.secret = secret_from_hex("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e1301"); @@ -821,6 +821,7 @@ static int test_htlc_output_creation(void) assert(tal_count(taproot_script) == 1+1+32); tap_hex = tal_hexstr(tmpctx, taproot_script, tal_count(taproot_script)); assert(tal_count(tap_hex) == (1+1+32)*2 + 1); + printf("Tap hex: %s\n", tap_hex); assert(!memcmp(tap_hex, hex_script, tal_count(tap_hex))); return 0; } From 65d878a8bb2312e39b47a7c4e53a84a64ad0281b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 30 Nov 2022 11:02:10 -0500 Subject: [PATCH 222/283] Add locktime to onchaind_spent message --- lightningd/onchain_control.c | 2 +- onchaind/eltoo_onchaind.c | 64 ++++++++++++++------------- onchaind/onchaind.c | 3 +- onchaind/onchaind_wire.csv | 1 + onchaind/test/run-grind_feerate-bug.c | 2 +- onchaind/test/run-grind_feerate.c | 2 +- 6 files changed, 40 insertions(+), 34 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 83cbd3f42fe0..88193c1ab601 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -263,7 +263,7 @@ static void onchain_txo_spent(struct channel *channel, const struct bitcoin_tx * watch_tx_and_outputs(channel, tx); - msg = towire_onchaind_spent(channel, parts, input_num, blockheight); + msg = towire_onchaind_spent(channel, parts, input_num, tx->wtx->locktime, blockheight); subd_send_msg(channel->owner, take(msg)); } diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index f4294c35d14f..fa4145521ce6 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1080,6 +1080,7 @@ static void wait_for_resolved(struct tracked_output **outs, struct htlcs_info *h u32 input_num, depth, tx_blockheight; struct preimage preimage; struct tx_parts *tx_parts; + u32 locktime; if (tal_count(queued_msgs)) { msg = tal_steal(outs, queued_msgs[0]); @@ -1092,7 +1093,7 @@ static void wait_for_resolved(struct tracked_output **outs, struct htlcs_info *h if (fromwire_onchaind_depth(msg, &txid, &depth)) { eltoo_tx_new_depth(outs, &txid, depth); - } else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num, + } else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &locktime, &input_num, &tx_blockheight)) { output_spent(&outs, tx_parts, input_num, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) @@ -1214,7 +1215,7 @@ static void eltoo_handle_mutual_close(struct tracked_output **outs, wait_for_mutual_resolved(outs); } -static void handle_latest_update(const struct tx_parts *tx, +static void handle_unilateral(const struct tx_parts *tx, u32 tx_blockheight, struct tracked_output **outs, u32 locktime) @@ -1224,6 +1225,8 @@ static void handle_latest_update(const struct tx_parts *tx, struct amount_asset asset; struct amount_sat amt; struct tracked_output *out; + const struct pubkey *pubkey_ptrs[2]; + secp256k1_musig_keyagg_cache keyagg_cache; /* State output will match index */ int state_index = funding_input_num(outs, tx); @@ -1234,7 +1237,7 @@ static void handle_latest_update(const struct tx_parts *tx, asset = wally_tx_output_get_amount(tx->outputs[state_index]); amt = amount_asset_to_sat(&asset); - htlcs_info = eltoo_init_reply(tmpctx, "Tracking final update transaction"); + htlcs_info = eltoo_init_reply(tmpctx, "Tracking update transactions"); onchain_annotate_txin(&tx->txid, state_index, TX_CHANNEL_UNILATERAL); @@ -1247,13 +1250,38 @@ static void handle_latest_update(const struct tx_parts *tx, DELAYED_OUTPUT_TO_US, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); + /* Fill out inner pubkey to complete re-binding of update transactions going forward */ + pubkey_ptrs[0] = &keyset->self_funding_key; + pubkey_ptrs[1] = &keyset->other_funding_key; + bipmusig_inner_pubkey(&keyset->inner_pubkey, + &keyagg_cache, + pubkey_ptrs, + /* n_pubkeys */ 2); + + /* FIXME I think this logic will be the same in main loop under output_spent */ + /* FIXME rework bind_update_tx_to_update_outpoint to take precisely what's required */ + /* FIXME onchaind_spent needs to give locktime of new tx */ + /* Proposed resolution is the matching settlement tx */ if (locktime == complete_update_tx->wtx->locktime) { bind_settle_tx(tx->txid, state_index, complete_settle_tx); propose_resolution(out, complete_settle_tx, complete_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); - } else { + } else if (locktime == committed_update_tx->wtx->locktime) { bind_settle_tx(tx->txid, state_index, committed_settle_tx); propose_resolution(out, committed_settle_tx, committed_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); + } else if (locktime > committed_update_tx->wtx->locktime) { + /* If we get lucky the settle transaction will hit chain and we can get balance back */ + status_debug("Uh-oh, update from the future!"); + } else { + /* Need to propose our last complete update */ +// bind_update_tx_to_update_outpoint(complete_update_tx, +// complete_settle_tx, +// &outpoint, +// keyset, +// invalidated_annex_hint, +// locktime /* invalidated_update_number */, +// &keyset->inner_pubkey, +// b340sig); } /* Run to completion since we don't fan out immediately in eltoo */ @@ -1272,7 +1300,7 @@ int main(int argc, char *argv[]) struct tracked_output **outs; struct bitcoin_outpoint funding; struct amount_sat funding_sats; - u32 locktime, tx_blockheight, max_known_version; + u32 locktime, tx_blockheight; u8 *scriptpubkey[NUM_SIDES]; keyset = tal(ctx, struct eltoo_keyset); @@ -1347,11 +1375,9 @@ int main(int argc, char *argv[]) tal_count(spending_tx->outputs)))); /* Committed state should be one step further max */ - max_known_version = complete_update_tx->wtx->locktime; if (committed_update_tx) { assert(complete_update_tx->wtx->locktime == committed_update_tx->wtx->locktime || complete_update_tx->wtx->locktime == committed_update_tx->wtx->locktime + 1); - max_known_version = committed_update_tx->wtx->locktime; } if (is_mutual_close(locktime)) { @@ -1359,29 +1385,7 @@ int main(int argc, char *argv[]) eltoo_handle_mutual_close(outs, spending_tx); } else { status_debug("Handling unilateral close!"); - if (locktime > max_known_version) { - /* Might as well track the state output, see if it ends up in a settlement tx - * So `to_node` values can be harvested, HTLCs rescued with counterparty's help? - * Or we should immediately report all HTLCs as missing, failing these? - */ - status_debug("Uh-oh, please be nice Mr Counterparty :("); - } else if (locktime == max_known_version) { - status_debug("Unilateral close of last known state detected"); - /* - * We are simply waiting for this particular update tx to mature - * before getting the settlement tx on chain and sweeping outputs. - */ - handle_latest_update(spending_tx, tx_blockheight, outs, locktime); - } else if (locktime == complete_update_tx->wtx->locktime) { - status_debug("Unilateral close of last complete state detected"); - /* - * It's possible this last transaction will be over-written - * by the committed state we don't have signatures for. - */ - handle_latest_update(spending_tx, tx_blockheight, outs, locktime); - } else { - status_debug("Cheater!"); - } + handle_unilateral(spending_tx, tx_blockheight, outs, locktime); } /* We're done! */ diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 83c0b059a658..8fae89bfb93c 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -2097,6 +2097,7 @@ static void wait_for_resolved(struct tracked_output **outs) u32 input_num, depth, tx_blockheight; struct preimage preimage; struct tx_parts *tx_parts; + u32 unused_locktime; if (tal_count(queued_msgs)) { msg = tal_steal(outs, queued_msgs[0]); @@ -2109,7 +2110,7 @@ static void wait_for_resolved(struct tracked_output **outs) if (fromwire_onchaind_depth(msg, &txid, &depth)) tx_new_depth(outs, &txid, depth); - else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &input_num, + else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &unused_locktime, &input_num, &tx_blockheight)) { output_spent(&outs, tx_parts, input_num, tx_blockheight); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index c83129eefcfd..87678e9757bd 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -78,6 +78,7 @@ msgdata,onchaind_broadcast_tx,is_rbf,bool, # master->onchaind: Notifier that an output has been spent by input_num of tx. msgtype,onchaind_spent,5004 msgdata,onchaind_spent,tx,tx_parts, +msgdata,onchaind_spent,locktime,u32, msgdata,onchaind_spent,input_num,u32, msgdata,onchaind_spent,blockheight,u32, diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index 8726dbaf3782..124839d95bc7 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -55,7 +55,7 @@ bool fromwire_onchaind_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, s bool fromwire_onchaind_known_preimage(const void *p UNNEEDED, struct preimage *preimage UNNEEDED) { fprintf(stderr, "fromwire_onchaind_known_preimage called!\n"); abort(); } /* Generated stub for fromwire_onchaind_spent */ -bool fromwire_onchaind_spent(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct tx_parts **tx UNNEEDED, u32 *input_num UNNEEDED, u32 *blockheight UNNEEDED) +bool fromwire_onchaind_spent(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct tx_parts **tx UNNEEDED, u32 *locktime UNNEEDED, u32 *input_num UNNEEDED, u32 *blockheight UNNEEDED) { fprintf(stderr, "fromwire_onchaind_spent called!\n"); abort(); } /* Generated stub for fromwire_peektype */ int fromwire_peektype(const u8 *cursor UNNEEDED) diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index e800b371cefa..1a79a8a24b36 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -60,7 +60,7 @@ bool fromwire_onchaind_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, s bool fromwire_onchaind_known_preimage(const void *p UNNEEDED, struct preimage *preimage UNNEEDED) { fprintf(stderr, "fromwire_onchaind_known_preimage called!\n"); abort(); } /* Generated stub for fromwire_onchaind_spent */ -bool fromwire_onchaind_spent(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct tx_parts **tx UNNEEDED, u32 *input_num UNNEEDED, u32 *blockheight UNNEEDED) +bool fromwire_onchaind_spent(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct tx_parts **tx UNNEEDED, u32 *locktime UNNEEDED, u32 *input_num UNNEEDED, u32 *blockheight UNNEEDED) { fprintf(stderr, "fromwire_onchaind_spent called!\n"); abort(); } /* Generated stub for fromwire_secp256k1_ecdsa_signature */ void fromwire_secp256k1_ecdsa_signature(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, From 84c5bfbf9c2c33c6c5a85202281ce3e76f858ed5 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 30 Nov 2022 11:05:29 -0500 Subject: [PATCH 223/283] test success message --- channeld/test/run-settle_tx.c | 2 ++ onchaind/eltoo_onchaind.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 0bf59387221b..58c816c6ff8b 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -846,6 +846,8 @@ int main(int argc, const char *argv[]) err |= test_invalid_update_tx(); assert(!err); + printf("Tests succeeded!\n"); + common_shutdown(); return err; diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index fa4145521ce6..c1e9ea7f210a 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1260,7 +1260,6 @@ static void handle_unilateral(const struct tx_parts *tx, /* FIXME I think this logic will be the same in main loop under output_spent */ /* FIXME rework bind_update_tx_to_update_outpoint to take precisely what's required */ - /* FIXME onchaind_spent needs to give locktime of new tx */ /* Proposed resolution is the matching settlement tx */ if (locktime == complete_update_tx->wtx->locktime) { From 3d6b2ae1418080319cfeb08bfafa5b56851e2262 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 30 Nov 2022 13:34:14 -0500 Subject: [PATCH 224/283] maybe support initial rebinding of invalidated update transactions --- lightningd/onchain_control.c | 5 ++++- onchaind/eltoo_onchaind.c | 34 +++++++++++++++++++++++++--------- onchaind/onchaind_wire.csv | 4 ++++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 88193c1ab601..40d29618867d 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -955,7 +955,10 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, &channel->local_funding_pubkey, &channel->channel_info.remote_fundingkey, &channel->local_basepoints.payment /* settlement key */, - &channel->channel_info.theirbase.payment /* settlement key */ + &channel->channel_info.theirbase.payment /* settlement key */, + &channel->eltoo_keyset.last_complete_state.self_psig, + &channel->eltoo_keyset.last_complete_state.other_psig, + &channel->eltoo_keyset.last_complete_state.session ); subd_send_msg(channel->owner, take(msg)); diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index c1e9ea7f210a..b59b3bfb929f 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -30,6 +30,16 @@ /* FIXME Everything copy/pasted bc static. Deduplicate later */ +/* Should make this a reusable thing */ +static bool bipmusig_partial_sigs_combine_state(const struct eltoo_sign *state, + struct bip340sig *sig) +{ + const secp256k1_musig_partial_sig *p_sigs[2]; + p_sigs[0] = &state->self_psig.p_sig; + p_sigs[1] = &state->other_psig.p_sig; + return bipmusig_partial_sigs_combine(p_sigs, 2 /* num_signers */, &state->session.session, sig); +} + /* Full tx we have partial signatures for */ static struct bitcoin_tx *complete_update_tx, *complete_settle_tx; @@ -1272,15 +1282,18 @@ static void handle_unilateral(const struct tx_parts *tx, /* If we get lucky the settle transaction will hit chain and we can get balance back */ status_debug("Uh-oh, update from the future!"); } else { + u8 *invalidated_annex_hint = tx->inputs[state_index]->witness->items[0].witness; + struct bip340sig sig; + bipmusig_partial_sigs_combine_state(&keyset->last_complete_state, &sig); /* Need to propose our last complete update */ -// bind_update_tx_to_update_outpoint(complete_update_tx, -// complete_settle_tx, -// &outpoint, -// keyset, -// invalidated_annex_hint, -// locktime /* invalidated_update_number */, -// &keyset->inner_pubkey, -// b340sig); + bind_update_tx_to_update_outpoint(complete_update_tx, + complete_settle_tx, + &outpoint, + keyset, + invalidated_annex_hint, + locktime /* invalidated_update_number */, + &keyset->inner_pubkey, + &sig); } /* Run to completion since we don't fan out immediately in eltoo */ @@ -1331,7 +1344,10 @@ int main(int argc, char *argv[]) &keyset->self_funding_key, &keyset->other_funding_key, &keyset->self_settle_key, - &keyset->other_settle_key)) { + &keyset->other_settle_key, + &keyset->last_complete_state.self_psig, + &keyset->last_complete_state.other_psig, + &keyset->last_complete_state.session)) { master_badmsg(WIRE_ELTOO_ONCHAIND_INIT, msg); } diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 87678e9757bd..89bbe447469d 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -162,6 +162,10 @@ msgdata,eltoo_onchaind_init,self_funding_key,pubkey, msgdata,eltoo_onchaind_init,other_funding_key,pubkey, msgdata,eltoo_onchaind_init,self_settle_key,pubkey, msgdata,eltoo_onchaind_init,other_settle_key,pubkey, +msgdata,eltoo_onchaind_init,complete_self_psig,partial_sig, +msgdata,eltoo_onchaind_init,complete_other_psig,partial_sig, +msgdata,eltoo_onchaind_init,complete_session,musig_session, + # This says we're ready; give us htlcs and preimages. msgtype,eltoo_onchaind_init_reply,5161 From 81051e298df9e1d91fc0df2d440bcb8c6d5e0385 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 30 Nov 2022 13:47:59 -0500 Subject: [PATCH 225/283] propose fixed update tx --- lightningd/onchain_control.c | 1 - onchaind/eltoo_onchaind.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 40d29618867d..706cdde96876 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -902,7 +902,6 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, if (channel->closer != NUM_SIDES) reason = REASON_UNKNOWN; /* will use last cause as reason */ - /* FIXME This submits and unfunded transaction :) Need to spend anchor */ channel_fail_permanent(channel, reason, "Funding transaction spent"); /* We could come from almost any state. */ diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index b59b3bfb929f..322d92e3cc27 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1269,7 +1269,6 @@ static void handle_unilateral(const struct tx_parts *tx, /* n_pubkeys */ 2); /* FIXME I think this logic will be the same in main loop under output_spent */ - /* FIXME rework bind_update_tx_to_update_outpoint to take precisely what's required */ /* Proposed resolution is the matching settlement tx */ if (locktime == complete_update_tx->wtx->locktime) { @@ -1282,6 +1281,7 @@ static void handle_unilateral(const struct tx_parts *tx, /* If we get lucky the settle transaction will hit chain and we can get balance back */ status_debug("Uh-oh, update from the future!"); } else { + /* FIXME probably should assert something here even though we checked for index already? */ u8 *invalidated_annex_hint = tx->inputs[state_index]->witness->items[0].witness; struct bip340sig sig; bipmusig_partial_sigs_combine_state(&keyset->last_complete_state, &sig); @@ -1294,6 +1294,7 @@ static void handle_unilateral(const struct tx_parts *tx, locktime /* invalidated_update_number */, &keyset->inner_pubkey, &sig); + propose_resolution(out, complete_update_tx, 0 /* depth_required */, ELTOO_UPDATE); } /* Run to completion since we don't fan out immediately in eltoo */ From 69d0234f0718039206664270dff050f71d23c66b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 30 Nov 2022 15:40:42 -0500 Subject: [PATCH 226/283] Testing out handling old updates for funding output spend --- contrib/startup_regtest.sh | 5 +++++ lightningd/onchain_control.c | 2 +- lightningd/peer_control.c | 2 +- onchaind/eltoo_onchaind.c | 19 +++++++++++++++---- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 4fb5f3961803..08697b282ecd 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -191,6 +191,11 @@ onchain_ln() { # Test for old update hitting chain txid=$(bt-cli decoderawtransaction $FIRST_UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 + # FIXME no way of grabbing latest bound tx to latest state output + # except by scraping logs + #txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) + #bt-cli prioritisetransaction $txid 0 100000000 + # Only manually send first bt-cli sendrawtransaction $FIRST_UPDATE_HEX bt-cli generatetoaddress 1 $btcaddr diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 706cdde96876..b096e4e116ab 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -263,7 +263,7 @@ static void onchain_txo_spent(struct channel *channel, const struct bitcoin_tx * watch_tx_and_outputs(channel, tx); - msg = towire_onchaind_spent(channel, parts, input_num, tx->wtx->locktime, blockheight); + msg = towire_onchaind_spent(channel, parts, tx->wtx->locktime, input_num, blockheight); subd_send_msg(channel->owner, take(msg)); } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 7d78542596ca..8bd9827d516f 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1004,8 +1004,8 @@ static void json_add_channel(struct lightningd *ld, if (channel->our_config.is_eltoo) { struct bitcoin_tx **bound_update_and_settle_txs; - /* Eltoo keyset should probably have all pubkeys... */ + /* FIXME would be nice to rebind to latest utxo, not just funding output that may by spent already */ bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->eltoo_keyset.complete_update_tx, &channel->funding, channel->eltoo_keyset.complete_settle_tx, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 322d92e3cc27..9b5a8327a060 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -788,6 +788,7 @@ static void output_spent(struct tracked_output ***outs, if (out->resolved) continue; + /* FIXME segfaulting here */ if (!wally_tx_input_spends(tx_parts->inputs[input_num], &out->outpoint)) continue; @@ -797,9 +798,16 @@ static void output_spent(struct tracked_output ***outs, if (out->resolved->tx_type == ELTOO_SETTLE) { track_settle_outputs(outs, tx_parts, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); } + /* FIXME handle our own response update tx being mined */ return; } + /* FIXME handle old update hitting the chain here */ + + /* FIXME handle complete update tx hitting the chain */ + + /* FIXME handle committed update tx hitting the chain */ + htlc_outpoint.txid = tx_parts->txid; htlc_outpoint.n = input_num; @@ -1274,15 +1282,18 @@ static void handle_unilateral(const struct tx_parts *tx, if (locktime == complete_update_tx->wtx->locktime) { bind_settle_tx(tx->txid, state_index, complete_settle_tx); propose_resolution(out, complete_settle_tx, complete_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); - } else if (locktime == committed_update_tx->wtx->locktime) { + } else if (committed_update_tx && locktime == committed_update_tx->wtx->locktime) { bind_settle_tx(tx->txid, state_index, committed_settle_tx); propose_resolution(out, committed_settle_tx, committed_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); - } else if (locktime > committed_update_tx->wtx->locktime) { + } else if ((committed_update_tx && locktime > committed_update_tx->wtx->locktime) || + (!committed_update_tx && locktime > complete_update_tx->wtx->locktime)) { /* If we get lucky the settle transaction will hit chain and we can get balance back */ status_debug("Uh-oh, update from the future!"); } else { /* FIXME probably should assert something here even though we checked for index already? */ - u8 *invalidated_annex_hint = tx->inputs[state_index]->witness->items[0].witness; + /* FIXME getting taproot committment mismatch here */ + struct wally_tx_witness_stack *wit_stack = tx->inputs[state_index]->witness; + u8 *invalidated_annex_hint = wit_stack->items[wit_stack->num_items - 1].witness; /* Annex is last witness item! */ struct bip340sig sig; bipmusig_partial_sigs_combine_state(&keyset->last_complete_state, &sig); /* Need to propose our last complete update */ @@ -1291,7 +1302,7 @@ static void handle_unilateral(const struct tx_parts *tx, &outpoint, keyset, invalidated_annex_hint, - locktime /* invalidated_update_number */, + locktime - 500000000 /* invalidated_update_number FIXME don't translate back and forth*/, &keyset->inner_pubkey, &sig); propose_resolution(out, complete_update_tx, 0 /* depth_required */, ELTOO_UPDATE); From 6643e7477f3e18c7167fa7bfdab13a3a6a300f63 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 30 Nov 2022 17:12:40 -0500 Subject: [PATCH 227/283] add/remove comments --- onchaind/eltoo_onchaind.c | 3 +-- onchaind/onchaind_wire.csv | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 9b5a8327a060..66a26509204c 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -788,7 +788,6 @@ static void output_spent(struct tracked_output ***outs, if (out->resolved) continue; - /* FIXME segfaulting here */ if (!wally_tx_input_spends(tx_parts->inputs[input_num], &out->outpoint)) continue; @@ -823,7 +822,7 @@ static void output_spent(struct tracked_output ***outs, /* We ignore this timeout tx, since we should * resolve by ignoring once we reach depth. */ onchain_annotate_txout( - &htlc_outpoint, + &htlc_outpoint, TX_CHANNEL_HTLC_TIMEOUT | TX_THEIRS); break; diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 89bbe447469d..653ce7462690 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -82,6 +82,8 @@ msgdata,onchaind_spent,locktime,u32, msgdata,onchaind_spent,input_num,u32, msgdata,onchaind_spent,blockheight,u32, +# FIXME make a onchaind_spent_reply to let node know about latest utxo ? + # master->onchaind: We will receive more than one of these, as depth changes. msgtype,onchaind_depth,5005 msgdata,onchaind_depth,txid,bitcoin_txid, From a72daf0cf66a696e54dd99a448b2c501380679a6 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Dec 2022 12:06:59 -0500 Subject: [PATCH 228/283] Expose rebound update txns over RPC, fix some bugs --- common/update_tx.c | 83 +++++++++++++++++++++ common/update_tx.h | 14 ++++ contrib/startup_regtest.sh | 25 ++++--- lightningd/channel.c | 1 + lightningd/channel.h | 5 ++ lightningd/onchain_control.c | 21 ++++++ lightningd/peer_control.c | 37 ++++++--- lightningd/test/run-invoice-select-inchan.c | 12 +++ onchaind/eltoo_onchaind.c | 81 ++++++++++++++++++-- onchaind/onchaind_wire.csv | 12 ++- wallet/test/run-wallet.c | 12 +++ 11 files changed, 272 insertions(+), 31 deletions(-) diff --git a/common/update_tx.c b/common/update_tx.c index 6fb3cbb66fbc..ec492bbf5dba 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -207,6 +207,89 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, bitcoin_tx_input_set_witness(update_tx, /* input_num */ 0, update_witness); } +struct bitcoin_tx **bind_txs_to_update_outpoint(const struct bitcoin_tx *update_tx, + const struct bitcoin_outpoint *latest_outpoint, + const struct bitcoin_tx *settle_tx, + const u8 *invalidated_annex_hint, + u32 invalidated_update_num, + const struct partial_sig *psig1, + const struct partial_sig *psig2, + const struct pubkey *funding_pubkey1, + const struct pubkey *funding_pubkey2, + const struct musig_session *session) +{ + struct bitcoin_tx **bound_update_and_settle_txs = tal_arr(tmpctx, struct bitcoin_tx *, 2); + + u8 *p = tal_arr(tmpctx, u8, 0); + const u8 *p_start; + struct bitcoin_tx *bound_update_tx, *bound_settle_tx; + size_t p_len; + const secp256k1_musig_partial_sig * psig_ptrs[2]; + const struct pubkey * pubkey_ptrs[2]; + struct bip340sig sig; + int ok; + secp256k1_musig_keyagg_cache dummy_cache; + struct pubkey inner_pubkey; + struct eltoo_keyset keyset_copy; + struct bitcoin_txid update_txid; + towire_bitcoin_tx(&p, update_tx); + p_start = p; + p_len = tal_count(p); + bound_update_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); + assert(bound_update_tx); + + /* re-set and serialize settle tx next */ + p = tal_arr(tmpctx, u8, 0); + towire_bitcoin_tx(&p, settle_tx); + p_start = p; + + p_len = tal_count(p); + bound_settle_tx = fromwire_bitcoin_tx(tmpctx, &p_start, &p_len); + assert(bound_settle_tx); + + psig_ptrs[0] = &psig1->p_sig; + psig_ptrs[1] = &psig2->p_sig; + + keyset_copy.self_funding_key = *funding_pubkey1; + keyset_copy.other_funding_key = *funding_pubkey2; + /* FIXME: inner_pubkey should be in PSBT, don't need to make key here */ + pubkey_ptrs[0] = &keyset_copy.self_funding_key; + pubkey_ptrs[1] = &keyset_copy.other_funding_key; + + ok = bipmusig_partial_sigs_combine(psig_ptrs, + 2 /* num_signers */, + &session->session, + &sig); + assert(ok); // Trusted data!!! + + bipmusig_inner_pubkey(&inner_pubkey, + &dummy_cache, + pubkey_ptrs, + 2 /* n_pubkeys */); + + /* FIXME pass in pubkeys, not keyset ... or get pubkeys from PSBT directly */ + bind_update_tx_to_update_outpoint(bound_update_tx, + bound_settle_tx, + latest_outpoint, + &keyset_copy, + invalidated_annex_hint, + invalidated_update_num, + &inner_pubkey, + &sig); + + bitcoin_txid(bound_update_tx, &update_txid); + bind_settle_tx(update_txid, + 0 /* output_index: we can't know for sure until update tx confirms, this is + for ease of use */, + bound_settle_tx); + + bound_update_and_settle_txs[0] = bound_update_tx; + bound_update_and_settle_txs[1] = bound_settle_tx; + + return bound_update_and_settle_txs; +} + + struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx, const struct bitcoin_outpoint *funding, const struct bitcoin_tx *settle_tx, diff --git a/common/update_tx.h b/common/update_tx.h index 3025e82229f0..a87a0e13c490 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -62,6 +62,20 @@ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update const struct pubkey *funding_pubkey2, const struct musig_session *session); +/* Wrapper for bind_update_tx_to_update_outpoint and bind_settle_tx which + * clones the original transactions and returns blinded bound + * transactions: update then settle transactions */ +struct bitcoin_tx **bind_txs_to_update_outpoint(const struct bitcoin_tx *update_tx, + const struct bitcoin_outpoint *latest_outpoint, + const struct bitcoin_tx *settle_tx, + const u8 *invalidated_annex_hint, + u32 invalidated_update_num, + const struct partial_sig *psig1, + const struct partial_sig *psig2, + const struct pubkey *funding_pubkey1, + const struct pubkey *funding_pubkey2, + const struct musig_session *session); + /* Used to bind the update transaction to the non-funding outpoints * of the eltoo contract. This only occurs if invalidated update * transactions are published, e.g. faulty watchtower, or malicious diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 08697b282ecd..ed4a65c3402f 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -191,20 +191,23 @@ onchain_ln() { # Test for old update hitting chain txid=$(bt-cli decoderawtransaction $FIRST_UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 - # FIXME no way of grabbing latest bound tx to latest state output - # except by scraping logs - #txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) - #bt-cli prioritisetransaction $txid 0 100000000 - # Only manually send first bt-cli sendrawtransaction $FIRST_UPDATE_HEX bt-cli generatetoaddress 1 $btcaddr - - # Settle tx can be broadcast after shared_delay, onchaind should - # be trying to spend the update tx output itself! - bt-cli generatetoaddress 6 $btcaddr - txid=$(bt-cli decoderawtransaction $FIRST_SETTLE_HEX | jq -r .txid) + sleep 1 + # Should be re-bound now + UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) + txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) bt-cli prioritisetransaction $txid 0 100000000 - bt-cli sendrawtransaction $FIRST_SETTLE_HEX + bt-cli generatetoaddress 1 $btcaddr + # Make sure final update txn is rebroadcasted into mempool + sleep 1 + bt-cli generatetoaddress 1 $btcaddr + SETTLE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_settle_tx ) + txid=$(bt-cli decoderawtransaction $SETTLE_HEX | jq -r .txid) + bt-cli prioritisetransaction $txid 0 100000000 + bt-cli generatetoaddress 6 $btcaddr + # Make sure settle txn is broadcasted into mempool + sleep 1 bt-cli generatetoaddress 1 $btcaddr } diff --git a/lightningd/channel.c b/lightningd/channel.c index 2a4d96c4e5e8..a770b62d0200 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -485,6 +485,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->eltoo_keyset.other_next_nonce = *their_next_nonce; channel->eltoo_keyset.self_next_nonce = *our_next_nonce; } + channel->onchain_invalidated_annex_hint = NULL; channel->last_htlc_sigs = tal_steal(channel, last_htlc_sigs); channel->channel_info = *channel_info; channel->fee_states = dup_fee_states(channel, fee_states); diff --git a/lightningd/channel.h b/lightningd/channel.h index 6129b83bf053..6ea6f1ddc6d5 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -154,6 +154,11 @@ struct channel { /* Stores "last" psigs, session */ struct eltoo_keyset eltoo_keyset; + /* Cache of state output information */ + struct bitcoin_outpoint onchain_state_outpoint; + u32 onchain_invalidated_update_num; + u8 *onchain_invalidated_annex_hint; + /* Keys for channel */ struct channel_info channel_info; diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index b096e4e116ab..e02f49f92a19 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -331,6 +331,23 @@ static void handle_onchain_log_coin_move(struct channel *channel, const u8 *msg) tal_free(mvt); } +static void handle_new_state_output(struct channel *channel, const u8 *msg) +{ + struct bitcoin_outpoint out; + u32 invalidated_update_num; + u8 *invalidated_annext_hint; + + if (!fromwire_eltoo_onchaind_new_state_output(msg, msg, &out, &invalidated_update_num, &invalidated_annext_hint)) { + channel_internal_error(channel, "Invalid onchain new_state_output"); + } + + /* Populate state output hints for listpeers */ + channel->onchain_state_outpoint = out; + channel->onchain_invalidated_update_num = invalidated_update_num; + tal_free(channel->onchain_invalidated_annex_hint); + channel->onchain_invalidated_annex_hint = tal_steal(channel, invalidated_annext_hint); +} + /** handle_onchain_broadcast_rbf_tx_cb * * @brief suppresses the rebroadcast of a @@ -637,6 +654,7 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U /* These are illegal */ case WIRE_ELTOO_ONCHAIND_INIT: case WIRE_ELTOO_ONCHAIND_INIT_REPLY: + case WIRE_ELTOO_ONCHAIND_NEW_STATE_OUTPUT: abort(); } @@ -672,6 +690,9 @@ static unsigned int eltoo_onchain_msg(struct subd *sd, const u8 *msg, const int case WIRE_ONCHAIND_ANNOTATE_TXOUT: onchain_annotate_txout(sd->channel, msg); break; + case WIRE_ELTOO_ONCHAIND_NEW_STATE_OUTPUT: + handle_new_state_output(sd->channel, msg); + break; case WIRE_ONCHAIND_HTLC_TIMEOUT: /* FIXME what needs to change for handling? */ handle_onchain_htlc_timeout(sd->channel, msg); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 8bd9827d516f..9c1f7ffe593d 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1005,21 +1005,38 @@ static void json_add_channel(struct lightningd *ld, if (channel->our_config.is_eltoo) { struct bitcoin_tx **bound_update_and_settle_txs; /* Eltoo keyset should probably have all pubkeys... */ - /* FIXME would be nice to rebind to latest utxo, not just funding output that may by spent already */ - bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->eltoo_keyset.complete_update_tx, - &channel->funding, - channel->eltoo_keyset.complete_settle_tx, - &channel->eltoo_keyset.last_complete_state.self_psig, - &channel->eltoo_keyset.last_complete_state.other_psig, - &channel->local_funding_pubkey, - &channel->channel_info.remote_fundingkey, - &channel->eltoo_keyset.last_complete_state.session); + if (channel->onchain_invalidated_annex_hint) { + /* If channel has this set, it means eltoo_onchaind has reported an invalidated state output onchain */ + bound_update_and_settle_txs = bind_txs_to_update_outpoint(channel->eltoo_keyset.complete_update_tx, + &channel->onchain_state_outpoint, + channel->eltoo_keyset.complete_settle_tx, + channel->onchain_invalidated_annex_hint, + channel->onchain_invalidated_update_num, + &channel->eltoo_keyset.last_complete_state.self_psig, + &channel->eltoo_keyset.last_complete_state.other_psig, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, + &channel->eltoo_keyset.last_complete_state.session); + + } else { + bound_update_and_settle_txs = bind_txs_to_funding_outpoint(channel->eltoo_keyset.complete_update_tx, + &channel->funding, + channel->eltoo_keyset.complete_settle_tx, + &channel->eltoo_keyset.last_complete_state.self_psig, + &channel->eltoo_keyset.last_complete_state.other_psig, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, + &channel->eltoo_keyset.last_complete_state.session); + } json_add_tx(response, "last_update_tx", bound_update_and_settle_txs[0]); json_add_tx(response, "last_settle_tx", bound_update_and_settle_txs[1]); + tal_free(bound_update_and_settle_txs[0]); + tal_free(bound_update_and_settle_txs[1]); json_add_tx(response, "unbound_update_tx", channel->eltoo_keyset.complete_update_tx); json_add_tx(response, "unbound_settle_tx", channel->eltoo_keyset.complete_settle_tx); - /* FIXME Deallocate copied txns? */ + + /* FIXME we need to expose committed txs too for settlement purposes at least */ } json_object_end(response); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index d1d7a44ce44c..fa14814d4b42 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -24,6 +24,18 @@ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update const struct pubkey *funding_pubkey2 UNNEEDED, const struct musig_session *session UNNEEDED) { fprintf(stderr, "bind_txs_to_funding_outpoint called!\n"); abort(); } +/* Generated stub for bind_txs_to_update_outpoint */ +struct bitcoin_tx **bind_txs_to_update_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, + const struct bitcoin_outpoint *latest_outpoint UNNEEDED, + const struct bitcoin_tx *settle_tx UNNEEDED, + const u8 *invalidated_annex_hint UNNEEDED, + u32 invalidated_update_num UNNEEDED, + const struct partial_sig *psig1 UNNEEDED, + const struct partial_sig *psig2 UNNEEDED, + const struct pubkey *funding_pubkey1 UNNEEDED, + const struct pubkey *funding_pubkey2 UNNEEDED, + const struct musig_session *session UNNEEDED) +{ fprintf(stderr, "bind_txs_to_update_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 66a26509204c..4af16e0d3730 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -85,6 +85,7 @@ struct tracked_output { u32 depth; struct amount_sat sat; enum output_type output_type; + u32 locktime; /* Used to detec update->settle transition */ /* If it is an HTLC, this is set, tapscripts are non-NULL. */ struct htlc_stub htlc; @@ -218,6 +219,7 @@ new_tracked_output(struct tracked_output ***outs, enum eltoo_tx_type tx_type, struct amount_sat sat, enum output_type output_type, + u32 locktime, const struct htlc_stub *htlc, const u8 *htlc_success_tapscript TAKES, const u8 *htlc_timeout_tapscript TAKES) @@ -235,6 +237,7 @@ new_tracked_output(struct tracked_output ***outs, out->depth = 0; out->sat = sat; out->output_type = output_type; + out->locktime = locktime; out->proposal = NULL; out->resolved = NULL; if (htlc) @@ -761,6 +764,7 @@ static void track_settle_outputs(struct tracked_output ***outs, ELTOO_SETTLE, satoshis, htlc_type /* output_type */, + 0 /* locktime (unused by settle logic) */, &htlcs_info->htlcs[matches[0]] /* htlc */, htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); @@ -776,6 +780,7 @@ static void output_spent(struct tracked_output ***outs, const struct tx_parts *tx_parts, u32 input_num, u32 tx_blockheight, + u32 locktime, u8 **htlc_success_scripts, u8 **htlc_timeout_scripts, struct htlcs_info *htlcs_info) @@ -794,14 +799,65 @@ static void output_spent(struct tracked_output ***outs, /* Was this our resolution? */ if (resolved_by_proposal(out, tx_parts)) { + /* FIXME Do we actually care if it was us for most cases? */ if (out->resolved->tx_type == ELTOO_SETTLE) { track_settle_outputs(outs, tx_parts, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); + return; } - /* FIXME handle our own response update tx being mined */ - return; } - /* FIXME handle old update hitting the chain here */ + /* Must be an update transaction since nlocktime is increasing */ + if (locktime != out->locktime) { + /* New state output will be on same index as tx input spending state */ + struct bitcoin_outpoint outpoint; + struct amount_asset asset; + struct amount_sat amt; + struct tracked_output *new_state_out; + + asset = wally_tx_output_get_amount(tx_parts->outputs[input_num]); + amt = amount_asset_to_sat(&asset); + outpoint.txid = tx_parts->txid; + outpoint.n = input_num; + + new_state_out = new_tracked_output(outs, &outpoint, tx_blockheight, ELTOO_UPDATE, amt, DELAYED_OUTPUT_TO_US, locktime, + NULL /* htlcs */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); + + if (locktime == complete_update_tx->wtx->locktime) { + bind_settle_tx(tx_parts->txid, input_num, complete_settle_tx); + propose_resolution(new_state_out, complete_settle_tx, complete_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); + } else if (committed_update_tx && locktime == committed_update_tx->wtx->locktime) { + bind_settle_tx(tx_parts->txid, input_num, committed_settle_tx); + propose_resolution(new_state_out, committed_settle_tx, committed_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); + } else if ((committed_update_tx && locktime > committed_update_tx->wtx->locktime) || + (!committed_update_tx && locktime > complete_update_tx->wtx->locktime)) { + /* If we get lucky the settle transaction will hit chain and we can get balance back */ + /* FIXME Should we give up after a long time? */ + status_debug("Uh-oh, update from the future!"); + } else { + /* FIXME probably should assert something here even though we checked for index already? */ + struct wally_tx_witness_stack *wit_stack = tx_parts->inputs[input_num]->witness; + u8 *invalidated_annex_hint = wit_stack->items[wit_stack->num_items - 1].witness; /* Annex is last witness item! */ + struct bip340sig sig; + u32 invalidated_update_num = locktime - 500000000; + bipmusig_partial_sigs_combine_state(&keyset->last_complete_state, &sig); + /* Need to propose our last complete update */ + bind_update_tx_to_update_outpoint(complete_update_tx, + complete_settle_tx, + &outpoint, + keyset, + invalidated_annex_hint, + invalidated_update_num, + &keyset->inner_pubkey, + &sig); + propose_resolution(out, complete_update_tx, 0 /* depth_required */, ELTOO_UPDATE); + + /* Inform master of latest known state output to rebind to over RPC responses + * We don't send complete/committed_tx state outputs or future ones */ + wire_sync_write(REQ_FD, + take(towire_eltoo_onchaind_new_state_output(out, &outpoint, invalidated_update_num, invalidated_annex_hint))); + } + + } /* FIXME handle complete update tx hitting the chain */ @@ -864,6 +920,8 @@ static void output_spent(struct tracked_output ***outs, case DELAYED_OUTPUT_TO_US: case ELEMENTS_FEE: case ANCHOR_TO_US: + /* FIXME none of this is working, just return for now */ + return; case ANCHOR_TO_THEM: status_failed(STATUS_FAIL_INTERNAL_ERROR, "Tracked spend of %s/%s?", @@ -1112,7 +1170,7 @@ static void wait_for_resolved(struct tracked_output **outs, struct htlcs_info *h eltoo_tx_new_depth(outs, &txid, depth); } else if (fromwire_onchaind_spent(msg, msg, &tx_parts, &locktime, &input_num, &tx_blockheight)) { - output_spent(&outs, tx_parts, input_num, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); + output_spent(&outs, tx_parts, input_num, tx_blockheight, locktime, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) /* We could be watching our settlement outputs even if they haven't entered utxo set to use for CPFP. */ @@ -1265,6 +1323,7 @@ static void handle_unilateral(const struct tx_parts *tx, ELTOO_UPDATE, amt, DELAYED_OUTPUT_TO_US, + locktime, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); /* Fill out inner pubkey to complete re-binding of update transactions going forward */ @@ -1290,10 +1349,10 @@ static void handle_unilateral(const struct tx_parts *tx, status_debug("Uh-oh, update from the future!"); } else { /* FIXME probably should assert something here even though we checked for index already? */ - /* FIXME getting taproot committment mismatch here */ struct wally_tx_witness_stack *wit_stack = tx->inputs[state_index]->witness; u8 *invalidated_annex_hint = wit_stack->items[wit_stack->num_items - 1].witness; /* Annex is last witness item! */ struct bip340sig sig; + u32 invalidated_update_num = locktime - 500000000; bipmusig_partial_sigs_combine_state(&keyset->last_complete_state, &sig); /* Need to propose our last complete update */ bind_update_tx_to_update_outpoint(complete_update_tx, @@ -1301,13 +1360,18 @@ static void handle_unilateral(const struct tx_parts *tx, &outpoint, keyset, invalidated_annex_hint, - locktime - 500000000 /* invalidated_update_number FIXME don't translate back and forth*/, + invalidated_update_num, &keyset->inner_pubkey, &sig); propose_resolution(out, complete_update_tx, 0 /* depth_required */, ELTOO_UPDATE); + + /* Inform master of latest known state output to rebind to over RPC responses + * We don't send complete/committed_tx state outputs or future ones */ + wire_sync_write(REQ_FD, + take(towire_eltoo_onchaind_new_state_output(out, &outpoint, invalidated_update_num, invalidated_annex_hint))); + } - /* Run to completion since we don't fan out immediately in eltoo */ wait_for_resolved(outs, htlcs_info); tal_free(htlcs_info); @@ -1391,7 +1455,8 @@ int main(int argc, char *argv[]) 0, /* We don't care about funding blockheight */ FUNDING_TRANSACTION, funding_sats, - FUNDING_OUTPUT, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); + FUNDING_OUTPUT, + locktime, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); /* Record funding output spent */ send_coin_mvt(take(new_coin_channel_close(NULL, &spending_tx->txid, diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 653ce7462690..ce6d6832dc22 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -82,8 +82,6 @@ msgdata,onchaind_spent,locktime,u32, msgdata,onchaind_spent,input_num,u32, msgdata,onchaind_spent,blockheight,u32, -# FIXME make a onchaind_spent_reply to let node know about latest utxo ? - # master->onchaind: We will receive more than one of these, as depth changes. msgtype,onchaind_depth,5005 msgdata,onchaind_depth,txid,bitcoin_txid, @@ -171,3 +169,13 @@ msgdata,eltoo_onchaind_init,complete_session,musig_session, # This says we're ready; give us htlcs and preimages. msgtype,eltoo_onchaind_init_reply,5161 + +# onchaind->master: Notifier that a new state output has been created, used +# for debugging purposes +msgtype,eltoo_onchaind_new_state_output,5062 +msgdata,eltoo_onchaind_new_state_output,new_prevout,bitcoin_outpoint, +msgdata,eltoo_onchaind_new_state_output,invalidated_update_num,u32, +msgdata,eltoo_onchaind_new_state_output,annex_hint_len,u16, +msgdata,eltoo_onchaind_new_state_output,invalidated_annex_hint,u8,annex_hint_len + + diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 982d2aee017d..79e47689db65 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -61,6 +61,18 @@ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update const struct pubkey *funding_pubkey2 UNNEEDED, const struct musig_session *session UNNEEDED) { fprintf(stderr, "bind_txs_to_funding_outpoint called!\n"); abort(); } +/* Generated stub for bind_txs_to_update_outpoint */ +struct bitcoin_tx **bind_txs_to_update_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, + const struct bitcoin_outpoint *latest_outpoint UNNEEDED, + const struct bitcoin_tx *settle_tx UNNEEDED, + const u8 *invalidated_annex_hint UNNEEDED, + u32 invalidated_update_num UNNEEDED, + const struct partial_sig *psig1 UNNEEDED, + const struct partial_sig *psig2 UNNEEDED, + const struct pubkey *funding_pubkey1 UNNEEDED, + const struct pubkey *funding_pubkey2 UNNEEDED, + const struct musig_session *session UNNEEDED) +{ fprintf(stderr, "bind_txs_to_update_outpoint called!\n"); abort(); } /* Generated stub for bitcoind_getutxout_ */ void bitcoind_getutxout_(struct bitcoind *bitcoind UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED, From 2eca9b18f48a7496226c5ffd46bbd0f6213c00ef Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 2 Dec 2022 14:13:04 -0500 Subject: [PATCH 229/283] Add untested hooks to introspect committed settle tx in RPC --- common/update_tx.c | 1 + contrib/startup_regtest.sh | 1 + lightningd/channel.h | 4 +++- lightningd/onchain_control.c | 13 +++++++++---- lightningd/peer_control.c | 11 +++++++++-- lightningd/test/run-invoice-select-inchan.c | 5 +++++ onchaind/eltoo_onchaind.c | 7 +++++++ wallet/test/run-wallet.c | 5 +++++ 8 files changed, 40 insertions(+), 7 deletions(-) diff --git a/common/update_tx.c b/common/update_tx.c index ec492bbf5dba..a4c9637f2df1 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -132,6 +132,7 @@ void bind_settle_tx(const struct bitcoin_txid update_txid, { assert(settle_tx->wtx->num_inputs == 1); /* We don't craft anything else */ memcpy(settle_tx->wtx->inputs[0].txhash, &update_txid, 32); + settle_tx->wtx->inputs[0].index = output_index; } void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index ed4a65c3402f..b016571cd1bb 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -193,6 +193,7 @@ onchain_ln() { bt-cli prioritisetransaction $txid 0 100000000 bt-cli sendrawtransaction $FIRST_UPDATE_HEX bt-cli generatetoaddress 1 $btcaddr + # Need to make sure onchaind are continuing first sleep 1 # Should be re-bound now UPDATE_HEX=$(l1-cli listpeers | jq -r .peers[0].channels[0].last_update_tx ) diff --git a/lightningd/channel.h b/lightningd/channel.h index 6ea6f1ddc6d5..e4489b21d17c 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -154,10 +154,12 @@ struct channel { /* Stores "last" psigs, session */ struct eltoo_keyset eltoo_keyset; - /* Cache of state output information */ + /* Cache of state output information reported by eltoo_onchaind */ struct bitcoin_outpoint onchain_state_outpoint; u32 onchain_invalidated_update_num; u8 *onchain_invalidated_annex_hint; + /* Only for rebinding committed settle tx if it exists */ + struct bitcoin_outpoint onchain_committed_hint; /* Keys for channel */ struct channel_info channel_info; diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index e02f49f92a19..183684fd8bc6 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -342,10 +342,15 @@ static void handle_new_state_output(struct channel *channel, const u8 *msg) } /* Populate state output hints for listpeers */ - channel->onchain_state_outpoint = out; - channel->onchain_invalidated_update_num = invalidated_update_num; - tal_free(channel->onchain_invalidated_annex_hint); - channel->onchain_invalidated_annex_hint = tal_steal(channel, invalidated_annext_hint); + if (tal_count(invalidated_annext_hint) > 0) { + channel->onchain_state_outpoint = out; + channel->onchain_invalidated_update_num = invalidated_update_num; + tal_free(channel->onchain_invalidated_annex_hint); + channel->onchain_invalidated_annex_hint = tal_steal(channel, invalidated_annext_hint); + } else { + /* No annex hint means this is a committed_settle_tx rebind hint only */ + channel->onchain_committed_hint = out; + } } /** handle_onchain_broadcast_rbf_tx_cb diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 9c1f7ffe593d..9176df161dbe 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1027,7 +1027,6 @@ static void json_add_channel(struct lightningd *ld, &channel->local_funding_pubkey, &channel->channel_info.remote_fundingkey, &channel->eltoo_keyset.last_complete_state.session); - } json_add_tx(response, "last_update_tx", bound_update_and_settle_txs[0]); json_add_tx(response, "last_settle_tx", bound_update_and_settle_txs[1]); @@ -1036,7 +1035,15 @@ static void json_add_channel(struct lightningd *ld, json_add_tx(response, "unbound_update_tx", channel->eltoo_keyset.complete_update_tx); json_add_tx(response, "unbound_settle_tx", channel->eltoo_keyset.complete_settle_tx); - /* FIXME we need to expose committed txs too for settlement purposes at least */ + /* Committed settle tx exists, rebind it with latest hint then unbind right after (just prevout modification) */ + if (channel->eltoo_keyset.committed_settle_tx) { + struct bitcoin_outpoint blank_out; + memset(blank_out.txid.shad.sha.u.u8, 0, sizeof(blank_out.txid)); + blank_out.n = 0; + bind_settle_tx(channel->onchain_committed_hint.txid, channel->onchain_committed_hint.n, channel->eltoo_keyset.committed_settle_tx); + json_add_tx(response, "last_committed_settle_tx", channel->eltoo_keyset.committed_settle_tx); + bind_settle_tx(blank_out.txid, blank_out.n, channel->eltoo_keyset.committed_settle_tx); + } } json_object_end(response); diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index fa14814d4b42..678b6d96922f 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -14,6 +14,11 @@ bool deprecated_apis = false; struct channel *any_channel_by_scid(struct lightningd *ld UNNEEDED, const struct short_channel_id *scid UNNEEDED) { fprintf(stderr, "any_channel_by_scid called!\n"); abort(); } +/* Generated stub for bind_settle_tx */ +void bind_settle_tx(const struct bitcoin_txid update_txid UNNEEDED, + int output_index UNNEEDED, + struct bitcoin_tx *settle_tx UNNEEDED) +{ fprintf(stderr, "bind_settle_tx called!\n"); abort(); } /* Generated stub for bind_txs_to_funding_outpoint */ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, const struct bitcoin_outpoint *funding UNNEEDED, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 4af16e0d3730..546e6bc21efe 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -1338,11 +1338,18 @@ static void handle_unilateral(const struct tx_parts *tx, /* Proposed resolution is the matching settlement tx */ if (locktime == complete_update_tx->wtx->locktime) { + status_debug("Handling the final complete update transaction."); bind_settle_tx(tx->txid, state_index, complete_settle_tx); propose_resolution(out, complete_settle_tx, complete_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); } else if (committed_update_tx && locktime == committed_update_tx->wtx->locktime) { + u8 *empty_hint = tal_arr(tmpctx, u8, 0); /* Make sure this doesn't sit around forever */ + status_debug("Handling the final committed update transaction."); bind_settle_tx(tx->txid, state_index, committed_settle_tx); propose_resolution(out, committed_settle_tx, committed_settle_tx->wtx->inputs[0].sequence /* depth_required */, ELTOO_SETTLE); + + /* Give hint to how to rebind the committed settle tx */ + wire_sync_write(REQ_FD, + take(towire_eltoo_onchaind_new_state_output(out, &outpoint, 0 /* invalidated_update_num */, empty_hint))); } else if ((committed_update_tx && locktime > committed_update_tx->wtx->locktime) || (!committed_update_tx && locktime > complete_update_tx->wtx->locktime)) { /* If we get lucky the settle transaction will hit chain and we can get balance back */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 79e47689db65..47a4e87b6f42 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -51,6 +51,11 @@ bool deprecated_apis = true; /* Generated stub for bigsize_put */ size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED) { fprintf(stderr, "bigsize_put called!\n"); abort(); } +/* Generated stub for bind_settle_tx */ +void bind_settle_tx(const struct bitcoin_txid update_txid UNNEEDED, + int output_index UNNEEDED, + struct bitcoin_tx *settle_tx UNNEEDED) +{ fprintf(stderr, "bind_settle_tx called!\n"); abort(); } /* Generated stub for bind_txs_to_funding_outpoint */ struct bitcoin_tx **bind_txs_to_funding_outpoint(const struct bitcoin_tx *update_tx UNNEEDED, const struct bitcoin_outpoint *funding UNNEEDED, From 07ee5b7732ca3301c0857f87efe04d1860957d75 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 5 Dec 2022 15:47:57 -0500 Subject: [PATCH 230/283] onchaind state machine up to HTLC resolution --- onchaind/eltoo_onchaind.c | 310 +++++++++++++++++++++---------------- onchaind/onchain_types.h | 5 +- onchaind/onchaind_wire.csv | 2 - 3 files changed, 176 insertions(+), 141 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 546e6bc21efe..25b949c77a46 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -40,6 +40,9 @@ static bool bipmusig_partial_sigs_combine_state(const struct eltoo_sign *state, return bipmusig_partial_sigs_combine(p_sigs, 2 /* num_signers */, &state->session.session, sig); } +/* Used as one-way latch to detect when the state ordering is being settled */ +static bool update_phase; + /* Full tx we have partial signatures for */ static struct bitcoin_tx *complete_update_tx, *complete_settle_tx; @@ -63,7 +66,8 @@ static struct amount_msat our_msat; /* If we broadcast a tx, or need a delay to resolve the output. */ struct proposed_resolution { - /* This can be NULL if our proposal is to simply ignore it after depth */ + /* This can be NULL if our proposal is to simply ignore it after depth + OR if we can make a transaction JIT (ELTOO_HTLC_{SUCESS/TIMEOUT}) */ const struct bitcoin_tx *tx; /* Non-zero if this is CSV-delayed. */ u32 depth_required; @@ -157,6 +161,16 @@ static u8 **derive_htlc_timeout_scripts(const tal_t *ctx, const struct htlc_stub return htlc_scripts; } +/* +static size_t resolve_htlc_timeouts(struct tracked_output *out, + const struct htlc_stub htlc, + u8 *htlc_success_script, + u8 *htlc_timeout_script) + +{ + return 0; +}*/ + /* They must all be in the same direction, since the scripts are different for * each dir. Unless, of course, they've found a sha256 clash. */ static enum side matches_direction(const size_t *matches, @@ -264,7 +278,7 @@ static void ignore_output(struct tracked_output *out) out->resolved = tal(out, struct resolution); out->resolved->txid = out->outpoint.txid; out->resolved->depth = 0; - out->resolved->tx_type = SELF; + out->resolved->tx_type = ELTOO_SELF; } static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum eltoo_tx_type t) @@ -279,7 +293,8 @@ static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum eltoo_tx_type t) case ELTOO_INVALIDATED_UPDATE: case ELTOO_SETTLE: case ELTOO_INVALIDATED_SETTLE: - case ELTOO_SWEEP: + case ELTOO_HTLC_SUCCESS: + case ELTOO_HTLC_TIMEOUT: case ELTOO_IGNORING_TINY_PAYMENT: case ELTOO_SELF: case ELTOO_UNKNOWN_TXTYPE: @@ -300,7 +315,8 @@ static bool eltoo_proposal_is_rbfable(const struct proposed_resolution *proposal */ return proposal->tx_type == ELTOO_UPDATE || proposal->tx_type == ELTOO_SETTLE || - proposal->tx_type == ELTOO_SWEEP; + proposal->tx_type == ELTOO_HTLC_SUCCESS || + proposal->tx_type == ELTOO_HTLC_TIMEOUT; } /** proposal_should_rbf @@ -358,13 +374,15 @@ static void eltoo_proposal_should_rbf(struct tracked_output *out) static void eltoo_proposal_meets_depth(struct tracked_output *out) { - bool is_rbf = false; + bool is_rbf = eltoo_proposal_is_rbfable(out->proposal); + + /* We only propose something if we have something to do */ +// if (!out->proposal->tx && +// out->proposal->tx_type != ELTOO_HTLC_TIMEOUT) { +// ignore_output(out); +// return; +// } - /* If there's no proposal, we're not gonna do anything. */ - if (!out->proposal->tx) { - ignore_output(out); - return; - } status_debug("Broadcasting %s (%s) to resolve %s/%s", eltoo_tx_type_name(out->proposal->tx_type), @@ -372,11 +390,6 @@ static void eltoo_proposal_meets_depth(struct tracked_output *out) eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type)); - if (out->proposal) - /* Any state transition we want is going to be package-RBFed. */ - is_rbf = eltoo_proposal_is_rbfable(out->proposal); - - /* FIXME Figure out how fees are going to be paid via anchor */ wire_sync_write( REQ_FD, take(towire_onchaind_broadcast_tx( @@ -583,7 +596,7 @@ static void billboard_update(struct tracked_output **outs) static void propose_resolution(struct tracked_output *out, const struct bitcoin_tx *tx, unsigned int depth_required, - enum tx_type tx_type) + enum eltoo_tx_type tx_type) { status_debug("Propose handling %s/%s by %s (%s) after %u blocks", eltoo_tx_type_name(out->tx_type), @@ -601,6 +614,39 @@ static void propose_resolution(struct tracked_output *out, eltoo_proposal_meets_depth(out); } +/* HTLC resolution won't have tx pre-built */ +static void propose_htlc_timeout_resolution(struct tracked_output *out, + unsigned int depth_required) +{ + status_debug("Propose handling %s/%s by %s after %u blocks", + eltoo_tx_type_name(out->tx_type), + output_type_name(out->output_type), + eltoo_tx_type_name(ELTOO_HTLC_TIMEOUT), + depth_required); + + out->proposal = tal(out, struct proposed_resolution); + out->proposal->depth_required = depth_required; + out->proposal->tx_type = ELTOO_HTLC_TIMEOUT; + + if (depth_required == 0) + eltoo_proposal_meets_depth(out); +} + +/* HTLC resolution won't have tx pre-built */ +static void propose_htlc_resolution_at_block(struct tracked_output *out, + unsigned int block_required, + enum eltoo_tx_type tx_type) +{ + u32 depth; + + /* Expiry could be in the past! */ + if (block_required < out->tx_blockheight) + depth = 0; + else /* Note that out->tx_blockheight is already at depth 1 */ + depth = block_required - out->tx_blockheight + 1; + propose_htlc_timeout_resolution(out, depth); +} + static void unwatch_txid(const struct bitcoin_txid *txid) { u8 *msg; @@ -609,6 +655,7 @@ static void unwatch_txid(const struct bitcoin_txid *txid) wire_sync_write(REQ_FD, take(msg)); } + static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, const struct tx_parts *tx_parts, const struct bitcoin_outpoint *htlc_outpoint) @@ -668,13 +715,6 @@ static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, &preimage))); } -static void onchain_annotate_txout(const struct bitcoin_outpoint *outpoint, - enum wallet_tx_type type) -{ - wire_sync_write(REQ_FD, take(towire_onchaind_annotate_txout( - tmpctx, outpoint, type))); -} - static void onchain_annotate_txin(const struct bitcoin_txid *txid, u32 innum, enum wallet_tx_type type) { @@ -714,6 +754,7 @@ static void track_settle_outputs(struct tracked_output ***outs, /* Everything should be taproot FIXME what do */ abort(); } + /* Balance outputs are self-resolving in the settle tx */ status_debug("Output script: %s", tal_hex(tmpctx, settle_out->script)); u8 *to_us = scriptpubkey_p2tr(tmpctx, &keyset->self_settle_key); status_debug("to_us script: %s", tal_hex(tmpctx, to_us)); @@ -748,27 +789,36 @@ static void track_settle_outputs(struct tracked_output ***outs, continue; } /* Update we don't recognise :( FIXME what do */ + /* This can hit if it was a "future" settlement transaction, which terminates the process with an error */ status_failed(STATUS_FAIL_INTERNAL_ERROR, "Couldn't match settlement output script to known output type"); } else { - enum output_type htlc_type; if (matches_direction(matches, htlcs_info->htlcs) == LOCAL) { /* (4) HTLC to us */ - htlc_type = THEIR_HTLC; + out = new_tracked_output(outs, &outpoint, + tx_blockheight, + ELTOO_SETTLE, + satoshis, + THEIR_HTLC, + 0 /* locktime (unused by settle logic) */, + &htlcs_info->htlcs[matches[0]] /* htlc */, + htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, + htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); + /* FIXME Proposal comes in at handle_preimage? */ } else { /* (5) HTLC to them */ - htlc_type = OUR_HTLC; + out = new_tracked_output(outs, &outpoint, + tx_blockheight, + ELTOO_SETTLE, + satoshis, + OUR_HTLC, + 0 /* locktime (unused by settle logic) */, + &htlcs_info->htlcs[matches[0]] /* htlc */, + htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, + htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); + + /* We'd like to propose a reasonable feerate tx at the time needed, not before */ + propose_htlc_resolution_at_block(out, htlcs_info->htlcs[matches[0]].cltv_expiry, ELTOO_HTLC_TIMEOUT); } - /* FIXME we need to propose a resolution for this output */ - out = new_tracked_output(outs, &outpoint, - tx_blockheight, - ELTOO_SETTLE, - satoshis, - htlc_type /* output_type */, - 0 /* locktime (unused by settle logic) */, - &htlcs_info->htlcs[matches[0]] /* htlc */, - htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, - htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); - // FIXME resolve_our_htlc_ourcommit <--- do something like this which proposes resolution tx assert(out); continue; } @@ -788,7 +838,7 @@ static void output_spent(struct tracked_output ***outs, assert(tal_count(htlc_success_scripts) == tal_count(htlc_timeout_scripts)); for (size_t i = 0; i < tal_count(*outs); i++) { struct tracked_output *out = (*outs)[i]; - struct bitcoin_outpoint htlc_outpoint; + struct bitcoin_outpoint htlc_outpoint; if (out->resolved) continue; @@ -797,17 +847,21 @@ static void output_spent(struct tracked_output ***outs, &out->outpoint)) continue; - /* Was this our resolution? */ - if (resolved_by_proposal(out, tx_parts)) { - /* FIXME Do we actually care if it was us for most cases? */ - if (out->resolved->tx_type == ELTOO_SETTLE) { - track_settle_outputs(outs, tx_parts, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); - return; - } - } + /* This output spend was either ours, or someone else's. Output is resolved either way */ + if (!resolved_by_proposal(out, tx_parts)) { + ignore_output(out); + } + + /* (1) Settlement transaction */ + if (locktime == out->locktime && update_phase) { + /* Update phase ends with repeating locktime, which should be settle tx */ + update_phase = false; + + /* Should be (any) settlement transaction! Process new outputs */ + track_settle_outputs(outs, tx_parts, tx_blockheight, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); + } else if (locktime != out->locktime && update_phase) { + /* (2) Update transaction*/ - /* Must be an update transaction since nlocktime is increasing */ - if (locktime != out->locktime) { /* New state output will be on same index as tx input spending state */ struct bitcoin_outpoint outpoint; struct amount_asset asset; @@ -849,99 +903,68 @@ static void output_spent(struct tracked_output ***outs, invalidated_update_num, &keyset->inner_pubkey, &sig); - propose_resolution(out, complete_update_tx, 0 /* depth_required */, ELTOO_UPDATE); + propose_resolution(new_state_out, complete_update_tx, 0 /* depth_required */, ELTOO_UPDATE); /* Inform master of latest known state output to rebind to over RPC responses * We don't send complete/committed_tx state outputs or future ones */ wire_sync_write(REQ_FD, take(towire_eltoo_onchaind_new_state_output(out, &outpoint, invalidated_update_num, invalidated_annex_hint))); } - + } else { + /* (3) Any transaction after settlement */ + + htlc_outpoint.txid = tx_parts->txid; + htlc_outpoint.n = input_num; + + /* We are only tracking HTLC outputs */ + switch (out->output_type) { + case OUR_HTLC: + /* They swept(and revealed HTLC), or we swept via timeout */ + + /* They revealed HTLC (sig+htlc+script+control block) */ + if (tx_parts->inputs[htlc_outpoint.n]->witness->num_items == 4) { + handle_eltoo_htlc_onchain_fulfill(out, tx_parts, &htlc_outpoint); + } + + /* We swept ¯\_(ツ)_/¯ (sig+script+control block only) */ + break; + case THEIR_HTLC: + /* We fulfilled and swept, or they timed out and we already swept. + * Either way we're done. + */ + break; + /* We don't track these; should never hit! */ + case OUTPUT_TO_US: + case DELAYED_OUTPUT_TO_THEM: + case DELAYED_CHEAT_OUTPUT_TO_THEM: + case DELAYED_OUTPUT_TO_US: + case OUTPUT_TO_THEM: + case ELEMENTS_FEE: + case ANCHOR_TO_US: + case ANCHOR_TO_THEM: + case FUNDING_OUTPUT: + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tracked spend of %s/%s?", + eltoo_tx_type_name(out->tx_type), + output_type_name(out->output_type)); + } } + /* If we got this far, we found the matching output, stop */ + return; + } - /* FIXME handle complete update tx hitting the chain */ - - /* FIXME handle committed update tx hitting the chain */ - - htlc_outpoint.txid = tx_parts->txid; - htlc_outpoint.n = input_num; - - switch (out->output_type) { - case OUTPUT_TO_US: - /* FIXME I'm gonna call this the state output, post-funding */ - /* There is no delayed to us... it just goes into our wallet - case DELAYED_OUTPUT_TO_US: - unknown_spend(out, tx_parts); - break; - */ - case THEIR_HTLC: - /* We ignore this timeout tx, since we should - * resolve by ignoring once we reach depth. */ - onchain_annotate_txout( - &htlc_outpoint, - TX_CHANNEL_HTLC_TIMEOUT | TX_THEIRS); - break; - - case OUR_HTLC: - /* The only way they can spend this: fulfill; even - * if it's revoked: */ - handle_eltoo_htlc_onchain_fulfill(out, tx_parts, - &htlc_outpoint); - - /* FIXME this is impossible, commenting out */ -// if (out->tx_type == THEIR_REVOKED_UNILATERAL) { -// } else { - /* BOLT #5: - * - * ## HTLC Output Handling: Local Commitment, - * Local Offers - *... - * - if the commitment transaction HTLC output - * is spent using the payment preimage, the - * output is considered *irrevocably resolved* - */ - ignore_output(out); - - onchain_annotate_txout( - &htlc_outpoint, - TX_CHANNEL_HTLC_SUCCESS | TX_THEIRS); -// } - break; - - case FUNDING_OUTPUT: - /* Master should be restarting us, as this implies - * that our old tx was unspent. */ - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Funding output spent again!"); - /* Um, we don't track these! */ - case OUTPUT_TO_THEM: - case DELAYED_OUTPUT_TO_THEM: - case DELAYED_CHEAT_OUTPUT_TO_THEM: - case DELAYED_OUTPUT_TO_US: - case ELEMENTS_FEE: - case ANCHOR_TO_US: - /* FIXME none of this is working, just return for now */ - return; - case ANCHOR_TO_THEM: - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Tracked spend of %s/%s?", - eltoo_tx_type_name(out->tx_type), - output_type_name(out->output_type)); - } - return; - } - - struct bitcoin_txid txid; - wally_tx_input_get_txid(tx_parts->inputs[input_num], &txid); - /* Not interesting to us, so unwatch the tx and all its outputs */ - status_debug("Notified about tx %s output %u spend, but we don't care", - type_to_string(tmpctx, struct bitcoin_txid, &txid), - tx_parts->inputs[input_num]->index); + /* Otherwise... */ + struct bitcoin_txid txid; + wally_tx_input_get_txid(tx_parts->inputs[input_num], &txid); + /* Not interesting to us, so unwatch the tx and all its outputs */ + status_debug("Notified about tx %s output %u spend, but we don't care", + type_to_string(tmpctx, struct bitcoin_txid, &txid), + tx_parts->inputs[input_num]->index); - unwatch_txid(&tx_parts->txid); + unwatch_txid(&tx_parts->txid); } -static void update_resolution_depth(struct tracked_output *out, u32 depth) +static void eltoo_update_resolution_depth(struct tracked_output *out, u32 depth) { bool reached_reasonable_depth; @@ -961,13 +984,14 @@ static void update_resolution_depth(struct tracked_output *out, u32 depth) * *resolved*: * - MUST *resolve* the output by spending it using their own `settlement_pubkey` to * any address deemed necessary. + * vvvvvvvvvvv * - once the resolving transaction has reached reasonable depth: * - MUST fail the corresponding incoming HTLC (if any). * - for any committed HTLC that has been trimmed: * - once the update transaction that spent the funding output has reached reasonable depth: * - MUST fail the corresponding incoming HTLC (if any). */ - if (out->resolved->tx_type == ELTOO_SWEEP && reached_reasonable_depth) { + if (out->resolved->tx_type == ELTOO_HTLC_TIMEOUT && reached_reasonable_depth) { u8 *msg; status_debug("%s/%s reached reasonable depth %u", eltoo_tx_type_name(out->tx_type), @@ -1004,19 +1028,28 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, if (bitcoin_txid_eq(&outs[i]->outpoint.txid, txid)) outs[i]->depth = depth; - /* Is this tx resolving an output? */ + /* Is this tx resolving an output? (Also, send + * off timed out notification once ELTOO_HTLC_TIMEOUT + * reaches reasonable depth) */ if (outs[i]->resolved) { if (bitcoin_txid_eq(&outs[i]->resolved->txid, txid)) { - update_resolution_depth(outs[i], depth); + eltoo_update_resolution_depth(outs[i], depth); } continue; } /* Otherwise, is this something we have a pending - * resolution for? */ + * proposal resolution for? */ if (outs[i]->proposal && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) && depth >= outs[i]->proposal->depth_required) { + /* Just-in-time creation of HTLC_TIMEOUT tx before gets broadcasted */ + if (outs[i]->proposal->tx_type == ELTOO_HTLC_TIMEOUT) { + // !!! FIXME Need to trigger this at right time with right args + // resolve_htlc_timeouts(out, htlcs_info->htlcs[matches[0]], htlc_success_scripts[matches[0]], htlc_timeout_scripts[matches[0]]); + // propose_htlc_timeout_tx(); <--- more like this + abort(); + } eltoo_proposal_meets_depth(outs[i]); } @@ -1026,6 +1059,7 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) && eltoo_proposal_is_rbfable(outs[i]->proposal)) eltoo_proposal_should_rbf(outs[i]); + } } @@ -1065,7 +1099,9 @@ static void eltoo_handle_preimage(struct tracked_output **outs, * could be due to multiple identical rhashes in tx. */ outs[i]->proposal = tal_free(outs[i]->proposal); - /* FIXME now that we know this output exists, we should resolve it */ + /* FIXME now that we know this output exists, we should propose to resolve it */ + // propose_htlc_success_tx(); + // propose_resolution(outs[i], sweep_tx, 0 /* depth_required */, ELTOO_HTLC_SUCCESS); } } @@ -1172,8 +1208,6 @@ static void wait_for_resolved(struct tracked_output **outs, struct htlcs_info *h &tx_blockheight)) { output_spent(&outs, tx_parts, input_num, tx_blockheight, locktime, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) - /* We could be watching our settlement outputs - even if they haven't entered utxo set to use for CPFP. */ eltoo_handle_preimage(outs, &preimage); else if (!handle_dev_memleak(outs, msg)) master_badmsg(-1, msg); @@ -1433,6 +1467,8 @@ int main(int argc, char *argv[]) master_badmsg(WIRE_ELTOO_ONCHAIND_INIT, msg); } + update_phase = true; + // It's not configurable for ln-penalty, just set it here? reasonable_depth = 3; diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index 8594193161ea..1ab790fe8af6 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -74,8 +74,9 @@ enum eltoo_tx_type { */ ELTOO_INVALIDATED_SETTLE, - /* Sweep of outputs from settlement tx */ - ELTOO_SWEEP, + /* Sweep of outputs from settlement tx to outselves */ + ELTOO_HTLC_TIMEOUT, + ELTOO_HTLC_SUCCESS, /* FIXME should I have more types? */ diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index ce6d6832dc22..9f785d3e772c 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -177,5 +177,3 @@ msgdata,eltoo_onchaind_new_state_output,new_prevout,bitcoin_outpoint, msgdata,eltoo_onchaind_new_state_output,invalidated_update_num,u32, msgdata,eltoo_onchaind_new_state_output,annex_hint_len,u16, msgdata,eltoo_onchaind_new_state_output,invalidated_annex_hint,u8,annex_hint_len - - From 130e4f0cf54fcefd5073745a668146dfdba733cd Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 5 Dec 2022 16:36:04 -0500 Subject: [PATCH 231/283] Add htlc feerate to eltoo_onchaind --- lightningd/onchain_control.c | 10 ++++++++++ onchaind/eltoo_onchaind.c | 4 ++++ onchaind/onchaind_wire.csv | 1 + 3 files changed, 15 insertions(+) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 183684fd8bc6..76370db7033a 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -922,6 +922,7 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, struct lightningd *ld = channel->peer->ld; int hsmfd; enum state_change reason; + u32 htlc_feerate; /* use REASON_ONCHAIN or closer's reason, if known */ reason = REASON_ONCHAIN; @@ -962,6 +963,14 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, return KEEP_WATCHING; } + htlc_feerate = htlc_resolution_feerate(ld->topology); + /* Unlike classic LN, we don't have any transactions sitting around to harvest feerates from */ + if (htlc_feerate == 0) { + log_unusual(ld->log, "Could not retrieve valid htlc resolution feerate for eltoo_onchaind. Continuing."); + /* FIXME we should guess better, at least take mempool min fee into account? Or figure out better fix */ + htlc_feerate = 250*5; /* default mempool min times 5 */ + } + /* Add HTLCs to init, since we know which HTLCs will be exposed */ msg = towire_eltoo_onchaind_init(channel, chainparams, @@ -975,6 +984,7 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, channel->eltoo_keyset.committed_settle_tx, blockheight, channel->our_msat, + htlc_feerate, channel->shutdown_scriptpubkey[LOCAL], channel->shutdown_scriptpubkey[REMOTE], &channel->local_funding_pubkey, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 25b949c77a46..04b76d867eed 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -52,6 +52,9 @@ static struct bitcoin_tx *committed_update_tx, *committed_settle_tx; /* Required in various places: keys for commitment transaction. */ static struct eltoo_keyset *keyset; +/* The feerate for transactions spending HTLC outputs. */ +static u32 htlc_feerate; + /* When to tell master about HTLCs which are missing/timed out */ static u32 reasonable_depth; @@ -1455,6 +1458,7 @@ int main(int argc, char *argv[]) &committed_settle_tx, &tx_blockheight, &our_msat, + &htlc_feerate, &scriptpubkey[LOCAL], &scriptpubkey[REMOTE], &keyset->self_funding_key, diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 9f785d3e772c..0c2a1256dbf3 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -154,6 +154,7 @@ msgdata,eltoo_onchaind_init,committed_update_tx,?bitcoin_tx, msgdata,eltoo_onchaind_init,committed_settle_tx,?bitcoin_tx, msgdata,eltoo_onchaind_init,tx_blockheight,u32, msgdata,eltoo_onchaind_init,our_msat,amount_msat, +msgdata,eltoo_onchaind_init,htlc_feerate,u32, msgdata,eltoo_onchaind_init,local_scriptpubkey_len,u16, msgdata,eltoo_onchaind_init,local_scriptpubkey,u8,local_scriptpubkey_len msgdata,eltoo_onchaind_init,remote_scriptpubkey_len,u16, From cb34f3f6b6ac4a5d8ad08cb4378e3ef4f873658c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 7 Dec 2022 17:15:19 -0500 Subject: [PATCH 232/283] HTLC timeout resolution implemented except for final witness construction --- hsmd/hsmd.c | 2 + hsmd/hsmd_wire.csv | 11 +++ hsmd/libhsmd.c | 50 +++++++++++- lightningd/onchain_control.c | 1 + onchaind/eltoo_onchaind.c | 144 ++++++++++++++++++++++++++++++++--- onchaind/onchaind_wire.csv | 1 + 6 files changed, 196 insertions(+), 13 deletions(-) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 4f4de6116eae..e9166826bbac 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -673,6 +673,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: case WIRE_HSMD_GEN_NONCE: case WIRE_HSMD_MIGRATE_NONCE: + case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, @@ -708,6 +709,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: case WIRE_HSMD_MIGRATE_NONCE_REPLY: + case WIRE_HSMD_SIGN_ELTOO_TX_REPLY: return bad_req_fmt(conn, c, c->msg_in, "Received an incoming message of type %s, " "which is not a request", diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 9d9d6da0ebe3..ceb6fa620172 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -360,3 +360,14 @@ msgdata,hsmd_migrate_nonce,temp_id,channel_id, msgdata,hsmd_migrate_nonce,final_id,channel_id, msgtype,hsmd_migrate_nonce_reply,197 + + +# Non-MuSig signature stuff for eltoo +msgtype,hsmd_sign_eltoo_htlc_timeout_tx,113 +msgdata,hsmd_sign_eltoo_htlc_timeout_tx,tx,bitcoin_tx, +msgdata,hsmd_sign_eltoo_htlc_timeout_tx,tapscript_len,u16, +msgdata,hsmd_sign_eltoo_htlc_timeout_tx,tapscript,u8,tapscript_len + +# Reply for all the above requests. +msgtype,hsmd_sign_eltoo_tx_reply,212 +msgdata,hsmd_sign_eltoo_tx_reply,sig,bip340sig, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 09337130cedd..f1277040b8e9 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -139,6 +139,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_READY_ELTOO_CHANNEL: + case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: /* FIXME unused for now ... */ return (client->capabilities & HSM_CAP_SIGN_REMOTE_TX) != 0; @@ -193,6 +194,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: case WIRE_HSMD_MIGRATE_NONCE_REPLY: + case WIRE_HSMD_SIGN_ELTOO_TX_REPLY: break; } return false; @@ -1540,7 +1542,10 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) pubkey_ptrs, /* n_pubkeys */ 2); - bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, /* non-NULL script signals bip342... */ annex, annex, &hash_out); + /* Update transactions do not require commitment to the tapleaf hash via APOAS, hence sending in annex here + * just to signal bip342 path evaluation */ + bitcoin_tx_taproot_hash_for_sig(update_tx, /* input_index */ 0, SIGHASH_ANYPREVOUTANYSCRIPT|SIGHASH_SINGLE, + annex /* tapleaf_script */, annex, &hash_out); printf("sign taproot Sighash: "); for (i = 0; i < 32; i++) { @@ -1703,6 +1708,46 @@ static u8 *handle_validate_revocation(struct hsmd_client *c, const u8 *msg_in) return towire_hsmd_validate_revocation_reply(NULL); } +static u8 *handle_sign_eltoo_htlc_timeout_tx(struct hsmd_client *c, + const u8 *msg_in) +{ + /* Key derivation boilerplate */ + struct secret channel_seed; + struct secrets secrets; + + struct bitcoin_tx *htlc_tx; + struct bip340sig sig; + u8 *tapleaf_script; + secp256k1_keypair key_pair; + int ret; + + if (!fromwire_hsmd_sign_eltoo_htlc_timeout_tx(tmpctx, msg_in, + &htlc_tx, + &tapleaf_script)) { + return hsmd_status_malformed_request(c, msg_in); + } + + get_channel_seed(&c->id, c->dbid, &channel_seed); + derive_basepoints(&channel_seed, + NULL, NULL, &secrets, NULL); + + /* FIXME still need to switch over to htlc key in spec and impl */ + ret = secp256k1_keypair_create(secp256k1_ctx, &key_pair, secrets.payment_basepoint_secret.data); + if (ret) { + return hsmd_status_bad_request(c, msg_in, + "Failed to generate htlc pubkey pair"); + } + + sign_tx_taproot_input(htlc_tx, + 0 /* input_index */, + SIGHASH_ALL, + tapleaf_script, + &key_pair, + &sig); + + return towire_hsmd_sign_eltoo_tx_reply(NULL, &sig); +} + /*~ This is used when a commitment transaction is onchain, and has an HTLC * output paying to us (because we have the preimage); this signs that * transaction, which lightningd will broadcast to collect the funds. */ @@ -1903,6 +1948,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, return handle_gen_nonce(client, msg); case WIRE_HSMD_MIGRATE_NONCE: return handle_migrate_nonce(client, msg); + case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: + return handle_sign_eltoo_htlc_timeout_tx(client, msg); /* Eltoo stuff ends */ case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: @@ -1934,6 +1981,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: case WIRE_HSMD_MIGRATE_NONCE_REPLY: + case WIRE_HSMD_SIGN_ELTOO_TX_REPLY: break; } return hsmd_status_bad_request(client, msg, "Unknown request"); diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 76370db7033a..873bd0d6d06d 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -985,6 +985,7 @@ enum watch_result eltoo_onchaind_funding_spent(struct channel *channel, blockheight, channel->our_msat, htlc_feerate, + channel->our_config.dust_limit, channel->shutdown_scriptpubkey[LOCAL], channel->shutdown_scriptpubkey[REMOTE], &channel->local_funding_pubkey, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 04b76d867eed..232b63a9dd25 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -55,6 +55,9 @@ static struct eltoo_keyset *keyset; /* The feerate for transactions spending HTLC outputs. */ static u32 htlc_feerate; +/* The dust limit to use when we generate transactions. */ +static struct amount_sat dust_limit; + /* When to tell master about HTLCs which are missing/timed out */ static u32 reasonable_depth; @@ -96,6 +99,7 @@ struct tracked_output { /* If it is an HTLC, this is set, tapscripts are non-NULL. */ struct htlc_stub htlc; + int parity_bit; /* Used to finish control block for tapscript spend of output */ const u8 *htlc_success_tapscript; /* EXPR_SUCCESS */ const u8 *htlc_timeout_tapscript; /* EXPR_TIMEOUT */ @@ -129,6 +133,14 @@ static const char *output_type_name(enum output_type output_type) return "unknown"; } +static u8 *htlc_timeout_to_us(const tal_t *ctx, + struct bitcoin_tx *tx, + const u8 *tapscript) +{ + return towire_hsmd_sign_eltoo_htlc_timeout_tx(ctx, + tx, tapscript); +} + static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) { wire_sync_write(REQ_FD, @@ -138,6 +150,103 @@ static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) tal_free(mvt); } +/* Currently only used for HTLC resolutions */ +static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, + u8 *(*hsm_sign_msg)(const tal_t *ctx, + struct bitcoin_tx *tx, + const u8 *tapscript), + struct tracked_output *out, + u32 locktime, + const u8 *tapscript, + const u8 *control_block, + enum eltoo_tx_type *tx_type, + u32 feerate) +{ + struct bitcoin_tx *tx; + size_t max_weight; + struct amount_sat fee, min_out, amt; + u8 *msg; + struct bip340sig sig; + + tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); + bitcoin_tx_add_input(tx, &out->outpoint, 0 /* sequence */, + NULL /* scriptSig */, out->sat, NULL /* scriptPubkey */, + NULL /* input_wscript */, NULL /* inner_pubkey */, NULL /* tap_tree */); + + /* FIXME figure out taproot output support to go directly into wallet aka "our_wallet_pubkey" */ + bitcoin_tx_add_output( + tx, scriptpubkey_p2wpkh(tmpctx, &keyset->self_settle_key), NULL, out->sat); + + /* BIP340 sigs are constant sized, 65 bytes for non-default, and we expose + a control block sized 33 + 32 for internal public key and tapleaf hash */ + max_weight = bitcoin_tx_weight(tx) + + 1 + /* Witness stack size */ + 1 + /* control block size */ + tal_count(control_block) + + 1 + /* tapscript size*/ + tal_count(tapscript) + + 1 + /* signature size */ + 65 /* BIP340 sig with non-default sighash flag */; + + /* FIXME elements support */ + max_weight += 0; + + fee = amount_tx_fee(feerate, max_weight); + + /* Result is trivial? Spend with small feerate, but don't wait + * around for it as it might not confirm. */ + if (!amount_sat_add(&min_out, dust_limit, fee)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Cannot add dust_limit %s and fee %s", + type_to_string(tmpctx, struct amount_sat, &dust_limit), + type_to_string(tmpctx, struct amount_sat, &fee)); + } + + if (amount_sat_less(out->sat, min_out)) { + /* FIXME: We should use SIGHASH_NONE so others can take it */ + fee = amount_tx_fee(feerate_floor(), max_weight); + status_unusual("TX %s amount %s too small to" + " pay reasonable fee, using minimal fee" + " and ignoring", + eltoo_tx_type_name(*tx_type), + type_to_string(tmpctx, struct amount_sat, &out->sat)); + *tx_type = IGNORING_TINY_PAYMENT; + } + + /* This can only happen if feerate_floor() is still too high; shouldn't + * happen! */ + if (!amount_sat_sub(&amt, out->sat, fee)) { + amt = dust_limit; + status_broken("TX %s can't afford minimal feerate" + "; setting output to %s", + eltoo_tx_type_name(*tx_type), + type_to_string(tmpctx, struct amount_sat, + &amt)); + } + bitcoin_tx_output_set_amount(tx, 0, amt); + bitcoin_tx_finalize(tx); + + + if (!wire_sync_write(HSM_FD, take(hsm_sign_msg(NULL, tx, tapscript)))) + status_failed(STATUS_FAIL_HSM_IO, "Writing sign request to hsm"); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!msg || !fromwire_hsmd_sign_eltoo_tx_reply(msg, &sig)) { + status_failed(STATUS_FAIL_HSM_IO, + "Reading sign_tx_reply: %s", + tal_hex(tmpctx, msg)); + } + + /* FIXME now that sig is coming back, get witness together for tapscript spend + witness = bitcoin_witness_sig_and_element(tx, &sig, elem, + elemsize, wscript); + */ + + /* + bitcoin_tx_input_set_witness(tx, 0, take(witness)); + */ + return tx; +} + static u8 **derive_htlc_success_scripts(const tal_t *ctx, const struct htlc_stub *htlcs, const struct pubkey *our_htlc_pubkey, const struct pubkey *their_htlc_pubkey) { size_t i; @@ -186,14 +295,13 @@ static enum side matches_direction(const size_t *matches, return htlcs[matches[0]].owner; } -/* Return tal_arr of htlc indexes. */ +/* Return tal_arr of htlc indexes. Should be length 0 or 1 since CLTV is in script. */ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, const struct wally_tx_output *out, u8 **htlc_success_scripts, - u8 **htlc_timeout_scripts) + u8 **htlc_timeout_scripts, + int *parity_bit) { -// wtf? assert(tal_count(htlc_success_scripts) == tal_count(htlc_timeout_scripts)); - size_t *matches = tal_arr(ctx, size_t, 0); const u8 *script = tal_dup_arr(tmpctx, u8, out->script, out->script_len, 0); @@ -223,8 +331,10 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, &tap_merkle_root, tap_tweak_out); taproot_script = scriptpubkey_p2tr(ctx, &taproot_pubkey); - if (memeq(taproot_script, tal_count(taproot_script), script, sizeof(script))) + if (memeq(taproot_script, tal_count(taproot_script), script, sizeof(script))) { tal_arr_expand(&matches, i); + *parity_bit = pubkey_parity(&taproot_pubkey); + } } return matches; } @@ -743,12 +853,13 @@ static void track_settle_outputs(struct tracked_output ***outs, struct wally_tx_output *settle_out = tx_parts->outputs[j]; struct tracked_output *out; struct amount_sat satoshis = amount_sat(settle_out->satoshi); + int parity_bit; /* (1) Ephemeral Anchor */ if (is_ephemeral_anchor(settle_out->script)) { /* Anchor is lightningd's problem */ continue; } - const size_t *matches = eltoo_match_htlc_output(tmpctx, settle_out, htlc_success_scripts, htlc_timeout_scripts); + const size_t *matches = eltoo_match_htlc_output(tmpctx, settle_out, htlc_success_scripts, htlc_timeout_scripts, &parity_bit); struct bitcoin_outpoint outpoint; outpoint.txid = tx_parts->txid; outpoint.n = j; @@ -806,6 +917,7 @@ static void track_settle_outputs(struct tracked_output ***outs, &htlcs_info->htlcs[matches[0]] /* htlc */, htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); + out->parity_bit = parity_bit; /* FIXME Proposal comes in at handle_preimage? */ } else { /* (5) HTLC to them */ @@ -818,7 +930,7 @@ static void track_settle_outputs(struct tracked_output ***outs, &htlcs_info->htlcs[matches[0]] /* htlc */, htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); - + out->parity_bit = parity_bit; /* We'd like to propose a reasonable feerate tx at the time needed, not before */ propose_htlc_resolution_at_block(out, htlcs_info->htlcs[matches[0]].cltv_expiry, ELTOO_HTLC_TIMEOUT); } @@ -1048,10 +1160,17 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, && depth >= outs[i]->proposal->depth_required) { /* Just-in-time creation of HTLC_TIMEOUT tx before gets broadcasted */ if (outs[i]->proposal->tx_type == ELTOO_HTLC_TIMEOUT) { - // !!! FIXME Need to trigger this at right time with right args - // resolve_htlc_timeouts(out, htlcs_info->htlcs[matches[0]], htlc_success_scripts[matches[0]], htlc_timeout_scripts[matches[0]]); - // propose_htlc_timeout_tx(); <--- more like this - abort(); + if (outs[i]->proposal->tx) { + status_broken("Proposal tx already exists for HTLC timeout when it should be null"); + } + outs[i]->proposal->tx = bip340_tx_to_us(outs[i], + htlc_timeout_to_us, + outs[i], + outs[i]->htlc.cltv_expiry, + outs[i]->htlc_timeout_tapscript, + compute_control_block(outs[i], outs[i]->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, outs[i]->parity_bit), + &outs[i]->proposal->tx_type, /* over-written if too small to care */ + htlc_feerate); } eltoo_proposal_meets_depth(outs[i]); } @@ -1103,7 +1222,7 @@ static void eltoo_handle_preimage(struct tracked_output **outs, outs[i]->proposal = tal_free(outs[i]->proposal); /* FIXME now that we know this output exists, we should propose to resolve it */ - // propose_htlc_success_tx(); + // propose_htlc_success_tx(); tx_to_us // propose_resolution(outs[i], sweep_tx, 0 /* depth_required */, ELTOO_HTLC_SUCCESS); } } @@ -1459,6 +1578,7 @@ int main(int argc, char *argv[]) &tx_blockheight, &our_msat, &htlc_feerate, + &dust_limit, &scriptpubkey[LOCAL], &scriptpubkey[REMOTE], &keyset->self_funding_key, diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index 0c2a1256dbf3..b10fba95fed6 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -155,6 +155,7 @@ msgdata,eltoo_onchaind_init,committed_settle_tx,?bitcoin_tx, msgdata,eltoo_onchaind_init,tx_blockheight,u32, msgdata,eltoo_onchaind_init,our_msat,amount_msat, msgdata,eltoo_onchaind_init,htlc_feerate,u32, +msgdata,eltoo_onchaind_init,local_dust_limit_satoshi,amount_sat, msgdata,eltoo_onchaind_init,local_scriptpubkey_len,u16, msgdata,eltoo_onchaind_init,local_scriptpubkey,u8,local_scriptpubkey_len msgdata,eltoo_onchaind_init,remote_scriptpubkey_len,u16, From cd58de88b2ee0420c9ede56b56cd7ba3a1ef9d85 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 8 Dec 2022 12:03:54 -0500 Subject: [PATCH 233/283] Create witness construction for HTLC resolutions --- bitcoin/script.c | 51 +++++++++++++++++++++++++++++++++++++++ bitcoin/script.h | 8 ++++++ bitcoin/signature.h | 1 + onchaind/eltoo_onchaind.c | 23 ++++++++++++------ 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 9589269e2e55..973d4d21427e 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -128,6 +128,18 @@ static u8 *stack_sig(const tal_t *ctx, const struct bitcoin_signature *sig) return tal_dup_arr(ctx, u8, der, len, 0); } +static u8 *stack_bip340sig(const tal_t *ctx, const struct bip340sig *sig, enum sighash_type sh_type) +{ + if (sh_type != SIGHASH_DEFAULT) { + u8 sig_flag[65]; + memcpy(sig_flag, sig->u8, 64); + sig_flag[sizeof(sig_flag)-1] = sh_type; + return tal_dup_arr(ctx, u8, sig->u8, sizeof(sig_flag), 0); + } else { + return tal_dup_arr(ctx, u8, sig->u8, 64, 0); + } +} + static u8 *stack_preimage(const tal_t *ctx, const struct preimage *preimage) { return tal_dup_arr(ctx, u8, preimage->r, sizeof(preimage->r), 0); @@ -587,6 +599,45 @@ u8 **bitcoin_witness_sig_and_element(const tal_t *ctx, return witness; } +u8 **bitcoin_witness_bip340sig_and_element(const tal_t *ctx, + const struct bip340sig *sig, + const void *elem, size_t elemsize, + const u8 *tapscript, + const u8 *control_block) +{ + /* Itms ordered as a stack for readability */ + if (elem) { + /* + * + * The recipient node can redeem the HTLC with the witness: + * + * + * + */ + u8 **witness = tal_arr(ctx, u8 *, 4); + + witness[3] = tal_dup_talarr(witness, u8, control_block); + witness[2] = tal_dup_talarr(witness, u8, tapscript); + witness[1] = tal_dup_arr(witness, u8, elem, elemsize, 0); + witness[0] = stack_bip340sig(witness, sig, SIGHASH_DEFAULT); + + return witness; + } else { + /* + * And the offerer via: + * + * + */ + u8 **witness = tal_arr(ctx, u8 *, 3); + + witness[2] = tal_dup_talarr(witness, u8, control_block); + witness[1] = tal_dup_talarr(witness, u8, tapscript); + witness[0] = stack_bip340sig(witness, sig, SIGHASH_DEFAULT); + + return witness; + } +} + /* BOLT #3: * * This output sends funds back to the owner of this commitment transaction and diff --git a/bitcoin/script.h b/bitcoin/script.h index a3093ba0695e..67b890aace8d 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -92,6 +92,14 @@ u8 **bitcoin_witness_sig_and_element(const tal_t *ctx, const void *elem, size_t elemsize, const u8 *witnessscript); +/* Create a witness which contains a sig, and possibly another entry, tapscript + * and control block for BIP342 spends */ +u8 **bitcoin_witness_bip340sig_and_element(const tal_t *ctx, + const struct bip340sig *sig, + const void *elem, size_t elemsize, + const u8 *tapscript, + const u8 *control_block); + /* BOLT #3 to-local output */ u8 *bitcoin_wscript_to_local(const tal_t *ctx, u16 to_self_delay, u32 lease_remaining, diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 1f7eeb539030..04fc84a8feb1 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -17,6 +17,7 @@ struct privkey; struct bitcoin_tx_output; enum sighash_type { + SIGHASH_DEFAULT = 0, SIGHASH_ALL = 1, SIGHASH_NONE = 2, SIGHASH_SINGLE = 3, diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 232b63a9dd25..cb6f3d7310e0 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -167,6 +167,9 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, struct amount_sat fee, min_out, amt; u8 *msg; struct bip340sig sig; + u8 **witness; + /* Modifying later, we need this at the end for witness construction */ + enum eltoo_tx_type tx_type_copy = *tx_type; tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); bitcoin_tx_add_input(tx, &out->outpoint, 0 /* sequence */, @@ -236,14 +239,20 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, tal_hex(tmpctx, msg)); } - /* FIXME now that sig is coming back, get witness together for tapscript spend - witness = bitcoin_witness_sig_and_element(tx, &sig, elem, - elemsize, wscript); - */ + if (tx_type_copy == ELTOO_HTLC_TIMEOUT) { + witness = bitcoin_witness_bip340sig_and_element(tx, &sig, NULL /* elem */, + 0 /* elemsize */, tapscript, control_block); + } else if (tx_type_copy == ELTOO_HTLC_SUCCESS) { + witness = bitcoin_witness_bip340sig_and_element(tx, &sig, out->payment_hash.u.u8 /* elem */, + 32 /* elemsize */, tapscript, control_block); + + } else { + /* Should only be called for HTLC resolutions for now */ + abort(); + } + + bitcoin_tx_input_set_witness(tx, 0 /* innum */, take(witness)); - /* - bitcoin_tx_input_set_witness(tx, 0, take(witness)); - */ return tx; } From a19b427e3d1fb467a6a30b7b1919897bc4e592bc Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 8 Dec 2022 12:41:56 -0500 Subject: [PATCH 234/283] Implement HTLC success txns --- hsmd/hsmd.c | 1 + hsmd/hsmd_wire.csv | 5 +++++ hsmd/libhsmd.c | 7 +++++-- onchaind/eltoo_onchaind.c | 24 +++++++++++++++++++++--- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index e9166826bbac..0bcd06f84755 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -674,6 +674,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_GEN_NONCE: case WIRE_HSMD_MIGRATE_NONCE: case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: + case WIRE_HSMD_SIGN_ELTOO_HTLC_SUCCESS_TX: /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index ceb6fa620172..11bb4242ab7c 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -368,6 +368,11 @@ msgdata,hsmd_sign_eltoo_htlc_timeout_tx,tx,bitcoin_tx, msgdata,hsmd_sign_eltoo_htlc_timeout_tx,tapscript_len,u16, msgdata,hsmd_sign_eltoo_htlc_timeout_tx,tapscript,u8,tapscript_len +msgtype,hsmd_sign_eltoo_htlc_success_tx,114 +msgdata,hsmd_sign_eltoo_htlc_success_tx,tx,bitcoin_tx, +msgdata,hsmd_sign_eltoo_htlc_success_tx,tapscript_len,u16, +msgdata,hsmd_sign_eltoo_htlc_success_tx,tapscript,u8,tapscript_len + # Reply for all the above requests. msgtype,hsmd_sign_eltoo_tx_reply,212 msgdata,hsmd_sign_eltoo_tx_reply,sig,bip340sig, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index f1277040b8e9..69d451c990fc 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -140,6 +140,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_READY_ELTOO_CHANNEL: case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: + case WIRE_HSMD_SIGN_ELTOO_HTLC_SUCCESS_TX: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: /* FIXME unused for now ... */ return (client->capabilities & HSM_CAP_SIGN_REMOTE_TX) != 0; @@ -1708,7 +1709,8 @@ static u8 *handle_validate_revocation(struct hsmd_client *c, const u8 *msg_in) return towire_hsmd_validate_revocation_reply(NULL); } -static u8 *handle_sign_eltoo_htlc_timeout_tx(struct hsmd_client *c, +/* FIXME: do more introspection*/ +static u8 *handle_sign_eltoo_htlc_tx(struct hsmd_client *c, const u8 *msg_in) { /* Key derivation boilerplate */ @@ -1949,7 +1951,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_MIGRATE_NONCE: return handle_migrate_nonce(client, msg); case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: - return handle_sign_eltoo_htlc_timeout_tx(client, msg); + case WIRE_HSMD_SIGN_ELTOO_HTLC_SUCCESS_TX: + return handle_sign_eltoo_htlc_tx(client, msg); /* Eltoo stuff ends */ case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index cb6f3d7310e0..29d3471c8b1a 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -141,6 +141,14 @@ static u8 *htlc_timeout_to_us(const tal_t *ctx, tx, tapscript); } +static u8 *htlc_success_to_us(const tal_t *ctx, + struct bitcoin_tx *tx, + const u8 *tapscript) +{ + return towire_hsmd_sign_eltoo_htlc_success_tx(ctx, + tx, tapscript); +} + static void send_coin_mvt(struct chain_coin_mvt *mvt TAKES) { wire_sync_write(REQ_FD, @@ -1209,6 +1217,9 @@ static void eltoo_handle_preimage(struct tracked_output **outs, ripemd160(&ripemd, &sha, sizeof(sha)); for (i = 0; i < tal_count(outs); i++) { + struct bitcoin_tx *tx; + enum eltoo_tx_type tx_type = ELTOO_HTLC_SUCCESS; + if (outs[i]->output_type != THEIR_HTLC) continue; @@ -1230,9 +1241,16 @@ static void eltoo_handle_preimage(struct tracked_output **outs, * could be due to multiple identical rhashes in tx. */ outs[i]->proposal = tal_free(outs[i]->proposal); - /* FIXME now that we know this output exists, we should propose to resolve it */ - // propose_htlc_success_tx(); tx_to_us - // propose_resolution(outs[i], sweep_tx, 0 /* depth_required */, ELTOO_HTLC_SUCCESS); + tx = bip340_tx_to_us(outs[i], + htlc_success_to_us, + outs[i], + 0 /* locktime */, + outs[i]->htlc_success_tapscript, + compute_control_block(outs[i], outs[i]->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, outs[i]->parity_bit), + &tx_type, /* over-written if too small to care */ + htlc_feerate); + + propose_resolution(outs[i], tx, 0 /* depth_required */, tx_type); } } From 8e5be4a2d1831f71149cb71636cd9bb5147e7a80 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 8 Dec 2022 13:13:30 -0500 Subject: [PATCH 235/283] Cache preimages prior to settle phase --- onchaind/eltoo_onchaind.c | 131 +++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 52 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 29d3471c8b1a..3fc9083727f7 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -43,6 +43,9 @@ static bool bipmusig_partial_sigs_combine_state(const struct eltoo_sign *state, /* Used as one-way latch to detect when the state ordering is being settled */ static bool update_phase; +/* During update_phase we queue all payment preimage notifications */ +static struct preimage **cached_preimages; + /* Full tx we have partial signatures for */ static struct bitcoin_tx *complete_update_tx, *complete_settle_tx; @@ -957,6 +960,67 @@ static void track_settle_outputs(struct tracked_output ***outs, } } +/* BOLT #XX: + * FIXME add BOLT text + */ +/* Master makes sure we only get told preimages once other node is committed. */ +static void eltoo_handle_preimage(struct tracked_output **outs, + const struct preimage *preimage) +{ + size_t i; + struct sha256 sha; + struct ripemd160 ripemd; + + sha256(&sha, preimage, sizeof(*preimage)); + ripemd160(&ripemd, &sha, sizeof(sha)); + + for (i = 0; i < tal_count(outs); i++) { + struct bitcoin_tx *tx; + enum eltoo_tx_type tx_type = ELTOO_HTLC_SUCCESS; + + if (outs[i]->output_type != THEIR_HTLC) + continue; + + if (!ripemd160_eq(&outs[i]->htlc.ripemd, &ripemd)) + continue; + + /* Too late? */ + if (outs[i]->resolved) { + status_broken("HTLC already resolved by %s" + " when we found preimage", + eltoo_tx_type_name(outs[i]->resolved->tx_type)); + return; + } + + /* stash the payment_hash so we can track this coin movement */ + outs[i]->payment_hash = sha; + + /* Discard any previous resolution. Could be a timeout, + * could be due to multiple identical rhashes in tx. */ + outs[i]->proposal = tal_free(outs[i]->proposal); + + tx = bip340_tx_to_us(outs[i], + htlc_success_to_us, + outs[i], + 0 /* locktime */, + outs[i]->htlc_success_tapscript, + compute_control_block(outs[i], outs[i]->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, outs[i]->parity_bit), + &tx_type, /* over-written if too small to care */ + htlc_feerate); + + propose_resolution(outs[i], tx, 0 /* depth_required */, tx_type); + } +} + +static void eltoo_handle_cached_preimages(struct tracked_output **outs, + struct preimage **cached_preimages) +{ + for (int j=0; jlocktime && update_phase) { /* (2) Update transaction*/ @@ -1202,57 +1270,6 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, } } -/* BOLT #XX: - * FIXME add BOLT text - */ -/* Master makes sure we only get told preimages once other node is committed. */ -static void eltoo_handle_preimage(struct tracked_output **outs, - const struct preimage *preimage) -{ - size_t i; - struct sha256 sha; - struct ripemd160 ripemd; - - sha256(&sha, preimage, sizeof(*preimage)); - ripemd160(&ripemd, &sha, sizeof(sha)); - - for (i = 0; i < tal_count(outs); i++) { - struct bitcoin_tx *tx; - enum eltoo_tx_type tx_type = ELTOO_HTLC_SUCCESS; - - if (outs[i]->output_type != THEIR_HTLC) - continue; - - if (!ripemd160_eq(&outs[i]->htlc.ripemd, &ripemd)) - continue; - - /* Too late? */ - if (outs[i]->resolved) { - status_broken("HTLC already resolved by %s" - " when we found preimage", - eltoo_tx_type_name(outs[i]->resolved->tx_type)); - return; - } - - /* stash the payment_hash so we can track this coin movement */ - outs[i]->payment_hash = sha; - - /* Discard any previous resolution. Could be a timeout, - * could be due to multiple identical rhashes in tx. */ - outs[i]->proposal = tal_free(outs[i]->proposal); - - tx = bip340_tx_to_us(outs[i], - htlc_success_to_us, - outs[i], - 0 /* locktime */, - outs[i]->htlc_success_tapscript, - compute_control_block(outs[i], outs[i]->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, outs[i]->parity_bit), - &tx_type, /* over-written if too small to care */ - htlc_feerate); - - propose_resolution(outs[i], tx, 0 /* depth_required */, tx_type); - } -} #if DEVELOPER static void memleak_remove_globals(struct htable *memtable, const tal_t *topctx) @@ -1357,7 +1374,12 @@ static void wait_for_resolved(struct tracked_output **outs, struct htlcs_info *h &tx_blockheight)) { output_spent(&outs, tx_parts, input_num, tx_blockheight, locktime, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); } else if (fromwire_onchaind_known_preimage(msg, &preimage)) - eltoo_handle_preimage(outs, &preimage); + /* We don't know the final set of settlement utxos yet */ + if (update_phase) { + tal_arr_expand(cached_preimages, preimage); + } else { + eltoo_handle_preimage(outs, &preimage); + } else if (!handle_dev_memleak(outs, msg)) master_badmsg(-1, msg); @@ -1588,6 +1610,11 @@ int main(int argc, char *argv[]) missing_htlc_msgs = tal_arr(ctx, u8 *, 0); queued_msgs = tal_arr(ctx, u8 *, 0); + /* Since eltoo is not "one shot", we have to wait to process + * preimage notifications until settlement tx is mined or + * we switch how we track settlement outputs prior to mining. + */ + cached_preimages = tal_arr(ctx, struct preimage *, 0); msg = wire_sync_read(tmpctx, REQ_FD); if (!fromwire_eltoo_onchaind_init(tmpctx, From 70b8059c41935c1e28e5127147d08a9b2b44df0a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 12 Dec 2022 14:00:58 -0500 Subject: [PATCH 236/283] Add schema changes for eltoo json --- doc/schemas/listpeers.schema.json | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/doc/schemas/listpeers.schema.json b/doc/schemas/listpeers.schema.json index d35091182c1c..405bb18181c1 100644 --- a/doc/schemas/listpeers.schema.json +++ b/doc/schemas/listpeers.schema.json @@ -738,6 +738,26 @@ } ] } + }, + "last_update_tx": { + "type": "string", + "description": "latest signed and finalized update transaction bound to latest state output" + }, + "last_settle_tx": { + "type": "string", + "description": "latest signed and finalized settle transaction bound to last_update_tx state outpoint" + }, + "unbound_update_tx": { + "type": "string", + "description": "latest unfinalized update transaction" + }, + "unbound_settle_tx": { + "type": "string", + "description": "latest unfinalized settle transaction" + }, + "last_committed_settle_tx": { + "type": "string", + "description": "latest finalized settle transaction bound to a committed-but-not-complete update transaction" } }, "allOf": [ @@ -813,6 +833,11 @@ "out_fulfilled_msat": {}, "out_msatoshi_fulfilled": {}, "htlcs": {}, + "last_update_tx": {}, + "last_settle_tx": {}, + "unbound_update_tx": {}, + "unbound_settle_tx": {}, + "last_committed_settle_tx": {}, "initial_feerate": {}, "last_feerate": {}, "next_feerate": {}, @@ -902,6 +927,11 @@ "out_fulfilled_msat": {}, "out_msatoshi_fulfilled": {}, "htlcs": {}, + "last_update_tx": {}, + "last_settle_tx": {}, + "unbound_update_tx": {}, + "unbound_settle_tx": {}, + "last_committed_settle_tx": {}, "initial_feerate": {}, "last_feerate": {}, "next_feerate": {}, @@ -992,6 +1022,11 @@ "out_fulfilled_msat": {}, "out_msatoshi_fulfilled": {}, "htlcs": {}, + "last_update_tx": {}, + "last_settle_tx": {}, + "unbound_update_tx": {}, + "unbound_settle_tx": {}, + "last_committed_settle_tx": {}, "initial_feerate": {}, "last_feerate": {}, "next_feerate": {}, @@ -1081,6 +1116,11 @@ "out_fulfilled_msat": {}, "out_msatoshi_fulfilled": {}, "htlcs": {}, + "last_update_tx": {}, + "last_settle_tx": {}, + "unbound_update_tx": {}, + "unbound_settle_tx": {}, + "last_committed_settle_tx": {}, "inflight": {}, "last_tx_fee": {}, "close_to_addr": {}, From 54ffcaedb49c2c54c64e32a73cdf992e28abbbba Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 12 Dec 2022 16:49:28 -0500 Subject: [PATCH 237/283] Start some proper testing of HTLC resolution --- .msggen.json | 7 +- cln-grpc/proto/node.proto | 5 + cln-grpc/src/convert.rs | 5 + cln-rpc/src/model.rs | 10 ++ contrib/pyln-testing/pyln/testing/utils.py | 2 +- doc/HACKING.md | 3 + doc/lightning-listpeers.7.md | 7 +- lightningd/peer_control.c | 2 +- tests/test_closing.py | 166 +++++++++++++++++++++ 9 files changed, 203 insertions(+), 4 deletions(-) diff --git a/.msggen.json b/.msggen.json index 48a398f0dbb2..6c2ccca5c583 100644 --- a/.msggen.json +++ b/.msggen.json @@ -684,7 +684,10 @@ "ListPeers.peers[].channels[].in_payments_offered": 38, "ListPeers.peers[].channels[].inflight[]": 13, "ListPeers.peers[].channels[].initial_feerate": 9, + "ListPeers.peers[].channels[].last_committed_settle_tx": 54, "ListPeers.peers[].channels[].last_feerate": 10, + "ListPeers.peers[].channels[].last_settle_tx": 51, + "ListPeers.peers[].channels[].last_update_tx": 50, "ListPeers.peers[].channels[].max_accepted_htlcs": 35, "ListPeers.peers[].channels[].max_to_us_msat": 22, "ListPeers.peers[].channels[].max_total_htlc_in_msat": 27, @@ -713,7 +716,9 @@ "ListPeers.peers[].channels[].their_reserve_msat": 28, "ListPeers.peers[].channels[].their_to_self_delay": 33, "ListPeers.peers[].channels[].to_us_msat": 20, - "ListPeers.peers[].channels[].total_msat": 23 + "ListPeers.peers[].channels[].total_msat": 23, + "ListPeers.peers[].channels[].unbound_settle_tx": 53, + "ListPeers.peers[].channels[].unbound_update_tx": 52 }, "ListpeersPeersChannelsFeerate": { "ListPeers.peers[].channels[].feerate.perkb": 2, diff --git a/cln-grpc/proto/node.proto b/cln-grpc/proto/node.proto index 9ac4dddab75f..286e10d3399a 100644 --- a/cln-grpc/proto/node.proto +++ b/cln-grpc/proto/node.proto @@ -210,6 +210,11 @@ message ListpeersPeersChannels { optional uint64 out_payments_fulfilled = 44; optional Amount out_fulfilled_msat = 45; repeated ListpeersPeersChannelsHtlcs htlcs = 46; + optional string last_update_tx = 50; + optional string last_settle_tx = 51; + optional string unbound_update_tx = 52; + optional string unbound_settle_tx = 53; + optional string last_committed_settle_tx = 54; optional string close_to_addr = 47; } diff --git a/cln-grpc/src/convert.rs b/cln-grpc/src/convert.rs index d1ae7f309843..6921cad2420d 100644 --- a/cln-grpc/src/convert.rs +++ b/cln-grpc/src/convert.rs @@ -148,6 +148,11 @@ impl From<&responses::ListpeersPeersChannels> for pb::ListpeersPeersChannels { out_payments_fulfilled: c.out_payments_fulfilled.clone(), // Rule #2 for type u64? out_fulfilled_msat: c.out_fulfilled_msat.map(|f| f.into()), // Rule #2 for type msat? htlcs: c.htlcs.as_ref().map(|arr| arr.iter().map(|i| i.into()).collect()).unwrap_or(vec![]), // Rule #3 + last_update_tx: c.last_update_tx.clone(), // Rule #2 for type string? + last_settle_tx: c.last_settle_tx.clone(), // Rule #2 for type string? + unbound_update_tx: c.unbound_update_tx.clone(), // Rule #2 for type string? + unbound_settle_tx: c.unbound_settle_tx.clone(), // Rule #2 for type string? + last_committed_settle_tx: c.last_committed_settle_tx.clone(), // Rule #2 for type string? close_to_addr: c.close_to_addr.clone(), // Rule #2 for type string? } } diff --git a/cln-rpc/src/model.rs b/cln-rpc/src/model.rs index d5286569aa1c..7feb14cec42b 100644 --- a/cln-rpc/src/model.rs +++ b/cln-rpc/src/model.rs @@ -1220,6 +1220,16 @@ pub mod responses { pub out_fulfilled_msat: Option, #[serde(alias = "htlcs", skip_serializing_if = "Option::is_none")] pub htlcs: Option>, + #[serde(alias = "last_update_tx", skip_serializing_if = "Option::is_none")] + pub last_update_tx: Option, + #[serde(alias = "last_settle_tx", skip_serializing_if = "Option::is_none")] + pub last_settle_tx: Option, + #[serde(alias = "unbound_update_tx", skip_serializing_if = "Option::is_none")] + pub unbound_update_tx: Option, + #[serde(alias = "unbound_settle_tx", skip_serializing_if = "Option::is_none")] + pub unbound_settle_tx: Option, + #[serde(alias = "last_committed_settle_tx", skip_serializing_if = "Option::is_none")] + pub last_committed_settle_tx: Option, #[serde(alias = "close_to_addr", skip_serializing_if = "Option::is_none")] pub close_to_addr: Option, } diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 90ec96a10ed2..d710dd48b5c1 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -378,7 +378,7 @@ def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None): os.makedirs(regtestdir) self.cmd_line = [ - 'bitcoind', + os.environ.get('BITCOIND_TEST_PATH', 'bitcoind'), '-datadir={}'.format(bitcoin_dir), '-printtoconsole', '-server', diff --git a/doc/HACKING.md b/doc/HACKING.md index 82f6813377ac..17242945bd72 100644 --- a/doc/HACKING.md +++ b/doc/HACKING.md @@ -220,6 +220,9 @@ There are four kinds of tests: `DEBUG_SUBD=` and `TIMEOUT=` can be useful for debugging subdaemons on individual tests. + You need `bitcoind` installed in your path, or must supply one as an environmental variable: + `BITCOIND_TEST_PATH=` + * **pylightning tests** - will check contrib pylightning for codestyle and run the tests in `contrib/pylightning/tests` afterwards: diff --git a/doc/lightning-listpeers.7.md b/doc/lightning-listpeers.7.md index 849b808c1814..2388197cbcbf 100644 --- a/doc/lightning-listpeers.7.md +++ b/doc/lightning-listpeers.7.md @@ -122,6 +122,11 @@ On success, an object containing **peers** is returned. It is an array of objec If **direction** is "in": - **state** (string): Status of the HTLC (one of "RCVD_ADD_HTLC", "RCVD_ADD_COMMIT", "SENT_ADD_REVOCATION", "SENT_ADD_ACK_COMMIT", "RCVD_ADD_ACK_REVOCATION", "SENT_REMOVE_HTLC", "SENT_REMOVE_COMMIT", "RCVD_REMOVE_REVOCATION", "RCVD_REMOVE_ACK_COMMIT", "SENT_REMOVE_ACK_REVOCATION") + - **last_update_tx** (string, optional): latest signed and finalized update transaction bound to latest state output + - **last_settle_tx** (string, optional): latest signed and finalized settle transaction bound to last_update_tx state outpoint + - **unbound_update_tx** (string, optional): latest unfinalized update transaction + - **unbound_settle_tx** (string, optional): latest unfinalized settle transaction + - **last_committed_settle_tx** (string, optional): latest finalized settle transaction bound to a committed-but-not-complete update transaction If **close_to** is present: - **close_to_addr** (string, optional): The bitcoin address we will close to @@ -380,4 +385,4 @@ Main web site: Lightning RFC site (BOLT \#9): -[comment]: # ( SHA256STAMP:6b0ec5c899c8685487190209f594635030205a275e1dc6d61a7b057adbf66192) +[comment]: # ( SHA256STAMP:ce4894e2a9dab0e3994bb88b6e3ba925ac80c0535236125bf544fb67d056ebf7) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 9176df161dbe..dc23d51b116f 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -2764,7 +2764,7 @@ static struct command_result *json_dev_reenable_commit(struct command *cmd, "Peer has no owner"); } - if (!streq(channel->owner->name, "channeld")) { + if (!streq(channel->owner->name, "channeld") && !streq(channel->owner->name, "eltoo_channeld")) { return command_fail(cmd, LIGHTNINGD, "Peer owned by %s", channel->owner->name); } diff --git a/tests/test_closing.py b/tests/test_closing.py index 36c510b63cbd..10467af92adf 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -18,6 +18,8 @@ import threading import unittest +# In msats +SAT = 1000 @pytest.mark.developer("Too slow without --dev-bitcoind-poll") def test_closing_simple(node_factory, bitcoind, chainparams): @@ -725,6 +727,170 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) +@pytest.mark.developer("needs dev-disable-commit-after") +def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): + """Test penalty transaction with an outgoing HTLC""" + + # We track channel balances, to verify that accounting is ok. + coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') + # First we need to get funds to l2, so suppress after second. + # Feerates identical so we don't get gratuitous commit to update them + l1, l2 = node_factory.line_graph(2, + opts=[{'dev-disable-commit-after': 1, # add HTLC once + 'may_fail': True, + 'feerates': (7500, 7500, 7500, 7500), + 'allow_broken_log': True, + 'plugin': coin_mvt_plugin}, + {'dev-disable-commit-after': 2, # remove HTLC, then later add + 'plugin': coin_mvt_plugin}]) + channel_id = first_channel_id(l1, l2) + + # Move some across to l2. This will cause *2* updates to be sent for + # addition and removal of HTLC + l1.pay(l2, 200000*SAT) + + # l1 won't be able to remove next HTLC after offering first addition + l1.daemon.wait_for_log('dev-disable-commit-after: disabling') + assert not l2.daemon.is_in_log('dev-disable-commit-after: disabling') + + # Now, this will get stuck due to l1 commit being disabled due to one more update.. + t = executor.submit(l2.pay, l1, 100000*SAT) + + from pdb import set_trace + set_trace() + + # Make sure we get partial signature + l1.daemon.wait_for_log('peer_in WIRE_UPDATE_ADD_HTLC') + l1.daemon.wait_for_log('peer_in WIRE_UPDATE_SIGNED') + + # They should both have commitments blocked now. + l2.daemon.wait_for_log('dev-disable-commit-after: disabling') + + # Both peers have partial sigs for the latest update transaction + l1.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') + l2.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') + + # Take our snapshot of complete tx with HTLC. + l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + l2_update_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l2_settle_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + assert l1_update_tx == l2_update_tx + assert l1_settle_tx == l2_settle_tx + + # Let them continue + l1.rpc.dev_reenable_commit(l2.info['id']) + l2.rpc.dev_reenable_commit(l1.info['id']) + + # Thread should complete. + t.result(timeout=10) + + # Make sure both sides got revoke_and_ack for final. + l1.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') + l2.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') + + # Now we really mess things up! + + # FIXME we need real anchor CPFP + package relay to pay fees + l1_update_details = bitcoind.decoderawtransaction(l1_update_tx) + bitcoind.rpc.prioritisetransaction(l1_update_details["txid"], 0, 100000000) + bitcoind.rpc.sendrawtransaction(l1_update_tx) + # Mine and mature the update tx + bitcoind.generate_block(6) + + # Symmetrical transactions(!), symmetrical state, mostly + l1.daemon.wait_for_log(' to ONCHAIN') + l2.daemon.wait_for_log(' to ONCHAIN') + + needle = l2.daemon.logsearch_start + + # The settle transaction should hit the mempool for both! + l1.wait_for_onchaind_broadcast('ELTOO_SETTLE', + 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') + l2.wait_for_onchaind_broadcast('ELTOO_SETTLE', + 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') + + # Mine it, then we should see HTLC resolution hit the mempool by the receiver + # since timeout hasn't occured yet + bitcoind.generate_block(1) + + l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', + 'ELTOO_SETTLE/THEIR_HTLC') + + # Now that fulfillment is in mempool, we can censor it + + # Then mine blocks until HTLC timeout path can be taken by offerer + + # Timeout should knock out the censored fulfillment tx + + # 100 blocks later, all resolved + + return + + l2.daemon.logsearch_start = needle + l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/OUR_HTLC') + + l2.daemon.logsearch_start = needle + l2.daemon.wait_for_log('Ignoring output.*: THEIR_REVOKED_UNILATERAL/OUTPUT_TO_US') + + # FIXME: test HTLC tx race! + + # 100 blocks later, all resolved. + bitcoind.generate_block(100) + + sync_blockheight(bitcoind, [l1, l2]) + wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 0) + + # Do one last pass over the logs to extract the reactions l2 sent + l2.daemon.logsearch_start = needle + needles = [ + r'Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by THEIR_REVOKED_UNILATERAL .([a-f0-9]{64}).', + r'Resolved THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM by our proposal OUR_PENALTY_TX .([a-f0-9]{64}).', + r'Resolved THEIR_REVOKED_UNILATERAL/OUR_HTLC by our proposal OUR_PENALTY_TX .([a-f0-9]{64}).', + ] + matches = list(map(l2.daemon.is_in_log, needles)) + + # Now extract the txids for these responses + txids = set([re.search(r'\(([0-9a-f]{64})\)', m).group(1) for m in matches]) + + # We should have one confirmed output for each of the above reactions in + # the list of funds we own. + outputs = l2.rpc.listfunds()['outputs'] + + assert [o['status'] for o in outputs] == ['confirmed'] * 3 + assert set([o['txid'] for o in outputs]) == txids + assert account_balance(l1, channel_id) == 0 + assert account_balance(l2, channel_id) == 0 + + # l1 loses all of their channel balance to the peer, as penalties + expected_1 = { + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], + 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('external', ['penalty'], None, None), ('external', ['penalty'], None, None), ('external', ['penalty'], None, None)], + } + + # l2 sweeps all of l1's closing outputs + expected_2 = { + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('wallet', ['deposit'], None, None), ('cid1', ['penalty'], ['to_wallet'], 'C'), ('cid1', ['penalty'], ['to_wallet'], 'D')], + 'C': [('wallet', ['deposit'], None, None)], + 'D': [('wallet', ['deposit'], None, None)] + } + + if anchor_expected(): + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) + + # We use a subset of tags in expected_2 that are used in expected_1 + tags = check_utxos_channel(l1, [channel_id], expected_1) + check_utxos_channel(l2, [channel_id], expected_2, tags) + + @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') From 4c8adf3dda4ec622786fc83a50890ce716d91575 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 12 Dec 2022 17:30:45 -0500 Subject: [PATCH 238/283] more test --- contrib/pyln-testing/pyln/testing/utils.py | 8 +++++++- tests/test_closing.py | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index d710dd48b5c1..9629ce5f5c3c 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -386,8 +386,14 @@ def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None): '-nolisten', '-txindex', '-nowallet', - '-addresstype=bech32' + '-addresstype=bech32', ] + + # Only for eltoo testing + if os.environ.get('BITCOIND_ELTOO_ARGS'): + self.cmd_line.append("-trueoutputs=1") + self.cmd_line.append("-annexcarrier=1") + # For up to and including 0.16.1, this needs to be in main section. BITCOIND_CONFIG['rpcport'] = rpcport # For after 0.16.1 (eg. 3f398d7a17f136cd4a67998406ca41a124ae2966), this diff --git a/tests/test_closing.py b/tests/test_closing.py index 10467af92adf..c074e4690606 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -756,9 +756,6 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): # Now, this will get stuck due to l1 commit being disabled due to one more update.. t = executor.submit(l2.pay, l1, 100000*SAT) - from pdb import set_trace - set_trace() - # Make sure we get partial signature l1.daemon.wait_for_log('peer_in WIRE_UPDATE_ADD_HTLC') l1.daemon.wait_for_log('peer_in WIRE_UPDATE_SIGNED') @@ -780,21 +777,24 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): assert l1_update_tx == l2_update_tx assert l1_settle_tx == l2_settle_tx - # Let them continue - l1.rpc.dev_reenable_commit(l2.info['id']) - l2.rpc.dev_reenable_commit(l1.info['id']) + # We can't them continue, since we'll end up blowing away old HTLCs (or having to deal with + # old state we didn't keep) + # l1.rpc.dev_reenable_commit(l2.info['id']) # Thread should complete. - t.result(timeout=10) +# t.result(timeout=10) # Make sure both sides got revoke_and_ack for final. - l1.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') - l2.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') +# l1.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') +# l2.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') + + from pdb import set_trace + set_trace() # Now we really mess things up! # FIXME we need real anchor CPFP + package relay to pay fees - l1_update_details = bitcoind.decoderawtransaction(l1_update_tx) + l1_update_details = bitcoind.rpc.decoderawtransaction(l1_update_tx) bitcoind.rpc.prioritisetransaction(l1_update_details["txid"], 0, 100000000) bitcoind.rpc.sendrawtransaction(l1_update_tx) # Mine and mature the update tx From bba5ddd2d1cf61681a34490a055e2585beadeeb9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 13 Dec 2022 12:55:32 -0500 Subject: [PATCH 239/283] HTLC resolution crashing now --- doc/HACKING.md | 3 ++- onchaind/eltoo_onchaind.c | 15 ++++++++------- tests/test_closing.py | 10 +++++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/doc/HACKING.md b/doc/HACKING.md index 17242945bd72..8313ecd51790 100644 --- a/doc/HACKING.md +++ b/doc/HACKING.md @@ -218,7 +218,8 @@ There are four kinds of tests: You can also append `-k TESTNAME` to run a single test. Environment variables `DEBUG_SUBD=` and `TIMEOUT=` can be useful for debugging - subdaemons on individual tests. + subdaemons on individual tests, with `VALGRIND=0` to make gdb debugging easier + and tests run quicker. You need `bitcoind` installed in your path, or must supply one as an environmental variable: `BITCOIND_TEST_PATH=` diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 3fc9083727f7..28b148bc4517 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -44,7 +44,7 @@ static bool bipmusig_partial_sigs_combine_state(const struct eltoo_sign *state, static bool update_phase; /* During update_phase we queue all payment preimage notifications */ -static struct preimage **cached_preimages; +static struct preimage *cached_preimages; /* Full tx we have partial signatures for */ static struct bitcoin_tx *complete_update_tx, *complete_settle_tx; @@ -965,13 +965,13 @@ static void track_settle_outputs(struct tracked_output ***outs, */ /* Master makes sure we only get told preimages once other node is committed. */ static void eltoo_handle_preimage(struct tracked_output **outs, - const struct preimage *preimage) + const struct preimage preimage) { size_t i; struct sha256 sha; struct ripemd160 ripemd; - sha256(&sha, preimage, sizeof(*preimage)); + sha256(&sha, &preimage, sizeof(preimage)); ripemd160(&ripemd, &sha, sizeof(sha)); for (i = 0; i < tal_count(outs); i++) { @@ -1013,8 +1013,9 @@ static void eltoo_handle_preimage(struct tracked_output **outs, } static void eltoo_handle_cached_preimages(struct tracked_output **outs, - struct preimage **cached_preimages) + struct preimage *cached_preimages) { + status_debug("Processing cached preimages now that we have settle tx confirmed"); for (int j=0; j Date: Tue, 13 Dec 2022 16:37:11 -0500 Subject: [PATCH 240/283] Stuff to revert? --- channeld/eltoo_channeld.c | 2 ++ channeld/settle_tx.c | 2 ++ hsmd/libhsmd.c | 3 +++ lightningd/onchain_control.c | 25 ++++--------------------- onchaind/eltoo_onchaind.c | 15 +++++++++++---- tests/test_closing.py | 5 +++-- wallet/wallet.c | 35 +++++++++++++++++++++++++++++++++++ wallet/wallet.h | 15 +++++++++++++++ 8 files changed, 75 insertions(+), 27 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 53e9f6866e7f..c4376baf2874 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -833,6 +833,7 @@ static void send_update(struct eltoo_peer *peer) return; } + status_debug("Creating pair of transactions for sending update"); update_and_settle_txs = eltoo_channel_txs(tmpctx, &htlc_map, direct_outputs, peer->channel, peer->next_index, LOCAL); @@ -1094,6 +1095,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) status_debug("Received update_sig"); + status_debug("Creating pair of transactions for update we received"); update_and_settle_txs = eltoo_channel_txs(tmpctx, &htlc_map, /* direct_outputs */ NULL, peer->channel, diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 3c378224873b..d14add8397b1 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -76,6 +76,8 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, htlc_scripts[0] = make_eltoo_htlc_success_script(tx, receiver_pubkey, htlc->rhash.u.u8); htlc_scripts[1] = make_eltoo_htlc_timeout_script(tx, sender_pubkey, htlc->expiry.locktime); + printf("Settle's HTLC success script: %s\n", tal_hex(NULL, htlc_scripts[0])); + printf("Settle's HTLC timeout script: %s\n", tal_hex(NULL, htlc_scripts[1])); compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out); diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 69d451c990fc..10fa6bbbbedc 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -836,6 +836,9 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) return hsmd_status_malformed_request(c, msg_in); + /* FIXME this is apparently not true */ + //tal_free(secretstuff.musig_map); + /* Shouldn't need to be freed, aside from channel teardown */ new_musig_state = tal(NULL, struct musig_state); new_musig_state->channel_id = channel_id; diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 873bd0d6d06d..d17f7452b639 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -142,9 +142,6 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m { struct htlc_stub *stubs; bool *tell, *tell_immediate; - /* We are only interested in latest HTLCs, the ones we will recall */ - u64 complete_update_num = channel->eltoo_keyset.complete_update_tx->wtx->locktime; - // u64 committed_update_num = complete_update_num + 1; /* May not exist, that's ok */ /* Signaling ready, send more data */ if (!fromwire_eltoo_onchaind_init_reply(msg)) { @@ -160,9 +157,8 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m REASON_UNKNOWN, "Onchain init reply"); - /* Tell it about any relevant HTLCs */ - stubs = wallet_htlc_stubs(tmpctx, channel->peer->ld->wallet, channel, - complete_update_num); + /* Tell it about any relevant HTLCs. Future Work: Delete stale HTLCS from db */ + stubs = all_wallet_htlc_stubs(tmpctx, channel->peer->ld->wallet, channel); tell = tal_arr(stubs, bool, tal_count(stubs)); tell_immediate = tal_arr(stubs, bool, tal_count(stubs)); @@ -172,23 +168,10 @@ static void handle_eltoo_onchain_init_reply(struct channel *channel, const u8 *m } msg = towire_onchaind_htlcs(channel, stubs, tell, tell_immediate); + log_info(channel->log, "Telling eltoo_onchaind about %lu HTLCs", tal_count(stubs)); subd_send_msg(channel->owner, take(msg)); - /* FIXME Do the same steps again for committed htlcs, if they exist - stubs = wallet_htlc_stubs(tmpctx, channel->peer->ld->wallet, channel, - committed_update_num); - tell = tal_arr(stubs, bool, tal_count(stubs)); - tell_immediate = tal_arr(stubs, bool, tal_count(stubs)); - - for (size_t i = 0; i < tal_count(stubs); i++) { - tell[i] = tell_if_missing(channel, &stubs[i], - &tell_immediate[i]); - } - msg = towire_onchaind_htlcs(channel, stubs, tell, tell_immediate); - - subd_send_msg(channel->owner, take(msg)); */ - - /* Finally, ell it about any preimages we know. */ + /* Finally, tell it about any preimages we know. */ onchaind_tell_fulfill(channel); } diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 28b148bc4517..77576efc66f1 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -274,8 +274,9 @@ static u8 **derive_htlc_success_scripts(const tal_t *ctx, const struct htlc_stub for (i = 0; i < tal_count(htlcs); i++) { htlc_scripts[i] = make_eltoo_htlc_success_script(htlc_scripts, - htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, + htlcs[i].owner == LOCAL ? their_htlc_pubkey : our_htlc_pubkey, htlcs[i].ripemd.u.u8); + status_debug("HTLC success script %lu: %s", i, tal_hex(NULL, htlc_scripts[i])); } return htlc_scripts; } @@ -289,6 +290,7 @@ static u8 **derive_htlc_timeout_scripts(const tal_t *ctx, const struct htlc_stub htlc_scripts[i] = make_eltoo_htlc_timeout_script(htlc_scripts, htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, htlcs[i].cltv_expiry); + status_debug("HTLC timeout script %lu: %s", i, tal_hex(NULL, htlc_scripts[i])); } return htlc_scripts; } @@ -326,9 +328,10 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, const u8 *script = tal_dup_arr(tmpctx, u8, out->script, out->script_len, 0); /* Must be a p2tr output */ - if (!is_p2tr(script, NULL)) - return matches; - + if (!is_p2tr(script, NULL)) { + /* FIXME do something better than crash */ + abort(); + } for (size_t i = 0; i < tal_count(htlc_success_scripts); i++) { struct sha256 tap_merkle_root; const struct pubkey *pubkey_ptrs[2]; @@ -351,6 +354,8 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, &tap_merkle_root, tap_tweak_out); taproot_script = scriptpubkey_p2tr(ctx, &taproot_pubkey); + status_debug("Reconstructed HTLC script for comparison with output: %s", tal_hex(NULL, taproot_script)); + if (memeq(taproot_script, tal_count(taproot_script), script, sizeof(script))) { tal_arr_expand(&matches, i); *parity_bit = pubkey_parity(&taproot_pubkey); @@ -1457,6 +1462,8 @@ static struct htlcs_info *eltoo_init_reply(const tal_t *ctx, const char *what) htlcs_info->tell_immediately[i] = htlcs[i].tell_immediately; } + status_debug("Handling %lu HTLC scripts for possible resolution", tal_count(htlcs_info->htlcs)); + return htlcs_info; } diff --git a/tests/test_closing.py b/tests/test_closing.py index 9db1a910abee..f52c508dc2eb 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -745,6 +745,9 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): 'plugin': coin_mvt_plugin}]) channel_id = first_channel_id(l1, l2) + from pdb import set_trace + set_trace() + # Move some across to l2. This will cause *2* updates to be sent for # addition and removal of HTLC l1.pay(l2, 200000*SAT) @@ -800,8 +803,6 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): bitcoind.generate_block(6) # FIXME we're here, settle tx should be shot off to mempool XXX - from pdb import set_trace - set_trace() # Symmetrical transactions(!), symmetrical state, mostly diff --git a/wallet/wallet.c b/wallet/wallet.c index ac4dc9b190a1..292242fc27d1 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2943,6 +2943,41 @@ struct invoice_details *wallet_invoice_details(const tal_t *ctx, return invoices_get_details(ctx, wallet->invoices, invoice); } +struct htlc_stub *all_wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, + struct channel *chan) +{ + struct htlc_stub *stubs; + struct sha256 payment_hash; + struct db_stmt *stmt; + + stmt = db_prepare_v2(wallet->db, + SQL("SELECT channel_id, direction, cltv_expiry, " + "channel_htlc_id, payment_hash " + "FROM channel_htlcs WHERE channel_id = ?;")); + + db_bind_u64(stmt, 0, chan->dbid); + db_query_prepared(stmt); + + stubs = tal_arr(ctx, struct htlc_stub, 0); + + while (db_step(stmt)) { + struct htlc_stub stub; + + assert(db_col_u64(stmt, "channel_id") == chan->dbid); + + /* FIXME: merge these two enums */ + stub.owner = db_col_int(stmt, "direction")==DIRECTION_INCOMING?REMOTE:LOCAL; + stub.cltv_expiry = db_col_int(stmt, "cltv_expiry"); + stub.id = db_col_u64(stmt, "channel_htlc_id"); + + db_col_sha256(stmt, "payment_hash", &payment_hash); + ripemd160(&stub.ripemd, payment_hash.u.u8, sizeof(payment_hash.u)); + tal_arr_expand(&stubs, stub); + } + tal_free(stmt); + return stubs; +} + struct htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, struct channel *chan, u64 commit_num) { diff --git a/wallet/wallet.h b/wallet/wallet.h index 4003adc749a5..883d33045175 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -1050,6 +1050,21 @@ struct invoice_details *wallet_invoice_details(const tal_t *ctx, struct wallet *wallet, struct invoice invoice); +/** + * all_wallet_htlc_stubs - Retrieve *all* HTLC stubs for the given channel + * + * This returns a `tal_arr` allocated off of @ctx with the + * necessary size to hold all HTLCs. Future pruning for eltoo + * channels can manage the state blowup here. + * + * @ctx: Allocation context for the return value + * @wallet: Wallet to load from + * @chan: Channel to fetch stubs for + */ +struct htlc_stub *all_wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, + struct channel *chan); + + /** * wallet_htlc_stubs - Retrieve HTLC stubs for the given channel * From af80f2b26e09e5162f60e5921f7c46ae5af6b517 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 13 Dec 2022 16:49:43 -0500 Subject: [PATCH 241/283] some notes --- hsmd/libhsmd.c | 4 +--- tests/test_closing.py | 7 +++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 10fa6bbbbedc..cdbfbe4dc679 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -836,9 +836,7 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) return hsmd_status_malformed_request(c, msg_in); - /* FIXME this is apparently not true */ - //tal_free(secretstuff.musig_map); - + /* FIXME Saw a strange memleak race, fix this reasoning */ /* Shouldn't need to be freed, aside from channel teardown */ new_musig_state = tal(NULL, struct musig_state); new_musig_state->channel_id = channel_id; diff --git a/tests/test_closing.py b/tests/test_closing.py index f52c508dc2eb..fad264f2aeaa 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -727,6 +727,8 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) +# Example flags to run test +# DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_closing.py -k test_eltoo_outhtlc @pytest.mark.developer("needs dev-disable-commit-after") def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): """Test penalty transaction with an outgoing HTLC""" @@ -745,8 +747,6 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): 'plugin': coin_mvt_plugin}]) channel_id = first_channel_id(l1, l2) - from pdb import set_trace - set_trace() # Move some across to l2. This will cause *2* updates to be sent for # addition and removal of HTLC @@ -780,6 +780,9 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): assert l1_update_tx == l2_update_tx assert l1_settle_tx == l2_settle_tx + from pdb import set_trace + set_trace() + # We can't them continue, since we'll end up blowing away old HTLCs (or having to deal with # old state we didn't keep) # l1.rpc.dev_reenable_commit(l2.info['id']) From 810385915ba418999282d2f9146ae1a67e1aabc1 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 14 Dec 2022 11:12:26 -0500 Subject: [PATCH 242/283] fix ripemd of htlc payment hash, reorder keys for contract --- bitcoin/script.c | 4 ++-- bitcoin/script.h | 2 +- channeld/settle_tx.c | 2 +- channeld/test/run-settle_tx.c | 5 +++-- onchaind/eltoo_onchaind.c | 11 +++++++---- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 973d4d21427e..e5f4040d3a79 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1264,7 +1264,7 @@ u8 *make_eltoo_funding_update_script(const tal_t *ctx) return script; } -u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const u8 *invoice_hash) +u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const struct ripemd160 *invoice_hash) { /* where EXPR_SUCCESS = * @@ -1278,7 +1278,7 @@ OP_EQUAL` add_number(&script, 32); add_op(&script, OP_EQUALVERIFY); add_op(&script, OP_HASH160); - script_push_bytes(&script, invoice_hash, 20); + script_push_bytes(&script, invoice_hash->u.u8, sizeof(invoice_hash->u.u8)); add_op(&script, OP_EQUAL); return script; } diff --git a/bitcoin/script.h b/bitcoin/script.h index 67b890aace8d..c96da0dbba51 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -218,7 +218,7 @@ u8 *make_eltoo_update_script(const tal_t *ctx, u32 update_num); u8 *make_eltoo_funding_update_script(const tal_t *ctx); /* Creates eltoo HTLC success script, with invoice hash lock */ -u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const u8 *invoice_hash); +u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const struct ripemd160 *invoice_hash); /* Creates eltoo HTLC timeout script, with timeout value */ u8 *make_eltoo_htlc_timeout_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u32 htlc_timeout); diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index d14add8397b1..44e67aa8ed65 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -74,7 +74,7 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); - htlc_scripts[0] = make_eltoo_htlc_success_script(tx, receiver_pubkey, htlc->rhash.u.u8); + htlc_scripts[0] = make_eltoo_htlc_success_script(tx, receiver_pubkey, &ripemd); htlc_scripts[1] = make_eltoo_htlc_timeout_script(tx, sender_pubkey, htlc->expiry.locktime); printf("Settle's HTLC success script: %s\n", tal_hex(NULL, htlc_scripts[0])); printf("Settle's HTLC timeout script: %s\n", tal_hex(NULL, htlc_scripts[1])); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 58c816c6ff8b..2b60e908de5b 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -775,7 +775,8 @@ static int test_htlc_output_creation(void) u8 *tapleaf_scripts[2]; u8 *taproot_script; /* 0-value hash image */ - unsigned char *invoice_hash = tal_arr(tmpctx, u8, 20); + struct ripemd160 invoice_hash; + memset(invoice_hash.u.u8, 0, sizeof(invoice_hash.u.u8)); struct sha256 tap_merkle_root; struct pubkey inner_pubkey; secp256k1_xonly_pubkey xonly_inner_pubkey; @@ -809,7 +810,7 @@ static int test_htlc_output_creation(void) ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, inner_pubkey_bytes, &xonly_inner_pubkey); assert(ok); - htlc_success_script = make_eltoo_htlc_success_script(tmpctx, &settlement_pubkey, invoice_hash); + htlc_success_script = make_eltoo_htlc_success_script(tmpctx, &settlement_pubkey, &invoice_hash); htlc_timeout_script = make_eltoo_htlc_timeout_script(tmpctx, &settlement_pubkey, 420); tapleaf_scripts[0] = htlc_success_script; tapleaf_scripts[1] = htlc_timeout_script; diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 77576efc66f1..26c60a21db5f 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -273,9 +273,10 @@ static u8 **derive_htlc_success_scripts(const tal_t *ctx, const struct htlc_stub u8 **htlc_scripts = tal_arr(ctx, u8 *, tal_count(htlcs)); for (i = 0; i < tal_count(htlcs); i++) { + /* FIXME shouldn't be right ... wrong key orderring. The scripts seem to be mismatched in orderingthis way? */ htlc_scripts[i] = make_eltoo_htlc_success_script(htlc_scripts, - htlcs[i].owner == LOCAL ? their_htlc_pubkey : our_htlc_pubkey, - htlcs[i].ripemd.u.u8); + htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, + &htlcs[i].ripemd); status_debug("HTLC success script %lu: %s", i, tal_hex(NULL, htlc_scripts[i])); } return htlc_scripts; @@ -287,8 +288,9 @@ static u8 **derive_htlc_timeout_scripts(const tal_t *ctx, const struct htlc_stub u8 **htlc_scripts = tal_arr(ctx, u8 *, tal_count(htlcs)); for (i = 0; i < tal_count(htlcs); i++) { + /* FIXME shouldn't be right ... wrong key orderring. The scripts seem to be mismatched in orderingthis way? */ htlc_scripts[i] = make_eltoo_htlc_timeout_script(htlc_scripts, - htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, + htlcs[i].owner == LOCAL ? their_htlc_pubkey : our_htlc_pubkey, htlcs[i].cltv_expiry); status_debug("HTLC timeout script %lu: %s", i, tal_hex(NULL, htlc_scripts[i])); } @@ -354,9 +356,10 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, &tap_merkle_root, tap_tweak_out); taproot_script = scriptpubkey_p2tr(ctx, &taproot_pubkey); - status_debug("Reconstructed HTLC script for comparison with output: %s", tal_hex(NULL, taproot_script)); + status_debug("Reconstructed HTLC script %s for comparison with output: %s", tal_hex(NULL, taproot_script), tal_hex(NULL, script)); if (memeq(taproot_script, tal_count(taproot_script), script, sizeof(script))) { + status_debug("Matched!"); tal_arr_expand(&matches, i); *parity_bit = pubkey_parity(&taproot_pubkey); } From 4d6b416efc8cd7b74058d720a7403fcce1827b9a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 14 Dec 2022 11:24:15 -0500 Subject: [PATCH 243/283] Don't sizeof a pointer... --- onchaind/eltoo_onchaind.c | 63 +++++++++++++++------------------------ 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 26c60a21db5f..27bec7756812 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -358,7 +358,7 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, status_debug("Reconstructed HTLC script %s for comparison with output: %s", tal_hex(NULL, taproot_script), tal_hex(NULL, script)); - if (memeq(taproot_script, tal_count(taproot_script), script, sizeof(script))) { + if (memeq(taproot_script, tal_count(taproot_script), script, tal_count(script))) { status_debug("Matched!"); tal_arr_expand(&matches, i); *parity_bit = pubkey_parity(&taproot_pubkey); @@ -882,54 +882,39 @@ static void track_settle_outputs(struct tracked_output ***outs, struct tracked_output *out; struct amount_sat satoshis = amount_sat(settle_out->satoshi); int parity_bit; + + status_debug("Output script: %s", tal_hex(tmpctx, settle_out->script)); + + /* (1) Ephemeral Anchor */ if (is_ephemeral_anchor(settle_out->script)) { /* Anchor is lightningd's problem */ continue; } + + if (!is_p2tr(settle_out->script, NULL)) { + /* Everything should be taproot FIXME what do */ + abort(); + } + + /* Balance outputs are self-resolving in the settle tx */ + u8 *to_us = scriptpubkey_p2tr(tmpctx, &keyset->self_settle_key); + status_debug("to_us script: %s", tal_hex(tmpctx, to_us)); + if (memcmp(settle_out->script, to_us, tal_count(to_us)) == 0) { + continue; + } + + u8 *to_them = scriptpubkey_p2tr(tmpctx, &keyset->other_settle_key); + status_debug("to_them script: %s", tal_hex(tmpctx, to_them)); + if (memcmp(settle_out->script, to_them, tal_count(to_them)) == 0) { + continue; + } + const size_t *matches = eltoo_match_htlc_output(tmpctx, settle_out, htlc_success_scripts, htlc_timeout_scripts, &parity_bit); struct bitcoin_outpoint outpoint; outpoint.txid = tx_parts->txid; outpoint.n = j; if (tal_count(matches) == 0) { - if (!is_p2tr(settle_out->script, NULL)) { - /* Everything should be taproot FIXME what do */ - abort(); - } - /* Balance outputs are self-resolving in the settle tx */ - status_debug("Output script: %s", tal_hex(tmpctx, settle_out->script)); - u8 *to_us = scriptpubkey_p2tr(tmpctx, &keyset->self_settle_key); - status_debug("to_us script: %s", tal_hex(tmpctx, to_us)); - if (memcmp(settle_out->script, to_us, tal_count(to_us)) == 0) { - /* (2) `to_node` to us */ - //out = new_tracked_output(outs, &outpoint, - // tx_blockheight, - // ELTOO_SETTLE, - // satoshis, - // OUTPUT_TO_US /* output_type */, - // NULL /* htlc */, - // NULL /* htlc_success_tapscript */, - // NULL /* htlc_timeout_tapscript */); - /* No need to resolve or track it */ - //ignore_output(out); - continue; - } - u8 *to_them = scriptpubkey_p2tr(tmpctx, &keyset->other_settle_key); - status_debug("to_them script: %s", tal_hex(tmpctx, to_them)); - if (memcmp(settle_out->script, to_them, tal_count(to_them)) == 0) { - /* (3) `to_node` to them */ - //out = new_tracked_output(outs, &outpoint, - // tx_blockheight, - // ELTOO_SETTLE, - // satoshis, - // OUTPUT_TO_THEM /* output_type */, - // NULL /* htlc */, - // NULL /* htlc_success_tapscript */, - // NULL /* htlc_timeout_tapscript */); - /* No need to resolve it */ - //ignore_output(out); - continue; - } /* Update we don't recognise :( FIXME what do */ /* This can hit if it was a "future" settlement transaction, which terminates the process with an error */ status_failed(STATUS_FAIL_INTERNAL_ERROR, "Couldn't match settlement output script to known output type"); From b5fcb595151a82fcf4fc67a71808cd72b83d24df Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 14 Dec 2022 11:36:19 -0500 Subject: [PATCH 244/283] fixup add_eltoo_htlc_out side arg, revert key ordering --- channeld/settle_tx.c | 4 ++-- onchaind/eltoo_onchaind.c | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 44e67aa8ed65..d65401620df8 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -48,7 +48,7 @@ bool settle_tx_amount_trimmed(const struct htlc **htlcs, static void add_eltoo_htlc_out(struct bitcoin_tx *tx, const struct htlc *htlc, const struct eltoo_keyset *eltoo_keyset, - enum side receiver_side) + enum side sender_side) { struct ripemd160 ripemd; u8 *htlc_scripts[2]; @@ -61,7 +61,7 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, struct pubkey taproot_pubkey; unsigned char tap_tweak_out[32]; - if (receiver_side == LOCAL) { + if (sender_side == REMOTE) { receiver_pubkey = &(eltoo_keyset->self_settle_key); sender_pubkey = &(eltoo_keyset->other_settle_key); } else { diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 27bec7756812..a9ba24a568f5 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -273,9 +273,8 @@ static u8 **derive_htlc_success_scripts(const tal_t *ctx, const struct htlc_stub u8 **htlc_scripts = tal_arr(ctx, u8 *, tal_count(htlcs)); for (i = 0; i < tal_count(htlcs); i++) { - /* FIXME shouldn't be right ... wrong key orderring. The scripts seem to be mismatched in orderingthis way? */ htlc_scripts[i] = make_eltoo_htlc_success_script(htlc_scripts, - htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, + htlcs[i].owner == LOCAL ? their_htlc_pubkey : our_htlc_pubkey, &htlcs[i].ripemd); status_debug("HTLC success script %lu: %s", i, tal_hex(NULL, htlc_scripts[i])); } @@ -288,9 +287,8 @@ static u8 **derive_htlc_timeout_scripts(const tal_t *ctx, const struct htlc_stub u8 **htlc_scripts = tal_arr(ctx, u8 *, tal_count(htlcs)); for (i = 0; i < tal_count(htlcs); i++) { - /* FIXME shouldn't be right ... wrong key orderring. The scripts seem to be mismatched in orderingthis way? */ htlc_scripts[i] = make_eltoo_htlc_timeout_script(htlc_scripts, - htlcs[i].owner == LOCAL ? their_htlc_pubkey : our_htlc_pubkey, + htlcs[i].owner == LOCAL ? our_htlc_pubkey : their_htlc_pubkey, htlcs[i].cltv_expiry); status_debug("HTLC timeout script %lu: %s", i, tal_hex(NULL, htlc_scripts[i])); } From 88b585e574db3707c614ba0b3a5710c12e867dbd Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 14 Dec 2022 16:47:59 -0500 Subject: [PATCH 245/283] Both HTLC txns being handled... and crashing in hsmd --- onchaind/eltoo_onchaind.c | 90 ++++++++++++++++++++++++--------------- onchaind/onchain_types.h | 3 ++ tests/test_closing.py | 14 +++--- 3 files changed, 66 insertions(+), 41 deletions(-) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index a9ba24a568f5..e62a657c06f4 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -99,6 +99,7 @@ struct tracked_output { struct amount_sat sat; enum output_type output_type; u32 locktime; /* Used to detec update->settle transition */ + u8 *scriptPubKey; /* If it is an HTLC, this is set, tapscripts are non-NULL. */ struct htlc_stub htlc; @@ -184,7 +185,7 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); bitcoin_tx_add_input(tx, &out->outpoint, 0 /* sequence */, - NULL /* scriptSig */, out->sat, NULL /* scriptPubkey */, + NULL /* scriptSig */, out->sat, out->scriptPubKey /* scriptPubkey */, NULL /* input_wscript */, NULL /* inner_pubkey */, NULL /* tap_tree */); /* FIXME figure out taproot output support to go directly into wallet aka "our_wallet_pubkey" */ @@ -372,6 +373,7 @@ new_tracked_output(struct tracked_output ***outs, enum eltoo_tx_type tx_type, struct amount_sat sat, enum output_type output_type, + u8 *scriptPubKey, u32 locktime, const struct htlc_stub *htlc, const u8 *htlc_success_tapscript TAKES, @@ -393,6 +395,8 @@ new_tracked_output(struct tracked_output ***outs, out->locktime = locktime; out->proposal = NULL; out->resolved = NULL; + if (scriptPubKey) + out->scriptPubKey = tal_dup(out, u8, scriptPubKey); if (htlc) out->htlc = *htlc; out->htlc_success_tapscript = tal_steal(out, htlc_success_tapscript); @@ -422,7 +426,7 @@ static void ignore_output(struct tracked_output *out) static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum eltoo_tx_type t) { - /* FIXME put eltoo_tx_type into proper wallet_tx_type */ + /* FIXME Need to distinguish TX_THEIRS when possible (SUCCESS/TIMEOUT) */ switch (t) { case ELTOO_FUNDING_TRANSACTION: return TX_CHANNEL_FUNDING; @@ -432,10 +436,15 @@ static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum eltoo_tx_type t) case ELTOO_INVALIDATED_UPDATE: case ELTOO_SETTLE: case ELTOO_INVALIDATED_SETTLE: + return TX_CHANNEL_UNILATERAL; case ELTOO_HTLC_SUCCESS: + return TX_CHANNEL_HTLC_SUCCESS; case ELTOO_HTLC_TIMEOUT: - case ELTOO_IGNORING_TINY_PAYMENT: + case ELTOO_HTLC_TIMEOUT_TO_THEM: + return TX_CHANNEL_HTLC_TIMEOUT; case ELTOO_SELF: + return TX_CHANNEL_SWEEP; + case ELTOO_IGNORING_TINY_PAYMENT: case ELTOO_UNKNOWN_TXTYPE: return TX_UNKNOWN; } @@ -515,13 +524,26 @@ static void eltoo_proposal_meets_depth(struct tracked_output *out) { bool is_rbf = eltoo_proposal_is_rbfable(out->proposal); - /* We only propose something if we have something to do */ -// if (!out->proposal->tx && -// out->proposal->tx_type != ELTOO_HTLC_TIMEOUT) { -// ignore_output(out); -// return; -// } - + /* Some transactions can be constructed just-in-time to have better fees if updated */ + if (out->proposal->tx_type == ELTOO_HTLC_TIMEOUT) { + if (!out->proposal->tx) { + status_broken("Proposal tx already exists for HTLC timeout when it should be null. Stumbling through."); + } else { + status_debug("Creating HTLC timeout sweep transaction to be signed"); + out->proposal->tx = bip340_tx_to_us(out, + htlc_timeout_to_us, + out, + out->htlc.cltv_expiry, + out->htlc_timeout_tapscript, + compute_control_block(out, out->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, out->parity_bit), + &out->proposal->tx_type, /* over-written if too small to care */ + htlc_feerate); + } + } else if (out->proposal->tx_type == ELTOO_HTLC_TIMEOUT_TO_THEM) { + // Not going to do anything to resolve this proposal here, + // instead we'll keep waiting for HTLC preimage + return; + } status_debug("Broadcasting %s (%s) to resolve %s/%s", eltoo_tx_type_name(out->proposal->tx_type), @@ -755,17 +777,18 @@ static void propose_resolution(struct tracked_output *out, /* HTLC resolution won't have tx pre-built */ static void propose_htlc_timeout_resolution(struct tracked_output *out, - unsigned int depth_required) + unsigned int depth_required, + enum eltoo_tx_type tx_type) { status_debug("Propose handling %s/%s by %s after %u blocks", eltoo_tx_type_name(out->tx_type), output_type_name(out->output_type), - eltoo_tx_type_name(ELTOO_HTLC_TIMEOUT), + eltoo_tx_type_name(tx_type), depth_required); out->proposal = tal(out, struct proposed_resolution); out->proposal->depth_required = depth_required; - out->proposal->tx_type = ELTOO_HTLC_TIMEOUT; + out->proposal->tx_type = tx_type; if (depth_required == 0) eltoo_proposal_meets_depth(out); @@ -773,7 +796,7 @@ static void propose_htlc_timeout_resolution(struct tracked_output *out, /* HTLC resolution won't have tx pre-built */ static void propose_htlc_resolution_at_block(struct tracked_output *out, - unsigned int block_required, + u32 block_required, enum eltoo_tx_type tx_type) { u32 depth; @@ -783,7 +806,7 @@ static void propose_htlc_resolution_at_block(struct tracked_output *out, depth = 0; else /* Note that out->tx_blockheight is already at depth 1 */ depth = block_required - out->tx_blockheight + 1; - propose_htlc_timeout_resolution(out, depth); + propose_htlc_timeout_resolution(out, depth, tx_type); } static void unwatch_txid(const struct bitcoin_txid *txid) @@ -917,26 +940,32 @@ static void track_settle_outputs(struct tracked_output ***outs, /* This can hit if it was a "future" settlement transaction, which terminates the process with an error */ status_failed(STATUS_FAIL_INTERNAL_ERROR, "Couldn't match settlement output script to known output type"); } else { - if (matches_direction(matches, htlcs_info->htlcs) == LOCAL) { - /* (4) HTLC to us */ + if (matches_direction(matches, htlcs_info->htlcs) == REMOTE) { + /* (4) HTLC they own (to us) */ out = new_tracked_output(outs, &outpoint, tx_blockheight, ELTOO_SETTLE, satoshis, THEIR_HTLC, + settle_out->script, 0 /* locktime (unused by settle logic) */, &htlcs_info->htlcs[matches[0]] /* htlc */, htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, htlc_timeout_scripts[matches[0]] /* htlc_timeout_tapscript */); out->parity_bit = parity_bit; - /* FIXME Proposal comes in at handle_preimage? */ + /* We set a resolution we won't trigger ourselves, ideally we sweep via preimage + * I do this mostly to satisfy the billboard notification of pending resolutions + * in billboard_update + */ + propose_htlc_resolution_at_block(out, htlcs_info->htlcs[matches[0]].cltv_expiry, ELTOO_HTLC_TIMEOUT_TO_THEM); } else { - /* (5) HTLC to them */ + /* (5) HTLC we own (to them) */ out = new_tracked_output(outs, &outpoint, tx_blockheight, ELTOO_SETTLE, satoshis, OUR_HTLC, + settle_out->script, 0 /* locktime (unused by settle logic) */, &htlcs_info->htlcs[matches[0]] /* htlc */, htlc_success_scripts[matches[0]] /* htlc_success_tapscript */, @@ -990,6 +1019,7 @@ static void eltoo_handle_preimage(struct tracked_output **outs, * could be due to multiple identical rhashes in tx. */ outs[i]->proposal = tal_free(outs[i]->proposal); + status_debug("Creating HTLC success sweep transaction to be signed"); tx = bip340_tx_to_us(outs[i], htlc_success_to_us, outs[i], @@ -1065,7 +1095,7 @@ static void output_spent(struct tracked_output ***outs, outpoint.txid = tx_parts->txid; outpoint.n = input_num; - new_state_out = new_tracked_output(outs, &outpoint, tx_blockheight, ELTOO_UPDATE, amt, DELAYED_OUTPUT_TO_US, locktime, + new_state_out = new_tracked_output(outs, &outpoint, tx_blockheight, ELTOO_UPDATE, amt, DELAYED_OUTPUT_TO_US, tx_parts->outputs[input_num]->script, locktime, NULL /* htlcs */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); if (locktime == complete_update_tx->wtx->locktime) { @@ -1235,20 +1265,6 @@ static void eltoo_tx_new_depth(struct tracked_output **outs, if (outs[i]->proposal && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) && depth >= outs[i]->proposal->depth_required) { - /* Just-in-time creation of HTLC_TIMEOUT tx before gets broadcasted */ - if (outs[i]->proposal->tx_type == ELTOO_HTLC_TIMEOUT) { - if (outs[i]->proposal->tx) { - status_broken("Proposal tx already exists for HTLC timeout when it should be null"); - } - outs[i]->proposal->tx = bip340_tx_to_us(outs[i], - htlc_timeout_to_us, - outs[i], - outs[i]->htlc.cltv_expiry, - outs[i]->htlc_timeout_tapscript, - compute_control_block(outs[i], outs[i]->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, outs[i]->parity_bit), - &outs[i]->proposal->tx_type, /* over-written if too small to care */ - htlc_feerate); - } eltoo_proposal_meets_depth(outs[i]); } @@ -1511,7 +1527,8 @@ static void handle_unilateral(const struct tx_parts *tx, asset = wally_tx_output_get_amount(tx->outputs[state_index]); amt = amount_asset_to_sat(&asset); - htlcs_info = eltoo_init_reply(tmpctx, "Tracking update transactions"); + /* HTLCs have to be stored until program termination */ + htlcs_info = eltoo_init_reply(outs, "Tracking update transactions"); onchain_annotate_txin(&tx->txid, state_index, TX_CHANNEL_UNILATERAL); @@ -1522,6 +1539,7 @@ static void handle_unilateral(const struct tx_parts *tx, ELTOO_UPDATE, amt, DELAYED_OUTPUT_TO_US, + tx->outputs[state_index]->script, locktime, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); @@ -1594,6 +1612,7 @@ int main(int argc, char *argv[]) struct bitcoin_outpoint funding; struct amount_sat funding_sats; u32 locktime, tx_blockheight; + /* UNUSED */ u8 *scriptpubkey[NUM_SIDES]; keyset = tal(ctx, struct eltoo_keyset); @@ -1671,6 +1690,7 @@ int main(int argc, char *argv[]) FUNDING_TRANSACTION, funding_sats, FUNDING_OUTPUT, + NULL /* scriptPubKey*/, locktime, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); /* Record funding output spent */ diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index 1ab790fe8af6..bd007714639f 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -78,6 +78,9 @@ enum eltoo_tx_type { ELTOO_HTLC_TIMEOUT, ELTOO_HTLC_SUCCESS, + /* We'll let this one time out */ + ELTOO_HTLC_TIMEOUT_TO_THEM, + /* FIXME should I have more types? */ /* Amount too small, we're just spending it to close UTXO */ diff --git a/tests/test_closing.py b/tests/test_closing.py index fad264f2aeaa..e62625e488d3 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -780,9 +780,6 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): assert l1_update_tx == l2_update_tx assert l1_settle_tx == l2_settle_tx - from pdb import set_trace - set_trace() - # We can't them continue, since we'll end up blowing away old HTLCs (or having to deal with # old state we didn't keep) # l1.rpc.dev_reenable_commit(l2.info['id']) @@ -805,8 +802,8 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): # Mine and mature the update tx bitcoind.generate_block(6) - # FIXME we're here, settle tx should be shot off to mempool XXX - + from pdb import set_trace + set_trace() # Symmetrical transactions(!), symmetrical state, mostly l1.daemon.wait_for_log(' to ONCHAIN') @@ -821,12 +818,17 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') # Mine it, then we should see HTLC resolution hit the mempool by the receiver - # since timeout hasn't occured yet + # since timeout hasn't occured yet, as well as a timeout tx after X blocks bitcoind.generate_block(1) + l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', 'ELTOO_SETTLE/THEIR_HTLC') + # Brings its own fees, no CPFP required + l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', + 'ELTOO_SETTLE/OUR_HTLC') + # Now that fulfillment is in mempool, we can censor it # Then mine blocks until HTLC timeout path can be taken by offerer From e961bfb2b686083c58bfd7f3b0cb8e01854c8c5c Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 14 Dec 2022 16:55:55 -0500 Subject: [PATCH 246/283] fixup some hsmd signing stuff --- hsmd/libhsmd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index cdbfbe4dc679..2ad7d0eb5fda 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -123,6 +123,8 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US: case WIRE_HSMD_SIGN_PENALTY_TO_US: case WIRE_HSMD_SIGN_LOCAL_HTLC_TX: + case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: + case WIRE_HSMD_SIGN_ELTOO_HTLC_SUCCESS_TX: return (client->capabilities & HSM_CAP_SIGN_ONCHAIN_TX) != 0; case WIRE_HSMD_GET_PER_COMMITMENT_POINT: @@ -139,8 +141,6 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: case WIRE_HSMD_READY_ELTOO_CHANNEL: - case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: - case WIRE_HSMD_SIGN_ELTOO_HTLC_SUCCESS_TX: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: /* FIXME unused for now ... */ return (client->capabilities & HSM_CAP_SIGN_REMOTE_TX) != 0; @@ -1736,7 +1736,7 @@ static u8 *handle_sign_eltoo_htlc_tx(struct hsmd_client *c, /* FIXME still need to switch over to htlc key in spec and impl */ ret = secp256k1_keypair_create(secp256k1_ctx, &key_pair, secrets.payment_basepoint_secret.data); - if (ret) { + if (ret != 1) { return hsmd_status_bad_request(c, msg_in, "Failed to generate htlc pubkey pair"); } @@ -1936,7 +1936,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, return handle_sign_remote_htlc_to_us(client, msg); case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: return handle_sign_delayed_payment_to_us(client, msg); - /* Eltoo stuff here FIXME enable reacting to the messages*/ + /* Eltoo stuff here */ case WIRE_HSMD_READY_ELTOO_CHANNEL: return handle_ready_eltoo_channel(client, msg); case WIRE_HSMD_PSIGN_UPDATE_TX: From f4853ce8033c20456dd8235e99ac2bab6e2bc4c8 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Dec 2022 14:13:30 -0500 Subject: [PATCH 247/283] unroll taphashing, more printing --- bitcoin/script.c | 45 ++++++++++++++++++++++------------- channeld/settle_tx.c | 3 +++ channeld/test/run-settle_tx.c | 11 ++++++++- common/update_tx.c | 13 ++++++---- common/update_tx.h | 4 ++++ hsmd/libhsmd.c | 5 +++- onchaind/eltoo_onchaind.c | 37 ++++++++++++++++++---------- 7 files changed, 83 insertions(+), 35 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index e5f4040d3a79..81b8be7ae44f 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1042,8 +1042,9 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n unsigned char tag_hash_buf[1000]; /* Needs to be large enough for HTLC scripts */ unsigned char tap_hashes[64]; /* To store the leaves for comparison */ - /* Only what's required for eltoo et al for now, sue me */ - assert(num_scripts <= 2); + /* FIXME 2 scripts is broken somehow, use compute_taptree_merkle_root_with_hint instead + * Only what's required for eltoo et al for now, sue me */ + assert(num_scripts == 1 || num_scripts == 2); if (num_scripts == 1) { size_t script_len = tal_count(scripts[0]); unsigned char *p = tag_hash_buf; @@ -1058,20 +1059,32 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", hash_out->u.u8); assert(ok == WALLY_OK); } else if (num_scripts == 2) { - int i; - for (i=0; i= 0) { memcpy(tag_hash_buf, tap_hashes, 32); diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index d65401620df8..89cad806262e 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -81,6 +82,8 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out); + printf("HTLC tweaked pubkey: %s\n", type_to_string(tmpctx, struct pubkey, + &taproot_pubkey)); taproot_script = scriptpubkey_p2tr(tx, &taproot_pubkey); amount = amount_msat_to_sat_round_down(htlc->amount); diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 2b60e908de5b..c8610d6fb50f 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -774,10 +774,11 @@ static int test_htlc_output_creation(void) u8 *htlc_timeout_script; u8 *tapleaf_scripts[2]; u8 *taproot_script; + u8 *success_annex; /* 0-value hash image */ struct ripemd160 invoice_hash; memset(invoice_hash.u.u8, 0, sizeof(invoice_hash.u.u8)); - struct sha256 tap_merkle_root; + struct sha256 tap_merkle_root, tap_merkle_root_annex; struct pubkey inner_pubkey; secp256k1_xonly_pubkey xonly_inner_pubkey; unsigned char inner_pubkey_bytes[32]; @@ -814,7 +815,15 @@ static int test_htlc_output_creation(void) htlc_timeout_script = make_eltoo_htlc_timeout_script(tmpctx, &settlement_pubkey, 420); tapleaf_scripts[0] = htlc_success_script; tapleaf_scripts[1] = htlc_timeout_script; + + /* Cross-check merkle root calculations between functions */ compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 2); + success_annex = make_annex_from_script(tmpctx, htlc_success_script); + assert(tal_count(success_annex) == 33); /* TapLeaf hash + annex prefix */ + assert(success_annex[0] == 0x50); + compute_taptree_merkle_root_with_hint(&tap_merkle_root_annex, htlc_timeout_script, success_annex); + assert(memcmp(tap_merkle_root.u.u8, tap_merkle_root_annex.u.u8, sizeof(tap_merkle_root.u.u8)) == 0); + bipmusig_finalize_keys(&agg_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 1, &tap_merkle_root, tap_tweak_out); taproot_script = scriptpubkey_p2tr(tmpctx, &agg_pubkey); diff --git a/common/update_tx.c b/common/update_tx.c index a4c9637f2df1..d5435225d533 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -24,13 +24,12 @@ int tx_add_state_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *s update_tx, settle_tx->psbt->inputs[0].witness_utxo->script, /* wscript */ NULL, amount /* FIXME pass in psbt fields for tap outputs */); } -u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) +u8 *make_annex_from_script(const tal_t *ctx, const u8 *script) { int ok; struct sha256 result; u8 *preimage_cursor; - u8 *settle_tapscript = make_eltoo_settle_script(tmpctx, settle_tx, /* input_num */ 0); - u64 tapscript_len = tal_count(settle_tapscript); + u64 tapscript_len = tal_count(script); u8 *tapleaf_preimage = tal_arr(ctx, u8, 1 + varint_size(tapscript_len) + tapscript_len); /* Enough space for annex flag plus the one hash we want published */ u8 *annex = tal_arr(ctx, u8, 1 + sizeof(result.u.u8)); @@ -39,7 +38,7 @@ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) preimage_cursor[0] = 0xC0; preimage_cursor++; preimage_cursor += varint_put(preimage_cursor, tapscript_len); - memcpy(preimage_cursor, settle_tapscript, tapscript_len); + memcpy(preimage_cursor, script, tapscript_len); preimage_cursor += tapscript_len; assert(tal_count(tapleaf_preimage) == preimage_cursor - tapleaf_preimage); @@ -51,6 +50,12 @@ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) return annex; } +u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx) +{ + u8 *settle_tapscript = make_eltoo_settle_script(ctx, settle_tx, /* input_num */ 0); + return make_annex_from_script(ctx, settle_tapscript); +} + void tx_add_unbound_input(struct bitcoin_tx *update_tx, struct amount_sat funding_sats, const struct pubkey *inner_pubkey) { int input_num; diff --git a/common/update_tx.h b/common/update_tx.h index a87a0e13c490..b9ad0186b5f6 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -13,6 +13,10 @@ struct bitcoin_outpoint; /* Generates the "state" output for eltoo update transaction, based on the settlement tx */ int tx_add_state_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx); +/* Generates TapLeaf hash of script, with annex byte prepended */ +u8 *make_annex_from_script(const tal_t *ctx, const u8 *script); + +/* Eltoo-specific wrapper for make_annex_from_script */ u8 *make_eltoo_annex(const tal_t *ctx, const struct bitcoin_tx *settle_tx); /* Appends a tx input to the update transaction, without diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 2ad7d0eb5fda..aa3e76fa4f69 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1710,7 +1710,7 @@ static u8 *handle_validate_revocation(struct hsmd_client *c, const u8 *msg_in) return towire_hsmd_validate_revocation_reply(NULL); } -/* FIXME: do more introspection*/ +/* FIXME: do more introspection. split functionality */ static u8 *handle_sign_eltoo_htlc_tx(struct hsmd_client *c, const u8 *msg_in) { @@ -1725,6 +1725,9 @@ static u8 *handle_sign_eltoo_htlc_tx(struct hsmd_client *c, int ret; if (!fromwire_hsmd_sign_eltoo_htlc_timeout_tx(tmpctx, msg_in, + &htlc_tx, + &tapleaf_script) && + !fromwire_hsmd_sign_eltoo_htlc_success_tx(tmpctx, msg_in, &htlc_tx, &tapleaf_script)) { return hsmd_status_malformed_request(c, msg_in); diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index e62a657c06f4..e30dbb3d1580 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -172,7 +172,8 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, const u8 *tapscript, const u8 *control_block, enum eltoo_tx_type *tx_type, - u32 feerate) + u32 feerate, + const void *elem, size_t elem_size) { struct bitcoin_tx *tx; size_t max_weight; @@ -183,6 +184,14 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, /* Modifying later, we need this at the end for witness construction */ enum eltoo_tx_type tx_type_copy = *tx_type; + status_debug("Making tx of type %s with outputs spk: %s, tapscript: %s, control block: %s, inner pubkey: %s", + eltoo_tx_type_name(*tx_type), + tal_hex(NULL, out->scriptPubKey), + tal_hex(NULL, tapscript), + tal_hex(NULL, control_block), + type_to_string(NULL, struct pubkey, + &keyset->inner_pubkey)); + tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); bitcoin_tx_add_input(tx, &out->outpoint, 0 /* sequence */, NULL /* scriptSig */, out->sat, out->scriptPubKey /* scriptPubkey */, @@ -251,13 +260,9 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, tal_hex(tmpctx, msg)); } - if (tx_type_copy == ELTOO_HTLC_TIMEOUT) { - witness = bitcoin_witness_bip340sig_and_element(tx, &sig, NULL /* elem */, - 0 /* elemsize */, tapscript, control_block); - } else if (tx_type_copy == ELTOO_HTLC_SUCCESS) { - witness = bitcoin_witness_bip340sig_and_element(tx, &sig, out->payment_hash.u.u8 /* elem */, - 32 /* elemsize */, tapscript, control_block); - + if (tx_type_copy == ELTOO_HTLC_TIMEOUT || tx_type_copy == ELTOO_HTLC_SUCCESS) { + witness = bitcoin_witness_bip340sig_and_element(tx, &sig, elem, + elem_size, tapscript, control_block); } else { /* Should only be called for HTLC resolutions for now */ abort(); @@ -341,6 +346,7 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, unsigned char tap_tweak_out[32]; u8 *htlc_scripts[2]; u8 *taproot_script; + //u8 *success_annex; htlc_scripts[0] = htlc_success_scripts[i]; htlc_scripts[1] = htlc_timeout_scripts[i]; @@ -350,7 +356,9 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, if (!htlc_success_scripts[i] || !htlc_timeout_scripts[i]) continue; - compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); + compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); + //success_annex = make_annex_from_script(tmpctx, htlc_success_scripts[i]); + //compute_taptree_merkle_root_with_hint(&tap_merkle_root_annex, htlc_timeout_scripts[i], success_annex); bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out); taproot_script = scriptpubkey_p2tr(ctx, &taproot_pubkey); @@ -396,7 +404,7 @@ new_tracked_output(struct tracked_output ***outs, out->proposal = NULL; out->resolved = NULL; if (scriptPubKey) - out->scriptPubKey = tal_dup(out, u8, scriptPubKey); + out->scriptPubKey = tal_dup_talarr(out, u8, scriptPubKey); if (htlc) out->htlc = *htlc; out->htlc_success_tapscript = tal_steal(out, htlc_success_tapscript); @@ -537,7 +545,8 @@ static void eltoo_proposal_meets_depth(struct tracked_output *out) out->htlc_timeout_tapscript, compute_control_block(out, out->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, out->parity_bit), &out->proposal->tx_type, /* over-written if too small to care */ - htlc_feerate); + htlc_feerate, + NULL /* elem */, 0 /* elem_size */); } } else if (out->proposal->tx_type == ELTOO_HTLC_TIMEOUT_TO_THEM) { // Not going to do anything to resolve this proposal here, @@ -1025,9 +1034,11 @@ static void eltoo_handle_preimage(struct tracked_output **outs, outs[i], 0 /* locktime */, outs[i]->htlc_success_tapscript, - compute_control_block(outs[i], outs[i]->htlc_success_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, outs[i]->parity_bit), + compute_control_block(outs[i], outs[i]->htlc_timeout_tapscript /* other_script */, NULL /* annex_hint*/, &keyset->inner_pubkey, outs[i]->parity_bit), &tx_type, /* over-written if too small to care */ - htlc_feerate); + htlc_feerate, + &preimage, + sizeof(preimage)); propose_resolution(outs[i], tx, 0 /* depth_required */, tx_type); } From d226c1c2dedc38e90cd44cb95479cea0d960e8ac Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Dec 2022 14:21:13 -0500 Subject: [PATCH 248/283] Add more belt and suspender check for tapleafs --- channeld/settle_tx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 89cad806262e..5ba8b75b15d4 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,9 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, secp256k1_musig_keyagg_cache keyagg_cache; struct pubkey taproot_pubkey; unsigned char tap_tweak_out[32]; + /* Double-checking calculation */ + u8 *success_annex; + struct sha256 tap_merkle_root_annex; if (sender_side == REMOTE) { receiver_pubkey = &(eltoo_keyset->self_settle_key); @@ -80,6 +84,10 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, printf("Settle's HTLC success script: %s\n", tal_hex(NULL, htlc_scripts[0])); printf("Settle's HTLC timeout script: %s\n", tal_hex(NULL, htlc_scripts[1])); compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); + success_annex = make_annex_from_script(tx, htlc_scripts[0]); + compute_taptree_merkle_root_with_hint(&tap_merkle_root_annex, htlc_scripts[1], success_annex); + assert(memcmp(tap_merkle_root.u.u8, tap_merkle_root_annex.u.u8, sizeof(tap_merkle_root.u.u8)) == 0); + bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, tap_tweak_out); printf("HTLC tweaked pubkey: %s\n", type_to_string(tmpctx, struct pubkey, From 84d69c5b3f6c3205a30a5fc88ff1f2c73c7df113 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Dec 2022 16:22:36 -0500 Subject: [PATCH 249/283] WRONG PUBKEYS OMG --- bitcoin/signature.c | 14 +++++- bitcoin/signature.h | 4 +- channeld/settle_tx.c | 21 ++++---- channeld/test/run-settle_tx.c | 91 +++++++++++++++++++++++++++++++++- common/initial_settlement_tx.c | 17 ++++--- common/update_tx.c | 6 ++- devtools/eltoo_mkfunding.c | 3 +- onchaind/eltoo_onchaind.c | 24 +++++---- 8 files changed, 145 insertions(+), 35 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index a27d6e38d505..716b364bc536 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -210,7 +210,8 @@ void bipmusig_finalize_keys(struct pubkey *agg_pk, const struct pubkey * const* pubkeys, size_t n_pubkeys, const struct sha256 *tap_merkle_root, - unsigned char *tap_tweak_out) + unsigned char *tap_tweak_out, + struct pubkey *inner_pubkey) { int i, ok; unsigned char taptweak_preimage[64]; @@ -243,6 +244,14 @@ void bipmusig_finalize_keys(struct pubkey *agg_pk, assert(ok); + if (inner_pubkey) { + ok = secp256k1_musig_pubkey_get(secp256k1_ctx, + &inner_pubkey->pubkey, + keyagg_cache); + + assert(ok); + } + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &agg_x_key); assert(ok); @@ -822,7 +831,8 @@ u8 *scriptpubkey_eltoo_funding(const tal_t *ctx, const struct pubkey *pubkey1, c pk_ptrs, /* n_pubkeys */ 2, &tap_merkle_root, - tap_tweak_out); + tap_tweak_out, + NULL); return scriptpubkey_p2tr(ctx, &taproot_pubkey); } diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 04fc84a8feb1..e13ec492b3e7 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -143,13 +143,15 @@ void bipmusig_inner_pubkey(struct pubkey *inner_pubkey, * NULL if script path spending is used. * @tap_tweak_out: Set to `t` in `t = hashTapTweak(p || k_m)` of BIP341. N.B. if @tap_merkle_root if NULL, k_m is implicitly the empty string. + * @inner_pubkey: If not NULL, is over-written with untweaked MuSig2 pubkey. */ void bipmusig_finalize_keys(struct pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const struct pubkey * const* pubkeys, size_t n_pubkeys, const struct sha256 *tap_merkle_root, - unsigned char *tap_tweak_out); + unsigned char *tap_tweak_out, + struct pubkey *inner_pubkey); /** * bipmusig_gen_nonce - Generates session id, private diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c index 5ba8b75b15d4..ff5bf011505c 100644 --- a/channeld/settle_tx.c +++ b/channeld/settle_tx.c @@ -57,7 +57,7 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, u8 *taproot_script; struct sha256 tap_merkle_root; const struct pubkey *sender_pubkey, *receiver_pubkey; - const struct pubkey *pubkey_ptrs[2]; + const struct pubkey *funding_pubkey_ptrs[2]; struct amount_sat amount; secp256k1_musig_keyagg_cache keyagg_cache; struct pubkey taproot_pubkey; @@ -74,8 +74,9 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, sender_pubkey = &(eltoo_keyset->self_settle_key); } - pubkey_ptrs[0] = receiver_pubkey; - pubkey_ptrs[1] = sender_pubkey; + /* For inner pubkey calculation */ + funding_pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); + funding_pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8)); @@ -88,8 +89,8 @@ static void add_eltoo_htlc_out(struct bitcoin_tx *tx, compute_taptree_merkle_root_with_hint(&tap_merkle_root_annex, htlc_scripts[1], success_annex); assert(memcmp(tap_merkle_root.u.u8, tap_merkle_root_annex.u.u8, sizeof(tap_merkle_root.u.u8)) == 0); - bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out); + bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, funding_pubkey_ptrs, /* n_pubkeys */ 2, + &tap_merkle_root, tap_tweak_out, NULL); printf("HTLC tweaked pubkey: %s\n", type_to_string(tmpctx, struct pubkey, &taproot_pubkey)); taproot_script = scriptpubkey_p2tr(tx, &taproot_pubkey); @@ -130,7 +131,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, struct htlc *dummy_to_local = (struct htlc *)0x01, *dummy_to_remote = (struct htlc *)0x02; struct pubkey inner_pubkey; - const struct pubkey *pubkey_ptrs[2]; + const struct pubkey *funding_pubkey_ptrs[2]; secp256k1_musig_keyagg_cache keyagg_cache; /* For non-initial settlement tx, we cannot safely * predict prevout, we will rebind this last second, @@ -141,8 +142,8 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, dummy_update_outpoint.n = 0; /* For MuSig aggregation for outputs */ - pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); - pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); + funding_pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); + funding_pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); printf("self update key: %s\n", tal_hexstr(ctx, &eltoo_keyset->self_funding_key, 33)); printf("other update key: %s\n", tal_hexstr(ctx, &eltoo_keyset->other_funding_key, 33)); @@ -152,7 +153,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, &keyagg_cache, - pubkey_ptrs, + funding_pubkey_ptrs, /* n_pubkeys */ 2); @@ -270,7 +271,7 @@ struct bitcoin_tx *settle_tx(const tal_t *ctx, * * * `txin[0]` sequence: upper 8 bits are 0x80, lower 24 bits are upper 24 bits of the obscured settlement number */ - add_settlement_input(tx, &dummy_update_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); + add_settlement_input(tx, &dummy_update_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, funding_pubkey_ptrs); /* Identify the direct outputs (to_us, to_them). */ if (direct_outputs != NULL) { diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index c8610d6fb50f..3bddba58c8a7 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -825,7 +825,7 @@ static int test_htlc_output_creation(void) assert(memcmp(tap_merkle_root.u.u8, tap_merkle_root_annex.u.u8, sizeof(tap_merkle_root.u.u8)) == 0); bipmusig_finalize_keys(&agg_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 1, - &tap_merkle_root, tap_tweak_out); + &tap_merkle_root, tap_tweak_out, NULL); taproot_script = scriptpubkey_p2tr(tmpctx, &agg_pubkey); /* Size of OP_1 script in hex output*/ assert(tal_count(taproot_script) == 1+1+32); @@ -836,6 +836,92 @@ static int test_htlc_output_creation(void) return 0; } +static int test_htlc_output(void) +{ + /* Static example that was failing */ + char success_hex[] = "202dbc0053dd6f3310d84e55eebaacfad53fe3e3ec3c2cecb1cffebdd95fa8063fad82012088a914f66d3a95a552244b5217f8e78c1c14b7a85447de87"; + u8 success_bytes[100]; + char timeout_hex[] = "20abc10666592840eb562f2afaedfac56930b4482ec5d8b61b5a4485b383c2cba8ad016db1"; + u8 timeout_bytes[100]; + char alice_pubkey_hex[] = "02abc10666592840eb562f2afaedfac56930b4482ec5d8b61b5a4485b383c2cba8"; + char bob_pubkey_hex[] = "022dbc0053dd6f3310d84e55eebaacfad53fe3e3ec3c2cecb1cffebdd95fa8063f"; + //char inner_pubkey_hex[] = "034c2ef50ba924c2d69bdb070db119ed4fa8be451a39f272579215820ee55eb518"; + char tweaked_key_hex[] = "032be81a351ad641050787eb265397054ecb025bf904982505cd5fa3446d95162c"; + char wiz_tweaked_key_hex[] = "03ffeeefd39b3fe2515b3c4d299b2df3d711cba1c70fdfc33407ae03b1c09ba4f9"; + struct pubkey alice_pubkey; + struct pubkey bob_pubkey; + struct pubkey tweaked_key; + struct pubkey wiz_tweaked_key; + + u8 *tapleaf_scripts[2]; + struct sha256 tap_merkle_root; + struct pubkey agg_pubkey; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_musig_keyagg_cache keyagg_cache2; + unsigned char tap_tweak_out[32]; + const struct pubkey * pubkey_ptrs[2]; + u8 *merkle_root; + struct pubkey inner_pubkey; + struct pubkey inner_pubkey2; + + pubkey_from_hexstr(alice_pubkey_hex, strlen(alice_pubkey_hex), &alice_pubkey); + pubkey_from_hexstr(bob_pubkey_hex, strlen(bob_pubkey_hex), &bob_pubkey); + //pubkey_from_hexstr(inner_pubkey_hex, strlen(inner_pubkey_hex), &inner_pubkey); + pubkey_from_hexstr(tweaked_key_hex, strlen(tweaked_key_hex), &tweaked_key); + pubkey_from_hexstr(wiz_tweaked_key_hex, strlen(wiz_tweaked_key_hex), &wiz_tweaked_key); + + + printf("Alice key: %s\n", + type_to_string(NULL, struct pubkey, + &alice_pubkey)); + + printf("Bob key: %s\n", + type_to_string(NULL, struct pubkey, + &bob_pubkey)); + + + hex_decode(success_hex, sizeof(success_hex), success_bytes, sizeof(success_bytes)); + hex_decode(timeout_hex, sizeof(timeout_hex), timeout_bytes, sizeof(timeout_bytes)); + + + /* Compute merkle root*/ + tapleaf_scripts[0] = tal_dup_arr(NULL, u8, success_bytes, strlen(success_hex)/2, 0); + tapleaf_scripts[1] = tal_dup_arr(NULL, u8, timeout_bytes, strlen(timeout_hex)/2, 0); + printf("Success script: %s\nTimeout script: %s\n", tal_hex(NULL, tapleaf_scripts[0]), tal_hex(NULL, tapleaf_scripts[1])); + compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 2); + merkle_root = tal_dup_arr(NULL, u8, tap_merkle_root.u.u8, sizeof(tap_merkle_root.u.u8), 0); + + printf("Merkle root hash: %s\n", tal_hex(NULL, merkle_root)); + + /* Compute final tweaked pubkey */ + pubkey_ptrs[0] = &alice_pubkey; + pubkey_ptrs[1] = &bob_pubkey; + bipmusig_finalize_keys(&agg_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, + &tap_merkle_root, tap_tweak_out, &inner_pubkey); + + bipmusig_inner_pubkey(&inner_pubkey2, &keyagg_cache2, pubkey_ptrs, 2); + + printf("Inner key: %s\n", + type_to_string(NULL, struct pubkey, + &inner_pubkey)); + + printf("Inner key 2: %s\n", + type_to_string(NULL, struct pubkey, + &inner_pubkey2)); + + printf("Final key: %s\n", + type_to_string(NULL, struct pubkey, + &agg_pubkey)); + + printf("Scriptwiz' key: %s\n", + type_to_string(NULL, struct pubkey, + &wiz_tweaked_key)); + + + return 0; + +} + int main(int argc, const char *argv[]) { int err = 0; @@ -856,6 +942,9 @@ int main(int argc, const char *argv[]) err |= test_invalid_update_tx(); assert(!err); + err |= test_htlc_output(); + assert(!err); + printf("Tests succeeded!\n"); common_shutdown(); diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c index 5df9e5805b00..130453374ae7 100644 --- a/common/initial_settlement_tx.c +++ b/common/initial_settlement_tx.c @@ -28,7 +28,7 @@ void tx_add_ephemeral_anchor_output(struct bitcoin_tx *tx) } void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint *update_outpoint, - struct amount_sat update_outpoint_sats, u32 shared_delay, const struct pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *pubkey_ptrs[2]) + struct amount_sat update_outpoint_sats, u32 shared_delay, const struct pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *funding_pubkey_ptrs[2]) { u8 *dummy_script; int input_num; @@ -66,10 +66,11 @@ void add_settlement_input(struct bitcoin_tx *tx, const struct bitcoin_outpoint * compute_taptree_merkle_root(&update_merkle_root, settle_and_update_tapscripts, /* num_scripts */ 2); bipmusig_finalize_keys(&update_agg_pk, &update_keyagg_cache, - pubkey_ptrs, + funding_pubkey_ptrs, /* n_pubkeys */ 2, &update_merkle_root, - update_tap_tweak); + update_tap_tweak, + NULL); parity_bit = pubkey_parity(&update_agg_pk); control_block = compute_control_block(tmpctx, settle_and_update_tapscripts[1], /* annex_hint */ NULL, inner_pubkey, parity_bit); @@ -109,7 +110,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, void *dummy_local = (void *)LOCAL, *dummy_remote = (void *)REMOTE; /* There is a direct output and possibly a shared anchor output */ const void *output_order[NUM_SIDES + 1]; - const struct pubkey *pubkey_ptrs[2]; + const struct pubkey *funding_pubkey_ptrs[2]; struct pubkey inner_pubkey; secp256k1_musig_keyagg_cache keyagg_cache; @@ -119,13 +120,13 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, fake_outpoint.n = 0; /* For MuSig aggregation for outputs */ - pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); - pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); + funding_pubkey_ptrs[0] = &(eltoo_keyset->self_funding_key); + funding_pubkey_ptrs[1] = &(eltoo_keyset->other_funding_key); /* Channel-wide inner public key computed here */ bipmusig_inner_pubkey(&inner_pubkey, &keyagg_cache, - pubkey_ptrs, + funding_pubkey_ptrs, /* n_pubkeys */ 2); if (!amount_msat_add(&total_pay, self_pay, other_pay)) @@ -232,7 +233,7 @@ struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, * * `txin[0]` script bytes: 0 */ - add_settlement_input(tx, &fake_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, pubkey_ptrs); + add_settlement_input(tx, &fake_outpoint, update_outpoint_sats, shared_delay, &inner_pubkey, obscured_update_number, funding_pubkey_ptrs); /* Transaction is now ready for broadcast! */ diff --git a/common/update_tx.c b/common/update_tx.c index d5435225d533..688df9226c5c 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -109,7 +109,8 @@ void bind_tx_to_funding_outpoint(struct bitcoin_tx *update_tx, pubkey_ptrs, /* n_pubkeys */ 2, &psbt_tap_merkle_root, - psbt_tap_tweak); + psbt_tap_tweak, + NULL); script_pubkey = scriptpubkey_p2tr(tmpctx, &taproot_pk); @@ -189,7 +190,8 @@ void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, pubkey_ptrs, /* n_pubkeys */ 2, &psbt_tap_merkle_root, - psbt_tap_tweak); + psbt_tap_tweak, + NULL); script_pubkey = scriptpubkey_p2tr(tmpctx, &taproot_pk); diff --git a/devtools/eltoo_mkfunding.c b/devtools/eltoo_mkfunding.c index d4cfe2c17c45..205cf8710ed6 100644 --- a/devtools/eltoo_mkfunding.c +++ b/devtools/eltoo_mkfunding.c @@ -72,7 +72,8 @@ static struct bitcoin_tx *funding_tx_eltoo(const tal_t *ctx, pubkeys, sizeof(pubkeys), /* tap_merkle_root */ NULL, - tap_tweak_out); + tap_tweak_out, + NULL); tx = tx_spending_utxo(ctx, utxo, 1, 0, BITCOIN_TX_DEFAULT_SEQUENCE); diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index e30dbb3d1580..b8ff4476b782 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -184,11 +184,15 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, /* Modifying later, we need this at the end for witness construction */ enum eltoo_tx_type tx_type_copy = *tx_type; - status_debug("Making tx of type %s with outputs spk: %s, tapscript: %s, control block: %s, inner pubkey: %s", + status_debug("Making tx of type %s with outputs spk: %s, tapscript: %s, control block: %s, our funding key: %s, their funding key: %s, inner pubkey: %s", eltoo_tx_type_name(*tx_type), tal_hex(NULL, out->scriptPubKey), tal_hex(NULL, tapscript), tal_hex(NULL, control_block), + type_to_string(NULL, struct pubkey, + &keyset->self_funding_key), + type_to_string(NULL, struct pubkey, + &keyset->other_funding_key), type_to_string(NULL, struct pubkey, &keyset->inner_pubkey)); @@ -340,7 +344,7 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, } for (size_t i = 0; i < tal_count(htlc_success_scripts); i++) { struct sha256 tap_merkle_root; - const struct pubkey *pubkey_ptrs[2]; + const struct pubkey *funding_pubkey_ptrs[2]; struct pubkey taproot_pubkey; secp256k1_musig_keyagg_cache keyagg_cache; unsigned char tap_tweak_out[32]; @@ -350,8 +354,8 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, htlc_scripts[0] = htlc_success_scripts[i]; htlc_scripts[1] = htlc_timeout_scripts[i]; - pubkey_ptrs[0] = &keyset->self_settle_key; - pubkey_ptrs[1] = &keyset->other_settle_key; + funding_pubkey_ptrs[0] = &keyset->self_funding_key; + funding_pubkey_ptrs[1] = &keyset->other_funding_key; if (!htlc_success_scripts[i] || !htlc_timeout_scripts[i]) continue; @@ -359,8 +363,8 @@ static const size_t *eltoo_match_htlc_output(const tal_t *ctx, compute_taptree_merkle_root(&tap_merkle_root, htlc_scripts, /* num_scripts */ 2); //success_annex = make_annex_from_script(tmpctx, htlc_success_scripts[i]); //compute_taptree_merkle_root_with_hint(&tap_merkle_root_annex, htlc_timeout_scripts[i], success_annex); - bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 2, - &tap_merkle_root, tap_tweak_out); + bipmusig_finalize_keys(&taproot_pubkey, &keyagg_cache, funding_pubkey_ptrs, /* n_pubkeys */ 2, + &tap_merkle_root, tap_tweak_out, NULL); taproot_script = scriptpubkey_p2tr(ctx, &taproot_pubkey); status_debug("Reconstructed HTLC script %s for comparison with output: %s", tal_hex(NULL, taproot_script), tal_hex(NULL, script)); @@ -1526,7 +1530,7 @@ static void handle_unilateral(const struct tx_parts *tx, struct amount_asset asset; struct amount_sat amt; struct tracked_output *out; - const struct pubkey *pubkey_ptrs[2]; + const struct pubkey *funding_pubkey_ptrs[2]; secp256k1_musig_keyagg_cache keyagg_cache; /* State output will match index */ @@ -1555,11 +1559,11 @@ static void handle_unilateral(const struct tx_parts *tx, NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); /* Fill out inner pubkey to complete re-binding of update transactions going forward */ - pubkey_ptrs[0] = &keyset->self_funding_key; - pubkey_ptrs[1] = &keyset->other_funding_key; + funding_pubkey_ptrs[0] = &keyset->self_funding_key; + funding_pubkey_ptrs[1] = &keyset->other_funding_key; bipmusig_inner_pubkey(&keyset->inner_pubkey, &keyagg_cache, - pubkey_ptrs, + funding_pubkey_ptrs, /* n_pubkeys */ 2); /* FIXME I think this logic will be the same in main loop under output_spent */ From 144c9dbe4974b81cd41975efbe18764862f525f2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Dec 2022 16:24:12 -0500 Subject: [PATCH 250/283] F --- channeld/test/run-settle_tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index 3bddba58c8a7..f50dd0b86644 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -843,8 +843,8 @@ static int test_htlc_output(void) u8 success_bytes[100]; char timeout_hex[] = "20abc10666592840eb562f2afaedfac56930b4482ec5d8b61b5a4485b383c2cba8ad016db1"; u8 timeout_bytes[100]; - char alice_pubkey_hex[] = "02abc10666592840eb562f2afaedfac56930b4482ec5d8b61b5a4485b383c2cba8"; - char bob_pubkey_hex[] = "022dbc0053dd6f3310d84e55eebaacfad53fe3e3ec3c2cecb1cffebdd95fa8063f"; + char alice_pubkey_hex[] = "02e3bd38009866c9da8ec4aa99cc4ea9c6c0dd46df15c61ef0ce1f271291714e57"; + char bob_pubkey_hex[] = "02324266de8403b3ab157a09f1f784d587af61831c998c151bcc21bb74c2b2314b"; //char inner_pubkey_hex[] = "034c2ef50ba924c2d69bdb070db119ed4fa8be451a39f272579215820ee55eb518"; char tweaked_key_hex[] = "032be81a351ad641050787eb265397054ecb025bf904982505cd5fa3446d95162c"; char wiz_tweaked_key_hex[] = "03ffeeefd39b3fe2515b3c4d299b2df3d711cba1c70fdfc33407ae03b1c09ba4f9"; From 3029ab9482941c70aa38eaf95d7f102b7c984462 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 15 Dec 2022 17:07:11 -0500 Subject: [PATCH 251/283] HTLC txns are being mined/replaced --- bitcoin/script.c | 4 ++-- bitcoin/signature.c | 4 ++-- contrib/pyln-testing/pyln/testing/utils.py | 1 + hsmd/libhsmd.c | 2 +- onchaind/eltoo_onchaind.c | 4 +++- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 81b8be7ae44f..e57d71f31c08 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -618,8 +618,8 @@ u8 **bitcoin_witness_bip340sig_and_element(const tal_t *ctx, witness[3] = tal_dup_talarr(witness, u8, control_block); witness[2] = tal_dup_talarr(witness, u8, tapscript); - witness[1] = tal_dup_arr(witness, u8, elem, elemsize, 0); - witness[0] = stack_bip340sig(witness, sig, SIGHASH_DEFAULT); + witness[1] = stack_bip340sig(witness, sig, SIGHASH_DEFAULT); + witness[0] = tal_dup_arr(witness, u8, elem, elemsize, 0); return witness; } else { diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 716b364bc536..3c25c25de425 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -461,13 +461,13 @@ void sign_tx_taproot_input(const struct bitcoin_tx *tx, struct privkey privkey; /* FIXME assert sighashes we actually support assert(sighash_type_valid(sighash_type)); */ - bitcoin_tx_taproot_hash_for_sig(tx, input_index, sighash_type, tapleaf_script, NULL /* annex */, &hash); + bitcoin_tx_taproot_hash_for_sig(tx, input_index, sighash_type, tapleaf_script, NULL /* annex */, &hash); /* TODO just have it take keypair? */ ret = secp256k1_keypair_xonly_pub(secp256k1_ctx, &pubkey, NULL /* pk_parity */, key_pair); assert(ret); x_key.pubkey = pubkey; - dump_tx("Signing", tx, input_index, tapleaf_script, NULL /* key */, &x_key, &hash); + dump_tx("Signing taproot input:", tx, input_index, tapleaf_script, NULL /* key */, &x_key, &hash); ret = secp256k1_keypair_sec(secp256k1_ctx, privkey.secret.data, key_pair); assert(ret); bip340_sign_hash(&privkey, &hash, sig); diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 9629ce5f5c3c..93fd5b56a789 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -387,6 +387,7 @@ def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None): '-txindex', '-nowallet', '-addresstype=bech32', + '-debug=1', ] # Only for eltoo testing diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index aa3e76fa4f69..c3ace90b244d 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1746,7 +1746,7 @@ static u8 *handle_sign_eltoo_htlc_tx(struct hsmd_client *c, sign_tx_taproot_input(htlc_tx, 0 /* input_index */, - SIGHASH_ALL, + SIGHASH_DEFAULT, tapleaf_script, &key_pair, &sig); diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index b8ff4476b782..13f069270acc 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -213,8 +213,10 @@ static struct bitcoin_tx *bip340_tx_to_us(const tal_t *ctx, tal_count(control_block) + 1 + /* tapscript size*/ tal_count(tapscript) + + 1 + /* elem size */ + elem_size + 1 + /* signature size */ - 65 /* BIP340 sig with non-default sighash flag */; + 64 /* BIP340 sig with default sighash flag */; /* FIXME elements support */ max_weight += 0; From a171fdb0bd692b26fe6655faad11311349abb207 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 16 Dec 2022 15:00:11 -0500 Subject: [PATCH 252/283] Fix preimage fetching from success tx --- contrib/pyln-testing/pyln/testing/utils.py | 4 +- onchaind/eltoo_onchaind.c | 5 +- tests/test_closing.py | 100 +++++---------------- 3 files changed, 28 insertions(+), 81 deletions(-) diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 93fd5b56a789..ce1ebd37e6da 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -88,7 +88,7 @@ def wait_for(success, timeout=TIMEOUT): while not success(): time_left = start_time + timeout - time.time() if time_left <= 0: - raise ValueError("Timeout while waiting for {}", success) + raise ValueError("Timeout while waiting for {}".format(success)) time.sleep(min(interval, time_left)) interval *= 2 if interval > 5: @@ -1111,7 +1111,7 @@ def wait_for_onchaind_broadcast(self, name, resolve=None): """Wait for onchaind to drop tx name to resolve (if any)""" if resolve: r = self.daemon.wait_for_log('Broadcasting {} .* to resolve {}' - .format(name, resolve)) + .format(name, resolve, 1)) else: r = self.daemon.wait_for_log('Broadcasting {} .* to resolve ' .format(name)) diff --git a/onchaind/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c index 13f069270acc..05616c065754 100644 --- a/onchaind/eltoo_onchaind.c +++ b/onchaind/eltoo_onchaind.c @@ -848,7 +848,7 @@ static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, /* BOLTXX * The recipient node can redeem the HTLC with the witness: * - * + * */ if (tx_parts->inputs[htlc_outpoint->n]->witness->num_items != 4) /* +2 for script/control block */ status_failed(STATUS_FAIL_INTERNAL_ERROR, @@ -857,8 +857,7 @@ static void handle_eltoo_htlc_onchain_fulfill(struct tracked_output *out, output_type_name(out->output_type), tx_parts->inputs[htlc_outpoint->n]->witness->num_items); - /* FIXME figure out proper index */ - preimage_item = &tx_parts->inputs[htlc_outpoint->n]->witness->items[1]; + preimage_item = &tx_parts->inputs[htlc_outpoint->n]->witness->items[0]; } else status_failed(STATUS_FAIL_INTERNAL_ERROR, "onchain_fulfill for %s/%s?", diff --git a/tests/test_closing.py b/tests/test_closing.py index e62625e488d3..6faaa9c81422 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -16,6 +16,7 @@ import re import subprocess import threading +import time import unittest # In msats @@ -799,17 +800,16 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): bitcoind.rpc.prioritisetransaction(l1_update_details["txid"], 0, 100000000) bitcoind.rpc.prioritisetransaction(l1_settle_details["txid"], 0, 100000000) bitcoind.rpc.sendrawtransaction(l1_update_tx) + # Mine and mature the update tx bitcoind.generate_block(6) - from pdb import set_trace - set_trace() - # Symmetrical transactions(!), symmetrical state, mostly l1.daemon.wait_for_log(' to ONCHAIN') l2.daemon.wait_for_log(' to ONCHAIN') - needle = l2.daemon.logsearch_start + needle_1 = l1.daemon.logsearch_start + needle_2 = l2.daemon.logsearch_start # The settle transaction should hit the mempool for both! l1.wait_for_onchaind_broadcast('ELTOO_SETTLE', @@ -819,87 +819,35 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): # Mine it, then we should see HTLC resolution hit the mempool by the receiver # since timeout hasn't occured yet, as well as a timeout tx after X blocks + assert len(bitcoind.rpc.getrawmempool()) == 1 bitcoind.generate_block(1) + assert len(bitcoind.rpc.getrawmempool()) == 0 + while len(bitcoind.rpc.getrawmempool()) != 1: + time.sleep(0.1) - l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', - 'ELTOO_SETTLE/THEIR_HTLC') - - # Brings its own fees, no CPFP required - l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', - 'ELTOO_SETTLE/OUR_HTLC') - - # Now that fulfillment is in mempool, we can censor it - - # Then mine blocks until HTLC timeout path can be taken by offerer - - # Timeout should knock out the censored fulfillment tx - - # 100 blocks later, all resolved - - return - - l2.daemon.logsearch_start = needle - l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', - 'THEIR_REVOKED_UNILATERAL/OUR_HTLC') - - l2.daemon.logsearch_start = needle - l2.daemon.wait_for_log('Ignoring output.*: THEIR_REVOKED_UNILATERAL/OUTPUT_TO_US') - - # FIXME: test HTLC tx race! - - # 100 blocks later, all resolved. - bitcoind.generate_block(100) - - sync_blockheight(bitcoind, [l1, l2]) - wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 0) - - # Do one last pass over the logs to extract the reactions l2 sent - l2.daemon.logsearch_start = needle - needles = [ - r'Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by THEIR_REVOKED_UNILATERAL .([a-f0-9]{64}).', - r'Resolved THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM by our proposal OUR_PENALTY_TX .([a-f0-9]{64}).', - r'Resolved THEIR_REVOKED_UNILATERAL/OUR_HTLC by our proposal OUR_PENALTY_TX .([a-f0-9]{64}).', - ] - matches = list(map(l2.daemon.is_in_log, needles)) - - # Now extract the txids for these responses - txids = set([re.search(r'\(([0-9a-f]{64})\)', m).group(1) for m in matches]) - - # We should have one confirmed output for each of the above reactions in - # the list of funds we own. - outputs = l2.rpc.listfunds()['outputs'] + # Right now this test is racey, we don't know which tx + # will be mined. Probably can take first in mempool + # check what kind it is, run the proper test + # censor it, mine a block to have it RBF'd + # and check the other tx out - assert [o['status'] for o in outputs] == ['confirmed'] * 3 - assert set([o['txid'] for o in outputs]) == txids - assert account_balance(l1, channel_id) == 0 - assert account_balance(l2, channel_id) == 0 + from pdb import set_trace + set_trace() - # l1 loses all of their channel balance to the peer, as penalties - expected_1 = { - '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], - 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], - 'B': [('external', ['penalty'], None, None), ('external', ['penalty'], None, None), ('external', ['penalty'], None, None)], - } + bitcoind.generate_block(1) - # l2 sweeps all of l1's closing outputs - expected_2 = { - 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], - 'B': [('wallet', ['deposit'], None, None), ('cid1', ['penalty'], ['to_wallet'], 'C'), ('cid1', ['penalty'], ['to_wallet'], 'D')], - 'C': [('wallet', ['deposit'], None, None)], - 'D': [('wallet', ['deposit'], None, None)] - } - if anchor_expected(): - expected_1['B'].append(('external', ['anchor'], None, None)) - expected_2['B'].append(('external', ['anchor'], None, None)) - expected_1['B'].append(('wallet', ['anchor'], None, None)) - expected_2['B'].append(('wallet', ['anchor'], None, None)) + #l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', + # 'ELTOO_SETTLE/THEIR_HTLC') + #l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', + # 'ELTOO_SETTLE/OUR_HTLC') - # We use a subset of tags in expected_2 that are used in expected_1 - tags = check_utxos_channel(l1, [channel_id], expected_1) - check_utxos_channel(l2, [channel_id], expected_2, tags) + + # Mine enough blocks to closed out onchaind + bitcoind.generate_block(99) + # FIXME Check wallet related things, balances @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') From 6fce49e72b85de80870cf7563ee22c9d12301ce2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 16 Dec 2022 15:27:11 -0500 Subject: [PATCH 253/283] Test runs until end... plus memory leaks --- tests/test_closing.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index 6faaa9c81422..270d0d840611 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -835,19 +835,37 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): from pdb import set_trace set_trace() - bitcoind.generate_block(1) + winning_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) + if len(winning_tx['vin'][0]['txinwitness']) == 4: + # Check requires tx to be in mempool to return + l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', + 'ELTOO_SETTLE/THEIR_HTLC') + else: + assert len(winning_tx['vin'][0]['txinwitness']) == 3 + l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', + 'ELTOO_SETTLE/OUR_HTLC') + # block the stream to allow us to put HTLC to chain + # following block post-rebroadcast of SUCCESS + bitcoind.rpc.prioritisetransaction(winning_tx['txid'], 0, -100000000) + bitcoind.generate_block(1) + l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', + 'ELTOO_SETTLE/THEIR_HTLC') + # Should have SUCCESS + while len(bitcoind.rpc.getrawmempool()) != 1: + time.sleep(0.1) - #l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', - # 'ELTOO_SETTLE/THEIR_HTLC') - #l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', - # 'ELTOO_SETTLE/OUR_HTLC') + success_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) + assert len(success_tx['vin'][0]['txinwitness']) == 4 + bitcoind.generate_block(1) + + # FIXME Check wallet related things, balances + # FIXME The mounds of memleaks # Mine enough blocks to closed out onchaind bitcoind.generate_block(99) - # FIXME Check wallet related things, balances @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') From 862633f1b091b8b3581832eefe577bc8ce62d031 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 16 Dec 2022 15:34:51 -0500 Subject: [PATCH 254/283] Test runs until end... plus memory leaks --- tests/test_closing.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index 270d0d840611..e9aba05cb677 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -832,9 +832,6 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): # censor it, mine a block to have it RBF'd # and check the other tx out - from pdb import set_trace - set_trace() - winning_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) if len(winning_tx['vin'][0]['txinwitness']) == 4: # Check requires tx to be in mempool to return From aa4cea38190ca7dcc7b5861564cc74a7cec5a986 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 16 Dec 2022 15:39:40 -0500 Subject: [PATCH 255/283] Test runs until end... plus memory leaks --- tests/test_closing.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index e9aba05cb677..83761e491473 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -732,7 +732,7 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): # DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_closing.py -k test_eltoo_outhtlc @pytest.mark.developer("needs dev-disable-commit-after") def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): - """Test penalty transaction with an outgoing HTLC""" + """Test HTLC resolution via eltoo_onchaind""" # We track channel balances, to verify that accounting is ok. coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') @@ -781,17 +781,6 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): assert l1_update_tx == l2_update_tx assert l1_settle_tx == l2_settle_tx - # We can't them continue, since we'll end up blowing away old HTLCs (or having to deal with - # old state we didn't keep) - # l1.rpc.dev_reenable_commit(l2.info['id']) - - # Thread should complete. -# t.result(timeout=10) - - # Make sure both sides got revoke_and_ack for final. -# l1.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') -# l2.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') - # Now we really mess things up! # FIXME we need real anchor CPFP + package relay to pay fees From da845e0eeec9c5615593e6b8324871a5e6d20f51 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 19 Dec 2022 11:08:18 -0500 Subject: [PATCH 256/283] cleanup htlc eltoo test --- tests/test_closing.py | 68 ++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index 83761e491473..0f62051bacec 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -16,7 +16,6 @@ import re import subprocess import threading -import time import unittest # In msats @@ -729,9 +728,9 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): check_utxos_channel(l2, [channel_id], expected_2, tags) # Example flags to run test -# DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_closing.py -k test_eltoo_outhtlc +# DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_closing.py -k test_eltoo_htlc @pytest.mark.developer("needs dev-disable-commit-after") -def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): +def test_eltoo_htlc(node_factory, bitcoind, executor, chainparams): """Test HTLC resolution via eltoo_onchaind""" # We track channel balances, to verify that accounting is ok. @@ -806,40 +805,37 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): l2.wait_for_onchaind_broadcast('ELTOO_SETTLE', 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') - # Mine it, then we should see HTLC resolution hit the mempool by the receiver - # since timeout hasn't occured yet, as well as a timeout tx after X blocks assert len(bitcoind.rpc.getrawmempool()) == 1 + + # We're going to disable transaction relay for the SUCCESS transaction + # To allow us to test broadcast of one transaction at a time + def censoring_sendrawtx(r): + return {'id': r['id'], 'result': {}} + + l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', censoring_sendrawtx) + + # Mine settle tx, then we should see HTLC timeout resolution hit the mempool by the receiver bitcoind.generate_block(1) - assert len(bitcoind.rpc.getrawmempool()) == 0 - - while len(bitcoind.rpc.getrawmempool()) != 1: - time.sleep(0.1) - - # Right now this test is racey, we don't know which tx - # will be mined. Probably can take first in mempool - # check what kind it is, run the proper test - # censor it, mine a block to have it RBF'd - # and check the other tx out - - winning_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) - if len(winning_tx['vin'][0]['txinwitness']) == 4: - # Check requires tx to be in mempool to return - l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', - 'ELTOO_SETTLE/THEIR_HTLC') - else: - assert len(winning_tx['vin'][0]['txinwitness']) == 3 - l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', - 'ELTOO_SETTLE/OUR_HTLC') - # block the stream to allow us to put HTLC to chain - # following block post-rebroadcast of SUCCESS - bitcoind.rpc.prioritisetransaction(winning_tx['txid'], 0, -100000000) - bitcoind.generate_block(1) - l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', - 'ELTOO_SETTLE/THEIR_HTLC') - # Should have SUCCESS - while len(bitcoind.rpc.getrawmempool()) != 1: - time.sleep(0.1) + wait_for(lambda: len(bitcoind.rpc.getrawmempool()) == 1) + + timeout_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) + assert len(timeout_tx['vin'][0]['txinwitness']) == 3 + l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', + 'ELTOO_SETTLE/OUR_HTLC') + # Stop mining of tx for this next block + bitcoind.rpc.prioritisetransaction(timeout_tx['txid'], 0, -100000000) + # Allow SUCCESS tx to hit mempool next block + l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', None) + + bitcoind.generate_block(1) + + # Wait until known tx is swapped out via RBF + wait_for(lambda: bitcoind.rpc.getrawmempool() != [timeout_tx['txid']]) + + # Now that it's in mempool, do the log/pool check + l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', + 'ELTOO_SETTLE/THEIR_HTLC') success_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) assert len(success_tx['vin'][0]['txinwitness']) == 4 @@ -851,8 +847,8 @@ def test_eltoo_outhtlc(node_factory, bitcoind, executor, chainparams): # Mine enough blocks to closed out onchaind bitcoind.generate_block(99) - - + l1.daemon.wait_for_log('onchaind complete, forgetting peer') + l2.daemon.wait_for_log('onchaind complete, forgetting peer') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') From 22701bacca7fe34a76dcabbdd20d99c5037fa36e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 19 Dec 2022 11:09:18 -0500 Subject: [PATCH 257/283] cleanup htlc eltoo test --- tests/test_closing.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index 0f62051bacec..5862d62d7f94 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -830,10 +830,7 @@ def censoring_sendrawtx(r): bitcoind.generate_block(1) - # Wait until known tx is swapped out via RBF - wait_for(lambda: bitcoind.rpc.getrawmempool() != [timeout_tx['txid']]) - - # Now that it's in mempool, do the log/pool check + # Should hit mempool; do the log/pool check l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', 'ELTOO_SETTLE/THEIR_HTLC') From c2007686824b4e9fb226530cf248089e2ef1f493 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 19 Dec 2022 11:41:45 -0500 Subject: [PATCH 258/283] Tests for all working scenarioes --- contrib/startup_regtest.sh | 1 + tests/test_closing.py | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index b016571cd1bb..6e98f5978d19 100755 --- a/contrib/startup_regtest.sh +++ b/contrib/startup_regtest.sh @@ -148,6 +148,7 @@ start_ln() { echo " bt-cli, stop_ln" } +# These two scenarios are now covered in black box testing onchain_ln() { # Test eltoo_onchaind handling l1addr=$(l1-cli newaddr | jq -r .bech32) diff --git a/tests/test_closing.py b/tests/test_closing.py index 5862d62d7f94..4fe1b209eb27 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -727,11 +727,36 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) +def test_eltoo_unannounced_hop(node_factory, bitcoind): + """Test eltoo payments work over hops""" + + # Make three nodes, two private channels + l1, l2, l3 = node_factory.line_graph(3, + opts=[{}, {}, {}], announce_channels=False) # Channel announcement unsupported, doing private hops) + channel_id = first_channel_id(l1, l2) + channel_id = first_channel_id(l1, l2) + + # l1 can pay l2 + l1.pay(l2, 100000*SAT) + + # l2 can pay back l1 + l1.pay(l2, 5000*SAT) + + # l2 can pay l3 + l2.pay(l3, 200000*SAT) + + # With proper hints exposed, + # l1 can pay l3 + scid = l3.rpc.listchannels()['channels'][0]['short_channel_id'] + invoice = l3.rpc.invoice(msatoshi=10000, label='hop', description='test', exposeprivatechannels=scid) + l1.rpc.pay(invoice['bolt11']) + wait_for(lambda: l3.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(200010000)) + # Example flags to run test # DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_closing.py -k test_eltoo_htlc @pytest.mark.developer("needs dev-disable-commit-after") def test_eltoo_htlc(node_factory, bitcoind, executor, chainparams): - """Test HTLC resolution via eltoo_onchaind""" + """Test HTLC resolution via eltoo_onchaind after a single successful payment""" # We track channel balances, to verify that accounting is ok. coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') From f7e0aecc7cd44f44aedcce5509d509f6e74029ef Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 19 Dec 2022 14:04:14 -0500 Subject: [PATCH 259/283] Silence memory leaks --- connectd/multiplex.c | 2 +- hsmd/libhsmd.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/connectd/multiplex.c b/connectd/multiplex.c index c8a1b2335bc5..44548ce30156 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -1047,7 +1047,7 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, if (!subd) { enum peer_wire t = fromwire_peektype(decrypted); status_peer_debug(&peer->id, "Activating for message %s, channel %s", - peer_wire_name(t), type_to_string(subd, struct channel_id, &channel_id)); + peer_wire_name(t), type_to_string(tmpctx, struct channel_id, &channel_id)); subd = activate_subd(peer, &t, &channel_id); if (!subd) return io_close(peer_conn); diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index c3ace90b244d..f867bd852a08 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -836,9 +837,10 @@ static u8 *handle_gen_nonce(struct hsmd_client *c, if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) return hsmd_status_malformed_request(c, msg_in); - /* FIXME Saw a strange memleak race, fix this reasoning */ /* Shouldn't need to be freed, aside from channel teardown */ new_musig_state = tal(NULL, struct musig_state); + /* FIXME this will allow leaks... let's free the map before shutdown somehow */ + tal_steal(NULL, notleak(new_musig_state)); new_musig_state->channel_id = channel_id; /* Generate privkey for additional nonce entropy */ From 6258943e09b7ee8ba975cc7deb8d58649ab78516 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 19 Dec 2022 15:17:16 -0500 Subject: [PATCH 260/283] f --- tests/test_closing.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index 4fe1b209eb27..1bdace04e5f0 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -733,8 +733,6 @@ def test_eltoo_unannounced_hop(node_factory, bitcoind): # Make three nodes, two private channels l1, l2, l3 = node_factory.line_graph(3, opts=[{}, {}, {}], announce_channels=False) # Channel announcement unsupported, doing private hops) - channel_id = first_channel_id(l1, l2) - channel_id = first_channel_id(l1, l2) # l1 can pay l2 l1.pay(l2, 100000*SAT) From 1ef38366cb3095097d6952f36e3311a28882f58d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 20 Dec 2022 12:19:36 -0500 Subject: [PATCH 261/283] Implement turn-taking ala Simplified Update --- channeld/eltoo_channeld.c | 182 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 6 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index c4376baf2874..357aeb8396f7 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -125,6 +125,10 @@ struct eltoo_peer { bool stfu_sent[NUM_SIDES]; /* Updates master asked, which we've deferred while quiescing */ struct msg_queue *update_queue; + /* Who's turn is it? */ + enum side turn; + /* Can we yield? i.e. have we not yet sent updates during our turn? (or not our turn at all) */ + bool can_yield; #endif #if DEVELOPER @@ -271,14 +275,30 @@ static void handle_stfu(struct eltoo_peer *peer, const u8 *stfu) maybe_send_stfu(peer); } +static bool is_our_turn(const struct eltoo_peer *peer) +{ + return peer->turn == LOCAL; +} + /* Returns true if we queued this for later handling (steals if true) */ static bool handle_master_request_later(struct eltoo_peer *peer, const u8 *msg) { if (peer->stfu) { + status_debug("queueing master update for later..."); msg_enqueue(peer->update_queue, take(msg)); return true; - } - return false; + } else if (!is_our_turn(peer)) { + /* We use a noop update to request they yield once, + then only queue up later messages while waiting. */ + if (msg_queue_length(peer->update_queue) == 0) { + u8 *noop = towire_update_noop(NULL, &peer->channel_id); + peer_write(peer->pps, take(noop)); + } + status_debug("queueing master update for later turn..."); + msg_enqueue(peer->update_queue, take(msg)); + return true; + } + return false; } #else /* !EXPERIMENTAL_FEATURES */ @@ -770,6 +790,14 @@ static u8 *master_wait_sync_reply(const tal_t *ctx, return reply; } +static void change_turn(struct eltoo_peer *peer, enum side turn) +{ + assert(peer->turn == !turn); + peer->turn = turn; + peer->can_yield = true; + status_debug("turn is now %s", side_to_str(turn)); +} + static void send_update(struct eltoo_peer *peer) { u8 *msg; @@ -913,6 +941,8 @@ static void send_update(struct eltoo_peer *peer) status_debug("Sending update_sig"); peer->next_index++; + /* Cannot yield after sending an update */ + peer->can_yield = false; msg = towire_update_signed(NULL, &peer->channel_id, &peer->channel->eltoo_keyset.last_committed_state.self_psig, @@ -921,6 +951,17 @@ static void send_update(struct eltoo_peer *peer) maybe_send_shutdown(peer); + /* + * - MUST give up its turn when: + * - sending `update_signed` + */ + if (is_our_turn(peer)){ + change_turn(peer, REMOTE); + } else { + /* We are not doing optimistic updates */ + status_broken("We're proposing updates out of turn?"); + } + /* Timer now considered expired, you can add a new one. */ peer->commit_timer = NULL; start_update_timer(peer); @@ -1176,6 +1217,16 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) status_debug("Failed to increment HTLC state after sending ACK..."); }*/ + /* + * - MUST accept its turn when: + * - receiving `update_signed` + */ + if (!is_our_turn(peer)) { + change_turn(peer, LOCAL); + } else { + status_broken("We are processing remote's update during our turn?"); + } + /* Tell master about this exchange, then the peer. Note: We do not persist nonces, as they will not outlive a single connection to peer! */ @@ -1534,6 +1585,90 @@ static void handle_unexpected_reestablish(struct eltoo_peer *peer, const u8 *msg &channel_id)); } +/* Simplified Update machinery starts */ + +static bool allow_their_turn(struct eltoo_peer *peer) +{ + /* BOLT-option_simplified_update #2: + * + * - During this node's turn: + * - if it receives an update message: + * - if it has sent its own update: + * - MUST ignore the message + * - otherwise: + * - MUST reply with `yield` and process the message. + */ + if (peer->turn == REMOTE) + return true; + + if (peer->turn == LOCAL && peer->can_yield) { + peer_write(peer->pps, + take(towire_yield(NULL, + &peer->channel_id))); + /* BOLT-option_simplified_update #2: + * - MUST give up its turn when: + *... + * - sending a `yield` + */ + change_turn(peer, REMOTE); + return true; + } + + /* Sorry, we've already sent updates. */ + status_debug("Sorry, ignoring your message"); + return false; +} + +static void handle_yield(struct eltoo_peer *peer, const u8 *yield) +{ + struct channel_id channel_id; + + if (!fromwire_yield(yield, &channel_id)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad yield %s", tal_hex(peer, yield)); + + /* is this lightningd's fault? */ + if (!channel_id_eq(&channel_id, &peer->channel_id)) { + peer_failed_err(peer->pps, &channel_id, + "Wrong yield channel_id: expected %s, got %s", + type_to_string(tmpctx, struct channel_id, + &peer->channel_id), + type_to_string(tmpctx, struct channel_id, + &channel_id)); + } + + /* Sanity check; change_turn assumes this has been caught */ + if (is_our_turn(peer)) { + peer_failed_err(peer->pps, &channel_id, + "yield when it's not your turn!"); + } + + /* BOLT-option_simplified_update #2: + * - MUST accept its turn when: + * - receiving `revoke_and_ack` + * - receiving a `yield` + */ + change_turn(peer, LOCAL); + + /* That will unplug the dequeue from update_queue */ +} + +static bool modifies_channel_tx_or_nop(enum peer_wire type) +{ + switch (type) { + case WIRE_UPDATE_ADD_HTLC: + case WIRE_UPDATE_FULFILL_HTLC: + case WIRE_UPDATE_FAIL_HTLC: + case WIRE_UPDATE_FAIL_MALFORMED_HTLC: + case WIRE_UPDATE_NOOP: + return true; + default: + return false; + }; +} + +/* Simplified Update machinery ends */ + static void peer_in(struct eltoo_peer *peer, const u8 *msg) { enum peer_wire type = fromwire_peektype(msg); @@ -1556,6 +1691,14 @@ static void peer_in(struct eltoo_peer *peer, const u8 *msg) } } + /* Early return from messages we will not service. + This will send off a yield message as + appropriate when it's our turn and are willing + to service it. */ + if (modifies_channel_tx_or_nop(type) && !allow_their_turn(peer)) { + return; + } + switch (type) { case WIRE_FUNDING_LOCKED_ELTOO: handle_peer_funding_locked_eltoo(peer, msg); @@ -1597,10 +1740,14 @@ static void peer_in(struct eltoo_peer *peer, const u8 *msg) case WIRE_SHUTDOWN: handle_peer_shutdown(peer, msg); return; - /* FIXME below */ case WIRE_UPDATE_NOOP: + /* + *- if it received `update_noop`: + * - MUST otherwise ignore the message + */ + return; case WIRE_YIELD: - /* FIXME handle these messages */ + handle_yield(peer, msg); return; #if EXPERIMENTAL_FEATURES @@ -1687,12 +1834,14 @@ static void send_fail_or_fulfill(struct eltoo_peer *peer, const struct htlc *h) "HTLC %"PRIu64" state %s not failed/fulfilled", h->id, htlc_state_name(h->state)); peer_write(peer->pps, take(msg)); + peer->can_yield = false; } /* FIXME Reconnect fun! Let's compile first. :) */ static void peer_reconnect(struct eltoo_peer *peer, bool reestablish_only) { + /* Need to determine who's turn it is here */ } /* ignores the funding_depth unless depth >= minimum_depth @@ -1808,6 +1957,7 @@ static void handle_offer_htlc(struct eltoo_peer *peer, const u8 *inmsg) 0, ""); wire_sync_write(MASTER_FD, take(msg)); peer->htlc_id++; + peer->can_yield = false; return; case CHANNEL_ERR_INVALID_EXPIRY: failwiremsg = towire_incorrect_cltv_expiry(inmsg, cltv_expiry, get_cupdate(peer)); @@ -2328,11 +2478,17 @@ static void init_channel(struct eltoo_peer *peer) /* from now we need keep watch over WIRE_CHANNELD_FUNDING_DEPTH */ peer->depth_togo = minimum_depth; + /* We don't send updates out of turn so this is always true */ + peer->can_yield = true; + /* OK, now we can process peer messages. */ if (reconnected) peer_reconnect(peer, reestablish_only); - else + else { assert(!reestablish_only); + peer->turn = + node_id_cmp(&(peer->node_ids[LOCAL]), &(peer->node_ids[REMOTE])) < 0 ? LOCAL : REMOTE; + } /* If we have a messages to send, send them immediately */ if (fwd_msg) @@ -2371,6 +2527,7 @@ int main(int argc, char *argv[]) peer->stfu = false; peer->stfu_sent[LOCAL] = peer->stfu_sent[REMOTE] = false; peer->update_queue = msg_queue_new(peer, false); + /* peer->our_turn is decided in init_channel */ #endif /* We send these to HSM to get real signatures; don't have valgrind @@ -2407,7 +2564,7 @@ int main(int argc, char *argv[]) /* Free any temporary allocations */ clean_tmpctx(); - /* For simplicity, we process one event at a time. */ + /* For simplicity, we process one event from master at a time. */ msg = msg_dequeue(peer->from_master); if (msg) { status_debug("Now dealing with deferred %s", @@ -2418,6 +2575,19 @@ int main(int argc, char *argv[]) continue; } + /* And one at a time from peers */ + if (!peer->stfu && is_our_turn(peer) + && (msg = msg_dequeue(peer->update_queue))) { + status_debug("Now dealing with deferred update %s", + channeld_wire_name( + fromwire_peektype(msg))); + req_in(peer, msg); + tal_free(msg); + continue; + } else if (msg_queue_length(peer->update_queue)) { + status_debug("Ignoring deferred updates..."); + } + expired = timers_expire(&peer->timers, now); if (expired) { timer_expired(expired); From 5bc8c9ce694b13b3189fe403eb95e58c5ddf3a9a Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 21 Dec 2022 12:20:46 -0500 Subject: [PATCH 262/283] Fixup eltoo_channeld transaction tracking --- channeld/eltoo_channeld.c | 52 +++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 357aeb8396f7..6d3cb431a33f 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -185,6 +185,20 @@ static void billboard_update(const struct eltoo_peer *peer) peer_billboard(false, update); } +/* Moves state in lockstep */ +static void migrate_committed_to_complete(struct eltoo_peer *peer) +{ + peer->channel->eltoo_keyset.last_complete_state = peer->channel->eltoo_keyset.last_committed_state; + tal_free(peer->channel->eltoo_keyset.complete_update_tx); + tal_free(peer->channel->eltoo_keyset.complete_settle_tx); + peer->channel->eltoo_keyset.complete_update_tx = + tal_steal(peer->channel, peer->channel->eltoo_keyset.committed_update_tx); + peer->channel->eltoo_keyset.complete_settle_tx = + tal_steal(peer->channel, peer->channel->eltoo_keyset.committed_settle_tx); + peer->channel->eltoo_keyset.committed_update_tx = NULL; + peer->channel->eltoo_keyset.committed_settle_tx = NULL; +} + const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES) { u8 *msg; @@ -1142,19 +1156,25 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) peer->channel, peer->next_index, LOCAL); + /* Put into committed stated until we promptly sign ourselves */ + tal_free(peer->channel->eltoo_keyset.committed_update_tx); + tal_free(peer->channel->eltoo_keyset.committed_settle_tx); + peer->channel->eltoo_keyset.committed_update_tx = tal_steal(peer->channel, update_and_settle_txs[0]); + peer->channel->eltoo_keyset.committed_settle_tx = tal_steal(peer->channel, update_and_settle_txs[1]); + /* We sign the same update transaction as peer should have signed */ msg = towire_hsmd_psign_update_tx(NULL, &peer->channel_id, - update_and_settle_txs[0], - update_and_settle_txs[1], + peer->channel->eltoo_keyset.committed_update_tx, + peer->channel->eltoo_keyset.committed_settle_tx, &peer->channel->eltoo_keyset.other_funding_key, &peer->channel->eltoo_keyset.other_next_nonce, &peer->channel->eltoo_keyset.self_next_nonce); status_debug("partial signature req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), - type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), - type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_settle_tx), type_to_string(tmpctx, struct pubkey, &peer->channel->eltoo_keyset.self_funding_key), type_to_string(tmpctx, struct pubkey, @@ -1178,8 +1198,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) status_debug("partial signature combine our_psig %s their_psig %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s, session %s", type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.other_psig), - type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[0]), - type_to_string(tmpctx, struct bitcoin_tx, update_and_settle_txs[1]), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_settle_tx), type_to_string(tmpctx, struct pubkey, &peer->channel->eltoo_keyset.self_funding_key), type_to_string(tmpctx, struct pubkey, @@ -1198,8 +1218,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.other_psig, &peer->channel->eltoo_keyset.last_committed_state.session, - update_and_settle_txs[0], - update_and_settle_txs[1], + peer->channel->eltoo_keyset.committed_update_tx, + peer->channel->eltoo_keyset.committed_settle_tx, &peer->channel->eltoo_keyset.inner_pubkey); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); @@ -1209,14 +1229,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) } /* Now that we've checked the update, migrate all signing state from last_committed_state to last_complete_state */ - peer->channel->eltoo_keyset.last_complete_state = peer->channel->eltoo_keyset.last_committed_state; + migrate_committed_to_complete(peer); - /* FIXME do we just bump on lightningd side? We are about to send an update, increment HTLCs to sent state - this was aping peer_sending_revocation - if (!channel_sending_sign_ack(peer->channel, &changed_htlcs)) { - status_debug("Failed to increment HTLC state after sending ACK..."); - }*/ - /* * - MUST accept its turn when: * - receiving `update_signed` @@ -1235,8 +1249,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.last_complete_state.self_psig, &peer->channel->eltoo_keyset.last_complete_state.other_psig, &peer->channel->eltoo_keyset.last_complete_state.session, - update_and_settle_txs[0], - update_and_settle_txs[1]); + peer->channel->eltoo_keyset.complete_update_tx, + peer->channel->eltoo_keyset.complete_settle_tx); /* We may now be quiescent on our side. */ maybe_send_stfu(peer); @@ -1316,8 +1330,8 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) "Bad hsmd_combine_psig_reply: %s", tal_hex(tmpctx, comb_msg)); - /* Update looks good, move completed state over */ - peer->channel->eltoo_keyset.last_complete_state = peer->channel->eltoo_keyset.last_committed_state; + /* Update looks good, move state over and wipe committed */ + migrate_committed_to_complete(peer); /* We start timer even if this returns false: we might have delayed * commit because we were waiting for this! */ From 240c6336453f556abb701ccae119d70004f95492 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 21 Dec 2022 15:52:34 -0500 Subject: [PATCH 263/283] Start implementing reconnection logic --- channeld/eltoo_channeld.c | 38 ++++++++++++++++++++++++++++++++++++-- hsmd/hsmd.c | 2 ++ hsmd/hsmd_wire.csv | 9 +++++++++ hsmd/libhsmd.c | 39 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 6d3cb431a33f..63345d696709 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1851,11 +1851,45 @@ static void send_fail_or_fulfill(struct eltoo_peer *peer, const struct htlc *h) peer->can_yield = false; } -/* FIXME Reconnect fun! Let's compile first. :) */ static void peer_reconnect(struct eltoo_peer *peer, bool reestablish_only) { - /* Need to determine who's turn it is here */ + u8 *msg; + u32 last_update_num = peer->channel->eltoo_keyset.committed_update_tx ? + peer->channel->eltoo_keyset.committed_update_tx->wtx->locktime : peer->channel->eltoo_keyset.complete_update_tx->wtx->locktime; + struct eltoo_sign *state = peer->channel->eltoo_keyset.committed_update_tx ? + &peer->channel->eltoo_keyset.last_committed_state : &peer->channel->eltoo_keyset.last_complete_state; + + /* - MUST set `last_update_number` to the value of the channel state number of the last + * partial signature the node has sent to its peer. + * - MUST set `update_psig` to the `last_update_number` channel state + * update transaction's partial signature. + * - MUST set `fresh_nonce` to the new nonce to be used for the next channel update partial signature. + */ + + /* Refresh and fetch MuSig nonce */ + msg = towire_hsmd_gen_nonce(NULL, &peer->channel_id); + wire_sync_write(HSM_FD, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_gen_nonce_reply(msg, &peer->channel->eltoo_keyset.self_next_nonce)) { + peer_failed_err(peer->pps, + &peer->channel_id, + "Failed to get nonce for channel reestablishment: %s", tal_hex(msg, msg)); + } + + /* Exchange reestablishment message with peer */ + msg = towire_channel_reestablish_eltoo(tmpctx, + &peer->channel_id, + last_update_num, + &state->self_psig, + &peer->channel->eltoo_keyset.self_next_nonce); + + peer_write(peer->pps, take(msg)); + + peer_billboard(false, "Sent reestablish, waiting for theirs"); + + /* FIXME read in message, act on it */ } /* ignores the funding_depth unless depth >= minimum_depth diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 0bcd06f84755..aa979f67757f 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -675,6 +675,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_MIGRATE_NONCE: case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: case WIRE_HSMD_SIGN_ELTOO_HTLC_SUCCESS_TX: + case WIRE_HSMD_REGEN_NONCE: /* Eltoo stuff ends */ /* Hand off to libhsmd for processing */ return req_reply(conn, c, @@ -709,6 +710,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: + case WIRE_HSMD_REGEN_NONCE_REPLY: case WIRE_HSMD_MIGRATE_NONCE_REPLY: case WIRE_HSMD_SIGN_ELTOO_TX_REPLY: return bad_req_fmt(conn, c, c->msg_in, diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 11bb4242ab7c..17d0a2b681ee 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -376,3 +376,12 @@ msgdata,hsmd_sign_eltoo_htlc_success_tx,tapscript,u8,tapscript_len # Reply for all the above requests. msgtype,hsmd_sign_eltoo_tx_reply,212 msgdata,hsmd_sign_eltoo_tx_reply,sig,bip340sig, + +# Regenerate musig public nonce for already funded channel +# e.g., channel reestablishment +msgtype,hsmd_regen_nonce,98 +msgdata,hsmd_regen_nonce,channel_id,channel_id, + +msgtype,hsmd_regen_nonce_reply,198 +msgdata,hsmd_regen_nonce_reply,pubnonce,nonce, + diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index f867bd852a08..eb4ac9240655 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -138,6 +138,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_VALIDATE_COMMITMENT_TX: case WIRE_HSMD_VALIDATE_REVOCATION: case WIRE_HSMD_GEN_NONCE: + case WIRE_HSMD_REGEN_NONCE: case WIRE_HSMD_MIGRATE_NONCE: case WIRE_HSMD_PSIGN_UPDATE_TX: case WIRE_HSMD_COMBINE_PSIG: @@ -195,6 +196,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: + case WIRE_HSMD_REGEN_NONCE_REPLY: case WIRE_HSMD_MIGRATE_NONCE_REPLY: case WIRE_HSMD_SIGN_ELTOO_TX_REPLY: break; @@ -1560,8 +1562,6 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) pubnonce_ptrs[0] = &remote_nonce.nonce; pubnonce_ptrs[1] = &local_nonce.nonce; - /* FIXME assert we have secnonce already... though if we don't this call will already crash... */ - /* Find secnonce in map */ musig_state_lookup = musig_state_map_get(&secretstuff.musig_map, &channel_id); if (!musig_state_lookup) { @@ -1588,6 +1588,38 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &local_nonce, &inner_pubkey); } +/* Should only be used if nonce for funded channel exists and new one will be sent to co-signer + * e.g., during channel reestblishment + */ +static u8 *handle_regen_nonce(struct hsmd_client *c, const u8 *msg_in) +{ + struct channel_id channel_id; + struct musig_state *musig_state_lookup; + struct secret channel_seed; + struct secrets secrets; + struct nonce fresh_nonce; + + if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) + return hsmd_status_malformed_request(c, msg_in); + + get_channel_seed(&c->id, c->dbid, &channel_seed); + derive_basepoints(&channel_seed, + NULL, NULL, &secrets, NULL); + + musig_state_lookup = musig_state_map_get(&secretstuff.musig_map, &channel_id); + if (!musig_state_lookup) { + return hsmd_status_bad_request(c, msg_in, + "No secret nonce found for this regen request"); + } + + bipmusig_gen_nonce(&musig_state_lookup->sec_nonce, + &fresh_nonce.nonce, + &secrets.funding_privkey, + NULL /* keyagg_cache */, + channel_id.id /* doesn't hurt; not strictly needed */); + + return towire_hsmd_regen_nonce_reply(NULL, &fresh_nonce); +} /*~ This is another lightningd-only interface; signing a commit transaction. * This is dangerous, since if we sign a revoked commitment tx we'll lose @@ -1959,6 +1991,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_SIGN_ELTOO_HTLC_TIMEOUT_TX: case WIRE_HSMD_SIGN_ELTOO_HTLC_SUCCESS_TX: return handle_sign_eltoo_htlc_tx(client, msg); + case WIRE_HSMD_REGEN_NONCE: + return handle_regen_nonce(client, msg); /* Eltoo stuff ends */ case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: @@ -1989,6 +2023,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_COMBINE_PSIG_REPLY: case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG_REPLY: case WIRE_HSMD_GEN_NONCE_REPLY: + case WIRE_HSMD_REGEN_NONCE_REPLY: case WIRE_HSMD_MIGRATE_NONCE_REPLY: case WIRE_HSMD_SIGN_ELTOO_TX_REPLY: break; From fdbb1fa0e5768d4ddda2eb81e2b49795f66aec5b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Wed, 4 Jan 2023 14:59:20 -0500 Subject: [PATCH 264/283] Maybe implemented channel reestablishment --- channeld/channeld_wire.csv | 2 + channeld/eltoo_channeld.c | 213 ++++++++++++++++++++++++++++++++++- lightningd/channel_control.c | 1 + 3 files changed, 210 insertions(+), 6 deletions(-) diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index c5998fdaa409..8a93f3e85c0e 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -310,6 +310,8 @@ msgdata,channeld_init_eltoo,local_node_id,node_id, msgdata,channeld_init_eltoo,remote_node_id,node_id, msgdata,channeld_init_eltoo,commit_msec,u32, msgdata,channeld_init_eltoo,cltv_delta,u16, +msgdata,channeld_init_eltoo,num_last_sent_commit,u16, +msgdata,channeld_init_eltoo,last_sent_commit,changed_htlc,num_last_sent_commit msgdata,channeld_init_eltoo,next_index,u64, msgdata,channeld_init_eltoo,updates_received,u64, msgdata,channeld_init_eltoo,next_htlc_id,u64, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 63345d696709..b31585edd7e4 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -139,9 +139,9 @@ struct eltoo_peer { bool dev_fast_gossip; #endif /* Information used for reestablishment. */ + struct changed_htlc *last_sent_commit; /* FIXME figure out what goes here bool last_was_revoke; - struct changed_htlc *last_sent_commit; u64 revocations_received; */ u8 channel_flags; @@ -1851,10 +1851,131 @@ static void send_fail_or_fulfill(struct eltoo_peer *peer, const struct htlc *h) peer->can_yield = false; } +/* Older LND sometimes sends funding_locked before reestablish! */ +/* ... or announcement_signatures. Sigh, let's handle whatever they send. */ +static bool capture_premature_msg(const u8 ***shit_lnd_says, const u8 *msg) +{ + if (fromwire_peektype(msg) == WIRE_CHANNEL_REESTABLISH_ELTOO) + return false; + + /* Don't allow infinite memory consumption. */ + if (tal_count(*shit_lnd_says) > 10) + return false; + + status_debug("Stashing early %s msg!", + peer_wire_name(fromwire_peektype(msg))); + + tal_arr_expand(shit_lnd_says, tal_steal(*shit_lnd_says, msg)); + return true; +} + +static int cmp_changed_htlc_id(const struct changed_htlc *a, + const struct changed_htlc *b, + void *unused) +{ + /* ids can be the same (sender and receiver are indep) but in + * that case we don't care about order. */ + if (a->id > b->id) + return 1; + else if (a->id < b->id) + return -1; + return 0; +} + +static void resend_updates(struct eltoo_peer *peer, struct changed_htlc *last) +{ + size_t i; + u8 *msg; + + status_debug("Retransmitting update"); + + /* Note that HTLCs must be *added* in order. Simplest thing to do + * is to sort them all into ascending ID order here (we could do + * this when we save them in channel_sending_commit, but older versions + * won't have them sorted in the db, so doing it here is better). */ + asort(last, tal_count(last), cmp_changed_htlc_id, NULL); + + /* In our case, we consider ourselves already committed to this, so + * retransmission is simplest. */ + /* We need to send fulfills/failures before adds, so we split them + * up into two loops -- this is the 'fulfill/fail' loop */ + for (i = 0; i < tal_count(last); i++) { + const struct htlc *h; + + h = eltoo_channel_get_htlc(peer->channel, + htlc_state_owner(last[i].newstate), + last[i].id); + /* FIXME necessary? I think this can happen if we actually received revoke_and_ack + * then they asked for a retransmit */ + if (!h) + peer_failed_warn(peer->pps, &peer->channel_id, + "Can't find HTLC %"PRIu64" to resend", + last[i].id); + + if (h->state == SENT_REMOVE_UPDATE) + send_fail_or_fulfill(peer, h); + } + + /* We need to send fulfills/failures before adds, so we split them + * up into two loops -- this is the 'add' loop */ + for (i = 0; i < tal_count(last); i++) { + const struct htlc *h; + + h = eltoo_channel_get_htlc(peer->channel, + htlc_state_owner(last[i].newstate), + last[i].id); + + /* FIXME necessary? I think this can happen if we actually received revoke_and_ack + * then they asked for a retransmit */ + if (!h) + peer_failed_warn(peer->pps, &peer->channel_id, + "Can't find HTLC %"PRIu64" to resend", + last[i].id); + + if (h->state == SENT_ADD_UPDATE) { +#if EXPERIMENTAL_FEATURES + struct tlv_update_add_tlvs *tlvs; + if (h->blinding) { + tlvs = tlv_update_add_tlvs_new(tmpctx); + tlvs->blinding = tal_dup(tlvs, struct pubkey, + h->blinding); + } else + tlvs = NULL; +#endif + u8 *msg = towire_update_add_htlc(NULL, &peer->channel_id, + h->id, h->amount, + &h->rhash, + abs_locktime_to_blocks( + &h->expiry), + h->routing +#if EXPERIMENTAL_FEATURES + , tlvs +#endif + ); + peer_write(peer->pps, take(msg)); + } + } + + /* No fee information required */ + + /* No blockheight info (yet) */ + + /* Resend psig and FRESH nonce */ + msg = towire_update_signed(NULL, &peer->channel_id, + &peer->channel->eltoo_keyset.last_committed_state.self_psig, + &peer->channel->eltoo_keyset.self_next_nonce); + peer_write(peer->pps, take(msg)); +} + static void peer_reconnect(struct eltoo_peer *peer, bool reestablish_only) { u8 *msg; + struct channel_id channel_id; + u64 remote_last_update_num; + struct partial_sig remote_update_psig; + struct nonce remote_fresh_nonce; + const u8 **premature_msgs = tal_arr(peer, const u8 *, 0); u32 last_update_num = peer->channel->eltoo_keyset.committed_update_tx ? peer->channel->eltoo_keyset.committed_update_tx->wtx->locktime : peer->channel->eltoo_keyset.complete_update_tx->wtx->locktime; struct eltoo_sign *state = peer->channel->eltoo_keyset.committed_update_tx ? @@ -1889,7 +2010,86 @@ static void peer_reconnect(struct eltoo_peer *peer, peer_billboard(false, "Sent reestablish, waiting for theirs"); - /* FIXME read in message, act on it */ + /* Read until they say something interesting (don't forward + * gossip *to* them yet: we might try sending channel_update + * before we've reestablished channel). */ + do { + clean_tmpctx(); + msg = peer_read(tmpctx, peer->pps); + + /* connectd promised us the msg was reestablish? */ + if (reestablish_only) { + if (fromwire_peektype(msg) != WIRE_CHANNEL_REESTABLISH_ELTOO) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Expected reestablish, got: %s", + tal_hex(tmpctx, msg)); + } + } while (handle_peer_error(peer->pps, &peer->channel_id, msg) || + capture_premature_msg(&premature_msgs, msg)); + + + if (!fromwire_channel_reestablish_eltoo(msg, + &channel_id, + &remote_last_update_num, + &remote_update_psig, + &remote_fresh_nonce)) { + peer_failed_warn(peer->pps, + &peer->channel_id, + "bad reestablish msg: %s %s", + peer_wire_name(fromwire_peektype(msg)), + tal_hex(msg, msg)); + + } + + if (peer->funding_locked[LOCAL] + && last_update_num == 0 + && remote_last_update_num == 0) { + u8 *msg; + + status_debug("Retransmitting funding_locked_eltoo for channel %s", + type_to_string(tmpctx, struct channel_id, &peer->channel_id)); + msg = towire_funding_locked_eltoo(NULL, + &peer->channel_id); + peer_write(peer->pps, take(msg)); + } + + + if (last_update_num == remote_last_update_num) { + /* Everything is ok, start next round */ + } else if (last_update_num == remote_last_update_num + 1) { + /* We committed but didn't get an ACK */ + peer->turn = LOCAL; + resend_updates(peer, peer->last_sent_commit); + } else if (remote_last_update_num == last_update_num + 1) { + /* They committed but didn't get an ACK + * It's their turn; return to normal operation. + */ + peer->turn = REMOTE; + } else { + /* Something bad has happened */ + peer_failed_err(peer->pps, + &peer->channel_id, + "bad reestablish last_update_number: %"PRIu64 + " vs %"PRIu32, + remote_last_update_num, + last_update_num); + } + + /* We allow peer to send us tx-sigs, until funding locked received */ + peer->tx_sigs_allowed = true; + peer_billboard(true, "Reconnected, and reestablished."); + + /* BOLT #2: + * - upon reconnection: + *... + * - MUST transmit `channel_reestablish` for each channel. + * - MUST wait to receive the other node's `channel_reestablish` + * message before sending any other messages for that channel. + */ + /* LND doesn't wait. */ + for (size_t i = 0; i < tal_count(premature_msgs); i++) + peer_in(peer, premature_msgs[i]); + tal_free(premature_msgs); } /* ignores the funding_depth unless depth >= minimum_depth @@ -2425,6 +2625,7 @@ static void init_channel(struct eltoo_peer *peer) &peer->node_ids[REMOTE], &peer->commit_msec, &peer->cltv_delta, + &peer->last_sent_commit, &peer->next_index, &peer->updates_received, &peer->htlc_id, @@ -2529,13 +2730,15 @@ static void init_channel(struct eltoo_peer *peer) /* We don't send updates out of turn so this is always true */ peer->can_yield = true; + /* Reconnect logic may overwrite this value due to unfinished turn */ + peer->turn = + node_id_cmp(&(peer->node_ids[LOCAL]), &(peer->node_ids[REMOTE])) < 0 ? LOCAL : REMOTE; + /* OK, now we can process peer messages. */ if (reconnected) peer_reconnect(peer, reestablish_only); else { assert(!reestablish_only); - peer->turn = - node_id_cmp(&(peer->node_ids[LOCAL]), &(peer->node_ids[REMOTE])) < 0 ? LOCAL : REMOTE; } /* If we have a messages to send, send them immediately */ @@ -2652,7 +2855,6 @@ int main(int argc, char *argv[]) } - status_debug("***SELECT***"); if (select(nfds, &rfds, NULL, NULL, tptr) < 0) { /* Signals OK, eg. SIGUSR1 */ if (errno == EINTR) @@ -2660,7 +2862,6 @@ int main(int argc, char *argv[]) status_failed(STATUS_FAIL_INTERNAL_ERROR, "select failed: %s", strerror(errno)); } - status_debug("***UNSELECT***"); if (FD_ISSET(MASTER_FD, &rfds)) { msg = wire_sync_read(tmpctx, MASTER_FD); diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 1a91606e66f4..89d5c1bd600a 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -761,6 +761,7 @@ void peer_start_eltoo_channeld(struct channel *channel, &channel->peer->id, cfg->commit_time_ms, cfg->cltv_expiry_delta, + channel->last_sent_commit, channel->next_index[LOCAL], 0 /* updates_received FIXME is this even necessary? locktime has this */, channel->next_htlc_id, From 23071e36405f3540ddd5b9bf2e10897d1a822274 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 5 Jan 2023 15:17:54 -0500 Subject: [PATCH 265/283] Start writing test for reestablishment --- channeld/channeld_wire.csv | 4 ++ channeld/eltoo_channeld.c | 93 +++++++++++++++++++++++++++++++----- common/keyset.h | 3 +- lightningd/channel_control.c | 4 ++ tests/test_closing.py | 39 +++++++++++++++ 5 files changed, 130 insertions(+), 13 deletions(-) diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 8a93f3e85c0e..fb990031de3d 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -296,6 +296,10 @@ msgdata,channeld_init_eltoo,our_committed_psig,partial_sig, msgdata,channeld_init_eltoo,committed_session,musig_session, msgdata,channeld_init_eltoo,their_next_nonce,nonce, msgdata,channeld_init_eltoo,our_next_nonce,nonce, +msgdata,channeld_init_eltoo,complete_update_tx,?bitcoin_tx, +msgdata,channeld_init_eltoo,complete_settle_tx,?bitcoin_tx, +msgdata,channeld_init_eltoo,committed_update_tx,?bitcoin_tx, +msgdata,channeld_init_eltoo,committed_settle_tx,?bitcoin_tx, msgdata,channeld_init_eltoo,their_funding_pubkey,pubkey, msgdata,channeld_init_eltoo,their_settle_pubkey,pubkey, msgdata,channeld_init_eltoo,opener,enum side, diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index b31585edd7e4..62dc8254e421 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -54,7 +54,7 @@ struct eltoo_peer { struct per_peer_state *pps; bool funding_locked[NUM_SIDES]; - u64 next_index; + u64 next_index; /* update number for next update_* messages */ /* Features peer supports. */ u8 *their_features; @@ -1974,12 +1974,10 @@ static void peer_reconnect(struct eltoo_peer *peer, struct channel_id channel_id; u64 remote_last_update_num; struct partial_sig remote_update_psig; - struct nonce remote_fresh_nonce; const u8 **premature_msgs = tal_arr(peer, const u8 *, 0); - u32 last_update_num = peer->channel->eltoo_keyset.committed_update_tx ? - peer->channel->eltoo_keyset.committed_update_tx->wtx->locktime : peer->channel->eltoo_keyset.complete_update_tx->wtx->locktime; - struct eltoo_sign *state = peer->channel->eltoo_keyset.committed_update_tx ? - &peer->channel->eltoo_keyset.last_committed_state : &peer->channel->eltoo_keyset.last_complete_state; + u32 last_update_num = peer->next_index - 1; + /* This should still be valid even if we received an ack for this committed state */ + struct eltoo_sign *state = &peer->channel->eltoo_keyset.last_committed_state; /* - MUST set `last_update_number` to the value of the channel state number of the last * partial signature the node has sent to its peer. @@ -2028,11 +2026,13 @@ static void peer_reconnect(struct eltoo_peer *peer, capture_premature_msg(&premature_msgs, msg)); + /* Their psig might be for our complete state + */ if (!fromwire_channel_reestablish_eltoo(msg, &channel_id, &remote_last_update_num, &remote_update_psig, - &remote_fresh_nonce)) { + &peer->channel->eltoo_keyset.other_next_nonce)) { peer_failed_warn(peer->pps, &peer->channel_id, "bad reestablish msg: %s %s", @@ -2055,14 +2055,69 @@ static void peer_reconnect(struct eltoo_peer *peer, if (last_update_num == remote_last_update_num) { - /* Everything is ok, start next round */ + + /* They say they sent a response we didn't get yet */ + if (peer->channel->eltoo_keyset.committed_update_tx) { + /* This section is(?) a carbon copy of normal operation of receiving ack */ + const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); + struct bip340sig update_sig; + +// if (memcmp(remote_update_psig.p_sig.data, +// peer->channel->eltoo_keyset->last_complete_state.other_psig, +// sizeof(remote_update_psig.p_sig.data)) != 0) { + + peer->channel->eltoo_keyset.last_committed_state.other_psig = remote_update_psig; + + /* Check psig */ + msg = towire_hsmd_combine_psig(NULL, + &peer->channel_id, + &peer->channel->eltoo_keyset.last_committed_state.self_psig, + &peer->channel->eltoo_keyset.last_committed_state.other_psig, + &peer->channel->eltoo_keyset.last_committed_state.session, + peer->channel->eltoo_keyset.committed_update_tx, + peer->channel->eltoo_keyset.committed_settle_tx, + &peer->channel->eltoo_keyset.inner_pubkey); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { + status_failed(STATUS_FAIL_HSM_IO, + "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); + } + + /* Migrate over and continue */ + migrate_committed_to_complete(peer); + + /* Fill out changed htlcs */ + if (channel_rcvd_update_sign_ack(peer->channel, &changed_htlcs)) { + /* FIXME I don't think this is possible? */ + status_debug("Commits outstanding after recv update_sign_ack"); + } else { + status_debug("No commits outstanding after recv update_sign_ack"); + } + + /* Tell master about things this locks in(and final signature), wait for response */ + msg = got_signed_ack_msg(peer, peer->next_index, + changed_htlcs, &peer->channel->eltoo_keyset.last_complete_state.other_psig, &peer->channel->eltoo_keyset.last_complete_state.self_psig, + &peer->channel->eltoo_keyset.last_complete_state.session); + master_wait_sync_reply(tmpctx, peer, take(msg), + WIRE_CHANNELD_GOT_ACK_REPLY); + + status_debug("update_signed_ack %s: update = %lu", + side_to_str(peer->channel->opener), peer->next_index - 1); + } + + /* Everything is ok, return to normal operation */ + } else if (last_update_num == remote_last_update_num + 1) { - /* We committed but didn't get an ACK */ + /* We committed but remote claims they didn't get it. + * We ignore their psig and replay our turn with fresh nonces. + */ peer->turn = LOCAL; resend_updates(peer, peer->last_sent_commit); } else if (remote_last_update_num == last_update_num + 1) { - /* They committed but didn't get an ACK - * It's their turn; return to normal operation. + /* They say they committed but we didn't get it. + * We will not use the psig. + * It's their turn; return to normal operation with fresh nonces. */ peer->turn = REMOTE; } else { @@ -2588,6 +2643,8 @@ static void init_channel(struct eltoo_peer *peer) struct channel_type *channel_type; u32 *dev_disable_commit; /* Always NULL */ bool dev_fast_gossip; + struct bitcoin_tx *complete_update_tx, *complete_settle_tx; + struct bitcoin_tx *committed_update_tx, *committed_settle_tx; #if !DEVELOPER bool dev_fail_process_onionpacket; /* Ignored */ #endif @@ -2611,6 +2668,10 @@ static void init_channel(struct eltoo_peer *peer) &committed_state.session, &nonces[REMOTE], &nonces[LOCAL], + &complete_update_tx, + &complete_settle_tx, + &committed_update_tx, + &committed_settle_tx, &funding_pubkey[REMOTE], &settle_pubkey[REMOTE], &opener, @@ -2709,9 +2770,17 @@ static void init_channel(struct eltoo_peer *peer) OPT_LARGE_CHANNELS), opener); - /* FIXME new_full_eltoo_channel should take the nonces... */ + /* FIXME new_full_eltoo_channel should take the nonces and txns... */ peer->channel->eltoo_keyset.other_next_nonce = nonces[REMOTE]; peer->channel->eltoo_keyset.self_next_nonce = nonces[LOCAL]; +// if (complete_update_tx) { + peer->channel->eltoo_keyset.complete_update_tx = tal_steal(peer, complete_update_tx); + peer->channel->eltoo_keyset.complete_settle_tx = tal_steal(peer, complete_settle_tx); +// } +// if (committed_update_tx) { + peer->channel->eltoo_keyset.committed_update_tx = tal_steal(peer, committed_update_tx); + peer->channel->eltoo_keyset.committed_settle_tx = tal_steal(peer, committed_settle_tx); +// } if (!channel_force_htlcs(peer->channel, cast_const2(const struct existing_htlc **, htlcs))) diff --git a/common/keyset.h b/common/keyset.h index 087715f8646a..0ebaa6d4c887 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -35,7 +35,8 @@ struct eltoo_keyset { struct bitcoin_tx *complete_settle_tx; /* State we have committed to but have incomplete signatures for. * This may be used in channel reestablishment or for reacting - to the appearance of the state on-chain. */ + to the appearance of the state on-chain. It should always contain + the most recent partial signatures and session for a node. */ struct eltoo_sign last_committed_state; /* Will be stolen, so needs to be not copied directly with other state */ struct bitcoin_tx *committed_update_tx; diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 89d5c1bd600a..76392e215b8b 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -747,6 +747,10 @@ void peer_start_eltoo_channeld(struct channel *channel, &channel->eltoo_keyset.last_committed_state.session, &channel->eltoo_keyset.other_next_nonce, &channel->eltoo_keyset.self_next_nonce, + channel->eltoo_keyset.complete_update_tx, + channel->eltoo_keyset.complete_settle_tx, + channel->eltoo_keyset.committed_update_tx, + channel->eltoo_keyset.committed_settle_tx, &channel->channel_info.remote_fundingkey, &channel->channel_info.theirbase.payment, /* their_settle_pubkey */ channel->opener, diff --git a/tests/test_closing.py b/tests/test_closing.py index 1bdace04e5f0..276024ca7e82 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -727,6 +727,45 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) + +def test_eltoo_empty_reestablishment(node_factory, bitcoind): + """Test that channel reestablishment does the expected thing""" + + l1, l2 = node_factory.line_graph(2, + opts=[{'may_reconnect': True}, {'may_reconnect': True}]) + + # Simple reestblishment where funding is locked + l1.rpc.disconnect(l2.info['id'], force=True) + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + + # We should see funding_locked messages be passed around, then + # normal operation + l1.daemon.wait_for_log('Reconnected, and reestablished') + l2.daemon.wait_for_log('Reconnected, and reestablished') + + l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + l2_update_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l2_settle_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + assert l1_update_tx == l2_update_tx + assert l1_settle_tx == l2_settle_tx + + l1_update_details = bitcoind.rpc.decoderawtransaction(l1_update_tx) + l1_settle_details = bitcoind.rpc.decoderawtransaction(l1_settle_tx) + + # First update recovered + assert l1_update_details["locktime"] == 500000000 + assert l1_settle_details["locktime"] == 500000000 + + from pdb import set_trace + set_trace() + + # l1 can pay l2 + l1.pay(l2, 100000*SAT) + + def test_eltoo_unannounced_hop(node_factory, bitcoind): """Test eltoo payments work over hops""" From 668e71f18bcdc2c6a67517b1ff54819961b4150d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 5 Jan 2023 15:20:06 -0500 Subject: [PATCH 266/283] Move eltoo tests to own thing --- tests/test_closing.py | 182 ------------------------------------- tests/test_eltoo.py | 203 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+), 182 deletions(-) create mode 100644 tests/test_eltoo.py diff --git a/tests/test_closing.py b/tests/test_closing.py index 276024ca7e82..7ae68bbf8c50 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -727,188 +727,6 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) - -def test_eltoo_empty_reestablishment(node_factory, bitcoind): - """Test that channel reestablishment does the expected thing""" - - l1, l2 = node_factory.line_graph(2, - opts=[{'may_reconnect': True}, {'may_reconnect': True}]) - - # Simple reestblishment where funding is locked - l1.rpc.disconnect(l2.info['id'], force=True) - l1.rpc.connect(l2.info['id'], 'localhost', l2.port) - - # We should see funding_locked messages be passed around, then - # normal operation - l1.daemon.wait_for_log('Reconnected, and reestablished') - l2.daemon.wait_for_log('Reconnected, and reestablished') - - l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] - l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] - - l2_update_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_update_tx'] - l2_settle_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] - - assert l1_update_tx == l2_update_tx - assert l1_settle_tx == l2_settle_tx - - l1_update_details = bitcoind.rpc.decoderawtransaction(l1_update_tx) - l1_settle_details = bitcoind.rpc.decoderawtransaction(l1_settle_tx) - - # First update recovered - assert l1_update_details["locktime"] == 500000000 - assert l1_settle_details["locktime"] == 500000000 - - from pdb import set_trace - set_trace() - - # l1 can pay l2 - l1.pay(l2, 100000*SAT) - - -def test_eltoo_unannounced_hop(node_factory, bitcoind): - """Test eltoo payments work over hops""" - - # Make three nodes, two private channels - l1, l2, l3 = node_factory.line_graph(3, - opts=[{}, {}, {}], announce_channels=False) # Channel announcement unsupported, doing private hops) - - # l1 can pay l2 - l1.pay(l2, 100000*SAT) - - # l2 can pay back l1 - l1.pay(l2, 5000*SAT) - - # l2 can pay l3 - l2.pay(l3, 200000*SAT) - - # With proper hints exposed, - # l1 can pay l3 - scid = l3.rpc.listchannels()['channels'][0]['short_channel_id'] - invoice = l3.rpc.invoice(msatoshi=10000, label='hop', description='test', exposeprivatechannels=scid) - l1.rpc.pay(invoice['bolt11']) - wait_for(lambda: l3.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(200010000)) - -# Example flags to run test -# DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_closing.py -k test_eltoo_htlc -@pytest.mark.developer("needs dev-disable-commit-after") -def test_eltoo_htlc(node_factory, bitcoind, executor, chainparams): - """Test HTLC resolution via eltoo_onchaind after a single successful payment""" - - # We track channel balances, to verify that accounting is ok. - coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') - # First we need to get funds to l2, so suppress after second. - # Feerates identical so we don't get gratuitous commit to update them - l1, l2 = node_factory.line_graph(2, - opts=[{'dev-disable-commit-after': 1, # add HTLC once - 'may_fail': True, - 'feerates': (7500, 7500, 7500, 7500), - 'allow_broken_log': True, - 'plugin': coin_mvt_plugin}, - {'dev-disable-commit-after': 2, # remove HTLC, then later add - 'plugin': coin_mvt_plugin}]) - channel_id = first_channel_id(l1, l2) - - - # Move some across to l2. This will cause *2* updates to be sent for - # addition and removal of HTLC - l1.pay(l2, 200000*SAT) - - # l1 won't be able to remove next HTLC after offering first addition - l1.daemon.wait_for_log('dev-disable-commit-after: disabling') - assert not l2.daemon.is_in_log('dev-disable-commit-after: disabling') - - # Now, this will get stuck due to l1 commit being disabled due to one more update.. - t = executor.submit(l2.pay, l1, 100000*SAT) - - # Make sure we get partial signature - l1.daemon.wait_for_log('peer_in WIRE_UPDATE_ADD_HTLC') - l1.daemon.wait_for_log('peer_in WIRE_UPDATE_SIGNED') - - # They should both have commitments blocked now. - l2.daemon.wait_for_log('dev-disable-commit-after: disabling') - - # Both peers have partial sigs for the latest update transaction - l1.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') - l2.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') - - # Take our snapshot of complete tx with HTLC. - l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] - l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] - - l2_update_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_update_tx'] - l2_settle_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] - - assert l1_update_tx == l2_update_tx - assert l1_settle_tx == l2_settle_tx - - # Now we really mess things up! - - # FIXME we need real anchor CPFP + package relay to pay fees - l1_update_details = bitcoind.rpc.decoderawtransaction(l1_update_tx) - l1_settle_details = bitcoind.rpc.decoderawtransaction(l1_settle_tx) - bitcoind.rpc.prioritisetransaction(l1_update_details["txid"], 0, 100000000) - bitcoind.rpc.prioritisetransaction(l1_settle_details["txid"], 0, 100000000) - bitcoind.rpc.sendrawtransaction(l1_update_tx) - - # Mine and mature the update tx - bitcoind.generate_block(6) - - # Symmetrical transactions(!), symmetrical state, mostly - l1.daemon.wait_for_log(' to ONCHAIN') - l2.daemon.wait_for_log(' to ONCHAIN') - - needle_1 = l1.daemon.logsearch_start - needle_2 = l2.daemon.logsearch_start - - # The settle transaction should hit the mempool for both! - l1.wait_for_onchaind_broadcast('ELTOO_SETTLE', - 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') - l2.wait_for_onchaind_broadcast('ELTOO_SETTLE', - 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') - - assert len(bitcoind.rpc.getrawmempool()) == 1 - - # We're going to disable transaction relay for the SUCCESS transaction - # To allow us to test broadcast of one transaction at a time - def censoring_sendrawtx(r): - return {'id': r['id'], 'result': {}} - - l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', censoring_sendrawtx) - - # Mine settle tx, then we should see HTLC timeout resolution hit the mempool by the receiver - bitcoind.generate_block(1) - - wait_for(lambda: len(bitcoind.rpc.getrawmempool()) == 1) - - timeout_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) - assert len(timeout_tx['vin'][0]['txinwitness']) == 3 - l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', - 'ELTOO_SETTLE/OUR_HTLC') - # Stop mining of tx for this next block - bitcoind.rpc.prioritisetransaction(timeout_tx['txid'], 0, -100000000) - # Allow SUCCESS tx to hit mempool next block - l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', None) - - bitcoind.generate_block(1) - - # Should hit mempool; do the log/pool check - l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', - 'ELTOO_SETTLE/THEIR_HTLC') - - success_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) - assert len(success_tx['vin'][0]['txinwitness']) == 4 - - bitcoind.generate_block(1) - - # FIXME Check wallet related things, balances - # FIXME The mounds of memleaks - - # Mine enough blocks to closed out onchaind - bitcoind.generate_block(99) - l1.daemon.wait_for_log('onchaind complete, forgetting peer') - l2.daemon.wait_for_log('onchaind complete, forgetting peer') - @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') @pytest.mark.slow_test diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py new file mode 100644 index 000000000000..cc00018e2142 --- /dev/null +++ b/tests/test_eltoo.py @@ -0,0 +1,203 @@ +from fixtures import * # noqa: F401,F403 +from pyln.client import RpcError, Millisatoshi +from shutil import copyfile +from pyln.testing.utils import SLOW_MACHINE +from utils import ( + only_one, sync_blockheight, wait_for, TIMEOUT, + account_balance, first_channel_id, closing_fee, TEST_NETWORK, + scriptpubkey_addr, calc_lease_fee, EXPERIMENTAL_FEATURES, + check_utxos_channel, anchor_expected, check_coin_moves, + check_balance_snaps, mine_funding_to_announce +) + +import os +import queue +import pytest +import re +import subprocess +import threading +import unittest + +# In msats +SAT = 1000 + +def test_eltoo_empty_reestablishment(node_factory, bitcoind): + """Test that channel reestablishment does the expected thing""" + + l1, l2 = node_factory.line_graph(2, + opts=[{'may_reconnect': True}, {'may_reconnect': True}]) + + # Simple reestblishment where funding is locked + l1.rpc.disconnect(l2.info['id'], force=True) + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + + # We should see funding_locked messages be passed around, then + # normal operation + l1.daemon.wait_for_log('Reconnected, and reestablished') + l2.daemon.wait_for_log('Reconnected, and reestablished') + + l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + l2_update_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l2_settle_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + assert l1_update_tx == l2_update_tx + assert l1_settle_tx == l2_settle_tx + + l1_update_details = bitcoind.rpc.decoderawtransaction(l1_update_tx) + l1_settle_details = bitcoind.rpc.decoderawtransaction(l1_settle_tx) + + # First update recovered + assert l1_update_details["locktime"] == 500000000 + assert l1_settle_details["locktime"] == 500000000 + + from pdb import set_trace + set_trace() + + # l1 can pay l2 + l1.pay(l2, 100000*SAT) + + +def test_eltoo_unannounced_hop(node_factory, bitcoind): + """Test eltoo payments work over hops""" + + # Make three nodes, two private channels + l1, l2, l3 = node_factory.line_graph(3, + opts=[{}, {}, {}], announce_channels=False) # Channel announcement unsupported, doing private hops) + + # l1 can pay l2 + l1.pay(l2, 100000*SAT) + + # l2 can pay back l1 + l1.pay(l2, 5000*SAT) + + # l2 can pay l3 + l2.pay(l3, 200000*SAT) + + # With proper hints exposed, + # l1 can pay l3 + scid = l3.rpc.listchannels()['channels'][0]['short_channel_id'] + invoice = l3.rpc.invoice(msatoshi=10000, label='hop', description='test', exposeprivatechannels=scid) + l1.rpc.pay(invoice['bolt11']) + wait_for(lambda: l3.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(200010000)) + +# Example flags to run test +# DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_eltoo.py -k test_eltoo_htlc +@pytest.mark.developer("needs dev-disable-commit-after") +def test_eltoo_htlc(node_factory, bitcoind, executor, chainparams): + """Test HTLC resolution via eltoo_onchaind after a single successful payment""" + + # We track channel balances, to verify that accounting is ok. + coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') + # First we need to get funds to l2, so suppress after second. + # Feerates identical so we don't get gratuitous commit to update them + l1, l2 = node_factory.line_graph(2, + opts=[{'dev-disable-commit-after': 1, # add HTLC once + 'may_fail': True, + 'feerates': (7500, 7500, 7500, 7500), + 'allow_broken_log': True, + 'plugin': coin_mvt_plugin}, + {'dev-disable-commit-after': 2, # remove HTLC, then later add + 'plugin': coin_mvt_plugin}]) + channel_id = first_channel_id(l1, l2) + + + # Move some across to l2. This will cause *2* updates to be sent for + # addition and removal of HTLC + l1.pay(l2, 200000*SAT) + + # l1 won't be able to remove next HTLC after offering first addition + l1.daemon.wait_for_log('dev-disable-commit-after: disabling') + assert not l2.daemon.is_in_log('dev-disable-commit-after: disabling') + + # Now, this will get stuck due to l1 commit being disabled due to one more update.. + t = executor.submit(l2.pay, l1, 100000*SAT) + + # Make sure we get partial signature + l1.daemon.wait_for_log('peer_in WIRE_UPDATE_ADD_HTLC') + l1.daemon.wait_for_log('peer_in WIRE_UPDATE_SIGNED') + + # They should both have commitments blocked now. + l2.daemon.wait_for_log('dev-disable-commit-after: disabling') + + # Both peers have partial sigs for the latest update transaction + l1.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') + l2.daemon.wait_for_log('WIRE_UPDATE_SIGNED_ACK') + + # Take our snapshot of complete tx with HTLC. + l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + l2_update_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_update_tx'] + l2_settle_tx = l2.rpc.listpeers(l1.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] + + assert l1_update_tx == l2_update_tx + assert l1_settle_tx == l2_settle_tx + + # Now we really mess things up! + + # FIXME we need real anchor CPFP + package relay to pay fees + l1_update_details = bitcoind.rpc.decoderawtransaction(l1_update_tx) + l1_settle_details = bitcoind.rpc.decoderawtransaction(l1_settle_tx) + bitcoind.rpc.prioritisetransaction(l1_update_details["txid"], 0, 100000000) + bitcoind.rpc.prioritisetransaction(l1_settle_details["txid"], 0, 100000000) + bitcoind.rpc.sendrawtransaction(l1_update_tx) + + # Mine and mature the update tx + bitcoind.generate_block(6) + + # Symmetrical transactions(!), symmetrical state, mostly + l1.daemon.wait_for_log(' to ONCHAIN') + l2.daemon.wait_for_log(' to ONCHAIN') + + needle_1 = l1.daemon.logsearch_start + needle_2 = l2.daemon.logsearch_start + + # The settle transaction should hit the mempool for both! + l1.wait_for_onchaind_broadcast('ELTOO_SETTLE', + 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') + l2.wait_for_onchaind_broadcast('ELTOO_SETTLE', + 'ELTOO_UPDATE/DELAYED_OUTPUT_TO_US') + + assert len(bitcoind.rpc.getrawmempool()) == 1 + + # We're going to disable transaction relay for the SUCCESS transaction + # To allow us to test broadcast of one transaction at a time + def censoring_sendrawtx(r): + return {'id': r['id'], 'result': {}} + + l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', censoring_sendrawtx) + + # Mine settle tx, then we should see HTLC timeout resolution hit the mempool by the receiver + bitcoind.generate_block(1) + + wait_for(lambda: len(bitcoind.rpc.getrawmempool()) == 1) + + timeout_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) + assert len(timeout_tx['vin'][0]['txinwitness']) == 3 + l2.wait_for_onchaind_broadcast('ELTOO_HTLC_TIMEOUT', + 'ELTOO_SETTLE/OUR_HTLC') + # Stop mining of tx for this next block + bitcoind.rpc.prioritisetransaction(timeout_tx['txid'], 0, -100000000) + # Allow SUCCESS tx to hit mempool next block + l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', None) + + bitcoind.generate_block(1) + + # Should hit mempool; do the log/pool check + l1.wait_for_onchaind_broadcast('ELTOO_HTLC_SUCCESS', + 'ELTOO_SETTLE/THEIR_HTLC') + + success_tx = bitcoind.rpc.getrawtransaction(bitcoind.rpc.getrawmempool()[0], 1) + assert len(success_tx['vin'][0]['txinwitness']) == 4 + + bitcoind.generate_block(1) + + # FIXME Check wallet related things, balances + # FIXME The mounds of memleaks + + # Mine enough blocks to closed out onchaind + bitcoind.generate_block(99) + l1.daemon.wait_for_log('onchaind complete, forgetting peer') + l2.daemon.wait_for_log('onchaind complete, forgetting peer') From 876ff95db2029bc4460322a48d599d8bca412b69 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 5 Jan 2023 15:49:20 -0500 Subject: [PATCH 267/283] oops s/gen/regen/ --- channeld/eltoo_channeld.c | 4 ++-- hsmd/libhsmd.c | 2 +- tests/test_eltoo.py | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 62dc8254e421..3f889ad31ad9 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1987,11 +1987,11 @@ static void peer_reconnect(struct eltoo_peer *peer, */ /* Refresh and fetch MuSig nonce */ - msg = towire_hsmd_gen_nonce(NULL, &peer->channel_id); + msg = towire_hsmd_regen_nonce(NULL, &peer->channel_id); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_gen_nonce_reply(msg, &peer->channel->eltoo_keyset.self_next_nonce)) { + if (!fromwire_hsmd_regen_nonce_reply(msg, &peer->channel->eltoo_keyset.self_next_nonce)) { peer_failed_err(peer->pps, &peer->channel_id, "Failed to get nonce for channel reestablishment: %s", tal_hex(msg, msg)); diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index eb4ac9240655..756390dc00a8 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1599,7 +1599,7 @@ static u8 *handle_regen_nonce(struct hsmd_client *c, const u8 *msg_in) struct secrets secrets; struct nonce fresh_nonce; - if (!fromwire_hsmd_gen_nonce(msg_in, &channel_id)) + if (!fromwire_hsmd_regen_nonce(msg_in, &channel_id)) return hsmd_status_malformed_request(c, msg_in); get_channel_seed(&c->id, c->dbid, &channel_seed); diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index cc00018e2142..69653807d7a0 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -52,12 +52,9 @@ def test_eltoo_empty_reestablishment(node_factory, bitcoind): assert l1_update_details["locktime"] == 500000000 assert l1_settle_details["locktime"] == 500000000 - from pdb import set_trace - set_trace() - # l1 can pay l2 l1.pay(l2, 100000*SAT) - + wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) def test_eltoo_unannounced_hop(node_factory, bitcoind): """Test eltoo payments work over hops""" From 53ecd77fa5914154ea4fd46c62e199e5a42114ca Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 5 Jan 2023 16:26:14 -0500 Subject: [PATCH 268/283] test_eltoo_offerer_ack_reestablishment failing with bad combine_psig message --- channeld/eltoo_channeld.c | 4 ++-- tests/test_eltoo.py | 31 +++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 3f889ad31ad9..2e58a32d1d16 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -2081,7 +2081,7 @@ static void peer_reconnect(struct eltoo_peer *peer, msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { status_failed(STATUS_FAIL_HSM_IO, - "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); + "Bad reestablish combine_psig reply %s", tal_hex(tmpctx, msg)); } /* Migrate over and continue */ @@ -2102,7 +2102,7 @@ static void peer_reconnect(struct eltoo_peer *peer, master_wait_sync_reply(tmpctx, peer, take(msg), WIRE_CHANNELD_GOT_ACK_REPLY); - status_debug("update_signed_ack %s: update = %lu", + status_debug("reestablishment update_signed_ack %s: update = %lu", side_to_str(peer->channel->opener), peer->next_index - 1); } diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index 69653807d7a0..eaca0d3c89f0 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -21,8 +21,35 @@ # In msats SAT = 1000 -def test_eltoo_empty_reestablishment(node_factory, bitcoind): - """Test that channel reestablishment does the expected thing""" +def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): + """Test that channel reestablishment does the expected thing when + update signed ack didn't make it back to offerer. Reestablishment + flow is essentially the offerer getting the ACK back on reconnect """ + + from pdb import set_trace + set_trace() + # Want receiving node to disconnect right before sending off update_signed_ack + disconnects = ['-WIRE_UPDATE_SIGNED_ACK'] + + l1, l2 = node_factory.line_graph(2, + opts=[{'may_reconnect': True}, {'may_reconnect': True, 'disconnect': disconnects}]) + + # Pay comment will cause disconnect, but should recover + l1.pay(l2, 100000*SAT) + + + +def test_eltoo_uneven_reestablishment(node_factory, bitcoind): + """Test that channel reestablishment does the expected thing when + an update signed message was sent but not received by the recipient + before disconnect """ + + l1, l2 = node_factory.line_graph(2, + opts=[{'may_reconnect': True}, {'may_reconnect': True}]) + + +def test_eltoo_base_reestablishment(node_factory, bitcoind): + """Test that channel reestablishment does the expected thing when all prior messages completed """ l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True}, {'may_reconnect': True}]) From 6e83d3ceb194792671c2cf9e5440ce1ab126176f Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 5 Jan 2023 16:28:56 -0500 Subject: [PATCH 269/283] ostensibly complete basic reestablishment tests --- tests/test_eltoo.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index eaca0d3c89f0..3e8643afb6f5 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -37,6 +37,8 @@ def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): # Pay comment will cause disconnect, but should recover l1.pay(l2, 100000*SAT) + wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) + def test_eltoo_uneven_reestablishment(node_factory, bitcoind): @@ -44,9 +46,16 @@ def test_eltoo_uneven_reestablishment(node_factory, bitcoind): an update signed message was sent but not received by the recipient before disconnect """ + # Want offering node to disconnect right before sending off update_signed + disconnects = ['+WIRE_UPDATE_SIGNED'] + l1, l2 = node_factory.line_graph(2, - opts=[{'may_reconnect': True}, {'may_reconnect': True}]) + opts=[{'may_reconnect': True, 'disconnect': disconnects}, {'may_reconnect': True}]) + # Pay comment will cause disconnect, but should recover + l1.pay(l2, 100000*SAT) + + wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) def test_eltoo_base_reestablishment(node_factory, bitcoind): """Test that channel reestablishment does the expected thing when all prior messages completed """ From 5a9a21bb70e27e1e981f30764af482d59662b7f2 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 6 Jan 2023 11:09:57 -0500 Subject: [PATCH 270/283] Fixup committed state in lightningd --- channeld/eltoo_channeld.c | 35 +++++++++++++++++++++++++++++++++++ lightningd/channel.c | 15 +++++++++++++-- tests/test_eltoo.py | 5 +++-- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 2e58a32d1d16..d35cc86ac38a 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1094,6 +1094,10 @@ static void send_update_sign_ack(struct eltoo_peer *peer, /* Tell master daemon about update_sig (and by implication, that we're * sending update_sig_ack), then wait for it to ack. */ + status_debug("Sending our_psig to master right before sending off ACK: %s", + type_to_string(tmpctx, struct partial_sig, our_update_psig)); + status_debug("Sending their_psig to master right before sending off ACK: %s", + type_to_string(tmpctx, struct partial_sig, their_update_psig)); msg_for_master = towire_channeld_got_updatesig(NULL, peer->next_index - 1, @@ -1997,6 +2001,14 @@ static void peer_reconnect(struct eltoo_peer *peer, "Failed to get nonce for channel reestablishment: %s", tal_hex(msg, msg)); } + status_debug("sending eltoo reestablishment update %u, self_psig: %s, next_nonce: %s, session: %s", + last_update_num, + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session)); + + /* Exchange reestablishment message with peer */ msg = towire_channel_reestablish_eltoo(tmpctx, &peer->channel_id, @@ -2068,6 +2080,23 @@ static void peer_reconnect(struct eltoo_peer *peer, peer->channel->eltoo_keyset.last_committed_state.other_psig = remote_update_psig; + status_debug("partial signature reestablish combine our_psig %s their_psig %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s, session %s", + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.other_psig), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_settle_tx), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce), + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session)); + /* Check psig */ msg = towire_hsmd_combine_psig(NULL, &peer->channel_id, @@ -2715,6 +2744,10 @@ static void init_channel(struct eltoo_peer *peer) &peer->channel_update)) { master_badmsg(WIRE_CHANNELD_INIT, msg); } + status_debug("Self psig for committed state: %s", + type_to_string(tmpctx, struct partial_sig, &committed_state.self_psig)); + status_debug("Self psig for complete state: %s", + type_to_string(tmpctx, struct partial_sig, &complete_state.self_psig)); peer->final_index = tal_dup(peer, u32, &final_index); peer->final_ext_key = tal_dup(peer, struct ext_key, &final_ext_key); @@ -2810,6 +2843,8 @@ static void init_channel(struct eltoo_peer *peer) assert(!reestablish_only); } + status_debug("Turn: %s", side_to_str(peer->turn)); + /* If we have a messages to send, send them immediately */ if (fwd_msg) peer_write(peer->pps, take(fwd_msg)); diff --git a/lightningd/channel.c b/lightningd/channel.c index a770b62d0200..0071cf71ae18 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -730,8 +730,19 @@ void channel_set_last_eltoo_txs(struct channel *channel, tal_free(channel->eltoo_keyset.complete_settle_tx); channel->eltoo_keyset.complete_settle_tx = tal_steal(channel, settle_tx); - /* FIXME We also clear out committed */ - + /* We should never have committed txs since we are the one + * receiving the committment from peer */ + assert(!channel->eltoo_keyset.committed_update_tx); + assert(!channel->eltoo_keyset.committed_settle_tx); + + /* In this case this data was not filled out yet, so we fill it + * to allow for channel reestablishment based on these fields. + */ + channel->eltoo_keyset.last_committed_state.other_psig = *their_psig; + channel->eltoo_keyset.last_committed_state.self_psig = *our_psig; + channel->eltoo_keyset.last_committed_state.session = *session; + + /* But it's also complete, will be used for on-chain */ channel->eltoo_keyset.last_complete_state.other_psig = *their_psig; channel->eltoo_keyset.last_complete_state.self_psig = *our_psig; channel->eltoo_keyset.last_complete_state.session = *session; diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index 3e8643afb6f5..0d7847a47773 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -26,14 +26,15 @@ def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): update signed ack didn't make it back to offerer. Reestablishment flow is essentially the offerer getting the ACK back on reconnect """ - from pdb import set_trace - set_trace() # Want receiving node to disconnect right before sending off update_signed_ack disconnects = ['-WIRE_UPDATE_SIGNED_ACK'] l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True}, {'may_reconnect': True, 'disconnect': disconnects}]) + from pdb import set_trace + set_trace() + # Pay comment will cause disconnect, but should recover l1.pay(l2, 100000*SAT) From 8c51c50d37ff0f1a1dbcf3670aedec674a399d5d Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 6 Jan 2023 13:29:23 -0500 Subject: [PATCH 271/283] test_eltoo_offerer_ack_reestablishment working --- channeld/eltoo_channeld.c | 74 +++++++++++++++++++++++++++++++++------ tests/test_eltoo.py | 3 -- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index d35cc86ac38a..b8e5aeced20b 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -146,8 +146,11 @@ struct eltoo_peer { */ u8 channel_flags; - /* Number of update_signed(_ack) messages received by peer */ - u64 updates_received; + /* Number of update_signed(_ack) messages received by peer. + * Should be the same as the update number of the latest + * complete tx. + */ + u64 sigs_received; bool announce_depth_reached; bool channel_local_active; @@ -716,7 +719,7 @@ static bool shutdown_complete(const struct eltoo_peer *peer) return peer->shutdown_sent[LOCAL] && peer->shutdown_sent[REMOTE] && num_channel_htlcs(peer->channel) == 0 - && peer->updates_received == peer->next_index - 1; + && peer->sigs_received == peer->next_index - 1; } /* BOLT #2: @@ -830,8 +833,8 @@ static void send_update(struct eltoo_peer *peer) /* FIXME: Document this requirement in BOLT 2! */ /* We can't send two commits in a row. */ - if (peer->updates_received != peer->next_index - 1) { - assert(peer->updates_received + if (peer->sigs_received != peer->next_index - 1) { + assert(peer->sigs_received == peer->next_index - 2); peer->commit_timer_attempts++; /* Only report this in extreme cases */ @@ -844,6 +847,8 @@ static void send_update(struct eltoo_peer *peer) peer->commit_timer = NULL; start_update_timer(peer); return; + } else { + peer->commit_timer_attempts = 0; } /* BOLT #2: @@ -987,7 +992,6 @@ static void start_update_timer(struct eltoo_peer *peer) if (peer->commit_timer) return; - peer->commit_timer_attempts = 0; peer->commit_timer = new_reltimer(&peer->timers, peer, time_from_msec(peer->commit_msec), send_update, peer); @@ -1150,7 +1154,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) peer_failed_warn(peer->pps, &peer->channel_id, "Bad update_signed %s", tal_hex(msg, msg)); - peer->updates_received++; + peer->sigs_received++; status_debug("Received update_sig"); @@ -1303,7 +1307,7 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) "Bad update_signed_ack %s", tal_hex(msg, msg)); } - peer->updates_received++; + peer->sigs_received++; status_debug("partial signature combine req on update tx %s, settle tx %s, our_psig: %s," " their_psig: %s, session %s, OLD our nonce %s, OLD their nonce %s", @@ -1893,6 +1897,8 @@ static void resend_updates(struct eltoo_peer *peer, struct changed_htlc *last) status_debug("Retransmitting update"); + peer->can_yield = false; + /* Note that HTLCs must be *added* in order. Simplest thing to do * is to sort them all into ascending ID order here (we could do * this when we save them in channel_sending_commit, but older versions @@ -1964,6 +1970,14 @@ static void resend_updates(struct eltoo_peer *peer, struct changed_htlc *last) /* No blockheight info (yet) */ + /* Give up our turn */ + if (is_our_turn(peer)){ + change_turn(peer, REMOTE); + } else { + /* We are not doing optimistic updates */ + status_broken("We're proposing updates out of turn?"); + } + /* Resend psig and FRESH nonce */ msg = towire_update_signed(NULL, &peer->channel_id, &peer->channel->eltoo_keyset.last_committed_state.self_psig, @@ -1978,6 +1992,8 @@ static void peer_reconnect(struct eltoo_peer *peer, struct channel_id channel_id; u64 remote_last_update_num; struct partial_sig remote_update_psig; + const struct htlc *resend_htlc; + struct htlc_map_iter resend_it; const u8 **premature_msgs = tal_arr(peer, const u8 *, 0); u32 last_update_num = peer->next_index - 1; /* This should still be valid even if we received an ack for this committed state */ @@ -2142,6 +2158,7 @@ static void peer_reconnect(struct eltoo_peer *peer, * We ignore their psig and replay our turn with fresh nonces. */ peer->turn = LOCAL; + /* This directly sends update, no commit timer. */ resend_updates(peer, peer->last_sent_commit); } else if (remote_last_update_num == last_update_num + 1) { /* They say they committed but we didn't get it. @@ -2159,6 +2176,34 @@ static void peer_reconnect(struct eltoo_peer *peer, last_update_num); } + /* Now stop, we've been polite long enough. */ + if (reestablish_only) { + /* If we were successfully closing, we still go to closingd. */ + if (shutdown_complete(peer)) { + send_shutdown_complete(peer); + daemon_shutdown(); + exit(0); + } + peer_failed_err(peer->pps, + &peer->channel_id, + "Channel is already closed"); + } + + /* Corner case: we didn't send shutdown before because update_add_htlc + * pending, but now they're cleared by restart, and we're actually + * complete. In that case, their `shutdown` will trigger us. */ + + /* Now, re-send any that we're supposed to be failing/fulfilling. */ + for (resend_htlc = htlc_map_first(peer->channel->htlcs, &resend_it); + resend_htlc; + resend_htlc = htlc_map_next(peer->channel->htlcs, &resend_it)) { + if (resend_htlc->state == SENT_REMOVE_HTLC) + send_fail_or_fulfill(peer, resend_htlc); + } + + /* Reset timer again since we just added more */ + start_update_timer(peer); + /* We allow peer to send us tx-sigs, until funding locked received */ peer->tx_sigs_allowed = true; peer_billboard(true, "Reconnected, and reestablished."); @@ -2717,7 +2762,7 @@ static void init_channel(struct eltoo_peer *peer) &peer->cltv_delta, &peer->last_sent_commit, &peer->next_index, - &peer->updates_received, + &peer->sigs_received, &peer->htlc_id, &htlcs, &peer->funding_locked[LOCAL], @@ -2749,6 +2794,13 @@ static void init_channel(struct eltoo_peer *peer) status_debug("Self psig for complete state: %s", type_to_string(tmpctx, struct partial_sig, &complete_state.self_psig)); + /* FIXME Never set/updated on master side, don't need it */ + assert(peer->sigs_received == 0); + if (complete_update_tx) { + /* If it's complete, that means I received that update */ + peer->sigs_received = complete_update_tx->wtx->locktime - 500000000; + } + peer->final_index = tal_dup(peer, u32, &final_index); peer->final_ext_key = tal_dup(peer, struct ext_key, &final_ext_key); @@ -2763,10 +2815,10 @@ static void init_channel(struct eltoo_peer *peer) status_debug("init %s: " " next_idx = %"PRIu64 - " updates_received = %"PRIu64, + " sigs_received = %"PRIu64, side_to_str(opener), peer->next_index, - peer->updates_received); + peer->sigs_received); if (remote_ann_node_sig && remote_ann_bitcoin_sig) { peer->announcement_node_sigs[REMOTE] = *remote_ann_node_sig; diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index 0d7847a47773..4b164e2754f5 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -32,9 +32,6 @@ def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True}, {'may_reconnect': True, 'disconnect': disconnects}]) - from pdb import set_trace - set_trace() - # Pay comment will cause disconnect, but should recover l1.pay(l2, 100000*SAT) From 2ff8dc340827ee1a3d930797a5a4b3c3bc9817d0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 6 Jan 2023 13:45:17 -0500 Subject: [PATCH 272/283] Add some asserts that should break in other cases --- channeld/eltoo_channeld.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index b8e5aeced20b..28f5385e00a5 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -2193,16 +2193,20 @@ static void peer_reconnect(struct eltoo_peer *peer, * pending, but now they're cleared by restart, and we're actually * complete. In that case, their `shutdown` will trigger us. */ + /* FIXME FIXME we can't send these unless it's our turn! Need to defer + * actions, or something */ /* Now, re-send any that we're supposed to be failing/fulfilling. */ for (resend_htlc = htlc_map_first(peer->channel->htlcs, &resend_it); resend_htlc; resend_htlc = htlc_map_next(peer->channel->htlcs, &resend_it)) { - if (resend_htlc->state == SENT_REMOVE_HTLC) + if (resend_htlc->state == SENT_REMOVE_HTLC) { send_fail_or_fulfill(peer, resend_htlc); + /* FIXME this will obviously(?) break if we sent removal updates + but not an update, then lose our turn on reconnect? */ + assert(is_our_turn(peer)); + } } - - /* Reset timer again since we just added more */ - start_update_timer(peer); + start_update_timer(peer); /* We allow peer to send us tx-sigs, until funding locked received */ peer->tx_sigs_allowed = true; From e8d1830a2f421badedd8156a9dfaf2c28c867060 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 6 Jan 2023 15:05:10 -0500 Subject: [PATCH 273/283] More plausible support for reestablishments during htlc removal --- channeld/eltoo_channeld.c | 43 ++++++++++++++++++++++++--------------- tests/test_eltoo.py | 15 ++++++++++++-- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 28f5385e00a5..a1ef6e7d94e1 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -140,6 +140,7 @@ struct eltoo_peer { #endif /* Information used for reestablishment. */ struct changed_htlc *last_sent_commit; + bool sent_uncommitted_removals; /* Have we sent uncommitted removals on reconnect? */ /* FIXME figure out what goes here bool last_was_revoke; u64 revocations_received; @@ -807,12 +808,34 @@ static u8 *master_wait_sync_reply(const tal_t *ctx, return reply; } +static void send_fail_or_fulfill(struct eltoo_peer *peer, const struct htlc *h); + +static void maybe_send_uncommitted_removals(struct eltoo_peer *peer) +{ + const struct htlc *resend_htlc; + struct htlc_map_iter resend_it; + if (is_our_turn(peer) && !peer->sent_uncommitted_removals) { + for (resend_htlc = htlc_map_first(peer->channel->htlcs, &resend_it); + resend_htlc; + resend_htlc = htlc_map_next(peer->channel->htlcs, &resend_it)) { + if (resend_htlc->state == SENT_REMOVE_HTLC) { + send_fail_or_fulfill(peer, resend_htlc); + } + } + /* May have sent something */ + start_update_timer(peer); + peer->sent_uncommitted_removals = true; + } +} + static void change_turn(struct eltoo_peer *peer, enum side turn) { assert(peer->turn == !turn); peer->turn = turn; peer->can_yield = true; status_debug("turn is now %s", side_to_str(turn)); + + maybe_send_uncommitted_removals(peer); } static void send_update(struct eltoo_peer *peer) @@ -1992,8 +2015,6 @@ static void peer_reconnect(struct eltoo_peer *peer, struct channel_id channel_id; u64 remote_last_update_num; struct partial_sig remote_update_psig; - const struct htlc *resend_htlc; - struct htlc_map_iter resend_it; const u8 **premature_msgs = tal_arr(peer, const u8 *, 0); u32 last_update_num = peer->next_index - 1; /* This should still be valid even if we received an ack for this committed state */ @@ -2193,20 +2214,9 @@ static void peer_reconnect(struct eltoo_peer *peer, * pending, but now they're cleared by restart, and we're actually * complete. In that case, their `shutdown` will trigger us. */ - /* FIXME FIXME we can't send these unless it's our turn! Need to defer - * actions, or something */ - /* Now, re-send any that we're supposed to be failing/fulfilling. */ - for (resend_htlc = htlc_map_first(peer->channel->htlcs, &resend_it); - resend_htlc; - resend_htlc = htlc_map_next(peer->channel->htlcs, &resend_it)) { - if (resend_htlc->state == SENT_REMOVE_HTLC) { - send_fail_or_fulfill(peer, resend_htlc); - /* FIXME this will obviously(?) break if we sent removal updates - but not an update, then lose our turn on reconnect? */ - assert(is_our_turn(peer)); - } - } - start_update_timer(peer); + /* Now, re-send any that we're supposed to be failing. (or send later as soon + * as it's our turn) */ + maybe_send_uncommitted_removals(peer); /* We allow peer to send us tx-sigs, until funding locked received */ peer->tx_sigs_allowed = true; @@ -2934,6 +2944,7 @@ int main(int argc, char *argv[]) peer->shutdown_wrong_funding = NULL; peer->last_update_timestamp = 0; peer->last_empty_commitment = 0; + peer->sent_uncommitted_removals = false; #if EXPERIMENTAL_FEATURES peer->stfu = false; peer->stfu_sent[LOCAL] = peer->stfu_sent[REMOTE] = false; diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index 4b164e2754f5..b8f83b8e476a 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -21,6 +21,19 @@ # In msats SAT = 1000 +def test_uncommitted_reestablishment(node_factory, bitcoind): + + # Want offering node to disconnect right afer sending off update_xxx_htlc + disconnects = ['+WIRE_UPDATE_FULFILL_HTLC'] + + l1, l2 = node_factory.line_graph(2, + opts=[{'may_reconnect': True}, {'may_reconnect': True, 'disconnect': disconnects}]) + + # Pay comment will cause disconnect, but should recover + l1.pay(l2, 100000*1000) + + wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) + def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): """Test that channel reestablishment does the expected thing when update signed ack didn't make it back to offerer. Reestablishment @@ -37,8 +50,6 @@ def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) - - def test_eltoo_uneven_reestablishment(node_factory, bitcoind): """Test that channel reestablishment does the expected thing when an update signed message was sent but not received by the recipient From 4958e5119111e3b72c56d4e5daf515749d21e649 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 6 Jan 2023 15:18:22 -0500 Subject: [PATCH 274/283] Test another uncommited reestablishment scenario --- tests/test_eltoo.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index b8f83b8e476a..739942f1d03a 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -16,12 +16,13 @@ import re import subprocess import threading +import time import unittest # In msats SAT = 1000 -def test_uncommitted_reestablishment(node_factory, bitcoind): +def test_uncommitted_removal_reestablishment(node_factory, bitcoind): # Want offering node to disconnect right afer sending off update_xxx_htlc disconnects = ['+WIRE_UPDATE_FULFILL_HTLC'] @@ -34,6 +35,28 @@ def test_uncommitted_reestablishment(node_factory, bitcoind): wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) +def test_uncommitted_addition_reestablishment(node_factory, bitcoind): + + # Want offering node to disconnect right afer sending off update_xxx_htlc + disconnects = ['+WIRE_UPDATE_ADD_HTLC'] + + l1, l2 = node_factory.line_graph(2, + opts=[{'may_reconnect': True, 'disconnect': disconnects}, {'may_reconnect': True}]) + + # Pay comment will cause disconnect, and payment should fail hard + try: + l1.pay(l2, 100000*1000) + raise Exception('Should have raised RPCError') + except RpcError: + # FIXME better way of waiting for channel to be ready? + time.sleep(5) + pass + + # But otherwise be ok on follow-up attempts + l1.pay(l2, 150000*1000) + + wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(150000000)) + def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): """Test that channel reestablishment does the expected thing when update signed ack didn't make it back to offerer. Reestablishment From 9f9af9132ef8628f936b9edafffcdf01ebb2579f Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Fri, 6 Jan 2023 16:26:41 -0500 Subject: [PATCH 275/283] fixup one test where it breaks --- channeld/eltoo_channeld.c | 4 ---- tests/test_eltoo.py | 13 +++++++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index a1ef6e7d94e1..e82b999c642f 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -2111,10 +2111,6 @@ static void peer_reconnect(struct eltoo_peer *peer, const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); struct bip340sig update_sig; -// if (memcmp(remote_update_psig.p_sig.data, -// peer->channel->eltoo_keyset->last_complete_state.other_psig, -// sizeof(remote_update_psig.p_sig.data)) != 0) { - peer->channel->eltoo_keyset.last_committed_state.other_psig = remote_update_psig; status_debug("partial signature reestablish combine our_psig %s their_psig %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s, session %s", diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index 739942f1d03a..b8794a39c6c0 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -71,15 +71,20 @@ def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): # Pay comment will cause disconnect, but should recover l1.pay(l2, 100000*SAT) + # Offerer gets new partial sig on reestablishment + l1.daemon.wait_for_log("partial signature reestablish combine our_psig") + wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) +# FIXME getting psig combiner error here on the pay command def test_eltoo_uneven_reestablishment(node_factory, bitcoind): """Test that channel reestablishment does the expected thing when - an update signed message was sent but not received by the recipient + an update signed message was "sent" but not received by the recipient before disconnect """ # Want offering node to disconnect right before sending off update_signed - disconnects = ['+WIRE_UPDATE_SIGNED'] + # So on reconnect offerer must replay all updates. + disconnects = ['-WIRE_UPDATE_SIGNED'] l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, 'disconnect': disconnects}, {'may_reconnect': True}]) @@ -87,6 +92,10 @@ def test_eltoo_uneven_reestablishment(node_factory, bitcoind): # Pay comment will cause disconnect, but should recover l1.pay(l2, 100000*SAT) + # Offerer sends whole update again + l1.daemon.wait_for_log('Retransmitting update') + l2.daemon.wait_for_log('Received update_sig') + wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) def test_eltoo_base_reestablishment(node_factory, bitcoind): From 5aa9e70db8666bce5a722650789154247fc02862 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 9 Jan 2023 13:34:54 -0500 Subject: [PATCH 276/283] uneven test working, need to cleanup keyagg cache lifecycle --- bitcoin/signature.c | 39 ++++++++++ bitcoin/signature.h | 19 +++++ channeld/channeld.c | 2 + channeld/channeld_wire.csv | 9 +++ channeld/eltoo_channeld.c | 139 +++++++++++++++++++++++++++++++---- common/keyset.h | 4 + hsmd/hsmd_wire.csv | 1 + hsmd/libhsmd.c | 14 ++-- lightningd/channel_control.c | 4 + lightningd/peer_htlcs.c | 50 ++++++++++++- lightningd/peer_htlcs.h | 1 + openingd/eltoo_openingd.c | 6 +- wallet/test/run-wallet.c | 6 ++ 13 files changed, 271 insertions(+), 23 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 3c25c25de425..5020335afee6 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -351,6 +351,32 @@ bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * co return secp256k1_schnorrsig_verify(secp256k1_ctx, sig->u8, hash->sha.u.u8, sizeof(hash->sha.u.u8), &xonly_inner_pubkey); } +bool bipmusig_partial_sig_verify(const struct partial_sig *p_sig, + const struct nonce *signer_nonce, + const struct pubkey *signer_pk, + const struct musig_keyagg_cache *keyagg_cache, + struct musig_session *session) +{ + int ret; + secp256k1_xonly_pubkey xonly_inner_pubkey; + + ret = secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, + &xonly_inner_pubkey, + NULL /* pk_parity */, + &signer_pk->pubkey); + + if (!ret) { + return false; + } + + return secp256k1_musig_partial_sig_verify(secp256k1_ctx, + &p_sig->p_sig, + &signer_nonce->nonce, + &xonly_inner_pubkey, + &keyagg_cache->cache, + &session->session); +} + bool bipmusig_partial_sigs_combine(const secp256k1_musig_partial_sig * const *p_sigs, size_t num_signers, const secp256k1_musig_session *session, @@ -764,6 +790,19 @@ char *fmt_musig_session(const tal_t *ctx, const struct musig_session *musig_sess REGISTER_TYPE_TO_HEXSTR(musig_session); +void towire_musig_keyagg_cache(u8 **pptr, const struct musig_keyagg_cache *cache) +{ + /* No proper serialization/parsing supplied, we're just copying bytes */ + towire_u8_array(pptr, cache->cache.data, sizeof(cache->cache.data)); +} + +void fromwire_musig_keyagg_cache(const u8 **cursor, size_t *max, + struct musig_keyagg_cache *cache){ + /* No proper serialization/parsing supplied, we're just copying bytes */ + if (!fromwire(cursor, max, cache->cache.data, sizeof(cache->cache.data))) + return; +} + /* BIP-340: * * This proposal suggests to include the tag by prefixing the hashed diff --git a/bitcoin/signature.h b/bitcoin/signature.h index e13ec492b3e7..f32e8d9faabe 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -1,6 +1,7 @@ #ifndef LIGHTNING_BITCOIN_SIGNATURE_H #define LIGHTNING_BITCOIN_SIGNATURE_H #include "config.h" +#include #include #include #include @@ -39,6 +40,11 @@ struct musig_session { secp256k1_musig_session session; }; +/* Primarily used to validate partial signatures separately */ +struct musig_keyagg_cache { + secp256k1_musig_keyagg_cache cache; +}; + #define SIGHASH_MASK 0x7F static inline bool sighash_single(enum sighash_type sighash_type) @@ -217,6 +223,15 @@ bool bipmusig_partial_sigs_combine(const secp256k1_musig_partial_sig * const *p_ const secp256k1_musig_session *session, struct bip340sig *sig); +/** + * bipmusig_partial_sig_verify - Verifies partial signatures separately + */ +bool bipmusig_partial_sig_verify(const struct partial_sig *p_sig, + const struct nonce *signer_nonce, + const struct pubkey *signer_pk, + const struct musig_keyagg_cache *keyagg_cache, + struct musig_session *session); + /** * check_signed_hash - check a raw secp256k1 signature. * @h: hash which was signed. @@ -337,6 +352,10 @@ void towire_musig_session(u8 **pptr, const struct musig_session *session); void fromwire_musig_session(const u8 **cursor, size_t *max, struct musig_session *session); +void towire_musig_keyagg_cache(u8 **pptr, const struct musig_keyagg_cache *cache); +void fromwire_musig_keyagg_cache(const u8 **cursor, size_t *max, + struct musig_keyagg_cache *cache); + /* Get a hex string sig */ char *fmt_signature(const tal_t *ctx, const secp256k1_ecdsa_signature *sig); char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig); diff --git a/channeld/channeld.c b/channeld/channeld.c index 6475ded381b8..df3777d9c645 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -3745,6 +3745,8 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_GOT_SHUTDOWN_ELTOO: case WIRE_CHANNELD_SENDING_UPDATESIG: case WIRE_CHANNELD_SENDING_UPDATESIG_REPLY: + case WIRE_CHANNELD_RESENDING_UPDATESIG: + case WIRE_CHANNELD_RESENDING_UPDATESIG_REPLY: case WIRE_CHANNELD_INIT_ELTOO: case WIRE_CHANNELD_GOT_ACK_REPLY: break; diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index fb990031de3d..815585fe2529 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -407,3 +407,12 @@ msgdata,channeld_sending_updatesig,settle_tx,bitcoin_tx, # Wait for reply, to make sure it's on disk before we send commit. msgtype,channeld_sending_updatesig_reply,1180 + +# Reestablishment message to update MuSig2 signing state +msgtype,channeld_resending_updatesig,1085 +msgdata,channeld_resending_updatesig,update_num,u64, +msgdata,channeld_resending_updatesig,our_update_p_sig,partial_sig, +msgdata,channeld_resending_updatesig,session,musig_session, + +# Wait for reply, to make sure it's on disk before we send commit. +msgtype,channeld_resending_updatesig_reply,1185 diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index e82b999c642f..58dd0077dd58 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -714,6 +714,19 @@ static u8 *sending_updatesig_msg(const tal_t *ctx, return msg; } +static u8 *resending_updatesig_msg(const tal_t *ctx, + u64 update_index, + const struct partial_sig *our_update_psig, + const struct musig_session *session) +{ + u8 *msg; + + /* Informing master of our new psig and session */ + msg = towire_channeld_resending_updatesig(ctx, update_index, + our_update_psig, session); + return msg; +} + static bool shutdown_complete(const struct eltoo_peer *peer) { /* FIXME last line is very wrong */ @@ -846,6 +859,7 @@ static void send_update(struct eltoo_peer *peer) struct bitcoin_tx **update_and_settle_txs; const struct htlc **htlc_map; struct wally_tx_output *direct_outputs[NUM_SIDES]; + struct musig_keyagg_cache cache; #if DEVELOPER if (peer->dev_disable_commit && !*peer->dev_disable_commit) { @@ -854,18 +868,17 @@ static void send_update(struct eltoo_peer *peer) } #endif - /* FIXME: Document this requirement in BOLT 2! */ /* We can't send two commits in a row. */ if (peer->sigs_received != peer->next_index - 1) { assert(peer->sigs_received - == peer->next_index - 2); + == peer->next_index - 2); peer->commit_timer_attempts++; /* Only report this in extreme cases */ if (peer->commit_timer_attempts % 100 == 0) status_debug("Can't send commit:" - " waiting for update_ack with %" - PRIu64" attempts", - peer->commit_timer_attempts); + " waiting for update_ack with %" + PRIu64" attempts", + peer->commit_timer_attempts); /* Mark this as done and try again. */ peer->commit_timer = NULL; start_update_timer(peer); @@ -932,7 +945,7 @@ static void send_update(struct eltoo_peer *peer) &peer->channel->eltoo_keyset.other_next_nonce)); hsmd_msg = hsm_req(tmpctx, take(msg)); - if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) + if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey, &cache)) status_failed(STATUS_FAIL_HSM_IO, "Reading psign_update_tx reply: %s", tal_hex(tmpctx, msg)); @@ -1154,6 +1167,7 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) struct bip340sig update_sig; const struct htlc **htlc_map, **changed_htlcs; struct nonce their_next_nonce; + struct musig_keyagg_cache cache; changed_htlcs = tal_arr(msg, const struct htlc *, 0); /* Does our counterparty offer any changes? */ @@ -1217,14 +1231,26 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) type_to_string(tmpctx, struct nonce, &peer->channel->eltoo_keyset.other_next_nonce)); - /* Slide their newest nonce into place after consuming it above */ - peer->channel->eltoo_keyset.other_next_nonce = their_next_nonce; - wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey)) + if (!fromwire_hsmd_psign_update_tx_reply(msg, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey, &cache)) { status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); + } + + /* Keyagg cache/session etc lets us verify partial sig; do that for blame purposes */ + if (!bipmusig_partial_sig_verify(&peer->channel->eltoo_keyset.last_committed_state.other_psig, + &peer->channel->eltoo_keyset.other_next_nonce, + &peer->channel->eltoo_keyset.other_funding_key, + &cache, + &peer->channel->eltoo_keyset.last_committed_state.session)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_signed; invalid partial signature %s", tal_hex(msg, msg)); + } + + /* Slide their newest nonce into place after checking psig above */ + peer->channel->eltoo_keyset.other_next_nonce = their_next_nonce; + status_debug("partial signature combine our_psig %s their_psig %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, NEW their nonce %s, session %s", type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), @@ -1243,6 +1269,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) &peer->channel->eltoo_keyset.other_next_nonce), type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session)); + + /* Before replying, make sure signature is correct */ msg = towire_hsmd_combine_psig(NULL, &peer->channel_id, @@ -1323,6 +1351,7 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) const u8 *comb_msg; struct bip340sig update_sig; const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); + //struct musig_keyagg_cache cache; if (!fromwire_update_signed_ack(msg, &channel_id, &peer->channel->eltoo_keyset.last_committed_state.other_psig, &peer->channel->eltoo_keyset.other_next_nonce)) { @@ -1356,6 +1385,17 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) wire_sync_write(HSM_FD, take(comb_msg)); comb_msg = wire_sync_read(tmpctx, HSM_FD); +// FIXME FIXME failure? +// /* Keyagg cache/session etc lets us verify partial sig; do that for blame purposes */ +// if (!bipmusig_partial_sig_verify(&peer->channel->eltoo_keyset.last_committed_state.other_psig, +// &peer->channel->eltoo_keyset.other_next_nonce, +// &peer->channel->eltoo_keyset.other_funding_key, +// &cache, +// &peer->channel->eltoo_keyset.last_committed_state.session)) { +// peer_failed_warn(peer->pps, &peer->channel_id, +// "Bad update_signed; invalid partial signature %s", tal_hex(msg, msg)); +// } + if (!fromwire_hsmd_combine_psig_reply(comb_msg, &update_sig)) status_failed(STATUS_FAIL_HSM_IO, "Bad hsmd_combine_psig_reply: %s", @@ -1913,13 +1953,21 @@ static int cmp_changed_htlc_id(const struct changed_htlc *a, return 0; } +/* Stripped-down htlc_x and `send_update` routine to avoid mucking in persisted state + * specifically for reestablishment + */ static void resend_updates(struct eltoo_peer *peer, struct changed_htlc *last) { size_t i; u8 *msg; + const u8 *hsmd_msg; + struct musig_keyagg_cache cache; +// /* We're replaying old state, decrement in memory before sending */ +// peer->next_index--; status_debug("Retransmitting update"); + /* Cannot yield after sending an update */ peer->can_yield = false; /* Note that HTLCs must be *added* in order. Simplest thing to do @@ -1993,7 +2041,70 @@ static void resend_updates(struct eltoo_peer *peer, struct changed_htlc *last) /* No blockheight info (yet) */ - /* Give up our turn */ + /* Finally, send off new psigned upated and continue */ + + /* Transactions are already cached since we offered, just need to re-partial-sign */ + status_debug("Re-signing channel txs for reestablishment"); + msg = towire_hsmd_psign_update_tx(tmpctx, + &peer->channel_id, + peer->channel->eltoo_keyset.committed_update_tx, + peer->channel->eltoo_keyset.committed_settle_tx, + &peer->channel->eltoo_keyset.other_funding_key, + &peer->channel->eltoo_keyset.other_next_nonce, + &peer->channel->eltoo_keyset.self_next_nonce); + + status_debug("partial signature reestablish req %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, OLD our nonce %s, OLD their nonce %s", + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_settle_tx), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce)); + + hsmd_msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_psign_update_tx_reply(hsmd_msg, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.last_committed_state.session, &peer->channel->eltoo_keyset.self_next_nonce, &peer->channel->eltoo_keyset.inner_pubkey, &cache)) + status_failed(STATUS_FAIL_HSM_IO, + "Reading psign_update_tx reply: %s", + tal_hex(tmpctx, msg)); + + /* We don't learn their new nonce until we get ACK... */ + status_debug("partial signature reestablish %s on update tx %s, settle tx %s, using our key %s, their key %s, inner pubkey %s, NEW our nonce %s, OLD their nonce %s, session %s", + type_to_string(tmpctx, struct partial_sig, &peer->channel->eltoo_keyset.last_committed_state.self_psig), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, peer->channel->eltoo_keyset.committed_settle_tx), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.self_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.other_funding_key), + type_to_string(tmpctx, struct pubkey, + &peer->channel->eltoo_keyset.inner_pubkey), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct nonce, + &peer->channel->eltoo_keyset.other_next_nonce), + type_to_string(tmpctx, struct musig_session, &peer->channel->eltoo_keyset.last_committed_state.session)); + + /* Need to store new partial sig/session for follow-on reestablishment attempts */ + msg = resending_updatesig_msg(NULL, peer->next_index - 1, /* it's the last state we already committed to */ + &peer->channel->eltoo_keyset.last_committed_state.self_psig, + &peer->channel->eltoo_keyset.last_committed_state.session); + /* Message is empty; receiving it is the point. */ + master_wait_sync_reply(tmpctx, peer, take(msg), + WIRE_CHANNELD_RESENDING_UPDATESIG_REPLY); + + status_debug("Sending reestablishment update_sig"); + + /* + * - MUST give up its turn when: + * - sending `update_signed` + */ if (is_our_turn(peer)){ change_turn(peer, REMOTE); } else { @@ -2001,11 +2112,11 @@ static void resend_updates(struct eltoo_peer *peer, struct changed_htlc *last) status_broken("We're proposing updates out of turn?"); } - /* Resend psig and FRESH nonce */ msg = towire_update_signed(NULL, &peer->channel_id, &peer->channel->eltoo_keyset.last_committed_state.self_psig, &peer->channel->eltoo_keyset.self_next_nonce); - peer_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); + } static void peer_reconnect(struct eltoo_peer *peer, @@ -2695,6 +2806,8 @@ static void req_in(struct eltoo_peer *peer, const u8 *msg) case WIRE_CHANNELD_GOT_SHUTDOWN_ELTOO: case WIRE_CHANNELD_SENDING_UPDATESIG: case WIRE_CHANNELD_SENDING_UPDATESIG_REPLY: + case WIRE_CHANNELD_RESENDING_UPDATESIG: + case WIRE_CHANNELD_RESENDING_UPDATESIG_REPLY: case WIRE_CHANNELD_INIT_ELTOO: break; } diff --git a/common/keyset.h b/common/keyset.h index 0ebaa6d4c887..7ac2b209c69a 100644 --- a/common/keyset.h +++ b/common/keyset.h @@ -27,6 +27,10 @@ struct eltoo_keyset { /* MuSig2 key using funding keys as input, session non-empty once partial sig created locally! */ struct pubkey inner_pubkey; + /* Cache for partial signature verification when checking + * sigs against inner_pubkey + */ + struct musig_keyagg_cache inner_cache; struct nonce self_next_nonce, other_next_nonce; /* State we can go to chain with at any point. */ struct eltoo_sign last_complete_state; diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 17d0a2b681ee..58f73f1322bb 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -325,6 +325,7 @@ msgdata,hsmd_psign_update_tx_reply,update_psig,partial_sig, msgdata,hsmd_psign_update_tx_reply,session,musig_session, msgdata,hsmd_psign_update_tx_reply,next_nonce,nonce, msgdata,hsmd_psign_update_tx_reply,inner_pubkey,pubkey, +msgdata,hsmd_psign_update_tx_reply,cache,musig_keyagg_cache, msgtype,hsmd_validate_update_tx_psig,163 msgdata,hsmd_validate_update_tx_psig,channel_id,channel_id, diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 756390dc00a8..7c97531fcb6f 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1481,8 +1481,8 @@ static u8 *handle_combine_psig(struct hsmd_client *c, const u8 *msg_in) &session.session, &hash_out, &sig)) { - /* FIXME better complaint from hsmd */ - return hsmd_status_malformed_request(c, msg_in); + return hsmd_status_bad_request(c, msg_in, + "Failed to verify combined psigs"); } return towire_hsmd_combine_psig_reply(NULL, &sig); } @@ -1504,7 +1504,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) /* MuSig stuff */ struct pubkey inner_pubkey; - secp256k1_musig_keyagg_cache keyagg_cache; + struct musig_keyagg_cache cache; const struct pubkey *pubkey_ptrs[2]; const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; u8 *annex; @@ -1544,7 +1544,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) pubkey_ptrs[0] = &remote_funding_pubkey; pubkey_ptrs[1] = &local_funding_pubkey; bipmusig_inner_pubkey(&inner_pubkey, - &keyagg_cache, + &cache.cache, pubkey_ptrs, /* n_pubkeys */ 2); @@ -1574,7 +1574,7 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) pubnonce_ptrs, /* num_signers */ 2, &hash_out, - &keyagg_cache, + &cache.cache, &session.session, &p_sig.p_sig); @@ -1582,10 +1582,10 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) bipmusig_gen_nonce(&musig_state_lookup->sec_nonce, &local_nonce.nonce, &secrets.funding_privkey, - &keyagg_cache, + &cache.cache, hash_out.sha.u.u8); - return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &local_nonce, &inner_pubkey); + return towire_hsmd_psign_update_tx_reply(NULL, &p_sig, &session, &local_nonce, &inner_pubkey, &cache); } /* Should only be used if nonce for funded channel exists and new one will be sent to co-signer diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 76392e215b8b..f047e663907e 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -600,6 +600,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_SENDING_UPDATESIG: peer_sending_updatesig(sd->channel, msg); break; + case WIRE_CHANNELD_RESENDING_UPDATESIG: + peer_resending_updatesig(sd->channel, msg); + break; case WIRE_CHANNELD_GOT_ACK: peer_got_ack(sd->channel, msg); break; @@ -608,6 +611,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_GOT_ACK_REPLY: case WIRE_CHANNELD_GOT_SHUTDOWN_ELTOO: case WIRE_CHANNELD_SENDING_UPDATESIG_REPLY: + case WIRE_CHANNELD_RESENDING_UPDATESIG_REPLY: #if EXPERIMENTAL_FEATURES case WIRE_CHANNELD_UPGRADED: handle_channel_upgrade(sd->channel, msg); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index fa99c31b8016..e61e5188b025 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1949,7 +1949,7 @@ static bool peer_save_updatesig_sent(struct channel *channel, channel_internal_error(channel, "channel_sent_updatesig: expected update_num %"PRIu64 " got %"PRIu64, - channel->next_index[REMOTE], update_num); + channel->next_index[LOCAL], update_num); return false; } @@ -1964,6 +1964,29 @@ static bool peer_save_updatesig_sent(struct channel *channel, return true; } +static bool peer_save_updatesig_resent(struct channel *channel, + u64 update_num, + struct partial_sig *our_psig, + struct musig_session *session) +{ + struct lightningd *ld = channel->peer->ld; + + /* Should be a repeat */ + if (update_num != channel->next_index[LOCAL] - 1) { + channel_internal_error(channel, + "channel_resent_updatesig: expected update_num %"PRIu64 + " got %"PRIu64, + channel->next_index[LOCAL] - 1, update_num); + return false; + } + + channel->eltoo_keyset.last_committed_state.self_psig = *our_psig; + channel->eltoo_keyset.last_committed_state.session = *session; + + wallet_channel_save(ld->wallet, channel); + return true; +} + static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) { if (feerate > channel->max_possible_feerate) @@ -2022,6 +2045,31 @@ void peer_got_ack(struct channel *channel, const u8 *msg) } +void peer_resending_updatesig(struct channel *channel, const u8 *msg) +{ + u64 update_num; + struct partial_sig our_update_psig; + struct musig_session session; + + if (!fromwire_channeld_resending_updatesig(msg, + &update_num, + &our_update_psig, + &session)) { + channel_internal_error(channel, "bad channel_resending_updatesig %s", + tal_hex(channel, msg)); + return; + } + + + /* Add newest state to channel, then save to db */ + if (!peer_save_updatesig_resent(channel, update_num, &our_update_psig, &session)) + return; + + /* Tell it we've got it, and to go ahead. */ + subd_send_msg(channel->owner, + take(towire_channeld_resending_updatesig_reply(msg))); +} + void peer_sending_updatesig(struct channel *channel, const u8 *msg) { u64 update_num; diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 5cd04581ece9..12921a933d1b 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -37,6 +37,7 @@ void peer_got_commitsig(struct channel *channel, const u8 *msg); void peer_got_revoke(struct channel *channel, const u8 *msg); void peer_sending_updatesig(struct channel *channel, const u8 *msg); +void peer_resending_updatesig(struct channel *channel, const u8 *msg); void peer_got_updatesig(struct channel *channel, const u8 *msg); void peer_got_ack(struct channel *channel, const u8 *msg); diff --git a/openingd/eltoo_openingd.c b/openingd/eltoo_openingd.c index d34146ae7c86..faf2f48f304c 100644 --- a/openingd/eltoo_openingd.c +++ b/openingd/eltoo_openingd.c @@ -463,6 +463,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, struct channel_id cid; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct bip340sig update_sig; + struct musig_keyagg_cache cache; /* Dummy fields since they're unused at time of channel creation */ struct eltoo_sign dummy_complete_state; @@ -595,7 +596,7 @@ static bool funder_finalize_channel_setup(struct eltoo_state *state, msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_psign_update_tx_reply(msg, &state->channel->eltoo_keyset.last_committed_state.self_psig, - &state->channel->eltoo_keyset.last_committed_state.session, &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey)) + &state->channel->eltoo_keyset.last_committed_state.session, &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey, &cache)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); @@ -778,6 +779,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) struct wally_tx_output *direct_outputs[NUM_SIDES]; /* Stored here before channel struct is made, then copied in */ struct nonce their_second_nonce; + struct musig_keyagg_cache cache; /* Dummy fields since they're unused at time of channel creation */ struct eltoo_sign dummy_complete_state; @@ -1119,7 +1121,7 @@ static u8 *fundee_channel(struct eltoo_state *state, const u8 *open_channel_msg) /* Reply puts next nonce into keyset and xmitted with funding_signed_eltoo */ if (!fromwire_hsmd_psign_update_tx_reply(msg, &state->channel->eltoo_keyset.last_committed_state.self_psig, &state->channel->eltoo_keyset.last_committed_state.session, - &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey)) + &state->channel->eltoo_keyset.self_next_nonce, &state->channel->eltoo_keyset.inner_pubkey, &cache)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 47a4e87b6f42..a44f61a619cb 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -178,6 +178,9 @@ bool fromwire_channeld_got_updatesig(const tal_t *ctx UNNEEDED, const void *p UN /* Generated stub for fromwire_channeld_offer_htlc_reply */ bool fromwire_channeld_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *id UNNEEDED, u8 **failuremsg UNNEEDED, wirestring **failurestr UNNEEDED) { fprintf(stderr, "fromwire_channeld_offer_htlc_reply called!\n"); abort(); } +/* Generated stub for fromwire_channeld_resending_updatesig */ +bool fromwire_channeld_resending_updatesig(const void *p UNNEEDED, u64 *update_num UNNEEDED, struct partial_sig *our_update_p_sig UNNEEDED, struct musig_session *session UNNEEDED) +{ fprintf(stderr, "fromwire_channeld_resending_updatesig called!\n"); abort(); } /* Generated stub for fromwire_channeld_sending_commitsig */ bool fromwire_channeld_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct penalty_base **pbase UNNEEDED, struct fee_states **fee_states UNNEEDED, struct height_states **blockheight_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_signature *commit_sig UNNEEDED, struct bitcoin_signature **htlc_sigs UNNEEDED) { fprintf(stderr, "fromwire_channeld_sending_commitsig called!\n"); abort(); } @@ -785,6 +788,9 @@ u8 *towire_channeld_got_updatesig_reply(const tal_t *ctx UNNEEDED) /* Generated stub for towire_channeld_offer_htlc */ u8 *towire_channeld_offer_htlc(const tal_t *ctx UNNEEDED, struct amount_msat amount_msat UNNEEDED, u32 cltv_expiry UNNEEDED, const struct sha256 *payment_hash UNNEEDED, const u8 onion_routing_packet[1366] UNNEEDED, const struct pubkey *blinding UNNEEDED) { fprintf(stderr, "towire_channeld_offer_htlc called!\n"); abort(); } +/* Generated stub for towire_channeld_resending_updatesig_reply */ +u8 *towire_channeld_resending_updatesig_reply(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "towire_channeld_resending_updatesig_reply called!\n"); abort(); } /* Generated stub for towire_channeld_sending_commitsig_reply */ u8 *towire_channeld_sending_commitsig_reply(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channeld_sending_commitsig_reply called!\n"); abort(); } From 7c5c8fc392fbe819c6d1fd74edfe71e0b80d1e9e Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 9 Jan 2023 13:41:59 -0500 Subject: [PATCH 277/283] Send failures instead of crashing hsmd on combine failure --- channeld/eltoo_channeld.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 58dd0077dd58..199522f7bbb1 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -1283,8 +1283,8 @@ static void handle_peer_update_sig(struct eltoo_peer *peer, const u8 *msg) wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { - status_failed(STATUS_FAIL_HSM_IO, - "Bad combine_psig reply %s", tal_hex(tmpctx, msg)); + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_sig %s", tal_hex(msg, msg)); } /* Now that we've checked the update, migrate all signing state from last_committed_state to last_complete_state */ @@ -1385,21 +1385,9 @@ static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) wire_sync_write(HSM_FD, take(comb_msg)); comb_msg = wire_sync_read(tmpctx, HSM_FD); -// FIXME FIXME failure? -// /* Keyagg cache/session etc lets us verify partial sig; do that for blame purposes */ -// if (!bipmusig_partial_sig_verify(&peer->channel->eltoo_keyset.last_committed_state.other_psig, -// &peer->channel->eltoo_keyset.other_next_nonce, -// &peer->channel->eltoo_keyset.other_funding_key, -// &cache, -// &peer->channel->eltoo_keyset.last_committed_state.session)) { -// peer_failed_warn(peer->pps, &peer->channel_id, -// "Bad update_signed; invalid partial signature %s", tal_hex(msg, msg)); -// } - if (!fromwire_hsmd_combine_psig_reply(comb_msg, &update_sig)) - status_failed(STATUS_FAIL_HSM_IO, - "Bad hsmd_combine_psig_reply: %s", - tal_hex(tmpctx, comb_msg)); + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_signed_ack %s", tal_hex(msg, msg)); /* Update looks good, move state over and wipe committed */ migrate_committed_to_complete(peer); @@ -2253,8 +2241,8 @@ static void peer_reconnect(struct eltoo_peer *peer, wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); if (!fromwire_hsmd_combine_psig_reply(msg, &update_sig)) { - status_failed(STATUS_FAIL_HSM_IO, - "Bad reestablish combine_psig reply %s", tal_hex(tmpctx, msg)); + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad reestablish psig %s", tal_hex(msg, msg)); } /* Migrate over and continue */ From 9dfb3ef6bf24bb0c76173d115ca04751a0cd794b Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 9 Jan 2023 13:47:42 -0500 Subject: [PATCH 278/283] rephrase --- channeld/eltoo_channeld.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c index 199522f7bbb1..39a0c30d6410 100644 --- a/channeld/eltoo_channeld.c +++ b/channeld/eltoo_channeld.c @@ -2278,8 +2278,9 @@ static void peer_reconnect(struct eltoo_peer *peer, resend_updates(peer, peer->last_sent_commit); } else if (remote_last_update_num == last_update_num + 1) { /* They say they committed but we didn't get it. - * We will not use the psig. - * It's their turn; return to normal operation with fresh nonces. + * We will not use the psig in this message. + * It's their turn; return to normal operation with fresh nonces + * since we expect rebroadcast. */ peer->turn = REMOTE; } else { From 23278daa86df76af201c7fe2b39cebae36bfbc52 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Feb 2023 15:52:45 -0500 Subject: [PATCH 279/283] untested: fix the commit-to-no-taptree musig implementation --- bitcoin/signature.c | 27 ++++++++++++++++----------- tests/test_eltoo.py | 2 ++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 5020335afee6..7e82317cdee6 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -216,6 +216,8 @@ void bipmusig_finalize_keys(struct pubkey *agg_pk, int i, ok; unsigned char taptweak_preimage[64]; secp256k1_xonly_pubkey agg_x_key; + struct pubkey tmp_inner_pubkey; + size_t key_len = 33; assert(n_pubkeys <= 100); /* Sorting moves pubkeys themselves, we copy and discard after */ @@ -244,26 +246,29 @@ void bipmusig_finalize_keys(struct pubkey *agg_pk, assert(ok); - if (inner_pubkey) { - ok = secp256k1_musig_pubkey_get(secp256k1_ctx, - &inner_pubkey->pubkey, - keyagg_cache); + ok = secp256k1_musig_pubkey_get(secp256k1_ctx, + &tmp_inner_pubkey.pubkey, + keyagg_cache); - assert(ok); - } - - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &agg_x_key); + assert(ok); - assert(ok); + if (inner_pubkey) { + *inner_pubkey = tmp_inner_pubkey; + } if (!tap_merkle_root) { /* No-tapscript recommended commitment: Q = P + int(hashTapTweak(bytes(P)))G */ - ok = wally_tagged_hash(taptweak_preimage, 32, "TapTweak", tap_tweak_out); + ok = secp256k1_ec_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &key_len, &tmp_inner_pubkey.pubkey, SECP256K1_EC_COMPRESSED); + assert(key_len == 33); + ok = wally_tagged_hash(taptweak_preimage, key_len, "TapTweak", tap_tweak_out); assert(ok == WALLY_OK); ok = secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_ctx, &(agg_pk->pubkey), keyagg_cache, tap_tweak_out); assert(ok); } else { - /* Otherwise: Q = P + int(hashTapTweak(bytes(P)||tap_merkle_root))G */ + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &agg_x_key); + assert(ok); + + /* Otherwise: Q = P + int(hashTapTweak(p||tap_merkle_root))G */ memcpy(taptweak_preimage + 32, tap_merkle_root->u.u8, sizeof(tap_merkle_root->u.u8)); ok = wally_tagged_hash(taptweak_preimage, sizeof(taptweak_preimage), "TapTweak", tap_tweak_out); assert(ok == WALLY_OK); diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index b8794a39c6c0..4a34cc0a6e6a 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -113,6 +113,8 @@ def test_eltoo_base_reestablishment(node_factory, bitcoind): l1.daemon.wait_for_log('Reconnected, and reestablished') l2.daemon.wait_for_log('Reconnected, and reestablished') + from pdb import set_trace + set_trace() l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] From 60b8df2a6723d56feafc83ccd20a48da43a52d29 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 21 Feb 2023 16:34:28 -0500 Subject: [PATCH 280/283] Revert "untested: fix the commit-to-no-taptree musig implementation" This reverts commit 23278daa86df76af201c7fe2b39cebae36bfbc52. I was mistaken; BIP is just a bit confusing --- bitcoin/signature.c | 27 +++++++++++---------------- tests/test_eltoo.py | 2 -- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/bitcoin/signature.c b/bitcoin/signature.c index 7e82317cdee6..5020335afee6 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -216,8 +216,6 @@ void bipmusig_finalize_keys(struct pubkey *agg_pk, int i, ok; unsigned char taptweak_preimage[64]; secp256k1_xonly_pubkey agg_x_key; - struct pubkey tmp_inner_pubkey; - size_t key_len = 33; assert(n_pubkeys <= 100); /* Sorting moves pubkeys themselves, we copy and discard after */ @@ -246,29 +244,26 @@ void bipmusig_finalize_keys(struct pubkey *agg_pk, assert(ok); - ok = secp256k1_musig_pubkey_get(secp256k1_ctx, - &tmp_inner_pubkey.pubkey, - keyagg_cache); - - assert(ok); - if (inner_pubkey) { - *inner_pubkey = tmp_inner_pubkey; + ok = secp256k1_musig_pubkey_get(secp256k1_ctx, + &inner_pubkey->pubkey, + keyagg_cache); + + assert(ok); } + ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &agg_x_key); + + assert(ok); + if (!tap_merkle_root) { /* No-tapscript recommended commitment: Q = P + int(hashTapTweak(bytes(P)))G */ - ok = secp256k1_ec_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &key_len, &tmp_inner_pubkey.pubkey, SECP256K1_EC_COMPRESSED); - assert(key_len == 33); - ok = wally_tagged_hash(taptweak_preimage, key_len, "TapTweak", tap_tweak_out); + ok = wally_tagged_hash(taptweak_preimage, 32, "TapTweak", tap_tweak_out); assert(ok == WALLY_OK); ok = secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_ctx, &(agg_pk->pubkey), keyagg_cache, tap_tweak_out); assert(ok); } else { - ok = secp256k1_xonly_pubkey_serialize(secp256k1_ctx, taptweak_preimage, &agg_x_key); - assert(ok); - - /* Otherwise: Q = P + int(hashTapTweak(p||tap_merkle_root))G */ + /* Otherwise: Q = P + int(hashTapTweak(bytes(P)||tap_merkle_root))G */ memcpy(taptweak_preimage + 32, tap_merkle_root->u.u8, sizeof(tap_merkle_root->u.u8)); ok = wally_tagged_hash(taptweak_preimage, sizeof(taptweak_preimage), "TapTweak", tap_tweak_out); assert(ok == WALLY_OK); diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index 4a34cc0a6e6a..b8794a39c6c0 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -113,8 +113,6 @@ def test_eltoo_base_reestablishment(node_factory, bitcoind): l1.daemon.wait_for_log('Reconnected, and reestablished') l2.daemon.wait_for_log('Reconnected, and reestablished') - from pdb import set_trace - set_trace() l1_update_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_update_tx'] l1_settle_tx = l1.rpc.listpeers(l2.info['id'])["peers"][0]["channels"][0]['last_settle_tx'] From 60a7cc2fc0e7f69c51c1aa1a7c07e3dad7afd310 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Tue, 14 Mar 2023 16:41:33 -0400 Subject: [PATCH 281/283] Adapt eltoo implementation to bitcoin-inquisition annex support --- bitcoin/script.c | 7 +++---- channeld/test/run-settle_tx.c | 2 +- common/update_tx.c | 7 ++++--- contrib/pyln-testing/pyln/testing/utils.py | 5 ----- tests/test_eltoo.py | 3 +-- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index e57d71f31c08..8c0ccfded09c 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1042,8 +1042,7 @@ void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t n unsigned char tag_hash_buf[1000]; /* Needs to be large enough for HTLC scripts */ unsigned char tap_hashes[64]; /* To store the leaves for comparison */ - /* FIXME 2 scripts is broken somehow, use compute_taptree_merkle_root_with_hint instead - * Only what's required for eltoo et al for now, sue me */ + /* Only what's required for eltoo et al for now, sue me */ assert(num_scripts == 1 || num_scripts == 2); if (num_scripts == 1) { size_t script_len = tal_count(scripts[0]); @@ -1106,7 +1105,7 @@ void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, co size_t script_len = tal_count(update_tapscript); unsigned char *p = tag_hash_buf; - assert(tal_count(invalidated_annex_hint) == 33 && invalidated_annex_hint[0] == 0x50); + assert(tal_count(invalidated_annex_hint) == 34 && invalidated_annex_hint[0] == 0x50); /* Let k0 = hashTapLeaf(v || compact_size(size of s) || s); also call it the tapleaf hash. */ p[0] = leaf_version; @@ -1119,7 +1118,7 @@ void compute_taptree_merkle_root_with_hint(struct sha256 *update_merkle_root, co assert(ok == WALLY_OK); /* Put invalidated hint in place as a tapleaf hash directly */ - memcpy(tap_hashes + 32, invalidated_annex_hint + 1, 32); + memcpy(tap_hashes + 32, invalidated_annex_hint + 2, 32); /* If kj ≥ ej: kj+1 = hashTapBranch(ej || kj), swap them*/ if (memcmp(tap_hashes, tap_hashes + 32, 32) >= 0) { diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c index f50dd0b86644..0f0d2fe0cee5 100644 --- a/channeld/test/run-settle_tx.c +++ b/channeld/test/run-settle_tx.c @@ -819,7 +819,7 @@ static int test_htlc_output_creation(void) /* Cross-check merkle root calculations between functions */ compute_taptree_merkle_root(&tap_merkle_root, tapleaf_scripts, /* num_scripts */ 2); success_annex = make_annex_from_script(tmpctx, htlc_success_script); - assert(tal_count(success_annex) == 33); /* TapLeaf hash + annex prefix */ + assert(tal_count(success_annex) == 34); /* annex prefix plus hash length plus TapLeaf hash + */ assert(success_annex[0] == 0x50); compute_taptree_merkle_root_with_hint(&tap_merkle_root_annex, htlc_timeout_script, success_annex); assert(memcmp(tap_merkle_root.u.u8, tap_merkle_root_annex.u.u8, sizeof(tap_merkle_root.u.u8)) == 0); diff --git a/common/update_tx.c b/common/update_tx.c index 688df9226c5c..8e55e0bf9cd7 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -31,8 +31,8 @@ u8 *make_annex_from_script(const tal_t *ctx, const u8 *script) u8 *preimage_cursor; u64 tapscript_len = tal_count(script); u8 *tapleaf_preimage = tal_arr(ctx, u8, 1 + varint_size(tapscript_len) + tapscript_len); - /* Enough space for annex flag plus the one hash we want published */ - u8 *annex = tal_arr(ctx, u8, 1 + sizeof(result.u.u8)); + /* Enough space for annex flag plus hash length and one hash we want published */ + u8 *annex = tal_arr(ctx, u8, 1 + 1 + sizeof(result.u.u8)); preimage_cursor = tapleaf_preimage; preimage_cursor[0] = 0xC0; @@ -46,7 +46,8 @@ u8 *make_annex_from_script(const tal_t *ctx, const u8 *script) assert(ok == WALLY_OK); annex[0] = 0x50; /* annex flag */ - memcpy(annex + 1, result.u.u8, sizeof(result)); + annex[1] = 32; /* payload length */ + memcpy(annex + 2, result.u.u8, sizeof(result)); return annex; } diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index ce1ebd37e6da..66161764ca81 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -390,11 +390,6 @@ def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None): '-debug=1', ] - # Only for eltoo testing - if os.environ.get('BITCOIND_ELTOO_ARGS'): - self.cmd_line.append("-trueoutputs=1") - self.cmd_line.append("-annexcarrier=1") - # For up to and including 0.16.1, this needs to be in main section. BITCOIND_CONFIG['rpcport'] = rpcport # For after 0.16.1 (eg. 3f398d7a17f136cd4a67998406ca41a124ae2966), this diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index b8794a39c6c0..8bd808a2ae7c 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -76,7 +76,6 @@ def test_eltoo_offerer_ack_reestablishment(node_factory, bitcoind): wait_for(lambda: l2.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(100000000)) -# FIXME getting psig combiner error here on the pay command def test_eltoo_uneven_reestablishment(node_factory, bitcoind): """Test that channel reestablishment does the expected thing when an update signed message was "sent" but not received by the recipient @@ -157,7 +156,7 @@ def test_eltoo_unannounced_hop(node_factory, bitcoind): wait_for(lambda: l3.rpc.listpeers()['peers'][0]['channels'][0]['in_fulfilled_msat'] == Millisatoshi(200010000)) # Example flags to run test -# DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_ELTOO_ARGS=1 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/bitcoin/src/bitcoind pytest -s tests/test_eltoo.py -k test_eltoo_htlc +# DEBUG_SUBD=eltoo_onchaind VALGRIND=0 BITCOIND_TEST_PATH=/home/greg/bitcoin-dev/lightning/eltoo_bitcoind pytest -s tests/test_eltoo.py -k test_eltoo_htlc @pytest.mark.developer("needs dev-disable-commit-after") def test_eltoo_htlc(node_factory, bitcoind, executor, chainparams): """Test HTLC resolution via eltoo_onchaind after a single successful payment""" From 864ac82e24c54a41dc74df65adbcf7d34fa237a0 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 16 Mar 2023 14:37:33 -0400 Subject: [PATCH 282/283] fixup compute_control_block --- bitcoin/script.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bitcoin/script.c b/bitcoin/script.c index 8c0ccfded09c..8d7ea1213651 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -1181,9 +1181,10 @@ u8 *compute_control_block(const tal_t *ctx, const u8 *other_script, const u8 *an assert(ok == WALLY_OK); control_block_cursor += 32; } else if (annex_hint) { - assert(tal_count(annex_hint) == 33); + assert(tal_count(annex_hint) == 34); assert(annex_hint[0] == 0x50); - memcpy(control_block_cursor, annex_hint + 1, 32); + assert(annex_hint[1] == 32); + memcpy(control_block_cursor, annex_hint + 2, 32); control_block_cursor += 32; } return control_block; From be3919d9814579e6c8fb42c49c2efc9fcb5cb91f Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Thu, 16 Mar 2023 14:38:18 -0400 Subject: [PATCH 283/283] Have update txns get an ephemeral anchor, remove test's prioritisetransaction call --- common/update_tx.c | 11 ++++++++++- common/update_tx.h | 2 ++ hsmd/libhsmd.c | 4 ++-- tests/test_eltoo.py | 4 ++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/common/update_tx.c b/common/update_tx.c index 8e55e0bf9cd7..549d9a39e1d7 100644 --- a/common/update_tx.c +++ b/common/update_tx.c @@ -16,6 +16,12 @@ struct wally_psbt; +void tx_update_add_ephemeral_anchor(struct bitcoin_tx *tx) +{ + u8 *spk = bitcoin_spk_ephemeral_anchor(tmpctx); + bitcoin_tx_add_output(tx, spk, /* wscript */ NULL, AMOUNT_SAT(0)); +} + int tx_add_state_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx) { struct amount_sat amount; @@ -386,12 +392,15 @@ struct bitcoin_tx *unbound_update_tx(const tal_t *ctx, int pos; /* 1 input 1 output tx */ - update_tx = bitcoin_tx(ctx, chainparams, 1, 1, 0); + update_tx = bitcoin_tx(ctx, chainparams, 1, 2, 0); /* Add output */ pos = tx_add_state_output(update_tx, settle_tx); assert(pos == 0); + /* Add ephemeral anchor */ + tx_update_add_ephemeral_anchor(update_tx); + /* Add unsigned, un-bound funding input */ tx_add_unbound_input(update_tx, funding_sats, inner_pubkey); diff --git a/common/update_tx.h b/common/update_tx.h index b9ad0186b5f6..250ea2c4c54e 100644 --- a/common/update_tx.h +++ b/common/update_tx.h @@ -13,6 +13,8 @@ struct bitcoin_outpoint; /* Generates the "state" output for eltoo update transaction, based on the settlement tx */ int tx_add_state_output(struct bitcoin_tx *update_tx, const struct bitcoin_tx *settle_tx); +void tx_update_add_ephemeral_anchor(struct bitcoin_tx *tx); + /* Generates TapLeaf hash of script, with annex byte prepended */ u8 *make_annex_from_script(const tal_t *ctx, const u8 *script); diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 7c97531fcb6f..50ccd368b03d 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1530,9 +1530,9 @@ static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) return hsmd_status_bad_request(c, msg_in, "update tx must have 1 input"); - if (update_tx->wtx->num_outputs != 1) + if (update_tx->wtx->num_outputs != 2) return hsmd_status_bad_request_fmt(c, msg_in, - "update tx must have 1 output"); + "update tx must have 2 outputs"); get_channel_seed(&c->id, c->dbid, &channel_seed); derive_basepoints(&channel_seed, diff --git a/tests/test_eltoo.py b/tests/test_eltoo.py index 8bd808a2ae7c..cc69dcd0356a 100644 --- a/tests/test_eltoo.py +++ b/tests/test_eltoo.py @@ -213,8 +213,8 @@ def test_eltoo_htlc(node_factory, bitcoind, executor, chainparams): # FIXME we need real anchor CPFP + package relay to pay fees l1_update_details = bitcoind.rpc.decoderawtransaction(l1_update_tx) l1_settle_details = bitcoind.rpc.decoderawtransaction(l1_settle_tx) - bitcoind.rpc.prioritisetransaction(l1_update_details["txid"], 0, 100000000) - bitcoind.rpc.prioritisetransaction(l1_settle_details["txid"], 0, 100000000) + + # N.B. We rely on bitcoin-inquisition imputing 1 sat/vbyte on txs with EAs bitcoind.rpc.sendrawtransaction(l1_update_tx) # Mine and mature the update tx