diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f0aabaaa276..a3a6e8a60e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ 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. +- 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/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..8db3ef8e75dc 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -39,10 +39,16 @@ 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, + 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/channeld/channel_wire.csv b/channeld/channel_wire.csv index 5744de929071..4f3586366a7f 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -22,7 +22,8 @@ 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,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 525d01d45d79..ab3ca85daa4e 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, @@ -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 */ @@ -1992,7 +2000,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 +2527,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 +2695,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 +2936,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; @@ -2936,14 +2944,14 @@ 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; 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)); @@ -2964,7 +2972,8 @@ static void init_channel(struct peer *peer) &points[REMOTE], &peer->remote_per_commit, &peer->old_remote_per_commit, - &funder, + &opener, + &local_funded, &peer->fee_base, &peer->fee_per_satoshi, &local_msat, @@ -2995,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, @@ -3015,7 +3024,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 +3072,8 @@ static void init_channel(struct peer *peer) &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], option_static_remotekey, - funder); + local_funded, + opener); if (!channel_force_htlcs(peer->channel, htlcs, hstates, fulfilled, fulfilled_sides, @@ -3091,7 +3101,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 */ @@ -3101,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/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..efeefa9e244f 100644 --- a/channeld/full_channel.c +++ b/channeld/full_channel.c @@ -47,7 +47,8 @@ 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) + bool local_funded, + enum side opener) { struct channel *channel = new_initial_channel(ctx, chain_hash, @@ -63,7 +64,8 @@ struct channel *new_full_channel(const tal_t *ctx, local_funding_pubkey, remote_funding_pubkey, option_static_remotekey, - funder); + local_funded, + opener); if (channel) { /* Feerates can be different. */ @@ -283,7 +285,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 +464,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 +538,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 +549,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 +564,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 +582,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 +878,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 +909,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 +940,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 +1020,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 +1071,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..7c3326d1d4b3 100644 --- a/channeld/full_channel.h +++ b/channeld/full_channel.h @@ -25,7 +25,8 @@ * @local_fundingkey: local funding key * @remote_fundingkey: remote funding key * @option_static_remotekey: use `option_static_remotekey`. - * @funder: which side initiated it. + * @local_funded: true if local has inputs in funding tx + * @opener: which side initiated it. * * Returns state, or NULL if malformed. */ @@ -44,7 +45,8 @@ 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); + bool local_funded, + enum side opener); /** * channel_txs: Get the current commitment and htlc txs for the channel. @@ -152,7 +154,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 +163,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..e0850b7a508a 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); @@ -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/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/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); 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/common/funding_tx.c b/common/funding_tx.c index 97e7711e6d22..bf1680ffceb4 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, + struct amount_sat *opener_change, + const void **input_map) +{ + size_t weight; + struct amount_sat funding_tx_fee, opener_total_sat, + accepter_total_sat, 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..f07493810d36 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,40 @@ 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 + * @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. + * @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, + 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, + struct amount_sat *opener_change, + const void **input_map); +#endif /* EXPERIMENTAL_FEATURES */ #endif /* LIGHTNING_COMMON_FUNDING_TX_H */ diff --git a/common/initial_channel.c b/common/initial_channel.c index 16547da5852f..baa621a853f7 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -23,7 +23,8 @@ 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) + bool local_funded, + enum side opener) { struct channel *channel = tal(ctx, struct channel); struct amount_msat remote_msatoshi; @@ -31,12 +32,13 @@ 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)) 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 +62,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 +102,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 +132,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..c395ef34d5f8 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -42,7 +42,10 @@ struct channel { u32 minimum_depth; /* Who is paying fees. */ - enum side funder; + 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,7 +89,9 @@ struct channel { * @remote_basepoints: remote basepoints. * @local_fundingkey: local funding key * @remote_fundingkey: remote funding key - * @funder: which side initiated it. + * @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,7 +110,8 @@ 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); + bool local_funded, + 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/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 new file mode 100644 index 000000000000..0187a69b513b --- /dev/null +++ b/common/test/run-funding_tx_dual.c @@ -0,0 +1,781 @@ +#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_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(); } +/* 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_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 { + 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, opener_change; + + 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, + &opener_change, 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 */ diff --git a/common/utxo.c b/common/utxo.c index 6b5eb7d73b50..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); @@ -29,6 +34,8 @@ void towire_utxo(u8 **pptr, const struct utxo *utxo) 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); @@ -36,9 +43,13 @@ 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; + 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); @@ -54,6 +65,7 @@ struct utxo *fromwire_utxo(const tal_t *ctx, const u8 **ptr, size_t *max) } else { utxo->close_info = NULL; } + 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/common/withdraw_tx.c b/common/withdraw_tx.c index 17e992cf3209..dd7933e9be23 100644 --- a/common/withdraw_tx.c +++ b/common/withdraw_tx.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -12,33 +13,49 @@ 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 pubkey *changekey, - struct amount_sat change, const struct ext_key *bip32_base, - int *change_outnum) + const void **input_map) { 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); + } + + /* 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); - 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); + 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 71e218589697..beaab58808aa 100644 --- a/common/withdraw_tx.h +++ b/common/withdraw_tx.h @@ -20,19 +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. - * @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_input **inputs, struct bitcoin_tx_output **outputs, - const struct pubkey *changekey, - struct amount_sat change, const struct ext_key *bip32_base, - int *change_outnum); + const void **input_map); #endif /* LIGHTNING_COMMON_WITHDRAW_TX_H */ 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/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) 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/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 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/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/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 e43d99114a59..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, @@ -67,13 +98,12 @@ 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_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 a8f60a6f85df..186b0421ccce 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,38 +1586,153 @@ 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); + sign_input(tx, utxos[i], &inkey, &sig, i); + } +} + +/* 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; + + 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); + } +} + +#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]); } - /* 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))); + 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. */ @@ -1632,27 +1782,47 @@ 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_input **inputs; struct bitcoin_tx_output **outputs; + size_t input_count, i, j; + int input_index; - if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, &satoshi_out, - &change_out, &change_keyindex, - &outputs, &utxos)) + if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, + &inputs, &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); + 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, - &changekey, change_out, NULL, NULL); - - sign_all_inputs(tx, utxos); + cast_const2(const struct utxo **, 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))); @@ -1836,6 +2006,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: @@ -1854,6 +2031,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: @@ -1906,6 +2084,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); @@ -1956,6 +2140,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: diff --git a/lightningd/channel.c b/lightningd/channel.c index a160b5a6d19e..66a455aba891 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, @@ -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, @@ -201,7 +202,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); @@ -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; @@ -407,7 +409,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..e5ec93cf595a 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; @@ -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. */ @@ -129,7 +133,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, @@ -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/channel_control.c b/lightningd/channel_control.c index 149ac2f9ad27..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; @@ -437,7 +437,8 @@ 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, + !amount_sat_eq(channel->our_funds, AMOUNT_SAT(0)), channel->feerate_base, channel->feerate_ppm, channel->our_msat, @@ -467,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, @@ -483,7 +484,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 +544,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..5e5622a70516 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 @@ -30,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +57,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; @@ -62,7 +69,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. */ @@ -93,6 +100,20 @@ struct funding_channel { /* Any commands trying to cancel us. */ struct command **cancels; + + /* 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, @@ -160,8 +181,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, @@ -179,17 +202,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] @@ -223,7 +257,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, @@ -232,8 +266,9 @@ wallet_commit_channel(struct lightningd *ld, 1, 1, 0, funding_txid, funding_outnum, - funding, + total_funding, push, + local_funding, false, /* !remote_funding_locked */ NULL, /* no scid yet */ /* The three arguments below are msatoshi_to_us, @@ -287,6 +322,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)); } @@ -306,6 +346,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)); @@ -341,6 +383,213 @@ 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 amount_sat opener_change, + 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); + utx->wtx->change = opener_change; + + 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, opener_change; + struct channel *channel; + struct lightningd *ld = openingd->ld; + u8 *remote_upfront_shutdown_script; + struct per_peer_state *pps; + struct witness_stack **remote_witnesses; + 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, + &opener_change, + &remote_witnesses, + &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, opener_change, 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) @@ -398,7 +647,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, @@ -430,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"); @@ -463,11 +717,12 @@ static void opening_fundee_finished(struct subd *openingd, &channel_info.remote_fundingkey, &funding_txid, &funding_outnum, - &funding, + &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", @@ -486,14 +741,25 @@ 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, + total_funding, + accepter_funding, push, + REMOTE, channel_flags, &channel_info, feerate, @@ -507,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 */ @@ -514,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; @@ -526,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, @@ -553,7 +825,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)); @@ -688,13 +960,17 @@ 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; 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; u16 max_accepted_htlcs; u8 channel_flags; @@ -708,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->funding_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); @@ -719,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); @@ -738,11 +1025,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); @@ -775,10 +1067,109 @@ 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); + else + pf->accepter_funding = AMOUNT_SAT(0); + } + } + + 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, @@ -804,13 +1195,15 @@ 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->funding_satoshis, + &payload->is_v2, + &payload->opener_satoshis, &payload->push_msat, &payload->dust_limit_satoshis, &payload->max_htlc_value_in_flight_msat, &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, @@ -821,6 +1214,18 @@ 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); + } else + uc->pf = NULL; + tal_add_destructor2(openingd, openchannel_payload_remove_openingd, payload); plugin_hook_call_openchannel(openingd->ld, payload, payload); } @@ -843,6 +1248,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", @@ -861,7 +1277,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; @@ -878,6 +1293,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: @@ -905,7 +1321,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", @@ -968,6 +1385,8 @@ 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; + const struct utxo **utxos; if (!param(cmd, buffer, params, p_req("id", param_node_id, &id), @@ -1000,11 +1419,37 @@ 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; + utxos = utx->wtx->utxos; + peer->uncommitted_channel->fc->utx = utx; + } else { + tx = NULL; + utxos = tal_arr(tmpctx, const struct utxo *, 0); + peer->uncommitted_channel->fc->utx = 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, + utxos, tx); + subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); return command_still_pending(cmd); } @@ -1162,11 +1607,18 @@ 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 + fc->is_v2 = feature_offered(peer->localfeatures, LOCAL_FUNDCHANNEL_V2); +#else + fc->is_v2 = false; +#endif + msg = towire_opening_funder_start(NULL, *amount, fc->push, *feerate_per_kw, - fc->channel_flags); + fc->channel_flags, + fc->is_v2); subd_send_msg(peer->uncommitted_channel->openingd, take(msg)); return command_still_pending(cmd); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index afc602d5e641..827b11ecb821 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, @@ -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->funder == 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->funder == 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)) { @@ -711,8 +699,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/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) 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/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 f3f969b3ad35..9a6a38c26a2d 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, @@ -44,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 @@ -72,6 +82,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 @@ -80,10 +91,14 @@ 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,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 msgtype,opening_funder_cancel,6013 @@ -107,17 +122,49 @@ 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,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, +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 efab07dd1709..c38a6d9d1855 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 @@ -86,7 +88,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; @@ -106,8 +108,24 @@ 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 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 @@ -120,8 +138,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 +152,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 +164,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 +179,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,10 +187,11 @@ 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; + struct amount_sat capacity, reserve, all_funding; + + all_funding = total_funding(state); /* BOLT #2: * @@ -181,7 +200,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 +223,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, @@ -213,8 +232,8 @@ 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, + if (!amount_sat_sub(&capacity, all_funding, reserve)) { + negotiation_failed(state, am_opener, "channel_reserve_satoshis %s" " and %s too large for funding %s", type_to_string(tmpctx, struct amount_sat, @@ -222,7 +241,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; } @@ -235,14 +254,14 @@ 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", 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; @@ -252,13 +271,13 @@ 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," " 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, @@ -274,7 +293,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 +306,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 +320,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, @@ -318,7 +337,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: * @@ -331,6 +350,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: @@ -352,7 +383,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 +445,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 +453,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. */ @@ -453,11 +484,52 @@ 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) + 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); + set_reserve(state); /*~ Grab a random ID until the funding tx is created (we can't do that * until we know their funding_pubkey) */ @@ -469,13 +541,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; } @@ -485,7 +557,7 @@ static bool setup_channel_funder(struct state *state) /* 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; @@ -494,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); @@ -541,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: * @@ -601,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; @@ -626,34 +770,320 @@ 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); } -static bool funder_finalize_channel_setup(struct state *state, - struct amount_msat local_msat, +#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 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; + const struct witness_stack **remote_witnesses; + + /* Derive components, omitting the funding output */ + derive_input_output_info(state, *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, + &opener_change, + (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"); - /*~ Now we can initialize the `struct channel`. This represents - * the current channel state and is how we can generate the current - * commitment transaction. - * - * The routines to support `struct channel` are split into a common - * part (common/initial_channel) which doesn't support HTLCs and is - * enough for us here, and the complete channel support required by - * `channeld` which lives in channeld/full_channel. */ state->channel = new_initial_channel(state, &state->chainparams->genesis_blockhash, &state->funding_txid, state->funding_txout, state->minimum_depth, - state->funding, - local_msat, + total_funding, + local_funding_msat, state->feerate_per_kw, &state->localconf, &state->remoteconf, @@ -662,197 +1092,846 @@ 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 */ + + /* 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, - "could not create channel with given config"); + "We could not create channel with given config"); - /* BOLT #2: - * - * ### The `funding_created` Message - * - * This message describes the outpoint which the funder has created - * for the initial commitment transactions. After receiving the - * peer's signature, via `funding_signed`, it will broadcast the funding - * transaction. - */ - /* This gives us their first commitment transaction. */ - *tx = initial_channel_tx(state, &wscript, state->channel, - &state->first_per_commitment_point[REMOTE], - REMOTE, &err_reason); - if (!*tx) { - /* This should not happen: we should never create channels we - * can't afford the fees for after reserve. */ + /* 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 their fees and reserve: %s", err_reason); - goto fail; - } + "Could not meet fees and reserve: %s", err_reason); - /* We ask the HSM to sign their commitment transaction for us: it knows - * our funding key, it just needs the remote funding key to create the - * witness script. It also needs the amount of the funding output, - * as segwit signatures commit to that as well, even though it doesn't - * explicitly appear in the transaction itself. */ msg = towire_hsm_sign_remote_commitment_tx(NULL, - *tx, + 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, sig)) + if (!fromwire_hsm_sign_tx_reply(msg, &our_sig)) status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); - /* You can tell this has been a problem before, since there's a debug - * message here: */ - status_debug("signature %s on tx %s using key %s", - type_to_string(tmpctx, struct bitcoin_signature, sig), - type_to_string(tmpctx, struct bitcoin_tx, *tx), - type_to_string(tmpctx, struct pubkey, - &state->our_funding_pubkey)); + 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 %s", + type_to_string(state, struct bitcoin_tx, funding_tx)); + + u32 *i_map = tal_arr(tmpctx, u32, input_count); + for (size_t i = 0; i < input_count; i++) { + i_map[i] = ptr2int(map[i]); + } + + return towire_opening_dual_funding_signed(state, + 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 */ +} + +static bool funder_finalize_channel_setup(struct state *state, + struct amount_msat local_msat, + struct bitcoin_signature *sig, + struct bitcoin_tx **tx) +{ + u8 *msg; + struct channel_id id_in; + const u8 *wscript; + char *err_reason; + + /*~ Now we can initialize the `struct channel`. This represents + * the current channel state and is how we can generate the current + * commitment transaction. + * + * The routines to support `struct channel` are split into a common + * part (common/initial_channel) which doesn't support HTLCs and is + * enough for us here, and the complete channel support required by + * `channeld` which lives in channeld/full_channel. */ + state->channel = new_initial_channel(state, + &state->chainparams->genesis_blockhash, + &state->funding_txid, + state->funding_txout, + state->minimum_depth, + total_funding(state), + 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, + true, + LOCAL); + /* We were supposed to do enough checks above, but just in case, + * new_initial_channel will fail to create absurd channels */ + if (!state->channel) + peer_failed(state->pps, + &state->channel_id, + "could not create channel with given config"); + + /* BOLT #2: + * + * ### The `funding_created` Message + * + * This message describes the outpoint which the funder has created + * for the initial commitment transactions. After receiving the + * peer's signature, via `funding_signed`, it will broadcast the funding + * transaction. + */ + /* This gives us their first commitment transaction. */ + *tx = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[REMOTE], + REMOTE, &err_reason); + if (!*tx) { + /* This should not happen: we should never create channels we + * can't afford the fees for after reserve. */ + negotiation_failed(state, true, + "Could not meet their fees and reserve: %s", err_reason); + goto fail; + } + + /* We ask the HSM to sign their commitment transaction for us: it knows + * our funding key, it just needs the remote funding key to create the + * witness script. It also needs the amount of the funding output, + * as segwit signatures commit to that as well, even though it doesn't + * explicitly appear in the transaction itself. */ + msg = towire_hsm_sign_remote_commitment_tx(NULL, + *tx, + &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, sig)) + status_failed(STATUS_FAIL_HSM_IO, "Bad sign_tx_reply %s", + tal_hex(tmpctx, msg)); + + /* You can tell this has been a problem before, since there's a debug + * message here: */ + status_debug("signature %s on tx %s using key %s", + type_to_string(tmpctx, struct bitcoin_signature, sig), + type_to_string(tmpctx, struct bitcoin_tx, *tx), + type_to_string(tmpctx, struct pubkey, + &state->our_funding_pubkey)); + + /* Now we give our peer the signature for their first commitment + * transaction. */ + msg = towire_funding_created(state, &state->channel_id, + &state->funding_txid, + state->funding_txout, + &sig->s); + sync_crypto_write(state->pps, msg); + + /* BOLT #2: + * + * ### The `funding_signed` Message + * + * This message gives the funder the signature it needs for the first + * commitment transaction, so it can broadcast the transaction knowing + * that funds can be redeemed, if need be. + */ + peer_billboard(false, + "Funding channel: create first tx, now waiting for their signature"); + + /* Now they send us their signature for that first commitment + * transaction. */ + msg = opening_negotiate_msg(tmpctx, state, true); + if (!msg) + goto fail; + + sig->sighash_type = SIGHASH_ALL; + if (!fromwire_funding_signed(msg, &id_in, &sig->s)) + peer_failed(state->pps, + &state->channel_id, + "Parsing funding_signed: %s", tal_hex(msg, msg)); + + /* BOLT #2: + * + * This message introduces the `channel_id` to identify the channel. + * It's derived from the funding transaction by combining the + * `funding_txid` and the `funding_output_index`, using big-endian + * exclusive-OR (i.e. `funding_output_index` alters the last 2 + * bytes). + */ + + /*~ Back in Milan, we chose to allow multiple channels between peers in + * the protocol. I insisted that we multiplex these over the same + * socket, and (even though I didn't plan on implementing it anytime + * soon) that we put it into the first version of the protocol + * because it would be painful to add in later. + * + * My logic seemed sound: we treat new connections as an implication + * that the old connection has disconnected, which happens more often + * than you'd hope on modern networks. However, supporting multiple + * channels via multiple connections would be far easier for us to + * support with our (introduced-since) separate daemon model. + * + * Let this be a lesson: beware premature specification, even if you + * suspect "we'll need it later!". */ + derive_channel_id(&state->channel_id, + &state->funding_txid, state->funding_txout); + + if (!channel_id_eq(&id_in, &state->channel_id)) + peer_failed(state->pps, &id_in, + "funding_signed ids don't match: expected %s got %s", + type_to_string(msg, struct channel_id, + &state->channel_id), + type_to_string(msg, struct channel_id, &id_in)); + + /* BOLT #2: + * + * The recipient: + * - if `signature` is incorrect: + * - MUST fail the channel. + */ + /* So we create *our* initial commitment transaction, and check the + * signature they sent against that. */ + *tx = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[LOCAL], + LOCAL, &err_reason); + if (!*tx) { + negotiation_failed(state, true, + "Could not meet our fees and reserve: %s", err_reason); + goto fail; + } + + if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) { + peer_failed(state->pps, + &state->channel_id, + "Bad signature %s on tx %s using key %s", + type_to_string(tmpctx, struct bitcoin_signature, + sig), + type_to_string(tmpctx, struct bitcoin_tx, *tx), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey)); + } + + peer_billboard(false, "Funding channel: opening negotiation succeeded"); + + return true; + +fail: + tal_free(wscript); + return false; +} + +static u8 *funder_channel_complete(struct state *state, + struct bitcoin_tx *tx, + struct utxo **utxos) +{ + struct bitcoin_signature sig; + struct amount_msat local_msat; + + /* Update the billboard about what we're doing*/ + peer_billboard(false, + "Funding channel con't: continuing with funding_txid %s", + type_to_string(tmpctx, struct bitcoin_txid, &state->funding_txid)); + + /* We recalculate the local_msat from cached values; should + * 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; + + return towire_opening_funder_reply(state, + &state->remoteconf, + tx, + &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->minimum_depth, + &state->their_funding_pubkey, + &state->funding_txid, + state->funding_txout, + state->feerate_per_kw, + state->localconf.channel_reserve, + 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); - /* Now we give our peer the signature for their first commitment - * transaction. */ - msg = towire_funding_created(state, &state->channel_id, - &state->funding_txid, - state->funding_txout, - &sig->s); - sync_crypto_write(state->pps, msg); + if (!funding_tx) + peer_failed(state->pps, + &state->channel_id, + "Opener unable to afford funding transaction"); - /* BOLT #2: - * - * ### The `funding_signed` Message - * - * This message gives the funder the signature it needs for the first - * commitment transaction, so it can broadcast the transaction knowing - * that funds can be redeemed, if need be. - */ - peer_billboard(false, - "Funding channel: create first tx, now waiting for their signature"); + bitcoin_txid(funding_tx, &state->funding_txid); + status_debug("dual funding tx is %s", + type_to_string(tmpctx, struct bitcoin_tx, funding_tx)); - /* Now they send us their signature for that first commitment - * transaction. */ - msg = opening_negotiate_msg(tmpctx, state, true); + /* 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) - goto fail; + return NULL; - sig->sighash_type = SIGHASH_ALL; - if (!fromwire_funding_signed(msg, &id_in, &sig->s)) + 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, - "Parsing funding_signed: %s", tal_hex(msg, msg)); + "Bad commitment_signed %s", tal_hex(msg, msg)); - /* BOLT #2: - * - * This message introduces the `channel_id` to identify the channel. - * It's derived from the funding transaction by combining the - * `funding_txid` and the `funding_output_index`, using big-endian - * exclusive-OR (i.e. `funding_output_index` alters the last 2 - * bytes). - */ + peer_billboard(false, "Incoming channel: commitment_signed received," + " composing funding tx"); - /*~ Back in Milan, we chose to allow multiple channels between peers in - * the protocol. I insisted that we multiplex these over the same - * socket, and (even though I didn't plan on implementing it anytime - * soon) that we put it into the first version of the protocol - * because it would be painful to add in later. - * - * My logic seemed sound: we treat new connections as an implication - * that the old connection has disconnected, which happens more often - * than you'd hope on modern networks. However, supporting multiple - * channels via multiple connections would be far easier for us to - * support with our (introduced-since) separate daemon model. - * - * Let this be a lesson: beware premature specification, even if you - * suspect "we'll need it later!". */ + 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 (!channel_id_eq(&id_in, &state->channel_id)) - peer_failed(state->pps, &id_in, - "funding_signed ids don't match: expected %s got %s", - type_to_string(msg, struct channel_id, - &state->channel_id), - type_to_string(msg, struct channel_id, &id_in)); + /* 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); - /* BOLT #2: - * - * The recipient: - * - if `signature` is incorrect: - * - MUST fail the channel. - */ - /* So we create *our* initial commitment transaction, and check the + /* We create *our* initial commitment transaction, and check the * signature they sent against that. */ - *tx = initial_channel_tx(state, &wscript, state->channel, - &state->first_per_commitment_point[LOCAL], - LOCAL, &err_reason); - if (!*tx) { - negotiation_failed(state, true, + 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); - goto fail; + return NULL; } - if (!check_tx_sig(*tx, 0, NULL, wscript, &state->their_funding_pubkey, sig)) { + 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, - sig), - type_to_string(tmpctx, struct bitcoin_tx, *tx), + &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); } - peer_billboard(false, "Funding channel: opening negotiation succeeded"); + msg = towire_hsm_sign_remote_commitment_tx(NULL, + remote_commit, + &state->channel->funding_pubkey[REMOTE], + state->channel->funding); - return true; + 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)); -fail: - tal_free(wscript); - return false; -} + /* 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); -static u8 *funder_channel_complete(struct state *state) -{ - struct bitcoin_tx *tx; - struct bitcoin_signature sig; - struct amount_msat local_msat; + 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)); + } - /* Update the billboard about what we're doing*/ - peer_billboard(false, - "Funding channel con't: continuing with funding_txid %s", - type_to_string(tmpctx, struct bitcoin_txid, &state->funding_txid)); + /* 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 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)); - if (!funder_finalize_channel_setup(state, local_msat, &sig, &tx)) - return NULL; + /* 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); - return towire_opening_funder_reply(state, - &state->remoteconf, - tx, - &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->minimum_depth, - &state->their_funding_pubkey, - &state->funding_txid, - state->funding_txout, - state->feerate_per_kw, - state->localconf.channel_reserve, - state->remote_upfront_shutdown_script); + 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) @@ -885,7 +1964,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, @@ -907,7 +1986,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, @@ -927,72 +2006,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)); - 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->funding, state->chainparams->max_funding)) { - negotiation_failed(state, false, - "funding_satoshis %s too large", - type_to_string(tmpctx, struct amount_sat, - &state->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->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->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); + if (!fundee_check_primitives(state, chain_hash)) 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); @@ -1029,20 +2045,22 @@ 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; /* 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->use_v2, + state->opener_funding, state->push_msat, state->remoteconf.dust_limit, state->remoteconf.max_htlc_value_in_flight, 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, @@ -1117,7 +2135,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, @@ -1126,6 +2144,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. */ @@ -1239,7 +2258,8 @@ 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, + AMOUNT_SAT(0), state->push_msat, channel_flags, state->feerate_per_kw, @@ -1259,6 +2279,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, @@ -1343,14 +2369,17 @@ 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; + struct utxo **utxos; u16 funding_txout; 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)) + &channel_flags, + &state->use_v2)) master_badmsg(WIRE_OPENING_FUNDER_START, msg); msg = funder_channel_start(state, channel_flags); @@ -1359,13 +2388,15 @@ 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, + &utxos, + &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, utxos); case WIRE_OPENING_FUNDER_CANCEL: /* We're aborting this, simple */ if (!fromwire_opening_funder_cancel(msg)) @@ -1383,11 +2414,13 @@ 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: case WIRE_OPENING_GOT_OFFER: case WIRE_OPENING_GOT_OFFER_REPLY: + case WIRE_OPENING_GOT_OFFER_REPLY_FUND: break; } diff --git a/plugins/fundchannel.c b/plugins/fundchannel.c index eacbc4086ac8..db84ca12de5b 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 */ @@ -137,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"); @@ -144,9 +148,17 @@ 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 */ + 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 */ - 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, '{'); @@ -259,6 +271,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; @@ -293,6 +307,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, '{'); @@ -446,6 +464,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/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 diff --git a/tools/generate-wire.py b/tools/generate-wire.py index 882350c03940..e044318fd230 100755 --- a/tools/generate-wire.py +++ b/tools/generate-wire.py @@ -221,6 +221,10 @@ class Type(FieldSet): 'per_peer_state', '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 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 534a75c23656..437fae08697a 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,99 @@ 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; + 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); +} + +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) { @@ -828,7 +922,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 +942,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 +962,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 +999,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 +1009,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 +1031,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 +1045,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 +1098,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 +1378,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=?," @@ -1305,7 +1403,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); @@ -1317,37 +1415,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); diff --git a/wallet/wallet.h b/wallet/wallet.h index 61e4bb724310..7deddc4ff35b 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -60,11 +60,11 @@ 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; - /* Index of change output, or -1 if none. */ - int change_outnum; }; /* Possible states for tracked outputs in the database. Not sure yet @@ -387,6 +387,25 @@ 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_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 * diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 8a9cbba9576b..df23e59b15fc 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 */ @@ -80,12 +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, - utx->wtx->amount, - utx->wtx->change, - utx->wtx->change_key_index, + cast_const2(const struct bitcoin_tx_input **, + utx->inputs), cast_const2(const struct bitcoin_tx_output **, utx->outputs), utx->wtx->utxos); @@ -120,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 @@ -134,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; @@ -155,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) { @@ -166,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(); @@ -292,10 +340,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; @@ -309,46 +355,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; - - /* 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); + struct bitcoin_tx_output *output; - 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; - 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)); + 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,19 +377,17 @@ 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); } create_tx: - (*utx)->outputs = tal_steal(*utx, outputs); - if (chosen_utxos) result = wtx_from_utxos((*utx)->wtx, *feerate_per_kw, out_len, maxheight, @@ -385,18 +404,35 @@ 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; + 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"); - } else - changekey = NULL; + + + 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); + } + + (*utx)->inputs = NULL; + (*utx)->outputs = tal_steal(*utx, outputs); (*utx)->tx = withdraw_tx(*utx, get_chainparams(cmd->ld), - (*utx)->wtx->utxos, (*utx)->outputs, - changekey, (*utx)->wtx->change, + (*utx)->wtx->utxos, + (*utx)->inputs, + (*utx)->outputs, cmd->ld->wallet->bip32_base, - &(*utx)->change_outnum); + NULL); + bitcoin_txid((*utx)->tx, &(*utx)->txid); return NULL; 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/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/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..a59829d730dc 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,332 @@ 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 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) +{ + 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 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) +{ + 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 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) +{ + bool ok = true; + eq_struct_set(a, b, witness_stacks, witness_stack); + 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) +{ + 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 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, const struct msg_channel_announcement *b) { @@ -789,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) { @@ -802,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) { @@ -809,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) { @@ -816,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) { @@ -841,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) { @@ -848,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) { @@ -861,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) { @@ -868,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) { @@ -881,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) { @@ -888,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) { @@ -895,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) { @@ -902,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) { @@ -918,20 +1397,39 @@ 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++) { \ 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); \ + assert(type##_truncation_check(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) { setup_locale(); @@ -956,6 +1454,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 +1649,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/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 f9781ab34c72..1e608b874fb9 100644 --- a/wire/wire.h +++ b/wire/wire.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -142,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 */