mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-06 15:44:21 +01:00
psbt: pull out changeset logic into common, update API
Greatly simplify the changeset API. Instead of 'diff' we simply generate the changes. Also pulls up the 'next message' method, as at some point the interactive tx protocol will be used for other things as well (splices/closes etc) Suggested-By: @rustyrussell
This commit is contained in:
@@ -6,7 +6,9 @@
|
||||
#include <ccan/asort/asort.h>
|
||||
#include <ccan/ccan/endian/endian.h>
|
||||
#include <ccan/ccan/mem/mem.h>
|
||||
#include <common/channel_id.h>
|
||||
#include <common/utils.h>
|
||||
#include <wire/peer_wire.h>
|
||||
|
||||
bool psbt_get_serial_id(const struct wally_map *map, u16 *serial_id)
|
||||
{
|
||||
@@ -213,39 +215,45 @@ void psbt_sort_by_serial_id(struct wally_psbt *psbt)
|
||||
struct type##_set a; \
|
||||
a.type = from->type##s[index]; \
|
||||
a.tx_##type = from->tx->type##s[index]; \
|
||||
tal_arr_expand(add_to, a); \
|
||||
tal_arr_expand(&add_to, a); \
|
||||
} while (0)
|
||||
|
||||
static struct psbt_changeset *new_changeset(const tal_t *ctx)
|
||||
{
|
||||
struct psbt_changeset *set = tal(ctx, struct psbt_changeset);
|
||||
|
||||
set->added_ins = tal_arr(set, struct input_set, 0);
|
||||
set->rm_ins = tal_arr(set, struct input_set, 0);
|
||||
set->added_outs = tal_arr(set, struct output_set, 0);
|
||||
set->rm_outs = tal_arr(set, struct output_set, 0);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/* this requires having a serial_id entry on everything */
|
||||
/* YOU MUST KEEP orig + new AROUND TO USE THE RESULTING SETS */
|
||||
bool psbt_has_diff(const tal_t *ctx,
|
||||
struct wally_psbt *orig,
|
||||
struct wally_psbt *new,
|
||||
struct input_set **added_ins,
|
||||
struct input_set **rm_ins,
|
||||
struct output_set **added_outs,
|
||||
struct output_set **rm_outs)
|
||||
struct psbt_changeset *psbt_get_changeset(const tal_t *ctx,
|
||||
struct wally_psbt *orig,
|
||||
struct wally_psbt *new)
|
||||
{
|
||||
int result;
|
||||
size_t i = 0, j = 0;
|
||||
struct psbt_changeset *set;
|
||||
|
||||
psbt_sort_by_serial_id(orig);
|
||||
psbt_sort_by_serial_id(new);
|
||||
|
||||
*added_ins = tal_arr(ctx, struct input_set, 0);
|
||||
*rm_ins = tal_arr(ctx, struct input_set, 0);
|
||||
*added_outs = tal_arr(ctx, struct output_set, 0);
|
||||
*rm_outs = tal_arr(ctx, struct output_set, 0);
|
||||
set = new_changeset(ctx);
|
||||
|
||||
/* Find the input diff */
|
||||
while (i < orig->num_inputs || j < new->num_inputs) {
|
||||
if (i >= orig->num_inputs) {
|
||||
ADD(input, added_ins, new, j);
|
||||
ADD(input, set->added_ins, new, j);
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
if (j >= new->num_inputs) {
|
||||
ADD(input, rm_ins, orig, i);
|
||||
ADD(input, set->rm_ins, orig, i);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
@@ -253,19 +261,19 @@ bool psbt_has_diff(const tal_t *ctx,
|
||||
result = compare_serials(&orig->inputs[i].unknowns,
|
||||
&new->inputs[j].unknowns);
|
||||
if (result == -1) {
|
||||
ADD(input, rm_ins, orig, i);
|
||||
ADD(input, set->rm_ins, orig, i);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (result == 1) {
|
||||
ADD(input, added_ins, new, j);
|
||||
ADD(input, set->added_ins, new, j);
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!input_identical(orig, i, new, j)) {
|
||||
ADD(input, rm_ins, orig, i);
|
||||
ADD(input, added_ins, new, j);
|
||||
ADD(input, set->rm_ins, orig, i);
|
||||
ADD(input, set->added_ins, new, j);
|
||||
}
|
||||
i++;
|
||||
j++;
|
||||
@@ -275,12 +283,12 @@ bool psbt_has_diff(const tal_t *ctx,
|
||||
j = 0;
|
||||
while (i < orig->num_outputs || j < new->num_outputs) {
|
||||
if (i >= orig->num_outputs) {
|
||||
ADD(output, added_outs, new, j);
|
||||
ADD(output, set->added_outs, new, j);
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
if (j >= new->num_outputs) {
|
||||
ADD(output, rm_outs, orig, i);
|
||||
ADD(output, set->rm_outs, orig, i);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
@@ -288,27 +296,106 @@ bool psbt_has_diff(const tal_t *ctx,
|
||||
result = compare_serials(&orig->outputs[i].unknowns,
|
||||
&new->outputs[j].unknowns);
|
||||
if (result == -1) {
|
||||
ADD(output, rm_outs, orig, i);
|
||||
ADD(output, set->rm_outs, orig, i);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (result == 1) {
|
||||
ADD(output, added_outs, new, j);
|
||||
ADD(output, set->added_outs, new, j);
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
if (!output_identical(orig, i, new, j)) {
|
||||
ADD(output, rm_outs, orig, i);
|
||||
ADD(output, added_outs, new, j);
|
||||
ADD(output, set->rm_outs, orig, i);
|
||||
ADD(output, set->added_outs, new, j);
|
||||
}
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
return tal_count(*added_ins) != 0 ||
|
||||
tal_count(*rm_ins) != 0 ||
|
||||
tal_count(*added_outs) != 0 ||
|
||||
tal_count(*rm_outs) != 0;
|
||||
return set;
|
||||
}
|
||||
|
||||
u8 *psbt_changeset_get_next(const tal_t *ctx, struct channel_id *cid,
|
||||
struct psbt_changeset *set)
|
||||
{
|
||||
u16 serial_id;
|
||||
u8 *msg;
|
||||
|
||||
if (tal_count(set->added_ins) != 0) {
|
||||
const struct input_set *in = &set->added_ins[0];
|
||||
u16 max_witness_len;
|
||||
u8 *script;
|
||||
|
||||
if (!psbt_get_serial_id(&in->input.unknowns, &serial_id))
|
||||
abort();
|
||||
|
||||
const u8 *prevtx = linearize_wtx(ctx,
|
||||
in->input.utxo);
|
||||
|
||||
if (!psbt_input_get_max_witness_len(&in->input,
|
||||
&max_witness_len))
|
||||
abort();
|
||||
|
||||
if (in->input.redeem_script_len)
|
||||
script = tal_dup_arr(ctx, u8,
|
||||
in->input.redeem_script,
|
||||
in->input.redeem_script_len, 0);
|
||||
else
|
||||
script = NULL;
|
||||
|
||||
msg = towire_tx_add_input(ctx, cid, serial_id,
|
||||
prevtx, in->tx_input.index,
|
||||
in->tx_input.sequence,
|
||||
max_witness_len,
|
||||
script,
|
||||
NULL);
|
||||
|
||||
tal_arr_remove(&set->added_ins, 0);
|
||||
return msg;
|
||||
}
|
||||
if (tal_count(set->rm_ins) != 0) {
|
||||
if (!psbt_get_serial_id(&set->rm_ins[0].input.unknowns,
|
||||
&serial_id))
|
||||
abort();
|
||||
|
||||
msg = towire_tx_remove_input(ctx, cid, serial_id);
|
||||
|
||||
tal_arr_remove(&set->rm_ins, 0);
|
||||
return msg;
|
||||
}
|
||||
if (tal_count(set->added_outs) != 0) {
|
||||
struct amount_sat sats;
|
||||
struct amount_asset asset_amt;
|
||||
|
||||
const struct output_set *out = &set->added_outs[0];
|
||||
if (!psbt_get_serial_id(&out->output.unknowns, &serial_id))
|
||||
abort();
|
||||
|
||||
asset_amt = wally_tx_output_get_amount(&out->tx_output);
|
||||
sats = amount_asset_to_sat(&asset_amt);
|
||||
const u8 *script = wally_tx_output_get_script(ctx,
|
||||
&out->tx_output);
|
||||
|
||||
msg = towire_tx_add_output(ctx, cid, serial_id,
|
||||
sats.satoshis, /* Raw: wire interface */
|
||||
script);
|
||||
|
||||
tal_arr_remove(&set->added_outs, 0);
|
||||
return msg;
|
||||
}
|
||||
if (tal_count(set->rm_outs) != 0) {
|
||||
if (!psbt_get_serial_id(&set->rm_outs[0].output.unknowns,
|
||||
&serial_id))
|
||||
abort();
|
||||
|
||||
msg = towire_tx_remove_output(ctx, cid, serial_id);
|
||||
|
||||
/* Is this a kosher way to move the list forward? */
|
||||
tal_arr_remove(&set->rm_outs, 0);
|
||||
return msg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void psbt_input_add_serial_id(struct wally_psbt_input *input,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <wally_psbt.h>
|
||||
#include <wally_transaction.h>
|
||||
|
||||
struct channel_id;
|
||||
struct wally_tx_input;
|
||||
struct wally_tx_output;
|
||||
struct wally_psbt;
|
||||
@@ -24,6 +25,13 @@ struct output_set {
|
||||
struct wally_psbt_output output;
|
||||
};
|
||||
|
||||
struct psbt_changeset {
|
||||
struct input_set *added_ins;
|
||||
struct input_set *rm_ins;
|
||||
struct output_set *added_outs;
|
||||
struct output_set *rm_outs;
|
||||
};
|
||||
|
||||
#define PSBT_TYPE_SERIAL_ID 0x01
|
||||
#define PSBT_TYPE_MAX_WITNESS_LEN 0x02
|
||||
|
||||
@@ -45,31 +53,35 @@ WARN_UNUSED_RESULT bool psbt_get_serial_id(const struct wally_map *map,
|
||||
*/
|
||||
void psbt_sort_by_serial_id(struct wally_psbt *psbt);
|
||||
|
||||
/* psbt_has_diff - Returns set of diffs btw orig + new psbt
|
||||
/* psbt_get_changeset - Returns set of diffs btw orig + new psbt
|
||||
*
|
||||
* All inputs+outputs MUST have a serial_id field present before
|
||||
* calling this.
|
||||
*
|
||||
* @ctx - allocation context for returned diffsets
|
||||
* @ctx - allocation context for returned changeset
|
||||
* @orig - original psbt
|
||||
* @new - updated psbt
|
||||
* @added_ins - inputs added {new}
|
||||
* @rm_ins - inputs removed {orig}
|
||||
* @added_outs - outputs added {new}
|
||||
* @rm_outs - outputs removed {orig}
|
||||
*
|
||||
* Note that the input + output data returned in the diff sets
|
||||
* contain references to the originating PSBT; they are not copies.
|
||||
*
|
||||
* Returns true if changes are found.
|
||||
* Note that the input + output data returned in the changeset
|
||||
* contains references to the originating PSBT; they are not copies.
|
||||
*/
|
||||
bool psbt_has_diff(const tal_t *ctx,
|
||||
struct wally_psbt *orig,
|
||||
struct wally_psbt *new,
|
||||
struct input_set **added_ins,
|
||||
struct input_set **rm_ins,
|
||||
struct output_set **added_outs,
|
||||
struct output_set **rm_outs);
|
||||
struct psbt_changeset *psbt_get_changeset(const tal_t *ctx,
|
||||
struct wally_psbt *orig,
|
||||
struct wally_psbt *new);
|
||||
|
||||
/* psbt_changeset_get_next - Get next message to send
|
||||
*
|
||||
* This generates the next message to send from a changeset for the
|
||||
* interactive transaction protocol.
|
||||
*
|
||||
* @ctx - allocation context of returned msg
|
||||
* @cid - channel_id for the message
|
||||
* @set - changeset to get next update from
|
||||
*
|
||||
* Returns a wire message or NULL if no changes.
|
||||
*/
|
||||
u8 *psbt_changeset_get_next(const tal_t *ctx, struct channel_id *cid,
|
||||
struct psbt_changeset *set);
|
||||
|
||||
/* psbt_input_add_serial_id - Adds a serial id to given input
|
||||
*
|
||||
|
||||
@@ -55,6 +55,18 @@ void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED,
|
||||
/* Generated stub for towire_sha256 */
|
||||
void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED)
|
||||
{ fprintf(stderr, "towire_sha256 called!\n"); abort(); }
|
||||
/* Generated stub for towire_tx_add_input */
|
||||
u8 *towire_tx_add_input(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED, const u8 *prevtx UNNEEDED, u32 prevtx_vout UNNEEDED, u32 sequence UNNEEDED, u16 max_witness_len UNNEEDED, const u8 *script UNNEEDED, const struct tlv_tx_add_input_tlvs *tlvs UNNEEDED)
|
||||
{ fprintf(stderr, "towire_tx_add_input called!\n"); abort(); }
|
||||
/* Generated stub for towire_tx_add_output */
|
||||
u8 *towire_tx_add_output(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED, u64 sats UNNEEDED, const u8 *script UNNEEDED)
|
||||
{ fprintf(stderr, "towire_tx_add_output called!\n"); abort(); }
|
||||
/* Generated stub for towire_tx_remove_input */
|
||||
u8 *towire_tx_remove_input(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED)
|
||||
{ fprintf(stderr, "towire_tx_remove_input called!\n"); abort(); }
|
||||
/* Generated stub for towire_tx_remove_output */
|
||||
u8 *towire_tx_remove_output(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED)
|
||||
{ fprintf(stderr, "towire_tx_remove_output called!\n"); abort(); }
|
||||
/* Generated stub for towire_u16 */
|
||||
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
|
||||
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }
|
||||
@@ -77,19 +89,14 @@ static void diff_count(struct wally_psbt *a,
|
||||
size_t diff_added,
|
||||
size_t diff_rm)
|
||||
{
|
||||
bool has_diff;
|
||||
struct input_set *added_in, *rm_in;
|
||||
struct output_set *added_out, *rm_out;
|
||||
struct psbt_changeset *set;
|
||||
|
||||
has_diff = psbt_has_diff(tmpctx, a, b,
|
||||
&added_in, &rm_in,
|
||||
&added_out, &rm_out);
|
||||
set = psbt_get_changeset(tmpctx, a, b);
|
||||
|
||||
assert(has_diff == (diff_added + diff_rm != 0));
|
||||
assert(tal_count(added_in) == diff_added);
|
||||
assert(tal_count(added_out) == diff_added);
|
||||
assert(tal_count(rm_in) == diff_rm);
|
||||
assert(tal_count(rm_out) == diff_rm);
|
||||
assert(tal_count(set->added_ins) == diff_added);
|
||||
assert(tal_count(set->added_outs) == diff_added);
|
||||
assert(tal_count(set->rm_ins) == diff_rm);
|
||||
assert(tal_count(set->rm_outs) == diff_rm);
|
||||
}
|
||||
|
||||
static void add_in_out_with_serial(struct wally_psbt *psbt,
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
#include "../gossmap.c"
|
||||
|
||||
/* AUTOGENERATED MOCKS START */
|
||||
/* Generated stub for amount_asset_extract_value */
|
||||
u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED)
|
||||
{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); }
|
||||
/* Generated stub for amount_asset_is_main */
|
||||
bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
|
||||
{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); }
|
||||
|
||||
Reference in New Issue
Block a user