From ec5106738a28746b1a4a961e902a03400794263c Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Tue, 8 Oct 2019 11:07:44 -0500 Subject: [PATCH 01/45] walletrpc: free utx on unsuccessful broadcast If we can't broadcast the transaction, we free the utx anyway. You're going to have to start over regardless. --- wallet/walletrpc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 8a9cbba9576b..863a0b3d21fc 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -71,6 +71,7 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED, "Error broadcasting transaction: %s. Unsent tx discarded", output)); } + tal_free(utx); } /* Signs the tx, broadcasts it: broadcast calls wallet_withdrawal_broadcast */ From 4938ac6398fbe80af9ae3e5c9ae58cd7de78a9ad Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 18 Sep 2019 19:04:17 -0500 Subject: [PATCH 02/45] amount: helper method for adding sats to an msat amount see title. --- common/amount.c | 12 ++++++++++++ common/amount.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/common/amount.c b/common/amount.c index 7bb2e6d40096..071198fbd9b9 100644 --- a/common/amount.c +++ b/common/amount.c @@ -278,6 +278,18 @@ WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val, return amount_msat_sub(val, msata, b); } +WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val, + struct amount_msat a, + struct amount_sat b) +{ + struct amount_msat msatb; + + if (!amount_sat_to_msat(&msatb, b)) + return false; + + return amount_msat_add(val, a, msatb); +} + bool amount_sat_eq(struct amount_sat a, struct amount_sat b) { return a.satoshis == b.satoshis; diff --git a/common/amount.h b/common/amount.h index c401d272e8b7..f5d9ef7f123a 100644 --- a/common/amount.h +++ b/common/amount.h @@ -70,6 +70,9 @@ WARN_UNUSED_RESULT bool amount_sat_sub(struct amount_sat *val, WARN_UNUSED_RESULT bool amount_msat_sub_sat(struct amount_msat *val, struct amount_msat a, struct amount_sat b); +WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val, + struct amount_msat a, + struct amount_sat b); WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val, struct amount_sat a, struct amount_msat b); From 302305035299b2adfbf8372b70c380fd753385e2 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 9 Sep 2019 11:11:24 -0500 Subject: [PATCH 03/45] df: rename 'funder' to 'opener' Previously we've used the term 'funder' to refer to the peer paying the fees for a transaction; v2 of openchannel will make this no longer true. Instead we rename this to 'opener', or the peer sending the 'open_channel' message, since this will be universally true in a dual-funding world. --- channeld/channel_wire.csv | 2 +- channeld/channeld.c | 28 +++++++------- channeld/commit_tx.c | 4 +- channeld/commit_tx.h | 4 +- channeld/full_channel.c | 64 ++++++++++++++++---------------- channeld/full_channel.h | 12 +++--- channeld/test/run-commit_tx.c | 4 +- channeld/test/run-full_channel.c | 2 +- closingd/closingd.c | 34 ++++++++--------- common/initial_channel.c | 14 +++---- common/initial_channel.h | 6 +-- common/initial_commit_tx.c | 18 ++++----- lightningd/channel.c | 6 +-- lightningd/channel.h | 4 +- lightningd/channel_control.c | 6 +-- lightningd/closing_control.c | 2 +- lightningd/onchain_control.c | 2 +- lightningd/opening_control.c | 2 +- lightningd/peer_control.c | 10 ++--- lightningd/peer_htlcs.c | 4 +- onchaind/onchain_wire.csv | 2 +- onchaind/onchaind.c | 10 ++--- openingd/openingd.c | 36 +++++++++--------- wallet/wallet.c | 2 +- 24 files changed, 139 insertions(+), 139 deletions(-) diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 5744de929071..9725269b5fe1 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -22,7 +22,7 @@ msgdata,channel_init,remote_fundingkey,pubkey, msgdata,channel_init,remote_basepoints,basepoints, msgdata,channel_init,remote_per_commit,pubkey, msgdata,channel_init,old_remote_per_commit,pubkey, -msgdata,channel_init,funder,enum side, +msgdata,channel_init,opener,enum side, msgdata,channel_init,fee_base,u32, msgdata,channel_init,fee_proportional,u32, msgdata,channel_init,local_msatoshi,amount_msat, diff --git a/channeld/channeld.c b/channeld/channeld.c index 525d01d45d79..73bb364f1762 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -669,10 +669,10 @@ static void handle_peer_feechange(struct peer *peer, const u8 *msg) * - if the sender is not responsible for paying the Bitcoin fee: * - MUST fail the channel. */ - if (peer->channel->funder != REMOTE) + if (peer->channel->opener != REMOTE) peer_failed(peer->pps, &peer->channel_id, - "update_fee from non-funder?"); + "update_fee from non-opener?"); status_debug("update_fee %u, range %u-%u", feerate, peer->feerate_min, peer->feerate_max); @@ -1128,7 +1128,7 @@ static void send_commit(struct peer *peer) } /* If we wanted to update fees, do it now. */ - if (peer->channel->funder == LOCAL) { + if (peer->channel->opener == LOCAL) { u32 feerate, max = approx_max_feerate(peer->channel); feerate = peer->desired_feerate; @@ -1386,11 +1386,11 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) } /* We were supposed to check this was affordable as we go. */ - if (peer->channel->funder == REMOTE) { + if (peer->channel->opener == REMOTE) { status_debug("Feerates are %u/%u", peer->channel->view[LOCAL].feerate_per_kw, peer->channel->view[REMOTE].feerate_per_kw); - assert(can_funder_afford_feerate(peer->channel, + assert(can_opener_afford_feerate(peer->channel, peer->channel->view[LOCAL] .feerate_per_kw)); } @@ -1584,7 +1584,7 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) peer->old_remote_per_commit = peer->remote_per_commit; peer->remote_per_commit = next_per_commit; status_debug("revoke_and_ack %s: remote_per_commit = %s, old_remote_per_commit = %s", - side_to_str(peer->channel->funder), + side_to_str(peer->channel->opener), type_to_string(tmpctx, struct pubkey, &peer->remote_per_commit), type_to_string(tmpctx, struct pubkey, @@ -1992,7 +1992,7 @@ static void resend_commitment(struct peer *peer, const struct changed_htlc *last } /* Make sure they have the correct fee. */ - if (peer->channel->funder == LOCAL) { + if (peer->channel->opener == LOCAL) { msg = towire_update_fee(NULL, &peer->channel_id, channel_feerate(peer->channel, REMOTE)); sync_crypto_write(peer->pps, take(msg)); @@ -2519,7 +2519,7 @@ static void peer_reconnect(struct peer *peer, * even tell by seeing if fees are different (short of saving full fee * state in database) since it could be a tiny feechange, or two * feechanges which cancelled out. */ - if (peer->channel->funder == LOCAL) + if (peer->channel->opener == LOCAL) peer->channel->changes_pending[LOCAL] = true; peer_billboard(true, "Reconnected, and reestablished."); @@ -2687,7 +2687,7 @@ static void handle_feerates(struct peer *peer, const u8 *inmsg) * sufficient (by a significant margin) for timely processing of the * commitment transaction. */ - if (peer->channel->funder == LOCAL) { + if (peer->channel->opener == LOCAL) { peer->desired_feerate = feerate; start_commit_timer(peer); } else { @@ -2928,7 +2928,7 @@ static void init_channel(struct peer *peer) struct pubkey funding_pubkey[NUM_SIDES]; struct channel_config conf[NUM_SIDES]; struct bitcoin_txid funding_txid; - enum side funder; + enum side opener; enum htlc_state *hstates; struct fulfilled_htlc *fulfilled; enum side *fulfilled_sides; @@ -2964,7 +2964,7 @@ static void init_channel(struct peer *peer) &points[REMOTE], &peer->remote_per_commit, &peer->old_remote_per_commit, - &funder, + &opener, &peer->fee_base, &peer->fee_per_satoshi, &local_msat, @@ -3015,7 +3015,7 @@ static void init_channel(struct peer *peer) " next_idx_remote = %"PRIu64 " revocations_received = %"PRIu64 " feerates %u/%u (range %u-%u)", - side_to_str(funder), + side_to_str(opener), type_to_string(tmpctx, struct pubkey, &peer->remote_per_commit), type_to_string(tmpctx, struct pubkey, @@ -3063,7 +3063,7 @@ static void init_channel(struct peer *peer) &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], option_static_remotekey, - funder); + opener); if (!channel_force_htlcs(peer->channel, htlcs, hstates, fulfilled, fulfilled_sides, @@ -3091,7 +3091,7 @@ static void init_channel(struct peer *peer) &peer->node_ids[REMOTE]); /* Default desired feerate is the feerate we set for them last. */ - if (peer->channel->funder == LOCAL) + if (peer->channel->opener == LOCAL) peer->desired_feerate = feerate_per_kw[REMOTE]; /* from now we need keep watch over WIRE_CHANNEL_FUNDING_DEPTH */ diff --git a/channeld/commit_tx.c b/channeld/commit_tx.c index 2973cc16e5ab..a6d77abc0f07 100644 --- a/channeld/commit_tx.c +++ b/channeld/commit_tx.c @@ -80,7 +80,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, const struct bitcoin_txid *funding_txid, unsigned int funding_txout, struct amount_sat funding, - enum side funder, + enum side opener, u16 to_self_delay, const struct keyset *keyset, u32 feerate_per_kw, @@ -126,7 +126,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, * 3. Subtract this base fee from the funder (either `to_local` or * `to_remote`), with a floor of 0 (see [Fee Payment](#fee-payment)). */ - try_subtract_fee(funder, side, base_fee, &self_pay, &other_pay); + try_subtract_fee(opener, side, base_fee, &self_pay, &other_pay); #ifdef PRINT_ACTUAL_FEE { diff --git a/channeld/commit_tx.h b/channeld/commit_tx.h index 2ad7c72fac8d..6ccc006ad631 100644 --- a/channeld/commit_tx.h +++ b/channeld/commit_tx.h @@ -28,7 +28,7 @@ size_t commit_tx_num_untrimmed(const struct htlc **htlcs, * commit_tx: create (unsigned) commitment tx to spend the funding tx output * @ctx: context to allocate transaction and @htlc_map from. * @funding_txid, @funding_out, @funding: funding outpoint. - * @funder: is the LOCAL or REMOTE paying the fee? + * @opener: is the LOCAL or REMOTE paying the fee? * @keyset: keys derived for this commit tx. * @feerate_per_kw: feerate to use * @dust_limit: dust limit below which to trim outputs. @@ -48,7 +48,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx, const struct bitcoin_txid *funding_txid, unsigned int funding_txout, struct amount_sat funding, - enum side funder, + enum side opener, u16 to_self_delay, const struct keyset *keyset, u32 feerate_per_kw, diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 94bb0a7c4298..799296543a0f 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -47,7 +47,7 @@ struct channel *new_full_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, - enum side funder) + enum side opener) { struct channel *channel = new_initial_channel(ctx, chain_hash, @@ -63,7 +63,7 @@ struct channel *new_full_channel(const tal_t *ctx, local_funding_pubkey, remote_funding_pubkey, option_static_remotekey, - funder); + opener); if (channel) { /* Feerates can be different. */ @@ -283,7 +283,7 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx, txs = tal_arr(ctx, struct bitcoin_tx *, 1); txs[0] = commit_tx( ctx, chainparams, &channel->funding_txid, channel->funding_txout, - channel->funding, channel->funder, + channel->funding, channel->opener, channel->config[!side].to_self_delay, &keyset, channel->view[side].feerate_per_kw, channel->config[side].dust_limit, channel->view[side].owed[side], @@ -462,7 +462,7 @@ static enum channel_add_err add_htlc(struct channel *channel, */ /* Also we should not add more htlc's than sender or recipient * configured. This mitigates attacks in which a peer can force the - * funder of the channel to pay unnecessary onchain fees during a fee + * opener of the channel to pay unnecessary onchain fees during a fee * spike with large commitment transactions. */ min_concurrent_htlcs = channel->config[recipient].max_accepted_htlcs; @@ -536,7 +536,7 @@ static enum channel_add_err add_htlc(struct channel *channel, &balance)) return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; - if (channel->funder == sender) { + if (channel->opener == sender) { if (amount_msat_less_sat(balance, fee)) { status_debug("Cannot afford fee %s with %s above reserve", type_to_string(tmpctx, struct amount_sat, @@ -547,12 +547,12 @@ static enum channel_add_err add_htlc(struct channel *channel, } } - /* Try not to add a payment which will take funder into fees + /* Try not to add a payment which will take opener into fees * on either our side or theirs. */ if (sender == LOCAL) { if (!get_room_above_reserve(channel, view, adding, removing, - channel->funder, + channel->opener, &balance)) return CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED; /* Should be able to afford both their own commit tx @@ -562,7 +562,7 @@ static enum channel_add_err add_htlc(struct channel *channel, committed, adding, removing, - channel->funder); + channel->opener); /* set fee output pointer if given */ if (htlc_fee && amount_sat_greater(fee, *htlc_fee)) *htlc_fee = fee; @@ -580,7 +580,7 @@ static enum channel_add_err add_htlc(struct channel *channel, committed, adding, removing, - !channel->funder); + !channel->opener); /* set fee output pointer if given */ if (htlc_fee && amount_sat_greater(fee, *htlc_fee)) *htlc_fee = fee; @@ -876,7 +876,7 @@ u32 approx_max_feerate(const struct channel *channel) struct amount_sat avail; const struct htlc **committed, **adding, **removing; - gather_htlcs(tmpctx, channel, !channel->funder, + gather_htlcs(tmpctx, channel, !channel->opener, &committed, &removing, &adding); /* Assume none are trimmed; this gives lower bound on feerate. */ @@ -907,28 +907,28 @@ u32 approx_max_feerate(const struct channel *channel) /* We should never go below reserve. */ if (!amount_sat_sub(&avail, - amount_msat_to_sat_round_down(channel->view[!channel->funder].owed[channel->funder]), - channel->config[!channel->funder].channel_reserve)) + amount_msat_to_sat_round_down(channel->view[!channel->opener].owed[channel->opener]), + channel->config[!channel->opener].channel_reserve)) avail = AMOUNT_SAT(0); return avail.satoshis / weight * 1000; /* Raw: once-off reverse feerate*/ } -bool can_funder_afford_feerate(const struct channel *channel, u32 feerate_per_kw) +bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw) { struct amount_sat needed, fee; - struct amount_sat dust_limit = channel->config[!channel->funder].dust_limit; + struct amount_sat dust_limit = channel->config[!channel->opener].dust_limit; size_t untrimmed; const struct htlc **committed, **adding, **removing; - gather_htlcs(tmpctx, channel, !channel->funder, + gather_htlcs(tmpctx, channel, !channel->opener, &committed, &removing, &adding); untrimmed = commit_tx_num_untrimmed(committed, feerate_per_kw, dust_limit, - !channel->funder) + !channel->opener) + commit_tx_num_untrimmed(adding, feerate_per_kw, dust_limit, - !channel->funder) + !channel->opener) - commit_tx_num_untrimmed(removing, feerate_per_kw, dust_limit, - !channel->funder); + !channel->opener); fee = commit_tx_base_fee(feerate_per_kw, untrimmed); @@ -938,39 +938,39 @@ bool can_funder_afford_feerate(const struct channel *channel, u32 feerate_per_kw * node's current commitment transaction: * - SHOULD fail the channel */ - /* Note: sender == funder */ + /* Note: sender == opener */ /* How much does it think it has? Must be >= reserve + fee */ if (!amount_sat_add(&needed, fee, - channel->config[!channel->funder].channel_reserve)) + channel->config[!channel->opener].channel_reserve)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Cannot add fee %s and reserve %s", type_to_string(tmpctx, struct amount_sat, &fee), type_to_string(tmpctx, struct amount_sat, - &channel->config[!channel->funder].channel_reserve)); + &channel->config[!channel->opener].channel_reserve)); status_debug("We need %s at feerate %u for %zu untrimmed htlcs: we have %s/%s", type_to_string(tmpctx, struct amount_sat, &needed), feerate_per_kw, untrimmed, type_to_string(tmpctx, struct amount_msat, - &channel->view[LOCAL].owed[channel->funder]), + &channel->view[LOCAL].owed[channel->opener]), type_to_string(tmpctx, struct amount_msat, - &channel->view[REMOTE].owed[channel->funder])); - return amount_msat_greater_eq_sat(channel->view[!channel->funder].owed[channel->funder], + &channel->view[REMOTE].owed[channel->opener])); + return amount_msat_greater_eq_sat(channel->view[!channel->opener].owed[channel->opener], needed); } bool channel_update_feerate(struct channel *channel, u32 feerate_per_kw) { - if (!can_funder_afford_feerate(channel, feerate_per_kw)) + if (!can_opener_afford_feerate(channel, feerate_per_kw)) return false; status_debug("Setting %s feerate to %u", - side_to_str(!channel->funder), feerate_per_kw); + side_to_str(!channel->opener), feerate_per_kw); - channel->view[!channel->funder].feerate_per_kw = feerate_per_kw; - channel->changes_pending[!channel->funder] = true; + channel->view[!channel->opener].feerate_per_kw = feerate_per_kw; + channel->changes_pending[!channel->opener] = true; return true; } @@ -1018,8 +1018,8 @@ bool channel_rcvd_revoke_and_ack(struct channel *channel, if (change & HTLC_LOCAL_F_PENDING) channel->changes_pending[LOCAL] = true; - /* For funder, ack also means time to apply new feerate locally. */ - if (channel->funder == LOCAL && + /* For opener, ack also means time to apply new feerate locally. */ + if (channel->opener == LOCAL && (channel->view[LOCAL].feerate_per_kw != channel->view[REMOTE].feerate_per_kw)) { status_debug("Applying feerate %u to LOCAL", @@ -1069,8 +1069,8 @@ bool channel_sending_revoke_and_ack(struct channel *channel) if (change & HTLC_REMOTE_F_PENDING) channel->changes_pending[REMOTE] = true; - /* For non-funder, sending ack means we apply any fund changes to them */ - if (channel->funder == REMOTE + /* For non-opener, sending ack means we apply any fund changes to them */ + if (channel->opener == REMOTE && (channel->view[LOCAL].feerate_per_kw != channel->view[REMOTE].feerate_per_kw)) { status_debug("Applying feerate %u to REMOTE", diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 01d4ce1607c3..01e47de4b2cd 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -25,7 +25,7 @@ * @local_fundingkey: local funding key * @remote_fundingkey: remote funding key * @option_static_remotekey: use `option_static_remotekey`. - * @funder: which side initiated it. + * @opener: which side initiated it. * * Returns state, or NULL if malformed. */ @@ -44,7 +44,7 @@ struct channel *new_full_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, - enum side funder); + enum side opener); /** * channel_txs: Get the current commitment and htlc txs for the channel. @@ -152,7 +152,7 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, struct htlc **htlcp); /** - * approx_max_feerate: what's the max funder could raise fee rate to? + * approx_max_feerate: what's the max opener could raise fee rate to? * @channel: The channel state * * This is not exact! To check if their offer is valid, try @@ -161,14 +161,14 @@ enum channel_remove_err channel_fulfill_htlc(struct channel *channel, u32 approx_max_feerate(const struct channel *channel); /** - * can_funder_afford_feerate: could the funder pay the fee? + * can_opener_afford_feerate: could the opener pay the fee? * @channel: The channel state * @feerate: The feerate in satoshi per 1000 bytes. */ -bool can_funder_afford_feerate(const struct channel *channel, u32 feerate); +bool can_opener_afford_feerate(const struct channel *channel, u32 feerate); /** - * channel_update_feerate: Change fee rate on non-funder side. + * channel_update_feerate: Change fee rate on non-opener side. * @channel: The channel * @feerate_per_kw: fee in satoshi per 1000 bytes. * diff --git a/channeld/test/run-commit_tx.c b/channeld/test/run-commit_tx.c index 94169ee5826c..e558eaee22c8 100644 --- a/channeld/test/run-commit_tx.c +++ b/channeld/test/run-commit_tx.c @@ -936,7 +936,7 @@ int main(void) tx = newtx; } while (tx->wtx->num_outputs > 1); - /* Now make sure we cover case where funder can't afford the fee; + /* Now make sure we cover case where opener can't afford the fee; * its output cannot go negative! */ for (;;) { struct amount_sat base_fee @@ -957,7 +957,7 @@ int main(void) assert(feerate_per_kw == 9651936); printf("\n" - "name: commitment tx with fee greater than funder amount\n" + "name: commitment tx with fee greater than opener amount\n" "to_local_msat: %"PRIu64"\n" "to_remote_msat: %"PRIu64"\n" "local_feerate_per_kw: %u\n", diff --git a/channeld/test/run-full_channel.c b/channeld/test/run-full_channel.c index e075366349c5..ed38cb907820 100644 --- a/channeld/test/run-full_channel.c +++ b/channeld/test/run-full_channel.c @@ -310,7 +310,7 @@ static void update_feerate(struct channel *channel, u32 feerate) ret = channel_update_feerate(channel, feerate); assert(ret); - if (channel->funder == LOCAL) { + if (channel->opener == LOCAL) { ret = channel_sending_commit(channel, NULL); assert(ret); ret = channel_rcvd_revoke_and_ack(channel, NULL); diff --git a/closingd/closingd.c b/closingd/closingd.c index 04b35438845f..86da8083713d 100644 --- a/closingd/closingd.c +++ b/closingd/closingd.c @@ -39,7 +39,7 @@ static struct bitcoin_tx *close_tx(const tal_t *ctx, unsigned int funding_txout, struct amount_sat funding, const struct amount_sat out[NUM_SIDES], - enum side funder, + enum side opener, struct amount_sat fee, struct amount_sat dust_limit) { @@ -48,7 +48,7 @@ static struct bitcoin_tx *close_tx(const tal_t *ctx, out_minus_fee[LOCAL] = out[LOCAL]; out_minus_fee[REMOTE] = out[REMOTE]; - if (!amount_sat_sub(&out_minus_fee[funder], out[funder], fee)) + if (!amount_sat_sub(&out_minus_fee[opener], out[opener], fee)) peer_failed(pps, channel_id, "Funder cannot afford fee %s (%s and %s)", type_to_string(tmpctx, struct amount_sat, &fee), @@ -242,7 +242,7 @@ static void send_offer(struct per_peer_state *pps, unsigned int funding_txout, struct amount_sat funding, const struct amount_sat out[NUM_SIDES], - enum side funder, + enum side opener, struct amount_sat our_dust_limit, struct amount_sat fee_to_offer) { @@ -262,7 +262,7 @@ static void send_offer(struct per_peer_state *pps, funding_txout, funding, out, - funder, fee_to_offer, our_dust_limit); + opener, fee_to_offer, our_dust_limit); /* BOLT #3: * @@ -320,7 +320,7 @@ receive_offer(struct per_peer_state *pps, unsigned int funding_txout, struct amount_sat funding, const struct amount_sat out[NUM_SIDES], - enum side funder, + enum side opener, struct amount_sat our_dust_limit, struct amount_sat min_fee_to_accept, struct bitcoin_txid *closing_txid) @@ -371,7 +371,7 @@ receive_offer(struct per_peer_state *pps, funding_txid, funding_txout, funding, - out, funder, received_fee, our_dust_limit); + out, opener, received_fee, our_dust_limit); if (!check_tx_sig(tx, 0, NULL, funding_wscript, &funding_pubkey[REMOTE], &their_sig)) { @@ -379,7 +379,7 @@ receive_offer(struct per_peer_state *pps, struct bitcoin_tx *trimmed; struct amount_sat trimming_out[NUM_SIDES]; - if (funder == REMOTE) + if (opener == REMOTE) trimming_out[REMOTE] = received_fee; else trimming_out[REMOTE] = AMOUNT_SAT(0); @@ -401,7 +401,7 @@ receive_offer(struct per_peer_state *pps, funding_txout, funding, trimming_out, - funder, received_fee, our_dust_limit); + opener, received_fee, our_dust_limit); if (!trimmed || !check_tx_sig(trimmed, 0, NULL, funding_wscript, &funding_pubkey[REMOTE], &their_sig)) { @@ -568,7 +568,7 @@ int main(int argc, char *argv[]) struct amount_sat our_dust_limit; struct amount_sat min_fee_to_accept, commitment_fee, offer[NUM_SIDES]; struct feerange feerange; - enum side funder; + enum side opener; u8 *scriptpubkey[NUM_SIDES], *funding_wscript; struct channel_id channel_id; bool reconnected; @@ -589,7 +589,7 @@ int main(int argc, char *argv[]) &funding, &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], - &funder, + &opener, &out[LOCAL], &out[REMOTE], &our_dust_limit, @@ -643,13 +643,13 @@ int main(int argc, char *argv[]) * commitment transaction: * - SHOULD send a `closing_signed` message. */ - whose_turn = funder; + whose_turn = opener; for (size_t i = 0; i < 2; i++, whose_turn = !whose_turn) { if (whose_turn == LOCAL) { send_offer(pps, chainparams, &channel_id, funding_pubkey, scriptpubkey, &funding_txid, funding_txout, - funding, out, funder, + funding, out, opener, our_dust_limit, offer[LOCAL]); } else { @@ -669,7 +669,7 @@ int main(int argc, char *argv[]) funding_wscript, scriptpubkey, &funding_txid, funding_txout, funding, - out, funder, + out, opener, our_dust_limit, min_fee_to_accept, &closing_txid); @@ -679,8 +679,8 @@ int main(int argc, char *argv[]) /* Now we have first two points, we can init fee range. */ init_feerange(&feerange, commitment_fee, offer); - /* Apply (and check) funder offer now. */ - adjust_feerange(&feerange, offer[funder], funder); + /* Apply (and check) opener offer now. */ + adjust_feerange(&feerange, offer[opener], opener); /* Now any extra rounds required. */ while (!amount_sat_eq(offer[LOCAL], offer[REMOTE])) { @@ -696,7 +696,7 @@ int main(int argc, char *argv[]) send_offer(pps, chainparams, &channel_id, funding_pubkey, scriptpubkey, &funding_txid, funding_txout, - funding, out, funder, + funding, out, opener, our_dust_limit, offer[LOCAL]); } else { @@ -711,7 +711,7 @@ int main(int argc, char *argv[]) funding_wscript, scriptpubkey, &funding_txid, funding_txout, funding, - out, funder, + out, opener, our_dust_limit, min_fee_to_accept, &closing_txid); diff --git a/common/initial_channel.c b/common/initial_channel.c index 16547da5852f..2714d4292f56 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -23,7 +23,7 @@ struct channel *new_initial_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, - enum side funder) + enum side opener) { struct channel *channel = tal(ctx, struct channel); struct amount_msat remote_msatoshi; @@ -36,7 +36,7 @@ struct channel *new_initial_channel(const tal_t *ctx, channel->funding, local_msatoshi)) return tal_free(channel); - channel->funder = funder; + channel->opener = opener; channel->config[LOCAL] = *local; channel->config[REMOTE] = *remote; channel->funding_pubkey[LOCAL] = *local_funding_pubkey; @@ -60,8 +60,8 @@ struct channel *new_initial_channel(const tal_t *ctx, channel->basepoints[REMOTE] = *remote_basepoints; channel->commitment_number_obscurer - = commit_number_obscurer(&channel->basepoints[funder].payment, - &channel->basepoints[!funder].payment); + = commit_number_obscurer(&channel->basepoints[opener].payment, + &channel->basepoints[!opener].payment); channel->chainparams = chainparams_by_chainhash(chain_hash); if (channel->chainparams == NULL) return tal_free(channel); @@ -100,7 +100,7 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx, &channel->funding_txid, channel->funding_txout, channel->funding, - channel->funder, + channel->opener, /* They specify our to_self_delay and v.v. */ channel->config[!side].to_self_delay, &keyset, @@ -130,12 +130,12 @@ static char *fmt_channel_view(const tal_t *ctx, const struct channel_view *view) static char *fmt_channel(const tal_t *ctx, const struct channel *channel) { return tal_fmt(ctx, "{ funding=%s," - " funder=%s," + " opener=%s," " local=%s," " remote=%s }", type_to_string(tmpctx, struct amount_sat, &channel->funding), - side_to_str(channel->funder), + side_to_str(channel->opener), fmt_channel_view(ctx, &channel->view[LOCAL]), fmt_channel_view(ctx, &channel->view[REMOTE])); } diff --git a/common/initial_channel.h b/common/initial_channel.h index 4db6d72a6cd0..242217a2ecf4 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -42,7 +42,7 @@ struct channel { u32 minimum_depth; /* Who is paying fees. */ - enum side funder; + enum side opener; /* Limits and settings on this channel. */ struct channel_config config[NUM_SIDES]; @@ -86,7 +86,7 @@ struct channel { * @remote_basepoints: remote basepoints. * @local_fundingkey: local funding key * @remote_fundingkey: remote funding key - * @funder: which side initiated it. + * @opener: which side initiated it. * * Returns channel, or NULL if malformed. */ @@ -105,7 +105,7 @@ struct channel *new_initial_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, - enum side funder); + enum side opener); /** diff --git a/common/initial_commit_tx.c b/common/initial_commit_tx.c index 0141f6a3ec58..35f476d55150 100644 --- a/common/initial_commit_tx.c +++ b/common/initial_commit_tx.c @@ -30,22 +30,22 @@ u64 commit_number_obscurer(const struct pubkey *opener_payment_basepoint, return be64_to_cpu(obscurer); } -bool try_subtract_fee(enum side funder, enum side side, +bool try_subtract_fee(enum side opener, enum side side, struct amount_sat base_fee, struct amount_msat *self, struct amount_msat *other) { - struct amount_msat *funder_amount; + struct amount_msat *opener_amount; - if (funder == side) - funder_amount = self; + if (opener == side) + opener_amount = self; else - funder_amount = other; + opener_amount = other; - if (amount_msat_sub_sat(funder_amount, *funder_amount, base_fee)) + if (amount_msat_sub_sat(opener_amount, *opener_amount, base_fee)) return true; - *funder_amount = AMOUNT_MSAT(0); + *opener_amount = AMOUNT_MSAT(0); return false; } @@ -63,7 +63,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, const struct bitcoin_txid *funding_txid, unsigned int funding_txout, struct amount_sat funding, - enum side funder, + enum side opener, u16 to_self_delay, const struct keyset *keyset, u32 feerate_per_kw, @@ -105,7 +105,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx, * 3. Subtract this base fee from the funder (either `to_local` or * `to_remote`), with a floor of 0 (see [Fee Payment](#fee-payment)). */ - if (!try_subtract_fee(funder, side, base_fee, &self_pay, &other_pay)) { + if (!try_subtract_fee(opener, side, base_fee, &self_pay, &other_pay)) { /* BOLT #2: * * The receiving node MUST fail the channel if: diff --git a/lightningd/channel.c b/lightningd/channel.c index a160b5a6d19e..8d81123af53f 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -142,7 +142,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, /* NULL or stolen */ struct wallet_shachain *their_shachain, enum channel_state state, - enum side funder, + enum side opener, /* NULL or stolen */ struct log *log, const char *transient_billboard TAKES, @@ -201,7 +201,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, shachain_init(&channel->their_shachain.chain); } channel->state = state; - channel->funder = funder; + channel->opener = opener; channel->owner = NULL; memset(&channel->billboard, 0, sizeof(channel->billboard)); channel->billboard.transient = tal_strdup(channel, transient_billboard); @@ -407,7 +407,7 @@ void channel_fail_forget(struct channel *channel, const char *fmt, ...) char *why; struct channel_id cid; - assert(channel->funder == REMOTE && + assert(channel->opener == REMOTE && channel->state == CHANNELD_AWAITING_LOCKIN); va_start(ap, fmt); why = tal_vfmt(tmpctx, fmt, ap); diff --git a/lightningd/channel.h b/lightningd/channel.h index b2cd42b47577..87273e384d0a 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -34,7 +34,7 @@ struct channel { enum channel_state state; /* Which side offered channel? */ - enum side funder; + enum side opener; /* Is there a single subdaemon responsible for us? */ struct subd *owner; @@ -129,7 +129,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, /* NULL or stolen */ struct wallet_shachain *their_shachain, enum channel_state state, - enum side funder, + enum side opener, /* NULL or stolen */ struct log *log, const char *transient_billboard TAKES, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 149ac2f9ad27..d751c6054635 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -437,7 +437,7 @@ void peer_start_channeld(struct channel *channel, &channel->channel_info.theirbase, &channel->channel_info.remote_per_commit, &channel->channel_info.old_remote_per_commit, - channel->funder, + channel->opener, channel->feerate_base, channel->feerate_ppm, channel->our_msat, @@ -483,7 +483,7 @@ void peer_start_channeld(struct channel *channel, subd_send_msg(channel->owner, take(initmsg)); /* On restart, feerate might not be what we expect: adjust now. */ - if (channel->funder == LOCAL) + if (channel->opener == LOCAL) try_update_feerates(ld, channel); } @@ -543,7 +543,7 @@ is_fundee_should_forget(struct lightningd *ld, */ /* Only applies if we are fundee. */ - if (channel->funder == LOCAL) + if (channel->opener == LOCAL) return false; /* Does not apply if we already saw the funding tx. */ diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 3772f1238ece..d33f8ff0129d 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -286,7 +286,7 @@ void peer_start_closingd(struct channel *channel, channel->funding, &channel->local_funding_pubkey, &channel->channel_info.remote_fundingkey, - channel->funder, + channel->opener, amount_msat_to_sat_round_down(channel->our_msat), amount_msat_to_sat_round_down(their_msat), channel->our_config.dust_limit, diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 7407478683d5..4fb9e588bdb0 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -553,7 +553,7 @@ enum watch_result onchaind_funding_spent(struct channel *channel, channel->shutdown_scriptpubkey[LOCAL], channel->shutdown_scriptpubkey[REMOTE], &final_key, - channel->funder, + channel->opener, &channel->local_basepoints, &channel->channel_info.theirbase, tx, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 98a9eb60b10d..901421a0d0da 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -62,7 +62,7 @@ struct uncommitted_channel { /* These are *not* filled in by new_uncommitted_channel: */ - /* Minimum funding depth (if funder == REMOTE). */ + /* Minimum funding depth (if opener == REMOTE). */ u32 minimum_depth; /* Our channel config. */ diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index afc602d5e641..f91a69436a63 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -446,7 +446,7 @@ void channel_errmsg(struct channel *channel, /* We should immediately forget the channel if we receive error during * CHANNELD_AWAITING_LOCKIN if we are fundee. */ - if (!err_for_them && channel->funder == REMOTE + if (!err_for_them && channel->opener == REMOTE && channel->state == CHANNELD_AWAITING_LOCKIN) channel_fail_forget(channel, "%s: %s ERROR %s", channel->owner->name, @@ -633,7 +633,7 @@ static void json_add_channel(struct lightningd *ld, // FIXME @conscott : Modify this when dual-funded channels // are implemented json_object_start(response, "funding_allocation_msat"); - if (channel->funder == LOCAL) { + if (channel->opener == LOCAL) { json_add_u64(response, node_id_to_hexstr(tmpctx, &p->id), 0); json_add_u64(response, node_id_to_hexstr(tmpctx, &ld->id), channel->funding.satoshis * 1000); /* Raw: raw JSON field */ @@ -645,7 +645,7 @@ static void json_add_channel(struct lightningd *ld, json_object_end(response); json_object_start(response, "funding_msat"); - if (channel->funder == LOCAL) { + if (channel->opener == LOCAL) { json_add_sat_only(response, node_id_to_hexstr(tmpctx, &p->id), AMOUNT_SAT(0)); @@ -711,8 +711,8 @@ static void json_add_channel(struct lightningd *ld, /* Take away any currently-offered HTLCs. */ subtract_offered_htlcs(channel, &spendable); - /* If we're funder, subtract txfees we'll need to spend this */ - if (channel->funder == LOCAL) { + /* If we're opener, subtract txfees we'll need to spend this */ + if (channel->opener == LOCAL) { if (!amount_msat_sub_sat(&spendable, spendable, commit_txfee(channel, spendable))) spendable = AMOUNT_MSAT(0); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index f54d7f09ad7a..797627c6e8cf 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -1546,7 +1546,7 @@ void peer_got_commitsig(struct channel *channel, const u8 *msg) } } - /* Update both feerates: if we're funder, REMOTE should already be + /* Update both feerates: if we're opener, REMOTE should already be * that feerate, if we're not, we're about to ACK anyway. */ channel->channel_info.feerate_per_kw[LOCAL] = channel->channel_info.feerate_per_kw[REMOTE] @@ -1658,7 +1658,7 @@ void peer_got_revoke(struct channel *channel, const u8 *msg) return; } - /* Update feerate: if we are funder, their revoke_and_ack has set + /* Update feerate: if we are opener, their revoke_and_ack has set * this for local feerate. */ channel->channel_info.feerate_per_kw[LOCAL] = feerate; diff --git a/onchaind/onchain_wire.csv b/onchaind/onchain_wire.csv index c4d9edf7ca61..b6fcb2df06f1 100644 --- a/onchaind/onchain_wire.csv +++ b/onchaind/onchain_wire.csv @@ -25,7 +25,7 @@ msgdata,onchain_init,remote_scriptpubkey_len,u16, msgdata,onchain_init,remote_scriptpubkey,u8,remote_scriptpubkey_len msgdata,onchain_init,ourwallet_pubkey,pubkey, # We need these two for commit number obscurer -msgdata,onchain_init,funder,enum side, +msgdata,onchain_init,opener,enum side, msgdata,onchain_init,local_basepoints,basepoints, msgdata,onchain_init,remote_basepoints,basepoints, msgdata,onchain_init,tx,bitcoin_tx, diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 54b396e099ff..655dde59e85c 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -699,7 +699,7 @@ static void unknown_spend(struct tracked_output *out, } static u64 unmask_commit_number(const struct bitcoin_tx *tx, - enum side funder, + enum side opener, const struct pubkey *local_payment_basepoint, const struct pubkey *remote_payment_basepoint) { @@ -712,7 +712,7 @@ static u64 unmask_commit_number(const struct bitcoin_tx *tx, * * The 48-bit commitment number is obscured by `XOR` with the lower 48 bits of... */ - obscurer = commit_number_obscurer(keys[funder], keys[!funder]); + obscurer = commit_number_obscurer(keys[opener], keys[!opener]); /* BOLT #3: * @@ -2658,7 +2658,7 @@ int main(int argc, char *argv[]) const tal_t *ctx = tal(NULL, char); u8 *msg; struct pubkey remote_per_commit_point, old_remote_per_commit_point; - enum side funder; + enum side opener; struct basepoints basepoints[NUM_SIDES]; struct shachain shachain; struct bitcoin_tx *tx; @@ -2694,7 +2694,7 @@ int main(int argc, char *argv[]) &scriptpubkey[LOCAL], &scriptpubkey[REMOTE], &our_wallet_pubkey, - &funder, + &opener, &basepoints[LOCAL], &basepoints[REMOTE], &tx, @@ -2769,7 +2769,7 @@ int main(int argc, char *argv[]) * *latest commitment transaction*. */ struct secret revocation_preimage; - commit_num = unmask_commit_number(tx, funder, + commit_num = unmask_commit_number(tx, opener, &basepoints[LOCAL].payment, &basepoints[REMOTE].payment); diff --git a/openingd/openingd.c b/openingd/openingd.c index efab07dd1709..b675e52d8152 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -120,8 +120,8 @@ static const u8 *dev_upfront_shutdown_script(const tal_t *ctx) } /*~ If we can't agree on parameters, we fail to open the channel. If we're - * the funder, we need to tell lightningd, otherwise it never really notices. */ -static void negotiation_aborted(struct state *state, bool am_funder, + * the opener, we need to tell lightningd, otherwise it never really notices. */ +static void negotiation_aborted(struct state *state, bool am_opener, const char *why) { status_debug("aborted opening negotiation: %s", why); @@ -134,7 +134,7 @@ static void negotiation_aborted(struct state *state, bool am_funder, peer_billboard(true, why); /* If necessary, tell master that funding failed. */ - if (am_funder) { + if (am_opener) { u8 *msg = towire_opening_funder_failed(NULL, why); wire_sync_write(REQ_FD, take(msg)); } @@ -146,7 +146,7 @@ static void negotiation_aborted(struct state *state, bool am_funder, } /*~ For negotiation failures: we tell them the parameter we didn't like. */ -static void negotiation_failed(struct state *state, bool am_funder, +static void negotiation_failed(struct state *state, bool am_opener, const char *fmt, ...) { va_list ap; @@ -161,7 +161,7 @@ static void negotiation_failed(struct state *state, bool am_funder, "You gave bad parameters: %s", errmsg); sync_crypto_write(state->pps, take(msg)); - negotiation_aborted(state, am_funder, errmsg); + negotiation_aborted(state, am_opener, errmsg); } /*~ This is the key function that checks that their configuration is reasonable: @@ -169,7 +169,7 @@ static void negotiation_failed(struct state *state, bool am_funder, * they've accepted our open. */ static bool check_config_bounds(struct state *state, const struct channel_config *remoteconf, - bool am_funder) + bool am_opener) { struct amount_sat capacity; struct amount_sat reserve; @@ -181,7 +181,7 @@ static bool check_config_bounds(struct state *state, * - `to_self_delay` is unreasonably large. */ if (remoteconf->to_self_delay > state->max_to_self_delay) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "to_self_delay %u larger than %u", remoteconf->to_self_delay, state->max_to_self_delay); @@ -204,7 +204,7 @@ static bool check_config_bounds(struct state *state, if (!amount_sat_add(&reserve, remoteconf->channel_reserve, state->localconf.channel_reserve)) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "channel_reserve_satoshis %s" " too large", type_to_string(tmpctx, struct amount_sat, @@ -214,7 +214,7 @@ static bool check_config_bounds(struct state *state, /* If reserves are larger than total sat, we fail. */ if (!amount_sat_sub(&capacity, state->funding, reserve)) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "channel_reserve_satoshis %s" " and %s too large for funding %s", type_to_string(tmpctx, struct amount_sat, @@ -235,7 +235,7 @@ static bool check_config_bounds(struct state *state, /* If the minimum htlc is greater than the capacity, the channel is * useless. */ if (amount_msat_greater_sat(remoteconf->htlc_minimum, capacity)) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "htlc_minimum_msat %s" " too large for funding %s" " capacity_msat %s", @@ -252,7 +252,7 @@ static bool check_config_bounds(struct state *state, * set by lightningd, don't bother opening it. */ if (amount_msat_greater_sat(state->min_effective_htlc_capacity, capacity)) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "channel capacity with funding %s," " reserves %s/%s," " max_htlc_value_in_flight_msat is %s," @@ -274,7 +274,7 @@ static bool check_config_bounds(struct state *state, /* We don't worry about how many HTLCs they accept, as long as > 0! */ if (remoteconf->max_accepted_htlcs == 0) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "max_accepted_htlcs %u invalid", remoteconf->max_accepted_htlcs); return false; @@ -287,7 +287,7 @@ static bool check_config_bounds(struct state *state, * - `max_accepted_htlcs` is greater than 483. */ if (remoteconf->max_accepted_htlcs > 483) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "max_accepted_htlcs %u too large", remoteconf->max_accepted_htlcs); return false; @@ -301,7 +301,7 @@ static bool check_config_bounds(struct state *state, */ if (amount_sat_greater(remoteconf->dust_limit, remoteconf->channel_reserve)) { - negotiation_failed(state, am_funder, + negotiation_failed(state, am_opener, "dust_limit_satoshis %s" " too large for channel_reserve_satoshis %s", type_to_string(tmpctx, struct amount_sat, @@ -352,7 +352,7 @@ static void temporary_channel_id(struct channel_id *channel_id) /*~ Handle random messages we might get during opening negotiation, (eg. gossip) * returning the first non-handled one, or NULL if we aborted negotiation. */ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, - bool am_funder) + bool am_opener) { /* This is an event loop of its own. That's generally considered poor * form, but we use it in a very limited way. */ @@ -414,7 +414,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, } /* Close connection on all_channels error. */ if (all_channels) { - if (am_funder) { + if (am_opener) { msg = towire_opening_funder_failed(NULL, err); wire_sync_write(REQ_FD, take(msg)); @@ -422,7 +422,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, peer_failed_received_errmsg(state->pps, err, NULL); } - negotiation_aborted(state, am_funder, + negotiation_aborted(state, am_opener, tal_fmt(tmpctx, "They sent error %s", err)); /* Return NULL so caller knows to stop negotiating. */ @@ -1029,7 +1029,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) return NULL; } - /* These checks are the same whether we're funder or fundee... */ + /* These checks are the same whether we're opener or accepter... */ if (!check_config_bounds(state, &state->remoteconf, false)) return NULL; diff --git a/wallet/wallet.c b/wallet/wallet.c index 534a75c23656..df2ad37e634f 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1305,7 +1305,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) else db_bind_null(stmt, 1); db_bind_int(stmt, 2, chan->state); - db_bind_int(stmt, 3, chan->funder); + db_bind_int(stmt, 3, chan->opener); db_bind_int(stmt, 4, chan->channel_flags); db_bind_int(stmt, 5, chan->minimum_depth); From 1e50e27becc0612fe15fd2610f7a5bc06c2379bb Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 9 Sep 2019 22:45:23 -0500 Subject: [PATCH 04/45] df: add wires for dual funding messages plus tests, with some of the corruption tests taken out, since it crashes. will be re-enabled in the next commit. --- channeld/channeld.c | 8 + gossipd/gossipd.c | 8 + wire/extracted_peer_experimental_737016aef | 92 ++++ wire/peer_wire.c | 16 + wire/test/Makefile | 2 + wire/test/run-peer-wire.c | 535 ++++++++++++++++++++- wire/wire.h | 1 + 7 files changed, 637 insertions(+), 25 deletions(-) create mode 100644 wire/extracted_peer_experimental_737016aef diff --git a/channeld/channeld.c b/channeld/channeld.c index 73bb364f1762..2c5e083bcd6b 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1863,6 +1863,14 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_FUNDING_SIGNED: case WIRE_CHANNEL_REESTABLISH: case WIRE_CLOSING_SIGNED: +#if EXPERIMENTAL_FEATURES + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_FUNDING_COMPOSE: + case WIRE_ACCEPTER_SIGS: + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: +#endif /* EXPERIMENTAL_FEATURES */ break; /* These are all swallowed by handle_peer_gossip_or_error */ diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index cd35c8bef639..d8b91550f382 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -503,6 +503,14 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, case WIRE_CHANNEL_REESTABLISH: case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: +#if EXPERIMENTAL_FEATURES + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_FUNDING_COMPOSE: + case WIRE_ACCEPTER_SIGS: + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: +#endif /* EXPERIMENTAL_FEATURES */ status_broken("peer %s: relayed unexpected msg of type %s", type_to_string(tmpctx, struct node_id, &peer->id), wire_type_name(fromwire_peektype(msg))); diff --git a/wire/extracted_peer_experimental_737016aef b/wire/extracted_peer_experimental_737016aef new file mode 100644 index 000000000000..a1048abd4475 --- /dev/null +++ b/wire/extracted_peer_experimental_737016aef @@ -0,0 +1,92 @@ +--- wire/extracted_peer_wire_csv 2019-08-21 13:30:32.219341098 -0500 ++++ - 2019-09-11 17:38:34.177415676 -0500 +@@ -77,6 +77,89 @@ + msgtype,funding_locked,36 + msgdata,funding_locked,channel_id,channel_id, + msgdata,funding_locked,next_per_commitment_point,point, ++msgtype,open_channel2,56 ++msgdata,open_channel2,chain_hash,chain_hash, ++msgdata,open_channel2,temporary_channel_id,byte,32 ++msgdata,open_channel2,funding_satoshis,u64, ++msgdata,open_channel2,push_msat,u64, ++msgdata,open_channel2,dust_limit_satoshis,u64, ++msgdata,open_channel2,max_htlc_value_in_flight_msat,u64, ++msgdata,open_channel2,htlc_minimum_msat,u64, ++msgdata,open_channel2,feerate_per_kw,u32, ++msgdata,open_channel2,feerate_per_kw_funding,u32, ++msgdata,open_channel2,to_self_delay,u16, ++msgdata,open_channel2,max_accepted_htlcs,u16, ++msgdata,open_channel2,funding_pubkey,point, ++msgdata,open_channel2,revocation_basepoint,point, ++msgdata,open_channel2,payment_basepoint,point, ++msgdata,open_channel2,delayed_payment_basepoint,point, ++msgdata,open_channel2,htlc_basepoint,point, ++msgdata,open_channel2,first_per_commitment_point,point, ++msgdata,open_channel2,channel_flags,byte, ++msgdata,open_channel2,opening_tlv,opening_tlvs, ++tlvtype,opening_tlvs,option_upfront_shutdown_script,1 ++tlvdata,opening_tlvs,option_upfront_shutdown_script,shutdown_len,u16, ++tlvdata,opening_tlvs,option_upfront_shutdown_script,shutdown_scriptpubkey,byte,shutdown_len ++msgtype,accept_channel2,57 ++msgdata,accept_channel2,temporary_channel_id,byte,32 ++msgdata,accept_channel2,funding_satoshis,u64, ++msgdata,accept_channel2,dust_limit_satoshis,u64, ++msgdata,accept_channel2,max_htlc_value_in_flight_msat,u64, ++msgdata,accept_channel2,htlc_minimum_msat,u64, ++msgdata,accept_channel2,minimum_depth,u32, ++msgdata,accept_channel2,to_self_delay,u16, ++msgdata,accept_channel2,max_accepted_htlcs,u16, ++msgdata,accept_channel2,funding_pubkey,point, ++msgdata,accept_channel2,revocation_basepoint,point, ++msgdata,accept_channel2,payment_basepoint,point, ++msgdata,accept_channel2,delayed_payment_basepoint,point, ++msgdata,accept_channel2,htlc_basepoint,point, ++msgdata,accept_channel2,first_per_commitment_point,point, ++msgdata,accept_channel2,accept_tlv,accept_tlvs, ++tlvtype,accept_tlvs,option_upfront_shutdown_script,1 ++tlvdata,accept_tlvs,option_upfront_shutdown_script,shutdown_len,u16, ++tlvdata,accept_tlvs,option_upfront_shutdown_script,shutdown_scriptpubkey,byte,shutdown_len ++msgtype,funding_compose,58 ++msgdata,funding_compose,temporary_channel_id,byte,32 ++msgdata,funding_compose,num_inputs,u16, ++msgdata,funding_compose,input_info,input_info,num_inputs ++msgdata,funding_compose,num_outputs,u16, ++msgdata,funding_compose,output_info,output_info,num_outputs ++subtype,input_info ++subtypedata,input_info,input_satoshis,u64, ++subtypedata,input_info,prevtx_txid,sha256, ++subtypedata,input_info,prevtx_vout,u32, ++subtypedata,input_info,prevtx_scriptpubkey_len,u16, ++subtypedata,input_info,prevtx_scriptpubkey,byte,prevtx_scriptpubkey_len ++subtypedata,input_info,max_witness_len,u16, ++subtypedata,input_info,scriptlen,u16, ++subtypedata,input_info,script,byte,scriptlen ++subtype,output_info ++subtypedata,output_info,output_satoshis,u64, ++subtypedata,output_info,scriptlen,u16, ++subtypedata,output_info,script,byte,scriptlen ++msgtype,accepter_sigs,60 ++msgdata,accepter_sigs,channel_id,channel_id, ++msgdata,accepter_sigs,commitment_signature,signature, ++msgdata,accepter_sigs,num_witnesses,u16, ++msgdata,accepter_sigs,witness_stack,witness_stack,num_witnesses ++subtype,witness_stack ++subtypedata,witness_stack,num_input_witness,u16, ++subtypedata,witness_stack,witness_element,witness_element,num_input_witness ++subtype,witness_element ++subtypedata,witness_element,len,u16, ++subtypedata,witness_element,witness,byte,len ++msgtype,init_rbf,62 ++msgdata,init_rbf,channel_id,channel_id, ++msgdata,init_rbf,funding_satoshis,u64, ++msgdata,init_rbf,feerate_per_kw,u32, ++msgdata,init_rbf,feerate_per_kw_funding,u32, ++msgdata,init_rbf,num_additional_inputs,u16, ++msgdata,init_rbf,input_info,input_info,num_additional_inputs ++msgdata,init_rbf,num_outputs,u16, ++msgdata,init_rbf,output_info,output_info,num_outputs ++msgtype,ack_rbf,63 ++msgdata,ack_rbf,channel_id,channel_id, + msgtype,shutdown,38 + msgdata,shutdown,channel_id,channel_id, + msgdata,shutdown,len,u16, diff --git a/wire/peer_wire.c b/wire/peer_wire.c index e9210d7d8434..aecdda66d067 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -31,6 +31,14 @@ static bool unknown_type(enum wire_type t) case WIRE_QUERY_CHANNEL_RANGE: case WIRE_REPLY_CHANNEL_RANGE: case WIRE_GOSSIP_TIMESTAMP_FILTER: +#if EXPERIMENTAL_FEATURES + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_FUNDING_COMPOSE: + case WIRE_ACCEPTER_SIGS: + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: +#endif /* EXPERIMENTAL_FEATURES */ return false; } return true; @@ -68,6 +76,14 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_CHANNEL_REESTABLISH: case WIRE_ANNOUNCEMENT_SIGNATURES: case WIRE_GOSSIP_TIMESTAMP_FILTER: +#if EXPERIMENTAL_FEATURES + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_FUNDING_COMPOSE: + case WIRE_ACCEPTER_SIGS: + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: +#endif /* EXPERIMENTAL_FEATURES */ break; } return false; diff --git a/wire/test/Makefile b/wire/test/Makefile index f086ac1b7a37..bdad99c9093d 100644 --- a/wire/test/Makefile +++ b/wire/test/Makefile @@ -9,6 +9,8 @@ WIRE_TEST_PROGRAMS := $(WIRE_TEST_OBJS:.o=) WIRE_TEST_COMMON_OBJS := \ common/utils.o +wire/test/run-peer-wire: common/bigsize.o + update-mocks: $(WIRE_TEST_SRC:%=update-mocks/%) $(WIRE_TEST_PROGRAMS): $(WIRE_TEST_COMMON_OBJS) $(BITCOIN_OBJS) diff --git a/wire/test/run-peer-wire.c b/wire/test/run-peer-wire.c index dfe3e2741b1a..f678942ea87c 100644 --- a/wire/test/run-peer-wire.c +++ b/wire/test/run-peer-wire.c @@ -1,8 +1,9 @@ #include "../gen_peer_wire.c" -#include "../towire.c" #include "../fromwire.c" #include "../peer_wire.c" +#include "../tlvstream.c" +#include "../towire.c" #include #include @@ -31,24 +32,6 @@ bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } -/* Generated stub for bigsize_get */ -size_t bigsize_get(const u8 *p UNNEEDED, size_t max UNNEEDED, bigsize_t *val UNNEEDED) -{ fprintf(stderr, "bigsize_get called!\n"); abort(); } -/* Generated stub for bigsize_put */ -size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED) -{ fprintf(stderr, "bigsize_put called!\n"); abort(); } -/* Generated stub for fromwire_tlvs */ -bool fromwire_tlvs(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, - const struct tlv_record_type types[] UNNEEDED, - size_t num_types UNNEEDED, - void *record UNNEEDED) -{ fprintf(stderr, "fromwire_tlvs called!\n"); abort(); } -/* Generated stub for towire_tlvs */ -void towire_tlvs(u8 **pptr UNNEEDED, - const struct tlv_record_type types[] UNNEEDED, - size_t num_types UNNEEDED, - const void *record UNNEEDED) -{ fprintf(stderr, "towire_tlvs called!\n"); abort(); } /* AUTOGENERATED MOCKS END */ /* memsetting pubkeys doesn't work */ @@ -96,6 +79,21 @@ static void set_node_id(struct node_id *id) (tal_count((p1)->field) == tal_count((p2)->field) \ && (tal_count((p1)->field) == 0 || memcmp((p1)->field, (p2)->field, tal_bytelen((p1)->field)) == 0)) +#define eq_struct_set(p1, p2, field, type) \ + do { \ + ok &= (!(p1) && !(p2)) || ((p1) && (p2)); \ + ok &= (!(p1)->field && !(p2)->field) || ((p1)->field && (p2)->field); \ + if (ok && (p1) && (p1)->field) \ + for (size_t i = 0; i < tal_count((p1)->field); i++) { \ + struct type *_a, *_b; \ + _a = a->field[i]; \ + _b = b->field[i]; \ + ok &= (_a && _b) || (!_a && !_b); \ + if (ok && _a) \ + ok &= (type##_eq(_a, _b)); \ + } \ + } while (0) \ + /* Convenience structs for everyone! */ struct msg_error { struct channel_id channel_id; @@ -250,6 +248,67 @@ struct msg_update_fee { u32 feerate_per_kw; }; +/* Open Channel 2 */ +struct msg_open_channel2 { + struct bitcoin_blkid chain_hash; + struct channel_id temporary_channel_id; + struct amount_sat funding_satoshis; + struct amount_msat push_msat; + struct amount_sat dust_limit_satoshis; + struct amount_msat max_htlc_value_in_flight_msat; + struct amount_msat htlc_minimum_msat; + u32 feerate_per_kw; + u32 feerate_per_kw_funding; + u16 to_self_delay; + u16 max_accepted_htlcs; + struct pubkey funding_pubkey; + struct pubkey revocation_basepoint; + struct pubkey payment_basepoint; + struct pubkey delayed_payment_basepoint; + struct pubkey htlc_basepoint; + struct pubkey first_per_commitment_point; + u8 channel_flags; + struct tlv_opening_tlvs *tlv; +}; +struct msg_accept_channel2 { + struct channel_id temporary_channel_id; + struct amount_sat funding_satoshis; + struct amount_sat dust_limit_satoshis; + struct amount_msat max_htlc_value_in_flight_msat; + struct amount_msat htlc_minimum_msat; + u32 minimum_depth; + u16 to_self_delay; + u16 max_accepted_htlcs; + struct pubkey funding_pubkey; + struct pubkey revocation_basepoint; + struct pubkey payment_basepoint; + struct pubkey delayed_payment_basepoint; + struct pubkey htlc_basepoint; + struct pubkey first_per_commitment_point; + struct tlv_accept_tlvs *tlv; +}; +struct msg_funding_compose { + struct channel_id temporary_channel_id; + struct input_info **input_infos; + struct output_info **output_infos; +}; +struct msg_accepter_sigs { + struct channel_id channel_id; + secp256k1_ecdsa_signature commitment_signature; + struct witness_stack **witness_stacks; +}; +struct msg_init_rbf { + struct channel_id channel_id; + struct amount_sat funding_satoshis; + u32 feerate_per_kw; + u32 feerate_per_kw_funding; + struct input_info **input_infos; + struct output_info **output_infos; +}; +struct msg_ack_rbf { + struct channel_id channel_id; +}; + static void *towire_struct_channel_announcement(const tal_t *ctx, const struct msg_channel_announcement *s) { @@ -776,6 +835,294 @@ static struct msg_init *fromwire_struct_init(const tal_t *ctx, const void *p) return s; } +#if EXPERIMENTAL_FEATURES +static void *towire_struct_open_channel2(const tal_t *ctx, + const struct msg_open_channel2 *s) +{ + return towire_open_channel2(ctx, + &s->chain_hash, + &s->temporary_channel_id, + s->funding_satoshis, + s->push_msat, + s->dust_limit_satoshis, + s->max_htlc_value_in_flight_msat, + s->htlc_minimum_msat, + s->feerate_per_kw, + s->feerate_per_kw_funding, + s->to_self_delay, + s->max_accepted_htlcs, + &s->funding_pubkey, + &s->revocation_basepoint, + &s->payment_basepoint, + &s->delayed_payment_basepoint, + &s->htlc_basepoint, + &s->first_per_commitment_point, + s->channel_flags, + s->tlv); +} + +static struct msg_open_channel2 *fromwire_struct_open_channel2(const tal_t *ctx, const void *p) +{ + struct msg_open_channel2 *s = tal(ctx, struct msg_open_channel2); + s->tlv = tlv_opening_tlvs_new(ctx); + + if (fromwire_open_channel2(p, &s->chain_hash, + &s->temporary_channel_id, + &s->funding_satoshis, + &s->push_msat, + &s->dust_limit_satoshis, + &s->max_htlc_value_in_flight_msat, + &s->htlc_minimum_msat, + &s->feerate_per_kw, + &s->feerate_per_kw_funding, + &s->to_self_delay, + &s->max_accepted_htlcs, + &s->funding_pubkey, + &s->revocation_basepoint, + &s->payment_basepoint, + &s->delayed_payment_basepoint, + &s->htlc_basepoint, + &s->first_per_commitment_point, + &s->channel_flags, + s->tlv)) + return s; + return tal_free(s); +} +static void *towire_struct_accept_channel2(const tal_t *ctx, + const struct msg_accept_channel2 *s) +{ + return towire_accept_channel2(ctx, + &s->temporary_channel_id, + s->funding_satoshis, + s->dust_limit_satoshis, + s->max_htlc_value_in_flight_msat, + s->htlc_minimum_msat, + s->minimum_depth, + s->to_self_delay, + s->max_accepted_htlcs, + &s->funding_pubkey, + &s->revocation_basepoint, + &s->payment_basepoint, + &s->htlc_basepoint, + &s->delayed_payment_basepoint, + &s->first_per_commitment_point, + s->tlv); +} + +static struct msg_accept_channel2 *fromwire_struct_accept_channel2(const tal_t *ctx, const void *p) +{ + struct msg_accept_channel2 *s = tal(ctx, struct msg_accept_channel2); + s->tlv = talz(ctx, struct tlv_accept_tlvs); + + if (fromwire_accept_channel2(p, &s->temporary_channel_id, + &s->funding_satoshis, + &s->dust_limit_satoshis, + &s->max_htlc_value_in_flight_msat, + &s->htlc_minimum_msat, + &s->minimum_depth, + &s->to_self_delay, + &s->max_accepted_htlcs, + &s->funding_pubkey, + &s->revocation_basepoint, + &s->payment_basepoint, + &s->htlc_basepoint, + &s->delayed_payment_basepoint, + &s->first_per_commitment_point, + s->tlv)) + return s; + return tal_free(s); +} +static void *towire_struct_funding_compose(const tal_t *ctx, + struct msg_funding_compose *s) +{ + return towire_funding_compose(ctx, + &s->temporary_channel_id, + (const struct input_info **)s->input_infos, + (const struct output_info **)s->output_infos); +} +static struct msg_funding_compose *fromwire_struct_funding_compose(const tal_t *ctx, const void *p) +{ + struct msg_funding_compose *s = tal(ctx, struct msg_funding_compose); + + if (fromwire_funding_compose(ctx, p, + &s->temporary_channel_id, + &s->input_infos, + &s->output_infos)) + return s; + return tal_free(s); +} +static void *towire_struct_accepter_sigs(const tal_t *ctx, + struct msg_accepter_sigs *s) +{ + return towire_accepter_sigs(ctx, + &s->channel_id, + &s->commitment_signature, + (const struct witness_stack **)s->witness_stacks); +} +static struct msg_accepter_sigs *fromwire_struct_accepter_sigs(const tal_t *ctx, const void *p) +{ + struct msg_accepter_sigs *s = tal(ctx, struct msg_accepter_sigs); + + if (fromwire_accepter_sigs(ctx, p, + &s->channel_id, + &s->commitment_signature, + &s->witness_stacks)) { + return s; + } + return tal_free(s); +} + +static void *towire_struct_init_rbf(const tal_t *ctx, + struct msg_init_rbf *s) +{ + return towire_init_rbf(ctx, + &s->channel_id, + s->funding_satoshis, + s->feerate_per_kw, + s->feerate_per_kw_funding, + (const struct input_info **)s->input_infos, + (const struct output_info **)s->output_infos); +} +static struct msg_init_rbf *fromwire_struct_init_rbf(const tal_t *ctx, const void *p) +{ + struct msg_init_rbf *s = tal(ctx, struct msg_init_rbf); + + if (fromwire_init_rbf(ctx, p, + &s->channel_id, + &s->funding_satoshis, + &s->feerate_per_kw, + &s->feerate_per_kw_funding, + &s->input_infos, + &s->output_infos)) + return s; + return tal_free(s); +} +static void *towire_struct_ack_rbf(const tal_t *ctx, const struct msg_ack_rbf *s) +{ + return towire_ack_rbf(ctx, &s->channel_id); +} +static struct msg_ack_rbf *fromwire_struct_ack_rbf(const tal_t *ctx, const void *p) +{ + struct msg_ack_rbf *s = tal(ctx, struct msg_ack_rbf); + + if (fromwire_ack_rbf(p, &s->channel_id)) + return s; + return tal_free(s); +} + +static bool open_option_upfront_shutdown_script_eq(const struct tlv_opening_tlvs_option_upfront_shutdown_script *a, + const struct tlv_opening_tlvs_option_upfront_shutdown_script *b) +{ + return (!a && !b) + || (a && b && eq_var(a, b, shutdown_scriptpubkey)); +} + +static bool accept_option_upfront_shutdown_script_eq(const struct tlv_accept_tlvs_option_upfront_shutdown_script *a, + const struct tlv_accept_tlvs_option_upfront_shutdown_script *b) +{ + return (!a && !b) + || (a && b && eq_var(a, b, shutdown_scriptpubkey)); +} + +static bool input_info_eq(struct input_info *a, + struct input_info *b) +{ + return eq_with(a, b, prevtx_vout) + && eq_var(a, b, prevtx_scriptpubkey) + && eq_field(a, b, max_witness_len) + && eq_var(a, b, script); +} + +static bool output_info_eq(struct output_info *a, + struct output_info *b) +{ + return eq_with(a, b, output_satoshis) + && eq_var(a, b, script); +} + +static bool witness_element_eq(struct witness_element *a, + struct witness_element *b) +{ + return ((!a && !b) || (a && b)) + && eq_var(a, b, witness); +} + +static bool witness_stack_eq(struct witness_stack *a, + struct witness_stack *b) +{ + bool ok = true; + eq_struct_set(a, b, witness_element, witness_element); + return ok; +} + + +static bool opening_tlv_eq(const struct tlv_opening_tlvs *a, + const struct tlv_opening_tlvs *b) +{ + return (!a && !b) || + (a && b && + open_option_upfront_shutdown_script_eq(a->option_upfront_shutdown_script, + b->option_upfront_shutdown_script)); +} + +static bool accept_tlv_eq(const struct tlv_accept_tlvs *a, + const struct tlv_accept_tlvs *b) +{ + return (!a && !b) || + (a && b && + accept_option_upfront_shutdown_script_eq(a->option_upfront_shutdown_script, + b->option_upfront_shutdown_script)); +} + +static bool open_channel2_eq(const struct msg_open_channel2 *a, + const struct msg_open_channel2 *b) +{ + return eq_with(a, b, max_accepted_htlcs) + && eq_between(a, b, funding_pubkey, channel_flags) + && opening_tlv_eq(a->tlv, b->tlv); +} + +static bool accept_channel2_eq(const struct msg_accept_channel2 *a, + const struct msg_accept_channel2 *b) +{ + return eq_with(a, b, max_accepted_htlcs) + && eq_between(a, b, funding_pubkey, first_per_commitment_point) + && accept_tlv_eq(a->tlv, b->tlv); +} + +static bool funding_compose_eq(const struct msg_funding_compose *a, + const struct msg_funding_compose *b) +{ + bool ok = true; + eq_struct_set(a, b, input_infos, input_info); + eq_struct_set(a, b, output_infos, output_info); + return ok && eq_upto(a, b, input_infos); +} + +static bool accepter_sigs_eq(const struct msg_accepter_sigs *a, + const struct msg_accepter_sigs *b) +{ + bool ok = true; + eq_struct_set(a, b, witness_stacks, witness_stack); + return ok && eq_upto(a, b, witness_stacks); +} + +static bool init_rbf_eq(const struct msg_init_rbf *a, + const struct msg_init_rbf *b) +{ + bool ok = true; + eq_struct_set(a, b, input_infos, input_info); + eq_struct_set(a, b, output_infos, output_info); + return ok && eq_upto(a, b, input_infos); +} + +static bool ack_rbf_eq(const struct msg_ack_rbf *a, + const struct msg_ack_rbf *b) +{ + return memcmp(a, b, sizeof(*a)) == 0; +} +#endif /* EXPERIMENTAL_FEATURES */ + static bool channel_announcement_eq(const struct msg_channel_announcement *a, const struct msg_channel_announcement *b) { @@ -922,15 +1269,24 @@ static bool node_announcement_eq(const struct msg_node_announcement *a, #define test_corruption(a, b, type) \ for (i = 0; i < tal_count(msg) * 8; i++) { \ msg[i / 8] ^= (1 << (i%8)); \ - b = fromwire_struct_##type(ctx, msg); \ + b = fromwire_struct_##type(ctx, msg); \ assert(!b || !type##_eq(a, b)); \ msg[i / 8] ^= (1 << (i%8)); \ } \ - for (i = 0; i < tal_count(msg); i++) { \ - u8 *trunc = tal_dup_arr(ctx, u8, msg, i, 0); \ - b = fromwire_struct_##type(ctx, trunc); \ - assert(!b); \ - } + +#if EXPERIMENTAL_FEATURES +/* Test failure due to duplicate TLV message */ +static void test_open_channel2_tlv_message_duplicate(const tal_t *ctx, u8 *msg) +{ + size_t len = tal_count(msg); + u8 *duplicate = tal_arr(ctx, u8, 10); + memcpy(duplicate, msg + (len - 10), 10); + towire(&msg, duplicate, 10); + msg[len - 11] = 20; /* duplicate the size variable */ + assert(fromwire_struct_open_channel2(ctx, msg) == NULL); +} +#endif /* EXPERIMENTAL_FEATURES */ + int main(void) { @@ -956,6 +1312,17 @@ int main(void) struct msg_accept_channel ac, *ac2; struct msg_update_add_htlc uah, *uah2; struct msg_node_announcement na, *na2; + +#if EXPERIMENTAL_FEATURES + /* v2 channel establishment */ + struct msg_open_channel2 ocv2, *ocv22; + struct msg_accept_channel2 acv2, *acv22; + struct msg_funding_compose fcom, *fcom2; + struct msg_accepter_sigs acs, *acs2; + struct msg_init_rbf irbf, *irbf2; + struct msg_ack_rbf arbf, *arbf2; +#endif /* EXPERIMENTAL_FEATURES */ + void *ctx = tal(NULL, char); size_t i; u8 *msg; @@ -1140,6 +1507,124 @@ int main(void) assert(node_announcement_eq(&na, na2)); test_corruption(&na, na2, node_announcement); +#if EXPERIMENTAL_FEATURES + /* Channel Establishment v2 */ + memset(&ocv2, 2, sizeof(ocv2)); + set_pubkey(&ocv2.funding_pubkey); + set_pubkey(&ocv2.revocation_basepoint); + set_pubkey(&ocv2.payment_basepoint); + set_pubkey(&ocv2.delayed_payment_basepoint); + set_pubkey(&ocv2.htlc_basepoint); + set_pubkey(&ocv2.first_per_commitment_point); + + ocv2.tlv = tal(ctx, struct tlv_opening_tlvs); + ocv2.tlv->option_upfront_shutdown_script = tal(ctx, struct tlv_opening_tlvs_option_upfront_shutdown_script); + ocv2.tlv->option_upfront_shutdown_script->shutdown_scriptpubkey = tal_arr(ctx, u8, 2); + memset(ocv2.tlv->option_upfront_shutdown_script->shutdown_scriptpubkey, 2, 2); + + msg = towire_struct_open_channel2(ctx, &ocv2); + ocv22 = fromwire_struct_open_channel2(ctx, msg); + assert(open_channel2_eq(&ocv2, ocv22)); + test_corruption(&ocv2, ocv22, open_channel2); + test_open_channel2_tlv_message_duplicate(ctx, msg); + + memset(&acv2, 2, sizeof(acv2)); + set_pubkey(&acv2.funding_pubkey); + set_pubkey(&acv2.revocation_basepoint); + set_pubkey(&acv2.payment_basepoint); + set_pubkey(&acv2.delayed_payment_basepoint); + set_pubkey(&acv2.htlc_basepoint); + set_pubkey(&acv2.first_per_commitment_point); + + acv2.tlv = tal(ctx, struct tlv_accept_tlvs); + acv2.tlv->option_upfront_shutdown_script = tal(ctx, struct tlv_accept_tlvs_option_upfront_shutdown_script); + acv2.tlv->option_upfront_shutdown_script->shutdown_scriptpubkey = tal_arr(ctx, u8, 2); + memset(acv2.tlv->option_upfront_shutdown_script->shutdown_scriptpubkey, 2, 2); + + msg = towire_struct_accept_channel2(ctx, &acv2); + acv22 = fromwire_struct_accept_channel2(ctx, msg); + assert(accept_channel2_eq(&acv2, acv22)); + test_corruption(&acv2, acv22, accept_channel2); + + memset(&fcom, 2, sizeof(fcom)); + fcom.input_infos = tal_arr(ctx, struct input_info *, 2); + memset(fcom.input_infos, 2, sizeof(struct input_info *) * 2); + for (i = 0; i < 2; i++) { + fcom.input_infos[i] = tal(ctx, struct input_info); + memset(fcom.input_infos[i], 2, sizeof(struct input_info)); + fcom.input_infos[i]->prevtx_scriptpubkey = tal_arr(ctx, u8, 2); + memset(fcom.input_infos[i]->prevtx_scriptpubkey, 2, 2); + fcom.input_infos[i]->script = tal_arr(ctx, u8, 2); + memset(fcom.input_infos[i]->script, 2, 2); + } + fcom.output_infos = tal_arr(ctx, struct output_info *, 2); + memset(fcom.output_infos, 2, sizeof(struct output_info *)*2); + for (i = 0; i < 2; i++) { + fcom.output_infos[i] = tal(ctx, struct output_info); + memset(fcom.output_infos[i], 2, sizeof(struct output_info)); + fcom.output_infos[i]->script = tal_arr(ctx, u8, 2); + memset(fcom.output_infos[i]->script, 2, 2); + } + + msg = towire_struct_funding_compose(ctx, &fcom); + fcom2 = fromwire_struct_funding_compose(ctx, msg); + assert(funding_compose_eq(&fcom, fcom2)); + test_corruption(&fcom, fcom2, funding_compose); + + memset(&acs, 2, sizeof(acs)); + acs.witness_stacks = tal_arr(ctx, struct witness_stack *, 2); + memset(acs.witness_stacks, 2, sizeof(struct witness_stack *) * 2); + for (i = 0; i < 2; i++) { + acs.witness_stacks[i] = tal(ctx, struct witness_stack); + memset(acs.witness_stacks[i], 2, sizeof(struct witness_stack)); + acs.witness_stacks[i]->witness_element = tal_arr(ctx, struct witness_element *, 2); + memset(acs.witness_stacks[i]->witness_element, 2, sizeof(struct witness_element *) * 2); + for (size_t j = 0; j < 2; j++) { + acs.witness_stacks[i]->witness_element[j] = tal(ctx, struct witness_element); + memset(acs.witness_stacks[i]->witness_element[j], 2, sizeof(struct witness_element)); + acs.witness_stacks[i]->witness_element[j]->witness = tal_arr(ctx, u8, 2); + memset(acs.witness_stacks[i]->witness_element[j]->witness, 2, 2); + } + } + + msg = towire_struct_accepter_sigs(ctx, &acs); + acs2 = fromwire_struct_accepter_sigs(ctx, msg); + assert(accepter_sigs_eq(&acs, acs2)); + test_corruption(&acs, acs2, accepter_sigs); + + memset(&irbf, 2, sizeof(irbf)); + irbf.input_infos = tal_arr(ctx, struct input_info *, 2); + memset(irbf.input_infos, 2, sizeof(struct input_info *) * 2); + for (i = 0; i < 2; i++) { + irbf.input_infos[i] = tal(ctx, struct input_info); + memset(irbf.input_infos[i], 2, sizeof(struct input_info)); + irbf.input_infos[i]->prevtx_scriptpubkey = tal_arr(ctx, u8, 2); + memset(irbf.input_infos[i]->prevtx_scriptpubkey, 2, 2); + irbf.input_infos[i]->script = tal_arr(ctx, u8, 2); + memset(irbf.input_infos[i]->script, 2, 2); + } + irbf.output_infos = tal_arr(ctx, struct output_info *, 2); + memset(irbf.output_infos, 2, sizeof(struct output_info *)*2); + for (i = 0; i < 2; i++) { + irbf.output_infos[i] = tal(ctx, struct output_info); + memset(irbf.output_infos[i], 2, sizeof(struct output_info)); + irbf.output_infos[i]->script = tal_arr(ctx, u8, 2); + memset(irbf.output_infos[i]->script, 2, 2); + } + + msg = towire_struct_init_rbf(ctx, &irbf); + irbf2 = fromwire_struct_init_rbf(ctx, msg); + assert(init_rbf_eq(&irbf, irbf2)); + test_corruption(&irbf, irbf2, init_rbf); + + memset(&arbf, 2, sizeof(arbf)); + + msg = towire_struct_ack_rbf(ctx, &arbf); + arbf2 = fromwire_struct_ack_rbf(ctx, msg); + assert(ack_rbf_eq(&arbf, arbf2)); + test_corruption(&arbf, arbf2, ack_rbf); + +#endif /* EXPERIMENTAL_FEATURES */ /* No memory leaks please */ secp256k1_context_destroy(secp256k1_ctx); tal_free(ctx); diff --git a/wire/wire.h b/wire/wire.h index f9781ab34c72..e71f2659106b 100644 --- a/wire/wire.h +++ b/wire/wire.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include From 64443ac78c17e44151cc198c006c34f051c0fcce Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Fri, 13 Sep 2019 12:25:37 -0500 Subject: [PATCH 05/45] df: add truncation check for wire messages Since wires can now have TLVs, we need to change up the truncation check to account for the fact that truncated TLVs are kosher. --- wire/test/run-peer-wire.c | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/wire/test/run-peer-wire.c b/wire/test/run-peer-wire.c index f678942ea87c..a59829d730dc 100644 --- a/wire/test/run-peer-wire.c +++ b/wire/test/run-peer-wire.c @@ -1082,6 +1082,15 @@ static bool open_channel2_eq(const struct msg_open_channel2 *a, && opening_tlv_eq(a->tlv, b->tlv); } +static bool open_channel2_truncation_check(const struct msg_open_channel2 *a) +{ + if (a) { + struct tlv_opening_tlvs *tlv = tlv_opening_tlvs_new(a); + return memcmp(a->tlv, tlv, sizeof(*a->tlv)) == 0; + } + return !a; +} + static bool accept_channel2_eq(const struct msg_accept_channel2 *a, const struct msg_accept_channel2 *b) { @@ -1090,6 +1099,15 @@ static bool accept_channel2_eq(const struct msg_accept_channel2 *a, && accept_tlv_eq(a->tlv, b->tlv); } +static bool accept_channel2_truncation_check(const struct msg_accept_channel2 *a) +{ + if (a) { + struct tlv_accept_tlvs *tlv = tlv_accept_tlvs_new(a); + return memcmp(a->tlv, tlv, sizeof(*a->tlv)) == 0; + } + return !a; +} + static bool funding_compose_eq(const struct msg_funding_compose *a, const struct msg_funding_compose *b) { @@ -1099,6 +1117,11 @@ static bool funding_compose_eq(const struct msg_funding_compose *a, return ok && eq_upto(a, b, input_infos); } +static bool funding_compose_truncation_check(const struct msg_funding_compose *a) +{ + return !a; +} + static bool accepter_sigs_eq(const struct msg_accepter_sigs *a, const struct msg_accepter_sigs *b) { @@ -1107,6 +1130,11 @@ static bool accepter_sigs_eq(const struct msg_accepter_sigs *a, return ok && eq_upto(a, b, witness_stacks); } +static bool accepter_sigs_truncation_check(const struct msg_accepter_sigs *a) +{ + return !a; +} + static bool init_rbf_eq(const struct msg_init_rbf *a, const struct msg_init_rbf *b) { @@ -1116,11 +1144,21 @@ static bool init_rbf_eq(const struct msg_init_rbf *a, return ok && eq_upto(a, b, input_infos); } +static bool init_rbf_truncation_check(const struct msg_init_rbf *a) +{ + return !a; +} + static bool ack_rbf_eq(const struct msg_ack_rbf *a, const struct msg_ack_rbf *b) { return memcmp(a, b, sizeof(*a)) == 0; } + +static bool ack_rbf_truncation_check(const struct msg_ack_rbf *a) +{ + return !a; +} #endif /* EXPERIMENTAL_FEATURES */ static bool channel_announcement_eq(const struct msg_channel_announcement *a, @@ -1136,12 +1174,22 @@ static bool channel_announcement_eq(const struct msg_channel_announcement *a, && eq_between(a, b, bitcoin_key_1, bitcoin_key_2); } +static bool channel_announcement_truncation_check(const struct msg_channel_announcement *a) +{ + return !a; +} + static bool funding_locked_eq(const struct msg_funding_locked *a, const struct msg_funding_locked *b) { return memcmp(a, b, sizeof(*a)) == 0; } +static bool funding_locked_truncation_check(const struct msg_funding_locked *a) +{ + return !a; +} + static bool announcement_signatures_eq(const struct msg_announcement_signatures *a, const struct msg_announcement_signatures *b) { @@ -1149,6 +1197,11 @@ static bool announcement_signatures_eq(const struct msg_announcement_signatures short_channel_id_eq(&a->short_channel_id, &b->short_channel_id); } +static bool announcement_signatures_truncation_check(const struct msg_announcement_signatures *a) +{ + return !a; +} + static bool update_fail_htlc_eq(const struct msg_update_fail_htlc *a, const struct msg_update_fail_htlc *b) { @@ -1156,6 +1209,11 @@ static bool update_fail_htlc_eq(const struct msg_update_fail_htlc *a, && eq_var(a, b, reason); } +static bool update_fail_htlc_truncation_check(const struct msg_update_fail_htlc *a) +{ + return !a; +} + static bool commitment_signed_eq(const struct msg_commitment_signed *a, const struct msg_commitment_signed *b) { @@ -1163,24 +1221,43 @@ static bool commitment_signed_eq(const struct msg_commitment_signed *a, && eq_var(a, b, htlc_signature); } +static bool commitment_signed_truncation_check(const struct msg_commitment_signed *a) +{ + return !a; +} + static bool funding_signed_eq(const struct msg_funding_signed *a, const struct msg_funding_signed *b) { return memcmp(a, b, sizeof(*a)) == 0; } +static bool funding_signed_truncation_check(const struct msg_funding_signed *a) +{ + return !a; +} + static bool closing_signed_eq(const struct msg_closing_signed *a, const struct msg_closing_signed *b) { return memcmp(a, b, sizeof(*a)) == 0; } +static bool closing_signed_truncation_check(const struct msg_closing_signed *a) +{ + return !a; +} static bool update_fulfill_htlc_eq(const struct msg_update_fulfill_htlc *a, const struct msg_update_fulfill_htlc *b) { return memcmp(a, b, sizeof(*a)) == 0; } +static bool update_fulfill_htlc_truncation_check(const struct msg_update_fulfill_htlc *a) +{ + return !a; +} + static bool error_eq(const struct msg_error *a, const struct msg_error *b) { @@ -1188,6 +1265,11 @@ static bool error_eq(const struct msg_error *a, && eq_var(a, b, data); } +static bool error_truncation_check(const struct msg_error *a) +{ + return !a; +} + static bool init_eq(const struct msg_init *a, const struct msg_init *b) { @@ -1195,12 +1277,22 @@ static bool init_eq(const struct msg_init *a, && eq_var(a, b, localfeatures); } +static bool init_truncation_check(const struct msg_init *a) +{ + return !a; +} + static bool update_fee_eq(const struct msg_update_fee *a, const struct msg_update_fee *b) { return memcmp(a, b, sizeof(*a)) == 0; } +static bool update_fee_truncation_check(const struct msg_update_fee *a) +{ + return !a; +} + static bool shutdown_eq(const struct msg_shutdown *a, const struct msg_shutdown *b) { @@ -1208,6 +1300,11 @@ static bool shutdown_eq(const struct msg_shutdown *a, && eq_var(a, b, scriptpubkey); } +static bool shutdown_truncation_check(const struct msg_shutdown *a) +{ + return !a; +} + static bool funding_created_eq(const struct msg_funding_created *a, const struct msg_funding_created *b) { @@ -1215,12 +1312,22 @@ static bool funding_created_eq(const struct msg_funding_created *a, && eq_field(a, b, signature); } +static bool funding_created_truncation_check(const struct msg_funding_created *a) +{ + return !a; +} + static bool revoke_and_ack_eq(const struct msg_revoke_and_ack *a, const struct msg_revoke_and_ack *b) { return memcmp(a, b, sizeof(*a)) == 0; } +static bool revoke_and_ack_truncation_check(const struct msg_revoke_and_ack *a) +{ + return !a; +} + static bool open_channel_eq(const struct msg_open_channel *a, const struct msg_open_channel *b) { @@ -1228,6 +1335,11 @@ static bool open_channel_eq(const struct msg_open_channel *a, && eq_between(a, b, funding_pubkey, channel_flags); } +static bool open_channel_truncation_check(const struct msg_open_channel *a) +{ + return !a; +} + static bool channel_update_eq(const struct msg_channel_update *a, const struct msg_channel_update *b) { @@ -1235,6 +1347,11 @@ static bool channel_update_eq(const struct msg_channel_update *a, short_channel_id_eq(&a->short_channel_id, &b->short_channel_id); } +static bool channel_update_truncation_check(const struct msg_channel_update *a) +{ + return !a; +} + static bool channel_update_opt_htlc_max_eq(const struct msg_channel_update_opt_htlc_max *a, const struct msg_channel_update_opt_htlc_max *b) { @@ -1242,6 +1359,11 @@ static bool channel_update_opt_htlc_max_eq(const struct msg_channel_update_opt_h short_channel_id_eq(&a->short_channel_id, &b->short_channel_id); } +static bool channel_update_opt_htlc_max_truncation_check(const struct msg_channel_update_opt_htlc_max *a) +{ + return !a; +} + static bool accept_channel_eq(const struct msg_accept_channel *a, const struct msg_accept_channel *b) { @@ -1249,12 +1371,22 @@ static bool accept_channel_eq(const struct msg_accept_channel *a, && eq_between(a, b, funding_pubkey, first_per_commitment_point); } +static bool accept_channel_truncation_check(const struct msg_accept_channel *a) +{ + return !a; +} + static bool update_add_htlc_eq(const struct msg_update_add_htlc *a, const struct msg_update_add_htlc *b) { return eq_with(a, b, onion_routing_packet); } +static bool update_add_htlc_truncation_check(const struct msg_update_add_htlc *a) +{ + return !a; +} + static bool node_announcement_eq(const struct msg_node_announcement *a, const struct msg_node_announcement *b) { @@ -1265,6 +1397,11 @@ static bool node_announcement_eq(const struct msg_node_announcement *a, && eq_var(a, b, addresses); } +static bool node_announcement_truncation_check(const struct msg_node_announcement *a) +{ + return !a; +} + /* Try flipping each bit, try running short. */ #define test_corruption(a, b, type) \ for (i = 0; i < tal_count(msg) * 8; i++) { \ @@ -1273,6 +1410,11 @@ static bool node_announcement_eq(const struct msg_node_announcement *a, assert(!b || !type##_eq(a, b)); \ msg[i / 8] ^= (1 << (i%8)); \ } \ + for (i = 0; i < tal_count(msg); i++) { \ + u8 *trunc = tal_dup_arr(ctx, u8, msg, i, 0); \ + b = fromwire_struct_##type(ctx, trunc); \ + assert(type##_truncation_check(b)); \ + } #if EXPERIMENTAL_FEATURES /* Test failure due to duplicate TLV message */ From b8e615426b7a116c1974cf9bfcfe3861073d1183 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Fri, 13 Sep 2019 14:14:14 -0500 Subject: [PATCH 06/45] df: pipe through whether or not we're using v2 we need a way to tell openingd to use v2 for channel open. --- lightningd/opening_control.c | 14 +++++++++++--- openingd/opening_wire.csv | 1 + openingd/openingd.c | 13 +++++++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 901421a0d0da..d87b2bd4f0bd 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -553,7 +553,7 @@ static void opening_funder_failed(struct subd *openingd, const u8 *msg, was_pending(command_success(uc->fc->cancels[i], response)); } - /* Tell any fundchannel_complete or fundchannel command */ + /* Tell any fundchannel_complete command */ if (uc->fc->cmd) was_pending(command_fail(uc->fc->cmd, LIGHTNINGD, "%s", desc)); @@ -1060,7 +1060,7 @@ static struct command_result *json_fund_channel_start(struct command *cmd, struct node_id *id; struct peer *peer; struct channel *channel; - bool *announce_channel; + bool *announce_channel, use_v2; u32 *feerate_per_kw; u8 *msg = NULL; @@ -1162,11 +1162,19 @@ static struct command_result *json_fund_channel_start(struct command *cmd, peer->uncommitted_channel->fc = tal_steal(peer->uncommitted_channel, fc); fc->uc = peer->uncommitted_channel; +#if EXPERIMENTAL_FEATURES + // FIXME: use features to flag on + use_v2 = true; +#else + use_v2 = false; +#endif + msg = towire_opening_funder_start(NULL, *amount, fc->push, *feerate_per_kw, - fc->channel_flags); + fc->channel_flags, + use_v2); subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); return command_still_pending(cmd); diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index f3f969b3ad35..323ee01173cd 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -72,6 +72,7 @@ msgdata,opening_funder_start,funding_satoshis,amount_sat, msgdata,opening_funder_start,push_msat,amount_msat, msgdata,opening_funder_start,feerate_per_kw,u32, msgdata,opening_funder_start,channel_flags,u8, +msgdata,opening_funder_start,use_v2,bool, # openingd->master: send back output script for 2-of-2 funding output msgtype,opening_funder_start_reply,6102 diff --git a/openingd/openingd.c b/openingd/openingd.c index b675e52d8152..2daaea3f7f1c 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -106,6 +106,11 @@ struct state { /* Which chain we're on, so we can check/set `chain_hash` fields */ const struct chainparams *chainparams; bool option_static_remotekey; + + /* Things for v2 */ + bool use_v2; + struct amount_sat accepter_funding; + u32 feerate_per_kw_funding; }; static const u8 *dev_upfront_shutdown_script(const tal_t *ctx) @@ -479,13 +484,16 @@ static bool setup_channel_funder(struct state *state) return false; } + if (!state->use_v2) + state->accepter_funding = AMOUNT_SAT(0); + return true; } /* We start the 'fund a channel' negotation with the supplied peer, but * stop when we get to the part where we need the funding txid */ static u8 *funder_channel_start(struct state *state, - u8 channel_flags) + u8 channel_flags) { u8 *msg; u8 *funding_output_script; @@ -1350,7 +1358,8 @@ static u8 *handle_master_in(struct state *state) if (!fromwire_opening_funder_start(msg, &state->funding, &state->push_msat, &state->feerate_per_kw, - &channel_flags)) + &channel_flags, + &state->use_v2)) master_badmsg(WIRE_OPENING_FUNDER_START, msg); msg = funder_channel_start(state, channel_flags); From 903ebdb0f6dcdd102f71c03c8e312e2db31150ed Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Fri, 13 Sep 2019 14:16:32 -0500 Subject: [PATCH 07/45] df: switch from funding -> opener_funding and wire in v2 calls We've now got two amounts we need to keep track of: the opener's funding and the accpeter's. We add a utlity to help keep track of the full funding. Also wires in the calls for open/accept v2 for when we're the opener. --- openingd/openingd.c | 353 ++++++++++++++++++++++++++++++-------------- 1 file changed, 245 insertions(+), 108 deletions(-) diff --git a/openingd/openingd.c b/openingd/openingd.c index 2daaea3f7f1c..ff353df4a316 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -86,7 +86,7 @@ struct state { struct channel_id channel_id; /* Funding and feerate: set by opening peer. */ - struct amount_sat funding; + struct amount_sat opener_funding; struct amount_msat push_msat; u32 feerate_per_kw; struct bitcoin_txid funding_txid; @@ -113,6 +113,17 @@ struct state { u32 feerate_per_kw_funding; }; +static struct amount_sat total_funding(const struct state *state) +{ + struct amount_sat total; + if (!amount_sat_add(&total, state->opener_funding, + state->accepter_funding)) + abort(); + + return total; + +} + static const u8 *dev_upfront_shutdown_script(const tal_t *ctx) { #if DEVELOPER @@ -176,8 +187,9 @@ static bool check_config_bounds(struct state *state, const struct channel_config *remoteconf, bool am_opener) { - struct amount_sat capacity; - struct amount_sat reserve; + struct amount_sat capacity, reserve, all_funding; + + all_funding = total_funding(state); /* BOLT #2: * @@ -218,7 +230,7 @@ static bool check_config_bounds(struct state *state, } /* If reserves are larger than total sat, we fail. */ - if (!amount_sat_sub(&capacity, state->funding, reserve)) { + if (!amount_sat_sub(&capacity, all_funding, reserve)) { negotiation_failed(state, am_opener, "channel_reserve_satoshis %s" " and %s too large for funding %s", @@ -227,7 +239,7 @@ static bool check_config_bounds(struct state *state, type_to_string(tmpctx, struct amount_sat, &state->localconf.channel_reserve), type_to_string(tmpctx, struct amount_sat, - &state->funding)); + &all_funding)); return false; } @@ -247,7 +259,7 @@ static bool check_config_bounds(struct state *state, type_to_string(tmpctx, struct amount_msat, &remoteconf->htlc_minimum), type_to_string(tmpctx, struct amount_sat, - &state->funding), + &all_funding), type_to_string(tmpctx, struct amount_sat, &capacity)); return false; @@ -263,7 +275,7 @@ static bool check_config_bounds(struct state *state, " max_htlc_value_in_flight_msat is %s," " channel capacity is %s, which is below %s", type_to_string(tmpctx, struct amount_sat, - &state->funding), + &all_funding), type_to_string(tmpctx, struct amount_sat, &remoteconf->channel_reserve), type_to_string(tmpctx, struct amount_sat, @@ -323,7 +335,7 @@ static bool check_config_bounds(struct state *state, static void set_reserve(struct state *state) { state->localconf.channel_reserve.satoshis /* Raw: rounding. */ - = state->funding.satoshis / 100; /* Raw: rounding. */ + = total_funding(state).satoshis / 100; /* Raw: rounding. */ /* BOLT #2: * @@ -336,6 +348,18 @@ static void set_reserve(struct state *state) state->localconf.channel_reserve)) state->localconf.channel_reserve = state->localconf.dust_limit; + + /* Early return if we're not setting the remote's also (v2) */ + if (!state->use_v2) + return; + + state->remoteconf.channel_reserve.satoshis /* Raw: rounding. */ + = total_funding(state).satoshis / 100; /* Raw: rounding. */ + + if (amount_sat_greater(state->remoteconf.dust_limit, + state->remoteconf.channel_reserve)) + state->remoteconf.channel_reserve + = state->remoteconf.dust_limit; } /* BOLT #2: @@ -458,11 +482,51 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, } } +static bool check_reserves(struct state *state) +{ + /* BOLT #2: + * + * The receiver: + *... + * - if `channel_reserve_satoshis` is less than `dust_limit_satoshis` + * within the `open_channel` message: + * - MUST reject the channel. + * + * - if `channel_reserve_satoshis` from the `open_channel` message is + * less than `dust_limit_satoshis`: + * - MUST reject the channel. + */ + if (amount_sat_greater(state->localconf.dust_limit, + state->remoteconf.channel_reserve)) { + negotiation_failed(state, true, + "channel reserve %s" + " would be below our dust %s", + type_to_string(tmpctx, struct amount_sat, + &state->remoteconf.channel_reserve), + type_to_string(tmpctx, struct amount_sat, + &state->localconf.dust_limit)); + return false; + } + if (amount_sat_greater(state->remoteconf.dust_limit, + state->localconf.channel_reserve)) { + negotiation_failed(state, true, + "dust limit %s" + " would be above our reserve %s", + type_to_string(tmpctx, struct amount_sat, + &state->remoteconf.dust_limit), + type_to_string(tmpctx, struct amount_sat, + &state->localconf.channel_reserve)); + return false; + } + return true; +} + static bool setup_channel_funder(struct state *state) { + if (!state->use_v2) /*~ For symmetry, we calculate our own reserve even though lightningd * could do it for the we-are-funding case. */ - set_reserve(state); + set_reserve(state); /*~ Grab a random ID until the funding tx is created (we can't do that * until we know their funding_pubkey) */ @@ -474,13 +538,13 @@ static bool setup_channel_funder(struct state *state) *... * - MUST set `funding_satoshis` to less than 2^24 satoshi. */ - if (amount_sat_greater(state->funding, state->chainparams->max_funding)) { + if (amount_sat_greater(state->opener_funding, state->chainparams->max_funding)) { status_failed(STATUS_FAIL_MASTER_IO, "funding_satoshis must be < %s, not %s", type_to_string(tmpctx, struct amount_sat, &state->chainparams->max_funding), type_to_string(tmpctx, struct amount_sat, - &state->funding)); + &state->opener_funding)); return false; } @@ -502,43 +566,84 @@ static u8 *funder_channel_start(struct state *state, if (!setup_channel_funder(state)) return NULL; - /* BOLT #2: - * - * - if both nodes advertised the `option_upfront_shutdown_script` - * feature: - * - MUST include either a valid `shutdown_scriptpubkey` as required - * by `shutdown` `scriptpubkey`, or a zero-length - * `shutdown_scriptpubkey`. - * - otherwise: - * - MAY include a`shutdown_scriptpubkey`. - */ - /* We don't use shutdown_scriptpubkey (at least for now), so leave it - * NULL. */ - msg = towire_open_channel_option_upfront_shutdown_script(NULL, - &state->chainparams->genesis_blockhash, - &state->channel_id, - state->funding, - state->push_msat, - state->localconf.dust_limit, - state->localconf.max_htlc_value_in_flight, - state->localconf.channel_reserve, - state->localconf.htlc_minimum, - state->feerate_per_kw, - state->localconf.to_self_delay, - state->localconf.max_accepted_htlcs, - &state->our_funding_pubkey, - &state->our_points.revocation, - &state->our_points.payment, - &state->our_points.delayed_payment, - &state->our_points.htlc, - &state->first_per_commitment_point[LOCAL], - channel_flags, - dev_upfront_shutdown_script(tmpctx)); + if (state->use_v2) { +#if EXPERIMENTAL_FEATURES + struct tlv_opening_tlvs *tlv = tlv_opening_tlvs_new(tmpctx); + tlv->option_upfront_shutdown_script = + tal(tlv, struct tlv_opening_tlvs_option_upfront_shutdown_script); + tlv->option_upfront_shutdown_script->shutdown_scriptpubkey = + (u8 *)dev_upfront_shutdown_script(tlv); + + /* For now, we use the same feerate for funding + commitment tx */ + /* FIXME: allow these to be done separately? */ + state->feerate_per_kw_funding = state->feerate_per_kw; + msg = towire_open_channel2(NULL, + &state->chainparams->genesis_blockhash, + &state->channel_id, + state->opener_funding, + state->push_msat, + state->localconf.dust_limit, + state->localconf.max_htlc_value_in_flight, + state->localconf.htlc_minimum, + state->feerate_per_kw, + state->feerate_per_kw_funding, + state->localconf.to_self_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, + &state->first_per_commitment_point[LOCAL], + channel_flags, + tlv); +#else + peer_failed(state->pps, + &state->channel_id, + "Bad state: signaled v2 channel_open but missing " + "experimental features."); +#endif /* EXPERIMENTAL_FEATURES */ + } else { + /* BOLT #2: + * + * - if both nodes advertised the `option_upfront_shutdown_script` + * feature: + * - MUST include either a valid `shutdown_scriptpubkey` as required + * by `shutdown` `scriptpubkey`, or a zero-length + * `shutdown_scriptpubkey`. + * - otherwise: + * - MAY include a`shutdown_scriptpubkey`. + */ + /* We don't use shutdown_scriptpubkey (at least for now), so leave it + * NULL. */ + msg = towire_open_channel_option_upfront_shutdown_script(NULL, + &state->chainparams->genesis_blockhash, + &state->channel_id, + state->opener_funding, + state->push_msat, + state->localconf.dust_limit, + state->localconf.max_htlc_value_in_flight, + state->localconf.channel_reserve, + state->localconf.htlc_minimum, + state->feerate_per_kw, + state->localconf.to_self_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, + &state->first_per_commitment_point[LOCAL], + channel_flags, + dev_upfront_shutdown_script(tmpctx)); + } + sync_crypto_write(state->pps, take(msg)); /* This is usually a very transient state... */ peer_billboard(false, - "Funding channel start: offered, now waiting for accept_channel"); + "Funding channel start: offered, now waiting for accept_channel%s", + state->use_v2 ? "2" : ""); /* ... since their reply should be immediate. */ msg = opening_negotiate_msg(tmpctx, state, true); @@ -549,52 +654,90 @@ static u8 *funder_channel_start(struct state *state, state->remote_upfront_shutdown_script = tal_free(state->remote_upfront_shutdown_script); - /* BOLT #2: - * - * The receiving node MUST fail the channel if: - *... - * - `funding_pubkey`, `revocation_basepoint`, `htlc_basepoint`, - * `payment_basepoint`, or `delayed_payment_basepoint` are not - * valid DER-encoded compressed secp256k1 pubkeys. - */ - if (local_feature_negotiated(state->localfeatures, - LOCAL_UPFRONT_SHUTDOWN_SCRIPT)) { - if (!fromwire_accept_channel_option_upfront_shutdown_script(state, - msg, &id_in, - &state->remoteconf.dust_limit, - &state->remoteconf.max_htlc_value_in_flight, - &state->remoteconf.channel_reserve, - &state->remoteconf.htlc_minimum, - &state->minimum_depth, - &state->remoteconf.to_self_delay, - &state->remoteconf.max_accepted_htlcs, - &state->their_funding_pubkey, - &state->their_points.revocation, - &state->their_points.payment, - &state->their_points.delayed_payment, - &state->their_points.htlc, - &state->first_per_commitment_point[REMOTE], - &state->remote_upfront_shutdown_script)) + if (state->use_v2) { +#if EXPERIMENTAL_FEATURES + struct tlv_accept_tlvs *tlv = tlv_accept_tlvs_new(tmpctx); + if (!fromwire_accept_channel2(msg, &id_in, + &state->accepter_funding, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.htlc_minimum, + &state->minimum_depth, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &state->their_funding_pubkey, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.delayed_payment, + &state->their_points.htlc, + &state->first_per_commitment_point[REMOTE], + tlv)) peer_failed(state->pps, &state->channel_id, - "Parsing accept_channel with option_upfront_shutdown_script %s", tal_hex(msg, msg)); - } else if (!fromwire_accept_channel(msg, &id_in, - &state->remoteconf.dust_limit, - &state->remoteconf.max_htlc_value_in_flight, - &state->remoteconf.channel_reserve, - &state->remoteconf.htlc_minimum, - &state->minimum_depth, - &state->remoteconf.to_self_delay, - &state->remoteconf.max_accepted_htlcs, - &state->their_funding_pubkey, - &state->their_points.revocation, - &state->their_points.payment, - &state->their_points.delayed_payment, - &state->their_points.htlc, - &state->first_per_commitment_point[REMOTE])) + "Parsing accept_channel2 %s", tal_hex(msg, msg)); + + /* This is gross */ + if (tlv->option_upfront_shutdown_script && + tlv->option_upfront_shutdown_script->shutdown_scriptpubkey) + state->remote_upfront_shutdown_script = tal_steal(state, + tlv->option_upfront_shutdown_script->shutdown_scriptpubkey); + +#else peer_failed(state->pps, &state->channel_id, - "Parsing accept_channel %s", tal_hex(msg, msg)); + "Bad state: signaled v2 channel_accept but missing " + "experimental features. %s", + tal_hex(msg, msg)); +#endif + + } else { + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - `funding_pubkey`, `revocation_basepoint`, `htlc_basepoint`, + * `payment_basepoint`, or `delayed_payment_basepoint` are not + * valid DER-encoded compressed secp256k1 pubkeys. + */ + if (local_feature_negotiated(state->localfeatures, + LOCAL_UPFRONT_SHUTDOWN_SCRIPT)) { + if (!fromwire_accept_channel_option_upfront_shutdown_script(state, + msg, &id_in, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.channel_reserve, + &state->remoteconf.htlc_minimum, + &state->minimum_depth, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &state->their_funding_pubkey, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.delayed_payment, + &state->their_points.htlc, + &state->first_per_commitment_point[REMOTE], + &state->remote_upfront_shutdown_script)) + peer_failed(state->pps, + &state->channel_id, + "Parsing accept_channel with option_upfront_shutdown_script %s", tal_hex(msg, msg)); + } else if (!fromwire_accept_channel(msg, &id_in, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.channel_reserve, + &state->remoteconf.htlc_minimum, + &state->minimum_depth, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &state->their_funding_pubkey, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.delayed_payment, + &state->their_points.htlc, + &state->first_per_commitment_point[REMOTE])) + peer_failed(state->pps, + &state->channel_id, + "Parsing accept_channel %s", tal_hex(msg, msg)); + } /* BOLT #2: * @@ -609,17 +752,10 @@ static u8 *funder_channel_start(struct state *state, type_to_string(msg, struct channel_id, &state->channel_id)); - if (amount_sat_greater(state->remoteconf.dust_limit, - state->localconf.channel_reserve)) { - negotiation_failed(state, true, - "dust limit %s" - " would be above our reserve %s", - type_to_string(tmpctx, struct amount_sat, - &state->remoteconf.dust_limit), - type_to_string(tmpctx, struct amount_sat, - &state->localconf.channel_reserve)); + if (state->use_v2) + set_reserve(state); + else if (!check_reserves(state)) return NULL; - } if (!check_config_bounds(state, &state->remoteconf, true)) return NULL; @@ -634,6 +770,7 @@ static u8 *funder_channel_start(struct state *state, peer_billboard(false, "Funding channel start: awaiting funding_txid with output to %s", tal_hex(tmpctx, funding_output_script)); + return towire_opening_funder_start_reply(state, funding_output_script); } @@ -660,7 +797,7 @@ static bool funder_finalize_channel_setup(struct state *state, &state->funding_txid, state->funding_txout, state->minimum_depth, - state->funding, + total_funding(state), local_msat, state->feerate_per_kw, &state->localconf, @@ -838,7 +975,7 @@ static u8 *funder_channel_complete(struct state *state) /* We recalculate the local_msat from cached values; should * succeed because we checked it earlier */ - assert(amount_sat_sub_msat(&local_msat, state->funding, state->push_msat)); + assert(amount_sat_sub_msat(&local_msat, state->opener_funding, state->push_msat)); if (!funder_finalize_channel_setup(state, local_msat, &sig, &tx)) return NULL; @@ -893,7 +1030,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) if (!fromwire_open_channel_option_upfront_shutdown_script(state, open_channel_msg, &chain_hash, &state->channel_id, - &state->funding, + &state->opener_funding, &state->push_msat, &state->remoteconf.dust_limit, &state->remoteconf.max_htlc_value_in_flight, @@ -915,7 +1052,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) "Parsing open_channel with option_upfront_shutdown_script %s", tal_hex(tmpctx, open_channel_msg)); } else if (!fromwire_open_channel(open_channel_msg, &chain_hash, &state->channel_id, - &state->funding, + &state->opener_funding, &state->push_msat, &state->remoteconf.dust_limit, &state->remoteconf.max_htlc_value_in_flight, @@ -955,11 +1092,11 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) * * The receiving node ... MUST fail the channel if `funding-satoshis` * is greater than or equal to 2^24 */ - if (amount_sat_greater(state->funding, state->chainparams->max_funding)) { + if (amount_sat_greater(state->opener_funding, state->chainparams->max_funding)) { negotiation_failed(state, false, "funding_satoshis %s too large", type_to_string(tmpctx, struct amount_sat, - &state->funding)); + &state->opener_funding)); return NULL; } @@ -969,7 +1106,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) * ... * - `push_msat` is greater than `funding_satoshis` * 1000. */ - if (amount_msat_greater_sat(state->push_msat, state->funding)) { + if (amount_msat_greater_sat(state->push_msat, state->opener_funding)) { peer_failed(state->pps, &state->channel_id, "Their push_msat %s" @@ -977,7 +1114,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) type_to_string(tmpctx, struct amount_msat, &state->push_msat), type_to_string(tmpctx, struct amount_sat, - &state->funding)); + &state->opener_funding)); return NULL; } @@ -1044,7 +1181,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) /* Check with lightningd that we can accept this? In particular, * if we have an existing channel, we don't support it. */ msg = towire_opening_got_offer(NULL, - state->funding, + state->opener_funding, state->push_msat, state->remoteconf.dust_limit, state->remoteconf.max_htlc_value_in_flight, @@ -1125,7 +1262,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) &state->funding_txid, state->funding_txout, state->minimum_depth, - state->funding, + state->opener_funding, state->push_msat, state->feerate_per_kw, &state->localconf, @@ -1247,7 +1384,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) &their_funding_pubkey, &state->funding_txid, state->funding_txout, - state->funding, + state->opener_funding, state->push_msat, channel_flags, state->feerate_per_kw, @@ -1355,7 +1492,7 @@ static u8 *handle_master_in(struct state *state) switch (t) { case WIRE_OPENING_FUNDER_START: - if (!fromwire_opening_funder_start(msg, &state->funding, + if (!fromwire_opening_funder_start(msg, &state->opener_funding, &state->push_msat, &state->feerate_per_kw, &channel_flags, From b2970dccde9f56d4d226522f22856c7ce813601d Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Fri, 13 Sep 2019 14:58:21 -0500 Subject: [PATCH 08/45] df: stash 'is_v2' into fundchannel object so we can refer to it later when doing 'complete' things --- lightningd/opening_control.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index d87b2bd4f0bd..77117b0acf64 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -93,6 +93,9 @@ struct funding_channel { /* Any commands trying to cancel us. */ struct command **cancels; + + /* Whether or not to use channel open v2 */ + bool is_v2; }; static void uncommitted_channel_disconnect(struct uncommitted_channel *uc, @@ -1060,7 +1063,7 @@ static struct command_result *json_fund_channel_start(struct command *cmd, struct node_id *id; struct peer *peer; struct channel *channel; - bool *announce_channel, use_v2; + bool *announce_channel; u32 *feerate_per_kw; u8 *msg = NULL; @@ -1164,9 +1167,9 @@ static struct command_result *json_fund_channel_start(struct command *cmd, #if EXPERIMENTAL_FEATURES // FIXME: use features to flag on - use_v2 = true; + fc->is_v2 = true; #else - use_v2 = false; + fc->is_v2 = false; #endif msg = towire_opening_funder_start(NULL, @@ -1174,7 +1177,7 @@ static struct command_result *json_fund_channel_start(struct command *cmd, fc->push, *feerate_per_kw, fc->channel_flags, - use_v2); + fc->is_v2); subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); return command_still_pending(cmd); From b74767b8351327be0c8c4e18a104f211a40f930f Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Fri, 13 Sep 2019 14:59:26 -0500 Subject: [PATCH 09/45] df: lookup transaction for the fundchannel_complete for v2 we need to know the inputs/outputs of the transaction so we look them up. there's more problems here that we need to unwind still: figuring out which the funding output is plus how to handle change. --- lightningd/opening_control.c | 26 ++++++++++++++++++++++++-- openingd/opening_wire.csv | 3 ++- openingd/openingd.c | 12 +++++++----- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 77117b0acf64..084af4833cd0 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -971,6 +971,7 @@ static struct command_result *json_fund_channel_complete(struct command *cmd, struct channel *channel; u32 *funding_txout_num; u16 funding_txout; + struct bitcoin_tx *tx; if (!param(cmd, buffer, params, p_req("id", param_node_id, &id), @@ -1003,11 +1004,32 @@ static struct command_result *json_fund_channel_complete(struct command *cmd, if (peer->uncommitted_channel->fc->cmd) return command_fail(cmd, LIGHTNINGD, "Channel funding in progress."); + /* We need to know the inputs/outputsfor v2 of fundchannel. + * Ideally, we'd get the PSBT for the tx passed in to fundchannel_complete, + * which would include all of the input/output information. + * Requires txprepare to return the PSBT of the tx, not just the txid + * Until this is patched, we can only do v2 self-funded tx's. + * + * FIXME: use PSBT for fundchannel_complete */ + if (peer->uncommitted_channel->fc->is_v2) { + struct unreleased_tx *utx; + utx = find_unreleased_tx(peer->ld->wallet, funding_txid); + + if (!utx) + return command_fail(cmd, LIGHTNINGD, "Unknown tx %s:%d. " + "Cannot fund a v2 channel with external tx.", + type_to_string(tmpctx, struct bitcoin_txid, funding_txid), + funding_txout); + tx = utx->tx; + } else + tx = NULL; + /* Set the cmd to this new cmd */ peer->uncommitted_channel->fc->cmd = cmd; msg = towire_opening_funder_complete(NULL, - funding_txid, - funding_txout); + funding_txid, funding_txout, + tx); + subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); return command_still_pending(cmd); } diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index 323ee01173cd..039ae91fd5fa 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -81,10 +81,11 @@ msgdata,opening_funder_start_reply,scriptpubkey,u8,script_len # master->openingd: complete channel establishment for a funding # tx that will be paid for by an external wallet -# response to this is a normal `opening_funder_reply` ?? +# response is `opening_funder_reply` msgtype,opening_funder_complete,6012 msgdata,opening_funder_complete,funding_txid,bitcoin_txid, msgdata,opening_funder_complete,funding_txout,u16, +msgdata,opening_funder_complete,tx,bitcoin_tx, #master->openingd: cancel channel establishment for a funding msgtype,opening_funder_cancel,6013 diff --git a/openingd/openingd.c b/openingd/openingd.c index ff353df4a316..970898c5ef56 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -962,9 +962,9 @@ static bool funder_finalize_channel_setup(struct state *state, return false; } -static u8 *funder_channel_complete(struct state *state) +static u8 *funder_channel_complete(struct state *state, + struct bitcoin_tx *tx) { - struct bitcoin_tx *tx; struct bitcoin_signature sig; struct amount_msat local_msat; @@ -1488,6 +1488,7 @@ static u8 *handle_master_in(struct state *state) enum opening_wire_type t = fromwire_peektype(msg); u8 channel_flags; struct bitcoin_txid funding_txid; + struct bitcoin_tx *tx; u16 funding_txout; switch (t) { @@ -1505,13 +1506,14 @@ static u8 *handle_master_in(struct state *state) wire_sync_write(REQ_FD, take(msg)); return NULL; case WIRE_OPENING_FUNDER_COMPLETE: - if (!fromwire_opening_funder_complete(msg, + if (!fromwire_opening_funder_complete(tmpctx, msg, &funding_txid, - &funding_txout)) + &funding_txout, + &tx)) master_badmsg(WIRE_OPENING_FUNDER_COMPLETE, msg); state->funding_txid = funding_txid; state->funding_txout = funding_txout; - return funder_channel_complete(state); + return funder_channel_complete(state, tx); case WIRE_OPENING_FUNDER_CANCEL: /* We're aborting this, simple */ if (!fromwire_opening_funder_cancel(msg)) From c0f2828ac223369845edf2456dd928d89d9e6477 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 16 Sep 2019 19:02:27 -0500 Subject: [PATCH 10/45] hsmd: pull up utxo signing going to need to re-use this later. --- hsmd/hsmd.c | 64 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index a8f60a6f85df..68fe59baa34d 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -1534,6 +1534,41 @@ static void hsm_key_for_utxo(struct privkey *privkey, struct pubkey *pubkey, } } +static void sign_input(struct bitcoin_tx *tx, struct utxo *in, + struct pubkey *inkey, + struct bitcoin_signature *sig, + int index) +{ + struct privkey inprivkey; + u8 *subscript, *wscript, *script; + + /* Figure out keys to spend this. */ + hsm_key_for_utxo(&inprivkey, inkey, in); + + /* It's either a p2wpkh or p2sh (we support that so people from + * the last bitcoin era can put funds into the wallet) */ + wscript = p2wpkh_scriptcode(tmpctx, inkey); + if (in->is_p2sh) { + /* For P2SH-wrapped Segwit, the (implied) redeemScript + * is defined in BIP141 */ + subscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, inkey); + script = bitcoin_scriptsig_p2sh_p2wpkh(tx, inkey); + bitcoin_tx_input_set_script(tx, index, script); + } else { + /* Pure segwit uses an empty inputScript; NULL has + * tal_count() == 0, so it works great here. */ + subscript = NULL; + bitcoin_tx_input_set_script(tx, index, NULL); + } + /* This is the core crypto magic. */ + sign_tx_input(tx, index, subscript, wscript, &inprivkey, inkey, + SIGHASH_ALL, sig); + + /* The witness is [sig] [key] */ + bitcoin_tx_input_set_witness( + tx, index, take(bitcoin_witness_p2wpkh(tx, sig, inkey))); +} + /* This completes the tx by filling in the input scripts with signatures. */ static void sign_all_inputs(struct bitcoin_tx *tx, struct utxo **utxos) { @@ -1551,36 +1586,9 @@ static void sign_all_inputs(struct bitcoin_tx *tx, struct utxo **utxos) assert(tx->wtx->num_inputs == tal_count(utxos)); for (size_t i = 0; i < tal_count(utxos); i++) { struct pubkey inkey; - struct privkey inprivkey; - const struct utxo *in = utxos[i]; - u8 *subscript, *wscript, *script; struct bitcoin_signature sig; - /* Figure out keys to spend this. */ - hsm_key_for_utxo(&inprivkey, &inkey, in); - - /* It's either a p2wpkh or p2sh (we support that so people from - * the last bitcoin era can put funds into the wallet) */ - wscript = p2wpkh_scriptcode(tmpctx, &inkey); - if (in->is_p2sh) { - /* For P2SH-wrapped Segwit, the (implied) redeemScript - * is defined in BIP141 */ - subscript = bitcoin_redeem_p2sh_p2wpkh(tmpctx, &inkey); - script = bitcoin_scriptsig_p2sh_p2wpkh(tx, &inkey); - bitcoin_tx_input_set_script(tx, i, script); - } else { - /* Pure segwit uses an empty inputScript; NULL has - * tal_count() == 0, so it works great here. */ - subscript = NULL; - bitcoin_tx_input_set_script(tx, i, NULL); - } - /* This is the core crypto magic. */ - sign_tx_input(tx, i, subscript, wscript, &inprivkey, &inkey, - SIGHASH_ALL, &sig); - - /* The witness is [sig] [key] */ - bitcoin_tx_input_set_witness( - tx, i, take(bitcoin_witness_p2wpkh(tx, &sig, &inkey))); + sign_input(tx, utxos[i], &inkey, &sig, i); } } From 6a8eb06dc4aa87a57208ad362e4e460ed1f743ae Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 16 Sep 2019 19:08:05 -0500 Subject: [PATCH 11/45] withdraw: refactor change output handling We're not using the change_outnum for withdraw tx's (and the way we were calculating it was broken as of the addition of 'multiple outputs'). This removes the change output knowhow from withdraw_tx entirely, and pushes the responsibility up to the caller to include the change output in the output set if desired. Consequently, we also remove the change output knowhow from hsmd. --- bitcoin/tx.c | 10 ++++++++++ bitcoin/tx.h | 3 +++ common/withdraw_tx.c | 43 +++++++++++++++++++++++++------------------ common/withdraw_tx.h | 8 +------- hsmd/hsm_wire.csv | 3 --- hsmd/hsmd.c | 14 +++----------- wallet/wallet.h | 2 -- wallet/walletrpc.c | 37 ++++++++++++++++++------------------- 8 files changed, 60 insertions(+), 60 deletions(-) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 0c27e89cf041..9f3f5992bc9d 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -14,6 +14,16 @@ #define SEGREGATED_WITNESS_FLAG 0x1 +struct bitcoin_tx_output *new_tx_output(const tal_t *ctx, + struct amount_sat amount, + const u8 *script) +{ + struct bitcoin_tx_output *output = tal(ctx, struct bitcoin_tx_output); + output->amount = amount; + output->script = tal_dup_arr(output, u8, script, tal_count(script), 0); + return output; +} + int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script, struct amount_sat amount) { diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 5e8f8d275527..2f2777f87553 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -43,6 +43,9 @@ struct bitcoin_tx_input { u8 **witness; }; +struct bitcoin_tx_output *new_tx_output(const tal_t *ctx, + struct amount_sat amount, + const u8 *script); /* SHA256^2 the tx: simpler than sha256_tx */ void bitcoin_txid(const struct bitcoin_tx *tx, struct bitcoin_txid *txid); diff --git a/common/withdraw_tx.c b/common/withdraw_tx.c index 17e992cf3209..edd6d8e6473c 100644 --- a/common/withdraw_tx.c +++ b/common/withdraw_tx.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -13,30 +14,36 @@ struct bitcoin_tx *withdraw_tx(const tal_t *ctx, const struct chainparams *chainparams, const struct utxo **utxos, struct bitcoin_tx_output **outputs, - const struct pubkey *changekey, - struct amount_sat change, - const struct ext_key *bip32_base, - int *change_outnum) + const struct ext_key *bip32_base) { struct bitcoin_tx *tx; + struct pubkey key; + u8 *script; + size_t i; - tx = tx_spending_utxos(ctx, chainparams, utxos, bip32_base, - !amount_sat_eq(change, AMOUNT_SAT(0)), - tal_count(outputs)); + assert(tal_count(utxos) > 0 && tal_count(outputs) > 0); + + tx = bitcoin_tx(ctx, chainparams, + tal_count(utxos), + tal_count(outputs)); + + /* Add our utxo's */ + for (i = 0; i < tal_count(utxos); i++) { + if (utxos[i]->is_p2sh && bip32_base) { + bip32_pubkey(bip32_base, &key, utxos[i]->keyindex); + script = bitcoin_scriptsig_p2sh_p2wpkh(tmpctx, &key); + } else { + script = NULL; + } + + bitcoin_tx_add_input(tx, &utxos[i]->txid, utxos[i]->outnum, + BITCOIN_TX_DEFAULT_SEQUENCE, + utxos[i]->amount, script); + } bitcoin_tx_add_multi_outputs(tx, outputs); + permute_outputs(tx, NULL, (const void **)outputs); - if (!amount_sat_eq(change, AMOUNT_SAT(0))) { - const void *map[2]; - map[0] = int2ptr(0); - map[1] = int2ptr(1); - bitcoin_tx_add_output(tx, scriptpubkey_p2wpkh(tmpctx, changekey), - change); - permute_outputs(tx, NULL, map); - if (change_outnum) - *change_outnum = ptr2int(map[1]); - } else if (change_outnum) - *change_outnum = -1; permute_inputs(tx, (const void **)utxos); elements_tx_add_fee_output(tx); assert(bitcoin_tx_check(tx)); diff --git a/common/withdraw_tx.h b/common/withdraw_tx.h index 71e218589697..fc1eb57a8120 100644 --- a/common/withdraw_tx.h +++ b/common/withdraw_tx.h @@ -21,18 +21,12 @@ struct utxo; * @chainparams: (in) the params for the created transaction. * @utxos: (in/out) tal_arr of UTXO pointers to spend (permuted to match) * @outputs: (in) tal_arr of bitcoin_tx_output, scriptPubKeys with amount to send to. - * @changekey: (in) key to send change to (only used if change_satoshis != 0). - * @change: (in) amount to send as change. * @bip32_base: (in) bip32 base for key derivation, or NULL. - * @change_outnum: (out) set to output index of change output or -1 if none, unless NULL. */ struct bitcoin_tx *withdraw_tx(const tal_t *ctx, const struct chainparams *chainparams, const struct utxo **utxos, struct bitcoin_tx_output **outputs, - const struct pubkey *changekey, - struct amount_sat change, - const struct ext_key *bip32_base, - int *change_outnum); + const struct ext_key *bip32_base); #endif /* LIGHTNING_COMMON_WITHDRAW_TX_H */ diff --git a/hsmd/hsm_wire.csv b/hsmd/hsm_wire.csv index e43d99114a59..dac781fe459d 100644 --- a/hsmd/hsm_wire.csv +++ b/hsmd/hsm_wire.csv @@ -67,9 +67,6 @@ msgdata,hsm_node_announcement_sig_reply,signature,secp256k1_ecdsa_signature, # Sign a withdrawal request msgtype,hsm_sign_withdrawal,7 -msgdata,hsm_sign_withdrawal,satoshi_out,amount_sat, -msgdata,hsm_sign_withdrawal,change_out,amount_sat, -msgdata,hsm_sign_withdrawal,change_keyindex,u32, msgdata,hsm_sign_withdrawal,num_outputs,u16, msgdata,hsm_sign_withdrawal,outputs,bitcoin_tx_output,num_outputs msgdata,hsm_sign_withdrawal,num_inputs,u16, diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 68fe59baa34d..e276bfc2151a 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -1640,25 +1640,17 @@ static struct io_plan *handle_sign_withdrawal_tx(struct io_conn *conn, struct client *c, const u8 *msg_in) { - struct amount_sat satoshi_out, change_out; - u32 change_keyindex; struct utxo **utxos; struct bitcoin_tx *tx; - struct pubkey changekey; struct bitcoin_tx_output **outputs; - if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, &satoshi_out, - &change_out, &change_keyindex, + if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, &outputs, &utxos)) return bad_req(conn, c, msg_in); - if (!bip32_pubkey(&secretstuff.bip32, &changekey, change_keyindex)) - return bad_req_fmt(conn, c, msg_in, - "Failed to get key %u", change_keyindex); - tx = withdraw_tx(tmpctx, c->chainparams, - cast_const2(const struct utxo **, utxos), outputs, - &changekey, change_out, NULL, NULL); + cast_const2(const struct utxo **, utxos), + outputs, NULL); sign_all_inputs(tx, utxos); diff --git a/wallet/wallet.h b/wallet/wallet.h index 61e4bb724310..55ee67ade222 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -63,8 +63,6 @@ struct unreleased_tx { /* The tx itself (unsigned initially) */ struct bitcoin_tx *tx; struct bitcoin_txid txid; - /* Index of change output, or -1 if none. */ - int change_outnum; }; /* Possible states for tracked outputs in the database. Not sure yet diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 863a0b3d21fc..98a3992e8b0e 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -84,9 +84,6 @@ static struct command_result *broadcast_and_wait(struct command *cmd, /* FIXME: hsm will sign almost anything, but it should really * fail cleanly (not abort!) and let us report the error here. */ u8 *msg = towire_hsm_sign_withdrawal(cmd, - utx->wtx->amount, - utx->wtx->change, - utx->wtx->change_key_index, cast_const2(const struct bitcoin_tx_output **, utx->outputs), utx->wtx->utxos); @@ -293,10 +290,8 @@ static struct command_result *json_prepare_tx(struct command *cmd, * Support only one output. */ if (destination) { outputs = tal_arr(tmpctx, struct bitcoin_tx_output *, 1); - outputs[0] = tal(outputs, struct bitcoin_tx_output); - outputs[0]->script = tal_steal(outputs[0], - cast_const(u8 *, destination)); - outputs[0]->amount = (*utx)->wtx->amount; + outputs[0] = new_tx_output(outputs, (*utx)->wtx->amount, + destination); out_len = tal_count(outputs[0]->script); goto create_tx; @@ -338,11 +333,9 @@ static struct command_result *json_prepare_tx(struct command *cmd, "'%.*s' is a invalid satoshi amount", t[2].end - t[2].start, buffer + t[2].start); + outputs[i] = new_tx_output(outputs, *amount, + cast_const(u8 *, destination)); out_len += tal_count(destination); - outputs[i] = tal(outputs, struct bitcoin_tx_output); - outputs[i]->amount = *amount; - outputs[i]->script = tal_steal(outputs[i], - cast_const(u8 *, destination)); /* In fact, the maximum amount of bitcoin satoshi is 2.1e15. * It can't be equal to/bigger than 2^64. @@ -368,8 +361,6 @@ static struct command_result *json_prepare_tx(struct command *cmd, } create_tx: - (*utx)->outputs = tal_steal(*utx, outputs); - if (chosen_utxos) result = wtx_from_utxos((*utx)->wtx, *feerate_per_kw, out_len, maxheight, @@ -386,18 +377,26 @@ static struct command_result *json_prepare_tx(struct command *cmd, if ((*utx)->wtx->all_funds) outputs[0]->amount = (*utx)->wtx->amount; + /* Add the change as the last output */ if (!amount_sat_eq((*utx)->wtx->change, AMOUNT_SAT(0))) { + struct bitcoin_tx_output *change_output; + changekey = tal(tmpctx, struct pubkey); if (!bip32_pubkey(cmd->ld->wallet->bip32_base, changekey, (*utx)->wtx->change_key_index)) return command_fail(cmd, LIGHTNINGD, "Keys generation failure"); - } else - changekey = NULL; + + change_output = new_tx_output(outputs, (*utx)->wtx->change, + scriptpubkey_p2wpkh(tmpctx, changekey)); + tal_arr_expand(outputs, *change_output); + } + + (*utx)->outputs = tal_steal(*utx, outputs); (*utx)->tx = withdraw_tx(*utx, get_chainparams(cmd->ld), - (*utx)->wtx->utxos, (*utx)->outputs, - changekey, (*utx)->wtx->change, - cmd->ld->wallet->bip32_base, - &(*utx)->change_outnum); + (*utx)->wtx->utxos, + (*utx)->outputs, + cmd->ld->wallet->bip32_base); + bitcoin_txid((*utx)->tx, &(*utx)->txid); return NULL; From f2467f127db59d1bd2e33828bb21e96cec28b693 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 16 Sep 2019 19:34:03 -0500 Subject: [PATCH 12/45] withdraw: add ability to have additional inputs on a tx Make it such that we can include other inputs on a transaction, sort them, and sign the ones we need. We're going to need this for dual-funded transactions. --- bitcoin/tx.h | 5 +++- common/withdraw_tx.c | 14 +++++++-- common/withdraw_tx.h | 5 +++- hsmd/hsm_wire.csv | 6 ++-- hsmd/hsmd.c | 66 +++++++++++++++++++++++++++++++++++++++--- tools/generate-wire.py | 1 + wallet/wallet.h | 2 ++ wallet/walletrpc.c | 10 ++++++- wire/fromwire.c | 33 +++++++++++++++++++-- wire/towire.c | 19 ++++++++++++ wire/wire.h | 4 ++- 11 files changed, 151 insertions(+), 14 deletions(-) diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 2f2777f87553..8db3ef8e75dc 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -39,8 +39,11 @@ struct bitcoin_tx_input { u8 *script; u32 sequence_number; - /* Only if BIP141 used. */ + /* If BIP141 used, or is external input */ u8 **witness; + + /* Needed for external inputs */ + struct amount_sat amount; }; struct bitcoin_tx_output *new_tx_output(const tal_t *ctx, diff --git a/common/withdraw_tx.c b/common/withdraw_tx.c index edd6d8e6473c..dd7933e9be23 100644 --- a/common/withdraw_tx.c +++ b/common/withdraw_tx.c @@ -13,8 +13,10 @@ struct bitcoin_tx *withdraw_tx(const tal_t *ctx, const struct chainparams *chainparams, const struct utxo **utxos, + struct bitcoin_tx_input **inputs, struct bitcoin_tx_output **outputs, - const struct ext_key *bip32_base) + const struct ext_key *bip32_base, + const void **input_map) { struct bitcoin_tx *tx; struct pubkey key; @@ -41,11 +43,19 @@ struct bitcoin_tx *withdraw_tx(const tal_t *ctx, utxos[i]->amount, script); } + /* Add 3rd party inputs */ + for (i = 0; i < tal_count(inputs); i++) { + bitcoin_tx_add_input(tx, &inputs[i]->txid, + inputs[i]->index, inputs[i]->sequence_number, + inputs[i]->amount, inputs[i]->script); + } + bitcoin_tx_add_multi_outputs(tx, outputs); permute_outputs(tx, NULL, (const void **)outputs); - permute_inputs(tx, (const void **)utxos); + permute_inputs(tx, input_map); elements_tx_add_fee_output(tx); + assert(bitcoin_tx_check(tx)); return tx; } diff --git a/common/withdraw_tx.h b/common/withdraw_tx.h index fc1eb57a8120..beaab58808aa 100644 --- a/common/withdraw_tx.h +++ b/common/withdraw_tx.h @@ -20,13 +20,16 @@ struct utxo; * @ctx: context to tal from. * @chainparams: (in) the params for the created transaction. * @utxos: (in/out) tal_arr of UTXO pointers to spend (permuted to match) + * @inputs: (in) tal_arr of inputs for this transaction, in addition to utxos. * @outputs: (in) tal_arr of bitcoin_tx_output, scriptPubKeys with amount to send to. * @bip32_base: (in) bip32 base for key derivation, or NULL. */ struct bitcoin_tx *withdraw_tx(const tal_t *ctx, const struct chainparams *chainparams, const struct utxo **utxos, + struct bitcoin_tx_input **inputs, struct bitcoin_tx_output **outputs, - const struct ext_key *bip32_base); + const struct ext_key *bip32_base, + const void **input_map); #endif /* LIGHTNING_COMMON_WITHDRAW_TX_H */ diff --git a/hsmd/hsm_wire.csv b/hsmd/hsm_wire.csv index dac781fe459d..4d6de1915970 100644 --- a/hsmd/hsm_wire.csv +++ b/hsmd/hsm_wire.csv @@ -67,10 +67,12 @@ msgdata,hsm_node_announcement_sig_reply,signature,secp256k1_ecdsa_signature, # Sign a withdrawal request msgtype,hsm_sign_withdrawal,7 +msgdata,hsm_sign_withdrawal,num_inputs,u16, +msgdata,hsm_sign_withdrawal,inputs,bitcoin_tx_input,num_inputs msgdata,hsm_sign_withdrawal,num_outputs,u16, msgdata,hsm_sign_withdrawal,outputs,bitcoin_tx_output,num_outputs -msgdata,hsm_sign_withdrawal,num_inputs,u16, -msgdata,hsm_sign_withdrawal,inputs,utxo,num_inputs +msgdata,hsm_sign_withdrawal,num_utxos,u16, +msgdata,hsm_sign_withdrawal,utxos,utxo,num_utxos msgtype,hsm_sign_withdrawal_reply,107 msgdata,hsm_sign_withdrawal_reply,tx,bitcoin_tx, diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index e276bfc2151a..98fea71127b7 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -1592,6 +1592,36 @@ static void sign_all_inputs(struct bitcoin_tx *tx, struct utxo **utxos) } } +/* For dual-funded transactions, we don't sign every input. Instead, + * we find the inputs that correspond with the utxos we have and sign + * only those + * */ +static void sign_our_inputs(struct bitcoin_tx *tx, struct utxo **utxos, + const void **map, size_t map_len) +{ + size_t i, j; + int input_index; + + assert(tx->wtx->num_inputs >= tal_count(utxos)); + assert(tal_count(utxos) <= map_len); + + /* We add utxos to the tx first, and then any other + * inputs. Thus, we can iterate through the map from zero upward + * to find the correct utxo placement to sign */ + for (i = 0; i < tal_count(utxos); i++) { + struct pubkey inkey; + struct bitcoin_signature sig; + + for (j = 0; j < map_len; j++) { + if (ptr2int(map[j]) == i) { + input_index = j; + break; + } + } + sign_input(tx, utxos[i], &inkey, &sig, input_index); + } +} + /*~ lightningd asks us to sign the transaction to fund a channel; it feeds us * the set of inputs and the local and remote pubkeys, and we sign it. */ static struct io_plan *handle_sign_funding_tx(struct io_conn *conn, @@ -1642,17 +1672,45 @@ static struct io_plan *handle_sign_withdrawal_tx(struct io_conn *conn, { struct utxo **utxos; struct bitcoin_tx *tx; + struct bitcoin_tx_input **inputs; struct bitcoin_tx_output **outputs; + size_t input_count, i, j; + int input_index; if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, - &outputs, &utxos)) + &inputs, &outputs, + &utxos)) return bad_req(conn, c, msg_in); + input_count = tal_count(utxos) + tal_count(inputs); + const void *map[input_count]; + for (i = 0; i < input_count; i++) + map[i] = int2ptr(i); + tx = withdraw_tx(tmpctx, c->chainparams, cast_const2(const struct utxo **, utxos), - outputs, NULL); - - sign_all_inputs(tx, utxos); + inputs, outputs, NULL, + (const void **)&map); + + /* Put our signatures on the transaction */ + sign_our_inputs(tx, utxos, (const void **)&map, input_count); + + /* Add any 3rd party signatures */ + for (i = 0; i < tal_count(inputs); i++) { + if (inputs[i]->witness) { + size_t offset = tal_count(utxos) + i; + + /* Find the index */ + for (j = 0; j < input_count; j++) { + if (ptr2int(map[j]) == offset) { + input_index = j; + break; + } + } + bitcoin_tx_input_set_witness(tx, input_index, + inputs[i]->witness); + } + } return req_reply(conn, c, take(towire_hsm_sign_withdrawal_reply(NULL, tx))); diff --git a/tools/generate-wire.py b/tools/generate-wire.py index 882350c03940..834fbed95519 100755 --- a/tools/generate-wire.py +++ b/tools/generate-wire.py @@ -221,6 +221,7 @@ class Type(FieldSet): 'per_peer_state', 'bitcoin_tx_output', 'exclude_entry', + 'bitcoin_tx_input', ] # Some BOLT types are re-typed based on their field name diff --git a/wallet/wallet.h b/wallet/wallet.h index 55ee67ade222..438b85b53991 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -60,6 +60,8 @@ struct unreleased_tx { struct wallet_tx *wtx; /* Outputs(scriptpubkey and satoshi) this pays to. */ struct bitcoin_tx_output **outputs; + /* Non-utxo inputs for this tx (i.e. not our wallet) */ + struct bitcoin_tx_input **inputs; /* The tx itself (unsigned initially) */ struct bitcoin_tx *tx; struct bitcoin_txid txid; diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 98a3992e8b0e..3a66e02aeb82 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -81,9 +81,15 @@ static struct command_result *broadcast_and_wait(struct command *cmd, struct bitcoin_tx *signed_tx; struct bitcoin_txid signed_txid; + /* Build input set */ + if (!utx->inputs) + utx->inputs = tal_arr(utx, struct bitcoin_tx_input *, 0); + /* FIXME: hsm will sign almost anything, but it should really * fail cleanly (not abort!) and let us report the error here. */ u8 *msg = towire_hsm_sign_withdrawal(cmd, + cast_const2(const struct bitcoin_tx_input **, + utx->inputs), cast_const2(const struct bitcoin_tx_output **, utx->outputs), utx->wtx->utxos); @@ -394,8 +400,10 @@ static struct command_result *json_prepare_tx(struct command *cmd, (*utx)->outputs = tal_steal(*utx, outputs); (*utx)->tx = withdraw_tx(*utx, get_chainparams(cmd->ld), (*utx)->wtx->utxos, + (*utx)->inputs, (*utx)->outputs, - cmd->ld->wallet->bip32_base); + cmd->ld->wallet->bip32_base, + NULL); bitcoin_txid((*utx)->tx, &(*utx)->txid); diff --git a/wire/fromwire.c b/wire/fromwire.c index 9fadeeb6b67c..37627ded57b8 100644 --- a/wire/fromwire.c +++ b/wire/fromwire.c @@ -384,10 +384,12 @@ void fromwire_bip32_key_version(const u8** cursor, size_t *max, struct bitcoin_tx_output *fromwire_bitcoin_tx_output(const tal_t *ctx, const u8 **cursor, size_t *max) { + u16 script_len; + struct bitcoin_tx_output *output = tal(ctx, struct bitcoin_tx_output); output->amount = fromwire_amount_sat(cursor, max); - u16 script_len = fromwire_u16(cursor, max); - output->script = tal_arr(output, u8, script_len); + script_len = fromwire_u16(cursor, max); + output->script = script_len ? tal_arr(output, u8, script_len) : NULL; fromwire_u8_array(cursor, max, output->script, script_len); return output; } @@ -399,3 +401,30 @@ void fromwire_chainparams(const u8 **cursor, size_t *max, fromwire_bitcoin_blkid(cursor, max, &genesis); *chainparams = chainparams_by_chainhash(&genesis); } + +struct bitcoin_tx_input *fromwire_bitcoin_tx_input(const tal_t *ctx, + const u8 **cursor, size_t *max) +{ + u16 script_len; + u16 witness_count; + u16 witness_len; + + struct bitcoin_tx_input *input = tal(ctx, struct bitcoin_tx_input); + + fromwire_bitcoin_txid(cursor, max, &input->txid); + input->index = fromwire_u32(cursor, max); + script_len = fromwire_u16(cursor, max); + input->script = script_len ? tal_arr(input, u8, script_len) : NULL; + fromwire_u8_array(cursor, max, input->script, script_len); + input->sequence_number = fromwire_u32(cursor, max); + + witness_count = fromwire_u16(cursor, max); + input->witness = witness_count ? tal_arr(input, u8 *, witness_count) : NULL; + for (size_t i = 0; i < witness_count; i++) { + witness_len = fromwire_u16(cursor, max); + input->witness[i] = witness_len ? tal_arr(input->witness, u8, witness_len) : NULL; + fromwire_u8_array(cursor, max, input->witness[i], witness_len); + } + input->amount = fromwire_amount_sat(cursor, max); + return input; +} diff --git a/wire/towire.c b/wire/towire.c index 09f689d612b0..2bff00c23f44 100644 --- a/wire/towire.c +++ b/wire/towire.c @@ -261,3 +261,22 @@ void towire_chainparams(u8 **cursor, const struct chainparams *chainparams) { towire_bitcoin_blkid(cursor, &chainparams->genesis_blockhash); } + +void towire_bitcoin_tx_input(u8 **pptr, const struct bitcoin_tx_input *input) +{ + u16 script_len = tal_count(input->script); + u16 witness_len; + + towire_bitcoin_txid(pptr, &input->txid); + towire_u32(pptr, input->index); + towire_u16(pptr, script_len); + towire_u8_array(pptr, input->script, script_len); + towire_u32(pptr, input->sequence_number); + towire_u16(pptr, tal_count(input->witness)); + for (size_t i = 0; i < tal_count(input->witness); i++) { + witness_len = tal_count(input->witness[i]); + towire_u16(pptr, witness_len); + towire_u8_array(pptr, input->witness[i], witness_len); + } + towire_amount_sat(pptr, input->amount); +} diff --git a/wire/wire.h b/wire/wire.h index e71f2659106b..1e608b874fb9 100644 --- a/wire/wire.h +++ b/wire/wire.h @@ -143,8 +143,10 @@ void fromwire_bip32_key_version(const u8 **cursor, size_t *max, struct bip32_key_version *version); struct bitcoin_tx_output *fromwire_bitcoin_tx_output(const tal_t *ctx, const u8 **cursor, size_t *max); - void fromwire_chainparams(const u8 **cursor, size_t *max, const struct chainparams **chainparams); +void towire_bitcoin_tx_input(u8 **pptr, const struct bitcoin_tx_input *input); +struct bitcoin_tx_input *fromwire_bitcoin_tx_input(const tal_t *ctx, + const u8 **cursor, size_t *max); #endif /* LIGHTNING_WIRE_WIRE_H */ From eafbeb97c993e7840227cf00f6af6fa16ffb78a4 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Tue, 17 Sep 2019 15:46:58 -0500 Subject: [PATCH 13/45] walletrpc: break out output extraction code pull up output parser into reusable method --- wallet/walletrpc.c | 82 ++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 3a66e02aeb82..83314b1e16e1 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -124,6 +124,47 @@ static struct command_result *broadcast_and_wait(struct command *cmd, return command_still_pending(cmd); } +/* Extract an output. Format: {destination: amount} */ +static struct command_result *extract_output(const tal_t *ctx, + struct command *cmd, + const char *buffer, + const jsmntok_t *t, + struct bitcoin_tx_output **output) +{ + + struct amount_sat *amount; + const u8 *destination; + enum address_parse_result res; + + if (t->type != JSMN_OBJECT) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "The output format must be " + "{destination: amount}");; + + res = json_to_address_scriptpubkey(cmd, + get_chainparams(cmd->ld), + buffer, &t[1], + &destination); + + if (res == ADDRESS_PARSE_UNRECOGNIZED) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Could not parse destination address"); + else if (res == ADDRESS_PARSE_WRONG_NETWORK) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Destination address is not on network %s", + get_chainparams(cmd->ld)->network_name); + + amount = tal(tmpctx, struct amount_sat); + if (!json_to_sat_or_all(buffer, &t[2], amount)) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "'%.*s' is a invalid satoshi amount", + t[2].end - t[2].start, buffer + t[2].start); + + *output = new_tx_output(ctx, *amount, destination); + return NULL; +} + + /* Common code for withdraw and txprepare. * * Returns NULL on success, and fills in wtx, output and @@ -311,44 +352,21 @@ static struct command_result *json_prepare_tx(struct command *cmd, (*utx)->wtx->all_funds = false; (*utx)->wtx->amount = AMOUNT_SAT(0); json_for_each_arr(i, t, outputstok) { - struct amount_sat *amount; - const u8 *destination; - enum address_parse_result res; + struct bitcoin_tx_output *output; - /* output format: {destination: amount} */ - if (t->type != JSMN_OBJECT) - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "The output format must be " - "{destination: amount}"); - - res = json_to_address_scriptpubkey(cmd, - get_chainparams(cmd->ld), - buffer, &t[1], - &destination); - if (res == ADDRESS_PARSE_UNRECOGNIZED) - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Could not parse destination address"); - else if (res == ADDRESS_PARSE_WRONG_NETWORK) - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Destination address is not on network %s", - get_chainparams(cmd->ld)->network_name); - - amount = tal(tmpctx, struct amount_sat); - if (!json_to_sat_or_all(buffer, &t[2], amount)) - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "'%.*s' is a invalid satoshi amount", - t[2].end - t[2].start, buffer + t[2].start); + result = extract_output(outputs, cmd, buffer, t, &output); + if (result) + return result; - outputs[i] = new_tx_output(outputs, *amount, - cast_const(u8 *, destination)); - out_len += tal_count(destination); + outputs[i] = output; + out_len += tal_count(output->script); /* In fact, the maximum amount of bitcoin satoshi is 2.1e15. * It can't be equal to/bigger than 2^64. * On the hand, the maximum amount of litoshi is 8.4e15, * which also can't overflow. */ /* This means this destination need "all" satoshi we have. */ - if (amount_sat_eq(*amount, AMOUNT_SAT(-1ULL))) { + if (amount_sat_eq(output->amount, AMOUNT_SAT(-1ULL))) { if (outputstok->size > 1) return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "outputs[%zi]: this destination wants" @@ -356,11 +374,11 @@ static struct command_result *json_prepare_tx(struct command *cmd, " can't be more than 1. ", i); (*utx)->wtx->all_funds = true; /* `AMOUNT_SAT(-1ULL)` is the max permissible for `wallet_select_all`. */ - (*utx)->wtx->amount = *amount; + (*utx)->wtx->amount = output->amount; break; } - if (!amount_sat_add(&(*utx)->wtx->amount, (*utx)->wtx->amount, *amount)) + if (!amount_sat_add(&(*utx)->wtx->amount, (*utx)->wtx->amount, output->amount)) return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "outputs: The sum of first %zi outputs" " overflow. ", i); From b3c5438be67c38f8795c561e0e0f044e0a9622e6 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 18 Sep 2019 19:05:47 -0500 Subject: [PATCH 14/45] funding: add method for building a dual-funded tx Function and helpers for making a dual funded funding tx --- common/funding_tx.c | 271 +++++++++++ common/funding_tx.h | 37 ++ common/test/run-funding_tx_dual.c | 768 ++++++++++++++++++++++++++++++ 3 files changed, 1076 insertions(+) create mode 100644 common/test/run-funding_tx_dual.c diff --git a/common/funding_tx.c b/common/funding_tx.c index 97e7711e6d22..944e890d0029 100644 --- a/common/funding_tx.c +++ b/common/funding_tx.c @@ -3,8 +3,11 @@ #include #include #include +#include #include +#include #include +#include #include #ifndef SUPERVERBOSE @@ -53,3 +56,271 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx, assert(bitcoin_tx_check(tx)); return tx; } + +#if EXPERIMENTAL_FEATURES +/* We leave out the change addresses if there's no change left after fees */ +static size_t calculate_input_weights(struct input_info **inputs, + struct amount_sat *total) +{ + u32 input_weight; + u64 scriptlen; + size_t weight = 0, i = 0; + + *total = AMOUNT_SAT(0); + for (i = 0; i < tal_count(inputs); i++) { + /* prev_out hash + index + sequence */ + input_weight = (32 + 4 + 4) * 4; + + if (inputs[i]->script) { + scriptlen = tal_bytelen(inputs[i]->script); + input_weight += (scriptlen + varint_size(scriptlen)) * 4; + } else { + /* 00 byte script_sig len */ + input_weight += 1 * 4; + } + + input_weight += inputs[i]->max_witness_len; + weight += input_weight; + + assert(amount_sat_add(total, *total, inputs[i]->input_satoshis)); + } + + return weight; +} + +static size_t calculate_output_weights(struct output_info **outputs) +{ + size_t i, output_weights = 0, scriptlen; + + for (i = 0; i < tal_count(outputs); i++) { + scriptlen = tal_bytelen(outputs[i]->script); + /* amount field + script + scriptlen varint */ + output_weights += (8 + scriptlen + varint_size(scriptlen)) * 4; + } + + return output_weights; +} + +static size_t calculate_weight(struct input_info **opener_inputs, + struct input_info **accepter_inputs, + struct output_info **opener_outputs, + struct output_info **accepter_outputs, + struct amount_sat *opener_total, + struct amount_sat *accepter_total) + +{ + size_t weight; + + /* version, input count, output count, locktime */ + weight = (4 + 1 + 1 + 4) * 4; + + /* add segwit fields: marker + flag */ + weight += 1 + 1; + + weight += calculate_input_weights(opener_inputs, opener_total); + weight += calculate_input_weights(accepter_inputs, accepter_total); + + /* channel funding output: amount, len, scriptpubkey */ + weight += (8 + 1 + BITCOIN_SCRIPTPUBKEY_P2WSH_LEN) * 4; + + weight += calculate_output_weights(opener_outputs); + weight += calculate_output_weights(accepter_outputs); + + return weight; +} + +static const struct output_info *find_change_output(struct output_info **outputs) +{ + size_t i = 0; + for (i = 0; i < tal_count(outputs); i++) { + if (amount_sat_eq(outputs[i]->output_satoshis, AMOUNT_SAT(0))) + return outputs[i]; + } + return NULL; +} + +static struct amount_sat calculate_output_value(struct output_info **outputs) +{ + size_t i = 0; + struct amount_sat total = AMOUNT_SAT(0); + + for (i = 0; i < tal_count(outputs); i++) { + assert(amount_sat_add(&total, total, outputs[i]->output_satoshis)); + } + return total; +} + +static void add_inputs(struct bitcoin_tx *tx, struct input_info **inputs) +{ + size_t i = 0; + for (i = 0; i < tal_count(inputs); i++) { + bitcoin_tx_add_input(tx, &inputs[i]->prevtx_txid, inputs[i]->prevtx_vout, + BITCOIN_TX_DEFAULT_SEQUENCE, + inputs[i]->input_satoshis, inputs[i]->script); + } +} + +static void add_outputs(struct bitcoin_tx *tx, struct output_info **outputs, + const struct amount_sat *change) +{ + size_t i = 0; + u8 *script; + struct amount_sat value; + + for (i = 0; i < tal_count(outputs); i++) { + /* Is this the change output?? */ + if (change && amount_sat_eq(outputs[i]->output_satoshis, AMOUNT_SAT(0))) { + /* If there's no change amount, we leave it out */ + if (amount_sat_eq(*change, AMOUNT_SAT(0))) + continue; + value = *change; + } else + value = outputs[i]->output_satoshis; + + script = tal_dup_arr(tx, u8, outputs[i]->script, + tal_count(outputs[i]->script), 0); + bitcoin_tx_add_output(tx, script, value); + } +} + +struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, + const struct chainparams *chainparams, + u16 *outnum, + u32 feerate_kw_funding, + struct amount_sat *opener_funding, + struct amount_sat accepter_funding, + struct input_info **opener_inputs, + struct input_info **accepter_inputs, + struct output_info **opener_outputs, + struct output_info **accepter_outputs, + const struct pubkey *local_fundingkey, + const struct pubkey *remote_fundingkey, + struct amount_sat *total_funding, + const void **input_map) +{ + size_t weight; + struct amount_sat funding_tx_fee, opener_total_sat, + accepter_total_sat, + opener_change, output_val; + struct bitcoin_tx *tx; + const struct output_info *change_output; + + size_t i = 0; + u64 scriptlen; + u32 input_count, output_count; + u8 *wscript; + + /* First, we calculate the weight of the transaction, with change outputs */ + weight = calculate_weight(opener_inputs, accepter_inputs, + opener_outputs, accepter_outputs, + &opener_total_sat, &accepter_total_sat); + funding_tx_fee = amount_tx_fee(feerate_kw_funding, weight); + + if (!amount_sat_sub(&opener_change, opener_total_sat, *opener_funding)) + return NULL; + + /* Check that the remaining amount at least covers the other + * indicated output values. We have to cover these other + * outputs, as they might be other funding transaction outputs. The + * only 'flexible' / change output that's removable etc is indicated + * by a zero value. */ + output_val = calculate_output_value(opener_outputs); + if (!amount_sat_sub(&opener_change, opener_change, output_val)) + return NULL; + + change_output = find_change_output(opener_outputs); + if (amount_sat_sub(&opener_change, opener_change, funding_tx_fee) && + amount_sat_greater(opener_change, chainparams->dust_limit)) { + if (!change_output) { + /* If there's no change output, we put the remainder into + * the funding output. TODO: add to spec */ + assert(amount_sat_add(opener_funding, + *opener_funding, opener_change)); + opener_change = AMOUNT_SAT(0); + } + + goto build_tx; + } + + /* Try removing opener's change output to fit fees */ + if (change_output) { + scriptlen = tal_count(change_output->script); + weight -= (8 + scriptlen + varint_size(scriptlen)) * 4; + funding_tx_fee = amount_tx_fee(feerate_kw_funding, weight); + + /* Any left over gets added to the funding output */ + if (amount_sat_sub(&opener_change, opener_change, funding_tx_fee)) { + assert(amount_sat_add(opener_funding, *opener_funding, opener_change)); + opener_change = AMOUNT_SAT(0); + goto build_tx; + } + } + + if (!amount_sat_sub(opener_funding, opener_total_sat, funding_tx_fee) || + !amount_sat_sub(opener_funding, *opener_funding, output_val)) + return NULL; + + opener_change = AMOUNT_SAT(0); + +build_tx: + input_count = tal_count(opener_inputs) + tal_count(accepter_inputs); + /* opener + accepter outputs plus the funding output */ + output_count = tal_count(opener_outputs) + + tal_count(accepter_outputs) + 1; + + /* If they had supplied a change output, but we removed it because + * remove it from the count */ + if (change_output && amount_sat_eq(AMOUNT_SAT(0), opener_change)) { + output_count -= 1; + assert(output_count > 0); + } + + tx = bitcoin_tx(ctx, chainparams, input_count, output_count); + + /* Add the funding output */ + wscript = bitcoin_redeem_2of2(tx, local_fundingkey, remote_fundingkey); + SUPERVERBOSE("# funding witness script = %s\n", + tal_hex(wscript, wscript)); + + *total_funding = *opener_funding; + assert(amount_sat_add(total_funding, *total_funding, accepter_funding)); + + /* Last check, make sure our funding output is greater than + * the dust limit */ + if (!amount_sat_greater(*total_funding, chainparams->dust_limit)) + return NULL; + + + const void *o_map[output_count]; + for (i = 0; i < output_count; i++) + o_map[i] = int2ptr(i); + + bitcoin_tx_add_output(tx, scriptpubkey_p2wsh(tx, wscript), *total_funding); + + /* Add the other outputs */ + add_outputs(tx, opener_outputs, &opener_change); + add_outputs(tx, accepter_outputs, NULL); + + /* Note that hsmd depends on the opener's inputs + * being added before the accepter's inputs */ + add_inputs(tx, opener_inputs); + add_inputs(tx, accepter_inputs); + + /* Sort inputs */ + permute_inputs(tx, input_map); + + /* Sort outputs */ + permute_outputs(tx, NULL, o_map); + + for (i = 0; i < output_count; i++) { + if (o_map[i] == int2ptr(0)) { + if (outnum) + *outnum = i; + break; + } + } + + assert(bitcoin_tx_check(tx)); + return tx; +} +#endif /* EXPERIMENTAL_FEATURES */ diff --git a/common/funding_tx.h b/common/funding_tx.h index 577a4cafb2ee..93cefc72941d 100644 --- a/common/funding_tx.h +++ b/common/funding_tx.h @@ -5,6 +5,9 @@ #include #include #include +#if EXPERIMENTAL_FEATURES +#include +#endif /* EXPERIMENTAL_FEATURES */ struct bitcoin_tx; struct ext_key; @@ -44,4 +47,38 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx, struct amount_sat change, const struct pubkey *changekey, const struct ext_key *bip32_base); + +#if EXPERIMENTAL_FEATURES +/** + * funding_tx: create a P2WSH funding transaction for a channel. + * @ctx: context to tal from. + * @chainparams: (in) the params for the resulting transaction. + * @outnum: (out) txout which is the funding output. + * @feerate_kw_funding: (in) feerate for the funding transaction + * @total_funding: (out) total funding amount for this transaction + * @opener_funding: (in/out) funding amount contributed by opener + * @accepter_funding: (in) funding amount contributed by accepter + * @opener_inputs: (in) inputs from the opener + * @accepter_inputs: (in) inputs from the accepter + * @opener_outputs: (in) outputs for the opener + * @accepter_outputs: (in) outputs for the accepter + * @local_fundingkey: (in) local key for 2of2 funding output. + * @remote_fundingkey: (in) remote key for 2of2 funding output. + * @input_map: (out) ordering of inputs, after being sorted. + */ +struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, + const struct chainparams *chainparams, + u16 *outnum, + u32 feerate_kw_funding, + struct amount_sat *opener_funding, + struct amount_sat accepter_funding, + struct input_info **opener_inputs, + struct input_info **accepter_inputs, + struct output_info **opener_outputs, + struct output_info **accepter_outputs, + const struct pubkey *local_fundingkey, + const struct pubkey *remote_fundingkey, + struct amount_sat *total_funding, + const void **input_map); +#endif /* EXPERIMENTAL_FEATURES */ #endif /* LIGHTNING_COMMON_FUNDING_TX_H */ diff --git a/common/test/run-funding_tx_dual.c b/common/test/run-funding_tx_dual.c new file mode 100644 index 000000000000..9cd10854d8d5 --- /dev/null +++ b/common/test/run-funding_tx_dual.c @@ -0,0 +1,768 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../amount.c" +#define SUPERVERBOSE printf +#include "../funding_tx.c" +#undef SUPERVERBOSE +#include "../key_derive.c" +#include "../type_to_string.c" +#include "../permute_tx.c" +#include "../utxo.c" + +/* AUTOGENERATED MOCKS START */ +/* Generated stub for fromwire_amount_sat */ +struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); } +/* Generated stub for fromwire_bitcoin_txid */ +void fromwire_bitcoin_txid(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "fromwire_bitcoin_txid 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 */ +const void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_fail called!\n"); abort(); } +/* Generated stub for fromwire_node_id */ +void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED) +{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); } +/* Generated stub for fromwire_pubkey */ +void fromwire_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct pubkey *pubkey UNNEEDED) +{ fprintf(stderr, "fromwire_pubkey 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 towire_amount_sat */ +void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED) +{ fprintf(stderr, "towire_amount_sat called!\n"); abort(); } +/* Generated stub for towire_bitcoin_txid */ +void towire_bitcoin_txid(u8 **pptr UNNEEDED, const struct bitcoin_txid *txid UNNEEDED) +{ fprintf(stderr, "towire_bitcoin_txid 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_node_id */ +void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "towire_node_id called!\n"); abort(); } +/* Generated stub for towire_pubkey */ +void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED) +{ fprintf(stderr, "towire_pubkey 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(); } +/* AUTOGENERATED MOCKS END */ + +struct test_case { + struct input_info **opener_inputs; + struct input_info **accepter_inputs; + struct output_info **opener_outputs; + struct output_info **accepter_outputs; + struct amount_sat opener_funding; + struct amount_sat accepter_funding; + struct amount_sat expected_funding; + struct bitcoin_tx *expected_tx; + char *local_pubkey_str; + char *remote_pubkey_str; + u32 feerate; +}; + +#if EXPERIMENTAL_FEATURES +static u8 *hex_to_u8(const tal_t *ctx, char *str) +{ + return tal_hexdata(ctx, str, strlen(str)); +} + +/* Test case from the 03 Appendix F, in the RFC */ +/* FIXME: add bolt reference for this */ +static struct test_case test1(const tal_t *ctx) +{ + struct bitcoin_txid txid; + bitcoin_txid_from_hex("4303ca8ff10c6c345b9299672a66f111c5b81ae027cc5b0d4d39d09c66b032b9", + strlen("4303ca8ff10c6c345b9299672a66f111c5b81ae027cc5b0d4d39d09c66b032b9"), + &txid); + + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 2); + struct input_info *input_one = tal(ctx, struct input_info); + input_one->input_satoshis = AMOUNT_SAT(250000000); + input_one->prevtx_txid = txid; + input_one->prevtx_vout = 0; + input_one->prevtx_scriptpubkey = hex_to_u8(ctx, "220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b946"); + input_one->max_witness_len = 75; + input_one->script = NULL; + opener_inputs[0] = input_one; + + struct input_info *input_two = tal(ctx, struct input_info); + input_two->input_satoshis = AMOUNT_SAT(250000000); + input_two->prevtx_txid = txid; + input_two->prevtx_vout = 1; + input_two->prevtx_scriptpubkey = hex_to_u8(ctx, "a9146a235d064786b49e7043e4a042d4cc429f7eb69487"); + input_two->max_witness_len = 75; + input_two->script = hex_to_u8(ctx, "220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b946"); + opener_inputs[1] = input_two; + + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 2); + struct input_info *input_three = tal(ctx, struct input_info); + input_three->input_satoshis = AMOUNT_SAT(250000000); + input_three->prevtx_txid = txid; + input_three->prevtx_vout = 2; + input_three->prevtx_scriptpubkey = hex_to_u8(ctx, "160014fbb4db9d85fba5e301f4399e3038928e44e37d32"); + input_three->max_witness_len = 109; + input_three->script = NULL; + accepter_inputs[0] = input_three; + + struct input_info *input_four = tal(ctx, struct input_info); + input_four->input_satoshis = AMOUNT_SAT(250000000); + input_four->prevtx_txid = txid; + input_four->prevtx_vout = 3; + input_four->prevtx_scriptpubkey = hex_to_u8(ctx, "a9147ecd1b519326bc13b0ec716e469b58ed02b112a087"); + input_four->max_witness_len = 109; + input_four->script = hex_to_u8(ctx, "160014fbb4db9d85fba5e301f4399e3038928e44e37d32"); + accepter_inputs[1] = input_four; + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 1); + struct output_info *output_one = tal(ctx, struct output_info); + output_one->output_satoshis = AMOUNT_SAT(0); + output_one->script = hex_to_u8(ctx, "00141ca1cca8855bad6bc1ea5436edd8cff10b7e448b"); + opener_outputs[0] = output_one; + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + struct output_info *output_two = tal(ctx, struct output_info); + output_two->output_satoshis = AMOUNT_SAT(200000000); + output_two->script = hex_to_u8(ctx, "001444cb0c39f93ecc372b5851725bd29d865d333b10"); + accepter_outputs[0] = output_two; + + char *expected_tx_str = "0200000004b932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430000000000ffffffffb932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430100000023220020fd89acf65485df89797d9ba7ba7a33624ac4452f00db08107f34257d33e5b946ffffffffb932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430200000000ffffffffb932b0669cd0394d0d5bcc27e01ab8c511f1662a6799925b346c0cf18fca03430300000017160014fbb4db9d85fba5e301f4399e3038928e44e37d32ffffffff03ea7f0100000000001600141ca1cca8855bad6bc1ea5436edd8cff10b7e448b00c2eb0b0000000016001444cb0c39f93ecc372b5851725bd29d865d333b106081ad2f00000000220020297b92c238163e820b82486084634b4846b86a3c658d87b9384192e6bea98ec500000000"; + struct test_case test1 = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(499900000), + .accepter_funding = AMOUNT_SAT(300000000), + .expected_funding = AMOUNT_SAT(799900000), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "02e16172a41e928cbd78f761bd1c657c4afc7495a1244f7f30166b654fbf7661e3", + .local_pubkey_str = "0292edb5f7bbf9e900f7e024be1c1339c6d149c11930e613af3a983d2565f4e41e", + }; + + assert(test1.expected_tx); + + return test1; +} + +/* The following inputs are build off of two prior transactions, depending + * on how many inputs there are from the 'accepter' side */ +const char* txid_str_one = "6c39988c96f100fbd1cc4ba47f73e3410922a9b41db07e80530a47fb71da053f"; +const char* txid_str_two = "07f983eea2be59f6aada611475df69c11f5f95aac5a04ff769effbf24ae9e951"; + +static struct input_info *input_one(const tal_t *ctx, int vout, const char* txid_str) +{ + struct bitcoin_txid txid; + bitcoin_txid_from_hex(txid_str, strlen(txid_str), &txid); + struct input_info *input_one = tal(ctx, struct input_info); + input_one->input_satoshis = AMOUNT_SAT(500000); + input_one->prevtx_txid = txid; + input_one->prevtx_vout = vout; + input_one->prevtx_scriptpubkey = hex_to_u8(ctx, "0014ca5cc81df579bd589a428c0d29dceb81513fce8d"); + input_one->max_witness_len = 109; + input_one->script = NULL; + return input_one; +} + +static struct input_info *input_two(const tal_t *ctx, const char *txid_str) +{ + struct bitcoin_txid txid; + bitcoin_txid_from_hex(txid_str, strlen(txid_str), &txid); + + struct input_info *input_two = tal(ctx, struct input_info); + input_two->input_satoshis = AMOUNT_SAT(1000000); + input_two->prevtx_txid = txid; + input_two->prevtx_vout = 0; + input_two->prevtx_scriptpubkey = hex_to_u8(ctx, "001483440596268132e6c99d44dae2d151dabd9a2b23"); + input_two->max_witness_len = 109; + input_two->script = NULL; + return input_two; +} + +static struct input_info *input_three(const tal_t *ctx, int vout, const char *txid_str) +{ + struct bitcoin_txid txid; + bitcoin_txid_from_hex(txid_str, strlen(txid_str), &txid); + + struct input_info *input = tal(ctx, struct input_info); + input->input_satoshis = AMOUNT_SAT(1500000); + input->prevtx_txid = txid; + input->prevtx_vout = vout; + input->prevtx_scriptpubkey = hex_to_u8(ctx, "0014d1f40e954d7a792284b6fb19a2e0bf777441d83e"); + input->max_witness_len = 109; + input->script = NULL; + return input; +} + +/* Input four only exists on the 'second' transaction */ +static struct input_info *input_four(const tal_t *ctx) +{ + struct bitcoin_txid txid; + bitcoin_txid_from_hex(txid_str_two, strlen(txid_str_two), &txid); + + struct input_info *input = tal(ctx, struct input_info); + input->input_satoshis = AMOUNT_SAT(2000000); + input->prevtx_txid = txid; + input->prevtx_vout = 1; + input->prevtx_scriptpubkey = hex_to_u8(ctx, "0014fd9658fbd476d318f3b825b152b152aafa49bc92"); + input->max_witness_len = 109; + input->script = NULL; + return input; +} + +static struct output_info *output_one(const tal_t *ctx, u64 amount) +{ + struct output_info *output_one = tal(ctx, struct output_info); + output_one->output_satoshis = (struct amount_sat){ amount }; + output_one->script = hex_to_u8(ctx, "00140f0963bc774334ebc14d11ce940c35cfa6986415"); + return output_one; +} + +static struct output_info *output_two(const tal_t *ctx, u64 amount) +{ + struct output_info *output = tal(ctx, struct output_info); + output->output_satoshis = (struct amount_sat){ amount }; + output->script = hex_to_u8(ctx, "0014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5"); + return output; +} + +static struct output_info *output_three(const tal_t *ctx, u64 amount) +{ + struct output_info *output = tal(ctx, struct output_info); + output->output_satoshis = (struct amount_sat){ amount }; + output->script = hex_to_u8(ctx, "0014d295f76da2319791f36df5759e45b15d5e105221"); + return output; +} + +/* Check that change filled in correctly */ +static struct test_case test2(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 1); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + accepter_inputs[0] = input_two(ctx, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 1); + opener_outputs[0] = output_one(ctx, 0); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + accepter_outputs[0] = output_two(ctx, 10000); + + char *expected_tx_str = "02000000023f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0000000000ffffffff3f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff0311260000000000001600140f0963bc774334ebc14d11ce940c35cfa69864151027000000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d54095160000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 253, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(490000), + .accepter_funding = AMOUNT_SAT(990000), + .expected_funding = AMOUNT_SAT(1480000), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* No change passed in, but output is exactly correct */ +static struct test_case test3(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 1); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + accepter_inputs[0] = input_two(ctx, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 1); + opener_outputs[0] = output_one(ctx, 9745); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + accepter_outputs[0] = output_two(ctx, 10000); + + char *expected_tx_str = "02000000023f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0000000000ffffffff3f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff0311260000000000001600140f0963bc774334ebc14d11ce940c35cfa69864151027000000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d54095160000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 253, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(490000), + .accepter_funding = AMOUNT_SAT(990000), + .expected_funding = AMOUNT_SAT(1480000), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* No change passed in, output is a little too big, funding impacted */ +static struct test_case test_no_change(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 1); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + accepter_inputs[0] = input_two(ctx, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 1); + opener_outputs[0] = output_one(ctx, 5000); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + accepter_outputs[0] = output_two(ctx, 10000); + + char *expected_tx_str = "02000000023f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0000000000ffffffff3f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff0388130000000000001600140f0963bc774334ebc14d11ce940c35cfa69864151027000000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5d8a4160000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(493000), + .accepter_funding = AMOUNT_SAT(990000), + .expected_funding = AMOUNT_SAT(1483992.0), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* With change */ +static struct test_case test_change(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 1); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + accepter_inputs[0] = input_two(ctx, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 2); + opener_outputs[0] = output_one(ctx, 5000); + opener_outputs[1] = output_three(ctx, 0); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + accepter_outputs[0] = output_two(ctx, 10000); + + char *expected_tx_str = "02000000023f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0000000000ffffffff3f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff046403000000000000160014d295f76da2319791f36df5759e45b15d5e10522188130000000000001600140f0963bc774334ebc14d11ce940c35cfa69864151027000000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5f8a0160000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(493000), + .accepter_funding = AMOUNT_SAT(990000), + .expected_funding = AMOUNT_SAT(1483000), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* With change trimmed, funding decreases */ +static struct test_case test_change_trimmed(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 1); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + accepter_inputs[0] = input_two(ctx, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 2); + opener_outputs[0] = output_one(ctx, 5000); + opener_outputs[1] = output_three(ctx, 0); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + accepter_outputs[0] = output_two(ctx, 10000); + + char *expected_tx_str = "02000000023f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0000000000ffffffff3f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff0388130000000000001600140f0963bc774334ebc14d11ce940c35cfa69864151027000000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d56881160000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 10000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(493000), + .accepter_funding = AMOUNT_SAT(990000), + .expected_funding = AMOUNT_SAT(1474920.0), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + + +/* With change trimmed, funding increases */ +static struct test_case test_change_trimmed_positive(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 1); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + accepter_inputs[0] = input_two(ctx, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 2); + opener_outputs[0] = output_one(ctx, 5000); + opener_outputs[1] = output_three(ctx, 0); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + accepter_outputs[0] = output_two(ctx, 10000); + + + // fee = 1310 + // change = 0 + char *expected_tx_str = "02000000023f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0000000000ffffffff3f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff0388130000000000001600140f0963bc774334ebc14d11ce940c35cfa69864151027000000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5aaa3160000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 1300, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(493000), + .accepter_funding = AMOUNT_SAT(990000), + .expected_funding = AMOUNT_SAT(1483690.0), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* Funding is less than dust_limit */ +static struct test_case test_less_than_dust(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 0); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 2); + opener_outputs[0] = output_one(ctx, 499000); + opener_outputs[1] = output_three(ctx, 0); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 0); + + struct test_case test = { + .feerate = 1300, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(1000), + .accepter_funding = AMOUNT_SAT(0), + .expected_funding = AMOUNT_SAT(206), + .expected_tx = NULL, + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + return test; +} + +/* Funding is less than dust_limit, with accepter inputs */ +static struct test_case test_less_than_dust_with_accepter(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 1); + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + accepter_inputs[0] = input_two(ctx, txid_str_one); + + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 2); + opener_outputs[0] = output_one(ctx, 499000); + opener_outputs[1] = output_three(ctx, 0); + + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 0); + + struct test_case test = { + .feerate = 1300, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(1000), + .accepter_funding = AMOUNT_SAT(1000000), + .expected_funding = AMOUNT_SAT(1000206), + .expected_tx = NULL, + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + return test; +} + +/* Opener one input, no outputs */ +static struct test_case test_one_input(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 0); + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 0); + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 0); + + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + + char *expected_tx_str = "02000000013f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff01399f070000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(100000), + .accepter_funding = AMOUNT_SAT(0), + .expected_funding = AMOUNT_SAT(499513), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* Opener two inputs, no outputs */ +static struct test_case test_two_input(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 2); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 0); + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 0); + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 0); + + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + opener_inputs[1] = input_three(ctx, 2, txid_str_one); + + char *expected_tx_str = "02000000023f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0100000000ffffffff3f05da71fb470a53807eb01db4a9220941e3737fa44bccd1fb00f1968c98396c0200000000ffffffff0188811e0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(100000), + .accepter_funding = AMOUNT_SAT(0), + .expected_funding = AMOUNT_SAT(1999240), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* Full input/output set */ +static struct test_case test_full_set(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 2); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 2); + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 2); + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 1); + + opener_inputs[0] = input_one(ctx, 2, txid_str_two); + opener_inputs[1] = input_three(ctx, 3, txid_str_two); + + accepter_inputs[0] = input_two(ctx, txid_str_two); + accepter_inputs[1] = input_four(ctx); + + opener_outputs[0] = output_one(ctx, 5000); + opener_outputs[1] = output_three(ctx, 0); + + accepter_outputs[0] = output_two(ctx, 10000); + + char *expected_tx_str = "020000000451e9e94af2fbef69f74fa0c5aa955f1fc169df751461daaaf659bea2ee83f9070000000000ffffffff51e9e94af2fbef69f74fa0c5aa955f1fc169df751461daaaf659bea2ee83f9070100000000ffffffff51e9e94af2fbef69f74fa0c5aa955f1fc169df751461daaaf659bea2ee83f9070200000000ffffffff51e9e94af2fbef69f74fa0c5aa955f1fc169df751461daaaf659bea2ee83f9070300000000ffffffff0488130000000000001600140f0963bc774334ebc14d11ce940c35cfa69864151027000000000000160014d640ab16f347d1de5aba5a715321a5fc4ba9a5d5cae31c0000000000160014d295f76da2319791f36df5759e45b15d5e10522150262f0000000000220020c46bf3d1686d6dbb2d9244f8f67b90370c5aa2747045f1aeccb77d818711738200000000"; + struct test_case test = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(100000), + .accepter_funding = AMOUNT_SAT(2990000), + .expected_funding = AMOUNT_SAT(3090000), + .expected_tx = bitcoin_tx_from_hex(ctx, expected_tx_str, strlen(expected_tx_str)), + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + assert(test.expected_tx); + + return test; +} + +/* More funding requested than has inputs for */ +static struct test_case test_more_than_input(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 0); + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 0); + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 0); + + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + + struct test_case test = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(600000), + .accepter_funding = AMOUNT_SAT(0), + .expected_funding = AMOUNT_SAT(499513), + .expected_tx = NULL, + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + return test; +} + +/* More funding requested (funding + outputs) than has inputs for */ +static struct test_case test_culmulative_more_than_input(const tal_t *ctx) +{ + struct input_info **opener_inputs = tal_arr(ctx, struct input_info *, 1); + struct input_info **accepter_inputs = tal_arr(ctx, struct input_info *, 0); + struct output_info **opener_outputs = tal_arr(ctx, struct output_info *, 1); + struct output_info **accepter_outputs = tal_arr(ctx, struct output_info *, 0); + + opener_inputs[0] = input_one(ctx, 1, txid_str_one); + + opener_outputs[0] = output_one(ctx, 100000); + + struct test_case test = { + .feerate = 1000, + .opener_inputs = opener_inputs, + .accepter_inputs = accepter_inputs, + .opener_outputs = opener_outputs, + .accepter_outputs = accepter_outputs, + .opener_funding = AMOUNT_SAT(500000), + .accepter_funding = AMOUNT_SAT(0), + .expected_funding = AMOUNT_SAT(499513), + .expected_tx = NULL, + .remote_pubkey_str = "03d30199d74fb5a22d47b6e054e2f378cedacffcb89904a61d75d0dbd407143e65", + .local_pubkey_str = "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a", + }; + + return test; +} + + +#define num_tests 14 +static struct test_case (*test_cases[num_tests])(const tal_t *ctx) = { + test1, test2, test3, test_no_change, test_change, test_change_trimmed, + test_change_trimmed_positive, test_less_than_dust, test_one_input, + test_two_input, test_full_set, test_less_than_dust_with_accepter, + test_more_than_input, test_culmulative_more_than_input, +}; + +static bool bitcoin_tx_eq(const struct bitcoin_tx *tx1, + const struct bitcoin_tx *tx2) +{ + u8 *lin1, *lin2; + bool eq; + lin1 = linearize_tx(NULL, tx1); + lin2 = linearize_tx(lin1, tx2); + eq = memeq(lin1, tal_count(lin1), lin2, tal_count(lin2)); + tal_free(lin1); + return eq; +} + +int main(void) +{ + setup_locale(); + + struct bitcoin_tx *funding; + + struct pubkey local_funding_pubkey, remote_funding_pubkey; + const struct chainparams *chainparams = chainparams_for_network("bitcoin"); + + secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY + | SECP256K1_CONTEXT_SIGN); + setup_tmpctx(); + + u16 outnum; + struct amount_sat total_funding; + + for (size_t i = 0; i < num_tests; i++) { + struct test_case test = test_cases[i](tmpctx); + + assert(amount_sat_add(&total_funding, test.opener_funding, test.accepter_funding)); + + if (!pubkey_from_hexstr(test.local_pubkey_str, strlen(test.local_pubkey_str), + &local_funding_pubkey)) + abort(); + if (!pubkey_from_hexstr(test.remote_pubkey_str, strlen(test.remote_pubkey_str), + &remote_funding_pubkey)) + abort(); + + /* Note that dust_limit is set to 546, via chainparams */ + funding = dual_funding_funding_tx(tmpctx, chainparams, + &outnum, test.feerate, + &test.opener_funding, + test.accepter_funding, + test.opener_inputs, + test.accepter_inputs, + test.opener_outputs, + test.accepter_outputs, + &local_funding_pubkey, + &remote_funding_pubkey, + &total_funding, NULL); + + if (!test.expected_tx && !funding) + continue; + + if (!test.expected_tx ^ !funding) + abort(); + + assert(amount_sat_eq(total_funding, test.expected_funding)); + assert(bitcoin_tx_eq(funding, test.expected_tx)); + } + + /* No memory leaks please */ + secp256k1_context_destroy(secp256k1_ctx); + tal_free(tmpctx); + + return 0; +} +#else +int main(void) +{ + return 0; +} +#endif /* EXPERIMENTAL_FEATURES */ From 0755cfad17deac52d22875e8f3f3fe1320a8ea7d Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 18 Sep 2019 19:20:44 -0500 Subject: [PATCH 15/45] opening: update wallet_commit_channel for df Update some assumtions of wallet_commit_channel to better take the dual-funded reality into account --- lightningd/opening_control.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 084af4833cd0..2f135c293c6e 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -163,8 +163,10 @@ wallet_commit_channel(struct lightningd *ld, struct bitcoin_signature *remote_commit_sig, const struct bitcoin_txid *funding_txid, u16 funding_outnum, - struct amount_sat funding, + struct amount_sat total_funding, + struct amount_sat local_funding, struct amount_msat push, + enum side opener, u8 channel_flags, struct channel_info *channel_info, u32 feerate, @@ -182,17 +184,28 @@ wallet_commit_channel(struct lightningd *ld, return NULL; } - if (uc->fc) { - if (!amount_sat_sub_msat(&our_msat, funding, push)) { + if (opener == LOCAL) { + if (!amount_sat_sub_msat(&our_msat, local_funding, push)) { log_broken(uc->log, "push %s exceeds funding %s", type_to_string(tmpctx, struct amount_msat, &push), type_to_string(tmpctx, struct amount_sat, - &funding)); + &local_funding)); return NULL; } - } else - our_msat = push; + } else { + if (!amount_msat_add_sat(&our_msat, push, local_funding)) { + log_broken(uc->log, "push %s exceeds funding %s", + type_to_string(tmpctx, struct amount_msat, + &push), + type_to_string(tmpctx, struct amount_sat, + &local_funding)); + return NULL; + } + } + + /* Check that we're still in bounds */ + assert(amount_msat_less_eq_sat(our_msat, total_funding)); /* Feerates begin identical. */ channel_info->feerate_per_kw[LOCAL] @@ -226,7 +239,7 @@ wallet_commit_channel(struct lightningd *ld, channel = new_channel(uc->peer, uc->dbid, NULL, /* No shachain yet */ CHANNELD_AWAITING_LOCKIN, - uc->fc ? LOCAL : REMOTE, + opener, uc->log, take(uc->transient_billboard), channel_flags, @@ -235,7 +248,7 @@ wallet_commit_channel(struct lightningd *ld, 1, 1, 0, funding_txid, funding_outnum, - funding, + total_funding, push, false, /* !remote_funding_locked */ NULL, /* no scid yet */ @@ -401,7 +414,9 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, &funding_txid, funding_txout, fc->funding, + fc->funding, fc->push, + LOCAL, fc->channel_flags, &channel_info, feerate, @@ -496,7 +511,9 @@ static void opening_fundee_finished(struct subd *openingd, &funding_txid, funding_outnum, funding, + AMOUNT_SAT(0), push, + REMOTE, channel_flags, &channel_info, feerate, From 0b6e0993f814c0387018583196904435bf77ded1 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 18 Sep 2019 19:23:17 -0500 Subject: [PATCH 16/45] funding: pass utxos through to openingd we're going to need them to construct the funding tx --- lightningd/opening_control.c | 11 ++++++++--- openingd/opening_wire.csv | 3 +++ openingd/openingd.c | 7 +++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 2f135c293c6e..502722e657ab 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -96,6 +96,7 @@ struct funding_channel { /* Whether or not to use channel open v2 */ bool is_v2; + struct unreleased_tx *utx; }; static void uncommitted_channel_disconnect(struct uncommitted_channel *uc, @@ -881,7 +882,6 @@ static unsigned int openingd_msg(struct subd *openingd, } opening_funder_failed(openingd, msg, uc); return 0; - case WIRE_OPENING_FUNDEE: if (tal_count(fds) != 3) return 3; @@ -989,6 +989,7 @@ static struct command_result *json_fund_channel_complete(struct command *cmd, u32 *funding_txout_num; u16 funding_txout; struct bitcoin_tx *tx; + const struct utxo **utxos; if (!param(cmd, buffer, params, p_req("id", param_node_id, &id), @@ -1038,14 +1039,18 @@ static struct command_result *json_fund_channel_complete(struct command *cmd, type_to_string(tmpctx, struct bitcoin_txid, funding_txid), funding_txout); tx = utx->tx; - } else + utxos = utx->wtx->utxos; + peer->uncommitted_channel->fc->utx = utx; + } else { tx = NULL; + utxos = tal_arr(tmpctx, const struct utxo *, 0); + } /* Set the cmd to this new cmd */ peer->uncommitted_channel->fc->cmd = cmd; msg = towire_opening_funder_complete(NULL, funding_txid, funding_txout, - tx); + utxos, tx); subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); return command_still_pending(cmd); diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index 039ae91fd5fa..eec0103d9037 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -85,6 +85,9 @@ msgdata,opening_funder_start_reply,scriptpubkey,u8,script_len msgtype,opening_funder_complete,6012 msgdata,opening_funder_complete,funding_txid,bitcoin_txid, msgdata,opening_funder_complete,funding_txout,u16, +msgdata,opening_funder_complete,num_ins,u16, +#include +msgdata,opening_funder_complete,utxos,utxo,num_ins msgdata,opening_funder_complete,tx,bitcoin_tx, #master->openingd: cancel channel establishment for a funding diff --git a/openingd/openingd.c b/openingd/openingd.c index 970898c5ef56..7efb9bb4188c 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -963,7 +963,8 @@ static bool funder_finalize_channel_setup(struct state *state, } static u8 *funder_channel_complete(struct state *state, - struct bitcoin_tx *tx) + struct bitcoin_tx *tx, + struct utxo **utxos) { struct bitcoin_signature sig; struct amount_msat local_msat; @@ -1489,6 +1490,7 @@ static u8 *handle_master_in(struct state *state) u8 channel_flags; struct bitcoin_txid funding_txid; struct bitcoin_tx *tx; + struct utxo **utxos; u16 funding_txout; switch (t) { @@ -1509,11 +1511,12 @@ static u8 *handle_master_in(struct state *state) if (!fromwire_opening_funder_complete(tmpctx, msg, &funding_txid, &funding_txout, + &utxos, &tx)) master_badmsg(WIRE_OPENING_FUNDER_COMPLETE, msg); state->funding_txid = funding_txid; state->funding_txout = funding_txout; - return funder_channel_complete(state, tx); + return funder_channel_complete(state, tx, utxos); case WIRE_OPENING_FUNDER_CANCEL: /* We're aborting this, simple */ if (!fromwire_opening_funder_cancel(msg)) From b1873a82e02ac3dda9a8341e313626ad5d2d2a3c Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 18 Sep 2019 19:24:31 -0500 Subject: [PATCH 17/45] dual-funding: wire up opener side of dual funding Dual funding means that both the opener (us) and the accepter (the remote peer) have the opportunity to add funds to the funding transaction. This patch implements the protocol set required for the second half of dual-funding; from fundchannel_complete onward. --- lightningd/opening_control.c | 215 +++++++++++++++ openingd/channel_establishment.h | 16 ++ openingd/opening_wire.csv | 26 ++ openingd/openingd.c | 454 +++++++++++++++++++++++++++++++ 4 files changed, 711 insertions(+) create mode 100644 openingd/channel_establishment.h diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 502722e657ab..c41c5842335d 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -358,6 +358,210 @@ static void opening_funder_start_replied(struct subd *openingd, const u8 *resp, tal_free(fc->uc); } +#if EXPERIMENTAL_FEATURES +static bool update_unreleased_tx(struct unreleased_tx *utx, + struct bitcoin_tx *tx, + u32 *input_map, + struct witness_stack **witnesses) +{ + size_t i, j, num_other_ins, num_utxo; + + num_utxo = tal_count(utx->wtx->utxos); + num_other_ins = tx->wtx->num_inputs - num_utxo; + assert(num_other_ins == tal_count(witnesses)); + + utx->inputs = tal_free(utx->inputs); + utx->inputs = tal_arr(utx, struct bitcoin_tx_input *, num_other_ins); + for (i = 0; i < num_other_ins; i++) { + struct wally_tx_input wi; + struct bitcoin_tx_input *in; + size_t index = -1; + + in = tal(utx->inputs, struct bitcoin_tx_input); + /* The input map is 'inverted', in that the + * original index is the value, the index is its + * current index. We know the original + * and need to find the current, so we iterate + * until we find the original -- its index is + * the current `index` */ + for (j = 0; j < tx->wtx->num_inputs; j++) { + if (input_map[j] == i + num_utxo) { + index = j; + break; + } + } + + if (index == -1) + return false; + + wi = tx->wtx->inputs[index]; + + bitcoin_tx_input_get_txid(tx, index, &in->txid); + in->index = wi.index; + in->sequence_number = wi.sequence; + + /* Amount is unknown here */ + in->amount = AMOUNT_SAT(0); + + /* Copy over input's scriptpubkey */ + if (wi.script_len) { + in->script = tal_arr(in, u8, wi.script_len); + memcpy(in->script, wi.script, wi.script_len); + } else + in->script = NULL; + + in->witness = tal_arr(in, u8 *, + tal_count(witnesses[i]->witness_element)); + for (j = 0; j < tal_count(witnesses[i]->witness_element); j++) { + in->witness[j] = + tal_dup_arr(in->witness, + u8, + witnesses[i]->witness_element[j]->witness, + tal_count(witnesses[i]->witness_element[j]->witness), + 0); + } + + utx->inputs[i] = in; + } + + utx->outputs = tal_free(utx->outputs); + utx->outputs = tal_arr(utx, struct bitcoin_tx_output *, tx->wtx->num_outputs); + for (i = 0; i < tx->wtx->num_outputs; i++) { + struct wally_tx_output out; + struct amount_sat amount; + u8 *script; + + out = tx->wtx->outputs[i]; + + amount.satoshis = out.satoshi; /* Raw: type conversion */ + + /* Copy over output's script */ + script = tal_arr(utx->outputs, u8, out.script_len); + memcpy(script, out.script, out.script_len); + + utx->outputs[i] = new_tx_output(utx->outputs, + amount, script); + } + + /* Update transaction fields on utx */ + utx->tx = tal_free(utx->tx); + utx->tx = tal_steal(utx, tx); + bitcoin_txid(tx, &utx->txid); + + return true; +} +#endif /* EXPERIMENTAL_FEATURES */ + +static void opening_opener_finished(struct subd *openingd, const u8 *resp, + const int *fds, + struct uncommitted_channel *uc) +{ +#if EXPERIMENTAL_FEATURES + struct channel_info channel_info; + struct bitcoin_txid funding_txid; + u16 funding_txout; + struct bitcoin_signature remote_commit_sig; + struct bitcoin_tx *remote_commit, *funding_tx; + u32 feerate, feerate_funding; + struct amount_sat local_funding, total_funding; + struct channel *channel; + struct lightningd *ld = openingd->ld; + u8 *remote_upfront_shutdown_script; + struct per_peer_state *pps; + struct bitcoin_tx_input **remote_ins; + struct funding_channel *fc = uc->fc; + struct unreleased_tx *utx = fc->utx; + u32 *input_map; + struct witness_stack **witnesses = NULL; + + /* This is a new channel_info.their_config so set its ID to 0 */ + channel_info.their_config.id = 0; + + if (!fromwire_opening_dual_funding_signed(resp, resp, + &pps, + &remote_commit, + &remote_commit_sig, + &funding_tx, + &funding_txout, + &remote_ins, + &input_map, + &local_funding, + &channel_info.their_config, + &channel_info.theirbase.revocation, + &channel_info.theirbase.payment, + &channel_info.theirbase.htlc, + &channel_info.theirbase.delayed_payment, + &channel_info.remote_per_commit, + &channel_info.remote_fundingkey, + &feerate, + &feerate_funding, + &uc->our_config.channel_reserve, + &remote_upfront_shutdown_script)) { + log_broken(fc->uc->log, + "bad OPENING_DUAL_FUNDING_SIGNED %s", + tal_hex(resp, resp)); + was_pending(command_fail(fc->cmd, LIGHTNINGD, + "bad OPENING_DUAL_FUNDING_SIGNED %s", + tal_hex(fc->cmd, resp))); + goto cleanup; + } + + remote_commit->chainparams = get_chainparams(openingd->ld); + per_peer_state_set_fds_arr(pps, fds); + + /* openingd should never accept them funding channel in this case. */ + if (peer_active_channel(uc->peer)) { + log_broken(uc->log, "openingd accepted peer funding channel"); + uncommitted_channel_disconnect(uc, "already have active channel"); + goto cleanup; + } + + /* Update the funding tx that we have for this */ + if (!update_unreleased_tx(utx, funding_tx, input_map, witnesses)) { + log_broken(uc->log, "Unable to update unreleased tx"); + uncommitted_channel_disconnect(uc, "internal error in creating updated tx"); + goto cleanup; + } + + + /* Pull out the funding amount */ + total_funding.satoshis /* Raw: type conversion */ + = utx->tx->wtx->outputs[funding_txout].satoshi; /* Raw: type conversion */ + bitcoin_txid(funding_tx, &funding_txid); + + /* Consumes uc */ + channel = wallet_commit_channel(ld, uc, + remote_commit, + &remote_commit_sig, + &funding_txid, + funding_txout, + total_funding, + local_funding, + fc->push, + LOCAL, + fc->channel_flags, + &channel_info, + feerate, + remote_upfront_shutdown_script); + + /* Watch for funding confirms */ + channel_watch_funding(ld, channel); + + /* Needed for the success statement */ + derive_channel_id(&fc->cid, &channel->funding_txid, funding_txout); + + funding_success(channel); + peer_start_channeld(channel, pps, NULL, false); + +cleanup: + subd_release_channel(openingd, uc); + uc->openingd = NULL; + tal_free(uc); +#else + fatal("Requires EXPERIMENTAL_FEATURES"); +#endif /* EXPERIMENTAL_FEATURES */ +} + static void opening_funder_finished(struct subd *openingd, const u8 *resp, const int *fds, struct funding_channel *fc) @@ -864,6 +1068,17 @@ static unsigned int openingd_msg(struct subd *openingd, return 3; opening_funder_finished(openingd, msg, fds, uc->fc); return 0; + case WIRE_OPENING_DUAL_FUNDING_SIGNED: + if (!uc->fc) { + log_broken(openingd->log, "Unexpected DUAL_FUNDING_SIGNED %s", + tal_hex(tmpctx, msg)); + tal_free(openingd); + return 0; + } + if (tal_count(fds) != 3) + return 3; + opening_opener_finished(openingd, msg, fds, uc); + return 0; case WIRE_OPENING_FUNDER_START_REPLY: if (!uc->fc) { log_broken(openingd->log, "Unexpected FUNDER_START_REPLY %s", diff --git a/openingd/channel_establishment.h b/openingd/channel_establishment.h new file mode 100644 index 000000000000..71bc0cb42ee3 --- /dev/null +++ b/openingd/channel_establishment.h @@ -0,0 +1,16 @@ +#ifndef LIGHTNING_OPENINGD_CHANNEL_ESTABLISHMENT_H +#define LIGHTNING_OPENINGD_CHANNEL_ESTABLISHMENT_H +#include + +#define REMOTE_CONTRIB_LIMIT 4 + +/* Designator for flagging what role a peer + * is playing in channel establishment (v2) + */ +enum role { + OPENER, + ACCEPTER, + NUM_ROLES +}; + +#endif /* LIGHTNING_OPENINGD_CHANNEL_ESTABLISHMENT_H */ diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index eec0103d9037..825837e52c3b 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -123,6 +123,32 @@ msgdata,opening_fundee,our_channel_reserve_satoshis,amount_sat, msgdata,opening_fundee,shutdown_len,u16, msgdata,opening_fundee,shutdown_scriptpubkey,u8,shutdown_len +# openingd->master: accepter's signatures etc +# for a dual-funded channel open +msgtype,opening_dual_funding_signed,6204 +msgdata,opening_dual_funding_signed,pps,per_peer_state, +msgdata,opening_dual_funding_signed,first_commit,bitcoin_tx, +msgdata,opening_dual_funding_signed,first_commit_sig,bitcoin_signature, +msgdata,opening_dual_funding_signed,funding_tx,bitcoin_tx, +msgdata,opening_dual_funding_signed,funding_tx_out,u16, +msgdata,opening_dual_funding_signed,num_witnesses,u16, +msgdata,opening_dual_funding_signed,remote_witnesses,bitcoin_tx_input,num_witnesses +msgdata,opening_dual_funding_signed,num_inputs,u32, +msgdata,opening_dual_funding_signed,input_map,u32,num_inputs +msgdata,opening_dual_funding_signed,local_funding,amount_sat, +msgdata,opening_dual_funding_signed,their_config,channel_config, +msgdata,opening_dual_funding_signed,revocation_basepoint,pubkey, +msgdata,opening_dual_funding_signed,payment_basepoint,pubkey, +msgdata,opening_dual_funding_signed,htlc_basepoint,pubkey, +msgdata,opening_dual_funding_signed,delayed_payment_basepoint,pubkey, +msgdata,opening_dual_funding_signed,their_per_commit_point,pubkey, +msgdata,opening_dual_funding_signed,remote_fundingkey,pubkey, +msgdata,opening_dual_funding_signed,feerate_per_kw,u32, +msgdata,opening_dual_funding_signed,feerate_per_kw_funding,u32, +msgdata,opening_dual_funding_signed,local_reserve,amount_sat, +msgdata,opening_dual_funding_signed,shutdown_len,u16, +msgdata,opening_dual_funding_signed,shutdown_scriptpubkey,u8,shutdown_len + # master -> openingd: do you have a memleak? msgtype,opening_dev_memleak,6033 diff --git a/openingd/openingd.c b/openingd/openingd.c index 7efb9bb4188c..57c2ec4ae8ee 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -774,6 +776,454 @@ static u8 *funder_channel_start(struct state *state, return towire_opening_funder_start_reply(state, funding_output_script); } +#if EXPERIMENTAL_FEATURES +static void check_channel_id(struct state *state, + struct channel_id *id_in, + struct channel_id *original_channel_id) +{ + /* BOLT #2: + * + * The `temporary_channel_id` MUST be the same as the + * `temporary_channel_id` in the `open_channel` message. + */ + if (!channel_id_eq(id_in, original_channel_id)) + peer_failed(state->pps, id_in, + "channel establishment: ids don't match: expected %s got %s", + type_to_string(tmpctx, struct channel_id, original_channel_id), + type_to_string(tmpctx, struct channel_id, id_in)); +} + +/* Derives the needed inputs / outputs from a bitcoin tx */ +static void derive_input_output_info(const tal_t *ctx, + struct bitcoin_tx *tx, + struct utxo **utxos, + bool exclude_funding_output, + struct input_info ***inputs, + struct output_info ***outputs) +{ + size_t i; + + *inputs = tal_arr(ctx, struct input_info *, tal_count(utxos)); + for (i = 0; i < tal_count(utxos); i++) { + struct input_info *in; + in = tal(*inputs, struct input_info); + + in->input_satoshis = utxos[i]->amount; + in->prevtx_txid = utxos[i]->txid; + in->prevtx_vout = utxos[i]->outnum; + in->prevtx_scriptpubkey = tal_dup_arr(in, u8, utxos[i]->scriptPubkey, + tal_bytelen(utxos[i]->scriptPubkey), 0); + + /* All our inputs are sig + key (P2WPKH or P2SH-P2WPKH) */ + in->max_witness_len = 1 + 1 + 73 + 1 + 33; + + /* + * FIXME: add BOLT reference when merged. + * `input_info`.`script` is the scriptPubkey data for the input. + * NB: for native SegWit inputs (P2WPKH and P2WSH) inputs, the `script` field + * will be empty. + */ + if (utxos[i]->is_p2sh) { + in->script = tal_arr(in, u8, tx->wtx->inputs[i].script_len); + memcpy(in->script, tx->wtx->inputs[i].script, + tx->wtx->inputs[i].script_len); + } else + in->script = NULL; + + (*inputs)[i] = in; + } + + *outputs = tal_arr(ctx, struct output_info *, 0); + for (i = 0; i < tx->wtx->num_outputs; i++) { + struct output_info *out; + struct wally_tx_output wo; + + wo = tx->wtx->outputs[i]; + + /* This is a hack that excludes P2WSH outputs + * which for us, now are exclusively funding outputs */ + if (exclude_funding_output && wo.script_len == 34) + continue; + + out = tal(*outputs, struct output_info); + out->output_satoshis.satoshis = wo.satoshi; /* Raw: type conversion */ + out->script = tal_arr(out, u8, wo.script_len); + memcpy(out->script, wo.script, wo.script_len); + + tal_arr_expand(outputs, out); + } +} + +static bool check_remote_inputs(struct input_info **remote_inputs, + struct amount_sat *input_funding) +{ + size_t i = 0; + + // FIXME: we should check that they don't also + // turn in the funding output + // and maybe check that none of their outputs + // are duplicates?? + *input_funding = AMOUNT_SAT(0); + for (i = 0; i < tal_count(remote_inputs); i++) { + + if (!amount_sat_add(input_funding, *input_funding, remote_inputs[i]->input_satoshis)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Overflow in remote input amount %s + %s", + type_to_string(tmpctx, struct amount_sat, + &remote_inputs[i]->input_satoshis), + type_to_string(tmpctx, struct amount_sat, + input_funding)); + /** TODO: add BOLT reference when merged + * - MUST ensure each `input_info` refers to a non-malleable (segwit) UTXO. */ + /* P2SH wrapped inputs send the redeemscript, which we can check */ + if (remote_inputs[i]->script) { + if (!is_p2wpkh(remote_inputs[i]->script, NULL) + && !is_p2wsh(remote_inputs[i]->script, NULL)) + return false; + } else if (!is_p2wpkh(remote_inputs[i]->prevtx_scriptpubkey, NULL) + && !is_p2wsh(remote_inputs[i]->prevtx_scriptpubkey, NULL)) + return false; + + } + return true; +} + + +/* Check that the tx info your peer sent you is kosher */ +static bool check_remote_input_outputs(struct state *state, + enum role remote_role, + struct input_info **remote_inputs, + struct output_info **remote_outputs, + struct amount_sat stated_funding_sats) +{ + size_t i = 0; + struct amount_sat funding, other_outputs, funding_tx_sats; + bool has_change_address; + + /** + * BOLT-737016aef544011f385a9e081f85eca34eb61ab6 + * - if is the `opener`: + * - MUST NOT send zero inputs (`num_inputs` cannot be zero). + */ + if (remote_role == OPENER) { + if (!tal_count(remote_inputs)) + peer_failed(state->pps, + &state->channel_id, + "Opener sent no funding inputs"); + } else { + /** + * BOLT-737016aef544011f385a9e081f85eca34eb61ab6 + * - if is the `accepter`: + * - consider the `contribution count` the total of their `num_inputs` plus + * `num_outputs' + * - MUST NOT send a `funding_compose` message where the `contribution count` + * exceeds the limit of 4. + */ + if (tal_count(remote_inputs) + tal_count(remote_outputs) > REMOTE_CONTRIB_LIMIT) + peer_failed(state->pps, + &state->channel_id, + "Too many remote contributions. " + "Received %ld inputs, %ld outputs; " + "max allowed is %d", + tal_count(remote_inputs), + tal_count(remote_outputs), + REMOTE_CONTRIB_LIMIT); + } + + if (!check_remote_inputs(remote_inputs, &funding)) + peer_failed(state->pps, + &state->channel_id, + "Peer sent malleable (non-Segwit) input."); + + other_outputs = AMOUNT_SAT(0); + has_change_address = false; + for (i = 0; i < tal_count(remote_outputs); i++) { + if (amount_sat_eq(AMOUNT_SAT(0), remote_outputs[i]->output_satoshis)) { + if (has_change_address) + peer_failed(state->pps, + &state->channel_id, + "Peer sent more than one change outputs."); + + has_change_address = true; + } + if (!amount_sat_add(&other_outputs, other_outputs, remote_outputs[i]->output_satoshis)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Overflow in remote outher_outputs satoshis %s + %s", + type_to_string(tmpctx, struct amount_sat, + &other_outputs), + type_to_string(tmpctx, struct amount_sat, + &remote_outputs[i]->output_satoshis)); + + /* TODO: add BOLT reference when merged + * - MUST ensure the `output_info`.`script` is a standard script + */ + if (!is_known_scripttype(remote_outputs[i]->script)) + peer_failed(state->pps, + &state->channel_id, + "Peer sent non-standard output script."); + + } + + /** TODO: add BOLT reference when merged + * The receiving node: + * - if the total `input_info`.`satoshis` is less than the total `output_info`.`satoshis` + * - MUST fail the channel. + */ + if (!amount_sat_sub(&funding_tx_sats, funding, other_outputs)) + peer_failed(state->pps, + &state->channel_id, + "Total remote input satoshi less than output satoshis. change:%s inputs:%s", + type_to_string(tmpctx, struct amount_sat, + &other_outputs), + type_to_string(tmpctx, struct amount_sat, + &funding)); + + if (!amount_sat_greater_eq(funding_tx_sats, stated_funding_sats)) + peer_failed(state->pps, + &state->channel_id, + "Input amounts won't afford " + "funding amount (desired: %s, provided: %s).", + type_to_string(tmpctx, struct amount_sat, + &stated_funding_sats), + type_to_string(tmpctx, struct amount_sat, + &funding_tx_sats)); + + return true; +} +#endif + +static u8 *funder_finalize_channel_setup2(struct state *state, + struct utxo **utxos, + struct bitcoin_signature *sig, + struct bitcoin_tx **tx) +{ +#if EXPERIMENTAL_FEATURES + u8 *msg; + struct channel_id id_in; + const u8 *wscript; + char *err_reason; + struct input_info **local_ins, **remote_ins; + struct output_info **local_outs, **remote_outs; + struct bitcoin_tx_input **remotetx_ins; + struct amount_sat total_funding; + struct bitcoin_signature their_sig, our_sig; + struct amount_msat local_funding_msat; + + size_t i, input_count; + struct bitcoin_tx *funding_tx, *remote_commit, *local_commit; + struct witness_stack **remote_witnesses; + + /* Derive components, omitting the funding output */ + local_ins = tal_arr(tmpctx, struct input_info *, 0); + local_outs = tal_arr(tmpctx, struct output_info *, 0); + derive_input_output_info(tmpctx, *tx, utxos, true, + &local_ins, &local_outs); + + /* Send them to the peer */ + msg = towire_funding_compose(tmpctx, &state->channel_id, + cast_const2(const struct input_info **, local_ins), + cast_const2(const struct output_info **, local_outs)); + + sync_crypto_write(state->pps, take(msg)); + + peer_billboard(false, + "Opening channel: funding_compose sent, " + "waiting for funding_compose reply"); + + msg = opening_negotiate_msg(tmpctx, state, false); + if (!msg) + return NULL; + + /* The next message is "funding_compose", which tells us the funding + * inputs and outputs they've selected. */ + if (!fromwire_funding_compose(state, msg, &id_in, + &remote_ins, + &remote_outs)) + peer_failed(state->pps, + &state->channel_id, + "Parsing received funding_compose"); + + if (!check_remote_input_outputs(state, ACCEPTER, + remote_ins, remote_outs, + state->accepter_funding)) + return NULL; + + /* FIXME: send their inputs master to verify via bitcoind */ + + input_count = tal_count(local_ins) + tal_count(remote_ins); + const void *map[input_count]; + for (i = 0; i < input_count; i++) + map[i] = int2ptr(i); + + /* Build the funding transaction */ + funding_tx = dual_funding_funding_tx(state, state->chainparams, + &state->funding_txout, + state->feerate_per_kw_funding, + &state->opener_funding, + state->accepter_funding, + local_ins, remote_ins, + local_outs, remote_outs, + &state->our_funding_pubkey, + &state->their_funding_pubkey, + &total_funding, + (const void **)&map); + + if (!funding_tx) + peer_failed(state->pps, + &state->channel_id, + "Unable to afford funding transaction"); + + bitcoin_txid(funding_tx, &state->funding_txid); + + /* Move our push_msat over to the other peer */ + if (!amount_sat_sub_msat(&local_funding_msat, state->opener_funding, state->push_msat)) + peer_failed(state->pps, + &state->channel_id, + "Unable to afford funding transaction, pushed to much"); + + state->channel = new_initial_channel(state, + &state->chainparams->genesis_blockhash, + &state->funding_txid, + state->funding_txout, + state->minimum_depth, + total_funding, + local_funding_msat, + state->feerate_per_kw, + &state->localconf, + &state->remoteconf, + &state->our_points, + &state->their_points, + &state->our_funding_pubkey, + &state->their_funding_pubkey, + state->option_static_remotekey, + LOCAL); + + /* We don't expect this to fail, but it does do some additional + * internal sanity checks. */ + if (!state->channel) + peer_failed(state->pps, + &state->channel_id, + "We could not create channel with given config"); + + /* We switch over to using the funding_tx derived channel_id */ + derive_channel_id(&state->channel_id, + &state->funding_txid, state->funding_txout); + + /* We need to send them the signatures for their commitment tx */ + remote_commit = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[REMOTE], + REMOTE, &err_reason); + + if (!remote_commit) + negotiation_failed(state, true, + "Could not meet fees and reserve: %s", err_reason); + + msg = towire_hsm_sign_remote_commitment_tx(NULL, + remote_commit, + &state->channel->funding_pubkey[REMOTE], + state->channel->funding); + + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsm_sign_tx_reply(msg, &our_sig)) + status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", + tal_hex(tmpctx, msg)); + + peer_billboard(false, "Opening channel: sending commitment_signed"); + + /* Now we send it */ + msg = towire_commitment_signed(tmpctx, &state->channel_id, + &our_sig.s, NULL); + + sync_crypto_write(state->pps, take(msg)); + msg = opening_negotiate_msg(tmpctx, state, false); + if (!msg) + return NULL; + + their_sig.sighash_type = SIGHASH_ALL; + if (!fromwire_accepter_sigs(state, msg, &id_in, + &their_sig.s, + (struct witness_stack ***)&remote_witnesses)) + peer_failed(state->pps, + &state->channel_id, + "Bad accepter_sigs in %s", tal_hex(msg, msg)); + + peer_billboard(false, + "Opening channel: accepter_sigs received"); + + /* Check that they're using the right channel_id */ + check_channel_id(state, &id_in, &state->channel_id); + + /* Check that they sent the right count of witnesses */ + if (tal_count(remote_witnesses) != tal_count(remote_ins)) + peer_failed(state->pps, + &state->channel_id, + "Received %ld witnesses for %ld inputs", + tal_count(remote_witnesses), + tal_count(remote_ins)); + + /* We create *our* initial commitment transaction, and check the + * signature they sent against that. */ + local_commit = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[LOCAL], + LOCAL, &err_reason); + if (!local_commit) + negotiation_failed(state, false, + "Did not meet fees and reserve: %s", err_reason); + + if (!check_tx_sig(local_commit, 0, NULL, wscript, &state->their_funding_pubkey, &their_sig)) + peer_failed(state->pps, + &state->channel_id, + "Bad signature %s on tx %s using key %s", + type_to_string(tmpctx, struct bitcoin_signature, + &their_sig), + type_to_string(tmpctx, struct bitcoin_tx, local_commit), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey)); + + peer_billboard(false, + "Opening channel: accepter sigs are acceptable, moving to sign tx"); + + u32 i_map[input_count]; + for (size_t i = 0; i < input_count; i++) { + i_map[i] = ptr2int(map[i]); + } + + /* Convert witnesses to something more palatable for + * how our generated wires work */ + /* FIXME: remove post EXPERIMENTAL_FEATURE, since witness_stack will be wireable */ + remotetx_ins = tal_arr(tmpctx, struct bitcoin_tx_input *, tal_count(remote_witnesses)); + for (i = 0; i < tal_count(remote_witnesses); i++) { + remotetx_ins[i] = tal(remotetx_ins, struct bitcoin_tx_input); + } + + return towire_opening_dual_funding_signed(state, + state->pps, + local_commit, + &their_sig, + funding_tx, + state->funding_txout, + cast_const2( + const struct bitcoin_tx_input **, + remotetx_ins), + i_map, + state->opener_funding, + &state->remoteconf, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.htlc, + &state->their_points.delayed_payment, + &state->first_per_commitment_point[REMOTE], + &state->their_funding_pubkey, + state->feerate_per_kw, + state->feerate_per_kw_funding, + state->localconf.channel_reserve, + state->remote_upfront_shutdown_script); +#else + return NULL; +#endif /* EXPERIMENTAL_FEATURES */ +} + static bool funder_finalize_channel_setup(struct state *state, struct amount_msat local_msat, struct bitcoin_signature *sig, @@ -978,6 +1428,9 @@ static u8 *funder_channel_complete(struct state *state, * succeed because we checked it earlier */ assert(amount_sat_sub_msat(&local_msat, state->opener_funding, state->push_msat)); + if (state->use_v2) + return funder_finalize_channel_setup2(state, utxos, &sig, &tx); + if (!funder_finalize_channel_setup(state, local_msat, &sig, &tx)) return NULL; @@ -1534,6 +1987,7 @@ static u8 *handle_master_in(struct state *state) case WIRE_OPENING_DEV_MEMLEAK_REPLY: case WIRE_OPENING_INIT: case WIRE_OPENING_FUNDER_REPLY: + case WIRE_OPENING_DUAL_FUNDING_SIGNED: case WIRE_OPENING_FUNDER_START_REPLY: case WIRE_OPENING_FUNDEE: case WIRE_OPENING_FUNDER_FAILED: From 1c5823fb72d945bdd3d26c1c5aa2a17b509701b4 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 18 Sep 2019 19:26:27 -0500 Subject: [PATCH 18/45] fundchannel_complete: return 'txid' and 'remote signed' tx Only applies for dual funded transactions. Ideally will be obsoleted with a PSBT implementation soon.TM --- lightningd/opening_control.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index c41c5842335d..79ee93736884 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -304,6 +304,11 @@ static void funding_success(struct channel *channel) json_add_string(response, "channel_id", type_to_string(tmpctx, struct channel_id, &fc->cid)); json_add_bool(response, "commitments_secured", true); + if (fc->utx) { + json_add_txid(response, "txid", &fc->utx->txid); + /* FIXME: use PSBT for this */ + json_add_tx(response, "tx_with_remotesigs", fc->utx->tx); + } was_pending(command_success(cmd, response)); } From 974967dae969342c86f38c5bc4eeafb40d747d0a Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 19 Sep 2019 18:13:25 -0500 Subject: [PATCH 19/45] df: wire in feature flag this number is tentative, will need to be updated when set definitively --- common/features.c | 9 ++++++++- common/features.h | 8 ++++++++ lightningd/opening_control.c | 3 +-- tests/test_misc.py | 4 +++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/common/features.c b/common/features.c index 2d2b023ade25..af96e99c17c9 100644 --- a/common/features.c +++ b/common/features.c @@ -10,6 +10,9 @@ static const u32 our_localfeatures[] = { OPTIONAL_FEATURE(LOCAL_GOSSIP_QUERIES), OPTIONAL_FEATURE(LOCAL_GOSSIP_QUERIES_EX), OPTIONAL_FEATURE(LOCAL_STATIC_REMOTEKEY), +#if EXPERIMENTAL_FEATURES + OPTIONAL_FEATURE(LOCAL_FUNDCHANNEL_V2), +#endif }; static const u32 our_globalfeatures[] = { @@ -171,7 +174,11 @@ static const char *feature_name(const tal_t *ctx, size_t f) "option_gossip_queries", "option_var_onion_optin", "option_gossip_queries_ex", - "option_static_remotekey" }; + "option_static_remotekey", +#if EXPERIMENTAL_FEATURES + "option_dual_fund", +#endif + }; assert(f / 2 < ARRAY_SIZE(fnames)); return tal_fmt(ctx, "%s/%s", diff --git a/common/features.h b/common/features.h index f6d23853bb3a..41ddfb77ac3e 100644 --- a/common/features.h +++ b/common/features.h @@ -54,6 +54,14 @@ void set_feature_bit(u8 **ptr, u32 bit); #define LOCAL_GOSSIP_QUERIES 6 #define LOCAL_GOSSIP_QUERIES_EX 10 +/*BOLT-1a9a018f5e2fa7239ae25f333c0be1f294f6c5e9 + * + * | Bits | Name |... + * | 28/29 | `option_dual_fund` |... + */ +/* FIXME: update the RFC to match */ +#define LOCAL_FUNDCHANNEL_V2 14 + /* BOLT #9: * | Bits | Name |... * | 12/13| `option_static_remotekey` |... diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 79ee93736884..c92b4cfc1739 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1430,8 +1430,7 @@ static struct command_result *json_fund_channel_start(struct command *cmd, fc->uc = peer->uncommitted_channel; #if EXPERIMENTAL_FEATURES - // FIXME: use features to flag on - fc->is_v2 = true; + fc->is_v2 = feature_offered(peer->localfeatures, LOCAL_FUNDCHANNEL_V2); #else fc->is_v2 = false; #endif diff --git a/tests/test_misc.py b/tests/test_misc.py index 16ade0e2e912..0e5f2121f531 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -5,7 +5,7 @@ from flaky import flaky # noqa: F401 from lightning import RpcError from threading import Event -from utils import DEVELOPER, TIMEOUT, VALGRIND, sync_blockheight, only_one, wait_for, TailableProc +from utils import EXPERIMENTAL_FEATURES, DEVELOPER, TIMEOUT, VALGRIND, sync_blockheight, only_one, wait_for, TailableProc from ephemeral_port_reserve import reserve import json @@ -1632,6 +1632,8 @@ def test_list_features_only(node_factory): 'option_gossip_queries/odd', 'option_gossip_queries_ex/odd', 'option_static_remotekey/odd'] + if EXPERIMENTAL_FEATURES: + expected += ['option_dual_fund/odd'] assert features == expected From db17094ef13052d35bf089f6cded9c43f22bea76 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 23 Sep 2019 18:26:20 -0500 Subject: [PATCH 20/45] utxos: pass through the scriptpubkey We're now passing utxos to openingd, who needs to know what the scriptPubkey is, to relay to our peer. --- common/test/run-funding_tx.c | 12 ++++++++++++ common/test/run-funding_tx_dual.c | 12 ++++++++++++ common/utxo.c | 11 +++++++---- lightningd/test/run-find_my_abspath.c | 2 +- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/common/test/run-funding_tx.c b/common/test/run-funding_tx.c index 24e04e3974a0..8035bbcea9d0 100644 --- a/common/test/run-funding_tx.c +++ b/common/test/run-funding_tx.c @@ -37,12 +37,18 @@ void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct n /* Generated stub for fromwire_pubkey */ void fromwire_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct pubkey *pubkey UNNEEDED) { fprintf(stderr, "fromwire_pubkey called!\n"); abort(); } +/* Generated stub for fromwire_u16 */ +u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u16 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_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 towire_amount_sat */ void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED) { fprintf(stderr, "towire_amount_sat called!\n"); abort(); } @@ -58,12 +64,18 @@ void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED) /* Generated stub for towire_pubkey */ void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED) { fprintf(stderr, "towire_pubkey called!\n"); abort(); } +/* Generated stub for towire_u16 */ +void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED) +{ fprintf(stderr, "towire_u16 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_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 */ #if 0 diff --git a/common/test/run-funding_tx_dual.c b/common/test/run-funding_tx_dual.c index 9cd10854d8d5..db4f825f0e63 100644 --- a/common/test/run-funding_tx_dual.c +++ b/common/test/run-funding_tx_dual.c @@ -37,12 +37,18 @@ void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct n /* Generated stub for fromwire_pubkey */ void fromwire_pubkey(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct pubkey *pubkey UNNEEDED) { fprintf(stderr, "fromwire_pubkey called!\n"); abort(); } +/* Generated stub for fromwire_u16 */ +u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u16 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_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 towire_amount_sat */ void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED) { fprintf(stderr, "towire_amount_sat called!\n"); abort(); } @@ -58,12 +64,18 @@ void towire_node_id(u8 **pptr UNNEEDED, const struct node_id *id UNNEEDED) /* Generated stub for towire_pubkey */ void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED) { fprintf(stderr, "towire_pubkey called!\n"); abort(); } +/* Generated stub for towire_u16 */ +void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED) +{ fprintf(stderr, "towire_u16 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_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 */ struct test_case { diff --git a/common/utxo.c b/common/utxo.c index 6b5eb7d73b50..fe59d238b349 100644 --- a/common/utxo.c +++ b/common/utxo.c @@ -24,11 +24,15 @@ void towire_utxo(u8 **pptr, const struct utxo *utxo) if (utxo->close_info->commitment_point) towire_pubkey(pptr, utxo->close_info->commitment_point); } + + towire_u16(pptr, tal_count(utxo->scriptPubkey)); + towire_u8_array(pptr, utxo->scriptPubkey, tal_count(utxo->scriptPubkey)); } struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) { struct utxo *utxo = tal(ctx, struct utxo); + u16 script_len; fromwire_bitcoin_txid(ptr, max, &utxo->txid); utxo->outnum = fromwire_u32(ptr, max); @@ -36,10 +40,6 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) utxo->keyindex = fromwire_u32(ptr, max); utxo->is_p2sh = fromwire_bool(ptr, max); - /* No need to tell hsmd about the scriptPubkey, it has all the info to - * derive it from the rest. */ - utxo->scriptPubkey = NULL; - if (fromwire_bool(ptr, max)) { utxo->close_info = tal(utxo, struct unilateral_close_info); utxo->close_info->channel_id = fromwire_u64(ptr, max); @@ -54,6 +54,9 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) } else { utxo->close_info = NULL; } + + script_len = fromwire_u16(ptr, max); + fromwire_u8_array(ptr, max, utxo->scriptPubkey, script_len); return utxo; } diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 948f9fe8a130..801c9077246b 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -13,7 +13,7 @@ void activate_peers(struct lightningd *ld UNNEEDED) { fprintf(stderr, "activate_peers called!\n"); abort(); } /* Generated stub for add_plugin_dir */ char *add_plugin_dir(struct plugins *plugins UNNEEDED, const char *dir UNNEEDED, - bool nonexist_ok UNNEEDED) + bool error_ok UNNEEDED) { fprintf(stderr, "add_plugin_dir called!\n"); abort(); } /* Generated stub for begin_topology */ void begin_topology(struct chain_topology *topo UNNEEDED) From 38ed05062fcd9fdbe668f3ddf5a37ddbbe6883e3 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 14:18:28 -0500 Subject: [PATCH 21/45] txprepare: zero out change if asked dual funding needs an output who's value is set to zero in order to correctly specify change for the opener. this modifies txprepare to allow for generating such an output --- CHANGELOG.md | 1 + plugins/fundchannel.c | 7 +++++++ wallet/walletrpc.c | 14 ++++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f0aabaaa276..10bc97e58c8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - JSON API: `fundchannel_start` now includes field `scriptpubkey` - JSON API: `txprepare` and `withdraw` now accept an optional parameter `utxos`, a list of utxos to include in the prepared transaction - JSON_API: `close` now accepts an optional parameter `destination`, to which the to-local output will be sent. +- JSON API: `txprepare` includes a parameter `zero_out_change`, which if true leaves the change value as zero. Useful for designating change output for dual-funded transactions. Defaults to false. - bolt11: support for parsing feature bits (field `9`). diff --git a/plugins/fundchannel.c b/plugins/fundchannel.c index eacbc4086ac8..f4a8393cbd4d 100644 --- a/plugins/fundchannel.c +++ b/plugins/fundchannel.c @@ -36,6 +36,9 @@ struct funding_req { /* Failing result (NULL on success) */ /* Raw JSON from RPC output */ const char *error; + + /* Are we using v2 protocol ? */ + bool is_v2; }; /* Helper to copy JSON object directly into a json_out */ @@ -259,6 +262,8 @@ static struct json_out *txprepare(struct command *cmd, json_out_add(ret, "minconf", false, "%u", *fr->minconf); if (fr->utxo_str) json_out_add_raw_len(ret, "utxos", fr->utxo_str, strlen(fr->utxo_str)); + if (fr->is_v2) + json_out_add(ret, "zero_out_change", false, "true"); json_out_end(ret, '}'); return ret; @@ -446,6 +451,8 @@ static struct command_result *json_fundchannel(struct command *cmd, } } + /* Set to false at start, will update when we know more */ + fr->is_v2 = false; fr->funding_all = streq(fr->funding_str, "all"); /* First we do a 'dry-run' of txprepare, so we can get diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 83314b1e16e1..df23e59b15fc 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -179,6 +179,7 @@ static struct command_result *json_prepare_tx(struct command *cmd, u32 *feerate_per_kw = NULL; struct command_result *result; u32 *minconf, maxheight; + bool *zero_out_change = NULL; struct pubkey *changekey; struct bitcoin_tx_output **outputs; const jsmntok_t *outputstok = NULL, *t; @@ -200,6 +201,7 @@ static struct command_result *json_prepare_tx(struct command *cmd, p_opt("feerate", param_feerate, &feerate_per_kw), p_opt_def("minconf", param_number, &minconf, 1), p_opt("utxos", param_utxos, &chosen_utxos), + p_opt_def("zero_out_change", param_bool, &zero_out_change, false), NULL)) return command_param_failed(); } else if (params->type == JSMN_ARRAY) { @@ -211,6 +213,7 @@ static struct command_result *json_prepare_tx(struct command *cmd, p_opt("feerate_or_sat", param_tok, &secondtok), p_opt("minconf_or_feerate", param_tok, &thirdtok), p_opt("utxos_or_minconf", param_tok, &fourthtok), + p_opt_def("zero_out_change", param_bool, &zero_out_change, false), NULL)) return command_param_failed(); @@ -404,17 +407,24 @@ static struct command_result *json_prepare_tx(struct command *cmd, /* Add the change as the last output */ if (!amount_sat_eq((*utx)->wtx->change, AMOUNT_SAT(0))) { struct bitcoin_tx_output *change_output; + struct amount_sat change; changekey = tal(tmpctx, struct pubkey); if (!bip32_pubkey(cmd->ld->wallet->bip32_base, changekey, (*utx)->wtx->change_key_index)) return command_fail(cmd, LIGHTNINGD, "Keys generation failure"); - change_output = new_tx_output(outputs, (*utx)->wtx->change, + + if (zero_out_change && *zero_out_change) + change = AMOUNT_SAT(0); + else + change = (*utx)->wtx->change; + change_output = new_tx_output(outputs, change, scriptpubkey_p2wpkh(tmpctx, changekey)); - tal_arr_expand(outputs, *change_output); + tal_arr_expand(&outputs, change_output); } + (*utx)->inputs = NULL; (*utx)->outputs = tal_steal(*utx, outputs); (*utx)->tx = withdraw_tx(*utx, get_chainparams(cmd->ld), (*utx)->wtx->utxos, From d24a7c70171b013074268309a84578f637d5a17a Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Tue, 8 Oct 2019 10:54:18 -0500 Subject: [PATCH 22/45] zero_out_change: add to pylightning --- contrib/pylightning/lightning/lightning.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/pylightning/lightning/lightning.py b/contrib/pylightning/lightning/lightning.py index bfd29e843aa8..0df5b8726d79 100644 --- a/contrib/pylightning/lightning/lightning.py +++ b/contrib/pylightning/lightning/lightning.py @@ -962,12 +962,13 @@ def txprepare(self, *args, **kwargs): if not isinstance(args[0], list): return self._deprecated_txprepare(*args, **kwargs) - def _txprepare(outputs, feerate=None, minconf=None, utxos=None): + def _txprepare(outputs, feerate=None, minconf=None, utxos=None, zero_out_change=None): payload = { "outputs": outputs, "feerate": feerate, "minconf": minconf, "utxos": utxos, + "zero_out_change": zero_out_change, } return self.call("txprepare", payload) From 9409550f94cef0a132efa355c7613830186a3220 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 14:27:07 -0500 Subject: [PATCH 23/45] wire: add dual-funding subtypes to list allows us to use them in wire definitions other than where they are defined. --- tools/generate-wire.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/generate-wire.py b/tools/generate-wire.py index 834fbed95519..e044318fd230 100755 --- a/tools/generate-wire.py +++ b/tools/generate-wire.py @@ -222,6 +222,9 @@ class Type(FieldSet): 'bitcoin_tx_output', 'exclude_entry', 'bitcoin_tx_input', + 'output_info', + 'input_info', + 'witness_stack', ] # Some BOLT types are re-typed based on their field name From 8c0942fa56ffa28a78ec425a2c4ad2cfb53e3bf9 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 16:47:16 -0500 Subject: [PATCH 24/45] wallet-df: save our_funds amount to channel record We'll need it to represent to user in `listpeers` --- lightningd/channel.c | 2 + lightningd/channel.h | 5 ++ lightningd/opening_control.c | 1 + wallet/db.c | 1 + wallet/wallet.c | 118 ++++++++++++++++++----------------- 5 files changed, 71 insertions(+), 56 deletions(-) diff --git a/lightningd/channel.c b/lightningd/channel.c index 8d81123af53f..66a455aba891 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -156,6 +156,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u16 funding_outnum, struct amount_sat funding, struct amount_msat push, + struct amount_sat our_funds, bool remote_funding_locked, /* NULL or stolen */ struct short_channel_id *scid, @@ -228,6 +229,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->funding_outnum = funding_outnum; channel->funding = funding; channel->push = push; + channel->our_funds = our_funds; channel->remote_funding_locked = remote_funding_locked; channel->scid = tal_steal(channel, scid); channel->our_msat = our_msat; diff --git a/lightningd/channel.h b/lightningd/channel.h index 87273e384d0a..e5ec93cf595a 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -60,6 +60,10 @@ struct channel { struct bitcoin_txid funding_txid; u16 funding_outnum; struct amount_sat funding; + + /* Our original funds, in funding amount */ + struct amount_sat our_funds; + struct amount_msat push; bool remote_funding_locked; /* Channel if locked locally. */ @@ -143,6 +147,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, u16 funding_outnum, struct amount_sat funding, struct amount_msat push, + struct amount_sat our_funds, bool remote_funding_locked, /* NULL or stolen */ struct short_channel_id *scid, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index c92b4cfc1739..6d7232651a37 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -251,6 +251,7 @@ wallet_commit_channel(struct lightningd *ld, funding_outnum, total_funding, push, + local_funding, false, /* !remote_funding_locked */ NULL, /* no scid yet */ /* The three arguments below are msatoshi_to_us, diff --git a/wallet/db.c b/wallet/db.c index 7ae27e3c3af1..a80b8ef8fc54 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -477,6 +477,7 @@ static struct migration dbmigrations[] = { ");"), NULL}, {SQL("ALTER TABLE channels ADD shutdown_scriptpubkey_local BLOB;"), NULL}, + {SQL("ALTER TABLE channels ADD COLUMN our_funding_satoshi INTEGER;"), NULL}, }; /* Leak tracking. */ diff --git a/wallet/wallet.c b/wallet/wallet.c index df2ad37e634f..253cec244a61 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -828,7 +828,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm struct basepoints local_basepoints; struct pubkey local_funding_pubkey; struct pubkey *future_per_commitment_point; - struct amount_sat funding_sat; + struct amount_sat funding_sat, our_funding_sat; struct amount_msat push_msat, our_msat, msat_to_us_min, msat_to_us_max; peer_dbid = db_column_u64(stmt, 1); @@ -848,15 +848,15 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm scid = NULL; } - ok &= wallet_shachain_load(w, db_column_u64(stmt, 27), &wshachain); + ok &= wallet_shachain_load(w, db_column_u64(stmt, 28), &wshachain); - remote_shutdown_scriptpubkey = db_column_arr(tmpctx, stmt, 28, u8); + remote_shutdown_scriptpubkey = db_column_arr(tmpctx, stmt, 29, u8); local_shutdown_scriptpubkey = db_column_arr(tmpctx, stmt, 46, u8); /* Do we have a last_sent_commit, if yes, populate */ - if (!db_column_is_null(stmt, 41)) { - const u8 *cursor = db_column_blob(stmt, 41); - size_t len = db_column_bytes(stmt, 41); + if (!db_column_is_null(stmt, 42)) { + const u8 *cursor = db_column_blob(stmt, 42); + size_t len = db_column_bytes(stmt, 42); size_t n = 0; last_sent_commit = tal_arr(tmpctx, struct changed_htlc, n); while (len) { @@ -868,35 +868,35 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm last_sent_commit = NULL; #ifdef COMPAT_V060 - if (!last_sent_commit && !db_column_is_null(stmt, 30)) { + if (!last_sent_commit && !db_column_is_null(stmt, 31)) { last_sent_commit = tal(tmpctx, struct changed_htlc); - last_sent_commit->newstate = db_column_u64(stmt, 30); - last_sent_commit->id = db_column_u64(stmt, 31); + last_sent_commit->newstate = db_column_u64(stmt, 31); + last_sent_commit->id = db_column_u64(stmt, 32); } #endif - if (!db_column_is_null(stmt, 40)) { + if (!db_column_is_null(stmt, 41)) { future_per_commitment_point = tal(tmpctx, struct pubkey); - db_column_pubkey(stmt, 40, future_per_commitment_point); + db_column_pubkey(stmt, 41, future_per_commitment_point); } else future_per_commitment_point = NULL; channel_config_id = db_column_u64(stmt, 3); ok &= wallet_channel_config_load(w, channel_config_id, &our_config); db_column_sha256d(stmt, 12, &funding_txid.shad); - ok &= db_column_signature(stmt, 33, &last_sig.s); + ok &= db_column_signature(stmt, 34, &last_sig.s); last_sig.sighash_type = SIGHASH_ALL; /* Populate channel_info */ - db_column_pubkey(stmt, 18, &channel_info.remote_fundingkey); - db_column_pubkey(stmt, 19, &channel_info.theirbase.revocation); - db_column_pubkey(stmt, 20, &channel_info.theirbase.payment); - db_column_pubkey(stmt, 21, &channel_info.theirbase.htlc); - db_column_pubkey(stmt, 22, &channel_info.theirbase.delayed_payment); - db_column_pubkey(stmt, 23, &channel_info.remote_per_commit); - db_column_pubkey(stmt, 24, &channel_info.old_remote_per_commit); - channel_info.feerate_per_kw[LOCAL] = db_column_int(stmt, 25); - channel_info.feerate_per_kw[REMOTE] = db_column_int(stmt, 26); + db_column_pubkey(stmt, 19, &channel_info.remote_fundingkey); + db_column_pubkey(stmt, 20, &channel_info.theirbase.revocation); + db_column_pubkey(stmt, 21, &channel_info.theirbase.payment); + db_column_pubkey(stmt, 22, &channel_info.theirbase.htlc); + db_column_pubkey(stmt, 23, &channel_info.theirbase.delayed_payment); + db_column_pubkey(stmt, 24, &channel_info.remote_per_commit); + db_column_pubkey(stmt, 25, &channel_info.old_remote_per_commit); + channel_info.feerate_per_kw[LOCAL] = db_column_int(stmt, 26); + channel_info.feerate_per_kw[REMOTE] = db_column_int(stmt, 27); wallet_channel_config_load(w, db_column_u64(stmt, 4), &channel_info.their_config); @@ -905,7 +905,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm return NULL; } - final_key_idx = db_column_u64(stmt, 29); + final_key_idx = db_column_u64(stmt, 30); if (final_key_idx < 0) { log_broken(w->log, "%s: Final key < 0", __func__); return NULL; @@ -915,10 +915,11 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm &local_basepoints, &local_funding_pubkey); db_column_amount_sat(stmt, 14, &funding_sat); - db_column_amount_msat(stmt, 16, &push_msat); - db_column_amount_msat(stmt, 17, &our_msat); - db_column_amount_msat(stmt, 38, &msat_to_us_min); - db_column_amount_msat(stmt, 39, &msat_to_us_max); + db_column_amount_sat(stmt, 15, &our_funding_sat); + db_column_amount_msat(stmt, 17, &push_msat); + db_column_amount_msat(stmt, 18, &our_msat); + db_column_amount_msat(stmt, 39, &msat_to_us_min); + db_column_amount_msat(stmt, 40, &msat_to_us_max); chan = new_channel(peer, db_column_u64(stmt, 0), &wshachain, @@ -936,12 +937,13 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_column_int(stmt, 13), funding_sat, push_msat, - db_column_int(stmt, 15) != 0, + our_funding_sat, + db_column_int(stmt, 16) != 0, scid, our_msat, msat_to_us_min, /* msatoshi_to_us_min */ msat_to_us_max, /* msatoshi_to_us_max */ - db_column_tx(tmpctx, stmt, 32), + db_column_tx(tmpctx, stmt, 33), &last_sig, wallet_htlc_sigs_load(tmpctx, w, db_column_u64(stmt, 0)), @@ -949,19 +951,19 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm remote_shutdown_scriptpubkey, local_shutdown_scriptpubkey, final_key_idx, - db_column_int(stmt, 34) != 0, + db_column_int(stmt, 35) != 0, last_sent_commit, - db_column_u64(stmt, 35), - db_column_int(stmt, 36), + db_column_u64(stmt, 36), db_column_int(stmt, 37), + db_column_int(stmt, 38), /* Not connected */ false, &local_basepoints, &local_funding_pubkey, future_per_commitment_point, - db_column_int(stmt, 42), db_column_int(stmt, 43), - db_column_arr(tmpctx, stmt, 44, u8), - db_column_int(stmt, 45)); + db_column_int(stmt, 44), + db_column_arr(tmpctx, stmt, 45, u8), + db_column_int(stmt, 46)); return chan; } @@ -1002,6 +1004,7 @@ static bool wallet_channels_load_active(struct wallet *w) ", funding_tx_id" ", funding_tx_outnum" ", funding_satoshi" + ", our_funding_satoshi" ", funding_locked_remote" ", push_msatoshi" ", msatoshi_local" @@ -1281,6 +1284,7 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) " funding_tx_id=?," " funding_tx_outnum=?," " funding_satoshi=?," + " our_funding_satoshi=?," " funding_locked_remote=?," " push_msatoshi=?," " msatoshi_local=?," @@ -1317,37 +1321,39 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) db_bind_int(stmt, 10, chan->funding_outnum); db_bind_amount_sat(stmt, 11, &chan->funding); - db_bind_int(stmt, 12, chan->remote_funding_locked); - db_bind_amount_msat(stmt, 13, &chan->push); - db_bind_amount_msat(stmt, 14, &chan->our_msat); + db_bind_amount_sat(stmt, 12, &chan->our_funds); + db_bind_int(stmt, 13, chan->remote_funding_locked); + db_bind_amount_msat(stmt, 14, &chan->push); + db_bind_amount_msat(stmt, 15, &chan->our_msat); if (chan->shutdown_scriptpubkey[REMOTE]) - db_bind_blob(stmt, 15, chan->shutdown_scriptpubkey[REMOTE], + db_bind_blob(stmt, 16, chan->shutdown_scriptpubkey[REMOTE], tal_count(chan->shutdown_scriptpubkey[REMOTE])); else - db_bind_null(stmt, 15); - - db_bind_u64(stmt, 16, chan->final_key_idx); - db_bind_u64(stmt, 17, chan->our_config.id); - db_bind_tx(stmt, 18, chan->last_tx); - db_bind_signature(stmt, 19, &chan->last_sig.s); - db_bind_int(stmt, 20, chan->last_was_revoke); - db_bind_int(stmt, 21, chan->min_possible_feerate); - db_bind_int(stmt, 22, chan->max_possible_feerate); - db_bind_amount_msat(stmt, 23, &chan->msat_to_us_min); - db_bind_amount_msat(stmt, 24, &chan->msat_to_us_max); - db_bind_int(stmt, 25, chan->feerate_base); - db_bind_int(stmt, 26, chan->feerate_ppm); + db_bind_null(stmt, 16); + + db_bind_u64(stmt, 17, chan->final_key_idx); + db_bind_u64(stmt, 18, chan->our_config.id); + db_bind_tx(stmt, 19, chan->last_tx); + db_bind_signature(stmt, 20, &chan->last_sig.s); + db_bind_int(stmt, 21, chan->last_was_revoke); + db_bind_int(stmt, 22, chan->min_possible_feerate); + db_bind_int(stmt, 23, chan->max_possible_feerate); + db_bind_amount_msat(stmt, 24, &chan->msat_to_us_min); + db_bind_amount_msat(stmt, 25, &chan->msat_to_us_max); + db_bind_int(stmt, 26, chan->feerate_base); + db_bind_int(stmt, 27, chan->feerate_ppm); if (chan->remote_upfront_shutdown_script) db_bind_blob( - stmt, 27, chan->remote_upfront_shutdown_script, + stmt, 28, chan->remote_upfront_shutdown_script, tal_count(chan->remote_upfront_shutdown_script)); else - db_bind_null(stmt, 27); - db_bind_int(stmt, 28, chan->option_static_remotekey); - db_bind_blob(stmt, 29, chan->shutdown_scriptpubkey[LOCAL], + db_bind_null(stmt, 28); + + db_bind_int(stmt, 29, chan->option_static_remotekey); + db_bind_blob(stmt, 30, chan->shutdown_scriptpubkey[LOCAL], tal_count(chan->shutdown_scriptpubkey[LOCAL])); - db_bind_u64(stmt, 30, chan->dbid); + db_bind_u64(stmt, 31, chan->dbid); db_exec_prepared_v2(take(stmt)); wallet_channel_config_save(w, &chan->channel_info.their_config); From 6602fa70e1673a28625b6a54e90234510952cc63 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:05:28 -0500 Subject: [PATCH 25/45] utxo: add scriptSig field Allow the utxo object to bear the scriptSig as well; also fixes broken scriptPubkey parsing on utxo --- common/utxo.c | 19 ++++++++++++++----- common/utxo.h | 3 +++ wallet/wallet.c | 17 +++++++++++++++++ wallet/wallet.h | 8 ++++++++ 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/common/utxo.c b/common/utxo.c index fe59d238b349..e8373b1d2473 100644 --- a/common/utxo.c +++ b/common/utxo.c @@ -16,6 +16,11 @@ void towire_utxo(u8 **pptr, const struct utxo *utxo) towire_u32(pptr, utxo->keyindex); towire_bool(pptr, utxo->is_p2sh); + towire_u16(pptr, tal_count(utxo->scriptPubkey)); + towire_u8_array(pptr, utxo->scriptPubkey, tal_count(utxo->scriptPubkey)); + towire_u16(pptr, tal_count(utxo->scriptSig)); + towire_u8_array(pptr, utxo->scriptSig, tal_count(utxo->scriptSig)); + towire_bool(pptr, is_unilateral_close); if (is_unilateral_close) { towire_u64(pptr, utxo->close_info->channel_id); @@ -24,15 +29,13 @@ void towire_utxo(u8 **pptr, const struct utxo *utxo) if (utxo->close_info->commitment_point) towire_pubkey(pptr, utxo->close_info->commitment_point); } - - towire_u16(pptr, tal_count(utxo->scriptPubkey)); - towire_u8_array(pptr, utxo->scriptPubkey, tal_count(utxo->scriptPubkey)); } struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) { struct utxo *utxo = tal(ctx, struct utxo); u16 script_len; + u16 scriptsig_len; fromwire_bitcoin_txid(ptr, max, &utxo->txid); utxo->outnum = fromwire_u32(ptr, max); @@ -40,6 +43,14 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) utxo->keyindex = fromwire_u32(ptr, max); utxo->is_p2sh = fromwire_bool(ptr, max); + script_len = fromwire_u16(ptr, max); + utxo->scriptPubkey = tal_arr(utxo, u8, script_len); + fromwire_u8_array(ptr, max, utxo->scriptPubkey, script_len); + + scriptsig_len = fromwire_u16(ptr, max); + utxo->scriptSig = tal_arr(utxo, u8, scriptsig_len); + fromwire_u8_array(ptr, max, utxo->scriptSig, scriptsig_len); + if (fromwire_bool(ptr, max)) { utxo->close_info = tal(utxo, struct unilateral_close_info); utxo->close_info->channel_id = fromwire_u64(ptr, max); @@ -55,8 +66,6 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) utxo->close_info = NULL; } - script_len = fromwire_u16(ptr, max); - fromwire_u8_array(ptr, max, utxo->scriptPubkey, script_len); return utxo; } diff --git a/common/utxo.h b/common/utxo.h index 1eef4a0828d5..46caccc44527 100644 --- a/common/utxo.h +++ b/common/utxo.h @@ -41,6 +41,9 @@ struct utxo { /* The scriptPubkey if it is known */ u8 *scriptPubkey; + + /* scriptSig. Only for P2SH outputs */ + u8 *scriptSig; }; void towire_utxo(u8 **pptr, const struct utxo *utxo); diff --git a/wallet/wallet.c b/wallet/wallet.c index 253cec244a61..d3a9a9fd98e7 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -172,6 +172,7 @@ static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt) utxo->blockheight = NULL; utxo->spendheight = NULL; utxo->scriptPubkey = NULL; + utxo->scriptSig = NULL; if (!db_column_is_null(stmt, 9)) { blockheight = tal(utxo, u32); @@ -532,6 +533,22 @@ const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, return utxo; } +u8 *derive_redeem_scriptsig(const tal_t *ctx, struct wallet *w, u32 keyindex) +{ + struct ext_key ext; + struct pubkey key; + + if (bip32_key_from_parent(w->bip32_base, keyindex, + BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK) { + fatal("Unable to derive pubkey"); + } + + if (!pubkey_from_der(ext.pub_key, PUBKEY_CMPR_LEN, &key)) + fatal("Unble to derive pubkey from DER"); + + return bitcoin_scriptsig_p2sh_p2wpkh(ctx, &key); +} + bool wallet_can_spend(struct wallet *w, const u8 *script, u32 *index, bool *output_is_p2sh) { diff --git a/wallet/wallet.h b/wallet/wallet.h index 438b85b53991..b9ac8c7db15a 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -387,6 +387,14 @@ const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, struct amount_sat *sat, struct amount_sat *fee_estimate); +/* derive_redeem_scriptsig - Compute the scriptSig for a P2SH-P2WPKH + * + * @ctx - allocation context + * @w - wallet + * @keyindex - index of the internal BIP32 key + */ +u8 *derive_redeem_scriptsig(const tal_t *ctx, struct wallet *w, u32 keyindex); + /** * wallet_select_specific - Select utxos given an array of txids and an array of outputs index * From 0ed16352d2ebb5913e8ab39efa344d8fb9aaef08 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:13:48 -0500 Subject: [PATCH 26/45] channeld: add flag for whether channel has our funds --- channeld/channel_wire.csv | 1 + channeld/channeld.c | 4 +++- channeld/full_channel.c | 2 ++ channeld/full_channel.h | 2 ++ channeld/test/run-full_channel.c | 4 ++-- common/initial_channel.c | 2 ++ common/initial_channel.h | 6 ++++++ devtools/mkcommit.c | 1 + lightningd/channel_control.c | 1 + openingd/openingd.c | 4 +++- 10 files changed, 23 insertions(+), 4 deletions(-) diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 9725269b5fe1..4f3586366a7f 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -23,6 +23,7 @@ msgdata,channel_init,remote_basepoints,basepoints, msgdata,channel_init,remote_per_commit,pubkey, msgdata,channel_init,old_remote_per_commit,pubkey, msgdata,channel_init,opener,enum side, +msgdata,channel_init,local_funded,bool, msgdata,channel_init,fee_base,u32, msgdata,channel_init,fee_proportional,u32, msgdata,channel_init,local_msatoshi,amount_msat, diff --git a/channeld/channeld.c b/channeld/channeld.c index 2c5e083bcd6b..952474d9581c 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2951,7 +2951,7 @@ static void init_channel(struct peer *peer) struct secret last_remote_per_commit_secret; secp256k1_ecdsa_signature *remote_ann_node_sig; secp256k1_ecdsa_signature *remote_ann_bitcoin_sig; - bool option_static_remotekey; + bool option_static_remotekey, local_funded; assert(!(fcntl(MASTER_FD, F_GETFL) & O_NONBLOCK)); @@ -2973,6 +2973,7 @@ static void init_channel(struct peer *peer) &peer->remote_per_commit, &peer->old_remote_per_commit, &opener, + &local_funded, &peer->fee_base, &peer->fee_per_satoshi, &local_msat, @@ -3071,6 +3072,7 @@ static void init_channel(struct peer *peer) &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], option_static_remotekey, + local_funded, opener); if (!channel_force_htlcs(peer->channel, htlcs, hstates, diff --git a/channeld/full_channel.c b/channeld/full_channel.c index 799296543a0f..efeefa9e244f 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -47,6 +47,7 @@ struct channel *new_full_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, + bool local_funded, enum side opener) { struct channel *channel = new_initial_channel(ctx, @@ -63,6 +64,7 @@ struct channel *new_full_channel(const tal_t *ctx, local_funding_pubkey, remote_funding_pubkey, option_static_remotekey, + local_funded, opener); if (channel) { diff --git a/channeld/full_channel.h b/channeld/full_channel.h index 01e47de4b2cd..7c3326d1d4b3 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -25,6 +25,7 @@ * @local_fundingkey: local funding key * @remote_fundingkey: remote funding key * @option_static_remotekey: use `option_static_remotekey`. + * @local_funded: true if local has inputs in funding tx * @opener: which side initiated it. * * Returns state, or NULL if malformed. @@ -44,6 +45,7 @@ struct channel *new_full_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, + bool local_funded, enum side opener); /** diff --git a/channeld/test/run-full_channel.c b/channeld/test/run-full_channel.c index ed38cb907820..e0850b7a508a 100644 --- a/channeld/test/run-full_channel.c +++ b/channeld/test/run-full_channel.c @@ -473,7 +473,7 @@ int main(void) &localbase, &remotebase, &local_funding_pubkey, &remote_funding_pubkey, - false, LOCAL); + false, true, LOCAL); rchannel = new_full_channel(tmpctx, &chainparams->genesis_blockhash, &funding_txid, funding_output_index, 0, @@ -484,7 +484,7 @@ int main(void) &remotebase, &localbase, &remote_funding_pubkey, &local_funding_pubkey, - false, REMOTE); + false, false, REMOTE); /* BOLT #3: * diff --git a/common/initial_channel.c b/common/initial_channel.c index 2714d4292f56..baa621a853f7 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -23,6 +23,7 @@ struct channel *new_initial_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, + bool local_funded, enum side opener) { struct channel *channel = tal(ctx, struct channel); @@ -31,6 +32,7 @@ struct channel *new_initial_channel(const tal_t *ctx, channel->funding_txid = *funding_txid; channel->funding_txout = funding_txout; channel->funding = funding; + channel->local_funded = local_funded; channel->minimum_depth = minimum_depth; if (!amount_sat_sub_msat(&remote_msatoshi, channel->funding, local_msatoshi)) diff --git a/common/initial_channel.h b/common/initial_channel.h index 242217a2ecf4..c395ef34d5f8 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -44,6 +44,9 @@ struct channel { /* Who is paying fees. */ enum side opener; + /* True if we have inputs in the funding tx */ + bool local_funded; + /* Limits and settings on this channel. */ struct channel_config config[NUM_SIDES]; @@ -86,6 +89,8 @@ struct channel { * @remote_basepoints: remote basepoints. * @local_fundingkey: local funding key * @remote_fundingkey: remote funding key + * @option_static_remotekey: whether to use static remotekeys or not + * @local_funded: true if we put funds into the funding tx * @opener: which side initiated it. * * Returns channel, or NULL if malformed. @@ -105,6 +110,7 @@ struct channel *new_initial_channel(const tal_t *ctx, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, + bool local_funded, enum side opener); diff --git a/devtools/mkcommit.c b/devtools/mkcommit.c index acb765403688..487a28678306 100644 --- a/devtools/mkcommit.c +++ b/devtools/mkcommit.c @@ -368,6 +368,7 @@ int main(int argc, char *argv[]) &localbase, &remotebase, &funding_localkey, &funding_remotekey, option_static_remotekey, + fee_payer == LOCAL, fee_payer); if (!channel_force_htlcs(channel, htlcs, hstates, NULL, NULL, NULL, NULL, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index d751c6054635..119790779fce 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -438,6 +438,7 @@ void peer_start_channeld(struct channel *channel, &channel->channel_info.remote_per_commit, &channel->channel_info.old_remote_per_commit, channel->opener, + !amount_sat_eq(channel->our_funds, AMOUNT_SAT(0)), channel->feerate_base, channel->feerate_ppm, channel->our_msat, diff --git a/openingd/openingd.c b/openingd/openingd.c index 57c2ec4ae8ee..59766f899b11 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -1096,6 +1096,7 @@ static u8 *funder_finalize_channel_setup2(struct state *state, &state->our_funding_pubkey, &state->their_funding_pubkey, state->option_static_remotekey, + true, LOCAL); /* We don't expect this to fail, but it does do some additional @@ -1257,7 +1258,7 @@ static bool funder_finalize_channel_setup(struct state *state, &state->our_funding_pubkey, &state->their_funding_pubkey, state->option_static_remotekey, - /* Opener is local */ + true, LOCAL); /* We were supposed to do enough checks above, but just in case, * new_initial_channel will fail to create absurd channels */ @@ -1725,6 +1726,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) &state->our_funding_pubkey, &their_funding_pubkey, state->option_static_remotekey, + false, REMOTE); /* We don't expect this to fail, but it does do some additional * internal sanity checks. */ From e99893dadb2fb795256e18cb651213467ba0a76e Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:29:05 -0500 Subject: [PATCH 27/45] df: pass opener's change through so we can update utx We need the change amount to be correct when we send the tx, so we save the change amount and pipe it through. --- common/funding_tx.c | 28 ++++++------- common/funding_tx.h | 4 +- common/test/run-funding_tx_dual.c | 5 ++- lightningd/opening_control.c | 12 ++++-- openingd/opening_wire.csv | 14 +++++-- openingd/openingd.c | 65 +++++++++++++------------------ 6 files changed, 66 insertions(+), 62 deletions(-) diff --git a/common/funding_tx.c b/common/funding_tx.c index 944e890d0029..bf1680ffceb4 100644 --- a/common/funding_tx.c +++ b/common/funding_tx.c @@ -196,12 +196,12 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, struct amount_sat *total_funding, + struct amount_sat *opener_change, const void **input_map) { size_t weight; struct amount_sat funding_tx_fee, opener_total_sat, - accepter_total_sat, - opener_change, output_val; + accepter_total_sat, output_val; struct bitcoin_tx *tx; const struct output_info *change_output; @@ -216,7 +216,7 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, &opener_total_sat, &accepter_total_sat); funding_tx_fee = amount_tx_fee(feerate_kw_funding, weight); - if (!amount_sat_sub(&opener_change, opener_total_sat, *opener_funding)) + if (!amount_sat_sub(opener_change, opener_total_sat, *opener_funding)) return NULL; /* Check that the remaining amount at least covers the other @@ -225,18 +225,18 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, * only 'flexible' / change output that's removable etc is indicated * by a zero value. */ output_val = calculate_output_value(opener_outputs); - if (!amount_sat_sub(&opener_change, opener_change, output_val)) + if (!amount_sat_sub(opener_change, *opener_change, output_val)) return NULL; change_output = find_change_output(opener_outputs); - if (amount_sat_sub(&opener_change, opener_change, funding_tx_fee) && - amount_sat_greater(opener_change, chainparams->dust_limit)) { + if (amount_sat_sub(opener_change, *opener_change, funding_tx_fee) && + amount_sat_greater(*opener_change, chainparams->dust_limit)) { if (!change_output) { /* If there's no change output, we put the remainder into * the funding output. TODO: add to spec */ assert(amount_sat_add(opener_funding, - *opener_funding, opener_change)); - opener_change = AMOUNT_SAT(0); + *opener_funding, *opener_change)); + *opener_change = AMOUNT_SAT(0); } goto build_tx; @@ -249,9 +249,9 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, funding_tx_fee = amount_tx_fee(feerate_kw_funding, weight); /* Any left over gets added to the funding output */ - if (amount_sat_sub(&opener_change, opener_change, funding_tx_fee)) { - assert(amount_sat_add(opener_funding, *opener_funding, opener_change)); - opener_change = AMOUNT_SAT(0); + if (amount_sat_sub(opener_change, *opener_change, funding_tx_fee)) { + assert(amount_sat_add(opener_funding, *opener_funding, *opener_change)); + *opener_change = AMOUNT_SAT(0); goto build_tx; } } @@ -260,7 +260,7 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, !amount_sat_sub(opener_funding, *opener_funding, output_val)) return NULL; - opener_change = AMOUNT_SAT(0); + *opener_change = AMOUNT_SAT(0); build_tx: input_count = tal_count(opener_inputs) + tal_count(accepter_inputs); @@ -270,7 +270,7 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, /* If they had supplied a change output, but we removed it because * remove it from the count */ - if (change_output && amount_sat_eq(AMOUNT_SAT(0), opener_change)) { + if (change_output && amount_sat_eq(AMOUNT_SAT(0), *opener_change)) { output_count -= 1; assert(output_count > 0); } @@ -298,7 +298,7 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, bitcoin_tx_add_output(tx, scriptpubkey_p2wsh(tx, wscript), *total_funding); /* Add the other outputs */ - add_outputs(tx, opener_outputs, &opener_change); + add_outputs(tx, opener_outputs, opener_change); add_outputs(tx, accepter_outputs, NULL); /* Note that hsmd depends on the opener's inputs diff --git a/common/funding_tx.h b/common/funding_tx.h index 93cefc72941d..f07493810d36 100644 --- a/common/funding_tx.h +++ b/common/funding_tx.h @@ -55,7 +55,6 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx, * @chainparams: (in) the params for the resulting transaction. * @outnum: (out) txout which is the funding output. * @feerate_kw_funding: (in) feerate for the funding transaction - * @total_funding: (out) total funding amount for this transaction * @opener_funding: (in/out) funding amount contributed by opener * @accepter_funding: (in) funding amount contributed by accepter * @opener_inputs: (in) inputs from the opener @@ -64,6 +63,8 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx, * @accepter_outputs: (in) outputs for the accepter * @local_fundingkey: (in) local key for 2of2 funding output. * @remote_fundingkey: (in) remote key for 2of2 funding output. + * @total_funding: (out) total funding amount for this transaction + * @opener_change: (out) change amount for opener * @input_map: (out) ordering of inputs, after being sorted. */ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, @@ -79,6 +80,7 @@ struct bitcoin_tx *dual_funding_funding_tx(const tal_t *ctx, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, struct amount_sat *total_funding, + struct amount_sat *opener_change, const void **input_map); #endif /* EXPERIMENTAL_FEATURES */ #endif /* LIGHTNING_COMMON_FUNDING_TX_H */ diff --git a/common/test/run-funding_tx_dual.c b/common/test/run-funding_tx_dual.c index db4f825f0e63..0187a69b513b 100644 --- a/common/test/run-funding_tx_dual.c +++ b/common/test/run-funding_tx_dual.c @@ -729,7 +729,7 @@ int main(void) setup_tmpctx(); u16 outnum; - struct amount_sat total_funding; + struct amount_sat total_funding, opener_change; for (size_t i = 0; i < num_tests; i++) { struct test_case test = test_cases[i](tmpctx); @@ -754,7 +754,8 @@ int main(void) test.accepter_outputs, &local_funding_pubkey, &remote_funding_pubkey, - &total_funding, NULL); + &total_funding, + &opener_change, NULL); if (!test.expected_tx && !funding) continue; diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 6d7232651a37..7ab0c6b7b13f 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -368,6 +368,7 @@ static void opening_funder_start_replied(struct subd *openingd, const u8 *resp, static bool update_unreleased_tx(struct unreleased_tx *utx, struct bitcoin_tx *tx, u32 *input_map, + struct amount_sat opener_change, struct witness_stack **witnesses) { size_t i, j, num_other_ins, num_utxo; @@ -453,6 +454,7 @@ static bool update_unreleased_tx(struct unreleased_tx *utx, utx->tx = tal_free(utx->tx); utx->tx = tal_steal(utx, tx); bitcoin_txid(tx, &utx->txid); + utx->wtx->change = opener_change; return true; } @@ -469,12 +471,12 @@ static void opening_opener_finished(struct subd *openingd, const u8 *resp, struct bitcoin_signature remote_commit_sig; struct bitcoin_tx *remote_commit, *funding_tx; u32 feerate, feerate_funding; - struct amount_sat local_funding, total_funding; + struct amount_sat local_funding, total_funding, opener_change; struct channel *channel; struct lightningd *ld = openingd->ld; u8 *remote_upfront_shutdown_script; struct per_peer_state *pps; - struct bitcoin_tx_input **remote_ins; + struct witness_stack **remote_witnesses; struct funding_channel *fc = uc->fc; struct unreleased_tx *utx = fc->utx; u32 *input_map; @@ -489,7 +491,8 @@ static void opening_opener_finished(struct subd *openingd, const u8 *resp, &remote_commit_sig, &funding_tx, &funding_txout, - &remote_ins, + &opener_change, + &remote_witnesses, &input_map, &local_funding, &channel_info.their_config, @@ -523,7 +526,7 @@ static void opening_opener_finished(struct subd *openingd, const u8 *resp, } /* Update the funding tx that we have for this */ - if (!update_unreleased_tx(utx, funding_tx, input_map, witnesses)) { + if (!update_unreleased_tx(utx, funding_tx, input_map, opener_change, witnesses)) { log_broken(uc->log, "Unable to update unreleased tx"); uncommitted_channel_disconnect(uc, "internal error in creating updated tx"); goto cleanup; @@ -693,6 +696,7 @@ static void opening_fundee_finished(struct subd *openingd, &funding_txid, &funding_outnum, &funding, + &AMOUNT_SAT(0), &push, &channel_flags, &feerate, diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index 825837e52c3b..6d4a58f9342e 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -112,27 +112,33 @@ msgdata,opening_fundee,their_per_commit_point,pubkey, msgdata,opening_fundee,remote_fundingkey,pubkey, msgdata,opening_fundee,funding_txid,bitcoin_txid, msgdata,opening_fundee,funding_txout,u16, -msgdata,opening_fundee,funding_satoshis,amount_sat, +msgdata,opening_fundee,opener_funding,amount_sat, +msgdata,opening_fundee,accepter_funding,amount_sat, msgdata,opening_fundee,push_msat,amount_msat, msgdata,opening_fundee,channel_flags,u8, msgdata,opening_fundee,feerate_per_kw,u32, -# The funding signed message: send this and we're committed. +# The 'signed' message: send this and we're committed. +# msgtype v1: funding_signed +# msgtype v2: accepter_sigs msgdata,opening_fundee,msglen,u16, -msgdata,opening_fundee,funding_signed_msg,u8,msglen +msgdata,opening_fundee,signed_msg,u8,msglen msgdata,opening_fundee,our_channel_reserve_satoshis,amount_sat, msgdata,opening_fundee,shutdown_len,u16, msgdata,opening_fundee,shutdown_scriptpubkey,u8,shutdown_len # openingd->master: accepter's signatures etc # for a dual-funded channel open +#include msgtype,opening_dual_funding_signed,6204 +#if EXPERIMENTAL_FEATURES msgdata,opening_dual_funding_signed,pps,per_peer_state, msgdata,opening_dual_funding_signed,first_commit,bitcoin_tx, msgdata,opening_dual_funding_signed,first_commit_sig,bitcoin_signature, msgdata,opening_dual_funding_signed,funding_tx,bitcoin_tx, msgdata,opening_dual_funding_signed,funding_tx_out,u16, +msgdata,opening_dual_funding_signed,opener_change,amount_sat, msgdata,opening_dual_funding_signed,num_witnesses,u16, -msgdata,opening_dual_funding_signed,remote_witnesses,bitcoin_tx_input,num_witnesses +msgdata,opening_dual_funding_signed,remote_witnesses,witness_stack,num_witnesses msgdata,opening_dual_funding_signed,num_inputs,u32, msgdata,opening_dual_funding_signed,input_map,u32,num_inputs msgdata,opening_dual_funding_signed,local_funding,amount_sat, diff --git a/openingd/openingd.c b/openingd/openingd.c index 59766f899b11..44394a910ebe 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -1004,19 +1004,16 @@ static u8 *funder_finalize_channel_setup2(struct state *state, char *err_reason; struct input_info **local_ins, **remote_ins; struct output_info **local_outs, **remote_outs; - struct bitcoin_tx_input **remotetx_ins; - struct amount_sat total_funding; + struct amount_sat total_funding, opener_change; struct bitcoin_signature their_sig, our_sig; struct amount_msat local_funding_msat; size_t i, input_count; struct bitcoin_tx *funding_tx, *remote_commit, *local_commit; - struct witness_stack **remote_witnesses; + const struct witness_stack **remote_witnesses; /* Derive components, omitting the funding output */ - local_ins = tal_arr(tmpctx, struct input_info *, 0); - local_outs = tal_arr(tmpctx, struct output_info *, 0); - derive_input_output_info(tmpctx, *tx, utxos, true, + derive_input_output_info(state, *tx, utxos, true, &local_ins, &local_outs); /* Send them to the peer */ @@ -1066,6 +1063,7 @@ static u8 *funder_finalize_channel_setup2(struct state *state, &state->our_funding_pubkey, &state->their_funding_pubkey, &total_funding, + &opener_change, (const void **)&map); if (!funding_tx) @@ -1183,43 +1181,35 @@ static u8 *funder_finalize_channel_setup2(struct state *state, &state->their_funding_pubkey)); peer_billboard(false, - "Opening channel: accepter sigs are acceptable, moving to sign tx"); + "Opening channel: accepter sigs are acceptable, moving to sign tx %s", + type_to_string(state, struct bitcoin_tx, funding_tx)); - u32 i_map[input_count]; + u32 *i_map = tal_arr(tmpctx, u32, input_count); for (size_t i = 0; i < input_count; i++) { i_map[i] = ptr2int(map[i]); } - /* Convert witnesses to something more palatable for - * how our generated wires work */ - /* FIXME: remove post EXPERIMENTAL_FEATURE, since witness_stack will be wireable */ - remotetx_ins = tal_arr(tmpctx, struct bitcoin_tx_input *, tal_count(remote_witnesses)); - for (i = 0; i < tal_count(remote_witnesses); i++) { - remotetx_ins[i] = tal(remotetx_ins, struct bitcoin_tx_input); - } - return towire_opening_dual_funding_signed(state, - state->pps, - local_commit, - &their_sig, - funding_tx, - state->funding_txout, - cast_const2( - const struct bitcoin_tx_input **, - remotetx_ins), - i_map, - state->opener_funding, - &state->remoteconf, - &state->their_points.revocation, - &state->their_points.payment, - &state->their_points.htlc, - &state->their_points.delayed_payment, - &state->first_per_commitment_point[REMOTE], - &state->their_funding_pubkey, - state->feerate_per_kw, - state->feerate_per_kw_funding, - state->localconf.channel_reserve, - state->remote_upfront_shutdown_script); + state->pps, + local_commit, + &their_sig, + funding_tx, + state->funding_txout, + opener_change, + remote_witnesses, + i_map, + state->opener_funding, + &state->remoteconf, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.htlc, + &state->their_points.delayed_payment, + &state->first_per_commitment_point[REMOTE], + &state->their_funding_pubkey, + state->feerate_per_kw, + state->feerate_per_kw_funding, + state->localconf.channel_reserve, + state->remote_upfront_shutdown_script); #else return NULL; #endif /* EXPERIMENTAL_FEATURES */ @@ -1841,6 +1831,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) &state->funding_txid, state->funding_txout, state->opener_funding, + AMOUNT_SAT(0), state->push_msat, channel_flags, state->feerate_per_kw, From bd55d30da1626373b2517012eba0998095b45286 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:36:32 -0500 Subject: [PATCH 28/45] hsmd: add method for signing dual funded txs method plus wire calls --- connectd/Makefile | 1 + gossipd/Makefile | 1 + hsmd/Makefile | 1 + hsmd/capabilities.h | 1 + hsmd/hsm_wire.csv | 31 ++++++++++++ hsmd/hsmd.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+) diff --git a/connectd/Makefile b/connectd/Makefile index 7e0b5b39b05e..50217da9c745 100644 --- a/connectd/Makefile +++ b/connectd/Makefile @@ -52,6 +52,7 @@ CONNECTD_COMMON_OBJS := \ common/features.o \ common/gen_status_wire.o \ common/gossip_rcvd_filter.o \ + common/htlc_wire.o \ common/key_derive.o \ common/memleak.o \ common/msg_queue.o \ diff --git a/gossipd/Makefile b/gossipd/Makefile index 6875f1baa1f7..e12053b5f5bd 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -55,6 +55,7 @@ GOSSIPD_COMMON_OBJS := \ common/features.o \ common/gen_status_wire.o \ common/gossip_rcvd_filter.o \ + common/htlc_wire.o \ common/key_derive.o \ common/memleak.o \ common/msg_queue.o \ diff --git a/hsmd/Makefile b/hsmd/Makefile index 9b4c49c25bf4..dab25e5ad206 100644 --- a/hsmd/Makefile +++ b/hsmd/Makefile @@ -22,6 +22,7 @@ HSMD_COMMON_OBJS := \ common/funding_tx.o \ common/gen_status_wire.o \ common/hash_u5.o \ + common/htlc_wire.o \ common/key_derive.o \ common/memleak.o \ common/msg_queue.o \ diff --git a/hsmd/capabilities.h b/hsmd/capabilities.h index 3a306e778a2a..98b8f7a2442e 100644 --- a/hsmd/capabilities.h +++ b/hsmd/capabilities.h @@ -7,6 +7,7 @@ #define HSM_CAP_COMMITMENT_POINT 8 #define HSM_CAP_SIGN_REMOTE_TX 16 #define HSM_CAP_SIGN_CLOSING_TX 32 +#define HSM_CAP_SIGN_ACCEPTER_FUNDING_TX 64 #define HSM_CAP_MASTER 1024 #endif /* LIGHTNING_HSMD_CAPABILITIES_H */ diff --git a/hsmd/hsm_wire.csv b/hsmd/hsm_wire.csv index 4d6de1915970..de49b8a12ef4 100644 --- a/hsmd/hsm_wire.csv +++ b/hsmd/hsm_wire.csv @@ -57,6 +57,37 @@ msgdata,hsm_sign_funding,inputs,utxo,num_inputs msgtype,hsm_sign_funding_reply,104 msgdata,hsm_sign_funding_reply,tx,bitcoin_tx, +# Return witness stack for a funding tx. +msgtype,hsm_dual_funding_sigs,40 +#if EXPERIMENTAL_FEATURES +#include +#include +#include +#include +msgdata,hsm_dual_funding_sigs,num_utxos,u16, +msgdata,hsm_dual_funding_sigs,our_utxos,utxo,num_utxos +msgdata,hsm_dual_funding_sigs,feerate_kw_funding,u32, +msgdata,hsm_dual_funding_sigs,opener_funding,amount_sat, +msgdata,hsm_dual_funding_sigs,accepter_funding,amount_sat, +msgdata,hsm_dual_funding_sigs,num_opener_inputs,u16, +msgdata,hsm_dual_funding_sigs,opener_inputs,input_info,num_opener_inputs +msgdata,hsm_dual_funding_sigs,num_accepter_inputs,u16, +msgdata,hsm_dual_funding_sigs,accepter_inputs,input_info,num_accepter_inputs +msgdata,hsm_dual_funding_sigs,num_opener_outputs,u16, +msgdata,hsm_dual_funding_sigs,opener_outputs,output_info,num_opener_outputs +msgdata,hsm_dual_funding_sigs,num_accepter_outputs,u16, +msgdata,hsm_dual_funding_sigs,accepter_outputs,output_info,num_accepter_outputs +msgdata,hsm_dual_funding_sigs,our_pubkey,pubkey, +msgdata,hsm_dual_funding_sigs,their_pubkey,pubkey, +msgdata,hsm_dual_funding_sigs,opener,enum side, + +msgtype,hsm_dual_funding_sigs_reply,42 +#if EXPERIMENTAL_FEATURES +msgdata,hsm_dual_funding_sigs_reply,stack_height,u16, +msgdata,hsm_dual_funding_sigs_reply,witnesses,witness_stack,stack_height +msgdata,hsm_dual_funding_sigs_reply,tx,bitcoin_tx, + + # Master asks the HSM to sign a node_announcement msgtype,hsm_node_announcement_sig_req,6 msgdata,hsm_node_announcement_sig_req,annlen,u16, diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 98fea71127b7..d5ed0bd1a247 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -1622,6 +1622,112 @@ static void sign_our_inputs(struct bitcoin_tx *tx, struct utxo **utxos, } } +#if EXPERIMENTAL_FEATURES +static struct io_plan *handle_sign_dual_funding_tx(struct io_conn *conn, + struct client *c, + const u8 *msg_in) +{ + size_t i = 0, j; + struct bitcoin_tx *tx; + u32 feerate_kw_funding, offset; + struct pubkey local_pubkey, remote_pubkey; + struct amount_sat opener_funding, accepter_funding; + struct input_info **opener_inputs, **accepter_inputs; + struct output_info **opener_outputs, **accepter_outputs; + struct utxo **our_utxos; + struct amount_sat total_funding, opener_change; + enum side opener; + struct witness_stack **stacks; + + if (!fromwire_hsm_dual_funding_sigs(tmpctx, + msg_in, + &our_utxos, + &feerate_kw_funding, + &opener_funding, + &accepter_funding, + &opener_inputs, + &accepter_inputs, + &opener_outputs, + &accepter_outputs, + &local_pubkey, + &remote_pubkey, + &opener)) + + return bad_req(conn, c, msg_in); + + size_t input_count = tal_count(opener_inputs) + + tal_count(accepter_inputs); + + const void *map[input_count]; + for (i = 0; i < input_count; i++) + map[i] = int2ptr(i); + + tx = dual_funding_funding_tx(tmpctx, + c->chainparams, + NULL, + feerate_kw_funding, + &opener_funding, + accepter_funding, + opener_inputs, accepter_inputs, + opener_outputs, accepter_outputs, + &local_pubkey, + &remote_pubkey, + &total_funding, + &opener_change, + (const void **)&map); + + if (!tx) + return bad_req_fmt(conn, c, msg_in, + "Unable to create valid funding tx."); + + /* For the input_map, the opener_inputs are added before the accepter's */ + offset = opener == LOCAL ? 0 : tal_count(opener_inputs); + + stacks = tal_arr(tmpctx, struct witness_stack *, tal_count(our_utxos)); + for (i = 0; i < tal_count(our_utxos); i++) { + struct bitcoin_signature sig; + struct pubkey inkey; + size_t input_index = -1; + struct witness_stack *stack; + u8 **witnesses; + + stack = tal(stacks, struct witness_stack); + for (j = 0; j < input_count; j++) { + if (ptr2int(map[j]) == i + offset) { + input_index = j; + break; + } + } + + if (input_index == -1) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Unable to find index for input"); + + sign_input(tx, our_utxos[i], &inkey, &sig, input_index); + witnesses = + bitcoin_witness_p2wpkh(tmpctx, &sig, &inkey); + + stack->witness_element = + tal_arr(stack, struct witness_element *, tal_count(witnesses)); + + for (j = 0; j < tal_count(witnesses); j++) { + stack->witness_element[j] = + tal(stack->witness_element, struct witness_element); + stack->witness_element[j]->witness = + tal_steal(stack->witness_element[j], witnesses[j]); + } + + stacks[i] = stack; + tal_free(witnesses); + } + + return req_reply(conn, c, take( + towire_hsm_dual_funding_sigs_reply(tmpctx, + cast_const2(const struct witness_stack **, stacks), + cast_const(const struct bitcoin_tx *, tx)))); +} +#endif /* EXPERIMENTAL_FEATURES */ + /*~ lightningd asks us to sign the transaction to fund a channel; it feeds us * the set of inputs and the local and remote pubkeys, and we sign it. */ static struct io_plan *handle_sign_funding_tx(struct io_conn *conn, @@ -1894,6 +2000,13 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_SIGN_MUTUAL_CLOSE_TX: return (client->capabilities & HSM_CAP_SIGN_CLOSING_TX) != 0; + case WIRE_HSM_DUAL_FUNDING_SIGS: +#if EXPERIMENTAL_FEATURES + return (client->capabilities & HSM_CAP_SIGN_ACCEPTER_FUNDING_TX) != 0; +#else + return false; +#endif /* EXPERIMENTAL_FEATURES */ + case WIRE_HSM_INIT: case WIRE_HSM_CLIENT_HSMFD: case WIRE_HSM_SIGN_FUNDING: @@ -1912,6 +2025,7 @@ static bool check_client_capabilities(struct client *client, case WIRE_HSM_CUPDATE_SIG_REPLY: case WIRE_HSM_CLIENT_HSMFD_REPLY: case WIRE_HSM_SIGN_FUNDING_REPLY: + case WIRE_HSM_DUAL_FUNDING_SIGS_REPLY: case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_SIGN_WITHDRAWAL_REPLY: case WIRE_HSM_SIGN_INVOICE_REPLY: @@ -1964,6 +2078,12 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSM_SIGN_FUNDING: return handle_sign_funding_tx(conn, c, c->msg_in); + case WIRE_HSM_DUAL_FUNDING_SIGS: +#if EXPERIMENTAL_FEATURES + return handle_sign_dual_funding_tx(conn, c, c->msg_in); +#else + return NULL; +#endif /* EXPERIMENTAL_FEATURES */ case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REQ: return handle_sign_node_announcement(conn, c, c->msg_in); @@ -2014,6 +2134,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSM_CUPDATE_SIG_REPLY: case WIRE_HSM_CLIENT_HSMFD_REPLY: case WIRE_HSM_SIGN_FUNDING_REPLY: + case WIRE_HSM_DUAL_FUNDING_SIGS_REPLY: case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY: case WIRE_HSM_SIGN_WITHDRAWAL_REPLY: case WIRE_HSM_SIGN_INVOICE_REPLY: From b77615891461b3fad65e90f462f7bbe2f57894d8 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:40:09 -0500 Subject: [PATCH 29/45] hsmd: allow openingd to call hsm to sign dual-funded tx Allow openingd to call hmsd for dual_funding tx's (accepter flow) --- lightningd/opening_control.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 7ab0c6b7b13f..80bad78b9745 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1150,7 +1150,8 @@ void peer_start_openingd(struct peer *peer, hsmfd = hsm_get_client_fd(peer->ld, &uc->peer->id, uc->dbid, HSM_CAP_COMMITMENT_POINT - | HSM_CAP_SIGN_REMOTE_TX); + | HSM_CAP_SIGN_REMOTE_TX + | HSM_CAP_SIGN_ACCEPTER_FUNDING_TX); uc->openingd = new_channel_subd(peer->ld, "lightning_openingd", From c6874abe23d09d621ab2f994a007e96406bad183 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:47:42 -0500 Subject: [PATCH 30/45] wallet: method to compute available funds for df When we're the accepter, we need to be able to tell a plugin hook what the total available sats we have for an open channel offer. This new wallet method will calculate the total amount of sats we have available, based on our top X highest valued utxos. --- wallet/wallet.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ wallet/wallet.h | 11 +++++++ 2 files changed, 88 insertions(+) diff --git a/wallet/wallet.c b/wallet/wallet.c index d3a9a9fd98e7..437fae08697a 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -533,6 +533,63 @@ const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, return utxo; } +/* Select highest value, confirmed, UTXOs. Optionally limit number to return */ +static struct utxo **sorted_confirmed_utxos(const tal_t *ctx, struct wallet *w, + const enum output_status state) +{ + struct utxo **results; + int i; + struct db_stmt *stmt; + + if (state == output_state_any) + stmt = db_prepare_v2(w->db, SQL("SELECT" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", confirmation_height" + ", spend_height" + ", scriptpubkey " + " FROM outputs" + " WHERE confirmation_height IS NOT NULL" + " ORDER BY value DESC")); + else { + stmt = db_prepare_v2(w->db, SQL("SELECT" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", confirmation_height" + ", spend_height" + ", scriptpubkey " + " FROM outputs" + " WHERE status = ?" + " AND confirmation_height IS NOT NULL" + " ORDER BY value DESC")); + db_bind_int(stmt, 0, output_status_in_db(state)); + } + db_query_prepared(stmt); + + results = tal_arr(ctx, struct utxo *, 0); + for (i = 0; db_step(stmt); i++) { + struct utxo *u = wallet_stmt2output(results, stmt); + tal_arr_expand(&results, u); + } + tal_free(stmt); + + return results; +} + u8 *derive_redeem_scriptsig(const tal_t *ctx, struct wallet *w, u32 keyindex) { struct ext_key ext; @@ -549,6 +606,26 @@ u8 *derive_redeem_scriptsig(const tal_t *ctx, struct wallet *w, u32 keyindex) return bitcoin_scriptsig_p2sh_p2wpkh(ctx, &key); } +void wallet_compute_max(struct wallet *w, u32 max_utxos, struct amount_sat *sat) +{ + size_t i = 0; + struct utxo **available; + + available = sorted_confirmed_utxos(NULL, w, output_state_available); + + *sat = AMOUNT_SAT(0); + for (i = 0; i < tal_count(available) && i < max_utxos; i++) { + if (!amount_sat_add(sat, *sat, available[i]->amount)) + fatal("Overflow in sum of available satoshis %zu/%zu %s + %s", + i, tal_count(available), + type_to_string(tmpctx, struct amount_sat, + sat), + type_to_string(tmpctx, struct amount_sat, + &available[i]->amount)); + } + tal_free(available); +} + bool wallet_can_spend(struct wallet *w, const u8 *script, u32 *index, bool *output_is_p2sh) { diff --git a/wallet/wallet.h b/wallet/wallet.h index b9ac8c7db15a..7deddc4ff35b 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -395,6 +395,17 @@ const struct utxo **wallet_select_all(const tal_t *ctx, struct wallet *w, */ u8 *derive_redeem_scriptsig(const tal_t *ctx, struct wallet *w, u32 keyindex); +/* wallet_compute_max - Compute the maxiumum amount of available sats in our largest + * {max_utxos} utxos + * + * Note that only calculates using the set of utxos that are currently available. + * + * @w - wallet, available utxos + * @max_utxos - limit to number of utxos to sum, ranked by largest + * @sat - (out) sum of {max_utxos} amounts + * */ +void wallet_compute_max(struct wallet *w, u32 max_utxos, struct amount_sat *sat); + /** * wallet_select_specific - Select utxos given an array of txids and an array of outputs index * From 83becfc742e9a962010900ab864f2dffb494af5c Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:50:51 -0500 Subject: [PATCH 31/45] fundchannel: update to work with dual funding Update fundchannel to correctly update the txid for txsend and to know whether or not we're using v2 (needed for knowing whether or not to use the zero_output flag) --- plugins/fundchannel.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/fundchannel.c b/plugins/fundchannel.c index f4a8393cbd4d..ef086b05b42a 100644 --- a/plugins/fundchannel.c +++ b/plugins/fundchannel.c @@ -140,6 +140,7 @@ static struct command_result *send_tx(struct command *cmd, struct json_out *ret; const jsmntok_t *tok; bool commitments_secured; + char *txid; /* For sanity's sake, let's check that it's secured */ tok = json_get_member(buf, result, "commitments_secured"); @@ -147,9 +148,14 @@ static struct command_result *send_tx(struct command *cmd, /* TODO: better failure path? this should never fail though. */ plugin_err("Commitment not secured."); + /* The txid might be updated, since the peer might have added + * inputs, also */ + txid = json_strdup(cmd, buf, json_get_member(buf, result, "txid")); + if (!bitcoin_txid_from_hex(txid, strlen(txid), &fr->tx_id)) + plugin_err("Unable to parse reserved txid %s", txid); + /* Stash the channel_id so we can return it when finalized */ - tok = json_get_member(buf, result, "channel_id"); - fr->chanstr = json_strdup(fr, buf, tok); + fr->chanstr = json_strdup(fr, buf, json_get_member(buf, result, "channel_id")); ret = json_out_new(NULL); json_out_start(ret, NULL, '{'); @@ -298,6 +304,10 @@ static struct command_result *fundchannel_start_done(struct command *cmd, fr->funding_addr = json_strdup(cmd, buf, json_get_member(buf, result, "funding_address")); + /* Is this a v2 request? */ + fr->is_v2 = json_tok_streq(buf, + json_get_member(buf, result, "open_channel_version"), "2"); + /* Now that we're ready to go, cancel the reserved tx */ ret = json_out_new(NULL); json_out_start(ret, NULL, '{'); From a35d298d6b8949d9583ebbe6c81d3dae051b0001 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 17:53:03 -0500 Subject: [PATCH 32/45] listpeers: show funding_allocation for df'd channels Calculate the correct funding amounts to display for dual funded channels. --- lightningd/peer_control.c | 40 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index f91a69436a63..827b11ecb821 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -601,6 +601,7 @@ static void json_add_channel(struct lightningd *ld, struct channel_id cid; struct channel_stats channel_stats; struct amount_msat spendable, funding_msat; + struct amount_sat remote_funds; struct peer *p = channel->peer; json_object_start(response, key); @@ -630,36 +631,23 @@ static void json_add_channel(struct lightningd *ld, response, "private", !(channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)); - // FIXME @conscott : Modify this when dual-funded channels - // are implemented + /* Calculate remote peer's funding contribution */ + assert(amount_sat_sub(&remote_funds, + channel->funding, channel->our_funds)); + /* Add funding amounts, raw msat */ json_object_start(response, "funding_allocation_msat"); - if (channel->opener == LOCAL) { - json_add_u64(response, node_id_to_hexstr(tmpctx, &p->id), 0); - json_add_u64(response, node_id_to_hexstr(tmpctx, &ld->id), - channel->funding.satoshis * 1000); /* Raw: raw JSON field */ - } else { - json_add_u64(response, node_id_to_hexstr(tmpctx, &ld->id), 0); - json_add_u64(response, node_id_to_hexstr(tmpctx, &p->id), - channel->funding.satoshis * 1000); /* Raw: raw JSON field */ - } + json_add_u64(response, node_id_to_hexstr(tmpctx, &p->id), + remote_funds.satoshis * 1000); /* Raw: raw JSON field */ + json_add_u64(response, node_id_to_hexstr(tmpctx, &ld->id), + channel->our_funds.satoshis * 1000); /* Raw: raw JSON field */ json_object_end(response); + /* Add funding amounts, 'msat' style */ json_object_start(response, "funding_msat"); - if (channel->opener == LOCAL) { - json_add_sat_only(response, - node_id_to_hexstr(tmpctx, &p->id), - AMOUNT_SAT(0)); - json_add_sat_only(response, - node_id_to_hexstr(tmpctx, &ld->id), - channel->funding); - } else { - json_add_sat_only(response, - node_id_to_hexstr(tmpctx, &ld->id), - AMOUNT_SAT(0)); - json_add_sat_only(response, - node_id_to_hexstr(tmpctx, &p->id), - channel->funding); - } + json_add_sat_only(response, node_id_to_hexstr(tmpctx, &p->id), + remote_funds); + json_add_sat_only(response, node_id_to_hexstr(tmpctx, &ld->id), + channel->our_funds); json_object_end(response); if (!amount_sat_to_msat(&funding_msat, channel->funding)) { From cb4f0bcc494ab9291b4cf5f21cc7265c07d3aeee Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 18:13:32 -0500 Subject: [PATCH 33/45] df-accepter: pass v2 info back to opening_control Send info that we need for doing the right thing in the openchannel plugin back to opening_control --- lightningd/opening_control.c | 5 +++++ openingd/opening_wire.csv | 2 ++ openingd/openingd.c | 2 ++ 3 files changed, 9 insertions(+) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 80bad78b9745..c1e3813b776d 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -924,12 +924,15 @@ static void channel_config(struct lightningd *ld, struct openchannel_hook_payload { struct subd *openingd; struct amount_sat funding_satoshis; + /* Is this a v2 openchannel call? */ + bool is_v2; struct amount_msat push_msat; struct amount_sat dust_limit_satoshis; struct amount_msat max_htlc_value_in_flight_msat; struct amount_sat channel_reserve_satoshis; struct amount_msat htlc_minimum_msat; u32 feerate_per_kw; + u32 feerate_per_kw_funding; u16 to_self_delay; u16 max_accepted_htlcs; u8 channel_flags; @@ -1039,6 +1042,7 @@ static void opening_got_offer(struct subd *openingd, payload = tal(openingd->ld, struct openchannel_hook_payload); payload->openingd = openingd; if (!fromwire_opening_got_offer(payload, msg, + &payload->is_v2, &payload->funding_satoshis, &payload->push_msat, &payload->dust_limit_satoshis, @@ -1046,6 +1050,7 @@ static void opening_got_offer(struct subd *openingd, &payload->channel_reserve_satoshis, &payload->htlc_minimum_msat, &payload->feerate_per_kw, + &payload->feerate_per_kw_funding, &payload->to_self_delay, &payload->max_accepted_htlcs, &payload->channel_flags, diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index 6d4a58f9342e..c986320ac0fb 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -28,6 +28,7 @@ msgdata,opening_init,dev_fast_gossip,bool, # Openingd->master: they offered channel, should we continue? msgtype,opening_got_offer,6005 +msgdata,opening_got_offer,is_v2,bool, msgdata,opening_got_offer,funding_satoshis,amount_sat, msgdata,opening_got_offer,push_msat,amount_msat, msgdata,opening_got_offer,dust_limit_satoshis,amount_sat, @@ -35,6 +36,7 @@ msgdata,opening_got_offer,max_htlc_value_in_flight_msat,amount_msat, msgdata,opening_got_offer,channel_reserve_satoshis,amount_sat, msgdata,opening_got_offer,htlc_minimum_msat,amount_msat, msgdata,opening_got_offer,feerate_per_kw,u32, +msgdata,opening_got_offer,feerate_per_kw_funding,u32, msgdata,opening_got_offer,to_self_delay,u16, msgdata,opening_got_offer,max_accepted_htlcs,u16, msgdata,opening_got_offer,channel_flags,u8, diff --git a/openingd/openingd.c b/openingd/openingd.c index 44394a910ebe..f4eaadb8e998 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -1626,6 +1626,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) /* Check with lightningd that we can accept this? In particular, * if we have an existing channel, we don't support it. */ msg = towire_opening_got_offer(NULL, + state->use_v2, state->opener_funding, state->push_msat, state->remoteconf.dust_limit, @@ -1633,6 +1634,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) state->remoteconf.channel_reserve, state->remoteconf.htlc_minimum, state->feerate_per_kw, + state->feerate_per_kw, state->remoteconf.to_self_delay, state->remoteconf.max_accepted_htlcs, channel_flags, From 37b6fe1937b842daae7925c162fae857d9203f33 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 18:17:06 -0500 Subject: [PATCH 34/45] df-accepter: if payload is v2, calculate available funds --- lightningd/opening_control.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index c1e3813b776d..ac938e4a7c06 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,10 @@ struct uncommitted_channel { /* If we offered channel, this contains information, otherwise NULL */ struct funding_channel *fc; + /* If this is dual funded and we're the accepter, + * this contains information, otherwise NULL */ + struct peer_funding *pf; + /* Our basepoints for the channel. */ struct basepoints local_basepoints; @@ -96,9 +101,19 @@ struct funding_channel { /* Whether or not to use channel open v2 */ bool is_v2; + + /* Transaction we're building for a v2 channel open */ struct unreleased_tx *utx; }; +struct peer_funding { + struct utxo **utxos; + struct amount_sat accepter_funding; + + /* Channel, subsequent owner of us */ + struct uncommitted_channel *uc; +}; + static void uncommitted_channel_disconnect(struct uncommitted_channel *uc, const char *desc) { @@ -931,6 +946,7 @@ struct openchannel_hook_payload { struct amount_msat max_htlc_value_in_flight_msat; struct amount_sat channel_reserve_satoshis; struct amount_msat htlc_minimum_msat; + struct amount_sat available_funds; u32 feerate_per_kw; u32 feerate_per_kw_funding; u16 to_self_delay; @@ -1061,6 +1077,17 @@ static void opening_got_offer(struct subd *openingd, return; } + if (payload->is_v2) { + uc->pf = tal(uc, struct peer_funding); + /* Calculate the max we can contribute to this channel */ + /* We use one less than the contribution count limit + * to leave room for a change output */ + wallet_compute_max(openingd->ld->wallet, + /* Leave space for change */ + REMOTE_CONTRIB_LIMIT - 1, + &payload->available_funds); + } + tal_add_destructor2(openingd, openchannel_payload_remove_openingd, payload); plugin_hook_call_openchannel(openingd->ld, payload, payload); } From df57686fd3a41f97f14523b57766d8eb713a663a Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 18:18:23 -0500 Subject: [PATCH 35/45] fundchannel_start: include version of open protocol --- CHANGELOG.md | 2 ++ lightningd/opening_control.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10bc97e58c8d..051f7f84dc54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - JSON API: `txprepare` and `withdraw` now accept an optional parameter `utxos`, a list of utxos to include in the prepared transaction - JSON_API: `close` now accepts an optional parameter `destination`, to which the to-local output will be sent. - JSON API: `txprepare` includes a parameter `zero_out_change`, which if true leaves the change value as zero. Useful for designating change output for dual-funded transactions. Defaults to false. +- JSON API: `fundchannel_start` now includes `open_channel_version`, a string which indicates +the protocol version used to open the channel. - bolt11: support for parsing feature bits (field `9`). diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index ac938e4a7c06..98b1d767c448 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -344,6 +344,8 @@ static void funding_started_success(struct funding_channel *fc, json_add_hex_talarr(response, "scriptpubkey", scriptPubkey); } + json_add_string(response, "open_channel_version", fc->is_v2 ? "2" : "1"); + /* Clear this so cancel doesn't think it's still in progress */ fc->cmd = NULL; was_pending(command_success(cmd, response)); From b5f4c789cbb92b7367cbbf9c61e3600092494493 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 18:28:02 -0500 Subject: [PATCH 36/45] df-accepter: accepter logic Implements accepter side of df --- channeld/channeld.c | 10 +- lightningd/channel_control.c | 4 +- lightningd/opening_control.c | 152 +++++++++- openingd/opening_wire.csv | 8 + openingd/openingd.c | 563 +++++++++++++++++++++++++++++++---- 5 files changed, 652 insertions(+), 85 deletions(-) diff --git a/channeld/channeld.c b/channeld/channeld.c index 952474d9581c..ab3ca85daa4e 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2944,7 +2944,7 @@ static void init_channel(struct peer *peer) enum side *failed_sides; struct added_htlc *htlcs; bool reconnected; - u8 *funding_signed; + u8 *sigs_msg; const u8 *msg; u32 feerate_per_kw[NUM_SIDES]; u32 minimum_depth, failheight; @@ -3004,7 +3004,7 @@ static void init_channel(struct peer *peer) &peer->shutdown_sent[REMOTE], &peer->final_scriptpubkey, &peer->channel_flags, - &funding_signed, + &sigs_msg, &peer->announce_depth_reached, &last_remote_per_commit_secret, &peer->localfeatures, @@ -3111,9 +3111,9 @@ static void init_channel(struct peer *peer) if (reconnected) peer_reconnect(peer, &last_remote_per_commit_secret); - /* If we have a funding_signed message, send that immediately */ - if (funding_signed) - sync_crypto_write(peer->pps, take(funding_signed)); + /* If we have a final sigs message, send that immediately */ + if (sigs_msg) + sync_crypto_write(peer->pps, take(sigs_msg)); /* Reenable channel */ channel_announcement_negotiate(peer); diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 119790779fce..2434b9e061ed 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -324,7 +324,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) void peer_start_channeld(struct channel *channel, struct per_peer_state *pps, - const u8 *funding_signed, + const u8 *sigs_msg, bool reconnected) { u8 *initmsg; @@ -468,7 +468,7 @@ void peer_start_channeld(struct channel *channel, channel->shutdown_scriptpubkey[REMOTE] != NULL, channel->shutdown_scriptpubkey[LOCAL], channel->channel_flags, - funding_signed, + sigs_msg, reached_announce_depth, &last_remote_per_commit_secret, channel->peer->localfeatures, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 98b1d767c448..0f9bf59ebb2b 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1,12 +1,14 @@ #include "bitcoin/feerate.h" #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -679,20 +681,23 @@ static void opening_fundee_finished(struct subd *openingd, const int *fds, struct uncommitted_channel *uc) { - u8 *funding_signed; + u8 *final_peer_msg; struct channel_info channel_info; struct bitcoin_signature remote_commit_sig; struct bitcoin_tx *remote_commit; struct lightningd *ld = openingd->ld; struct bitcoin_txid funding_txid; u16 funding_outnum; - struct amount_sat funding; + struct amount_sat opener_funding; + struct amount_sat accepter_funding; + struct amount_sat total_funding; struct amount_msat push; u32 feerate; u8 channel_flags; struct channel *channel; u8 *remote_upfront_shutdown_script; struct per_peer_state *pps; + struct utxo **utxos; log_debug(uc->log, "Got opening_fundee_finish_response"); @@ -712,12 +717,12 @@ static void opening_fundee_finished(struct subd *openingd, &channel_info.remote_fundingkey, &funding_txid, &funding_outnum, - &funding, - &AMOUNT_SAT(0), + &opener_funding, + &accepter_funding, &push, &channel_flags, &feerate, - &funding_signed, + &final_peer_msg, &uc->our_config.channel_reserve, &remote_upfront_shutdown_script)) { log_broken(uc->log, "bad OPENING_FUNDEE_REPLY %s", @@ -736,14 +741,23 @@ static void opening_fundee_finished(struct subd *openingd, goto failed; } + if (!amount_sat_add(&total_funding, opener_funding, accepter_funding)) + abort(); + + if (uc->pf) + /* We steal here, because otherwise gets eaten below */ + utxos = tal_steal(tmpctx, uc->pf->utxos); + else + utxos = NULL; + /* Consumes uc */ channel = wallet_commit_channel(ld, uc, remote_commit, &remote_commit_sig, &funding_txid, funding_outnum, - funding, - AMOUNT_SAT(0), + total_funding, + accepter_funding, push, REMOTE, channel_flags, @@ -759,6 +773,11 @@ static void opening_fundee_finished(struct subd *openingd, type_to_string(reply, struct bitcoin_txid, &channel->funding_txid)); + if (utxos) { + // TODO: mark utxos as shared + tal_free(utxos); + } + channel_watch_funding(ld, channel); /* Tell plugins about the success */ @@ -766,7 +785,7 @@ static void opening_fundee_finished(struct subd *openingd, &channel->funding_txid, &channel->remote_funding_locked); /* On to normal operation! */ - peer_start_channeld(channel, pps, funding_signed, false); + peer_start_channeld(channel, pps, final_peer_msg, false); subd_release_channel(openingd, uc); uc->openingd = NULL; @@ -778,6 +797,7 @@ static void opening_fundee_finished(struct subd *openingd, close(fds[1]); close(fds[3]); tal_free(uc); + tal_free(utxos); } static void opening_funder_failed(struct subd *openingd, const u8 *msg, @@ -940,9 +960,9 @@ static void channel_config(struct lightningd *ld, struct openchannel_hook_payload { struct subd *openingd; - struct amount_sat funding_satoshis; /* Is this a v2 openchannel call? */ bool is_v2; + struct amount_sat opener_satoshis; struct amount_msat push_msat; struct amount_sat dust_limit_satoshis; struct amount_msat max_htlc_value_in_flight_msat; @@ -965,7 +985,7 @@ openchannel_hook_serialize(struct openchannel_hook_payload *payload, json_object_start(stream, "openchannel"); json_add_node_id(stream, "id", &uc->peer->id); json_add_amount_sat_only(stream, "funding_satoshis", - payload->funding_satoshis); + payload->opener_satoshis); json_add_amount_msat_only(stream, "push_msat", payload->push_msat); json_add_amount_sat_only(stream, "dust_limit_satoshis", payload->dust_limit_satoshis); @@ -994,11 +1014,16 @@ static void openchannel_payload_remove_openingd(struct subd *openingd, } static void openchannel_hook_cb(struct openchannel_hook_payload *payload, - const char *buffer, - const jsmntok_t *toks) + const char *buffer, + const jsmntok_t *toks) { struct subd *openingd = payload->openingd; + struct uncommitted_channel *uc = openingd->channel; + struct peer_funding *pf = uc->pf; const char *errmsg = NULL; + struct amount_sat change; + struct bitcoin_tx_output **outputs; + bool has_change; /* We want to free this, whatever happens. */ tal_steal(tmpctx, payload); @@ -1009,6 +1034,7 @@ static void openchannel_hook_cb(struct openchannel_hook_payload *payload, tal_del_destructor2(openingd, openchannel_payload_remove_openingd, payload); + pf->accepter_funding = AMOUNT_SAT(0); /* If we had a hook, check what it says */ if (buffer) { const jsmntok_t *t = json_get_member(buffer, toks, "result"); @@ -1031,10 +1057,107 @@ static void openchannel_hook_cb(struct openchannel_hook_payload *payload, fatal("Plugin returned an invalid result for the " "openchannel hook: %.*s", t->end - t->start, buffer + t->start); + + if (payload->is_v2 && !errmsg) { + const jsmntok_t *funding_sats = json_get_member(buffer, + toks, + "funding_sats"); + if (funding_sats) + json_to_sat(buffer, funding_sats, &pf->accepter_funding); + } + } + + if (!payload->is_v2 || errmsg) { + subd_send_msg(openingd, + take(towire_opening_got_offer_reply(NULL, errmsg))); + return; + } + + /* Find utxos for funding this */ + if (amount_sat_greater(pf->accepter_funding, AMOUNT_SAT(0))) { + /* Print a warning if we're trying to fund a channel with more + * than we said that we'd be allowed to */ + if (amount_sat_greater(pf->accepter_funding, payload->available_funds)) + log_info(openingd->log, + "Attempting to fund channel for %s when max was set to %s", + type_to_string( + tmpctx, struct amount_sat, &pf->accepter_funding), + type_to_string( + tmpctx, struct amount_sat, &payload->available_funds)); + + struct amount_sat fee_estimate UNUSED; + pf->utxos = (struct utxo **)wallet_select_coins(pf, openingd->ld->wallet, + true, pf->accepter_funding, + 0, 0, + UINT32_MAX, /* minconf 1 */ + &fee_estimate, &change); + + /* Verify that we're still under the max remote that is allowed */ + if (tal_count(pf->utxos) > REMOTE_CONTRIB_LIMIT) { + log_info(openingd->log, + "Too many utxos selected (%ld), only %"PRIu16" allowed", + tal_count(pf->utxos), REMOTE_CONTRIB_LIMIT - 1); + pf->utxos = tal_free(pf->utxos); + change = AMOUNT_SAT(0); + } + } else { + change = AMOUNT_SAT(0); + pf->utxos = NULL; + } + + /* Either no utxos were found, or we weren't funding it anyway */ + if (!pf->utxos) { + if (amount_sat_greater(pf->accepter_funding, AMOUNT_SAT(0))) + /* FIXME: send notification to the plugin that + * we weren't able to fund this channel as they + * requested; utxo set has changed since hook was called */ + log_unusual(openingd->log, + "Unable to fund channel with %s; utxos unavailable", + type_to_string(tmpctx, struct amount_sat, + &pf->accepter_funding)); + + pf->accepter_funding = AMOUNT_SAT(0); + change = AMOUNT_SAT(0); + } + + has_change = amount_sat_greater(change, AMOUNT_SAT(0)); + outputs = tal_arr(tmpctx, struct bitcoin_tx_output *, has_change ? 1 : 0); + if (has_change) { + struct bitcoin_tx_output *output; + struct pubkey *changekey; + s64 change_keyindex; + + output = tal(outputs, struct bitcoin_tx_output); + output->amount = change; + + change_keyindex = wallet_get_newindex(openingd->ld); + changekey = tal(tmpctx, struct pubkey); + if (!bip32_pubkey(openingd->ld->wallet->bip32_base, + changekey, change_keyindex)) { + fatal("Error deriving change key %lu", change_keyindex); + } + output->script = scriptpubkey_p2wpkh(output, changekey); + outputs[0] = output; + } + + /* We need to supply the scriptSig to our peer, for P2SH wrapped inputs */ + for (size_t i = 0; i < tal_count(pf->utxos); i++) { + if (pf->utxos[i]->is_p2sh) + pf->utxos[i]->scriptSig = + derive_redeem_scriptsig(pf->utxos[i], + openingd->ld->wallet, + pf->utxos[i]->keyindex); + else + pf->utxos[i]->scriptSig = NULL; + } subd_send_msg(openingd, - take(towire_opening_got_offer_reply(NULL, errmsg))); + take(towire_opening_got_offer_reply_fund( + NULL, pf->accepter_funding, + cast_const2(const struct utxo **, pf->utxos), + cast_const2(const struct bitcoin_tx_output **, + outputs)))); } REGISTER_PLUGIN_HOOK(openchannel, @@ -1061,7 +1184,7 @@ static void opening_got_offer(struct subd *openingd, payload->openingd = openingd; if (!fromwire_opening_got_offer(payload, msg, &payload->is_v2, - &payload->funding_satoshis, + &payload->opener_satoshis, &payload->push_msat, &payload->dust_limit_satoshis, &payload->max_htlc_value_in_flight_msat, @@ -1157,6 +1280,7 @@ static unsigned int openingd_msg(struct subd *openingd, case WIRE_OPENING_FUNDER_COMPLETE: case WIRE_OPENING_FUNDER_CANCEL: case WIRE_OPENING_GOT_OFFER_REPLY: + case WIRE_OPENING_GOT_OFFER_REPLY_FUND: case WIRE_OPENING_DEV_MEMLEAK: /* Replies never get here */ case WIRE_OPENING_DEV_MEMLEAK_REPLY: diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index c986320ac0fb..073474c58c27 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -46,6 +46,14 @@ msgdata,opening_got_offer,shutdown_scriptpubkey,u8,shutdown_len msgtype,opening_got_offer_reply,6105 msgdata,opening_got_offer_reply,rejection,?wirestring, +# master->openingd: we'd like to fund this too, maybe +msgtype,opening_got_offer_reply_fund,6107 +msgdata,opening_got_offer_reply_fund,our_funding,amount_sat, +msgdata,opening_got_offer_reply_fund,num_inputs,u16, +msgdata,opening_got_offer_reply_fund,utxos,utxo,num_inputs +msgdata,opening_got_offer_reply_fund,num_outputs,u16, +msgdata,opening_got_offer_reply_fund,outputs,bitcoin_tx_output,num_outputs + # Openingd->master: we've successfully offered channel. # This gives their sig, means we can broadcast tx: we're done. msgtype,opening_funder_reply,6101 diff --git a/openingd/openingd.c b/openingd/openingd.c index f4eaadb8e998..f49a1509d268 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -1444,6 +1444,497 @@ static u8 *funder_channel_complete(struct state *state, state->remote_upfront_shutdown_script); } +static bool fundee_check_primitives(struct state *state, + struct bitcoin_blkid chain_hash) +{ + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + * - the `chain_hash` value is set to a hash of a chain + * that is unknown to the receiver. + */ + if (!bitcoin_blkid_eq(&chain_hash, + &state->chainparams->genesis_blockhash)) { + negotiation_failed(state, false, + "Unknown chain-hash %s", + type_to_string(tmpctx, + struct bitcoin_blkid, + &chain_hash)); + return false; + } + + /* BOLT #2 FIXME: + * + * The receiving node ... MUST fail the channel if `funding-satoshis` + * is greater than or equal to 2^24 */ + if (amount_sat_greater(state->opener_funding, state->chainparams->max_funding)) { + negotiation_failed(state, false, + "funding_satoshis %s too large", + type_to_string(tmpctx, struct amount_sat, + &state->opener_funding)); + return false; + } + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + * ... + * - `push_msat` is greater than `funding_satoshis` * 1000. + */ + if (amount_msat_greater_sat(state->push_msat, state->opener_funding)) { + peer_failed(state->pps, + &state->channel_id, + "Their push_msat %s" + " would be too large for funding_satoshis %s", + type_to_string(tmpctx, struct amount_msat, + &state->push_msat), + type_to_string(tmpctx, struct amount_sat, + &state->opener_funding)); + return false; + } + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - it considers `feerate_per_kw` too small for timely processing or + * unreasonably large. + */ + if (state->feerate_per_kw < state->min_feerate) { + negotiation_failed(state, false, + "feerate_per_kw %u below minimum %u", + state->feerate_per_kw, state->min_feerate); + return false; + } + + if (state->feerate_per_kw > state->max_feerate) { + negotiation_failed(state, false, + "feerate_per_kw %u above maximum %u", + state->feerate_per_kw, state->max_feerate); + return false; + } + return true; +} + +#if EXPERIMENTAL_FEATURES +static void inputs_to_infos(const tal_t *ctx, struct utxo **utxos, + struct input_info ***input_infos) +{ + size_t i; + + *input_infos = tal_arr(ctx, struct input_info *, tal_count(utxos)); + for (i = 0; i < tal_count(utxos); i++) { + struct input_info *info; + info = tal(*input_infos, struct input_info); + info->input_satoshis = utxos[i]->amount; + info->prevtx_txid = utxos[i]->txid; + info->prevtx_vout = utxos[i]->outnum; + + info->prevtx_scriptpubkey = tal_dup_arr(info, u8, utxos[i]->scriptPubkey, + tal_bytelen(utxos[i]->scriptPubkey), 0); + + /* All our outputs are sig + key (P2WPKH or P2SH-P2WPKH) */ + info->max_witness_len = 1 + 1 + 73 + 1 + 33; + + /* + * BOLT-1a9a018f5e2fa7239ae25f333c0be1f294f6c5e9 + * `input_info`.`script` is the scriptPubkey data for the input. + * NB: for native SegWit inputs (P2WPKH and P2WSH) inputs, the `script` field + * will be empty. + */ + if (tal_count(utxos[i]->scriptSig)) + info->script = tal_dup_arr(info, u8, utxos[i]->scriptSig, + tal_count(utxos[i]->scriptSig), 0); + else + info->script = NULL; + + (*input_infos)[i] = info; + } +} + +static struct output_info **outputs_to_infos(const tal_t *ctx, struct bitcoin_tx_output **outputs) +{ + struct output_info **infos; + size_t i; + + infos = tal_arr(ctx, struct output_info *, tal_count(outputs)); + for (i = 0; i < tal_count(outputs); i++) { + struct output_info *info; + info = tal(infos, struct output_info); + + info->script = tal_dup_arr(info, u8, outputs[i]->script, + tal_count(outputs[i]->script), 0); + info->output_satoshis = outputs[i]->amount; + infos[i] = info; + } + + return infos; +} + +static u8 *fundee_channel2(struct state *state, const u8 *open_channel2_msg) +{ + struct bitcoin_blkid chain_hash; + struct utxo **utxos; + struct bitcoin_tx_output **outputs; + struct input_info **their_inputs, **our_inputs; + struct output_info **their_outputs, **our_outputs; + + char *err_reason; + struct witness_stack **our_stack; + struct bitcoin_txid hsm_funding_txid; + struct bitcoin_tx *funding_tx; + struct bitcoin_signature their_sig, our_sig; + secp256k1_ecdsa_signature *htlc_sigs; + struct bitcoin_tx *local_commit, *remote_commit; + struct amount_sat total_funding, opener_change; + struct amount_msat local_msat; + struct channel_id id_in; + const u8 *wscript; + u8 channel_flags; + u8 *msg; + + struct tlv_opening_tlvs *tlv = tlv_opening_tlvs_new(tmpctx); + if (!fromwire_open_channel2(open_channel2_msg, + &chain_hash, + &state->channel_id, + &state->opener_funding, + &state->push_msat, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.htlc_minimum, + &state->feerate_per_kw, + &state->feerate_per_kw_funding, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &state->their_funding_pubkey, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.delayed_payment, + &state->their_points.htlc, + &state->first_per_commitment_point[REMOTE], + &channel_flags, + tlv)) + peer_failed(state->pps, NULL, + "Bad open_channel2 %s", + tal_hex(open_channel2_msg, open_channel2_msg)); + + /* Default is no shutdown_scriptpubkey: free any leftover one. */ + state->remote_upfront_shutdown_script + = tal_free(state->remote_upfront_shutdown_script); + + if (tlv->option_upfront_shutdown_script && + tlv->option_upfront_shutdown_script->shutdown_scriptpubkey) + state->remote_upfront_shutdown_script = tal_steal(state, + tlv->option_upfront_shutdown_script->shutdown_scriptpubkey); + + if (!fundee_check_primitives(state, chain_hash)) + return NULL; + + // we do all the reserve checks after we've gotten their amounts + + /* Check with lightningd that we can accept this? In particular, + * if we have an existing channel, we don't support it. */ + msg = towire_opening_got_offer(NULL, + state->use_v2, + state->opener_funding, + state->push_msat, + state->remoteconf.dust_limit, + state->remoteconf.max_htlc_value_in_flight, + AMOUNT_SAT(0), + state->remoteconf.htlc_minimum, + state->feerate_per_kw, + state->feerate_per_kw_funding, + state->remoteconf.to_self_delay, + state->remoteconf.max_accepted_htlcs, + channel_flags, + state->remote_upfront_shutdown_script); + wire_sync_write(REQ_FD, take(msg)); + msg = wire_sync_read(tmpctx, REQ_FD); + + enum opening_wire_type t = fromwire_peektype(msg); + if (t == WIRE_OPENING_GOT_OFFER_REPLY) { + if (!fromwire_opening_got_offer_reply(tmpctx, msg, &err_reason)) + master_badmsg(WIRE_OPENING_GOT_OFFER_REPLY, msg); + + /* We only call this if there's an error to return */ + if (!err_reason) + err_reason = "Unknown error occurred attempting" + " to open channel."; + + u8 *errmsg = towire_errorfmt(NULL, &state->channel_id, + "%s", err_reason); + sync_crypto_write(state->pps, take(errmsg)); + + /* We exit here. Errored in lightningd */ + return NULL; + + } else if (!fromwire_opening_got_offer_reply_fund(state, msg, + &state->accepter_funding, + &utxos, &outputs)) + master_badmsg(WIRE_OPENING_GOT_OFFER_REPLY_FUND, msg); + + /* This reserves 1% of the channel (rounded up) */ + set_reserve(state); + + /* These checks are the same whether we're opener or accepter... */ + if (!check_config_bounds(state, &state->remoteconf, true)) + return NULL; + + // FIXME: handle upfront remotekey + msg = towire_accept_channel2(tmpctx, &state->channel_id, + state->accepter_funding, + state->localconf.dust_limit, + state->localconf.max_htlc_value_in_flight, + state->localconf.htlc_minimum, + state->minimum_depth, + state->localconf.to_self_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, + &state->first_per_commitment_point[LOCAL], + NULL); + + sync_crypto_write(state->pps, take(msg)); + + peer_billboard(false, "Incoming channel: accepted, now " + "waiting for them to send funding_compose"); + + msg = opening_negotiate_msg(tmpctx, state, false); + if (!msg) + return NULL; + + /* Convert our inputs/outputs to the correct format */ + inputs_to_infos(state, utxos, &our_inputs); + our_outputs = outputs_to_infos(state, outputs); + + /* The next message should be "funding_compose" which tells us the funding + * inputs and outputs they've selected. */ + if (!fromwire_funding_compose(state, msg, &id_in, + &their_inputs, + &their_outputs)) + peer_failed(state->pps, + &state->channel_id, + "Parsing received funding_compose"); + + check_channel_id(state, &id_in, &state->channel_id); + + if (!check_remote_input_outputs(state, OPENER, + their_inputs, + their_outputs, + state->opener_funding)) + return NULL; + + /* Build the funding tx */ + funding_tx = dual_funding_funding_tx(state, state->chainparams, + &state->funding_txout, + state->feerate_per_kw_funding, + &state->opener_funding, + state->accepter_funding, + their_inputs, our_inputs, + their_outputs, our_outputs, + &state->our_funding_pubkey, + &state->their_funding_pubkey, + &total_funding, + &opener_change, + NULL); + + if (!funding_tx) + peer_failed(state->pps, + &state->channel_id, + "Opener unable to afford funding transaction"); + + bitcoin_txid(funding_tx, &state->funding_txid); + status_debug("dual funding tx is %s", + type_to_string(tmpctx, struct bitcoin_tx, funding_tx)); + + /* Now we send our inputs/outputs to them */ + msg = towire_funding_compose(tmpctx, &state->channel_id, + cast_const2(const struct input_info **, our_inputs), + cast_const2(const struct output_info **, our_outputs)); + + sync_crypto_write(state->pps, take(msg)); + + peer_billboard(false, "Incoming channel: funding_compose sent," + " now waiting for commitment_signed"); + + msg = opening_negotiate_msg(tmpctx, state, false); + if (!msg) + return NULL; + + their_sig.sighash_type = SIGHASH_ALL; + if (!fromwire_commitment_signed(tmpctx, msg, + &id_in, &their_sig.s, &htlc_sigs)) + peer_failed(state->pps, + &state->channel_id, + "Bad commitment_signed %s", tal_hex(msg, msg)); + + peer_billboard(false, "Incoming channel: commitment_signed received," + " composing funding tx"); + + if (!amount_msat_add_sat(&local_msat, state->push_msat, + state->accepter_funding)) + peer_failed(state->pps, + &state->channel_id, + "Overflow adding our funding %s with push_msat %s", + type_to_string(tmpctx, struct amount_sat, + &state->accepter_funding), + type_to_string(tmpctx, struct amount_msat, + &state->push_msat)); + + bool we_funded = !amount_sat_eq(state->accepter_funding, AMOUNT_SAT(0)); + state->channel = new_initial_channel(state, + &chain_hash, + &state->funding_txid, + state->funding_txout, + state->minimum_depth, + total_funding, + local_msat, + state->feerate_per_kw, + &state->localconf, + &state->remoteconf, + &state->our_points, + &state->their_points, + &state->our_funding_pubkey, + &state->their_funding_pubkey, + state->option_static_remotekey, + we_funded, + REMOTE); + + /* We don't expect this to fail, but it does do some additional + * internal sanity checks. */ + if (!state->channel) + peer_failed(state->pps, + &state->channel_id, + "We could not create channel with given config"); + + if (tal_count(htlc_sigs)) + peer_failed(state->pps, + &state->channel_id, + "Peer sent HTLCs with initial commitment signed msg"); + + /* We expect to have switched over to using the funding_tx + * derived channel_id as of now */ + derive_channel_id(&state->channel_id, + &state->funding_txid, state->funding_txout); + + /* If this check fails, we know that they've derived a different funding + * tx than we have */ + check_channel_id(state, &id_in, &state->channel_id); + + /* We create *our* initial commitment transaction, and check the + * signature they sent against that. */ + local_commit = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[LOCAL], + LOCAL, &err_reason); + + if (!local_commit) { + negotiation_failed(state, false, + "Could not meet our fees and reserve: %s", err_reason); + return NULL; + } + + if (!check_tx_sig(local_commit, 0, NULL, wscript, &state->their_funding_pubkey, &their_sig)) + peer_failed(state->pps, + &state->channel_id, + "Bad signature %s on tx %s using key %s", + type_to_string(tmpctx, struct bitcoin_signature, + &their_sig), + type_to_string(tmpctx, struct bitcoin_tx, local_commit), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey)); + + /* Now we generate our commitment sig for them */ + remote_commit = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[REMOTE], + REMOTE, &err_reason); + + if (!remote_commit) { + negotiation_failed(state, true, + "Could not meet their fees and reserve: %s", err_reason); + } + + msg = towire_hsm_sign_remote_commitment_tx(NULL, + remote_commit, + &state->channel->funding_pubkey[REMOTE], + state->channel->funding); + + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsm_sign_tx_reply(msg, &our_sig)) + status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", + tal_hex(tmpctx, msg)); + + /* We generate our witnesses for the funding tx */ + /* FIXME: update with BOLT ref when included + * - MUST set `witness` to the serialized witness data for each of its + * inputs, in funding transaction order. FIXME: link to funding tx order + */ + msg = towire_hsm_dual_funding_sigs(tmpctx, + cast_const2(const struct utxo **, utxos), + state->feerate_per_kw_funding, + state->opener_funding, + state->accepter_funding, + cast_const2(const struct input_info **, their_inputs), + cast_const2(const struct input_info **, our_inputs), + cast_const2(const struct output_info **, their_outputs), + cast_const2(const struct output_info **, our_outputs), + &state->our_funding_pubkey, + &state->their_funding_pubkey, + REMOTE); + + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsm_dual_funding_sigs_reply(tmpctx, msg, + &our_stack, + &funding_tx)) { + status_failed(STATUS_FAIL_HSM_IO, + "Bad dual_funding_sigs reply %s", + tal_hex(msg, msg)); + } + + /* Verify that it's the same as openingd computed */ + bitcoin_txid(funding_tx, &hsm_funding_txid); + assert(bitcoin_txid_eq(&hsm_funding_txid, &state->funding_txid)); + + + /* We don't send this ourselves: channeld does, because master needs + * to save state to disk before doing so. */ + assert(our_sig.sighash_type == SIGHASH_ALL); + + msg = towire_accepter_sigs(state, &state->channel_id, + &our_sig.s, + cast_const2(const struct witness_stack **, our_stack)); + + /* we send everything to lightning, who commits things to the database etc. + * lightningd will forward the signatures etc over to channeld, who + * sends the final opening sequence message for us. */ + return towire_opening_fundee(state, + &state->remoteconf, + local_commit, + &their_sig, + state->pps, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.htlc, + &state->their_points.delayed_payment, + &state->first_per_commitment_point[REMOTE], + &state->their_funding_pubkey, + &state->funding_txid, + state->funding_txout, + state->opener_funding, + state->accepter_funding, + state->push_msat, + channel_flags, + state->feerate_per_kw, + msg, + state->localconf.channel_reserve, + state->remote_upfront_shutdown_script); +} +#endif /* EXPERIMENTAL_FEATURES */ + /*~ The peer sent us an `open_channel`, that means we're the fundee. */ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) { @@ -1517,72 +2008,9 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) "Bad open_channel %s", tal_hex(open_channel_msg, open_channel_msg)); - /* BOLT #2: - * - * The receiving node MUST fail the channel if: - * - the `chain_hash` value is set to a hash of a chain - * that is unknown to the receiver. - */ - if (!bitcoin_blkid_eq(&chain_hash, - &state->chainparams->genesis_blockhash)) { - negotiation_failed(state, false, - "Unknown chain-hash %s", - type_to_string(tmpctx, - struct bitcoin_blkid, - &chain_hash)); + if (!fundee_check_primitives(state, chain_hash)) return NULL; - } - /* BOLT #2 FIXME: - * - * The receiving node ... MUST fail the channel if `funding-satoshis` - * is greater than or equal to 2^24 */ - if (amount_sat_greater(state->opener_funding, state->chainparams->max_funding)) { - negotiation_failed(state, false, - "funding_satoshis %s too large", - type_to_string(tmpctx, struct amount_sat, - &state->opener_funding)); - return NULL; - } - - /* BOLT #2: - * - * The receiving node MUST fail the channel if: - * ... - * - `push_msat` is greater than `funding_satoshis` * 1000. - */ - if (amount_msat_greater_sat(state->push_msat, state->opener_funding)) { - peer_failed(state->pps, - &state->channel_id, - "Their push_msat %s" - " would be too large for funding_satoshis %s", - type_to_string(tmpctx, struct amount_msat, - &state->push_msat), - type_to_string(tmpctx, struct amount_sat, - &state->opener_funding)); - return NULL; - } - - /* BOLT #2: - * - * The receiving node MUST fail the channel if: - *... - * - it considers `feerate_per_kw` too small for timely processing or - * unreasonably large. - */ - if (state->feerate_per_kw < state->min_feerate) { - negotiation_failed(state, false, - "feerate_per_kw %u below minimum %u", - state->feerate_per_kw, state->min_feerate); - return NULL; - } - - if (state->feerate_per_kw > state->max_feerate) { - negotiation_failed(state, false, - "feerate_per_kw %u above maximum %u", - state->feerate_per_kw, state->max_feerate); - return NULL; - } /* This reserves 1% of the channel (rounded up) */ set_reserve(state); @@ -1853,6 +2281,12 @@ static u8 *handle_peer_in(struct state *state) if (t == WIRE_OPEN_CHANNEL) return fundee_channel(state, msg); +#if EXPERIMENTAL_FEATURES + else if (t == WIRE_OPEN_CHANNEL2) { + state->use_v2 = true; + return fundee_channel2(state, msg); + } +#endif /* EXPERIMENTAL_FEATURES */ /* Handles standard cases, and legal unknown ones. */ if (handle_peer_gossip_or_error(state->pps, @@ -1988,6 +2422,7 @@ static u8 *handle_master_in(struct state *state) case WIRE_OPENING_FUNDER_FAILED: case WIRE_OPENING_GOT_OFFER: case WIRE_OPENING_GOT_OFFER_REPLY: + case WIRE_OPENING_GOT_OFFER_REPLY_FUND: break; } From d6c831759df2fa704be9ed7f41b4b0ef05f42f7d Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Mon, 30 Sep 2019 18:34:35 -0500 Subject: [PATCH 37/45] openchannel: add dual-funding fields to hook Adds fields that are only relevant for v2 of openchannel protocol to the openchannel hook. --- CHANGELOG.md | 1 + lightningd/opening_control.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 051f7f84dc54..a3a6e8a60e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - JSON API: `txprepare` includes a parameter `zero_out_change`, which if true leaves the change value as zero. Useful for designating change output for dual-funded transactions. Defaults to false. - JSON API: `fundchannel_start` now includes `open_channel_version`, a string which indicates the protocol version used to open the channel. +- Plugin: `openchannel` hook includes fields for v2 channel establishment - bolt11: support for parsing feature bits (field `9`). diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 0f9bf59ebb2b..2e8c1f840a41 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -984,8 +984,13 @@ openchannel_hook_serialize(struct openchannel_hook_payload *payload, struct uncommitted_channel *uc = payload->openingd->channel; json_object_start(stream, "openchannel"); json_add_node_id(stream, "id", &uc->peer->id); - json_add_amount_sat_only(stream, "funding_satoshis", - payload->opener_satoshis); + json_add_string(stream, "version", payload->is_v2 ? "2" : "1"); + if (payload->is_v2) + json_add_amount_sat_only(stream, "opener_satoshis", + payload->opener_satoshis); + else + json_add_amount_sat_only(stream, "funding_satoshis", + payload->opener_satoshis); json_add_amount_msat_only(stream, "push_msat", payload->push_msat); json_add_amount_sat_only(stream, "dust_limit_satoshis", payload->dust_limit_satoshis); @@ -995,7 +1000,13 @@ openchannel_hook_serialize(struct openchannel_hook_payload *payload, payload->channel_reserve_satoshis); json_add_amount_msat_only(stream, "htlc_minimum_msat", payload->htlc_minimum_msat); + if (payload->is_v2) + json_add_amount_sat_only(stream, "available_funds", + payload->available_funds); json_add_num(stream, "feerate_per_kw", payload->feerate_per_kw); + if (payload->is_v2) + json_add_num(stream, "feerate_per_kw_funding", + payload->feerate_per_kw_funding); json_add_num(stream, "to_self_delay", payload->to_self_delay); json_add_num(stream, "max_accepted_htlcs", payload->max_accepted_htlcs); json_add_num(stream, "channel_flags", payload->channel_flags); From c63b5bfbf8f68a083186ecd184064b56647f9350 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 9 Oct 2019 20:38:36 -0500 Subject: [PATCH 38/45] plugins: add documentation for openchannel v2 fields Add documentation for new openchannel fields to doc/PLUGINS.md --- doc/PLUGINS.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/PLUGINS.md b/doc/PLUGINS.md index e76a51cd07e5..30e418221331 100644 --- a/doc/PLUGINS.md +++ b/doc/PLUGINS.md @@ -556,13 +556,17 @@ and it has passed basic sanity checks: { "openchannel": { "id": "03864ef025fde8fb587d989186ce6a4a186895ee44a926bfc370e2c366597a3f8f", - "funding_satoshis": "100000000msat", + "version": "2", // v2+ + "opening_satoshis": "100000000msat", // v2+ + "funding_satoshis": "100000000msat", // v1 "push_msat": "0msat", "dust_limit_satoshis": "546000msat", "max_htlc_value_in_flight_msat": "18446744073709551615msat", "channel_reserve_satoshis": "1000000msat", "htlc_minimum_msat": "0msat", + "available_funds": "201000msat", // v2+ "feerate_per_kw": 7500, + "feerate_per_kw_funding": 7500, // v2+ "to_self_delay": 5, "max_accepted_htlcs": 483, "channel_flags": 1 @@ -578,6 +582,17 @@ the string `reject` or `continue`. If `reject` and there's a member `error_message`, that member is sent to the peer before disconnection. +If this is a version "2" openchannel, then it allows for dual-funding. +A plugin can choose to dual-fund a channel by replying with a `continue` +message that contains a `funding_sats` field e.g.: + +```json +{ + "result": "continue", + "funding_sats": "100000sat" +} +``` + #### `htlc_accepted` The `htlc_accepted` hook is called whenever an incoming HTLC is accepted, and From 451748d34086c4e7d9e0ee759d41b71b8a88193b Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 10 Oct 2019 15:45:28 -0500 Subject: [PATCH 39/45] fixup b5f4c789cb --- lightningd/opening_control.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 2e8c1f840a41..12459cbc2b31 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1045,7 +1045,6 @@ static void openchannel_hook_cb(struct openchannel_hook_payload *payload, tal_del_destructor2(openingd, openchannel_payload_remove_openingd, payload); - pf->accepter_funding = AMOUNT_SAT(0); /* If we had a hook, check what it says */ if (buffer) { const jsmntok_t *t = json_get_member(buffer, toks, "result"); @@ -1075,6 +1074,8 @@ static void openchannel_hook_cb(struct openchannel_hook_payload *payload, "funding_sats"); if (funding_sats) json_to_sat(buffer, funding_sats, &pf->accepter_funding); + else + pf->accepter_funding = AMOUNT_SAT(0); } } From 5a66dc497206ddc3a80c2cc1dfbc6a2da1ec6eb0 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 10 Oct 2019 15:53:37 -0500 Subject: [PATCH 40/45] fixup! f2467f127d --- hsmd/hsmd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index d5ed0bd1a247..186b0421ccce 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -1612,12 +1612,18 @@ static void sign_our_inputs(struct bitcoin_tx *tx, struct utxo **utxos, struct pubkey inkey; struct bitcoin_signature sig; + input_index = -1; for (j = 0; j < map_len; j++) { if (ptr2int(map[j]) == i) { input_index = j; break; } } + + if (input_index < 0) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Unable to find index for input %zu", i); + sign_input(tx, utxos[i], &inkey, &sig, input_index); } } From 0bf122f02dc03e95214e61ebe927f8ae243b746d Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 10 Oct 2019 17:55:23 -0500 Subject: [PATCH 41/45] fixup! df-accepter: if payload is v2, calculate available funds --- lightningd/opening_control.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 12459cbc2b31..c64dbda0c83c 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1223,7 +1223,8 @@ static void opening_got_offer(struct subd *openingd, /* Leave space for change */ REMOTE_CONTRIB_LIMIT - 1, &payload->available_funds); - } + } else + uc->pf = NULL; tal_add_destructor2(openingd, openchannel_payload_remove_openingd, payload); plugin_hook_call_openchannel(openingd->ld, payload, payload); From 5f5a3a5d405cb39ab82f8fab1662b321767b5d38 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 10 Oct 2019 17:58:10 -0500 Subject: [PATCH 42/45] fixup! funding: pass utxos through to openingd --- lightningd/opening_control.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index c64dbda0c83c..5e5622a70516 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -1441,6 +1441,7 @@ static struct command_result *json_fund_channel_complete(struct command *cmd, } else { tx = NULL; utxos = tal_arr(tmpctx, const struct utxo *, 0); + peer->uncommitted_channel->fc->utx = NULL; } /* Set the cmd to this new cmd */ From 9b8d5406da07001ef007983bb88bf30066975bb8 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 10 Oct 2019 18:03:37 -0500 Subject: [PATCH 43/45] fixup! df: lookup transaction for the fundchannel_complete --- openingd/opening_wire.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index 073474c58c27..9a6a38c26a2d 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -98,7 +98,7 @@ msgdata,opening_funder_complete,funding_txout,u16, msgdata,opening_funder_complete,num_ins,u16, #include msgdata,opening_funder_complete,utxos,utxo,num_ins -msgdata,opening_funder_complete,tx,bitcoin_tx, +msgdata,opening_funder_complete,tx,?bitcoin_tx, #master->openingd: cancel channel establishment for a funding msgtype,opening_funder_cancel,6013 From 5d7283863412ac3a489a5af63a137db41f9d5c1d Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 10 Oct 2019 18:06:22 -0500 Subject: [PATCH 44/45] fixup! df: pipe through whether or not we're using v2 --- openingd/openingd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openingd/openingd.c b/openingd/openingd.c index f49a1509d268..c38a6d9d1855 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -526,6 +526,7 @@ static bool check_reserves(struct state *state) static bool setup_channel_funder(struct state *state) { if (!state->use_v2) + state->accepter_funding = AMOUNT_SAT(0); /*~ For symmetry, we calculate our own reserve even though lightningd * could do it for the we-are-funding case. */ set_reserve(state); @@ -550,9 +551,6 @@ static bool setup_channel_funder(struct state *state) return false; } - if (!state->use_v2) - state->accepter_funding = AMOUNT_SAT(0); - return true; } From 0e88f3897c4647645bdb3e4c0ad4ea4e149aa153 Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Thu, 10 Oct 2019 18:07:13 -0500 Subject: [PATCH 45/45] fixup! fundchannel: update to work with dual funding --- plugins/fundchannel.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/fundchannel.c b/plugins/fundchannel.c index ef086b05b42a..db84ca12de5b 100644 --- a/plugins/fundchannel.c +++ b/plugins/fundchannel.c @@ -150,9 +150,12 @@ static struct command_result *send_tx(struct command *cmd, /* The txid might be updated, since the peer might have added * inputs, also */ - txid = json_strdup(cmd, buf, json_get_member(buf, result, "txid")); - if (!bitcoin_txid_from_hex(txid, strlen(txid), &fr->tx_id)) - plugin_err("Unable to parse reserved txid %s", txid); + tok = json_get_member(buf, result, "txid"); + if (tok) { + txid = json_strdup(cmd, buf, tok); + if (!bitcoin_txid_from_hex(txid, strlen(txid), &fr->tx_id)) + plugin_err("Unable to parse reserved txid %s", txid); + } /* Stash the channel_id so we can return it when finalized */ fr->chanstr = json_strdup(fr, buf, json_get_member(buf, result, "channel_id"));