Browse Source

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
bump-pyln-proto
niftynei 4 years ago
committed by Rusty Russell
parent
commit
c50f377a85
  1. 3
      cli/test/run-human-mode.c
  2. 141
      common/psbt_open.c
  3. 44
      common/psbt_open.h
  4. 33
      common/test/exp-run-psbt_diff.c
  5. 3
      common/test/run-gossmap-fp16.c
  6. 20
      lightningd/dual_open_control.c
  7. 7
      lightningd/test/run-invoice-select-inchan.c
  8. 123
      openingd/dualopend.c
  9. 2
      wallet/db_postgres_sqlgen.c
  10. 2
      wallet/db_sqlite3_sqlgen.c
  11. 4
      wallet/statements_gettextgen.po
  12. 4
      wallet/test/run-wallet.c

3
cli/test/run-human-mode.c

@ -33,9 +33,6 @@ int test_chdir(const char *path);
#undef main
/* 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(); }

141
common/psbt_open.c

@ -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 psbt_changeset *psbt_get_changeset(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 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,

44
common/psbt_open.h

@ -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 psbt_changeset *psbt_get_changeset(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 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
*

33
common/test/exp-run-psbt_diff.c

@ -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;
has_diff = psbt_has_diff(tmpctx, a, b,
&added_in, &rm_in,
&added_out, &rm_out);
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);
struct psbt_changeset *set;
set = psbt_get_changeset(tmpctx, a, b);
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,

3
common/test/run-gossmap-fp16.c

@ -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(); }

20
lightningd/dual_open_control.c

@ -389,14 +389,16 @@ static bool psbt_side_contribs_changed(struct wally_psbt *orig,
struct wally_psbt *new,
enum side opener_side)
{
struct input_set *added_in, *rm_in;
struct output_set *added_out, *rm_out;
struct psbt_changeset *cs;
u16 serial_id;
bool ok;
if (!psbt_has_diff(tmpctx, orig, new,
&added_in, &rm_in,
&added_out, &rm_out))
cs = psbt_get_changeset(tmpctx, orig, new);
if (tal_count(cs->added_ins) == 0 &&
tal_count(cs->rm_ins) == 0 &&
tal_count(cs->added_outs) == 0 &&
tal_count(cs->rm_outs) == 0)
return false;
/* If there were *any* changes, then the answer to the 'both sides'
@ -406,10 +408,10 @@ static bool psbt_side_contribs_changed(struct wally_psbt *orig,
/* Check that none of the included updates have a serial
* id that's the peer's parity */
CHECK_CHANGES(added_in, input);
CHECK_CHANGES(rm_in, input);
CHECK_CHANGES(added_out, output);
CHECK_CHANGES(rm_out, output);
CHECK_CHANGES(cs->added_ins, input);
CHECK_CHANGES(cs->rm_ins, input);
CHECK_CHANGES(cs->added_outs, output);
CHECK_CHANGES(cs->rm_outs, output);
return false;
}

7
lightningd/test/run-invoice-select-inchan.c

@ -117,10 +117,6 @@ void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UN
/* Generated stub for delete_channel */
void delete_channel(struct channel *channel STEALS UNNEEDED)
{ fprintf(stderr, "delete_channel called!\n"); abort(); }
/* Generated stub for derive_channel_id */
void derive_channel_id(struct channel_id *channel_id UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED, u16 txout UNNEEDED)
{ fprintf(stderr, "derive_channel_id called!\n"); abort(); }
/* Generated stub for encode_scriptpubkey_to_addr */
char *encode_scriptpubkey_to_addr(const tal_t *ctx UNNEEDED,
const struct chainparams *chainparams UNNEEDED,
@ -545,9 +541,6 @@ void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED)
/* Generated stub for towire_onchaind_dev_memleak */
u8 *towire_onchaind_dev_memleak(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "towire_onchaind_dev_memleak called!\n"); abort(); }
/* Generated stub for txfilter_add_scriptpubkey */
void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES UNNEEDED)
{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); }
/* Generated stub for version */
const char *version(void)
{ fprintf(stderr, "version called!\n"); abort(); }

123
openingd/dualopend.c

