diff --git a/common/test/run-bolt12_merkle.c b/common/test/run-bolt12_merkle.c index 228da66d08b1..fad71bbc70ff 100644 --- a/common/test/run-bolt12_merkle.c +++ b/common/test/run-bolt12_merkle.c @@ -326,7 +326,7 @@ int main(int argc, char *argv[]) invreq->invreq_metadata = tal_arrz(invreq, u8, 8); /* Populate ->fields array, for merkle routine */ - invreq->fields = tlv_make_fields(invreq, tlv_invoice_request); + tlv_update_fields(invreq, tlv_invoice_request, &invreq->fields); merkle_tlv(invreq->fields, &test_m); /* BOLT-offers #12: diff --git a/lightningd/invoice.c b/lightningd/invoice.c index f43e967522a8..5f756941089c 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -1684,8 +1684,7 @@ static void add_stub_blindedpath(const tal_t *ctx, inv->invoice_blindedpay[0]->features = NULL; /* Recalc ->fields */ - tal_free(inv->fields); - inv->fields = tlv_make_fields(inv, tlv_invoice); + tlv_update_fields(inv, tlv_invoice, &inv->fields); } static struct command_result *json_createinvoice(struct command *cmd, diff --git a/lightningd/offer.c b/lightningd/offer.c index 0156fc808320..17a417c50ac1 100644 --- a/lightningd/offer.c +++ b/lightningd/offer.c @@ -467,7 +467,7 @@ static struct command_result *json_createinvoicerequest(struct command *cmd, * [Signature Calculation](#signature-calculation) using the `invreq_payer_id`. */ /* This populates the ->fields from our entries */ - invreq->fields = tlv_make_fields(invreq, tlv_invoice_request); + tlv_update_fields(invreq, tlv_invoice_request, &invreq->fields); merkle_tlv(invreq->fields, &merkle); invreq->signature = tal(invreq, struct bip340sig); hsm_sign_b12(cmd->ld, "invoice_request", "signature", diff --git a/wire/tlvstream.c b/wire/tlvstream.c index 4813b3514947..9e1c774261bb 100644 --- a/wire/tlvstream.c +++ b/wire/tlvstream.c @@ -365,17 +365,30 @@ void towire_tlv(u8 **pptr, } -struct tlv_field *tlv_make_fields_(const struct tlv_record_type *types, - size_t num_types, - const void *record) +void tlv_update_fields_(const struct tlv_record_type *types, + size_t num_types, + const void *record, + struct tlv_field **tlv_fields) { + /* We merge unknown fields from record */ + const struct tlv_field *field, *end; struct tlv_field *fields = tal_arr(record, struct tlv_field, 0); + field = first_unknown_field(*tlv_fields, &end); + for (size_t i = 0; i < num_types; i++) { struct tlv_field f; u8 *val; if (i != 0) assert(types[i].type > types[i-1].type); + + /* Add any unknowns which precede this. */ + while (field && field->numtype < types[i].type) { + tal_steal(fields, field->value); + tal_arr_expand(&fields, *field); + field = next_unknown_field(field, end); + } + val = types[i].towire(NULL, record); if (!val) continue; @@ -386,5 +399,14 @@ struct tlv_field *tlv_make_fields_(const struct tlv_record_type *types, f.value = tal_steal(fields, val); tal_arr_expand(&fields, f); } - return fields; + + /* Add any unknowns at the end. */ + while (field) { + tal_steal(fields, field->value); + tal_arr_expand(&fields, *field); + field = next_unknown_field(field, end); + } + + tal_free(*tlv_fields); + *tlv_fields = fields; } diff --git a/wire/tlvstream.h b/wire/tlvstream.h index 0b3f71735dba..090ba4e21433 100644 --- a/wire/tlvstream.h +++ b/wire/tlvstream.h @@ -30,13 +30,14 @@ struct tlv_field { /* Given any tlvstream serialize the raw fields (untyped ones). */ void towire_tlvstream_raw(u8 **pptr, struct tlv_field *fields); -/* Given a tlv record with manually-set fields, populate ->fields */ -#define tlv_make_fields(tlv, type) \ - tlv_make_fields_(tlvs_##type, TLVS_ARRAY_SIZE_##type, (tlv)) +/* Given a tlv record with manually-set fields, repopulate ->fields (maintaining any unknowns)*/ +#define tlv_update_fields(tlv, type, tlv_fields) \ + tlv_update_fields_(tlvs_##type, TLVS_ARRAY_SIZE_##type, (tlv), (tlv_fields)) -struct tlv_field *tlv_make_fields_(const struct tlv_record_type *types, - size_t num_types, - const void *record); +void tlv_update_fields_(const struct tlv_record_type *types, + size_t num_types, + const void *record, + struct tlv_field **tlv_fields); /** * fromwire_tlv: generic TLV decode engine