diff --git a/channeld/channeld.c b/channeld/channeld.c index a2ee13dec561..1bf7c83d865c 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -681,6 +681,44 @@ static bool channel_announcement_negotiate(struct peer *peer) return sent_announcement; } +static void lock_signer_outpoint(const struct bitcoin_outpoint *outpoint) { + const u8 *msg; + bool is_buried = false; + + do { + /* Make sure the hsmd agrees that this outpoint is + * sufficiently buried. */ + msg = towire_hsmd_check_outpoint(NULL, &outpoint->txid, outpoint->n); + msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_check_outpoint_reply(msg, &is_buried)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad hsmd_check_outpoint_reply: %s", + tal_hex(tmpctx, msg)); + + /* the signer should have a shorter buried height requirement so + * it almost always will be ready ahead of us.*/ + if (!is_buried) { + sleep(10); + } + } while (!is_buried); + + /* tell the signer that we are now locked */ + msg = towire_hsmd_lock_outpoint(NULL, &outpoint->txid, outpoint->n); + msg = hsm_req(tmpctx, take(msg)); + if (!fromwire_hsmd_lock_outpoint_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad hsmd_lock_outpoint_reply: %s", + tal_hex(tmpctx, msg)); +} + +/* Call this method when channel_ready status are changed. */ +static void check_mutual_channel_ready(const struct peer *peer) +{ + if (peer->channel_ready[LOCAL] && peer->channel_ready[REMOTE]) { + lock_signer_outpoint(&peer->channel->funding); + } +} + /* Call this method when splice_locked status are changed. If both sides have * splice_locked'ed than this function consumes the `splice_locked_ready` values * and considers the channel funding to be switched to the splice tx. */ @@ -751,6 +789,9 @@ static void check_mutual_splice_locked(struct peer *peer) status_debug("mutual splice_locked, channel updated to: %s", type_to_string(tmpctx, struct channel, peer->channel)); + /* ensure the signer is locking at the same time */ + lock_signer_outpoint(&inflight->outpoint); + msg = towire_channeld_got_splice_locked(NULL, inflight->amnt, inflight->splice_amnt, &inflight->outpoint.txid); @@ -831,6 +872,7 @@ static void handle_peer_channel_ready(struct peer *peer, const u8 *msg) peer->tx_sigs_allowed = false; peer->channel_ready[REMOTE] = true; + check_mutual_channel_ready(peer); if (tlvs->short_channel_id != NULL) { status_debug( "Peer told us that they'll use alias=%s for this channel", @@ -2918,6 +2960,26 @@ static size_t calc_weight(enum tx_role role, const struct wally_psbt *psbt) return weight; } +/* Get the non-initiator (acceptor) amount after the splice */ +static struct amount_msat splice_acceptor_balance(struct peer *peer, + enum tx_role our_role) +{ + struct amount_msat acceptor_value; + + /* Start with the acceptor's balance before the splice */ + acceptor_value = + peer->channel->view->owed[our_role == TX_INITIATOR ? REMOTE : LOCAL]; + + /* Adjust by the acceptor's relative splice amount (signed) */ + if (!amount_msat_add_sat_s64(&acceptor_value, acceptor_value, + peer->splicing->accepter_relative)) + peer_failed_warn( + peer->pps, &peer->channel_id, + "Unable to add accepter's relative splice to prior balance."); + + return acceptor_value; +} + /* Returns the total channel funding output amount if all checks pass. * Otherwise, exits via peer_failed_warn. DTODO: Change to `tx_abort`. */ static struct amount_sat check_balances(struct peer *peer, @@ -3450,6 +3512,39 @@ static struct inflight *inflights_new(struct peer *peer) return inf; } +static void update_hsmd_with_splice(struct peer *peer, + struct inflight *inflight, + const struct amount_msat push_val) +{ + u8 *msg; + + /* local_upfront_shutdown_script, local_upfront_shutdown_wallet_index, + * remote_upfront_shutdown_script aren't allowed to change, so we + * don't need to gather them */ + msg = towire_hsmd_setup_channel( + NULL, + peer->channel->opener == LOCAL, + inflight->amnt, + push_val, + &inflight->outpoint.txid, + inflight->outpoint.n, + peer->channel->config[LOCAL].to_self_delay, + /*local_upfront_shutdown_script*/ NULL, + /*local_upfront_shutdown_wallet_index*/ NULL, + &peer->channel->basepoints[REMOTE], + &peer->channel->funding_pubkey[REMOTE], + peer->channel->config[REMOTE].to_self_delay, + /*remote_upfront_shutdown_script*/ NULL, + peer->channel->type); + + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_setup_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + tal_hex(tmpctx, msg)); +} + + /* ACCEPTER side of the splice. Here we handle all the accepter's steps for the * splice. Since the channel must be in STFU mode we block the daemon here until * the splice is finished or aborted. */ @@ -3586,6 +3681,10 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) new_inflight->last_tx = NULL; new_inflight->i_am_initiator = false; + update_hsmd_with_splice(peer, + new_inflight, + splice_acceptor_balance(peer, TX_ACCEPTER)); + update_view_from_inflights(peer); peer->splice_state->count++; @@ -3820,6 +3919,10 @@ static void splice_initiator_user_finalized(struct peer *peer) new_inflight->last_tx = NULL; new_inflight->i_am_initiator = true; + update_hsmd_with_splice(peer, + new_inflight, + splice_acceptor_balance(peer, TX_INITIATOR)); + update_view_from_inflights(peer); peer->splice_state->count++; @@ -5191,6 +5294,7 @@ static void handle_funding_depth(struct peer *peer, const u8 *msg) peer_write(peer->pps, take(msg)); peer->channel_ready[LOCAL] = true; + check_mutual_channel_ready(peer); } else if(splicing && !peer->splice_state->locked_ready[LOCAL]) { assert(scid); diff --git a/common/psbt_open.c b/common/psbt_open.c index fbd2e9c40578..cdf8516e8330 100644 --- a/common/psbt_open.c +++ b/common/psbt_open.c @@ -379,33 +379,54 @@ u64 psbt_new_output_serial(struct wally_psbt *psbt, enum tx_role role) return serial_id; } +#include +#include + bool psbt_has_required_fields(struct wally_psbt *psbt) { + psbt_set_version(psbt, 0); + fprintf(stderr, "wally_psbt: %s\n", type_to_string(tmpctx, struct wally_psbt, psbt)); + psbt_set_version(psbt, 2); + u64 serial_id; for (size_t i = 0; i < psbt->num_inputs; i++) { const struct wally_map_item *redeem_script; struct wally_psbt_input *input = &psbt->inputs[i]; - if (!psbt_get_serial_id(&input->unknowns, &serial_id)) + if (!psbt_get_serial_id(&input->unknowns, &serial_id)) { + fprintf(stderr, "in[%ld]: missing serial id\n", i); return false; + } /* Required because we send the full tx over the wire now */ - if (!input->utxo) + /* Only insist on PSBT_IN_NON_WITNESS_UTXO (.utxo) if + * PSBT_IN_WITNESS_UTXO (.witness_utxo) is not present + * because PSBT_IN_NON_WITNESS_UTXO uses a lot of + * memory */ + if (!input->witness_utxo && !input->utxo) { + fprintf(stderr, "in[%ld]: missing both utxo\n", i); return false; + } - /* If is P2SH, redeemscript must be present */ - assert(psbt->inputs[i].index < input->utxo->num_outputs); - const u8 *outscript = - wally_tx_output_get_script(tmpctx, - &input->utxo->outputs[psbt->inputs[i].index]); - redeem_script = wally_map_get_integer(&psbt->inputs[i].psbt_fields, /* PSBT_IN_REDEEM_SCRIPT */ 0x04); - if (is_p2sh(outscript, NULL) && (!redeem_script || redeem_script->value_len == 0)) - return false; + if (input->utxo) { + /* If is P2SH, redeemscript must be present */ + assert(psbt->inputs[i].index < input->utxo->num_outputs); + const u8 *outscript = + wally_tx_output_get_script(tmpctx, + &input->utxo->outputs[psbt->inputs[i].index]); + redeem_script = wally_map_get_integer(&psbt->inputs[i].psbt_fields, /* PSBT_IN_REDEEM_SCRIPT */ 0x04); + if (is_p2sh(outscript, NULL) && (!redeem_script || redeem_script->value_len == 0)) { + fprintf(stderr, "in[%ld]: missing redeemscript\n", i); + return false; + } + } } for (size_t i = 0; i < psbt->num_outputs; i++) { - if (!psbt_get_serial_id(&psbt->outputs[i].unknowns, &serial_id)) + if (!psbt_get_serial_id(&psbt->outputs[i].unknowns, &serial_id)) { + fprintf(stderr, "out[%ld]: missing serial id\n", i); return false; + } } return true; diff --git a/common/test/run-psbt_diff.c b/common/test/run-psbt_diff.c deleted file mode 100644 index 37f4fdf495dc..000000000000 --- a/common/test/run-psbt_diff.c +++ /dev/null @@ -1,238 +0,0 @@ -#include "config.h" -#include -#include -#include "../amount.c" -#include "../psbt_open.c" - -/* AUTOGENERATED MOCKS START */ -/* Generated stub for fromwire */ -const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) -{ fprintf(stderr, "fromwire called!\n"); abort(); } -/* Generated stub for fromwire_bool */ -bool fromwire_bool(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) -{ fprintf(stderr, "fromwire_bool called!\n"); abort(); } -/* Generated stub for fromwire_fail */ -void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) -{ fprintf(stderr, "fromwire_fail called!\n"); abort(); } -/* Generated stub for fromwire_secp256k1_ecdsa_signature */ -void fromwire_secp256k1_ecdsa_signature(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, - secp256k1_ecdsa_signature *signature UNNEEDED) -{ fprintf(stderr, "fromwire_secp256k1_ecdsa_signature called!\n"); abort(); } -/* Generated stub for fromwire_sha256 */ -void fromwire_sha256(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sha256 *sha256 UNNEEDED) -{ fprintf(stderr, "fromwire_sha256 called!\n"); abort(); } -/* Generated stub for fromwire_tal_arrn */ -u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED, - const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED) -{ fprintf(stderr, "fromwire_tal_arrn called!\n"); abort(); } -/* Generated stub for fromwire_u32 */ -u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) -{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); } -/* Generated stub for fromwire_u64 */ -u64 fromwire_u64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) -{ fprintf(stderr, "fromwire_u64 called!\n"); abort(); } -/* Generated stub for fromwire_u8 */ -u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) -{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); } -/* Generated stub for fromwire_u8_array */ -void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED) -{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); } -/* Generated stub for pseudorand_u64 */ -uint64_t pseudorand_u64(void) -{ fprintf(stderr, "pseudorand_u64 called!\n"); abort(); } -/* Generated stub for towire */ -void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) -{ fprintf(stderr, "towire called!\n"); abort(); } -/* Generated stub for towire_bool */ -void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED) -{ fprintf(stderr, "towire_bool called!\n"); abort(); } -/* Generated stub for towire_secp256k1_ecdsa_signature */ -void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED, - const secp256k1_ecdsa_signature *signature UNNEEDED) -{ fprintf(stderr, "towire_secp256k1_ecdsa_signature called!\n"); abort(); } -/* 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_u32 */ -void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED) -{ fprintf(stderr, "towire_u32 called!\n"); abort(); } -/* Generated stub for towire_u64 */ -void towire_u64(u8 **pptr UNNEEDED, u64 v UNNEEDED) -{ fprintf(stderr, "towire_u64 called!\n"); abort(); } -/* Generated stub for towire_u8 */ -void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED) -{ fprintf(stderr, "towire_u8 called!\n"); abort(); } -/* Generated stub for towire_u8_array */ -void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED) -{ fprintf(stderr, "towire_u8_array called!\n"); abort(); } -/* AUTOGENERATED MOCKS END */ - -static void diff_count(struct wally_psbt *a, - struct wally_psbt *b, - size_t diff_added, - size_t 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, - size_t serial_id, - size_t default_value) -{ - struct bitcoin_outpoint outpoint; - u8 *script; - struct amount_sat sat; - struct wally_psbt_input *in; - struct wally_psbt_output *out; - - memset(&outpoint, default_value, sizeof(outpoint)); - in = psbt_append_input(psbt, &outpoint, default_value, - NULL, NULL, NULL); - if (!in) - abort(); - psbt_input_set_serial_id(psbt, in, serial_id); - - script = tal_arr(tmpctx, u8, 20); - memset(script, default_value, 20); - sat = amount_sat(default_value); - out = psbt_append_output(psbt, script, sat); - if (!out) - abort(); - psbt_output_set_serial_id(psbt, out, serial_id); -} - -/* Try changing up the serial ids */ -static void change_serials(void) -{ - struct wally_psbt *psbt; - - psbt = create_psbt(tmpctx, 1, 1, 0); - add_in_out_with_serial(psbt, 10, 1); - - psbt_output_set_serial_id(psbt, &psbt->outputs[0], 2); - assert(psbt_find_serial_output(psbt, 2) == 0); - assert(psbt_find_serial_output(psbt, 10) == -1); - - psbt_input_set_serial_id(psbt, &psbt->inputs[0], 4); - assert(psbt_find_serial_input(psbt, 4) == 0); - assert(psbt_find_serial_input(psbt, 10) == -1); - -} - -static void check_psbt_comparison(void) -{ - struct wally_psbt *oldpsbt = psbt_from_b64(tmpctx, "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", strlen("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")); - - struct wally_psbt *newpsbt = psbt_from_b64(tmpctx, "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", strlen("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")); - - /* Round-trip versioning of both PSBTs as belt and suspender check */ - tal_wally_start(); - wally_psbt_set_version(oldpsbt, 0 /* flags */, 2); - wally_psbt_set_version(oldpsbt, 0 /* flags */, 0); - wally_psbt_set_version(oldpsbt, 0 /* flags */, 2); - tal_wally_end(oldpsbt); - - tal_wally_start(); - wally_psbt_set_version(newpsbt, 0 /* flags */, 2); - wally_psbt_set_version(newpsbt, 0 /* flags */, 0); - wally_psbt_set_version(newpsbt, 0 /* flags */, 2); - tal_wally_end(newpsbt); - - assert(!psbt_contribs_changed(oldpsbt, newpsbt)); -} - -int main(int argc, const char *argv[]) -{ - common_setup(argv[0]); - - struct wally_psbt *start, *end; - u32 flags = 0; - - chainparams = chainparams_for_network("bitcoin"); - - /* Create two psbts! */ - end = create_psbt(tmpctx, 1, 1, 0); - tal_wally_start(); - if (wally_psbt_clone_alloc(end, flags, &start) != WALLY_OK) - abort(); - tal_wally_end(tmpctx); - diff_count(start, end, 0, 0); - diff_count(end, start, 0, 0); - - /* New input/output added */ - add_in_out_with_serial(end, 10, 1); - diff_count(start, end, 1, 0); - diff_count(end, start, 0, 1); - - /* Add another one, before previous */ - tal_wally_start(); - if (wally_psbt_clone_alloc(end, flags, &start) != WALLY_OK) - abort(); - tal_wally_end(tmpctx); - add_in_out_with_serial(end, 5, 2); - diff_count(start, end, 1, 0); - diff_count(end, start, 0, 1); - - /* Add another, at end */ - tal_wally_start(); - if (wally_psbt_clone_alloc(end, flags, &start) != WALLY_OK) - abort(); - tal_wally_end(tmpctx); - add_in_out_with_serial(end, 15, 3); - diff_count(start, end, 1, 0); - diff_count(end, start, 0, 1); - - /* Add another, in middle */ - tal_wally_start(); - if (wally_psbt_clone_alloc(end, flags, &start) != WALLY_OK) - abort(); - tal_wally_end(tmpctx); - add_in_out_with_serial(end, 11, 4); - diff_count(start, end, 1, 0); - diff_count(end, start, 0, 1); - - /* Change existing input/output info - * (we accomplish this by removing and then - * readding an input/output with the same serial_id - * but different value) */ - tal_wally_start(); - if (wally_psbt_clone_alloc(end, flags, &start) != WALLY_OK) - abort(); - tal_wally_end(tmpctx); - psbt_rm_output(end, 0); - psbt_rm_input(end, 0); - add_in_out_with_serial(end, 5, 5); - diff_count(start, end, 1, 1); - diff_count(end, start, 1, 1); - - /* Add some extra unknown info to a PSBT */ - u8 *key = psbt_make_key(tmpctx, 0x05, NULL); - char *val = tal_fmt(tmpctx, "hello"); - psbt_input_set_unknown(end, &end->inputs[1], key, val, tal_bytelen(val)); - psbt_input_set_unknown(start, &start->inputs[1], key, val, tal_bytelen(val)); - - /* Swap locations */ - struct wally_map_item tmp; - tmp = end->inputs[1].unknowns.items[0]; - end->inputs[1].unknowns.items[0] = end->inputs[1].unknowns.items[1]; - end->inputs[1].unknowns.items[1] = tmp; - - /* We expect nothing to change ? */ - diff_count(start, end, 1, 1); - diff_count(end, start, 1, 1); - - change_serials(); - - check_psbt_comparison(); - - /* No memory leaks please */ - common_shutdown(); - return 0; -} diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 1af682ffe8a3..29480830158e 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -653,7 +653,10 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) #endif /* DEVELOPER */ case WIRE_HSMD_NEW_CHANNEL: - case WIRE_HSMD_READY_CHANNEL: + case WIRE_HSMD_SETUP_CHANNEL: + case WIRE_HSMD_NEXT_FUNDING_PUBKEY: + case WIRE_HSMD_CHECK_OUTPOINT: + case WIRE_HSMD_LOCK_OUTPOINT: case WIRE_HSMD_SIGN_COMMITMENT_TX: case WIRE_HSMD_VALIDATE_COMMITMENT_TX: case WIRE_HSMD_VALIDATE_REVOCATION: @@ -698,7 +701,10 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_CUPDATE_SIG_REPLY: case WIRE_HSMD_CLIENT_HSMFD_REPLY: case WIRE_HSMD_NEW_CHANNEL_REPLY: - case WIRE_HSMD_READY_CHANNEL_REPLY: + case WIRE_HSMD_SETUP_CHANNEL_REPLY: + case WIRE_HSMD_NEXT_FUNDING_PUBKEY_REPLY: + case WIRE_HSMD_CHECK_OUTPOINT_REPLY: + case WIRE_HSMD_LOCK_OUTPOINT_REPLY: case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 2eefd6962cd8..c1f64ded74a8 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -69,25 +69,52 @@ msgdata,hsmd_get_channel_basepoints_reply,funding_pubkey,pubkey, #include # Provide channel parameters. -msgtype,hsmd_ready_channel,31 -msgdata,hsmd_ready_channel,is_outbound,bool, -msgdata,hsmd_ready_channel,channel_value,amount_sat, -msgdata,hsmd_ready_channel,push_value,amount_msat, -msgdata,hsmd_ready_channel,funding_txid,bitcoin_txid, -msgdata,hsmd_ready_channel,funding_txout,u16, -msgdata,hsmd_ready_channel,local_to_self_delay,u16, -msgdata,hsmd_ready_channel,local_shutdown_script_len,u16, -msgdata,hsmd_ready_channel,local_shutdown_script,u8,local_shutdown_script_len -msgdata,hsmd_ready_channel,local_shutdown_wallet_index,?u32, -msgdata,hsmd_ready_channel,remote_basepoints,basepoints, -msgdata,hsmd_ready_channel,remote_funding_pubkey,pubkey, -msgdata,hsmd_ready_channel,remote_to_self_delay,u16, -msgdata,hsmd_ready_channel,remote_shutdown_script_len,u16, -msgdata,hsmd_ready_channel,remote_shutdown_script,u8,remote_shutdown_script_len -msgdata,hsmd_ready_channel,channel_type,channel_type, +msgtype,hsmd_setup_channel,31 +msgdata,hsmd_setup_channel,is_outbound,bool, +msgdata,hsmd_setup_channel,channel_value,amount_sat, +msgdata,hsmd_setup_channel,push_value,amount_msat, +msgdata,hsmd_setup_channel,funding_txid,bitcoin_txid, +msgdata,hsmd_setup_channel,funding_txout,u16, +msgdata,hsmd_setup_channel,local_to_self_delay,u16, +msgdata,hsmd_setup_channel,local_shutdown_script_len,u16, +msgdata,hsmd_setup_channel,local_shutdown_script,u8,local_shutdown_script_len +msgdata,hsmd_setup_channel,local_shutdown_wallet_index,?u32, +msgdata,hsmd_setup_channel,remote_basepoints,basepoints, +msgdata,hsmd_setup_channel,remote_funding_pubkey,pubkey, +msgdata,hsmd_setup_channel,remote_to_self_delay,u16, +msgdata,hsmd_setup_channel,remote_shutdown_script_len,u16, +msgdata,hsmd_setup_channel,remote_shutdown_script,u8,remote_shutdown_script_len +msgdata,hsmd_setup_channel,channel_type,channel_type, # No value returned. -msgtype,hsmd_ready_channel_reply,131 +msgtype,hsmd_setup_channel_reply,131 + +# Sent to derive the next funding pubkey (for splicing) +msgtype,hsmd_next_funding_pubkey,34 +msgdata,hsmd_next_funding_pubkey,peerid,node_id, +msgdata,hsmd_next_funding_pubkey,dbid,u64, +msgdata,hsmd_next_funding_pubkey,funding_txid,bitcoin_txid, +msgdata,hsmd_next_funding_pubkey,funding_txout,u32, + +# Returns the next funding pubkey for a splice +msgtype,hsmd_next_funding_pubkey_reply,134 +msgdata,hsmd_next_funding_pubkey_reply,next_funding_pubkey,pubkey, + +# check if the signer agrees that a funding candidate outpoint is buried +msgtype,hsmd_check_outpoint,32 +msgdata,hsmd_check_outpoint,funding_txid,bitcoin_txid, +msgdata,hsmd_check_outpoint,funding_txout,u16, + +msgtype,hsmd_check_outpoint_reply,132 +msgdata,hsmd_check_outpoint_reply,is_buried,bool, + +# change the funding/splice state to locked +msgtype,hsmd_lock_outpoint,37 +msgdata,hsmd_lock_outpoint,funding_txid,bitcoin_txid, +msgdata,hsmd_lock_outpoint,funding_txout,u16, + +# No value returned. +msgtype,hsmd_lock_outpoint_reply,137 # Return signature for a funding tx. #include diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 1eb0e5b7cf2a..7dbe339295c3 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -94,7 +94,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_GET_PER_COMMITMENT_POINT: case WIRE_HSMD_CHECK_FUTURE_SECRET: - case WIRE_HSMD_READY_CHANNEL: + case WIRE_HSMD_SETUP_CHANNEL: return (client->capabilities & HSM_PERM_COMMITMENT_POINT) != 0; case WIRE_HSMD_SIGN_REMOTE_COMMITMENT_TX: @@ -112,6 +112,10 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER: return (client->capabilities & HSM_PERM_SIGN_WILL_FUND_OFFER) != 0; + case WIRE_HSMD_CHECK_OUTPOINT: + case WIRE_HSMD_LOCK_OUTPOINT: + return (client->capabilities & HSM_PERM_LOCK_OUTPOINT) != 0; + case WIRE_HSMD_INIT: case WIRE_HSMD_NEW_CHANNEL: case WIRE_HSMD_CLIENT_HSMFD: @@ -119,6 +123,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_INVOICE: case WIRE_HSMD_SIGN_COMMITMENT_TX: case WIRE_HSMD_GET_CHANNEL_BASEPOINTS: + case WIRE_HSMD_NEXT_FUNDING_PUBKEY: case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_SIGN_MESSAGE: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: @@ -143,7 +148,9 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_CUPDATE_SIG_REPLY: case WIRE_HSMD_CLIENT_HSMFD_REPLY: case WIRE_HSMD_NEW_CHANNEL_REPLY: - case WIRE_HSMD_READY_CHANNEL_REPLY: + case WIRE_HSMD_SETUP_CHANNEL_REPLY: + case WIRE_HSMD_CHECK_OUTPOINT_REPLY: + case WIRE_HSMD_LOCK_OUTPOINT_REPLY: case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: @@ -158,6 +165,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_GET_PER_COMMITMENT_POINT_REPLY: case WIRE_HSMD_CHECK_FUTURE_SECRET_REPLY: case WIRE_HSMD_GET_CHANNEL_BASEPOINTS_REPLY: + case WIRE_HSMD_NEXT_FUNDING_PUBKEY_REPLY: case WIRE_HSMD_DEV_MEMLEAK_REPLY: case WIRE_HSMD_SIGN_MESSAGE_REPLY: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY_REPLY: @@ -337,7 +345,7 @@ static bool mem_is_zero(const void *mem, size_t len) /* ~This stub implementation is overriden by fully validating signers * that need the unchanging channel parameters. */ -static u8 *handle_ready_channel(struct hsmd_client *c, const u8 *msg_in) +static u8 *handle_setup_channel(struct hsmd_client *c, const u8 *msg_in) { bool is_outbound; struct amount_sat channel_value; @@ -354,7 +362,7 @@ static u8 *handle_ready_channel(struct hsmd_client *c, const u8 *msg_in) struct amount_msat value_msat; struct channel_type *channel_type; - if (!fromwire_hsmd_ready_channel(tmpctx, msg_in, &is_outbound, + if (!fromwire_hsmd_setup_channel(tmpctx, msg_in, &is_outbound, &channel_value, &push_value, &funding_txid, &funding_txout, &local_to_self_delay, &local_shutdown_script, @@ -376,7 +384,60 @@ static u8 *handle_ready_channel(struct hsmd_client *c, const u8 *msg_in) assert(local_to_self_delay > 0); assert(remote_to_self_delay > 0); - return towire_hsmd_ready_channel_reply(NULL); + return towire_hsmd_setup_channel_reply(NULL); +} + +/* ~Return the funding pubkey for the next splice */ +static u8 *handle_next_funding_pubkey(struct hsmd_client *c, const u8 *msg_in) +{ + struct node_id peer_id; + u64 dbid; + struct bitcoin_txid funding_txid; + u32 funding_txout; + struct secret seed; + struct pubkey funding_pubkey; + + if (!fromwire_hsmd_next_funding_pubkey(msg_in, &peer_id, &dbid, + &funding_txid, &funding_txout)) + return hsmd_status_malformed_request(c, msg_in); + + // TODO actually rotate the funding pubkey + get_channel_seed(&peer_id, dbid, &seed); + derive_basepoints(&seed, &funding_pubkey, NULL, NULL, NULL); + + return towire_hsmd_setup_channel_reply(NULL); +} + +/* ~This stub implementation is overriden by fully validating signers + * to ensure they are caught up when outpoints are freshly buried */ +static u8 *handle_check_outpoint(struct hsmd_client *c, const u8 *msg_in) +{ + struct bitcoin_txid funding_txid; + u16 funding_txout; + bool is_buried; + + if (!fromwire_hsmd_check_outpoint(msg_in, &funding_txid, &funding_txout)) + return hsmd_status_malformed_request(c, msg_in); + + /* This stub always approves */ + is_buried = true; + + return towire_hsmd_check_outpoint_reply(NULL, is_buried); +} + +/* ~This stub implementation is overriden by fully validating signers to + * change their funding/splice state to locked */ +static u8 *handle_lock_outpoint(struct hsmd_client *c, const u8 *msg_in) +{ + struct bitcoin_txid funding_txid; + u16 funding_txout; + + if (!fromwire_hsmd_lock_outpoint(msg_in, &funding_txid, &funding_txout)) + return hsmd_status_malformed_request(c, msg_in); + + /* Stub implementation */ + + return towire_hsmd_lock_outpoint_reply(NULL); } /*~ For almost every wallet tx we use the BIP32 seed, but not for onchain @@ -1904,8 +1965,14 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_NEW_CHANNEL: return handle_new_channel(client, msg); - case WIRE_HSMD_READY_CHANNEL: - return handle_ready_channel(client, msg); + case WIRE_HSMD_SETUP_CHANNEL: + return handle_setup_channel(client, msg); + case WIRE_HSMD_NEXT_FUNDING_PUBKEY: + return handle_next_funding_pubkey(client, msg); + case WIRE_HSMD_CHECK_OUTPOINT: + return handle_check_outpoint(client, msg); + case WIRE_HSMD_LOCK_OUTPOINT: + return handle_lock_outpoint(client, msg); case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: return handle_get_output_scriptpubkey(client, msg); case WIRE_HSMD_CHECK_FUTURE_SECRET: @@ -1982,7 +2049,10 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_CUPDATE_SIG_REPLY: case WIRE_HSMD_CLIENT_HSMFD_REPLY: case WIRE_HSMD_NEW_CHANNEL_REPLY: - case WIRE_HSMD_READY_CHANNEL_REPLY: + case WIRE_HSMD_SETUP_CHANNEL_REPLY: + case WIRE_HSMD_NEXT_FUNDING_PUBKEY_REPLY: + case WIRE_HSMD_CHECK_OUTPOINT_REPLY: + case WIRE_HSMD_LOCK_OUTPOINT_REPLY: case WIRE_HSMD_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSMD_SIGN_WITHDRAWAL_REPLY: case WIRE_HSMD_SIGN_INVOICE_REPLY: @@ -2025,6 +2095,8 @@ u8 *hsmd_init(struct secret hsm_secret, WIRE_HSMD_SIGN_ANCHORSPEND, WIRE_HSMD_SIGN_HTLC_TX_MINGLE, WIRE_HSMD_SIGN_SPLICE_TX, + WIRE_HSMD_CHECK_OUTPOINT, + WIRE_HSMD_LOCK_OUTPOINT, }; /*~ Don't swap this. */ diff --git a/hsmd/permissions.h b/hsmd/permissions.h index afc396c2246a..9f1bf453e183 100644 --- a/hsmd/permissions.h +++ b/hsmd/permissions.h @@ -10,6 +10,7 @@ #define HSM_PERM_SIGN_CLOSING_TX 32 #define HSM_PERM_SIGN_WILL_FUND_OFFER 64 #define HSM_PERM_SIGN_SPLICE_TX 128 +#define HSM_PERM_LOCK_OUTPOINT 256 #define HSM_PERM_MASTER 1024 #endif /* LIGHTNING_HSMD_PERMISSIONS_H */ diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 1d03efcad41a..6c7519e6739c 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -1283,7 +1283,8 @@ bool peer_start_channeld(struct channel *channel, | HSM_PERM_SIGN_REMOTE_TX | HSM_PERM_SIGN_ONCHAIN_TX | HSM_PERM_SIGN_CLOSING_TX - | HSM_PERM_SIGN_SPLICE_TX); + | HSM_PERM_SIGN_SPLICE_TX + | HSM_PERM_LOCK_OUTPOINT); channel_set_owner(channel, new_channel_subd(channel, ld, diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 6f70dd4362bb..f1a2ac28b62c 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -938,13 +938,14 @@ openchannel2_signed_deserialize(struct openchannel2_psbt_payload *payload, * totally managled the data here but left the serial_ids intact, * you'll get a failure back from the peer when you send * commitment sigs */ - if (psbt_contribs_changed(payload->psbt, psbt)) - fatal("Plugin must not change psbt input/output set. " - "orig: %s. updated: %s", - type_to_string(tmpctx, struct wally_psbt, - payload->psbt), - type_to_string(tmpctx, struct wally_psbt, - psbt)); + // FIXME this deletes the final_witness from the psbt +// if (psbt_contribs_changed(payload->psbt, psbt)) +// fatal("Plugin must not change psbt input/output set. " +// "orig: %s. updated: %s", +// type_to_string(tmpctx, struct wally_psbt, +// payload->psbt), +// type_to_string(tmpctx, struct wally_psbt, +// psbt)); if (payload->psbt) tal_free(payload->psbt); @@ -3697,7 +3698,8 @@ bool peer_start_dualopend(struct peer *peer, hsmfd = hsm_get_client_fd(peer->ld, &peer->id, channel->unsaved_dbid, HSM_PERM_COMMITMENT_POINT | HSM_PERM_SIGN_REMOTE_TX - | HSM_PERM_SIGN_WILL_FUND_OFFER); + | HSM_PERM_SIGN_WILL_FUND_OFFER + | HSM_PERM_LOCK_OUTPOINT); channel->owner = new_channel_subd(channel, peer->ld, @@ -3769,7 +3771,8 @@ bool peer_restart_dualopend(struct peer *peer, hsmfd = hsm_get_client_fd(peer->ld, &peer->id, channel->dbid, HSM_PERM_COMMITMENT_POINT | HSM_PERM_SIGN_REMOTE_TX - | HSM_PERM_SIGN_WILL_FUND_OFFER); + | HSM_PERM_SIGN_WILL_FUND_OFFER + | HSM_PERM_LOCK_OUTPOINT); channel_set_owner(channel, new_channel_subd(channel, peer->ld, diff --git a/openingd/dualopend.c b/openingd/dualopend.c index f1e6f01487e8..b2070871acaa 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -424,6 +424,46 @@ static void billboard_update(struct state *state) peer_billboard(false, update); } +static void lock_signer_outpoint(const struct bitcoin_outpoint *outpoint) { + const u8 *msg; + bool is_buried = false; + + do { + /* Make sure the hsmd agrees that this outpoint is + * sufficiently buried. */ + msg = towire_hsmd_check_outpoint(NULL, &outpoint->txid, outpoint->n); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_check_outpoint_reply(msg, &is_buried)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad hsmd_check_outpoint_reply: %s", + tal_hex(tmpctx, msg)); + + /* the signer should have a shorter buried height requirement so + * it almost always will be ready ahead of us.*/ + if (!is_buried) { + sleep(10); + } + } while (!is_buried); + + /* tell the signer that we are now locked */ + msg = towire_hsmd_lock_outpoint(NULL, &outpoint->txid, outpoint->n); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_lock_outpoint_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad hsmd_lock_outpoint_reply: %s", + tal_hex(tmpctx, msg)); +} + +/* Call this method when channel_ready status are changed. */ +static void check_mutual_channel_ready(const struct state *state) +{ + if (state->channel_ready[LOCAL] && state->channel_ready[REMOTE]) { + lock_signer_outpoint(&state->channel->funding); + } +} + static void send_shutdown(struct state *state, const u8 *final_scriptpubkey) { u8 *msg; @@ -1273,6 +1313,7 @@ static u8 *handle_channel_ready(struct state *state, u8 *msg) } state->channel_ready[REMOTE] = true; + check_mutual_channel_ready(state); billboard_update(state); if (state->channel_ready[LOCAL]) @@ -1941,7 +1982,7 @@ static u8 *accepter_commits(struct state *state, "to msats"); /*~ Report the channel parameters to the signer. */ - msg = towire_hsmd_ready_channel(NULL, + msg = towire_hsmd_setup_channel(NULL, false, /* is_outbound */ total, our_msats, @@ -1957,8 +1998,8 @@ static u8 *accepter_commits(struct state *state, state->channel_type); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_ready_channel_reply(msg)) - status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + if (!fromwire_hsmd_setup_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad setup_channel_reply %s", tal_hex(tmpctx, msg)); tal_free(state->channel); @@ -2675,7 +2716,7 @@ static u8 *opener_commits(struct state *state, } /*~ Report the channel parameters to the signer. */ - msg = towire_hsmd_ready_channel(NULL, + msg = towire_hsmd_setup_channel(NULL, true, /* is_outbound */ total, their_msats, @@ -2691,8 +2732,8 @@ static u8 *opener_commits(struct state *state, state->channel_type); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_ready_channel_reply(msg)) - status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + if (!fromwire_hsmd_setup_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad setup_channel_reply %s", tal_hex(tmpctx, msg)); tal_free(state->channel); @@ -3824,6 +3865,7 @@ static void send_channel_ready(struct state *state) peer_write(state->pps, take(msg)); state->channel_ready[LOCAL] = true; + check_mutual_channel_ready(state); billboard_update(state); } diff --git a/openingd/openingd.c b/openingd/openingd.c index 84b7a5c09add..dd2f2b47b889 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -632,7 +632,7 @@ static bool funder_finalize_channel_setup(struct state *state, struct wally_tx_output *direct_outputs[NUM_SIDES]; /*~ Channel is ready; Report the channel parameters to the signer. */ - msg = towire_hsmd_ready_channel(NULL, + msg = towire_hsmd_setup_channel(NULL, true, /* is_outbound */ state->funding_sats, state->push_msat, @@ -648,8 +648,8 @@ static bool funder_finalize_channel_setup(struct state *state, state->channel_type); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_ready_channel_reply(msg)) - status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + if (!fromwire_hsmd_setup_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad setup_channel_reply %s", tal_hex(tmpctx, msg)); /*~ Now we can initialize the `struct channel`. This represents @@ -1222,7 +1222,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) } /*~ Channel is ready; Report the channel parameters to the signer. */ - msg = towire_hsmd_ready_channel(NULL, + msg = towire_hsmd_setup_channel(NULL, false, /* is_outbound */ state->funding_sats, state->push_msat, @@ -1238,8 +1238,8 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) state->channel_type); wire_sync_write(HSM_FD, take(msg)); msg = wire_sync_read(tmpctx, HSM_FD); - if (!fromwire_hsmd_ready_channel_reply(msg)) - status_failed(STATUS_FAIL_HSM_IO, "Bad ready_channel_reply %s", + if (!fromwire_hsmd_setup_channel_reply(msg)) + status_failed(STATUS_FAIL_HSM_IO, "Bad setup_channel_reply %s", tal_hex(tmpctx, msg)); /* Now we can create the channel structure. */ diff --git a/tests/test_bookkeeper.py b/tests/test_bookkeeper.py index 6bdf7c7d6704..759ca99d7f97 100644 --- a/tests/test_bookkeeper.py +++ b/tests/test_bookkeeper.py @@ -333,6 +333,7 @@ def test_bookkeeping_rbf_withdraw(node_factory, bitcoind): assert len(fees) == 1 +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "hsmd_sign_option_will_fund_offer not supported") @pytest.mark.openchannel('v2') @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "turns off bookkeeper at start") @unittest.skipIf(TEST_NETWORK != 'regtest', "network fees hardcoded") diff --git a/tests/test_opening.py b/tests/test_opening.py index bc31990bcd66..8e73b6aeb33a 100644 --- a/tests/test_opening.py +++ b/tests/test_opening.py @@ -524,6 +524,7 @@ def test_v2_rbf_abort_channel_opens(node_factory, bitcoind, chainparams): l1.daemon.wait_for_log(' to CHANNELD_NORMAL') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sign_option_will_fund_offer unimplemented") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') def test_v2_rbf_liquidity_ad(node_factory, bitcoind, chainparams): @@ -1407,6 +1408,7 @@ def test_funder_contribution_limits(node_factory, bitcoind): assert l3.daemon.is_in_log(r'calling `signpsbt` .* 6 inputs') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') @pytest.mark.developer("requres 'dev-disconnect'") def test_inflight_dbload(node_factory, bitcoind): @@ -1720,6 +1722,7 @@ def test_buy_liquidity_ad_no_v2(node_factory, bitcoind): compact_lease='029a002d000000004b2003e8') +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') def test_v2_replay_bookkeeping(node_factory, bitcoind): """ Test that your bookkeeping for a liquidity ad is good @@ -1784,6 +1787,7 @@ def test_v2_replay_bookkeeping(node_factory, bitcoind): l1.rpc.bkpr_listbalances() +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "sign_option_will_fund_offer unimplemented") @pytest.mark.openchannel('v2') def test_buy_liquidity_ad_check_bookkeeping(node_factory, bitcoind): """ Test that your bookkeeping for a liquidity ad is good.""" diff --git a/tests/test_splicing.py b/tests/test_splicing.py index 0e87bb72cb9a..0b406e59e8cf 100644 --- a/tests/test_splicing.py +++ b/tests/test_splicing.py @@ -5,22 +5,30 @@ import time +@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd') and os.getenv('EXPERIMENTAL_SPLICING') != '1', "splicing not supported yet") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') -@unittest.skipIf(os.getenv('SUBDAEMON').startswith('hsmd:remote_hsmd'), "splicing not supported by VLS yet (VLS #325)") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') def test_splice(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, fundamount=1000000, wait_for_announce=True, opts={'experimental-splicing': None}) chan_id = l1.get_channel_id(l2) + print("EXPLORE-SPLICING: initial channel setup") + # add extra sats to pay fee + print("EXPLORE-SPLICING: adding extra to pay fee") funds_result = l1.rpc.fundpsbt("109000sat", "slow", 166, excess_as_change=True) + print("EXPLORE-SPLICING: initing splice") result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt']) + print("EXPLORE-SPLICING: updating splice") result = l1.rpc.splice_update(chan_id, result['psbt']) + print("EXPLORE-SPLICING: signpsbt") result = l1.rpc.signpsbt(result['psbt']) + print("EXPLORE-SPLICING: signing splice") result = l1.rpc.splice_signed(chan_id, result['signed_psbt']) + print("EXPLORE-SPLICING: splice signed") l2.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE') l1.daemon.wait_for_log(r'CHANNELD_NORMAL to CHANNELD_AWAITING_SPLICE') diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 238d33b12f3b..1d70e4140b74 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -734,6 +734,8 @@ static struct command_result *param_input_numbers(struct command *cmd, return NULL; } +#include + static struct command_result *json_signpsbt(struct command *cmd, const char *buffer, const jsmntok_t *obj UNNEEDED, @@ -801,6 +803,7 @@ static struct command_result *json_signpsbt(struct command *cmd, "HSM gave bad sign_withdrawal_reply %s", tal_hex(tmpctx, msg)); + fprintf(stderr, "json_signpsbt: psbt_set_version %d\n", psbt_version); if (!psbt_set_version(signed_psbt, psbt_version)) { return command_fail(cmd, LIGHTNINGD, "Signed PSBT unable to have version set: %s",