common/wire: update, don't replace fields array in TLV structures.

Regnerating them entirely loses unknown fields.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-07-18 11:02:55 +09:30
parent ea4025b1ed
commit c342f204b2
5 changed files with 36 additions and 14 deletions

View File

@ -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:

View File

@ -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,

View File

@ -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",

View File

@ -365,17 +365,30 @@ void towire_tlv(u8 **pptr,
}
struct tlv_field *tlv_make_fields_(const struct tlv_record_type *types,
void tlv_update_fields_(const struct tlv_record_type *types,
size_t num_types,
const void *record)
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;
}

View File

@ -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,
void tlv_update_fields_(const struct tlv_record_type *types,
size_t num_types,
const void *record);
const void *record,
struct tlv_field **tlv_fields);
/**
* fromwire_tlv: generic TLV decode engine