diff --git a/closingd/closingd.c b/closingd/closingd.c index 106b7caa552d..fe575736d53c 100644 --- a/closingd/closingd.c +++ b/closingd/closingd.c @@ -187,7 +187,7 @@ static void send_offer(struct per_peer_state *pps, type_to_string(tmpctx, struct amount_sat, &fee_to_offer)); assert(our_sig.sighash_type == SIGHASH_ALL); - msg = towire_closing_signed(NULL, channel_id, fee_to_offer, &our_sig.s); + msg = towire_closing_signed(NULL, channel_id, fee_to_offer, &our_sig.s, NULL); sync_crypto_write(pps, take(msg)); } @@ -231,6 +231,7 @@ receive_offer(struct per_peer_state *pps, struct amount_sat received_fee; struct bitcoin_signature their_sig; struct bitcoin_tx *tx; + struct tlv_closing_signed_tlvs *close_tlvs; /* Wait for them to say something interesting */ do { @@ -254,8 +255,10 @@ receive_offer(struct per_peer_state *pps, } while (!msg); their_sig.sighash_type = SIGHASH_ALL; + close_tlvs = tlv_closing_signed_tlvs_new(msg); if (!fromwire_closing_signed(msg, &their_channel_id, - &received_fee, &their_sig.s)) + &received_fee, &their_sig.s, + close_tlvs)) peer_failed_warn(pps, channel_id, "Expected closing_signed: %s", tal_hex(tmpctx, msg)); diff --git a/wire/extracted_peer_04_closing_fee_nego.patch b/wire/extracted_peer_04_closing_fee_nego.patch new file mode 100644 index 000000000000..0fe946af0721 --- /dev/null +++ b/wire/extracted_peer_04_closing_fee_nego.patch @@ -0,0 +1,13 @@ +--- wire/peer_wire.csv 2021-05-18 11:15:05.539134131 -0500 ++++ - 2021-05-18 11:15:15.690789516 -0500 +@@ -90,6 +90,10 @@ + msgdata,closing_signed,channel_id,channel_id, + msgdata,closing_signed,fee_satoshis,u64, + msgdata,closing_signed,signature,signature, ++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_add_htlc,128 + msgdata,update_add_htlc,channel_id,channel_id, + msgdata,update_add_htlc,id,u64, diff --git a/wire/peer_printgen.c b/wire/peer_printgen.c index 74baba6a4106..f8ab33376f5d 100644 --- a/wire/peer_printgen.c +++ b/wire/peer_printgen.c @@ -518,6 +518,33 @@ static const struct tlv_print_record_type print_tlvs_shutdown_tlvs[] = { { 100, printwire_tlv_shutdown_tlvs_wrong_funding }, }; +static void printwire_tlv_closing_signed_tlvs_fee_range(const char *fieldname, const u8 **cursor, size_t *plen) +{ + printf("(msg_name=%s)\n", "fee_range"); + + printf("min_fee_satoshis="); + struct amount_sat min_fee_satoshis = fromwire_amount_sat(cursor, plen); + + printwire_amount_sat(tal_fmt(NULL, "%s.min_fee_satoshis", fieldname), &min_fee_satoshis); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + printf("max_fee_satoshis="); + struct amount_sat max_fee_satoshis = fromwire_amount_sat(cursor, plen); + + printwire_amount_sat(tal_fmt(NULL, "%s.max_fee_satoshis", fieldname), &max_fee_satoshis); + if (!*cursor) { + printf("**TRUNCATED**\n"); + return; + } + +} + +static const struct tlv_print_record_type print_tlvs_closing_signed_tlvs[] = { + { 1, printwire_tlv_closing_signed_tlvs_fee_range }, +}; + static void printwire_tlv_query_short_channel_ids_tlvs_query_flags(const char *fieldname, const u8 **cursor, size_t *plen) { printf("(msg_name=%s)\n", "query_flags"); @@ -1924,6 +1951,8 @@ void printwire_closing_signed(const char *fieldname, const u8 *cursor) printf("**TRUNCATED**\n"); return; } + printf("tlvs="); + printwire_tlvs(tal_fmt(NULL, "%s.tlvs", fieldname), &cursor, &plen, print_tlvs_closing_signed_tlvs, ARRAY_SIZE(print_tlvs_closing_signed_tlvs)); if (plen != 0) @@ -2922,6 +2951,9 @@ void printpeer_wire_tlv_message(const char *tlv_name, const u8 *msg) { if (strcmp(tlv_name, "shutdown_tlvs") == 0) { printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_shutdown_tlvs, ARRAY_SIZE(print_tlvs_shutdown_tlvs)); } + if (strcmp(tlv_name, "closing_signed_tlvs") == 0) { + printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_closing_signed_tlvs, ARRAY_SIZE(print_tlvs_closing_signed_tlvs)); + } if (strcmp(tlv_name, "query_short_channel_ids_tlvs") == 0) { printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_query_short_channel_ids_tlvs, ARRAY_SIZE(print_tlvs_query_short_channel_ids_tlvs)); } @@ -2935,4 +2967,4 @@ void printpeer_wire_tlv_message(const char *tlv_name, const u8 *msg) { printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_onion_message_tlvs, ARRAY_SIZE(print_tlvs_onion_message_tlvs)); } } -// SHA256STAMP:d4f6f16581d26f95c512a5a98e962abe529ff37a70a7563bd41f25ac802bdb63 +// SHA256STAMP:fc3f11a2f65e54398d8736b4db8458bf9582651ccddb9370954b2e182fce8cfc diff --git a/wire/peer_printgen.h b/wire/peer_printgen.h index a678cadb6734..121c55b22f5e 100644 --- a/wire/peer_printgen.h +++ b/wire/peer_printgen.h @@ -96,4 +96,4 @@ void printwire_channel_update_checksums(const char *fieldname, const u8 **cursor void printwire_channel_update_timestamps(const char *fieldname, const u8 **cursor, size_t *plen); void printwire_witness_stack(const char *fieldname, const u8 **cursor, size_t *plen); #endif /* LIGHTNING_WIRE_PEER_PRINTGEN_H */ -// SHA256STAMP:d4f6f16581d26f95c512a5a98e962abe529ff37a70a7563bd41f25ac802bdb63 +// SHA256STAMP:fc3f11a2f65e54398d8736b4db8458bf9582651ccddb9370954b2e182fce8cfc diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 40b78f1751c4..4e3631f16735 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -182,6 +182,10 @@ msgtype,closing_signed,39 msgdata,closing_signed,channel_id,channel_id, msgdata,closing_signed,fee_satoshis,u64, msgdata,closing_signed,signature,signature, +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_add_htlc,128 msgdata,update_add_htlc,channel_id,channel_id, msgdata,update_add_htlc,id,u64, diff --git a/wire/peer_wiregen.c b/wire/peer_wiregen.c index a68a873666ed..ace400c6152a 100644 --- a/wire/peer_wiregen.c +++ b/wire/peer_wiregen.c @@ -748,6 +748,63 @@ bool shutdown_tlvs_is_valid(const struct tlv_shutdown_tlvs *record, size_t *err_ } +struct tlv_closing_signed_tlvs *tlv_closing_signed_tlvs_new(const tal_t *ctx) +{ + /* Initialize everything to NULL. (Quiet, C pedants!) */ + struct tlv_closing_signed_tlvs *inst = talz(ctx, struct tlv_closing_signed_tlvs); + + /* Initialized the fields to an empty array. */ + inst->fields = tal_arr(inst, struct tlv_field, 0); + return inst; +} + +/* CLOSING_SIGNED_TLVS MSG: fee_range */ +static u8 *towire_tlv_closing_signed_tlvs_fee_range(const tal_t *ctx, const void *vrecord) +{ + const struct tlv_closing_signed_tlvs *r = vrecord; + u8 *ptr; + + if (!r->fee_range) + return NULL; + + + ptr = tal_arr(ctx, u8, 0); + + towire_amount_sat(&ptr, r->fee_range->min_fee_satoshis); + + towire_amount_sat(&ptr, r->fee_range->max_fee_satoshis); + return ptr; +} +static void fromwire_tlv_closing_signed_tlvs_fee_range(const u8 **cursor, size_t *plen, void *vrecord) +{ + struct tlv_closing_signed_tlvs *r = vrecord; + + r->fee_range = tal(r, struct tlv_closing_signed_tlvs_fee_range); + r->fee_range->min_fee_satoshis = fromwire_amount_sat(cursor, plen); + r->fee_range->max_fee_satoshis = fromwire_amount_sat(cursor, plen); +} + +static const struct tlv_record_type tlvs_closing_signed_tlvs[] = { + { 1, towire_tlv_closing_signed_tlvs_fee_range, fromwire_tlv_closing_signed_tlvs_fee_range }, +}; + +void towire_closing_signed_tlvs(u8 **pptr, const struct tlv_closing_signed_tlvs *record) +{ + towire_tlv(pptr, tlvs_closing_signed_tlvs, 1, record); +} + + +bool fromwire_closing_signed_tlvs(const u8 **cursor, size_t *max, struct tlv_closing_signed_tlvs *record) +{ + return fromwire_tlv(cursor, max, tlvs_closing_signed_tlvs, 1, record, &record->fields); +} + +bool closing_signed_tlvs_is_valid(const struct tlv_closing_signed_tlvs *record, size_t *err_index) +{ + return tlv_fields_valid(record->fields, NULL, err_index); +} + + struct tlv_query_short_channel_ids_tlvs *tlv_query_short_channel_ids_tlvs_new(const tal_t *ctx) { /* Initialize everything to NULL. (Quiet, C pedants!) */ @@ -1705,7 +1762,7 @@ bool fromwire_shutdown(const tal_t *ctx, const void *p, struct channel_id *chann } /* WIRE: CLOSING_SIGNED */ -u8 *towire_closing_signed(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat fee_satoshis, const secp256k1_ecdsa_signature *signature) +u8 *towire_closing_signed(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat fee_satoshis, const secp256k1_ecdsa_signature *signature, const struct tlv_closing_signed_tlvs *tlvs) { u8 *p = tal_arr(ctx, u8, 0); @@ -1713,10 +1770,11 @@ u8 *towire_closing_signed(const tal_t *ctx, const struct channel_id *channel_id, towire_channel_id(&p, channel_id); towire_amount_sat(&p, fee_satoshis); towire_secp256k1_ecdsa_signature(&p, signature); + towire_closing_signed_tlvs(&p, tlvs); return memcheck(p, tal_count(p)); } -bool fromwire_closing_signed(const void *p, struct channel_id *channel_id, struct amount_sat *fee_satoshis, secp256k1_ecdsa_signature *signature) +bool fromwire_closing_signed(const void *p, struct channel_id *channel_id, struct amount_sat *fee_satoshis, secp256k1_ecdsa_signature *signature, struct tlv_closing_signed_tlvs *tlvs) { const u8 *cursor = p; size_t plen = tal_count(p); @@ -1726,6 +1784,7 @@ bool fromwire_closing_signed(const void *p, struct channel_id *channel_id, struc fromwire_channel_id(&cursor, &plen, channel_id); *fee_satoshis = fromwire_amount_sat(&cursor, &plen); fromwire_secp256k1_ecdsa_signature(&cursor, &plen, signature); + fromwire_closing_signed_tlvs(&cursor, &plen, tlvs); return cursor != NULL; } @@ -2330,4 +2389,4 @@ bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ec *htlc_maximum_msat = fromwire_amount_msat(&cursor, &plen); return cursor != NULL; } -// SHA256STAMP:d4f6f16581d26f95c512a5a98e962abe529ff37a70a7563bd41f25ac802bdb63 +// SHA256STAMP:fc3f11a2f65e54398d8736b4db8458bf9582651ccddb9370954b2e182fce8cfc diff --git a/wire/peer_wiregen.h b/wire/peer_wiregen.h index 994b98a0e8ec..6f59e4f88700 100644 --- a/wire/peer_wiregen.h +++ b/wire/peer_wiregen.h @@ -99,6 +99,10 @@ struct tlv_shutdown_tlvs_wrong_funding { struct bitcoin_txid txid; u32 outnum; }; +struct tlv_closing_signed_tlvs_fee_range { + struct amount_sat min_fee_satoshis; + struct amount_sat max_fee_satoshis; +}; struct tlv_query_short_channel_ids_tlvs_query_flags { u8 encoding_type; u8 *encoded_query_flags; @@ -175,6 +179,14 @@ struct tlv_shutdown_tlvs { * tlv_field entries above to save on memory. */ struct tlv_shutdown_tlvs_wrong_funding *wrong_funding; }; +struct tlv_closing_signed_tlvs { + /* Raw fields including unknown ones. */ + struct tlv_field *fields; + + /* TODO The following explicit fields could just point into the + * tlv_field entries above to save on memory. */ + struct tlv_closing_signed_tlvs_fee_range *fee_range; +}; struct tlv_query_short_channel_ids_tlvs { /* Raw fields including unknown ones. */ struct tlv_field *fields; @@ -529,6 +541,43 @@ void towire_shutdown_tlvs(u8 **pptr, const struct tlv_shutdown_tlvs *record); bool shutdown_tlvs_is_valid(const struct tlv_shutdown_tlvs *record, size_t *err_index); +struct tlv_closing_signed_tlvs *tlv_closing_signed_tlvs_new(const tal_t *ctx); + +/** + * Deserialize a TLV stream for the closing_signed_tlvs namespace. + * + * This function will parse any TLV stream, as long as the type, length and + * value fields are formatted correctly. Fields that are not known in the + * current namespace are stored in the `fields` member. Validity can be + * checked using closing_signed_tlvs_is_valid. + */ +bool fromwire_closing_signed_tlvs(const u8 **cursor, size_t *max, + struct tlv_closing_signed_tlvs * record); + +/** + * Serialize a TLV stream for the closing_signed_tlvs namespace. + * + * This function only considers known fields from the closing_signed_tlvs namespace, + * and will ignore any fields that may be stored in the `fields` member. This + * ensures that the resulting stream is valid according to + * `closing_signed_tlvs_is_valid`. + */ +void towire_closing_signed_tlvs(u8 **pptr, const struct tlv_closing_signed_tlvs *record); + +/** + * Check that the TLV stream is valid. + * + * Enforces the followin validity rules: + * - Types must be in monotonic non-repeating order + * - We must understand all even types + * + * Returns false if an error was detected, otherwise returns true. If err_index + * is non-null and we detect an error it is set to the index of the first error + * detected. + */ +bool closing_signed_tlvs_is_valid(const struct tlv_closing_signed_tlvs *record, + size_t *err_index); + struct tlv_query_short_channel_ids_tlvs *tlv_query_short_channel_ids_tlvs_new(const tal_t *ctx); /** @@ -778,8 +827,8 @@ u8 *towire_shutdown(const tal_t *ctx, const struct channel_id *channel_id, const bool fromwire_shutdown(const tal_t *ctx, const void *p, struct channel_id *channel_id, u8 **scriptpubkey, struct tlv_shutdown_tlvs *tlvs); /* WIRE: CLOSING_SIGNED */ -u8 *towire_closing_signed(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat fee_satoshis, const secp256k1_ecdsa_signature *signature); -bool fromwire_closing_signed(const void *p, struct channel_id *channel_id, struct amount_sat *fee_satoshis, secp256k1_ecdsa_signature *signature); +u8 *towire_closing_signed(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat fee_satoshis, const secp256k1_ecdsa_signature *signature, const struct tlv_closing_signed_tlvs *tlvs); +bool fromwire_closing_signed(const void *p, struct channel_id *channel_id, struct amount_sat *fee_satoshis, secp256k1_ecdsa_signature *signature, struct tlv_closing_signed_tlvs *tlvs); /* WIRE: UPDATE_ADD_HTLC */ u8 *towire_update_add_htlc(const tal_t *ctx, const struct channel_id *channel_id, u64 id, struct amount_msat amount_msat, const struct sha256 *payment_hash, u32 cltv_expiry, const u8 onion_routing_packet[1366]); @@ -859,4 +908,4 @@ bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ec #endif /* LIGHTNING_WIRE_PEER_WIREGEN_H */ -// SHA256STAMP:d4f6f16581d26f95c512a5a98e962abe529ff37a70a7563bd41f25ac802bdb63 +// SHA256STAMP:fc3f11a2f65e54398d8736b4db8458bf9582651ccddb9370954b2e182fce8cfc diff --git a/wire/test/run-peer-wire.c b/wire/test/run-peer-wire.c index 160a889bbf35..0ab898112169 100644 --- a/wire/test/run-peer-wire.c +++ b/wire/test/run-peer-wire.c @@ -611,20 +611,27 @@ static struct msg_funding_signed *fromwire_struct_funding_signed(const tal_t *ct static void *towire_struct_closing_signed(const tal_t *ctx, const struct msg_closing_signed *s) { + struct tlv_closing_signed_tlvs *close_tlvs; + + close_tlvs = tlv_closing_signed_tlvs_new(ctx); return towire_closing_signed(ctx, &s->channel_id, s->fee_satoshis, - &s->signature); + &s->signature, + close_tlvs); } static struct msg_closing_signed *fromwire_struct_closing_signed(const tal_t *ctx, const void *p) { struct msg_closing_signed *s = tal(ctx, struct msg_closing_signed); + struct tlv_closing_signed_tlvs *close_tlvs; + close_tlvs = tlv_closing_signed_tlvs_new(ctx); if (fromwire_closing_signed(p, &s->channel_id, &s->fee_satoshis, - &s->signature)) + &s->signature, + close_tlvs)) return s; return tal_free(s); }