diff --git a/ccan/ccan/read_write_all/read_write_all.c b/ccan/ccan/read_write_all/read_write_all.c index 7f0b70b9d020..c4b0f9e205d4 100644 --- a/ccan/ccan/read_write_all/read_write_all.c +++ b/ccan/ccan/read_write_all/read_write_all.c @@ -20,6 +20,8 @@ bool write_all(int fd, const void *data, size_t size) return true; } +int read_all_last_result_on_false = -1; + bool read_all(int fd, void *data, size_t size) { while (size) { @@ -28,8 +30,10 @@ bool read_all(int fd, void *data, size_t size) done = read(fd, data, size); if (done < 0 && errno == EINTR) continue; - if (done <= 0) + if (done <= 0) { + read_all_last_result_on_false = done; return false; + } data = (char *)data + done; size -= done; } diff --git a/channeld/channeld.c b/channeld/channeld.c index a4ea9219c744..6d9e6113afb4 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,8 @@ #include #include #include +#include +#include #include #include #include @@ -225,17 +228,35 @@ static void billboard_update(const struct peer *peer) peer_billboard(false, update); } +extern int wire_sync_read_fail_reason; + const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES) { u8 *msg; /* hsmd goes away at shutdown. That's OK. */ - if (!wire_sync_write(HSM_FD, req)) + if (!wire_sync_write(HSM_FD, req)) { + status_info("!wire_sync_write exit"); + exit(0); + } + + fd_set fds, efds; + FD_ZERO(&fds); + FD_ZERO(&efds); + FD_SET(HSM_FD, &fds); + FD_SET(HSM_FD, &efds); + select(HSM_FD+1, &fds, NULL, &efds, NULL); + + if(FD_ISSET(HSM_FD, &efds)) { + status_info("fd has an error! %s", strerror(errno)); exit(0); + } msg = wire_sync_read(ctx, HSM_FD); - if (!msg) + if (!msg) { + status_info("!wire_sync_read-msg exit, errno: %s, wire_sync_read_fail_reason: %d", strerror(errno), wire_sync_read_fail_reason); exit(0); + } return msg; } @@ -291,21 +312,33 @@ static void maybe_send_stfu(struct peer *peer) } } +/* Durring reestablish, STFU mode is assumed if continuing a splice */ +static void assume_stfu_mode(struct peer *peer) +{ + peer->stfu_sent[LOCAL] = peer->stfu_sent[REMOTE] = true; +} + static void handle_stfu(struct peer *peer, const u8 *stfu) { struct channel_id channel_id; u8 remote_initiated; + status_info("handle_stfu.1"); + if (!feature_negotiated(peer->our_features, peer->their_features, OPT_QUIESCE)) peer_failed_warn(peer->pps, &peer->channel_id, "stfu not supported"); + status_info("handle_stfu.2"); + if (!fromwire_stfu(stfu, &channel_id, &remote_initiated)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad stfu %s", tal_hex(peer, stfu)); + status_info("handle_stfu.3"); + if (!channel_id_eq(&channel_id, &peer->channel_id)) { peer_failed_err(peer->pps, &channel_id, "Wrong stfu channel_id: expected %s, got %s", @@ -315,11 +348,15 @@ static void handle_stfu(struct peer *peer, const u8 *stfu) &channel_id)); } + status_info("handle_stfu.4"); + /* Sanity check */ if (pending_updates(peer->channel, REMOTE, false)) peer_failed_warn(peer->pps, &peer->channel_id, "STFU but you still have updates pending?"); + status_info("handle_stfu.5"); + if (!peer->want_stfu) { peer->want_stfu = true; if (!remote_initiated) @@ -346,6 +383,8 @@ static void handle_stfu(struct peer *peer, const u8 *stfu) } } + status_info("handle_stfu.6"); + /* BOLT-quiescent #2: * The receiver of `stfu`: * - if it has sent `stfu` then: @@ -356,6 +395,8 @@ static void handle_stfu(struct peer *peer, const u8 *stfu) */ peer->stfu_sent[REMOTE] = true; + status_info("handle_stfu.7"); + maybe_send_stfu(peer); } @@ -1970,6 +2011,175 @@ static void send_revocation(struct peer *peer, peer_write(peer->pps, take(msg)); } +static struct inflight *last_inflight(struct peer *peer) +{ + size_t count = tal_count(peer->splice_state->inflights); + + if (count) + return peer->splice_state->inflights[count - 1]; + + return NULL; +} + +static size_t last_inflight_index(struct peer *peer) +{ + assert(tal_count(peer->splice_state->inflights) > 0); + + return tal_count(peer->splice_state->inflights) - 1; +} + +static u32 find_channel_funding_input(struct wally_psbt *psbt, + struct bitcoin_outpoint *funding) +{ + for (size_t i = 0; i < psbt->num_inputs; i++) { + struct bitcoin_outpoint psbt_outpoint; + wally_psbt_input_get_outpoint(&psbt->inputs[i], &psbt_outpoint); + + if (!bitcoin_outpoint_eq(&psbt_outpoint, funding)) + continue; + + if (funding->n == psbt->inputs[i].index) + return i; + } + + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Unable to find splice funding tx"); + + return UINT_MAX; +} + +static bool have_i_signed_inflight(const struct peer *peer, + const struct inflight *inflight) +{ + bool has_sig; + u32 index; + + if (!inflight || !inflight->psbt) + return false; + + index = find_channel_funding_input(inflight->psbt, + &peer->channel->funding); + + if (!psbt_input_have_signature(inflight->psbt, index, + &peer->channel->funding_pubkey[LOCAL], + &has_sig)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Unable parse inflight psbt"); + + return has_sig; +} + +static void check_tx_abort(struct peer *peer, const u8 *msg) +{ + struct inflight *inflight = last_inflight(peer); + struct bitcoin_outpoint *outpoint; + struct channel_id channel_id; + u8 *reason; + + if (!msg || fromwire_peektype(msg) != WIRE_TX_ABORT) + return; + + if (have_i_signed_inflight(peer, inflight)) { + peer_failed_err(peer->pps, &peer->channel_id, "tx_abort" + " is not allowed after I have sent my" + " signature. msg: %s", + tal_hex(tmpctx, msg)); + } + + if (!fromwire_tx_abort(tmpctx, msg, &channel_id, &reason)) + peer_failed_warn(peer->pps, &peer->channel_id, + "bad tx_abort %s", tal_hex(msg, msg)); + + if (!is_stfu_active(peer)) + peer_failed_warn(peer->pps, &peer->channel_id, + "tx_abort is invalid out of STFU mode"); + + if (!peer->splicing || !peer->splicing->mode) + peer_failed_warn(peer->pps, &peer->channel_id, + "tx_abort is invalid outside of a splice" + " session"); + + status_info("Send ack of tx_abort"); + + peer_write(peer->pps, + take(towire_tx_abort(NULL, &peer->channel_id, NULL))); + + outpoint = NULL; + if (inflight) + outpoint = &inflight->outpoint; + + status_info("Send tx_abort to master"); + + fprintf(stderr, "channeld -> lightningd towire_channeld_splice_abort pid:%d\n", (int)getpid()); + wire_sync_write(MASTER_FD, + take(towire_channeld_splice_abort(NULL, false, + outpoint, + (char*)reason))); + status_info("tx_abort is sent"); + // fdpass_send(MASTER_FD, peer->pps->peer_fd); + // fdpass_send(MASTER_FD, HSM_FD); + status_info("peer fd is passed to master"); + + /* Give master a chance to pass the fd along */ + status_info("Delaying closing of master fd by 1 second"); + sleep(1); + + close(MASTER_FD); + exit(0); +} + +static void splice_abort(struct peer *peer, const char *fmt, ...) +{ + struct inflight *inflight = last_inflight(peer); + struct bitcoin_outpoint *outpoint; + u8 *msg; + char *reason; + va_list ap; + + va_start(ap, fmt); + reason = tal_vfmt(NULL, fmt, ap); + va_end(ap); + + if (have_i_signed_inflight(peer, inflight)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tried to abort a splice where I have already" + " sent my signatures"); + + status_info("We are initiating tx_abort for reason: %s", reason); + + peer_write(peer->pps, + take(towire_tx_abort(NULL, &peer->channel_id, (u8*)reason))); + + do { + msg = peer_read(tmpctx, peer->pps); + if (handle_peer_error_or_warning(peer->pps, msg)) { + status_info("Received warning/error while expecting " + "tx_abort, msg: %s", tal_hex(tmpctx, msg)); + exit(0); + } + } while (fromwire_peektype(msg) != WIRE_TX_ABORT); + + status_info("We got TX_ABORT ack, now telling master about it"); + + outpoint = NULL; + if (inflight) + outpoint = &inflight->outpoint; + + fprintf(stderr, "channeld -> lightningd towire_channeld_splice_abort"); + msg = towire_channeld_splice_abort(tmpctx, true, outpoint, reason); + + wire_sync_write(MASTER_FD, msg); + + /* Give master a chance to pass the fd along */ + status_info("Delaying closing of master fd by 1 second"); + sleep(1); + + fprintf(stderr, "delay is finished\n"); + + close(MASTER_FD); + exit(0); +} + struct commitsig_info { struct commitsig *commitsig; struct secret *old_secret; @@ -2251,6 +2461,7 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer, s64 sub_splice_amnt = peer->splice_state->inflights[i]->splice_amnt; splice_msg = peer_read(tmpctx, peer->pps); + check_tx_abort(peer, splice_msg); /* Check type for cleaner failure message */ type = fromwire_peektype(msg); if (type != WIRE_COMMITMENT_SIGNED) @@ -2917,6 +3128,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer, WIRE_TX_SIGNATURES, WIRE_TX_ABORT); + check_tx_abort(peer, msg); + if (msg_received) *msg_received = msg; @@ -3176,7 +3389,7 @@ static struct amount_sat check_balances(struct peer *peer, out[TX_INITIATOR], true); wire_sync_write(MASTER_FD, take(msg)); - peer_failed_warn(peer->pps, &peer->channel_id, + splice_abort(peer, "Initiator funding is less than commited" " amount. Initiator contributing %s but they" " committed to %s. Pending offered HTLC" @@ -3198,7 +3411,7 @@ static struct amount_sat check_balances(struct peer *peer, out[TX_INITIATOR], true); wire_sync_write(MASTER_FD, take(msg)); - peer_failed_warn(peer->pps, &peer->channel_id, + splice_abort(peer, "Accepter funding is less than commited" " amount. Accepter contributing %s but they" " committed to %s. Pending offered HTLC" @@ -3240,8 +3453,7 @@ static struct amount_sat check_balances(struct peer *peer, msg = towire_channeld_splice_feerate_error(NULL, initiator_fee, false); wire_sync_write(MASTER_FD, take(msg)); - /* DTODO: Swap `peer_failed_warn` out for `tx_abort`? */ - peer_failed_warn(peer->pps, &peer->channel_id, + splice_abort(peer, "%s fee (%s) was too low, must be at least %s", opener ? "Our" : "Your", type_to_string(tmpctx, struct amount_msat, @@ -3254,8 +3466,7 @@ static struct amount_sat check_balances(struct peer *peer, msg = towire_channeld_splice_feerate_error(NULL, initiator_fee, true); wire_sync_write(MASTER_FD, take(msg)); - /* DTODO: Swap `peer_failed_warn` out for `tx_abort` */ - peer_failed_warn(peer->pps, &peer->channel_id, + splice_abort(peer, "Our own fee (%s) was too high, max without" " forcing is %s.", type_to_string(tmpctx, struct amount_msat, @@ -3268,8 +3479,7 @@ static struct amount_sat check_balances(struct peer *peer, msg = towire_channeld_splice_feerate_error(NULL, accepter_fee, false); wire_sync_write(MASTER_FD, take(msg)); - /* DTODO: Swap `peer_failed_warn` out for `tx_abort`? */ - peer_failed_warn(peer->pps, &peer->channel_id, + splice_abort(peer, "%s fee (%s) was too low, must be at least %s", opener ? "Your" : "Our", type_to_string(tmpctx, struct amount_msat, @@ -3282,8 +3492,7 @@ static struct amount_sat check_balances(struct peer *peer, msg = towire_channeld_splice_feerate_error(NULL, accepter_fee, true); wire_sync_write(MASTER_FD, take(msg)); - /* DTODO: Swap `peer_failed_warn` out for `tx_abort` */ - peer_failed_warn(peer->pps, &peer->channel_id, + splice_abort(peer, "Our own fee (%s) was too high, max without" " forcing is %s.", type_to_string(tmpctx, struct amount_msat, @@ -3336,26 +3545,6 @@ static struct amount_sat check_balances(struct peer *peer, return funding_amount_res; } -static u32 find_channel_funding_input(struct wally_psbt *psbt, - struct bitcoin_outpoint *funding) -{ - for (size_t i = 0; i < psbt->num_inputs; i++) { - struct bitcoin_outpoint psbt_outpoint; - wally_psbt_input_get_outpoint(&psbt->inputs[i], &psbt_outpoint); - - if (!bitcoin_outpoint_eq(&psbt_outpoint, funding)) - continue; - - if (funding->n == psbt->inputs[i].index) - return i; - } - - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Unable to find splice funding tx"); - - return UINT_MAX; -} - static void update_view_from_inflights(struct peer *peer) { struct inflight **inflights = peer->splice_state->inflights; @@ -3379,58 +3568,6 @@ static void update_view_from_inflights(struct peer *peer) } } -static struct inflight *last_inflight(struct peer *peer) -{ - size_t count = tal_count(peer->splice_state->inflights); - - if (count) - return peer->splice_state->inflights[count - 1]; - - return NULL; -} - -static size_t last_inflight_index(struct peer *peer) -{ - assert(tal_count(peer->splice_state->inflights) > 0); - - return tal_count(peer->splice_state->inflights) - 1; -} - -static bool have_i_signed_inflight(const struct peer *peer, - const struct inflight *inflight) -{ - bool has_sig; - u32 index; - - index = find_channel_funding_input(inflight->psbt, - &peer->channel->funding); - - if (!psbt_input_have_signature(inflight->psbt, index, - &peer->channel->funding_pubkey[LOCAL], - &has_sig)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Unable parse inflight psbt"); - - return has_sig; -} - -static bool check_tx_abort(struct peer *peer, const u8 *msg) -{ - if (!msg || fromwire_peektype(msg) != WIRE_TX_ABORT) - return false; - - if (have_i_signed_inflight(peer, last_inflight(peer))) { - peer_failed_err(peer->pps, &peer->channel_id, "tx_abort" - " is not allowed after I have sent my" - " signature. msg: %s", - tal_hex(tmpctx, msg)); - } - - /* DTODO: Remove last_inflight */ - - return true; -} - /* Called to finish an ongoing splice OR on restart from chanenl_reestablish. */ static void resume_splice_negotiation(struct peer *peer, bool send_commitments, @@ -3488,8 +3625,7 @@ static void resume_splice_negotiation(struct peer *peer, recv_commitments, &msg_received); - if (check_tx_abort(peer, msg_received)) - return; + check_tx_abort(peer, msg_received); if (their_commit) { if (inflight->last_tx != their_commit->tx) @@ -3591,8 +3727,7 @@ static void resume_splice_negotiation(struct peer *peer, type = fromwire_peektype(msg); - if (check_tx_abort(peer, msg)) - return; + check_tx_abort(peer, msg); if (handle_peer_error_or_warning(peer->pps, msg)) return; @@ -3804,6 +3939,10 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) struct bitcoin_outpoint outpoint; struct amount_msat current_push_val; const enum tx_role our_role = TX_ACCEPTER; + struct tlv_splice_tlvs *splice_tlvs; + struct tlv_splice_ack_tlvs *splice_ack_tlvs; + struct amount_sat requested_sats; + u8 *abort_msg; /* Can't start a splice with another splice still active */ assert(!peer->splicing); @@ -3812,13 +3951,14 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) ictx = new_interactivetx_context(tmpctx, our_role, peer->pps, peer->channel_id); - if (!fromwire_splice(inmsg, + if (!fromwire_splice(tmpctx, inmsg, &channel_id, &genesis_blockhash, &peer->splicing->opener_relative, &funding_feerate_perkw, &locktime, - &splice_remote_pubkey)) + &splice_remote_pubkey, + &splice_tlvs)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad wire_splice %s", tal_hex(tmpctx, inmsg)); @@ -3849,11 +3989,21 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) /* TODO: Add plugin hook for user to adjust accepter amount */ peer->splicing->accepter_relative = 0; + requested_sats = AMOUNT_SAT(0); + if (splice_tlvs && splice_tlvs->request_funds) { + requested_sats.satoshis = splice_tlvs->request_funds->requested_sats; /* Raw: wire -> struct */ + status_info("Peer requests we add %s funds to splice!", + type_to_string(tmpctx, struct amount_sat, + &requested_sats)); + } + + splice_ack_tlvs = NULL; msg = towire_splice_ack(NULL, &peer->channel_id, &chainparams->genesis_blockhash, peer->splicing->accepter_relative, - &peer->channel->funding_pubkey[LOCAL]); + &peer->channel->funding_pubkey[LOCAL], + splice_ack_tlvs); peer->splicing->mode = true; @@ -3870,11 +4020,14 @@ static void splice_accepter(struct peer *peer, const u8 *inmsg) ictx->pause_when_complete = false; error = process_interactivetx_updates(tmpctx, ictx, - &peer->splicing->received_tx_complete); + &peer->splicing->received_tx_complete, + &abort_msg); if (error) peer_failed_err(peer->pps, &peer->channel_id, "Interactive splicing error: %s", error); + check_tx_abort(peer, abort_msg); + assert(ictx->pause_when_complete == false); peer->splicing->sent_tx_complete = true; @@ -3968,15 +4121,18 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) u32 sequence = 0; u8 *scriptPubkey; char *error; + struct tlv_splice_ack_tlvs *tlvs; + u8 *msg, *abort_msg; ictx = new_interactivetx_context(tmpctx, TX_INITIATOR, peer->pps, peer->channel_id); - if (!fromwire_splice_ack(inmsg, + if (!fromwire_splice_ack(tmpctx, inmsg, &channel_id, &genesis_blockhash, &peer->splicing->accepter_relative, - &splice_remote_pubkey)) + &splice_remote_pubkey, + &tlvs)) peer_failed_warn(peer->pps, &peer->channel_id, "Bad wire_splice_ack %s", tal_hex(tmpctx, inmsg)); @@ -3995,6 +4151,21 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) peer_failed_warn(peer->pps, &peer->channel_id, "Splice[ACK] doesnt support changing pubkeys"); + if (peer->splicing->requested_sats) { + if (!tlvs || !tlvs->will_fund) { + + msg = towire_channeld_splice_lease_error(NULL, + "Peer lease" + " rejected :("); + wire_sync_write(MASTER_FD, take(msg)); + + splice_abort(peer, tal_fmt(tmpctx, "You rejected our lease request you jerk")); + return; + } + // TODO: add minimum lease amount setting and check that + // TODO: check lease terms + } + peer->splicing->received_tx_complete = false; peer->splicing->sent_tx_complete = false; peer->splice_state->locked_ready[LOCAL] = false; @@ -4058,12 +4229,15 @@ static void splice_initiator(struct peer *peer, const u8 *inmsg) error = process_interactivetx_updates(tmpctx, ictx, - &peer->splicing->received_tx_complete); + &peer->splicing->received_tx_complete, + &abort_msg); if (error) peer_failed_warn(peer->pps, &peer->channel_id, "Interactive splicing_ack error: %s", error); + check_tx_abort(peer, abort_msg); + peer->splicing->tx_add_input_count = ictx->tx_add_input_count; peer->splicing->tx_add_output_count = ictx->tx_add_output_count; @@ -4098,6 +4272,7 @@ static void splice_initiator_user_finalized(struct peer *peer) struct commitsig *their_commit; struct amount_msat current_push_val; const enum tx_role our_role = TX_INITIATOR; + u8 *abort_msg; ictx = new_interactivetx_context(tmpctx, our_role, peer->pps, peer->channel_id); @@ -4109,11 +4284,14 @@ static void splice_initiator_user_finalized(struct peer *peer) ictx->tx_add_output_count = peer->splicing->tx_add_output_count; error = process_interactivetx_updates(tmpctx, ictx, - &peer->splicing->received_tx_complete); + &peer->splicing->received_tx_complete, + &abort_msg); if (error) peer_failed_warn(peer->pps, &peer->channel_id, "Splice interactivetx error: %s", error); + check_tx_abort(peer, abort_msg); + /* With pause_when_complete fase, this assert should never fail */ assert(peer->splicing->received_tx_complete); peer->splicing->sent_tx_complete = true; @@ -4195,7 +4373,7 @@ static void splice_initiator_user_finalized(struct peer *peer) * new details to the active PSBT. Each user call enters here: */ static void splice_initiator_user_update(struct peer *peer, const u8 *inmsg) { - u8 *outmsg, *msg; + u8 *outmsg, *msg, *abort_msg; struct interactivetx_context *ictx; char *error; @@ -4244,11 +4422,14 @@ static void splice_initiator_user_update(struct peer *peer, const u8 *inmsg) } error = process_interactivetx_updates(tmpctx, ictx, - &peer->splicing->received_tx_complete); + &peer->splicing->received_tx_complete, + &abort_msg); if (error) peer_failed_warn(peer->pps, &peer->channel_id, "Splice update error: %s", error); + check_tx_abort(peer, abort_msg); + peer->splicing->tx_add_input_count = ictx->tx_add_input_count; peer->splicing->tx_add_output_count = ictx->tx_add_output_count; @@ -4347,13 +4528,25 @@ static void splice_initiator_user_signed(struct peer *peer, const u8 *inmsg) /* This occurs once our 'stfu' transition was successful. */ static void handle_splice_stfu_success(struct peer *peer) { + struct tlv_splice_tlvs *tlvs; + + if (peer->splicing->requested_sats) { + tlvs = tlv_splice_tlvs_new(tmpctx); + tlvs->request_funds = tal(tlvs, + struct tlv_splice_tlvs_request_funds); + tlvs->request_funds->requested_sats = + peer->splicing->requested_sats->satoshis; /* Raw: struct -> wire */ + } else { + tlvs = NULL; + } u8 *msg = towire_splice(tmpctx, &peer->channel_id, &chainparams->genesis_blockhash, peer->splicing->opener_relative, peer->splicing->feerate_per_kw, peer->splicing->current_psbt->fallback_locktime, - &peer->channel->funding_pubkey[LOCAL]); + &peer->channel->funding_pubkey[LOCAL], + tlvs); peer->splice_state->await_commitment_succcess = false; peer_write(peer->pps, take(msg)); } @@ -4381,7 +4574,9 @@ static void handle_splice_init(struct peer *peer, const u8 *inmsg) &peer->splicing->current_psbt, &peer->splicing->opener_relative, &peer->splicing->feerate_per_kw, - &peer->splicing->force_feerate)) + &peer->splicing->force_feerate, + &peer->splicing->requested_sats, + &peer->splicing->expected_rates)) master_badmsg(WIRE_CHANNELD_SPLICE_INIT, inmsg); if (peer->want_stfu) { @@ -4434,6 +4629,15 @@ static void peer_in(struct peer *peer, const u8 *msg) if (handle_peer_error_or_warning(peer->pps, msg)) return; + check_tx_abort(peer, msg); + + /* If we're in STFU mode and aren't waiting for a STFU mode + * specific message, the only valid message was tx_abort */ + if (is_stfu_active(peer) && !peer->stfu_wait_single_msg) + peer_failed_warn(peer->pps, &peer->channel_id, + "Received message %s when only TX_ABORT was" + " valid", peer_wire_name(type)); + /* Must get channel_ready before almost anything. */ if (!peer->channel_ready[REMOTE]) { if (type != WIRE_CHANNEL_READY @@ -5170,6 +5374,7 @@ static void peer_reconnect(struct peer *peer, if (inflight && (remote_next_funding || local_next_funding)) { if (!remote_next_funding) { status_info("Resuming splice negotation."); + assume_stfu_mode(peer); resume_splice_negotiation(peer, false, true, @@ -5178,6 +5383,7 @@ static void peer_reconnect(struct peer *peer, } else if (bitcoin_txid_eq(remote_next_funding, &inflight->outpoint.txid)) { status_info("Resuming splice negotation"); + assume_stfu_mode(peer); resume_splice_negotiation(peer, !inflight->remote_tx_sigs, local_next_funding, @@ -5482,6 +5688,8 @@ static void peer_reconnect(struct peer *peer, if (shutdown_complete(peer)) { send_shutdown_complete(peer); daemon_shutdown(); + status_info("reestablish_only exit"); + sleep(1); exit(0); } peer_failed_err(peer->pps, @@ -6002,6 +6210,9 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT: case WIRE_CHANNELD_SPLICE_FEERATE_ERROR: case WIRE_CHANNELD_SPLICE_FUNDING_ERROR: + case WIRE_CHANNELD_SPLICE_LEASE_ERROR: + case WIRE_CHANNELD_SPLICE_ABORT: + check_tx_abort(peer, msg); break; case WIRE_CHANNELD_DEV_REENABLE_COMMIT: if (peer->developer) { @@ -6171,7 +6382,7 @@ static void init_channel(struct peer *peer) " next_idx_remote = %"PRIu64 " revocations_received = %"PRIu64 " feerates %s range %u-%u" - " blockheights %s, our current %u", + " blockheights %s, our current %u, pid = %d", side_to_str(opener), type_to_string(tmpctx, struct pubkey, &peer->remote_per_commit), @@ -6182,7 +6393,7 @@ static void init_channel(struct peer *peer) type_to_string(tmpctx, struct fee_states, fee_states), peer->feerate_min, peer->feerate_max, type_to_string(tmpctx, struct height_states, blockheight_states), - peer->our_blockheight); + peer->our_blockheight, (int)getpid()); if (remote_ann_node_sig && remote_ann_bitcoin_sig) { peer->announcement_node_sigs[REMOTE] = *remote_ann_node_sig; @@ -6206,6 +6417,8 @@ static void init_channel(struct peer *peer) get_per_commitment_point(peer->next_index[LOCAL], &peer->next_local_per_commit, NULL); + status_debug("Building new full channel instance"); + peer->channel = new_full_channel(peer, &peer->channel_id, &funding, minimum_depth, @@ -6223,6 +6436,8 @@ static void init_channel(struct peer *peer) OPT_LARGE_CHANNELS), opener); + status_debug("full channel instance created"); + if (!channel_force_htlcs(peer->channel, cast_const2(const struct existing_htlc **, htlcs))) status_failed(STATUS_FAIL_INTERNAL_ERROR, @@ -6231,6 +6446,8 @@ static void init_channel(struct peer *peer) /* We don't need these any more, so free them. */ tal_free(htlcs); + status_debug("update view from inflights"); + update_view_from_inflights(peer); peer->channel_direction = node_id_idx(&peer->node_ids[LOCAL], @@ -6244,19 +6461,27 @@ static void init_channel(struct peer *peer) peer->depth_togo = minimum_depth; /* OK, now we can process peer messages. */ - if (reconnected) + if (reconnected) { + status_debug("begin peer_reconnect"); peer_reconnect(peer, &last_remote_per_commit_secret, reestablish_only); - else + } + else { + status_debug("skip peer_reconnect"); assert(!reestablish_only); + } /* If we have a messages to send, send them immediately */ if (fwd_msg) peer_write(peer->pps, take(fwd_msg)); + status_debug("Finished init process, checking channel_announcement_negotiate now"); + /* Reenable channel */ channel_announcement_negotiate(peer); + status_debug("init finally will update the billboard"); + billboard_update(peer); } @@ -6355,11 +6580,6 @@ int main(int argc, char *argv[]) tptr = &timeout; } - /* If we're in STFU mode and aren't waiting for a STFU mode - * specific message, don't read from the peer. */ - if (is_stfu_active(peer) && !peer->stfu_wait_single_msg) - FD_CLR(peer->pps->peer_fd, &rfds); - if (select(nfds, &rfds, NULL, NULL, tptr) < 0) { /* Signals OK, eg. SIGUSR1 */ if (errno == EINTR) @@ -6387,5 +6607,6 @@ int main(int argc, char *argv[]) assert(shutdown_complete(peer)); send_shutdown_complete(peer); daemon_shutdown(); + sleep(1); return 0; } diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 53590a2e6ee6..8d6cba152f89 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -10,6 +10,7 @@ #include #include #include +#include # Begin! (passes gossipd-client fd) msgtype,channeld_init,1000 @@ -211,6 +212,9 @@ msgdata,channeld_splice_init,psbt,wally_psbt, msgdata,channeld_splice_init,relative_amount,s64, msgdata,channeld_splice_init,feerate_per_kw,u32, msgdata,channeld_splice_init,force_feerate,bool, +msgdata,channeld_splice_init,requested_sats,?amount_sat, +# must go last because embedded tu32 +msgdata,channeld_splice_init,expected_rates,?lease_rates, # channeld->master: hello, I started a channel splice open msgtype,channeld_splice_confirmed_init,7205 @@ -282,6 +286,16 @@ msgdata,channeld_splice_funding_error,opener_error,bool, msgtype,channeld_splice_state_error,7221 msgdata,channeld_splice_state_error,state_error,wirestring, +# channeld->master: A lease error has occured +msgtype,channeld_splice_lease_error,7222 +msgdata,channeld_splice_lease_error,reason,wirestring, + +# channeld->master: Peer rejected our splice +msgtype,channeld_splice_abort,7223 +msgdata,channeld_splice_abort,did_i_initiate,bool, +msgdata,channeld_splice_abort,inflight_outpoint,?bitcoin_outpoint, +msgdata,channeld_splice_abort,reason,?wirestring, + # Tell peer to shut down channel. msgtype,channeld_send_shutdown,1023 msgdata,channeld_send_shutdown,final_index,?u32, diff --git a/channeld/splice.c b/channeld/splice.c index 473159614f09..43ea15286bb7 100644 --- a/channeld/splice.c +++ b/channeld/splice.c @@ -30,6 +30,8 @@ struct splicing *splicing_new(const tal_t *ctx) splicing->current_psbt = NULL; splicing->received_tx_complete = false; splicing->sent_tx_complete = false; + splicing->requested_sats = NULL; + splicing->expected_rates = NULL; return splicing; } diff --git a/channeld/splice.h b/channeld/splice.h index 267fddbac679..1b090a6a8d2c 100644 --- a/channeld/splice.h +++ b/channeld/splice.h @@ -51,6 +51,10 @@ struct splicing { bool received_tx_complete; /* If, in the last splice_update, we sent tx_complete */ bool sent_tx_complete; + /* Lease request sats */ + struct amount_sat *requested_sats; + /* Lease request terms */ + struct lease_rates *expected_rates; }; /* Sets `splice` items to default values */ diff --git a/common/interactivetx.c b/common/interactivetx.c index 3442d8526537..690b422e3109 100644 --- a/common/interactivetx.c +++ b/common/interactivetx.c @@ -128,8 +128,7 @@ static u8 *read_next_msg(const tal_t *ctx, desc = is_peer_warning(msg, msg); if (desc) { status_info("They sent %s", desc); - tal_free(msg); - continue; + return tal_free(msg); } /* In theory, we're in the middle of an open/RBF/splice, but @@ -142,9 +141,8 @@ static u8 *read_next_msg(const tal_t *ctx, case WIRE_TX_ADD_OUTPUT: case WIRE_TX_REMOVE_OUTPUT: case WIRE_TX_COMPLETE: - return msg; case WIRE_TX_ABORT: - /* TODO */ + return msg; case WIRE_TX_SIGNATURES: case WIRE_CHANNEL_READY: case WIRE_TX_INIT_RBF: @@ -345,13 +343,16 @@ bool interactivetx_has_changes(struct interactivetx_context *ictx, char *process_interactivetx_updates(const tal_t *ctx, struct interactivetx_context *ictx, - bool *received_tx_complete) + bool *received_tx_complete, + u8 **abort_msg) { bool we_complete = false, they_complete = false; u8 *msg; char *error = NULL; struct wally_psbt *next_psbt; + *abort_msg = NULL; + if (received_tx_complete) they_complete = *received_tx_complete; @@ -696,7 +697,8 @@ char *process_interactivetx_updates(const tal_t *ctx, *received_tx_complete = true; break; case WIRE_TX_ABORT: - /* Todo */ + *abort_msg = msg; + return NULL; case WIRE_INIT: case WIRE_ERROR: case WIRE_WARNING: diff --git a/common/interactivetx.h b/common/interactivetx.h index a63d01896dd9..d2233f4df463 100644 --- a/common/interactivetx.h +++ b/common/interactivetx.h @@ -77,10 +77,13 @@ struct interactivetx_context *new_interactivetx_context(const tal_t *ctx, * out -> true means the last message from the peer was 'tx_complete'. * * Returns NULL on success or a description of the error on failure. + * + * If `tx_abort` is received, NULL is returned and `abort_msg` will be set to */ char *process_interactivetx_updates(const tal_t *ctx, struct interactivetx_context *ictx, - bool *received_tx_complete); + bool *received_tx_complete, + u8 **abort_msg); /* If the given ictx would cause `process_interactivetx_updates to send tx * changes when called. Returns true if an error occurs diff --git a/common/jsonrpc_errors.h b/common/jsonrpc_errors.h index 05136bbfc1cc..989be11368d1 100644 --- a/common/jsonrpc_errors.h +++ b/common/jsonrpc_errors.h @@ -77,6 +77,8 @@ enum jsonrpc_errcode { SPLICE_STATE_ERROR = 358, SPLICE_LOW_FEE = 359, SPLICE_HIGH_FEE = 360, + SPLICE_LEASE_ERROR = 361, + SPLICE_ABORT = 362, /* `connect` errors */ CONNECT_NO_KNOWN_ADDRESS = 400, diff --git a/common/peer_failed.c b/common/peer_failed.c index f21754e3a96e..734850f637b3 100644 --- a/common/peer_failed.c +++ b/common/peer_failed.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include /* Fatal error here, return peer control to lightningd */ void NORETURN @@ -104,7 +106,10 @@ void peer_failed_received_errmsg(struct per_peer_state *pps, peer_fatal_continue(take(msg), pps); } +extern int wire_sync_read_fail_reason; + void peer_failed_connection_lost(void) { + status_info("peer_failed_connection_lost pid: %d, wire_sync_read_fail_reason: %d", (int)getpid(), wire_sync_read_fail_reason); status_send_fatal(take(towire_status_peer_connection_lost(NULL))); } diff --git a/common/peer_io.c b/common/peer_io.c index 3f090a834ea4..f3946e53c500 100644 --- a/common/peer_io.c +++ b/common/peer_io.c @@ -26,6 +26,11 @@ void peer_write(struct per_peer_state *pps, const void *msg TAKES) u8 *peer_read(const tal_t *ctx, struct per_peer_state *pps) { u8 *msg = wire_sync_read(ctx, pps->peer_fd); + if (!msg) { + unsigned int seconds = 3; + while((seconds = sleep(seconds))); + msg = wire_sync_read(ctx, pps->peer_fd); + } if (!msg) peer_failed_connection_lost(); diff --git a/common/wire_error.c b/common/wire_error.c index 10a5c7fc17f2..f99a9f3f0bd6 100644 --- a/common/wire_error.c +++ b/common/wire_error.c @@ -84,17 +84,17 @@ char *sanitize_error(const tal_t *ctx, const u8 *errmsg, struct channel_id dummy; u8 *data; size_t i; - bool warning; + char *tag; if (!channel_id) channel_id = &dummy; if (fromwire_error(ctx, errmsg, channel_id, &data)) - warning = false; + tag = "ERROR"; else if (fromwire_warning(ctx, errmsg, channel_id, &data)) - warning = true; + tag = "WARNING"; else if (fromwire_tx_abort(ctx, errmsg, channel_id, &data)) - warning = true; + tag = "ABORT"; else return tal_fmt(ctx, "Invalid ERROR message '%s'", tal_hex(ctx, errmsg)); @@ -118,7 +118,7 @@ char *sanitize_error(const tal_t *ctx, const u8 *errmsg, } return tal_fmt(ctx, "%s%s%s: %.*s", - warning ? "WARNING" : "ERROR", + tag, channel_id_is_all(channel_id) ? "": " channel ", channel_id_is_all(channel_id) ? "" : type_to_string(tmpctx, struct channel_id, channel_id), diff --git a/connectd/multiplex.c b/connectd/multiplex.c index a3b9e2d08258..a27b9968124a 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -1156,6 +1156,12 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, /* If we don't find a subdaemon for this, create a new one. */ subd = find_subd(peer, &channel_id); + if (!subd) { + status_info("Waiting 2 seconds and trying to find subd again."); + unsigned int seconds = 2; + while((seconds = sleep(seconds))); + subd = find_subd(peer, &channel_id); + } if (!subd) { enum peer_wire t = fromwire_peektype(decrypted); @@ -1187,6 +1193,7 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, /* Is this a tx_abort? Ignore from now on, and close after sending! */ if (type == WIRE_TX_ABORT) { subd->rcvd_tx_abort = true; + status_info("WE GOT TX_ABORT, KILL THE PROCESS in 5 seconds"); /* In case it doesn't close by itself */ notleak(new_reltimer(&peer->daemon->timers, subd, time_from_sec(5), @@ -1288,6 +1295,7 @@ void peer_connect_subd(struct daemon *daemon, const u8 *msg, int fd) /* Races can happen: this might be gone by now (or reconnected!). */ peer = peer_htable_get(daemon->peers, &id); if (!peer || peer->counter != counter) { + abort(); close(fd); return; } diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index 0b7a9f5cba80..d07554b2a1b9 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1123,17 +1123,25 @@ static u8 *handle_get_per_commitment_point(struct hsmd_client *c, const u8 *msg_ u64 n; struct secret *old_secret; + hsmd_status_debug("handle_get_per_commitment_point.1"); + if (!fromwire_hsmd_get_per_commitment_point(msg_in, &n)) return hsmd_status_malformed_request(c, msg_in); + hsmd_status_debug("handle_get_per_commitment_point.2"); + get_channel_seed(&c->id, c->dbid, &channel_seed); if (!derive_shaseed(&channel_seed, &shaseed)) return hsmd_status_bad_request(c, msg_in, "bad derive_shaseed"); + hsmd_status_debug("handle_get_per_commitment_point.3"); + if (!per_commit_point(&shaseed, &per_commitment_point, n)) return hsmd_status_bad_request_fmt( c, msg_in, "bad per_commit_point %" PRIu64, n); + hsmd_status_debug("handle_get_per_commitment_point.4"); + if (n >= 2) { old_secret = tal(tmpctx, struct secret); if (!per_commit_secret(&shaseed, old_secret, n - 2)) { @@ -1143,11 +1151,17 @@ static u8 *handle_get_per_commitment_point(struct hsmd_client *c, const u8 *msg_ } else old_secret = NULL; + hsmd_status_debug("handle_get_per_commitment_point.5"); + /*~ hsm_client_wire.csv marks the secret field here optional, so it only * gets included if the parameter is non-NULL. We violate 80 columns * pretty badly here, but it's a recommendation not a religion. */ - return towire_hsmd_get_per_commitment_point_reply( + u8* res = towire_hsmd_get_per_commitment_point_reply( NULL, &per_commitment_point, old_secret); + + hsmd_status_debug("handle_get_per_commitment_point.6"); + + return res; } /*~ lightningd asks us to sign a withdrawal; same as above but in theory diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index ae57e891a77b..0d1ae0e8acee 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -245,8 +246,8 @@ static void handle_splice_state_error(struct lightningd *ld, } static void handle_splice_feerate_error(struct lightningd *ld, - struct channel *channel, - const u8 *msg) + struct channel *channel, + const u8 *msg) { struct splice_command *cc; struct amount_msat fee; @@ -283,6 +284,123 @@ static void handle_splice_feerate_error(struct lightningd *ld, } } +static void handle_splice_lease_error(struct lightningd *ld, + struct channel *channel, + const u8 *msg) +{ + struct splice_command *cc; + char *error_msg; + + if (!fromwire_channeld_splice_lease_error(tmpctx, msg, &error_msg)) { + channel_internal_error(channel, + "bad fromwire_channeld_splice_lease_error %s", + tal_hex(channel, msg)); + return; + } + + cc = splice_command_for_chan(ld, channel); + if (cc) { + was_pending(command_fail(cc->cmd, + SPLICE_LEASE_ERROR, + "%s", error_msg)); + } + else { + log_peer_unusual(ld->log, &channel->peer->id, "Lease fails %s", + error_msg); + } +} + +static void handle_splice_abort(struct lightningd *ld, + struct channel *channel, + const u8 *msg) +{ + struct splice_command *cc; + struct peer *peer = channel->peer; + bool did_i_abort; + struct bitcoin_outpoint *outpoint; + struct channel_inflight *inflight; + char *reason; + u8 *error; + int fds[2]; + + if (!fromwire_channeld_splice_abort(tmpctx, msg, &did_i_abort, + &outpoint, &reason)) { + channel_internal_error(channel, + "bad fromwire_channeld_splice_abort %s", + tal_hex(channel, msg)); + return; + } + + if (outpoint) { + inflight = list_tail(&channel->inflights, + struct channel_inflight, + list); + + if (!bitcoin_outpoint_eq(outpoint, + &inflight->funding->outpoint)) + channel_internal_error(channel, + "abort outpoint %s does not" + " match ours %s", + type_to_string(tmpctx, + struct bitcoin_outpoint, + outpoint), + type_to_string(tmpctx, + struct bitcoin_outpoint, + &inflight->funding->outpoint)); + + wallet_inflight_del(ld->wallet, channel, inflight); + } + + cc = splice_command_for_chan(ld, channel); + if (cc) + was_pending(command_fail(cc->cmd, SPLICE_ABORT, "%s", reason)); + else + log_peer_unusual(ld->log, &peer->id, "Splice aborted" + " %s", reason); + + log_debug(channel->log, + "Restarting channeld after tx_abort on %s channel", + channel_state_name(channel)); + + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { + log_broken(channel->log, + "Failed to create socketpair: %s", + strerror(errno)); + + error = towire_warningfmt(tmpctx, &channel->cid, + "Trouble in paradise?"); + log_peer_debug(ld->log, &channel->peer->id, + "Telling connectd to send error %s", + tal_hex(tmpctx, error)); + /* Get connectd to send error and close. */ + subd_send_msg(ld->connectd, + take(towire_connectd_peer_final_msg(NULL, + &peer->id, + peer->connectd_counter, + error))); + return; + } + log_debug(channel->log, "made the socket pair"); + + // try expilcity killing the old channeld + fprintf(stderr, "tx_abort calls peer_start_channeld\n"); + if (peer_start_channeld(channel, new_peer_fd(tmpctx, fds[0]), NULL, + true, false, NULL)) { + log_info(channel->log, "Sending the peer fd to connectd"); + subd_send_msg(ld->connectd, + take(towire_connectd_peer_connect_subd(NULL, + &peer->id, + peer->connectd_counter, + &channel->cid))); + subd_send_fd(ld->connectd, fds[1]); + log_info(channel->log, "Sent the peer fd to channeld"); + } + else { + log_info(channel->log, "peer_start_channeld failed"); + close(fds[1]); + } +} + /* When channeld finishes processing the `splice_init` command, this is called */ static void handle_splice_confirmed_init(struct lightningd *ld, struct channel *channel, @@ -1387,9 +1505,15 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_SPLICE_FEERATE_ERROR: handle_splice_feerate_error(sd->ld, sd->channel, msg); break; + case WIRE_CHANNELD_SPLICE_LEASE_ERROR: + handle_splice_lease_error(sd->ld, sd->channel, msg); + break; case WIRE_CHANNELD_SPLICE_FUNDING_ERROR: handle_splice_funding_error(sd->ld, sd->channel, msg); break; + case WIRE_CHANNELD_SPLICE_ABORT: + handle_splice_abort(sd->ld, sd->channel, msg); + break; case WIRE_CHANNELD_SPLICE_STATE_ERROR: handle_splice_state_error(sd->ld, sd->channel, msg); break; @@ -1453,7 +1577,8 @@ bool peer_start_channeld(struct channel *channel, struct peer_fd *peer_fd, const u8 *fwd_msg, bool reconnected, - bool reestablish_only) + bool reestablish_only, + const int *hsmfd_in) { u8 *initmsg; int hsmfd; @@ -1471,6 +1596,8 @@ bool peer_start_channeld(struct channel *channel, struct inflight **inflights; struct bitcoin_txid txid; + fprintf(stderr, "peer_start_channeld calls hsm_get_client_fd\n"); + hsmfd = hsm_get_client_fd(ld, &channel->peer->id, channel->dbid, HSM_PERM_SIGN_GOSSIP @@ -2031,6 +2158,8 @@ static struct command_result *json_splice_init(struct command *cmd, s64 *relative_amount; u32 *feerate_per_kw; bool *force_feerate; + struct amount_sat *request_amt; + struct lease_rates *rates; u8 *msg; if (!param_check(cmd, buffer, params, @@ -2039,6 +2168,8 @@ static struct command_result *json_splice_init(struct command *cmd, p_opt("initialpsbt", param_psbt, &initialpsbt), p_opt("feerate_per_kw", param_feerate, &feerate_per_kw), p_opt_def("force_feerate", param_bool, &force_feerate, false), + p_opt_def("request_amt", param_sat, &request_amt, AMOUNT_SAT(0)), + p_opt("compact_lease", param_lease_hex, &rates), NULL)) return command_param_failed(); @@ -2056,6 +2187,11 @@ static struct command_result *json_splice_init(struct command *cmd, *feerate_per_kw = opening_feerate(cmd->ld->topology); } + if (!amount_sat_zero(*request_amt) && !rates) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Must pass in 'compact_lease' if requesting" + " funds from peer"); + if (!initialpsbt) initialpsbt = create_psbt(cmd, 0, 0, 0); if (!validate_psbt(initialpsbt)) @@ -2075,7 +2211,10 @@ static struct command_result *json_splice_init(struct command *cmd, cc->channel = channel; msg = towire_channeld_splice_init(NULL, initialpsbt, *relative_amount, - *feerate_per_kw, *force_feerate); + *feerate_per_kw, *force_feerate, + amount_sat_zero(*request_amt) ? + NULL : request_amt, + rates); subd_send_msg(channel->owner, take(msg)); return command_still_pending(cmd); diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index d8c52bdb1141..fbda1fb5eaa3 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -14,7 +14,8 @@ bool peer_start_channeld(struct channel *channel, struct peer_fd *peer_fd, const u8 *fwd_msg, bool reconnected, - bool reestablish_only); + bool reestablish_only, + const int *hsm_fd); /* Send message to channeld (if connected) to tell it about depth * c.f. dualopen_tell_depth! */ diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 5de6d1138336..7419d2bbf17f 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -1994,7 +1994,7 @@ static void handle_channel_locked(struct subd *dualopend, channel_watch_funding(dualopend->ld, channel); /* FIXME: LND sigs/update_fee msgs? */ - peer_start_channeld(channel, peer_fd, NULL, false, NULL); + peer_start_channeld(channel, peer_fd, NULL, false, NULL, NULL); return; } diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 0acc6f1b2d58..6e52edb58390 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -29,6 +29,7 @@ #include #include #include +#include #include void json_add_uncommitted_channel(struct json_stream *response, @@ -454,7 +455,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, wallet_penalty_base_add(ld->wallet, channel->dbid, pbase); funding_success(channel); - peer_start_channeld(channel, peer_fd, NULL, false, NULL); + fprintf(stderr, "opening_funder_finished calls peer_start_channeld\n"); + peer_start_channeld(channel, peer_fd, NULL, false, NULL, NULL); cleanup: /* Frees fc too */ @@ -558,7 +560,8 @@ static void opening_fundee_finished(struct subd *openingd, wallet_penalty_base_add(ld->wallet, channel->dbid, pbase); /* On to normal operation! */ - peer_start_channeld(channel, peer_fd, fwd_msg, false, NULL); + fprintf(stderr, "opening_fundee_finished calls peer_start_channeld\n"); + peer_start_channeld(channel, peer_fd, fwd_msg, false, NULL, NULL); tal_free(uc); return; diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index cabac68dc439..0231c1aa8455 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -467,6 +467,8 @@ void channel_errmsg(struct channel *channel, /* Clean up any in-progress open attempts */ channel_cleanup_commands(channel, desc); + /* DTODO: should i move all the txabort handling to here? */ + if (channel_state_uncommitted(channel->state)) { log_info(channel->log, "%s", "Unsaved peer failed." " Deleting channel."); @@ -1283,10 +1285,11 @@ static void connect_activate_subd(struct lightningd *ld, struct channel *channel "Trouble in paradise?"); goto send_error; } + fprintf(stderr, "CLOSINGD_SIGEXCHANGE calls peer_start_channeld\n"); if (peer_start_channeld(channel, new_peer_fd(tmpctx, fds[0]), NULL, true, - NULL)) { + NULL, NULL)) { goto tell_connectd; } close(fds[1]); @@ -1666,7 +1669,7 @@ void peer_spoke(struct lightningd *ld, const u8 *msg) "Trouble in paradise?"); goto send_error; } - if (peer_start_channeld(channel, new_peer_fd(tmpctx, fds[0]), NULL, true, true)) { + if (peer_start_channeld(channel, new_peer_fd(tmpctx, fds[0]), NULL, true, true, NULL)) { goto tell_connectd; } /* FIXME: Send informative error? */ diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index de7a800fe3d8..893ecbfeacf3 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -850,7 +850,8 @@ bool peer_start_channeld(struct channel *channel UNNEEDED, struct peer_fd *peer_fd UNNEEDED, const u8 *fwd_msg UNNEEDED, bool reconnected UNNEEDED, - bool reestablish_only UNNEEDED) + bool reestablish_only UNNEEDED, + const int *hsmd_fd UNNEEDED) { fprintf(stderr, "peer_start_channeld called!\n"); abort(); } /* Generated stub for peer_start_dualopend */ bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, diff --git a/tests/fuzz/fuzz-wire-splice.c b/tests/fuzz/fuzz-wire-splice.c index 2b2adda94dbe..368d18b197ae 100644 --- a/tests/fuzz/fuzz-wire-splice.c +++ b/tests/fuzz/fuzz-wire-splice.c @@ -10,29 +10,47 @@ struct splice { u32 funding_feerate_perkw; u32 locktime; struct pubkey funding_pubkey; + struct tlv_splice_tlvs *tlvs; }; static void *encode(const tal_t *ctx, const struct splice *s) { return towire_splice(ctx, &s->channel_id, &s->chain_hash, s->relative_satoshis, s->funding_feerate_perkw, - s->locktime, &s->funding_pubkey); + s->locktime, &s->funding_pubkey, s->tlvs); } static struct splice *decode(const tal_t *ctx, const void *p) { struct splice *s = tal(ctx, struct splice); - if (fromwire_splice(p, &s->channel_id, &s->chain_hash, + if (fromwire_splice(s, p, &s->channel_id, &s->chain_hash, &s->relative_satoshis, &s->funding_feerate_perkw, - &s->locktime, &s->funding_pubkey)) + &s->locktime, &s->funding_pubkey, &s->tlvs)) return s; return tal_free(s); } +static bool request_funds_equal(const struct tlv_splice_tlvs_request_funds *x, + const struct tlv_splice_tlvs_request_funds *y) +{ + if (!x && !y) + return true; + if (!x || !y) + return false; + if (x->requested_sats != y->requested_sats) + return false; + + return x->blockheight == y->blockheight; +} + static bool equal(const struct splice *x, const struct splice *y) { - return memcmp(x, y, sizeof(*x)) == 0; + if (!request_funds_equal(x->tlvs->request_funds, + y->tlvs->request_funds)) + return false; + + return memcmp(x, y, sizeof(*x) - sizeof(struct tlv_splice_tlvs*)) == 0; } void run(const u8 *data, size_t size) diff --git a/tests/fuzz/fuzz-wire-splice_ack.c b/tests/fuzz/fuzz-wire-splice_ack.c index 2095ab4037df..0e50175fb48c 100644 --- a/tests/fuzz/fuzz-wire-splice_ack.c +++ b/tests/fuzz/fuzz-wire-splice_ack.c @@ -8,27 +8,46 @@ struct splice_ack { struct bitcoin_blkid chain_hash; s64 relative_satoshis; struct pubkey funding_pubkey; + struct tlv_splice_ack_tlvs *tlvs; }; static void *encode(const tal_t *ctx, const struct splice_ack *s) { return towire_splice_ack(ctx, &s->channel_id, &s->chain_hash, - s->relative_satoshis, &s->funding_pubkey); + s->relative_satoshis, &s->funding_pubkey, + NULL); } static struct splice_ack *decode(const tal_t *ctx, const void *p) { struct splice_ack *s = tal(ctx, struct splice_ack); - if (fromwire_splice_ack(p, &s->channel_id, &s->chain_hash, - &s->relative_satoshis, &s->funding_pubkey)) + if (fromwire_splice_ack(s, p, &s->channel_id, &s->chain_hash, + &s->relative_satoshis, &s->funding_pubkey, + NULL)) return s; return tal_free(s); } +static bool will_fund_equal(const struct tlv_splice_tlvs_will_fund *x, + const struct tlv_splice_tlvs_will_fund *y) +{ + if (!x && !y) + return true; + if (!x || !y) + return false; + if (memcmp(x->signature, y->signature, sizeof(*x->signature)) != 0) + return false; + + return memcmp(x->lease_rates, y->lease_rates, sizeof(*x->lease_rates)) == 0; +} + static bool equal(const struct splice_ack *x, const struct splice_ack *y) { - return memcmp(x, y, sizeof(*x)) == 0; + if (!will_fund_equal(x->tlvs->will_fund, y->tlvs->will_fund)) + return false; + + return memcmp(x, y, sizeof(*x) - sizeof(struct tlv_splice_ack_tlvs*)) == 0; } void run(const u8 *data, size_t size) diff --git a/tests/test_splicing.py b/tests/test_splicing.py index 78e480571ac8..912c307b36b4 100644 --- a/tests/test_splicing.py +++ b/tests/test_splicing.py @@ -1,5 +1,4 @@ from fixtures import * # noqa: F401,F403 -from flaky import flaky from pyln.client import RpcError import pytest import unittest @@ -12,8 +11,7 @@ @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') -@flaky -def test_splice(node_factory, bitcoind): +def test_splicea(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) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 42cec47f1ef0..d4f4296f1638 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -827,7 +827,8 @@ bool peer_start_channeld(struct channel *channel UNNEEDED, struct peer_fd *peer_fd UNNEEDED, const u8 *fwd_msg UNNEEDED, bool reconnected UNNEEDED, - bool reestablish_only UNNEEDED) + bool reestablish_only UNNEEDED, + const int *hsm_fd) { fprintf(stderr, "peer_start_channeld called!\n"); abort(); } /* Generated stub for peer_start_dualopend */ bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, diff --git a/wallet/wallet.c b/wallet/wallet.c index e2e7986594a6..de0c90e9198c 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1264,6 +1264,24 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight) tal_free(stmt); } +void wallet_inflight_del(struct wallet *w, struct channel *chan, + struct channel_inflight *inflight) +{ + struct db_stmt *stmt; + + /* Remove all the inflights for the channel */ + stmt = db_prepare_v2(w->db, SQL("DELETE FROM channel_funding_inflights" + " WHERE channel_id = ?" + " AND funding_tx_id = ?" + " AND funding_tx_outnum = ?")); + db_bind_u64(stmt, chan->dbid); + db_bind_txid(stmt, &inflight->funding->outpoint.txid); + db_bind_int(stmt, inflight->funding->outpoint.n); + db_exec_prepared_v2(take(stmt)); + + tal_free(inflight); +} + void wallet_inflight_save(struct wallet *w, struct channel_inflight *inflight) { diff --git a/wallet/wallet.h b/wallet/wallet.h index 2e8138d5fcfb..5a54907926f3 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -620,6 +620,12 @@ void wallet_channel_insert(struct wallet *w, struct channel *chan); */ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight); +/** + * Delete an inflight transaction for a channel + */ +void wallet_inflight_del(struct wallet *w, struct channel *chan, + struct channel_inflight *inflight); + /** * Update an existing inflight channel transaction */ diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 063d8cf07bd5..e55c9bd349e6 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -213,11 +213,19 @@ msgdata,splice,relative_satoshis,s64, msgdata,splice,funding_feerate_perkw,u32, msgdata,splice,locktime,u32, msgdata,splice,funding_pubkey,point, +msgdata,splice,tlvs,splice_tlvs, +tlvtype,splice_tlvs,request_funds,3 +tlvdata,splice_tlvs,request_funds,requested_sats,u64, +tlvdata,splice_tlvs,request_funds,blockheight,u32, msgtype,splice_ack,76 msgdata,splice_ack,channel_id,channel_id, msgdata,splice_ack,chain_hash,chain_hash, msgdata,splice_ack,relative_satoshis,s64, msgdata,splice_ack,funding_pubkey,point, +msgdata,splice_ack,tlvs,splice_ack_tlvs, +tlvtype,splice_ack_tlvs,will_fund,3 +tlvdata,splice_ack_tlvs,will_fund,signature,signature, +tlvdata,splice_ack_tlvs,will_fund,lease_rates,lease_rates, msgtype,splice_locked,77, msgdata,splice_locked,channel_id,channel_id, msgtype,shutdown,38 diff --git a/wire/wire_sync.c b/wire/wire_sync.c index ce2107b93c2b..9e6d07918fd2 100644 --- a/wire/wire_sync.c +++ b/wire/wire_sync.c @@ -19,19 +19,26 @@ bool wire_sync_write(int fd, const void *msg TAKES) return ret; } +int wire_sync_read_fail_reason = 0; + u8 *wire_sync_read(const tal_t *ctx, int fd) { wire_len_t len; u8 *msg; - if (!read_all(fd, &len, sizeof(len))) + if (!read_all(fd, &len, sizeof(len))) { + wire_sync_read_fail_reason = 1; return NULL; + } if (wirelen_to_cpu(len) >= WIRE_LEN_LIMIT) { + wire_sync_read_fail_reason = 2; errno = E2BIG; return NULL; } msg = tal_arr(ctx, u8, wirelen_to_cpu(len)); - if (!read_all(fd, msg, wirelen_to_cpu(len))) + if (!read_all(fd, msg, wirelen_to_cpu(len))) { + wire_sync_read_fail_reason = 3; return tal_free(msg); + } return msg; }