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/.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/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/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/pubkey.c b/bitcoin/pubkey.c index 00ce2f1398ab..5132757449a1 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]; @@ -159,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/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/script.c b/bitcoin/script.c index 316388696548..8d7ea1213651 100644 --- a/bitcoin/script.c +++ b/bitcoin/script.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -10,6 +11,8 @@ #include #include +#include + /* To push 0-75 bytes onto stack. */ #define OP_PUSHBYTES(val) (val) @@ -86,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]; @@ -111,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); @@ -310,6 +339,48 @@ 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) +{ + 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 @@ -481,6 +552,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) @@ -501,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] = stack_bip340sig(witness, sig, SIGHASH_DEFAULT); + witness[0] = tal_dup_arr(witness, u8, elem, elemsize, 0); + + 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 @@ -886,3 +1023,289 @@ 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; +} + +void compute_taptree_merkle_root(struct sha256 *hash_out, u8 **scripts, size_t num_scripts) +{ + 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 */ + + /* 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; + /* 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, 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 == WALLY_OK); + } else if (num_scripts == 2) { + /* First script */ + 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. */ + p[0] = leaf_version; + p++; + p += varint_put(p, script_len); + memcpy(p, scripts[0], script_len); + p += script_len; + + ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", tap_hashes); + assert(ok == WALLY_OK); + + /* Second script */ + script_len = tal_count(scripts[1]); + 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, scripts[1], script_len); + p += script_len; + + ok = wally_tagged_hash(tag_hash_buf, p - tag_hash_buf, "TapLeaf", tap_hashes + 32); + assert(ok == WALLY_OK); + + /* 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", hash_out->u.u8); + assert(ok == WALLY_OK); + } +} + +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) == 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; + 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 + 2, 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, 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)); + + 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(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, + &xonly_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 == WALLY_OK); + control_block_cursor += 32; + } else if (annex_hint) { + assert(tal_count(annex_hint) == 34); + assert(annex_hint[0] == 0x50); + assert(annex_hint[1] == 32); + memcpy(control_block_cursor, annex_hint + 2, 32); + control_block_cursor += 32; + } + return control_block; +} + +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; + 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]; + + /* 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 anyways. + */ + bitcoin_tx_taproot_hash_for_sig(settle_tx, + input_index, + sh_type, + script, + /* annex */ NULL, + &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); + + memcpy(sig_with_flag, sig.u8, sizeof(sig.u8)); + sig_with_flag[64] = sh_type; + + /* Build the script */ + 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; +} + +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_CHECKLOCKTIMEVERIFY); + return script; +} + +u8 *make_eltoo_funding_update_script(const tal_t *ctx) +{ + /* where EXPR_UPDATE(n) = + * + *`<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_CHECKSIG); + return script; +} + +u8 *make_eltoo_htlc_success_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, const struct ripemd160 *invoice_hash) +{ + /* where EXPR_SUCCESS = + * + * ` 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); + add_op(&script, OP_CHECKSIGVERIFY); + add_op(&script, OP_SIZE); + add_number(&script, 32); + add_op(&script, OP_EQUALVERIFY); + add_op(&script, OP_HASH160); + script_push_bytes(&script, invoice_hash->u.u8, sizeof(invoice_hash->u.u8)); + add_op(&script, OP_EQUAL); + return script; +} + +u8 *make_eltoo_htlc_timeout_script(const tal_t *ctx, const struct pubkey *settlement_pubkey, u32 htlc_timeout) +{ + /* and EXPR_TIMEOUT = + * + * ` OP_CHECKSIGVERIFY N OP_CHECKLOCKTIMEVERIFY` + */ + u8 *script = tal_arr(ctx, u8, 0); + add_push_xonly_key(&script, settlement_pubkey); + add_op(&script, OP_CHECKSIGVERIFY); + add_number(&script, htlc_timeout); + add_op(&script, OP_CHECKLOCKTIMEVERIFY); + return script; +} diff --git a/bitcoin/script.h b/bitcoin/script.h index 89f225ae860f..c96da0dbba51 100644 --- a/bitcoin/script.h +++ b/bitcoin/script.h @@ -53,6 +53,12 @@ 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); + /* Create an output script for a 20-byte witness program. */ u8 *scriptpubkey_p2wpkh(const tal_t *ctx, const struct pubkey *key); @@ -86,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, @@ -153,6 +167,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); @@ -165,6 +185,44 @@ 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); + +/* 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); + +/* 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, 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: + * CovSig(n) 1_G OP_CHECKSIG + */ +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); + +/* 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 */ +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); + /* OP_DUP + OP_HASH160 + PUSH(20-byte-hash) + OP_EQUALVERIFY + OP_CHECKSIG */ #define BITCOIN_SCRIPTPUBKEY_P2PKH_LEN (1 + 1 + 1 + 20 + 1 + 1) @@ -177,4 +235,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 4e0cda8ada98..5020335afee6 100644 --- a/bitcoin/signature.c +++ b/bitcoin/signature.c @@ -10,6 +10,13 @@ #include #include #include +#include + +#include + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif #undef DEBUG #ifdef DEBUG @@ -31,6 +38,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 +66,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 +84,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) { } @@ -124,6 +138,253 @@ 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_xonly_pubkey pubkey; + 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); + + + 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 bipmusig_inner_pubkey(struct pubkey *inner_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + 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 */, + 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, + 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, + struct pubkey *inner_pubkey) +{ + int i, ok; + unsigned char taptweak_preimage[64]; + secp256k1_xonly_pubkey agg_x_key; + 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 */, + &agg_x_key, + keyagg_cache, + x_keys_ptr, + n_pubkeys); + + 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); + + 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); + ok = secp256k1_musig_pubkey_xonly_tweak_add(secp256k1_ctx, &(agg_pk->pubkey), keyagg_cache, tap_tweak_out); + assert(ok); + } +} + +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 */ + /* FIXME Does it help at all to get 32 more bytes of randomness? */ + 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, + const secp256k1_musig_pubnonce * const *pubnonces, + size_t num_signers, + struct sha256_double *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->sha.u.u8, cache, /* adaptor */ NULL); + + assert(ok); + + 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); +} + +bool bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, + size_t num_signers, + 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); + + if (!ret) { + return false; + } + + 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, + 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, @@ -157,6 +418,40 @@ void bitcoin_tx_hash_for_sig(const struct bitcoin_tx *tx, unsigned int in, tal_wally_end(tx->wtx); } +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; + + /* 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), (sighash_type & SIGHASH_ANYPREVOUTANYSCRIPT) == SIGHASH_ANYPREVOUTANYSCRIPT ? 0x01 : 0x00 /* key_version */, + 0xFFFFFFFF /* codesep_position */, annex, tal_count(annex), 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, @@ -174,10 +469,36 @@ 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); } +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_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, 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 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); +} + bool check_signed_hash(const struct sha256_double *hash, const secp256k1_ecdsa_signature *signature, const struct pubkey *key) @@ -198,6 +519,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, @@ -219,11 +549,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, /* annex */ NULL, &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; } @@ -378,6 +734,48 @@ 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) +{ + 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, + 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_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 */ + 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, sizeof(session->session.data))) + return; +} + char *fmt_bip340sig(const tal_t *ctx, const struct bip340sig *bip340sig) { return tal_hexstr(ctx, bip340sig->u8, sizeof(bip340sig->u8)); @@ -385,6 +783,26 @@ 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); + +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 @@ -415,3 +833,45 @@ 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); +} + +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, + NULL); + + return scriptpubkey_p2tr(ctx, &taproot_pubkey); +} diff --git a/bitcoin/signature.h b/bitcoin/signature.h index 29d368148430..f32e8d9faabe 100644 --- a/bitcoin/signature.h +++ b/bitcoin/signature.h @@ -1,22 +1,48 @@ #ifndef LIGHTNING_BITCOIN_SIGNATURE_H #define LIGHTNING_BITCOIN_SIGNATURE_H #include "config.h" +#include #include #include #include +#include +#include +struct sha256; struct sha256_double; struct sha256_ctx; struct bitcoin_tx; struct pubkey; +struct point32; struct privkey; struct bitcoin_tx_output; enum sighash_type { + SIGHASH_DEFAULT = 0, SIGHASH_ALL = 1, SIGHASH_NONE = 2, SIGHASH_SINGLE = 3, - SIGHASH_ANYONECANPAY = 0x80 + SIGHASH_ANYONECANPAY = 0x80, + SIGHASH_ANYPREVOUTANYSCRIPT = 0xC0, +}; + +/* Schnorr */ +struct bip340sig { + u8 u8[64]; +}; + +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; +}; + +/* Primarily used to validate partial signatures separately */ +struct musig_keyagg_cache { + secp256k1_musig_keyagg_cache cache; }; #define SIGHASH_MASK 0x7F @@ -61,6 +87,23 @@ 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 + * @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); + /** * sign_hash - produce a raw secp256k1 signature (with low R value). * @p: secret key @@ -71,6 +114,124 @@ void sign_hash(const struct privkey *p, const struct sha256_double *h, secp256k1_ecdsa_signature *sig); +/** + * bip340_sign_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); + +/** + * bipmusig_inner_pubkey - produce the sorted taproot inner pubkey using sort order. + * @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(struct pubkey *inner_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + const struct pubkey * const* pubkeys, + size_t n_pubkeys); + +/** + * bipmusig_finalize_keys - Aggregate keys in lexigraphically + * sorted order, tweaks required for keyspend, + * and initializes the cache required for signing + * sessions + * @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. + 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, + struct pubkey *inner_pubkey); + +/** + * bipmusig_gen_nonce - Generates session id, private + * 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 (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, + 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 + * 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, + struct sha256_double *msg32, + secp256k1_musig_keyagg_cache *cache, + secp256k1_musig_session *session, + secp256k1_musig_partial_sig *p_sig); + +/** + * 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 bipmusig_partial_sigs_combine_verify(const secp256k1_musig_partial_sig * const *p_sigs, + size_t num_signers, + const struct pubkey *agg_pk, + secp256k1_musig_session *session, + 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); + +/** + * 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. @@ -84,6 +245,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. @@ -103,6 +277,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. @@ -121,6 +311,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); @@ -132,17 +340,27 @@ 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); +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); + +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); +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, @@ -150,4 +368,10 @@ 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); + +/* 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/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..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 @@ -95,10 +95,18 @@ 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) { 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 29d0ed8ab0f7..d915f8ffa38f 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -183,12 +183,56 @@ 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 struct 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, struct amount_sat amount, const u8 *scriptPubkey, - const u8 *input_wscript) + const u8 *input_wscript, const struct pubkey *inner_pubkey, + const u8 *tap_tree) { + /* FIXME use inner_pubkey and tap_tree */ int wally_err; int input_num = tx->wtx->num_inputs; @@ -225,6 +269,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 cb0903ccf40d..b4a1cb0a1989 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 @@ -103,9 +104,21 @@ 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 struct pubkey *inner_pubkey); + /* 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 +126,11 @@ 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); + +/* 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, diff --git a/channeld/Makefile b/channeld/Makefile index bdab8ffa0c13..510abed7d3b6 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -8,21 +8,42 @@ 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) $(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 @@ -59,7 +80,9 @@ 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 \ common/key_derive.o \ common/memleak.o \ @@ -85,6 +108,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 \ @@ -100,4 +124,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/channeld.c b/channeld/channeld.c index 72cd437bfdd2..df3777d9c645 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: @@ -2285,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(); } @@ -3721,6 +3738,17 @@ 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: + 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_RESENDING_UPDATESIG: + case WIRE_CHANNELD_RESENDING_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 3a40416f6c1c..223707199065 100644 --- a/channeld/channeld_htlc.h +++ b/channeld/channeld_htlc.h @@ -38,6 +38,11 @@ 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); @@ -72,6 +77,20 @@ 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 b2179908b0d4..815585fe2529 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -275,3 +275,144 @@ 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 + +# Begin! (passes gossipd-client fd) +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, +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_config,channel_config, +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,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, +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,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, +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, +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 + +# 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, +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 +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 + +# 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,their_next_nonce,nonce, + +# 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, +# 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 + +# 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/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/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/channeld/eltoo_channeld.c b/channeld/eltoo_channeld.c new file mode 100644 index 000000000000..39a0c30d6410 --- /dev/null +++ b/channeld/eltoo_channeld.c @@ -0,0 +1,3158 @@ +/* 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 +#include + +/* stdin == requests, 3 == peer, 4 = HSM */ +#define MASTER_FD STDIN_FILENO +#define HSM_FD 4 + +struct eltoo_peer { + struct per_peer_state *pps; + bool funding_locked[NUM_SIDES]; + u64 next_index; /* update number for next update_* messages */ + + /* Features peer supports. */ + u8 *their_features; + + /* Features we support. */ + struct feature_set *our_features; + + /* 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; + + /* 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; + /* 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 + /* 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. */ + 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; + */ + u8 channel_flags; + + /* 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; + + /* 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; + + /* 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 eltoo_peer *peer); +static void start_update_timer(struct eltoo_peer *peer); + +static void billboard_update(const struct eltoo_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); +} + +/* 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; + + /* 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 eltoo_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 eltoo_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); +} + +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; + } 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 */ +static bool handle_master_request_later(struct eltoo_peer *peer, const u8 *msg) +{ + return false; +} + +static void maybe_send_stfu(struct eltoo_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 eltoo_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 eltoo_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 eltoo_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 eltoo_peer *peer) +{ + return; + /* 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 eltoo_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 eltoo_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 eltoo_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 eltoo_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. + */ + /* FIXME no announcements for now */ + 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 eltoo_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; + + if (!fromwire_funding_locked_eltoo(msg, &chanid)) + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad funding_locked_eltoo %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))); + + channel_announcement_negotiate(peer); + billboard_update(peer); +} + +static void handle_peer_announcement_signatures(struct eltoo_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 eltoo_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 = eltoo_channel_add_htlc(peer->channel, REMOTE, id, amount, + cltv_expiry, &payment_hash, + 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)); +} + +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_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 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, 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, committed_update_tx, committed_settle_tx); + 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 */ + return peer->shutdown_sent[LOCAL] + && peer->shutdown_sent[REMOTE] + && num_channel_htlcs(peer->channel) == 0 + && peer->sigs_received == peer->next_index - 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 eltoo_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 eltoo_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 eltoo_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; +} + +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) +{ + u8 *msg; + const u8 *hsmd_msg; + const struct htlc **changed_htlcs; + 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) { + peer->commit_timer = NULL; + return; + } +#endif + + /* 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->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); + /* Mark this as done and try again. */ + peer->commit_timer = NULL; + start_update_timer(peer); + return; + } else { + peer->commit_timer_attempts = 0; + } + + /* 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; + } + + /* 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_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. */ + maybe_send_shutdown(peer); + + peer->commit_timer = NULL; + 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); + + 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_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 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 %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, 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), + 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 */ + 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) { + (*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 update..."); + /* 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.last_committed_state.self_psig, + &peer->channel->eltoo_keyset.last_committed_state.session, + 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); + + 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, + &peer->channel->eltoo_keyset.self_next_nonce); + peer_write(peer->pps, take(msg)); + + 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); +} + +static void start_update_timer(struct eltoo_peer *peer) +{ + /* Already armed? */ + if (peer->commit_timer) + return; + + peer->commit_timer = new_reltimer(&peer->timers, peer, + time_from_msec(peer->commit_msec), + send_update, 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, our_update_psig, next_nonce); +} + +/* 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_UPDATE) { + 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_UPDATE) { + 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 + || htlc->state == RCVD_ADD_ACK + || htlc->state == SENT_REMOVE_REVOCATION /* SENT_REMOVE_ACK */); + + c.id = htlc->id; + c.newstate = htlc->state; + tal_arr_expand(changed, c); + } + } +} + +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, + const struct musig_session *session, + const struct bitcoin_tx *update_tx, + const struct bitcoin_tx *settle_tx) +{ + 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); + + 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++; + + /* 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_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. */ + 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, + our_update_psig, + their_update_psig, + session, + added, + fulfilled, + failed, + changed, + update_tx, + settle_tx); + master_wait_sync_reply(tmpctx, peer, take(msg_for_master), + WIRE_CHANNELD_GOT_UPDATESIG_REPLY); + + /* 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) +{ + struct channel_id channel_id; + struct bitcoin_tx **update_and_settle_txs; + 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? */ + if (!channel_rcvd_update(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); + 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; + } + + if (!fromwire_update_signed(msg, + &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)); + + peer->sigs_received++; + + 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, + 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, + 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, 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)); + + 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, &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), + 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)); + + + + /* Before replying, make sure signature is correct */ + 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)) { + 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 */ + migrate_committed_to_complete(peer); + + /* + * - 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! */ + send_update_sign_ack(peer, + changed_htlcs, + &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, + 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); + +} + +static u8 *got_signed_ack_msg(struct eltoo_peer *peer, + u64 update_num, + const struct htlc **changed_htlcs, + 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); + + for (size_t i = 0; i < tal_count(changed_htlcs); i++) { + struct changed_htlc c; + const struct htlc *htlc = changed_htlcs[i]; + + status_debug("got_signed_ack 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); + } + + msg = towire_channeld_got_ack(peer, update_num, + changed, their_psig, our_psig, session); + + return msg; +} + +static void handle_peer_update_sig_ack(struct eltoo_peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + 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)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad update_signed_ack %s", tal_hex(msg, msg)); + } + + 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", + 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), + 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.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(comb_msg)); + comb_msg = wire_sync_read(tmpctx, HSM_FD); + + if (!fromwire_hsmd_combine_psig_reply(comb_msg, &update_sig)) + 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); + + /* 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)) { + /* 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); + + /* We may now be quiescent on our side. */ + maybe_send_stfu(peer); + + start_update_timer(peer); +} + +static void handle_peer_fulfill_htlc(struct eltoo_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_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 + * 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 eltoo_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_update_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 eltoo_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_update_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 eltoo_peer *peer, const u8 *shutdown) +{ + struct channel_id channel_id; + u8 *scriptpubkey; + + /* 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)) + 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)); + + + /* 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, + &peer->channel->eltoo_keyset.other_next_nonce))); + + 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_update_timer(peer); + } + billboard_update(peer); +} + +static void handle_unexpected_reestablish(struct eltoo_peer *peer, const u8 *msg) +{ + struct channel_id channel_id; + u64 last_update_number; + struct partial_sig their_last_psig; + struct nonce their_next_nonce; + + /* No reestablish tlvs for now */ + if (!fromwire_channel_reestablish_eltoo + (msg, &channel_id, + &last_update_number, + &their_last_psig, + &their_next_nonce) + ) + 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)); +} + +/* 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); + + 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); + } + } + + /* 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); + 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: + /* FIXME How should we handle illegal messages in general? */ + return; + case WIRE_UPDATE_FEE: + /* FIXME How should we handle illegal messages in general? */ + return; + case WIRE_UPDATE_SIGNED: + handle_peer_update_sig(peer, msg); + return; + case WIRE_UPDATE_BLOCKHEIGHT: + /* FIXME How should we handle illegal messages in general? */ + return; + case WIRE_REVOKE_AND_ACK: + /* 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; + 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: + /* + *- if it received `update_noop`: + * - MUST otherwise ignore the message + */ + return; + case WIRE_YIELD: + handle_yield(peer, msg); + 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: + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: + case WIRE_CHANNEL_REESTABLISH: + break; + case WIRE_CHANNEL_REESTABLISH_ELTOO: + 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_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 send_fail_or_fulfill(struct eltoo_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)); + 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; +} + +/* 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 + * 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) */ + + /* 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 { + /* We are not doing optimistic updates */ + status_broken("We're proposing updates out of turn?"); + } + + 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; + 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 */ + 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. + * - 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_regen_nonce(NULL, &peer->channel_id); + wire_sync_write(HSM_FD, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + 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)); + } + + 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, + 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"); + + /* 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)); + + + /* Their psig might be for our complete state + */ + if (!fromwire_channel_reestablish_eltoo(msg, + &channel_id, + &remote_last_update_num, + &remote_update_psig, + &peer->channel->eltoo_keyset.other_next_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) { + + /* 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; + + 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, + &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)) { + peer_failed_warn(peer->pps, &peer->channel_id, + "Bad reestablish psig %s", tal_hex(msg, 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("reestablishment 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 remote claims they didn't get it. + * 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. + * 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 { + /* 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); + } + + /* 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. (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; + 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 eltoo_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_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; + } + + 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 eltoo_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 eltoo_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 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 = eltoo_channel_add_htlc(peer->channel, LOCAL, peer->htlc_id, + amount, cltv_expiry, &payment_hash, + onion_routing_packet, take(blinding), NULL, + 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_update_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++; + peer->can_yield = false; + 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"); + 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_config_channel(struct eltoo_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 eltoo_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_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 + * 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 eltoo_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_update_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 eltoo_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_update_timer(peer); +} + +/* Lightningd tells us when channel_update has changed. */ +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 eltoo_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 eltoo_peer *peer) +{ + peer->dev_disable_commit = tal_free(peer->dev_disable_commit); + 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 eltoo_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))); +} + +/* 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) +{ + 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 eltoo_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: + handle_feerates(peer, msg); + return; + case WIRE_CHANNELD_BLOCKHEIGHT: + 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: + /* 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_RESENDING_UPDATESIG: + case WIRE_CHANNELD_RESENDING_UPDATESIG_REPLY: + case WIRE_CHANNELD_INIT_ELTOO: + break; + } + master_badmsg(-1, msg); +} + +/* We do this synchronously. */ +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]; + struct eltoo_sign complete_state; + struct eltoo_sign committed_state; + struct nonce nonces[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; + u32 minimum_depth; + secp256k1_ecdsa_signature *remote_ann_node_sig; + secp256k1_ecdsa_signature *remote_ann_bitcoin_sig; + bool reestablish_only; + 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 + + assert(!(fcntl(MASTER_FD, F_GETFL) & O_NONBLOCK)); + + msg = wire_sync_read(tmpctx, MASTER_FD); + if (!fromwire_channeld_init_eltoo(peer, msg, + &chainparams, + &peer->our_features, + &peer->channel_id, + &funding, + &funding_sats, + &minimum_depth, + &conf[LOCAL], &conf[REMOTE], + &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], + &complete_update_tx, + &complete_settle_tx, + &committed_update_tx, + &committed_settle_tx, + &funding_pubkey[REMOTE], + &settle_pubkey[REMOTE], + &opener, + &peer->fee_base, + &peer->fee_per_satoshi, + &peer->htlc_minimum_msat, + &peer->htlc_maximum_msat, + &local_msat, + &funding_pubkey[LOCAL], + &settle_pubkey[LOCAL], + &peer->node_ids[LOCAL], + &peer->node_ids[REMOTE], + &peer->commit_msec, + &peer->cltv_delta, + &peer->last_sent_commit, + &peer->next_index, + &peer->sigs_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, + &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, + &reestablish_only, + &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)); + + /* 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); + +#if DEVELOPER + peer->dev_disable_commit = dev_disable_commit; + peer->dev_fast_gossip = dev_fast_gossip; +#endif + + /* stdin == requests, 3 == peer */ + peer->pps = new_per_peer_state(peer); + per_peer_state_set_fd(peer->pps, 3); + + status_debug("init %s: " + " next_idx = %"PRIu64 + " sigs_received = %"PRIu64, + side_to_str(opener), + peer->next_index, + peer->sigs_received); + + 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 > 0); + + peer->channel = new_full_eltoo_channel(peer, &peer->channel_id, + &funding, + minimum_depth, + funding_sats, + local_msat, + &conf[LOCAL], &conf[REMOTE], + &funding_pubkey[LOCAL], + &funding_pubkey[REMOTE], + &settle_pubkey[LOCAL], + &settle_pubkey[REMOTE], + &complete_state, + &committed_state, + take(channel_type), + feature_offered(peer->their_features, + OPT_LARGE_CHANNELS), + opener); + + /* 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))) + 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]); + + /* 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; + + /* 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); + } + + 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)); + + /* 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 eltoo_peer *peer; + + subdaemon_setup(argc, argv); + + status_setup_sync(MASTER_FD); + + 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; + 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; + peer->sent_uncommitted_removals = false; +#if EXPERIMENTAL_FEATURES + 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 + * 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 from master 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; + } + + /* 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); + 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)); + 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? */ + 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..9dd2cdfa9979 --- /dev/null +++ b/channeld/eltoo_channeld.h @@ -0,0 +1,10 @@ +#ifndef LIGHTNING_CHANNELD_ELTOO_CHANNELD_H +#define LIGHTNING_CHANNELD_ELTOO_CHANNELD_H +#include "config.h" +#include +#include +#include + +const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES); + +#endif /* LIGHTNING_CHANNELD_ELTOO_CHANNELD_H */ diff --git a/channeld/eltoo_full_channel.c b/channeld/eltoo_full_channel.c new file mode 100644 index 000000000000..9e969f11addc --- /dev/null +++ b/channeld/eltoo_full_channel.c @@ -0,0 +1,949 @@ +#include "config.h" +#include +#include +#include +#include +#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_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_msat, + 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 eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, + const struct channel_type *type TAKES, + bool option_wumbo, + enum side opener) +{ + struct channel *channel = new_initial_eltoo_channel(ctx, + cid, + funding, + minimum_depth, + funding_sats, + local_msat, + local, remote, + local_funding_pubkey, + remote_funding_pubkey, + local_settle_pubkey, + remote_settle_pubkey, + complete_state, + committed_state, + 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; + enum htlc_state state = htlc->state; + + if (htlc->state <= SENT_REMOVE_ACK) + remote_state = state + 10; + else + remote_state = state - 10; + + status_debug("%s: HTLC %s %"PRIu64" = %s/%s %s", + prefix, + htlc_state_owner(state) == LOCAL ? "LOCAL" : "REMOTE", + htlc->id, + htlc_state_name(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 (eltoo_htlc_has(htlc, committed_flag)) { +#ifdef SUPERVERBOSE + dump_htlc(htlc, "COMMITTED"); +#endif + htlc_arr_append(committed, htlc); + 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 (eltoo_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; +} + +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) /* FIXME remove */ +{ + assert(side == LOCAL); + struct bitcoin_tx **txs; + const struct htlc **committed; + + /* Figure out what @side will already be committed to. */ + /* 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[LOCAL].shared_delay, + &channel->eltoo_keyset, + 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 */ + txs[0] = unbound_update_tx(ctx, + txs[1], + channel->funding_sats, + &channel->eltoo_keyset.inner_pubkey); + + /* 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->eltoo_keyset.self_funding_key); + psbt_input_add_pubkey(txs[0]->psbt, 0, + &channel->eltoo_keyset.other_funding_key); + + tal_free(committed); + return txs; +} + +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, + 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; + size_t htlc_count; + bool ok; + + 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; + } + + /* 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; + } + + /* No fee "fun", just don't make relay dust */ + + 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, + channel->config[LOCAL].max_dust_htlc_exposure_msat)) { + 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 */ + 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 eltoo_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, + bool err_immediate_failures) +{ + /* FIXME figure out HTLC state machine for eltoo */ + 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, err_immediate_failures); +} + +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 channel *channel, + enum side owner, + u64 id, + const struct preimage *preimage, + struct htlc **htlcp) +{ + struct sha256 hash; + struct htlc *htlc; + + htlc = eltoo_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 (!eltoo_htlc_has(htlc, HTLC_FLAG(!htlc_owner(htlc), HTLC_F_COMMITTED))) { + status_unusual("channel_fulfill_htlc: %"PRIu64" in state %s, uncommitted", + 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`. + */ + /* 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 == 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, not irrevocable", + 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 = eltoo_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 (!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)); + 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) + 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, 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, + struct balance owed[NUM_SIDES]) +{ + 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+state_gap)); + + preflags = eltoo_htlc_state_flags(htlc->state); + 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 += state_gap; + + /* 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 flags which were changed. */ +static int change_htlcs(struct channel *channel, + // FIXME not needed? 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[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, 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)); + } + } + } + + for (i = 0; i < NUM_SIDES; 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(LOCAL), + side_to_str(i), + type_to_string(tmpctx, struct amount_msat, + &channel->view[LOCAL].owed[i]), + owed[i].msat); + } + } + + return cflags; +} + +bool channel_sending_update(struct channel *channel, + const struct htlc ***htlcs) +{ + int change; + const enum htlc_state states_to_inc[] = { SENT_ADD_HTLC, + SENT_REMOVE_HTLC }; + status_debug("Trying update"); + + change = change_htlcs(channel, states_to_inc, ARRAY_SIZE(states_to_inc), + htlcs, "sending_update"); + if (!change) + return false; + + 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_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) +{ + int change; + const enum htlc_state states[] = { SENT_ADD_UPDATE, + SENT_REMOVE_UPDATE }; + + status_debug("Received update_sign_ack"); + 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. */ + return (change & HTLC_LOCAL_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 (!eltoo_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 (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 + ? "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; + + /* No blockheight updates for eltoo for now, continue */ + + for (htlc = htlc_map_first(channel->htlcs, &it); + htlc; + htlc = htlc_map_next(channel->htlcs, &it)) { + int flags = eltoo_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 (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))) + 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, 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..efde7169b241 --- /dev/null +++ b/channeld/eltoo_full_channel.h @@ -0,0 +1,220 @@ +/* This is the full channel routines, with HTLC support. */ +#ifndef LIGHTNING_CHANNELD_ELTOO_FULL_CHANNEL_H +#define LIGHTNING_CHANNELD_ELTOO_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. + * @funding_sats: The commitment transaction amount. + * @local_msat: The amount for the local side (remainder goes to remote) + * @local: local channel configuration + * @remote: remote channel configuration + * @local_fundingkey: local funding key + * @remote_fundingkey: remote funding key + * @local_settle_pubkey: local settlement key + * @remote_settle_pubkey: remote settlement key + * @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. + * + * Returns state, or NULL if malformed. + */ +struct channel *new_full_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_msat, + 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 eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, + 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 **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); + +/** + * 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. + * @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 eltoo_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, + bool err_immediate_failures); + +/** + * eltoo_channel_get_htlc: find an HTLC + * @channel: The channel + * @offerer: the side offering the HTLC. + * @id: unique HTLC 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. + * @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); + +/** + * 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_update(struct channel *channel, + const struct htlc ***htlcs); + +/** + * channel_rcvd_update_sign_ack: accept ack on update. + * @channel: the channel + * @htlcs: initially-empty tal_arr() for htlcs which changed state. + * + */ +bool channel_rcvd_update_sign_ack(struct channel *channel, + const struct htlc ***htlcs); + +/** + * channel_rcvd_update: commit all outstanding changes. + * @channel: the channel + * @htlcs: initially-empty tal_arr() for htlcs which changed state. + * + */ +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 + */ +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_ELTOO_FULL_CHANNEL_H */ diff --git a/channeld/settle_tx.c b/channeld/settle_tx.c new file mode 100644 index 000000000000..ff5bf011505c --- /dev/null +++ b/channeld/settle_tx.c @@ -0,0 +1,294 @@ +#include "config.h" +#include +#include +#include +#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 sender_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 *funding_pubkey_ptrs[2]; + struct amount_sat amount; + 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); + sender_pubkey = &(eltoo_keyset->other_settle_key); + } else { + receiver_pubkey = &(eltoo_keyset->other_settle_key); + sender_pubkey = &(eltoo_keyset->self_settle_key); + } + + /* 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)); + + 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])); + 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, 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); + + 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) +{ + 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; + u32 *cltvs; + bool to_local, to_remote; + struct htlc *dummy_to_local = (struct htlc *)0x01, + *dummy_to_remote = (struct htlc *)0x02; + struct pubkey inner_pubkey; + 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, + * 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 */ + 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)); + 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, + funding_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++; + } + + /* 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 + 500000000); + + /* 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, &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) { + 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..3d61549866cf --- /dev/null +++ b/channeld/settle_tx.h @@ -0,0 +1,61 @@ +#ifndef LIGHTNING_CHANNELD_SETTLE_TX_H +#define LIGHTNING_CHANNELD_SETTLE_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); + +/** + * settle_tx: create (unsigned) settlement tx to spend the funding tx output + * @ctx: context to allocate transaction and @htlc_map from. + * @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 for update number + * + * 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_SETTLE_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/channeld/test/Makefile b/channeld/test/Makefile index 77ea655abbf2..81c4750cddeb 100644 --- a/channeld/test/Makefile +++ b/channeld/test/Makefile @@ -17,16 +17,18 @@ 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 \ 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) -$(CHANNELD_TEST_OBJS): $(CHANNELD_HEADERS) $(CHANNELD_SRC) +$(CHANNELD_TEST_OBJS): $(CHANNELD_HEADERS) $(CHANNELD_SRC) $(ELTOO_CHANNELD_SRC) check-units: $(CHANNELD_TEST_PROGRAMS:%=unittest/%) diff --git a/channeld/test/run-settle_tx.c b/channeld/test/run-settle_tx.c new file mode 100644 index 000000000000..0f0d2fe0cee5 --- /dev/null +++ b/channeld/test/run-settle_tx.c @@ -0,0 +1,954 @@ +#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 "../settle_tx.c" +#include +#include +#include +#include +#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 */ + +char regression_tx_hex[] = "02000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000002a00000003000000000000000001511027000000000000225120466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f271ce80000000000002251204f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa02654196b83a7a213da9614e4ea004f03d8130ef9db83ef134725474c265a5d4e041f9f76134aa4133a3910e2fbc8906581f6e1679af46d6e45376aba0886fdf4196a7c1210179be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac41c1442b558d2430be010fc3aa405a78b81d3c254145fc96dc28f9347e4748cc70a4b4d868d7231ff3d15775dbd01acf0051b86eccd1f1139772222152b32986c4df0065cd1d"; + +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) +{ + 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 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) +{ + 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, + &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, + inner_pubkey, + &session[i], + &msg_out, + &sig); + assert(ok); + } + + return sig; +} + +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)); +} + +/* 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; + 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; + assert(other_pay.millisatoshis < 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); + + assert(tx->wtx->locktime == obscured_update_number + 500000000); + + 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 + 500000000); + 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; +} + +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; + 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, *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; + const struct htlc **htlc_map; + + /* Aggregation stuff */ + secp256k1_musig_keyagg_cache keyagg_cache[2]; + struct pubkey inner_pubkey; + const struct pubkey *pubkey_ptrs[2]; + int i; + + /* MuSig signing stuff */ + u8 *annex_0, *annex_1; + struct bip340sig 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; + obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ + + tx = initial_settlement_tx(tmpctx, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + obscured_update_number, + /* 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); + + /* 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(&inner_pubkey, + &keyagg_cache[i], + pubkey_ptrs, + /* n_pubkeys */ 2); + } + + /* Will be bound later */ + update_tx = unbound_update_tx(tmpctx, + tx, + update_output_sats, + &inner_pubkey); + + /* Signing happens next */ + annex_0 = make_eltoo_annex(tmpctx, tx); + 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_tx_to_funding_outpoint(update_tx, + tx, + &update_output, + &eltoo_keyset, + &inner_pubkey, + &sig); + + psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); + printf("Update transaction 0: %s\n", psbt_b64); + + /* Go to second update, Bob gets paid */ + obscured_update_number++; + self_pay.millisatoshis -= 1000; + other_pay.millisatoshis += 1000; + + 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, + /* direct_outputs FIXME Cannot figure out how this is used. */ NULL, + obscured_update_number); + + 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, + update_output_sats, + &inner_pubkey); + + /* Authorize this next state update */ + annex_1 = make_eltoo_annex(tmpctx, settle_tx_1); + 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_tx_to_funding_outpoint(update_tx_1_A, + settle_tx_1, + &update_output, + &eltoo_keyset, + &inner_pubkey, + &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 */ + &inner_pubkey, + &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; + 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, *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 */ + struct pubkey inner_pubkey; + u8 *annex; + struct bip340sig 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; + obscured_update_number = 0; /* non-0 mask not allowed currently, this should always be 0 */ + + tx = initial_settlement_tx(tmpctx, + update_output_sats, + shared_delay, + &eltoo_keyset, + dust_limit, + self_pay, + other_pay, + obscured_update_number, + /* 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); + + /* 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(&inner_pubkey, + &keyagg_cache[i], + pubkey_ptrs, + /* n_pubkeys */ 2); + } + + /* Will be bound later */ + update_tx = unbound_update_tx(tmpctx, + tx, + update_output_sats, + &inner_pubkey); + + 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); + 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 */ + + /* Re-bind, add final script/tapscript info into PSBT */ + bind_tx_to_funding_outpoint(update_tx, + tx, + &update_output, + &eltoo_keyset, + &inner_pubkey, + &sig); + + psbt_b64 = psbt_to_b64(tmpctx, update_tx->psbt); + printf("Initial update psbt with finalized witness for input: %s\n", psbt_b64); + + 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; + 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, tap_merkle_root_annex; + 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]; + int ok; + char *tap_hex; + /* Ground truth generated elsewhere */ + char hex_script[] = "5120d6df6951e80e3ba3f0b3dd900263e31d93cbfdb4c74d302aa6a8957f2784adb9"; + + 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, + &keyagg_cache, + pubkey_ptrs, + /* n_pubkeys */ 1); + + 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); + 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) == 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); + + bipmusig_finalize_keys(&agg_pubkey, &keyagg_cache, pubkey_ptrs, /* n_pubkeys */ 1, + &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); + 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; +} + +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[] = "02e3bd38009866c9da8ec4aa99cc4ea9c6c0dd46df15c61ef0ce1f271291714e57"; + char bob_pubkey_hex[] = "02324266de8403b3ab157a09f1f784d587af61831c998c151bcc21bb74c2b2314b"; + //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; + + common_setup(argv[0]); + + chainparams = chainparams_for_network("bitcoin"); + + err |= test_initial_settlement_tx(); + assert(!err); + + err |= test_htlc_output_creation(); + assert(!err); + + err |= test_settlement_tx(); + assert(!err); + + err |= test_invalid_update_tx(); + assert(!err); + + err |= test_htlc_output(); + assert(!err); + + printf("Tests succeeded!\n"); + + common_shutdown(); + + return err; +} + 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/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/common/Makefile b/common/Makefile index 86f1588b421b..4b8c34c2b7da 100644 --- a/common/Makefile +++ b/common/Makefile @@ -46,6 +46,8 @@ 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 \ common/json_helpers.c \ @@ -84,6 +86,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/channel_config.c b/common/channel_config.c index 55e32ae6dc66..9a7cd56a4dfa 100644 --- a/common/channel_config.c +++ b/common/channel_config.c @@ -4,23 +4,43 @@ 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); + } 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); + 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 fb74a4998c01..2636cd5f7f13 100644 --- a/common/channel_config.h +++ b/common/channel_config.h @@ -77,9 +77,27 @@ struct channel_config { * maximum dust exposure allowed for this channel */ struct amount_msat max_dust_htlc_exposure_msat; + + /* Eltoo fields start here + * + * We do not use: to_self_delay, channel_reserve + */ + + bool is_eltoo; + + /* 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; + + /* Eltoo fields end here */ + }; 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/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/derive_basepoints.h b/common/derive_basepoints.h index efe1adb42af6..fb5294d7afad 100644 --- a/common/derive_basepoints.h +++ b/common/derive_basepoints.h @@ -10,7 +10,7 @@ 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; }; 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/common/htlc.h b/common/htlc.h index c300f0ffe5d9..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) { diff --git a/common/htlc_state.c b/common/htlc_state.c index 75b841d3837e..9dd4d8c93e67 100644 --- a/common/htlc_state.c +++ b/common/htlc_state.c @@ -139,3 +139,77 @@ int htlc_state_flags(enum htlc_state state) return per_state_bits[state]; } +/* 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 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..5f08228093c3 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,26 @@ enum htlc_state { HTLC_STATE_INVALID }; + +/* 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 (SENT_ADD_ACK_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 (RCVD_ADD_ACK_REVOCATION) + +/* SENT_REMOVE_HTLC is same */ +#define SENT_REMOVE_UPDATE (SENT_REMOVE_COMMIT) +#define RCVD_REMOVE_ACK (SENT_REMOVE_ACK_REVOCATION) + + +/* HTLC_STATE_INVALID is same */ + #endif /* LIGHTNING_COMMON_HTLC_STATE_H */ 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_channel.h b/common/initial_channel.h index 713d55f5fc76..440abb54c9c2 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -8,6 +8,7 @@ #include #include #include +#include struct signature; struct added_htlc; @@ -60,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. */ @@ -70,6 +72,17 @@ struct channel { /* When the lease expires for the funds in this channel */ u32 lease_expiry; + + /* Eltoo fields below */ + + /* 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; + + /* End Eltoo fields*/ + }; /** 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_eltoo_channel.c b/common/initial_eltoo_channel.c new file mode 100644 index 000000000000..7e3fab70a748 --- /dev/null +++ b/common/initial_eltoo_channel.c @@ -0,0 +1,138 @@ +#include "config.h" +#include +#include +#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, + 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 eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, + const struct channel_type *type TAKES, + bool option_wumbo, + enum side opener) +{ + struct channel *channel = tal(ctx, struct channel); + struct amount_msat remote_msatoshi; + const struct pubkey *pubkey_ptrs[2]; + secp256k1_musig_keyagg_cache keyagg_cache; + + 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->eltoo_keyset.last_complete_state = *complete_state; + channel->eltoo_keyset.last_committed_state = *committed_state; + 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; + 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 channel *channel, + struct wally_tx_output *direct_outputs[NUM_SIDES]) +{ + struct bitcoin_tx *init_settle_tx; + + /* 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_sats, + channel->config->shared_delay, + &channel->eltoo_keyset, + channel->config->dust_limit, + channel->view->owed[LOCAL], + channel->view->owed[REMOTE], + 0 ^ channel->update_number_obscurer, + direct_outputs); + + 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 channel *channel) +{ + 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. + */ + 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); + + init_update_tx = unbound_update_tx(ctx, + settle_tx, + channel->funding_sats, + &dummy_inner_pubkey); + + 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; +} diff --git a/common/initial_eltoo_channel.h b/common/initial_eltoo_channel.h new file mode 100644 index 000000000000..1d7f07eeeb12 --- /dev/null +++ b/common/initial_eltoo_channel.h @@ -0,0 +1,84 @@ +/* This represents a channel with no HTLCs: all that's required for openingd. */ +#ifndef LIGHTNING_COMMON_INITIAL_ELTOO_CHANNEL_H +#define LIGHTNING_COMMON_INITIAL_ELTOO_CHANNEL_H +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +struct signature; +struct added_htlc; +struct failed_htlc; +struct fulfilled_htlc; + +/** + * 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 + * @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. + * + * 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 eltoo_sign *complete_state, + const struct eltoo_sign *committed_state, + 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). + * + * 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 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 + * *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 + * + */ +struct bitcoin_tx *initial_update_channel_tx(const tal_t *ctx, + const struct bitcoin_tx *settle_tx, + const struct channel *channel); + +#endif /* LIGHTNING_COMMON_INITIAL_ELTOO_CHANNEL_H */ diff --git a/common/initial_settlement_tx.c b/common/initial_settlement_tx.c new file mode 100644 index 000000000000..130453374ae7 --- /dev/null +++ b/common/initial_settlement_tx.c @@ -0,0 +1,254 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#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) +{ + return bitcoin_tx_add_output( + 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) +{ + u8 *spk = bitcoin_spk_ephemeral_anchor(tmpctx); + 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, const struct pubkey *inner_pubkey, u32 obscured_update_number, const struct pubkey *funding_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]; + int parity_bit; + u8 *control_block; + u8 *script_pubkey; + u8 **witness; /* settle_and_update_tapscripts[0] script and control_block */ + + /* + * We do not know what scriptPubKey, tap_tree look like yet because we're computing + * a sighash to then put into the input script. 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); + + /* 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); + + 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, + funding_pubkey_ptrs, + /* n_pubkeys */ 2, + &update_merkle_root, + 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); + 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_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, + struct amount_sat update_outpoint_sats, + u32 shared_delay, + const 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]) +{ + struct bitcoin_tx *tx; + size_t output_index, num_untrimmed; + bool to_local, to_remote; + struct amount_msat total_pay; + 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 *funding_pubkey_ptrs[2]; + 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 */ + 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, + funding_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 committed HTLCs need to be trimmed (see + * [Trimmed Outputs](#trimmed-outputs)). + */ + num_untrimmed = 0; + + /* Worst-case sizing: both to-local and to-remote outputs + single anchor. */ + 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. */ + + output_index = 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_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)) { + 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++; + 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 == output_index); + output_order[output_index] = dummy_remote; + output_index++; + to_remote = true; + } else + to_remote = false; + + /* BOLT #???: + */ + if (to_local || to_remote || num_untrimmed != 0) { + tx_add_ephemeral_anchor_output(tx); + output_order[output_index] = NULL; + output_index++; + } + + assert(output_index <= tx->wtx->num_outputs); + assert(output_index <= ARRAY_SIZE(output_order)); + + /* BOLT #???: + * + * 9. Sort the outputs into [BIP 69+CLTV + * order](#transaction-input-and-output-ordering) + */ + /* FIXME? */ + permute_outputs(tx, NULL, output_order); + + /* BOLT #???: + * + * ## Commitment Transaction + * + * * version: 2 + */ + assert(tx->wtx->version == 2); + + /* 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, + obscured_update_number + 500000000); + + /* BOLT #???: + * + * * 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 + */ + + 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! */ + + 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); + + return tx; +} diff --git a/common/initial_settlement_tx.h b/common/initial_settlement_tx.h new file mode 100644 index 000000000000..7b77712c1df5 --- /dev/null +++ b/common/initial_settlement_tx.h @@ -0,0 +1,49 @@ +/* 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 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. + * @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. + * @self_pay: amount to pay directly to self + * @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). + * + */ +struct bitcoin_tx *initial_settlement_tx(const tal_t *ctx, + struct amount_sat update_outpoint_sats, + u32 shared_delay, + const 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]); + + +/* 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); + +/* 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/common/keyset.h b/common/keyset.h index ba74ceeb024f..7ac2b209c69a 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; @@ -13,6 +14,39 @@ struct keyset { struct pubkey self_payment_key, other_payment_key; }; +/* Holds all information for a particular state being signed */ +struct eltoo_sign { + 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; + struct pubkey self_funding_key, other_funding_key; + /* 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; + /* 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. 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; + struct bitcoin_tx *committed_settle_tx; +}; + /* Self == owner of commitment tx, other == non-owner. */ bool derive_keyset(const struct pubkey *per_commitment_point, const struct basepoints *self, diff --git a/common/type_to_string.h b/common/type_to_string.h index 171ac476a843..c6bd1c9d5510 100644 --- a/common/type_to_string.h +++ b/common/type_to_string.h @@ -30,6 +30,9 @@ 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 musig_session *musig_session; const struct channel *channel; const struct amount_msat *amount_msat; const struct amount_sat *amount_sat; diff --git a/common/update_tx.c b/common/update_tx.c new file mode 100644 index 000000000000..549d9a39e1d7 --- /dev/null +++ b/common/update_tx.c @@ -0,0 +1,415 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + +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; + 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_annex_from_script(const tal_t *ctx, const u8 *script) +{ + int ok; + struct sha256 result; + 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 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; + preimage_cursor++; + preimage_cursor += varint_put(preimage_cursor, tapscript_len); + memcpy(preimage_cursor, script, tapscript_len); + preimage_cursor += tapscript_len; + + assert(tal_count(tapleaf_preimage) == preimage_cursor - tapleaf_preimage); + ok = wally_tagged_hash(tapleaf_preimage, tal_count(tapleaf_preimage), "TapLeaf", result.u.u8); + assert(ok == WALLY_OK); + + annex[0] = 0x50; /* annex flag */ + annex[1] = 32; /* payload length */ + memcpy(annex + 2, result.u.u8, sizeof(result)); + 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; + + /* 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_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, + const struct bip340sig *sig) +{ + const struct pubkey *pubkey_ptrs[2]; + u8 *update_tapscript[1]; + int input_num; + u8 *script_pubkey; + struct pubkey taproot_pk; + 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); + + /* FIXME embed this in PSBT as well... */ + update_tapscript[0] = make_eltoo_funding_update_script(tmpctx); + + 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, + &psbt_tap_merkle_root, + psbt_tap_tweak, + NULL); + + 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_sats, script_pubkey, /* input_wscript */ NULL, /* inner_pubkey */ NULL, /* tap_tree */ NULL); + assert(input_num == 0); + + /* 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, /* 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_settle_tx(const struct bitcoin_txid update_txid, + int output_index, + struct bitcoin_tx *settle_tx) +{ + 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, + 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, + struct pubkey *psbt_inner_pubkey, + const struct bip340sig *sig) +{ + const struct pubkey *pubkey_ptrs[2]; + u8 *update_tapscript; + int input_num; + u8 *script_pubkey; + struct pubkey taproot_pk; + 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); + + /* FIXME embed this in PSBT as well... */ + /* 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); + + bipmusig_finalize_keys(&taproot_pk, + &unused_coop_cache, + pubkey_ptrs, + /* n_pubkeys */ 2, + &psbt_tap_merkle_root, + psbt_tap_tweak, + NULL); + + 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 **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, + 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_tx_to_funding_outpoint(bound_update_tx, + bound_settle_tx, + funding, + &keyset_copy, + &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 *unbound_update_tx(const tal_t *ctx, + const struct bitcoin_tx *settle_tx, + struct amount_sat funding_sats, + const struct pubkey *inner_pubkey) +{ + struct bitcoin_tx *update_tx; + int pos; + + /* 1 input 1 output tx */ + 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); + + /* 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/update_tx.h b/common/update_tx.h new file mode 100644 index 000000000000..250ea2c4c54e --- /dev/null +++ b/common/update_tx.h @@ -0,0 +1,124 @@ +#ifndef LIGHTNING_COMMON_UPDATE_TX_H +#define LIGHTNING_COMMON_UPDATE_TX_H +#include "config.h" +#include +#include +#include +#include +#include +#include + +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); + +/* 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 + * binding it to a particular outpoint or script */ +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_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_txid update_txid, + int output_index, + struct bitcoin_tx *settle_tx); + +/* Used to bind the update transaction to the funding outpoint + * 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 + * @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 + * @sig: bip340 signature to be put into witness + */ +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, + 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); + +/* 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 + * 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 + * @sig: bip340 signature to put into witness + */ +void bind_update_tx_to_update_outpoint(struct bitcoin_tx *update_tx, + 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, + struct pubkey *psbt_inner_pubkey, + const struct bip340sig *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 + * @inner_pubkey: inner public key for the eltoo channel + * + */ +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); + + +#endif /* LIGHTNING_COMMON_UPDATE_TX_H */ diff --git a/connectd/multiplex.c b/connectd/multiplex.c index 54740a7b3c4f..44548ce30156 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 @@ -291,6 +302,10 @@ 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: + case WIRE_UPDATE_SIGNED: + case WIRE_UPDATE_SIGNED_ACK: return true; }; @@ -481,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; } @@ -774,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: @@ -829,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: @@ -839,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; } @@ -1027,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(tmpctx, struct channel_id, &channel_id)); subd = activate_subd(peer, &t, &channel_id); if (!subd) return io_close(peer_conn); diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index 90ec96a10ed2..66161764ca81 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: @@ -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', @@ -386,8 +386,10 @@ def __init__(self, bitcoin_dir="/tmp/bitcoind-test", rpcport=None): '-nolisten', '-txindex', '-nowallet', - '-addresstype=bech32' + '-addresstype=bech32', + '-debug=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 @@ -1104,7 +1106,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/contrib/startup_regtest.sh b/contrib/startup_regtest.sh index 280ef85f95ad..6e98f5978d19 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=5 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" & + "$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 @@ -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 + $(pwd)/../bitcoin/src/bitcoind -regtest -txindex -fallbackfee=0.00000253 -daemon -daemonwait -trueoutputs=1 -annexcarrier=1 - # 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 @@ -148,6 +148,114 @@ 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) + 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 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 + + # 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 + sleep 1 + # settle tx should be pushed after next block + bt-cli generatetoaddress 1 $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 + 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 ) + txid=$(bt-cli decoderawtransaction $UPDATE_HEX | jq -r .txid) + bt-cli prioritisetransaction $txid 0 100000000 + 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 +} + +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 + l1-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 + + sleep 2 + 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 +} + stop_nodes() { if [ -z "$2" ]; then network=regtest 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/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..205cf8710ed6 --- /dev/null +++ b/devtools/eltoo_mkfunding.c @@ -0,0 +1,191 @@ +/* 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, NULL, 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, + NULL); + + tx = tx_spending_utxo(ctx, utxo, + 1, 0, BITCOIN_TX_DEFAULT_SEQUENCE); + + /* Generate P2TR scriptpubkey */ + /* 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)); + 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; +} 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/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/doc/HACKING.md b/doc/HACKING.md index 82f6813377ac..8313ecd51790 100644 --- a/doc/HACKING.md +++ b/doc/HACKING.md @@ -218,7 +218,11 @@ 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=` * **pylightning tests** - will check contrib pylightning for codestyle and run the tests in `contrib/pylightning/tests` afterwards: 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. 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/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": {}, 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=/ \ diff --git a/external/libwally-core b/external/libwally-core index f7c0824e56a0..339dbc6ec12b 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit f7c0824e56a068c4d9c27cb2e8b26e2a9b8ea3b3 +Subproject commit 339dbc6ec12b7e5509197ee4f85020a4787b35db diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index a776d294f457..3d9800c79611 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -555,6 +555,20 @@ 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: + /* 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/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 4ea0805c84aa..aa979f67757f 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 */ + 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: + 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, take(hsmd_handle_client_message( @@ -694,6 +705,14 @@ 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_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, "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 a62edce8c520..58f73f1322bb 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -281,3 +281,108 @@ 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,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, +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, +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,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, + +msgtype,hsmd_combine_psig_reply,192 +msgdata,hsmd_combine_psig_reply,sig,bip340sig, + +# 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 + + +# 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 + +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, + +# 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 84f78de344d7..50ccd368b03d 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1,20 +1,28 @@ #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 + #if DEVELOPER /* If they specify --dev-force-privkey it ends up in here. */ struct privkey *dev_force_privkey; @@ -22,12 +30,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; + struct musig_state_map musig_map; } secretstuff; /* Have we initialized the secretstuff? */ @@ -87,6 +124,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: @@ -98,6 +137,13 @@ 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_REGEN_NONCE: + case WIRE_HSMD_MIGRATE_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: @@ -145,6 +191,14 @@ 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_GEN_NONCE_REPLY: + case WIRE_HSMD_REGEN_NONCE_REPLY: + case WIRE_HSMD_MIGRATE_NONCE_REPLY: + case WIRE_HSMD_SIGN_ELTOO_TX_REPLY: break; } return false; @@ -353,6 +407,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 @@ -733,6 +827,66 @@ 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 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); + /* 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 */ + get_channel_seed(&c->id, c->dbid, &channel_seed); + derive_basepoints(&channel_seed, + NULL, NULL, &secrets, NULL); + + /* 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 @@ -1285,6 +1439,188 @@ 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]; + struct musig_session session; + + int i; + if (!fromwire_hsmd_combine_psig(tmpctx, msg_in, + &channel_id, + &p_sig_1, + &p_sig_2, + &session, + &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); + 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, + &inner_pubkey, + &session.session, + &hash_out, + &sig)) { + return hsmd_status_bad_request(c, msg_in, + "Failed to verify combined psigs"); + } + 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. + */ +static u8 *handle_psign_update_tx(struct hsmd_client *c, const u8 *msg_in) +{ + struct pubkey remote_funding_pubkey, local_funding_pubkey; + struct secret channel_seed; + struct bitcoin_tx *update_tx, *settle_tx; + struct partial_sig p_sig; + struct secrets secrets; + struct nonce remote_nonce, local_nonce; + struct channel_id channel_id; + struct musig_session session; + + /* MuSig stuff */ + struct pubkey inner_pubkey; + struct musig_keyagg_cache cache; + const struct pubkey *pubkey_ptrs[2]; + const secp256k1_musig_pubnonce *pubnonce_ptrs[2]; + u8 *annex; + struct sha256_double hash_out; + struct musig_state *musig_state_lookup; + + int i; + + if (!fromwire_hsmd_psign_update_tx(tmpctx, msg_in, + &channel_id, + &update_tx, + &settle_tx, + &remote_funding_pubkey, + &remote_nonce, + &local_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 != 2) + return hsmd_status_bad_request_fmt(c, msg_in, + "update tx must have 2 outputs"); + + get_channel_seed(&c->id, c->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(&inner_pubkey, + &cache.cache, + pubkey_ptrs, + /* n_pubkeys */ 2); + + /* 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++) + { + printf("%02X", hash_out.sha.u.u8[i]); + } + printf("\n"); + + pubnonce_ptrs[0] = &remote_nonce.nonce; + pubnonce_ptrs[1] = &local_nonce.nonce; + + /* 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, + &musig_state_lookup->sec_nonce, + pubnonce_ptrs, + /* num_signers */ 2, + &hash_out, + &cache.cache, + &session.session, + &p_sig.p_sig); + + /* Refill and return own next_nonce, using RNG+extra stuff for more security */ + bipmusig_gen_nonce(&musig_state_lookup->sec_nonce, + &local_nonce.nonce, + &secrets.funding_privkey, + &cache.cache, + hash_out.sha.u.u8); + + 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 + * 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_regen_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 * funds, thus it's only available to lightningd. @@ -1408,6 +1744,50 @@ static u8 *handle_validate_revocation(struct hsmd_client *c, const u8 *msg_in) return towire_hsmd_validate_revocation_reply(NULL); } +/* FIXME: do more introspection. split functionality */ +static u8 *handle_sign_eltoo_htlc_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) && + !fromwire_hsmd_sign_eltoo_htlc_success_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 != 1) { + return hsmd_status_bad_request(c, msg_in, + "Failed to generate htlc pubkey pair"); + } + + sign_tx_taproot_input(htlc_tx, + 0 /* input_index */, + SIGHASH_DEFAULT, + 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. */ @@ -1593,7 +1973,27 @@ 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 */ + 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: + return handle_combine_psig(client, msg); + case WIRE_HSMD_VALIDATE_UPDATE_TX_PSIG: + /* We immediately sign ourselves and check via handle_combine_psig... + Unneeded? */ + break; + case WIRE_HSMD_GEN_NONCE: + 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: + 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: case WIRE_HSMD_CANNOUNCEMENT_SIG_REPLY: @@ -1618,6 +2018,14 @@ 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_GEN_NONCE_REPLY: + case WIRE_HSMD_REGEN_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"); @@ -1738,6 +2146,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/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/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/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.c b/lightningd/channel.c index 789d75554161..0071cf71ae18 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 */ @@ -393,7 +393,16 @@ 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, + /* 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) { struct channel *channel = tal(peer->ld, struct channel); struct amount_msat htlc_min, htlc_max; @@ -441,10 +450,42 @@ 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; - channel->last_sig = *last_sig; + 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... */ + 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; + } + 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); @@ -672,6 +713,41 @@ 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) +{ + /* Since we have the complete set, it's complete, not "committed" */ + assert(update_tx->chainparams); + assert(settle_tx->chainparams); + 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->eltoo_keyset.complete_settle_tx); + channel->eltoo_keyset.complete_settle_tx = tal_steal(channel, settle_tx); + + /* 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; +} + 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 db81ce8c484c..e4489b21d17c 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -3,6 +3,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -149,6 +150,17 @@ struct channel { struct bitcoin_signature last_sig; const struct bitcoin_signature *last_htlc_sigs; + /* Eltoo-only fields */ + /* Stores "last" psigs, session */ + struct eltoo_keyset eltoo_keyset; + + /* 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; @@ -319,7 +331,15 @@ 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 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); /* new_inflight - Create a new channel_inflight for a channel */ struct channel_inflight * @@ -409,6 +429,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 9c73949decb1..f047e663907e 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, @@ -206,6 +209,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 +239,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 +560,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,6 +594,24 @@ 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_UPDATESIG: + peer_got_updatesig(sd->channel, msg); + break; + 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; + case WIRE_CHANNELD_INIT_ELTOO: + case WIRE_CHANNELD_GOT_UPDATESIG_REPLY: + 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); @@ -584,6 +648,169 @@ 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->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->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, + channel->feerate_base, + channel->feerate_ppm, + channel->htlc_minimum_msat, + channel->htlc_maximum_msat, + channel->our_msat, + &channel->local_funding_pubkey, + &channel->local_basepoints.payment /* our_settle_pubkey */, + &ld->id, + &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, + 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..c9f6f19bb43d 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, @@ -30,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); 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/lightningd.c b/lightningd/lightningd.c index b8e60b3fff65..0d2de4329b68 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -309,7 +309,11 @@ static const char *subdaemons[] = { "lightning_gossipd", "lightning_hsmd", "lightning_onchaind", - "lightning_openingd" + "lightning_openingd", + // FIXME "lightning_eltoo_closingd", + "lightning_eltoo_channeld", + "lightning_eltoo_openingd", + "lightning_eltoo_onchaind" }; /* Return true if called with a recognized subdaemon e.g. "hsmd" */ @@ -828,6 +832,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/onchain_control.c b/lightningd/onchain_control.c index 1c22cc1b9627..d17f7452b639 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -135,6 +135,46 @@ 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; + bool *tell, *tell_immediate; + + /* 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)); + return; + } + + /* FIXME: We may already be ONCHAIN state when we implement restart! */ + channel_set_state(channel, + FUNDING_SPEND_SEEN /* old_state */, + ONCHAIN /* state */, + REASON_UNKNOWN, + "Onchain init reply"); + + /* 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)); + + 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); + + log_info(channel->log, "Telling eltoo_onchaind about %lu HTLCs", tal_count(stubs)); + subd_send_msg(channel->owner, take(msg)); + + /* Finally, tell it about any preimages we know. */ + onchaind_tell_fulfill(channel); +} + /** * Notify onchaind about the depth change of the watched tx. */ @@ -206,7 +246,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, tx->wtx->locktime, input_num, blockheight); subd_send_msg(channel->owner, take(msg)); } @@ -274,6 +314,28 @@ 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 */ + 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 * * @brief suppresses the rebroadcast of a @@ -577,11 +639,78 @@ 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: + case WIRE_ELTOO_ONCHAIND_NEW_STATE_OUTPUT: + abort(); } 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: + 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_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); + break; + case WIRE_ONCHAIND_EXTRACTED_PREIMAGE: + handle_extracted_preimage(sd->channel, msg); + break; + case WIRE_ONCHAIND_MISSING_HTLC_OUTPUT: + case WIRE_ONCHAIND_ADD_UTXO: + /* 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 +736,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 +895,98 @@ 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; + u32 htlc_feerate; + + /* 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; + } + + 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, + &channel->funding, + channel->funding_sats, + tx_parts_from_wally_tx(tmpctx, tx->wtx, -1, -1), + tx->wtx->locktime, + 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, + htlc_feerate, + channel->our_config.dust_limit, + channel->shutdown_scriptpubkey[LOCAL], + channel->shutdown_scriptpubkey[REMOTE], + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, + &channel->local_basepoints.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)); + + 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; @@ -786,7 +1011,7 @@ void onchaind_replay_channels(struct lightningd *ld) } 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 c0fe3d3b09dd..a0cc333457c5 100644 --- a/lightningd/onchain_control.h +++ b/lightningd/onchain_control.h @@ -11,6 +11,11 @@ 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/opening_common.c b/lightningd/opening_common.c index f866a91f5be0..9d11d676b1fe 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -162,4 +162,47 @@ 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; +} + +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 = ld->config.locktime_max; + + /* 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; + + /* FIXME better voodoo based on TODO BOLT description */ + ours->shared_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..3f30dbb7b927 100644 --- a/lightningd/opening_common.h +++ b/lightningd/opening_common.h @@ -58,6 +58,8 @@ struct uncommitted_channel { /* Our channel config. */ struct channel_config our_config; + + bool is_eltoo; }; struct funding_channel { @@ -123,4 +125,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..199ace012ab9 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1,3 +1,4 @@ +#include #include "config.h" #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include void json_add_uncommitted_channel(struct json_stream *response, @@ -90,7 +92,15 @@ 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 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) { struct channel *channel; struct amount_msat our_msat; @@ -212,7 +222,15 @@ 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, + complete_state, + complete_update_tx, + complete_settle_tx, + committed_state, + committed_update_tx, + committed_settle_tx, + their_next_nonce, + our_next_nonce); /* Now we finally put it in the database. */ wallet_channel_insert(ld->wallet, channel); @@ -295,22 +313,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) @@ -328,6 +358,105 @@ static void opening_funder_start_replied(struct subd *openingd, const u8 *resp, tal_free(fc->uc); } +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 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, 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 */ + channel_info.their_config.id = 0; + + if (!fromwire_openingd_eltoo_funder_reply(resp, resp, + &channel_info.their_config, + &complete_update_tx, + &complete_settle_tx, + &fc->uc->minimum_depth, + &channel_info.remote_fundingkey, + &channel_info.theirbase.payment /* settlement key */, + &complete_state.other_psig, + &complete_state.self_psig, + &complete_state.session, + &their_next_nonce, + &our_next_nonce, + &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; + } + complete_update_tx->chainparams = chainparams; + complete_settle_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 */ + derive_channel_id(&cid, &funding); + + /* Steals fields from uc */ + channel = wallet_commit_channel(ld, fc->uc, + &cid, + NULL /* last_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, + &complete_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) { + was_pending(command_fail(fc->cmd, LIGHTNINGD, + "Key generation failure")); + goto cleanup; + } + + /* Watch for funding confirms */ + channel_watch_funding(ld, channel); + + funding_success(channel); + peer_start_eltoo_channeld(channel, peer_fd, NULL, false /* reconnected */, false /* reestablish_only */); + +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) @@ -400,7 +529,15 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, feerate, fc->our_upfront_shutdown_script, remote_upfront_shutdown_script, - type); + type, + 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) { was_pending(command_fail(fc->cmd, LIGHTNINGD, "Key generation failure")); @@ -421,6 +558,126 @@ 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 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; + + 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"); + + /* 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); + + if (!fromwire_openingd_eltoo_fundee(tmpctx, reply, + &channel_info.their_config, + &complete_update_tx, + &complete_settle_tx, + &channel_info.remote_fundingkey, + &channel_info.theirbase.payment, + &complete_state.other_psig, + &complete_state.self_psig, + &complete_state.session, + &their_next_nonce, + &our_next_nonce, + &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; + } + + + /* 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)); + + complete_update_tx->chainparams = chainparams; + complete_settle_tx->chainparams = chainparams; + + derive_channel_id(&cid, &funding); + + /* Consumes uc */ + channel = wallet_commit_channel(ld, uc, + &cid, + NULL /* remote_commit */, + NULL /* remote_commit_sig */, + &funding, + funding_sats, + push, + channel_flags, + &channel_info, + 0 /* feerate */, + local_upfront_shutdown_script, + remote_upfront_shutdown_script, + type, + &complete_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) { + 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_eltoo_channeld(channel, peer_fd, fwd_msg, false /* reconnected */, false /* reestablish_only */); + + tal_free(uc); + return; + +failed: + tal_free(uc); +} + static void opening_fundee_finished(struct subd *openingd, const u8 *reply, const int *fds, @@ -449,7 +706,8 @@ static void opening_fundee_finished(struct subd *openingd, channel_info.their_config.id = 0; peer_fd = new_peer_fd_arr(tmpctx, fds); - if (!fromwire_openingd_fundee(tmpctx, reply, + + if (!fromwire_openingd_fundee(tmpctx, reply, &channel_info.their_config, &remote_commit, &pbase, @@ -497,7 +755,15 @@ static void opening_fundee_finished(struct subd *openingd, feerate, local_upfront_shutdown_script, remote_upfront_shutdown_script, - type); + type, + 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) { uncommitted_channel_disconnect(uc, LOG_BROKEN, "Commit channel failed"); @@ -792,6 +1058,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_eltoo_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, true /* eltoo */); + 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_eltoo_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) { @@ -817,7 +1143,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); @@ -851,10 +1177,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 +1189,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 +1213,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 +1231,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_basepoints.payment, + 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; } @@ -926,6 +1276,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), @@ -994,10 +1345,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); } @@ -1056,6 +1419,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; @@ -1114,10 +1478,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 = !eltoo && feature_negotiated(cmd->ld->our_features, peer->their_features, - OPT_DUAL_FUND)) + OPT_DUAL_FUND); + + if (!peer->uncommitted_channel) { + if (dual) return command_fail(cmd, FUNDING_STATE_INVALID, "Peer negotiated" " `option_dual_fund`," @@ -1185,20 +1554,32 @@ 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, take(towire_connectd_peer_make_active(NULL, &peer->id, &tmp_channel_id))); + return command_still_pending(cmd); } 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..dc23d51b116f 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -231,6 +232,40 @@ static bool invalid_last_tx(const struct bitcoin_tx *tx) #endif } +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->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); + + /* 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); +} + static void sign_and_send_last(struct lightningd *ld, struct channel *channel, struct bitcoin_tx *last_tx, @@ -252,9 +287,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, channel); + + 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: * @@ -634,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); @@ -718,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); @@ -939,7 +999,53 @@ static void json_add_channel(struct lightningd *ld, "out_msatoshi_fulfilled", "out_fulfilled_msat"); + json_add_htlcs(ld, response, channel); + + if (channel->our_config.is_eltoo) { + struct bitcoin_tx **bound_update_and_settle_txs; + /* Eltoo keyset should probably have all pubkeys... */ + 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); + + /* 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); } @@ -1216,6 +1322,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); @@ -1274,16 +1381,28 @@ 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(); } - dual_fund = feature_negotiated(ld->our_features, + 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); @@ -1301,7 +1420,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); } @@ -1317,6 +1436,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"); @@ -1328,7 +1448,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) { @@ -1537,7 +1657,8 @@ static enum watch_result funding_depth_cb(struct lightningd *ld, struct short_channel_id scid; /* Sanity check */ - if (!check_funding_tx(tx, channel)) { + /* FIXME this doesn't work for eltoo. */ + if (false && !check_funding_tx(tx, channel)) { channel_internal_error(channel, "Bad tx %s: %s", type_to_string(tmpctx, struct bitcoin_txid, txid), @@ -1628,7 +1749,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 UNUSED, const struct block *block) { struct bitcoin_txid txid; @@ -1636,7 +1757,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) @@ -2643,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/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/peer_htlcs.c b/lightningd/peer_htlcs.c index 763ce23a4fb1..e61e5188b025 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -34,12 +34,23 @@ static bool state_update_ok(struct channel *channel, u64 htlc_id, const char *dir) { enum htlc_state expected = oldstate + 1; + 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 * work). */ - if (expected == RCVD_REMOVE_HTLC) - expected = RCVD_REMOVE_COMMIT; + 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 */ + else if (is_eltoo && (expected % 5 == 2)) { + expected += 2; + } if (newstate != expected) { channel_internal_error(channel, @@ -321,8 +332,9 @@ 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; + enum htlc_state final_state = channel->our_config.is_eltoo ? 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)); @@ -1097,20 +1109,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); } @@ -1174,6 +1190,9 @@ 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... */ + /* 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; @@ -1186,14 +1205,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; } @@ -1332,6 +1351,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) { @@ -1826,6 +1867,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) @@ -1869,6 +1935,58 @@ 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 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; + + if (update_num != channel->next_index[LOCAL]) { + channel_internal_error(channel, + "channel_sent_updatesig: expected update_num %"PRIu64 + " got %"PRIu64, + channel->next_index[LOCAL], update_num); + return false; + } + + channel->next_index[LOCAL]++; + + 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; +} + +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) @@ -1877,6 +1995,149 @@ static void adjust_channel_feerate_bounds(struct channel *channel, u32 feerate) channel->min_possible_feerate = feerate; } +void peer_got_ack(struct channel *channel, const u8 *msg) +{ + u64 update_num; + 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)); + return; + } + + log_debug(channel->log, + "got ack %"PRIu64": %zu changed", + update_num, tal_count(changed)); + + /* 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; + } + } + + /* 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); + + /* Tell it we've got it, and to go ahead. */ + subd_send_msg(channel->owner, + take(towire_channeld_got_ack_reply(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; + struct changed_htlc *changed_htlcs; + size_t i, maxid = 0, num_local_added = 0; + struct lightningd *ld = channel->peer->ld; + + 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, + &committed_update_tx, + &committed_settle_tx)) { + 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_updatesig: 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; + } + + /* 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? */ + 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; @@ -2024,6 +2285,42 @@ 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; + } + /* 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; + } + 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, @@ -2068,6 +2365,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) { @@ -2075,6 +2379,153 @@ 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; /* 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, + &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 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)) + return; + + /* 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. */ + subd_send_msg(channel->owner, take(towire_channeld_got_updatesig_reply(msg))); +} + + /* This also implies we're sending revocation */ void peer_got_commitsig(struct channel *channel, const u8 *msg) { diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 1bcef7bb3502..12921a933d1b 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -36,6 +36,11 @@ 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_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); + void update_per_commit_point(struct channel *channel, const struct pubkey *per_commitment_point); 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); } diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 976af4bb8f54..678b6d96922f 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -14,6 +14,33 @@ 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, + 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 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, @@ -88,9 +115,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(); } @@ -608,9 +632,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) + 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/onchaind/Makefile b/onchaind/Makefile index 28c8b6a32f10..71549b02f117 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 += \ @@ -63,11 +70,13 @@ 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 \ 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/eltoo_onchaind.c b/onchaind/eltoo_onchaind.c new file mode 100644 index 000000000000..05616c065754 --- /dev/null +++ b/onchaind/eltoo_onchaind.c @@ -0,0 +1,1738 @@ +#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 "onchain_types_names_gen.h" + +/* stdin == requests */ +#define REQ_FD STDIN_FILENO +#define HSM_FD 3 + +/* 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); +} + +/* 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; + +/* Tx we do not have full signatures for, but may appear on-chain */ +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; + +/* 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; + +/* 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; + +/* 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 + 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; + enum eltoo_tx_type tx_type; +}; + +/* How it actually got resolved. */ +struct resolution { + struct bitcoin_txid txid; + unsigned int depth; + enum eltoo_tx_type tx_type; +}; + +struct tracked_output { + 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 */ + u32 depth; + 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; + 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 */ + + /* 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 *eltoo_tx_type_name(enum eltoo_tx_type tx_type) +{ + size_t i; + + 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"; +} + +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 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 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, + take(towire_onchaind_notify_coin_mvt(NULL, mvt))); + + if (taken(mvt)) + 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, + const void *elem, size_t elem_size) +{ + struct bitcoin_tx *tx; + size_t max_weight; + 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; + + 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)); + + tx = bitcoin_tx(ctx, chainparams, 1, 1, locktime); + bitcoin_tx_add_input(tx, &out->outpoint, 0 /* sequence */, + 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" */ + 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 + /* elem size */ + elem_size + + 1 + /* signature size */ + 64 /* BIP340 sig with 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)); + } + + 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(); + } + + bitcoin_tx_input_set_witness(tx, 0 /* innum */, 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; + 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, + 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])); + } + return htlc_scripts; +} + +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(ctx, 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); + status_debug("HTLC timeout script %lu: %s", i, tal_hex(NULL, htlc_scripts[i])); + } + 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, + 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. 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, + int *parity_bit) +{ + 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)) { + /* 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 *funding_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; + //u8 *success_annex; + htlc_scripts[0] = htlc_success_scripts[i]; + htlc_scripts[1] = htlc_timeout_scripts[i]; + + 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; + + 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, 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)); + + 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); + } + } + return matches; +} + +static struct tracked_output * +new_tracked_output(struct tracked_output ***outs, + const struct bitcoin_outpoint *outpoint, + u32 tx_blockheight, + 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, + const u8 *htlc_timeout_tapscript 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), + eltoo_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->locktime = locktime; + out->proposal = NULL; + out->resolved = NULL; + if (scriptPubKey) + out->scriptPubKey = tal_dup_talarr(out, u8, scriptPubKey); + if (htlc) + out->htlc = *htlc; + 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); + + 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", + type_to_string(tmpctx, struct bitcoin_outpoint, + &out->outpoint), + eltoo_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 = ELTOO_SELF; +} + +static enum wallet_tx_type onchain_txtype_to_wallet_txtype(enum eltoo_tx_type t) +{ + /* FIXME Need to distinguish TX_THEIRS when possible (SUCCESS/TIMEOUT) */ + switch (t) { + case ELTOO_FUNDING_TRANSACTION: + return TX_CHANNEL_FUNDING; + case ELTOO_MUTUAL_CLOSE: + return TX_CHANNEL_CLOSE; + case ELTOO_UPDATE: + 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_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; + } + abort(); +} + +/** 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 eltoo_proposal_is_rbfable(const struct proposed_resolution *proposal) +{ + /* We may fee bump anything time-sensitive + */ + return proposal->tx_type == ELTOO_UPDATE || + proposal->tx_type == ELTOO_SETTLE || + proposal->tx_type == ELTOO_HTLC_SUCCESS || + proposal->tx_type == ELTOO_HTLC_TIMEOUT; +} + +/** 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 `eltoo_proposal_is_rbfable`. + */ +static void eltoo_proposal_should_rbf(struct tracked_output *out) +{ + struct bitcoin_tx *tx = NULL; + u32 depth; + + assert(out->proposal); + assert(eltoo_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; + + /* 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"", + eltoo_tx_type_name(out->proposal->tx_type), + type_to_string(tmpctx, struct bitcoin_tx, tx), + eltoo_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 eltoo_proposal_meets_depth(struct tracked_output *out) +{ + bool is_rbf = eltoo_proposal_is_rbfable(out->proposal); + + /* 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, + 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, + // 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), + type_to_string(tmpctx, struct bitcoin_tx, out->proposal->tx), + eltoo_tx_type_name(out->tx_type), + output_type_name(out->output_type)); + + 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 == ELTOO_IGNORING_TINY_PAYMENT) { + ignore_output(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)", + eltoo_tx_type_name(out->tx_type), + output_type_name(out->output_type), + eltoo_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 eltoo_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)", + eltoo_tx_type_name(out->tx_type), + output_type_name(out->output_type), + eltoo_tx_type_name(tx_type), + type_to_string(tmpctx, struct bitcoin_txid, txid)); +} + +static bool is_mutual_close(u32 locktime) +{ + /* If we mask update number, this needs to change */ + return locktime == 0; +} + +/* 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++) { + /* FIXME If an output gets reorged out, what do we do? */ + 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), + eltoo_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), + eltoo_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 propose_resolution(struct tracked_output *out, + const struct bitcoin_tx *tx, + unsigned int depth_required, + 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), + output_type_name(out->output_type), + eltoo_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) + 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, + 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(tx_type), + depth_required); + + out->proposal = tal(out, struct proposed_resolution); + out->proposal->depth_required = depth_required; + out->proposal->tx_type = tx_type; + + 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, + u32 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, tx_type); +} + +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_eltoo_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 == 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", + eltoo_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[0]; + } else + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "onchain_fulfill for %s/%s?", + eltoo_tx_type_name(out->tx_type), + output_type_name(out->output_type)); + + 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)", + 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, + &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", + 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, + take(towire_onchaind_extracted_preimage(NULL, + &preimage))); +} + +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))); +} + +struct htlcs_info { + struct htlc_stub *htlcs; + bool *tell_if_missing; + 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); + 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) { + /* 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 { + 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; + /* 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 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 */, + 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); + } + assert(out); + continue; + } + } +} + +/* 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); + + status_debug("Creating HTLC success sweep transaction to be signed"); + 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_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, + &preimage, + sizeof(preimage)); + + propose_resolution(outs[i], tx, 0 /* depth_required */, tx_type); + } +} + +static void eltoo_handle_cached_preimages(struct tracked_output **outs, + struct preimage *cached_preimages) +{ + status_debug("Processing cached preimages now that we have settle tx confirmed"); + for (int j=0; jresolved) + continue; + + if (!wally_tx_input_spends(tx_parts->inputs[input_num], + &out->outpoint)) + continue; + + /* 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); + + /* Now that we've left update phase and know settlement outputs, process cached preimages */ + eltoo_handle_cached_preimages(*outs, cached_preimages); + + } else if (locktime != out->locktime && update_phase) { + /* (2) Update transaction*/ + + /* 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, tx_parts->outputs[input_num]->script, 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(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; + } + + /* 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); +} + +static void eltoo_update_resolution_depth(struct tracked_output *out, u32 depth) +{ + bool reached_reasonable_depth; + + status_debug("%s/%s->%s depth %u", + eltoo_tx_type_name(out->tx_type), + output_type_name(out->output_type), + eltoo_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 #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. + * 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_HTLC_TIMEOUT && reached_reasonable_depth) { + u8 *msg; + status_debug("%s/%s reached reasonable depth %u", + eltoo_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 eltoo_tx_new_depth(struct tracked_output **outs, + const struct bitcoin_txid *txid, u32 depth) +{ + size_t i; + + /* 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. */ + if (bitcoin_txid_eq(&outs[i]->outpoint.txid, txid)) + outs[i]->depth = depth; + + /* 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)) { + eltoo_update_resolution_depth(outs[i], depth); + } + continue; + } + + /* Otherwise, is this something we have a pending + * proposal resolution for? */ + if (outs[i]->proposal + && bitcoin_txid_eq(&outs[i]->outpoint.txid, txid) + && depth >= outs[i]->proposal->depth_required) { + eltoo_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) + && eltoo_proposal_is_rbfable(outs[i]->proposal)) + eltoo_proposal_should_rbf(outs[i]); + + } +} + + +#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, 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 */ + +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(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; + struct bitcoin_txid txid; + 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]); + 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)) { + 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, locktime, htlc_success_scripts, htlc_timeout_scripts, htlcs_info); + } else if (fromwire_onchaind_known_preimage(msg, &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); + + billboard_update(outs); + tal_free(msg); + clean_tmpctx(); + } + + wire_sync_write(REQ_FD, + take(towire_onchaind_all_irrevocably_resolved(outs))); +} + +struct htlc_with_tells { + struct htlc_stub htlc; + 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; +} + +/* 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_onchaind_htlcs(tmpctx, msg, + &htlcs_info->htlcs, + &htlcs_info->tell_if_missing, + &htlcs_info->tell_immediately)) { + 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]; + 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; + } + + status_debug("Handling %lu HTLC scripts for possible resolution", tal_count(htlcs_info->htlcs)); + + return htlcs_info; +} + +/* 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; + /* 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++) { + 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)); + return i; +} + +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: + * + * 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_mutual_resolved(outs); +} + +static void handle_unilateral(const struct tx_parts *tx, + u32 tx_blockheight, + 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; + const struct pubkey *funding_pubkey_ptrs[2]; + secp256k1_musig_keyagg_cache keyagg_cache; + + /* 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 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); + + resolved_by_other(outs[0], &tx->txid, ELTOO_UPDATE); + + out = new_tracked_output(&outs, + &outpoint, tx_blockheight, + ELTOO_UPDATE, + amt, + DELAYED_OUTPUT_TO_US, + tx->outputs[state_index]->script, + locktime, + NULL /* htlc */, NULL /* htlc_success_tapscript */, NULL /* htlc_timeout_tapscript */); + + /* Fill out inner pubkey to complete re-binding of update transactions going forward */ + funding_pubkey_ptrs[0] = &keyset->self_funding_key; + funding_pubkey_ptrs[1] = &keyset->other_funding_key; + bipmusig_inner_pubkey(&keyset->inner_pubkey, + &keyagg_cache, + funding_pubkey_ptrs, + /* n_pubkeys */ 2); + + /* FIXME I think this logic will be the same in main loop under output_spent */ + + /* 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 */ + 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->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, + 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))); + + } + + wait_for_resolved(outs, htlcs_info); + + tal_free(htlcs_info); +} + +int main(int argc, char *argv[]) +{ + setup_locale(); + + const tal_t *ctx = tal(NULL, char); + u8 *msg; + struct tx_parts *spending_tx; + struct tracked_output **outs; + struct bitcoin_outpoint funding; + struct amount_sat funding_sats; + u32 locktime, tx_blockheight; + /* UNUSED */ + u8 *scriptpubkey[NUM_SIDES]; + + keyset = tal(ctx, struct eltoo_keyset); + + subdaemon_setup(argc, argv); + + status_setup_sync(REQ_FD); + + 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, + msg, + &chainparams, + &funding, + &funding_sats, + &spending_tx, + &locktime, + /* Transactions are global for ease of access */ + &complete_update_tx, + &complete_settle_tx, + &committed_update_tx, + &committed_settle_tx, + &tx_blockheight, + &our_msat, + &htlc_feerate, + &dust_limit, + &scriptpubkey[LOCAL], + &scriptpubkey[REMOTE], + &keyset->self_funding_key, + &keyset->other_funding_key, + &keyset->self_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); + } + + update_phase = true; + + // 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 a constant number: not really a leak */ + tal_steal(ctx, notleak(spending_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, complete_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, complete_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, committed_update_tx), + type_to_string(tmpctx, struct bitcoin_tx, committed_settle_tx)); + } + + /* These are the utxos we are interested in */ + outs = tal_arr(ctx, struct tracked_output *, 0); + + /* 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 /* scriptPubKey*/, + 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, + &funding, tx_blockheight, + our_msat, + funding_sats, + tal_count(spending_tx->outputs)))); + + /* Committed state should be one step further max */ + 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); + } + + if (is_mutual_close(locktime)) { + status_debug("Handling mutual close!"); + eltoo_handle_mutual_close(outs, spending_tx); + } else { + status_debug("Handling unilateral close!"); + handle_unilateral(spending_tx, tx_blockheight, outs, locktime); + } + + /* We're done! */ + tal_free(ctx); + daemon_shutdown(); + + return 0; +} diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index 3e1e874f90d5..bd007714639f 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -51,6 +51,48 @@ 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, + + /* Latest unilateral: 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 to outselves */ + 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 */ + 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 +106,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 +117,7 @@ enum output_type { ELEMENTS_FEE, /* Anchor outputs for option_anchor_outputs */ - ANCHOR_TO_US, + ANCHOR_TO_US, /* Eltoo: ephemeral anchor */ ANCHOR_TO_THEM, }; diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 7d10e36a4b5c..8fae89bfb93c 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, @@ -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 e2dfd031620a..b10fba95fed6 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, @@ -139,3 +140,42 @@ 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 +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,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,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, +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, +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 + +# 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/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, 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/common.c b/openingd/common.c index c31bb7774d72..8b71e04a8ca9 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 channel_config *remoteconf, + const struct 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. */ @@ -263,3 +355,25 @@ void validate_initial_commitment_signature(int hsm_fd, tal_hex(tmpctx, msg)); } +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; + 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 838321867dda..0c32d37de37f 100644 --- a/openingd/common.h +++ b/openingd/common.h @@ -4,10 +4,18 @@ #include "config.h" struct amount_sat; +struct bip340sig; 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 channel_config *remoteconf, + const struct channel_config *localconf, + char **err_reason); bool check_config_bounds(const tal_t *ctx, struct amount_sat funding, @@ -27,4 +35,9 @@ 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_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/dualopend.c b/openingd/dualopend.c index 2afcc4993586..d4efa7e5494a 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -1295,6 +1295,20 @@ 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: + /* 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 @@ -1638,6 +1652,20 @@ 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: + /* 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 @@ -3762,6 +3790,20 @@ static u8 *handle_peer_in(struct state *state) case WIRE_WARNING: case WIRE_PING: 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 new file mode 100644 index 000000000000..faf2f48f304c --- /dev/null +++ b/openingd/eltoo_openingd.c @@ -0,0 +1,1426 @@ +/*~ 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 // channel +#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. Copied into channel.eltoo_keyset */ + struct pubkey our_funding_pubkey; + struct pubkey our_settlement_pubkey; + + /* Information we need between funding_start and funding_complete + * Copied into channel.eltoo_keyset */ + 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; + + /* 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 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 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); +} + +/*~ 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) +{ + +#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; + u8 *funding_output_script; + struct channel_id id_in; + struct tlv_open_channel_eltoo_tlvs *open_tlvs; + struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; + char *err_reason; + + 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_eltoo_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; + + /* Fetch MuSig nonce */ + msg = towire_hsmd_gen_nonce(NULL, &state->channel_id); + wire_sync_write(HSM_FD, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + 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)); + } + + 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, + state->funding_sats, + state->push_msat, + state->localconf.dust_limit, + state->localconf.max_htlc_value_in_flight, + state->localconf.htlc_minimum, + state->localconf.shared_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_settlement_pubkey, /* FIXME is this set?? */ + channel_flags, + &state->our_init_nonce, + 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. + */ + if (!fromwire_accept_channel_eltoo(tmpctx, msg, &id_in, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.htlc_minimum, + &state->minimum_depth, + &state->remoteconf.shared_delay, + &state->remoteconf.max_accepted_htlcs, + &state->their_funding_pubkey, + &state->their_settlement_pubkey, + &state->their_init_nonce, + &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); + + 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: + * - 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 (!check_eltoo_config_bounds(tmpctx, state->funding_sats, + state->max_shared_delay, + state->min_effective_htlc_capacity, + &state->remoteconf, + &state->localconf, + &err_reason)) { + negotiation_failed(state, "%s", err_reason); + 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); + + /* 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_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 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; + struct eltoo_sign dummy_committed_state; + + /*~ Channel is ready; Report the channel parameters to the signer. */ + msg = towire_hsmd_ready_eltoo_channel(NULL, + /* is_outbound */ 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_funding_pubkey, + &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", + 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 + * 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 + * enough for us here, and the complete channel support required by + * `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, + 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, + &dummy_complete_state, + &dummy_committed_state, + state->channel_type, + feature_offered(state->their_features, + 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) + 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(state, state->channel, + direct_outputs); + if (!*settle_tx) { + negotiation_failed(state, + "Could not make settle tx???"); + return false; + } + + *update_tx = initial_update_channel_tx(state, *settle_tx, state->channel); + + if (!*update_tx) { + negotiation_failed(state, + "Could not make update tx???"); + return false; + } + + /* 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. */ + msg = towire_hsmd_psign_update_tx(NULL, + &cid, /* We track signature sessions via "final" channel id only */ + *update_tx, + *settle_tx, + &state->their_funding_pubkey, + &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", + 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->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 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.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, &cache)) + 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.last_committed_state.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->channel->eltoo_keyset.inner_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)); + + /* 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, + &state->channel->eltoo_keyset.last_committed_state.self_psig, + &state->channel->eltoo_keyset.self_next_nonce); + peer_write(state->pps, msg); + + /* BOLT #2: + * + * ### The `funding_signed_eltoo` Message + * + * 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, + "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) + return false; + + 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)); + + 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. + * 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 the initial update transaction, and check the + * signature they sent against that. */ + + /* 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, + &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); + 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)); + } + + /* 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"); + + return true; +} + +static u8 *funder_channel_complete(struct eltoo_state *state) +{ + /* 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*/ + 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, &update_tx, &settle_tx)) + return NULL; + + return towire_openingd_eltoo_funder_reply(state, + &state->remoteconf, + update_tx, + settle_tx, + state->minimum_depth, + &state->channel->eltoo_keyset.other_funding_key, + &state->channel->eltoo_keyset.other_settle_key, + &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, + 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; + struct bip340sig update_sig; + struct bitcoin_tx *settle_tx, *update_tx; + struct bitcoin_blkid chain_hash; + u8 *msg; + u8 channel_flags; + u16 funding_txout; + char* err_reason; + struct tlv_accept_channel_eltoo_tlvs *accept_tlvs; + struct tlv_open_channel_eltoo_tlvs *open_tlvs; + 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; + + struct eltoo_sign committed_state; + + /* 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. + */ + 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.htlc_minimum, + &state->remoteconf.shared_delay, + &state->remoteconf.max_accepted_htlcs, + &state->their_funding_pubkey, + &state->their_settlement_pubkey, + &channel_flags, + &state->their_init_nonce, + &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); + + 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: + *... + * - 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; + } + + /* These checks are the same whether we're opener or accepter... */ + if (!check_eltoo_config_bounds(tmpctx, state->funding_sats, + state->max_shared_delay, + state->min_effective_htlc_capacity, + &state->remoteconf, + &state->localconf, + &err_reason)) { + negotiation_failed(state, "%s", err_reason); + tal_free(err_reason); + 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, + state->our_features, + state->their_features); + + /* OK, we accept! */ + accept_tlvs = tlv_accept_channel_eltoo_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; + + /* Fetch MuSig nonce for channel since we have none yet */ + msg = towire_hsmd_gen_nonce(NULL, &state->channel_id); + wire_sync_write(HSM_FD, take(msg)); + + msg = wire_sync_read(tmpctx, HSM_FD); + 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)); + } + + 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, + state->localconf.htlc_minimum, + state->minimum_depth, + state->localconf.shared_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_settlement_pubkey, + &state->our_init_nonce, + 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_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, + &funding_txout, + &committed_state.other_psig, + &their_second_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; + + /* 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. */ + msg = towire_hsmd_ready_eltoo_channel(NULL, + /* is_outbound */ false, + 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_funding_pubkey, + &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", + 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, + &state->their_funding_pubkey, + &state->our_settlement_pubkey, + &state->their_settlement_pubkey, + &dummy_complete_state, + &committed_state, + state->channel_type, + feature_offered(state->their_features, + 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) + 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); + /* This shouldn't happen either, AFAICT. */ + if (!settle_tx) { + negotiation_failed(state, + "Failed to make settle tx???"); + return NULL; + } + + update_tx = initial_update_channel_tx(tmpctx, settle_tx, state->channel); + /* Nor this */ + if (!update_tx) { + negotiation_failed(state, + "Failed to make update tx???"); + return NULL; + } + + /* 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); + + /* 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. + * + * FIXME: Perhaps we should have channeld generate this, so we + * can't possibly send before channel committed to disk? + */ + + /* BOLT #2: + * + * ### 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 + * that funds can be redeemed, if need be. + */ + + /* Make HSM sign it */ + msg = towire_hsmd_psign_update_tx(NULL, + &state->channel_id, /* Final channel_id just derived above */ + update_tx, + settle_tx, + &state->their_funding_pubkey, + &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", + type_to_string(tmpctx, struct bitcoin_tx, update_tx), + type_to_string(tmpctx, struct 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 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); + /* 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, &cache)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); + + /* 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.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), + 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, + &state->channel->eltoo_keyset.self_next_nonce), + type_to_string(tmpctx, struct 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, + &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); + 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)); + } + + /* 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. */ + 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 */ + bind_tx_to_funding_outpoint(update_tx, + settle_tx, + &state->funding, + &state->channel->eltoo_keyset, + &state->channel->eltoo_keyset.inner_pubkey, + &update_sig); + + return towire_openingd_eltoo_fundee(state, + &state->remoteconf, + update_tx, + settle_tx, + &state->their_funding_pubkey, + &state->their_settlement_pubkey, + &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, + state->funding_sats, + state->push_msat, + channel_flags, + msg, + 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_ELTOO) + 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; + struct bitcoin_txid funding_txid; + u16 funding_txout; + + switch (t) { + case WIRE_OPENINGD_ELTOO_FUNDER_START: + 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->channel_id, + &channel_flags)) + 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) + wire_sync_write(REQ_FD, take(msg)); + return NULL; + case WIRE_OPENINGD_ELTOO_FUNDER_COMPLETE: + if (!fromwire_openingd_eltoo_funder_complete(state, msg, + &funding_txid, + &funding_txout, + &state->channel_type)) + 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 */ + 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: + case WIRE_OPENINGD_ELTOO_GOT_OFFER: + case WIRE_OPENINGD_ELTOO_GOT_OFFER_REPLY: + 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. + */ diff --git a/openingd/eltoo_openingd_wire.csv b/openingd/eltoo_openingd_wire.csv new file mode 100644 index 000000000000..1fb50b3b7879 --- /dev/null +++ b/openingd/eltoo_openingd_wire.csv @@ -0,0 +1,133 @@ +#include +#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 +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, +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. +# 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_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 +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,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,channel_config, +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, +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,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, + +# 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/tests/test_closing.py b/tests/test_closing.py index 36c510b63cbd..7ae68bbf8c50 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,7 +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) - @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..cc69dcd0356a --- /dev/null +++ b/tests/test_eltoo.py @@ -0,0 +1,276 @@ +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 time +import unittest + +# In msats +SAT = 1000 + +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'] + + 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_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 + flow is essentially the offerer getting the ACK back on reconnect """ + + # 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) + + # 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)) + +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 """ + + # Want offering node to disconnect right before sending off 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}]) + + # 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): + """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}]) + + # 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 + + # 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""" + + # 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_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""" + + # 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) + + # 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 + 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') diff --git a/wallet/db.c b/wallet/db.c index 04497400dcdb..79b8da31b5f1 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -141,6 +141,20 @@ static struct migration dbmigrations[] = { " last_sig BLOB," " closing_fee_received INTEGER," " closing_sig_received BLOB," + /* START Eltoo stuff*/ + " 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 */ " PRIMARY KEY (id)" ");"), NULL}, @@ -152,6 +166,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/test/run-wallet.c b/wallet/test/run-wallet.c index eee265e4f0ac..a44f61a619cb 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -51,6 +51,33 @@ 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, + 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 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, @@ -136,18 +163,30 @@ 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(); } /* 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(); } +/* 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(); } +/* 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, 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) { fprintf(stderr, "fromwire_connectd_peer_active called!\n"); abort(); } @@ -648,9 +687,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) + struct peer_fd *peer_fd UNNEEDED, + 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) @@ -726,18 +773,30 @@ 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(); } /* 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(); } +/* 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(); } +/* 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(); } @@ -1619,7 +1678,15 @@ 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 /* 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); CHECK(!wallet_err); wallet_channel_insert(w, chan); diff --git a/wallet/wallet.c b/wallet/wallet.c index ff9506299b67..292242fc27d1 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; } @@ -1330,17 +1331,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 +1351,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 +1360,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) { @@ -1482,7 +1485,15 @@ 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_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 */); if (!wallet_channel_load_inflights(w, chan)) { tal_free(chan); @@ -1772,7 +1783,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); @@ -1781,7 +1793,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)); } @@ -1859,8 +1872,20 @@ 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 - " WHERE id=?")); // 44 + " htlc_maximum_msat=?," // 43 + " 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); @@ -1889,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); @@ -1925,7 +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_u64(stmt, 44, 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); @@ -2892,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 * diff --git a/wire/Makefile b/wire/Makefile index d6f1bf5f593b..c328a02f5da5 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -13,7 +13,7 @@ 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 \ # We don't include peer_printgen/onion_printgen here since most don't need it. WIRE_SRC := wire/wire_sync.c \ @@ -25,7 +25,7 @@ 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_PRINT_SRC := \ wire/onion$(EXP)_printgen.c \ @@ -77,7 +77,7 @@ BOLT12_PATCHES := $(filter-out $(BOLT12_EXP_PATCHES),$(ALL_BOLT12_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 +89,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; cat wire/eltoo_wire.csv >> wire/peer_wire.csv + wire/peer_wire.csv.raw: bolt-precheck @$(BOLT_EXTRACT) $(LOCAL_BOLTDIR)/0[127]*.md > $@ @@ -98,6 +101,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-eltoo*.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 +115,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..1ec067e13819 --- /dev/null +++ b/wire/eltoo_wire.csv @@ -0,0 +1,76 @@ +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, diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 35089e48f1d7..7f672a9bd4b5 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -47,6 +47,20 @@ 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: + /* 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 @@ -101,6 +115,20 @@ 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: + /* 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 @@ -155,6 +183,20 @@ 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: + /* 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 @@ -239,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 */ @@ -392,6 +435,22 @@ 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 */ + /* Eltoo stuff */ + 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 a028ddc66d92..34057ee9cc41 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, @@ -338,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,