@ -61,13 +61,6 @@
#define REQ_FD STDIN_FILENO
#define HSM_FD 6
struct psbt_changeset {
struct input_set *added_ins;
struct input_set *rm_ins;
struct output_set *added_outs;
struct output_set *rm_outs;
};
/* Global state structure. This is only for the one specific peer and channel */
struct state {
struct per_peer_state *pps;
@ -131,100 +124,7 @@ struct state {
struct psbt_changeset *changeset;
};
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;
}
#if EXPERIMENTAL_FEATURES
static u8 *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;
}
/*~ If we can't agree on parameters, we fail to open the channel. If we're
* the opener, we need to tell lightningd, otherwise it never really notices. */
@ -521,7 +421,7 @@ static bool send_next(struct state *state, struct wally_psbt **psbt)
struct psbt_changeset *cs = state->changeset;
/* First we check our cached changes */
msg = changeset_get_next(tmpctx, &state->channel_id, cs);
msg = psbt_changeset_get_next(tmpctx, &state->channel_id, cs);
if (msg)
goto sendmsg;
@ -534,22 +434,21 @@ static bool send_next(struct state *state, struct wally_psbt **psbt)
peer_failed(state->pps, &state->channel_id,
"Unable to determine next tx update");
if (psbt_has_diff(cs, *psbt, updated_psbt,
&cs->added_ins, &cs->rm_ins,
&cs->added_outs, &cs->rm_outs)) {
state->changeset = tal_free(state->changeset);
state->changeset = psbt_get_changeset(state, *psbt, updated_psbt);
/* We want this old psbt to be cleaned up when the changeset is freed */
tal_steal(state->changeset, *psbt);
*psbt = tal_steal(state, updated_psbt);
msg = changeset_get_next(tmpctx, &state->channel_id,
msg = psbt_changeset_get_next(tmpctx, &state->channel_id,
state->changeset);
assert(msg);
goto sendmsg;
}
/*
* If there's no more moves, we send tx_complete
* and reply that we're finished */
if (!msg) {
msg = towire_tx_complete(tmpctx, &state->channel_id);
finished = true;
}
sendmsg:
sync_crypto_write(state->pps, msg);
@ -559,13 +458,10 @@ sendmsg:
static void init_changeset(struct state *state, struct wally_psbt *psbt)
{
struct psbt_changeset *cs = state->changeset;
/* We need an empty to compare to */
struct wally_psbt *empty_psbt = create_psbt(tmpctx, 0, 0, 0);
psbt_has_diff(cs, empty_psbt, psbt,
&cs->added_ins, &cs->rm_ins,
&cs->added_outs, &cs->rm_outs);
state->changeset = psbt_get_changeset(state, empty_psbt, psbt);
}
/*~ Handle random messages we might get during opening negotiation, (eg. gossip)
@ -1531,7 +1427,6 @@ int main(int argc, char *argv[])
* handle_peer_gossip_or_error compares this. */
memset(&state->channel_id, 0, sizeof(state->channel_id));
state->channel = NULL;
state->changeset = new_changeset(state);
/*~ We set these to NULL, meaning no requirements on shutdown */
state->upfront_shutdown_script[LOCAL]

2
wallet/db_postgres_sqlgen.c

@ -1648,4 +1648,4 @@ struct db_query db_postgres_queries[] = {
#endif /* LIGHTNINGD_WALLET_GEN_DB_POSTGRES */
// SHA256STAMP:4b62394a2377b4aada8173bf750c6f293c84e4f0c9097c8774e625f76e17faa6
// SHA256STAMP:e55a8febb74330a9167e8498b26e556609d95b7ca6ef984da1fa200e53e36a7e

2
wallet/db_sqlite3_sqlgen.c

@ -1648,4 +1648,4 @@ struct db_query db_sqlite3_queries[] = {
#endif /* LIGHTNINGD_WALLET_GEN_DB_SQLITE3 */
// SHA256STAMP:4b62394a2377b4aada8173bf750c6f293c84e4f0c9097c8774e625f76e17faa6
// SHA256STAMP:e55a8febb74330a9167e8498b26e556609d95b7ca6ef984da1fa200e53e36a7e

4
wallet/statements_gettextgen.po

@ -1082,7 +1082,7 @@ msgstr ""
msgid "not a valid SQL statement"
msgstr ""
#: wallet/test/run-wallet.c:1355
#: wallet/test/run-wallet.c:1351
msgid "INSERT INTO channels (id) VALUES (1);"
msgstr ""
# SHA256STAMP:c0605983e2071b5f504b2bcbfd747ca305658f7a8b4f9df4176ffd0815bf7bff
# SHA256STAMP:de15ae770286fe050f7b2d712bcc2a3311a8737e920353bb8c7d8dbf0188db69

4
wallet/test/run-wallet.c

@ -474,10 +474,6 @@ bool outpointfilter_matches(struct outpointfilter *of UNNEEDED,
/* Generated stub for outpointfilter_new */
struct outpointfilter *outpointfilter_new(tal_t *ctx UNNEEDED)
{ fprintf(stderr, "outpointfilter_new called!\n"); abort(); }
/* Generated stub for outpointfilter_remove */
void outpointfilter_remove(struct outpointfilter *of UNNEEDED,
const struct bitcoin_txid *txid UNNEEDED, const u32 outnum UNNEEDED)
{ fprintf(stderr, "outpointfilter_remove called!\n"); abort(); }
/* Generated stub for param */
bool param(struct command *cmd UNNEEDED, const char *buffer UNNEEDED,
const jsmntok_t params[] UNNEEDED, ...)

Loading…
Cancel
Save