From a730cbdc96f445c30685e74bef09953b571fa5e6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 14 Aug 2020 11:00:42 +0930 Subject: [PATCH] onchaind: recognize (and ignore) anchor outputs. Without this, onchaind fails to identify them. So onchaind now needs to know the funding pubkeys. Signed-off-by: Rusty Russell --- lightningd/onchain_control.c | 2 + onchaind/onchain_types.h | 4 + onchaind/onchain_wire.csv | 2 + onchaind/onchaind.c | 130 ++++++++++++++++++++++++-- onchaind/test/run-grind_feerate-bug.c | 2 +- onchaind/test/run-grind_feerate.c | 2 +- 6 files changed, 132 insertions(+), 10 deletions(-) diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index 936e8a338..ad8ba4c5d 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -624,6 +624,8 @@ enum watch_result onchaind_funding_spent(struct channel *channel, channel->min_possible_feerate, channel->max_possible_feerate, channel->future_per_commitment_point, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, channel->option_static_remotekey, channel->option_anchor_outputs, is_replay); diff --git a/onchaind/onchain_types.h b/onchaind/onchain_types.h index 667a006e4..3e1e874f9 100644 --- a/onchaind/onchain_types.h +++ b/onchaind/onchain_types.h @@ -73,6 +73,10 @@ enum output_type { /* For elements we need a fee output type */ ELEMENTS_FEE, + + /* Anchor outputs for option_anchor_outputs */ + ANCHOR_TO_US, + ANCHOR_TO_THEM, }; diff --git a/onchaind/onchain_wire.csv b/onchaind/onchain_wire.csv index 1e5388d1d..ab3023035 100644 --- a/onchaind/onchain_wire.csv +++ b/onchaind/onchain_wire.csv @@ -44,6 +44,8 @@ msgdata,onchain_init,num_htlcs,u64, msgdata,onchain_init,min_possible_feerate,u32, msgdata,onchain_init,max_possible_feerate,u32, msgdata,onchain_init,possible_remote_per_commit_point,?pubkey, +msgdata,onchain_init,local_funding_pubkey,pubkey, +msgdata,onchain_init,remote_funding_pubkey,pubkey, msgdata,onchain_init,option_static_remotekey,bool, msgdata,onchain_init,option_anchor_outputs,bool, msgdata,onchain_init,is_replay,bool, diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 1b797c68e..0ecac4aa4 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -79,6 +79,9 @@ static u8 **missing_htlc_msgs; /* Our recorded channel balance at 'chain time' */ static struct amount_msat our_msat; +/* Needed for anchor outputs */ +static struct pubkey funding_pubkey[NUM_SIDES]; + /* Does option_static_remotekey apply to this commitment tx? */ static bool option_static_remotekey; @@ -1512,6 +1515,8 @@ static void output_spent(struct tracked_output ***outs, case OUTPUT_TO_THEM: case DELAYED_OUTPUT_TO_THEM: case ELEMENTS_FEE: + case ANCHOR_TO_US: + case ANCHOR_TO_THEM: status_failed(STATUS_FAIL_INTERNAL_ERROR, "Tracked spend of %s/%s?", tx_type_name(out->tx_type), @@ -1724,7 +1729,8 @@ static void handle_preimage(struct tracked_output **outs, * - MUST *resolve* the output by spending it to a * convenient address. */ - tx = tx_to_us(outs[i], remote_htlc_to_us, outs[i], 0, + tx = tx_to_us(outs[i], remote_htlc_to_us, outs[i], + option_anchor_outputs ? 1 : 0, 0, preimage, sizeof(*preimage), outs[i]->wscript, &tx_type, htlc_feerate); @@ -1970,7 +1976,8 @@ static size_t resolve_our_htlc_ourcommit(struct tracked_output *out, "No valid signature found for %zu htlc_timeout_txs" " feerate %u-%u," " last tx %s, input %s, signature %s," - " cltvs %s wscripts %s", + " cltvs %s wscripts %s" + " %s", tal_count(matches), min_possible_feerate, max_possible_feerate, type_to_string(tmpctx, struct bitcoin_tx, tx), @@ -1978,7 +1985,9 @@ static size_t resolve_our_htlc_ourcommit(struct tracked_output *out, &out->sat), type_to_string(tmpctx, struct bitcoin_signature, out->remote_htlc_sig), - cltvs, wscripts); + cltvs, wscripts, + option_anchor_outputs + ? "option_anchor_outputs" : ""); } hsm_sign_local_htlc_tx(tx, htlc_scripts[matches[i]], &localsig); @@ -2030,7 +2039,9 @@ static size_t resolve_our_htlc_theircommit(struct tracked_output *out, * - MUST *resolve* the output, by spending it to a convenient * address. */ - tx = tx_to_us(out, remote_htlc_to_us, out, 0, cltv_expiry, NULL, 0, + tx = tx_to_us(out, remote_htlc_to_us, out, + option_anchor_outputs ? 1 : 0, + cltv_expiry, NULL, 0, htlc_scripts[matches[0]], &tx_type, htlc_feerate); propose_resolution_at_block(out, tx, cltv_expiry, tx_type, is_replay); @@ -2147,6 +2158,20 @@ static void note_missing_htlcs(u8 **htlc_scripts, } } +static void get_anchor_scriptpubkeys(const tal_t *ctx, u8 **anchor) +{ + if (!option_anchor_outputs) { + anchor[LOCAL] = anchor[REMOTE] = NULL; + return; + } + + for (enum side side = 0; side < NUM_SIDES; side++) { + u8 *wscript = bitcoin_wscript_anchor(tmpctx, + &funding_pubkey[side]); + anchor[side] = scriptpubkey_p2wsh(ctx, wscript); + } +} + static void handle_our_unilateral(const struct tx_parts *tx, u32 tx_blockheight, const struct basepoints basepoints[NUM_SIDES], @@ -2158,7 +2183,7 @@ static void handle_our_unilateral(const struct tx_parts *tx, bool is_replay) { u8 **htlc_scripts; - u8 *local_wscript, *script[NUM_SIDES]; + u8 *local_wscript, *script[NUM_SIDES], *anchor[NUM_SIDES]; struct pubkey local_per_commitment_point; struct keyset *ks; size_t i; @@ -2235,6 +2260,8 @@ static void handle_our_unilateral(const struct tx_parts *tx, tx->outputs[i]->script_len)); } + get_anchor_scriptpubkeys(tmpctx, anchor); + for (i = 0; i < tal_count(tx->outputs); i++) { struct tracked_output *out; const size_t *matches; @@ -2327,6 +2354,33 @@ static void handle_our_unilateral(const struct tx_parts *tx, add_amt(&their_outs, amt); continue; } + if (anchor[LOCAL] + && wally_tx_output_scripteq(tx->outputs[i], + anchor[LOCAL])) { + /* FIXME: We should be able to spend this! */ + out = new_tracked_output(&outs, &tx->txid, + tx_blockheight, + OUR_UNILATERAL, i, + amt, + ANCHOR_TO_US, + NULL, NULL, NULL); + ignore_output(out); + anchor[LOCAL] = NULL; + continue; + } + if (anchor[REMOTE] + && wally_tx_output_scripteq(tx->outputs[i], + anchor[REMOTE])) { + out = new_tracked_output(&outs, &tx->txid, + tx_blockheight, + OUR_UNILATERAL, i, + amt, + ANCHOR_TO_THEM, + NULL, NULL, NULL); + ignore_output(out); + anchor[REMOTE] = NULL; + continue; + } matches = match_htlc_output(tmpctx, tx->outputs[i], htlc_scripts); /* FIXME: limp along when this happens! */ @@ -2479,7 +2533,7 @@ static void tell_wallet_to_remote(const struct tx_parts *tx, */ static void update_ledger_cheat(const struct bitcoin_txid *txid, u32 blockheight, - struct tracked_output *out) + const struct tracked_output *out) { /* how much of a difference should we update the * channel account ledger by? */ @@ -2520,7 +2574,7 @@ static void handle_their_cheat(const struct tx_parts *tx, bool is_replay) { u8 **htlc_scripts; - u8 *remote_wscript, *script[NUM_SIDES]; + u8 *remote_wscript, *script[NUM_SIDES], *anchor[NUM_SIDES]; struct keyset *ks; struct pubkey *k; size_t i; @@ -2633,6 +2687,8 @@ static void handle_their_cheat(const struct tx_parts *tx, status_debug("Script to-me: %s", tal_hex(tmpctx, script[LOCAL])); + get_anchor_scriptpubkeys(tmpctx, anchor); + for (i = 0; i < tal_count(tx->outputs); i++) { if (tx->outputs[i]->script_len == 0) continue; @@ -2710,6 +2766,33 @@ static void handle_their_cheat(const struct tx_parts *tx, add_amt(&total_outs, amt); continue; } + if (anchor[LOCAL] + && wally_tx_output_scripteq(tx->outputs[i], + anchor[LOCAL])) { + /* FIXME: We should be able to spend this! */ + out = new_tracked_output(&outs, &tx->txid, + tx_blockheight, + THEIR_REVOKED_UNILATERAL, i, + amt, + ANCHOR_TO_US, + NULL, NULL, NULL); + ignore_output(out); + anchor[LOCAL] = NULL; + continue; + } + if (anchor[REMOTE] + && wally_tx_output_scripteq(tx->outputs[i], + anchor[REMOTE])) { + out = new_tracked_output(&outs, &tx->txid, + tx_blockheight, + THEIR_REVOKED_UNILATERAL, i, + amt, + ANCHOR_TO_THEM, + NULL, NULL, NULL); + ignore_output(out); + anchor[REMOTE] = NULL; + continue; + } matches = match_htlc_output(tmpctx, tx->outputs[i], htlc_scripts); if (tal_count(matches) == 0) @@ -2786,7 +2869,7 @@ static void handle_their_unilateral(const struct tx_parts *tx, bool is_replay) { u8 **htlc_scripts; - u8 *remote_wscript, *script[NUM_SIDES]; + u8 *remote_wscript, *script[NUM_SIDES], *anchor[NUM_SIDES]; struct keyset *ks; size_t i; struct amount_sat their_outs = AMOUNT_SAT(0), our_outs = AMOUNT_SAT(0); @@ -2885,6 +2968,8 @@ static void handle_their_unilateral(const struct tx_parts *tx, status_debug("Script to-me: %s", tal_hex(tmpctx, script[LOCAL])); + get_anchor_scriptpubkeys(tmpctx, anchor); + for (i = 0; i < tal_count(tx->outputs); i++) { if (tx->outputs[i]->script_len == 0) continue; @@ -2962,6 +3047,33 @@ static void handle_their_unilateral(const struct tx_parts *tx, add_amt(&their_outs, amt); continue; } + if (anchor[LOCAL] + && wally_tx_output_scripteq(tx->outputs[i], + anchor[LOCAL])) { + /* FIXME: We should be able to spend this! */ + out = new_tracked_output(&outs, &tx->txid, + tx_blockheight, + THEIR_UNILATERAL, i, + amt, + ANCHOR_TO_US, + NULL, NULL, NULL); + ignore_output(out); + anchor[LOCAL] = NULL; + continue; + } + if (anchor[REMOTE] + && wally_tx_output_scripteq(tx->outputs[i], + anchor[REMOTE])) { + out = new_tracked_output(&outs, &tx->txid, + tx_blockheight, + THEIR_UNILATERAL, i, + amt, + ANCHOR_TO_THEM, + NULL, NULL, NULL); + ignore_output(out); + anchor[REMOTE] = NULL; + continue; + } matches = match_htlc_output(tmpctx, tx->outputs[i], htlc_scripts); if (tal_count(matches) == 0) @@ -3242,6 +3354,8 @@ int main(int argc, char *argv[]) &min_possible_feerate, &max_possible_feerate, &possible_remote_per_commitment_point, + &funding_pubkey[LOCAL], + &funding_pubkey[REMOTE], &option_static_remotekey, &option_anchor_outputs, &open_is_replay)) { diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index 4b21ade63..1519c9010 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -50,7 +50,7 @@ bool fromwire_onchain_dev_memleak(const void *p UNNEEDED) bool fromwire_onchain_htlc(const void *p UNNEEDED, struct htlc_stub *htlc UNNEEDED, bool *tell_if_missing UNNEEDED, bool *tell_immediately UNNEEDED) { fprintf(stderr, "fromwire_onchain_htlc called!\n"); abort(); } /* Generated stub for fromwire_onchain_init */ -bool fromwire_onchain_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct shachain *shachain UNNEEDED, const struct chainparams **chainparams UNNEEDED, struct amount_sat *funding_amount_satoshi UNNEEDED, struct amount_msat *our_msat UNNEEDED, struct pubkey *old_remote_per_commitment_point UNNEEDED, struct pubkey *remote_per_commitment_point UNNEEDED, u32 *local_to_self_delay UNNEEDED, u32 *remote_to_self_delay UNNEEDED, u32 *delayed_to_us_feerate UNNEEDED, u32 *htlc_feerate UNNEEDED, u32 *penalty_feerate UNNEEDED, struct amount_sat *local_dust_limit_satoshi UNNEEDED, struct bitcoin_txid *our_broadcast_txid UNNEEDED, u8 **local_scriptpubkey UNNEEDED, u8 **remote_scriptpubkey UNNEEDED, struct pubkey *ourwallet_pubkey UNNEEDED, enum side *opener UNNEEDED, struct basepoints *local_basepoints UNNEEDED, struct basepoints *remote_basepoints UNNEEDED, struct tx_parts **tx_parts UNNEEDED, u32 *locktime UNNEEDED, u32 *tx_blockheight UNNEEDED, u32 *reasonable_depth UNNEEDED, struct bitcoin_signature **htlc_signature UNNEEDED, u64 *num_htlcs UNNEEDED, u32 *min_possible_feerate UNNEEDED, u32 *max_possible_feerate UNNEEDED, struct pubkey **possible_remote_per_commit_point UNNEEDED, bool *option_static_remotekey UNNEEDED, bool *option_anchor_outputs UNNEEDED, bool *is_replay UNNEEDED) +bool fromwire_onchain_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct shachain *shachain UNNEEDED, const struct chainparams **chainparams UNNEEDED, struct amount_sat *funding_amount_satoshi UNNEEDED, struct amount_msat *our_msat UNNEEDED, struct pubkey *old_remote_per_commitment_point UNNEEDED, struct pubkey *remote_per_commitment_point UNNEEDED, u32 *local_to_self_delay UNNEEDED, u32 *remote_to_self_delay UNNEEDED, u32 *delayed_to_us_feerate UNNEEDED, u32 *htlc_feerate UNNEEDED, u32 *penalty_feerate UNNEEDED, struct amount_sat *local_dust_limit_satoshi UNNEEDED, struct bitcoin_txid *our_broadcast_txid UNNEEDED, u8 **local_scriptpubkey UNNEEDED, u8 **remote_scriptpubkey UNNEEDED, struct pubkey *ourwallet_pubkey UNNEEDED, enum side *opener UNNEEDED, struct basepoints *local_basepoints UNNEEDED, struct basepoints *remote_basepoints UNNEEDED, struct tx_parts **tx_parts UNNEEDED, u32 *locktime UNNEEDED, u32 *tx_blockheight UNNEEDED, u32 *reasonable_depth UNNEEDED, struct bitcoin_signature **htlc_signature UNNEEDED, u64 *num_htlcs UNNEEDED, u32 *min_possible_feerate UNNEEDED, u32 *max_possible_feerate UNNEEDED, struct pubkey **possible_remote_per_commit_point UNNEEDED, struct pubkey *local_funding_pubkey UNNEEDED, struct pubkey *remote_funding_pubkey UNNEEDED, bool *option_static_remotekey UNNEEDED, bool *option_anchor_outputs UNNEEDED, bool *is_replay UNNEEDED) { fprintf(stderr, "fromwire_onchain_init called!\n"); abort(); } /* Generated stub for fromwire_onchain_known_preimage */ bool fromwire_onchain_known_preimage(const void *p UNNEEDED, struct preimage *preimage UNNEEDED, bool *is_replay UNNEEDED) diff --git a/onchaind/test/run-grind_feerate.c b/onchaind/test/run-grind_feerate.c index f46bc5a82..3b7c0450d 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -54,7 +54,7 @@ bool fromwire_onchain_dev_memleak(const void *p UNNEEDED) bool fromwire_onchain_htlc(const void *p UNNEEDED, struct htlc_stub *htlc UNNEEDED, bool *tell_if_missing UNNEEDED, bool *tell_immediately UNNEEDED) { fprintf(stderr, "fromwire_onchain_htlc called!\n"); abort(); } /* Generated stub for fromwire_onchain_init */ -bool fromwire_onchain_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct shachain *shachain UNNEEDED, const struct chainparams **chainparams UNNEEDED, struct amount_sat *funding_amount_satoshi UNNEEDED, struct amount_msat *our_msat UNNEEDED, struct pubkey *old_remote_per_commitment_point UNNEEDED, struct pubkey *remote_per_commitment_point UNNEEDED, u32 *local_to_self_delay UNNEEDED, u32 *remote_to_self_delay UNNEEDED, u32 *delayed_to_us_feerate UNNEEDED, u32 *htlc_feerate UNNEEDED, u32 *penalty_feerate UNNEEDED, struct amount_sat *local_dust_limit_satoshi UNNEEDED, struct bitcoin_txid *our_broadcast_txid UNNEEDED, u8 **local_scriptpubkey UNNEEDED, u8 **remote_scriptpubkey UNNEEDED, struct pubkey *ourwallet_pubkey UNNEEDED, enum side *opener UNNEEDED, struct basepoints *local_basepoints UNNEEDED, struct basepoints *remote_basepoints UNNEEDED, struct tx_parts **tx_parts UNNEEDED, u32 *locktime UNNEEDED, u32 *tx_blockheight UNNEEDED, u32 *reasonable_depth UNNEEDED, struct bitcoin_signature **htlc_signature UNNEEDED, u64 *num_htlcs UNNEEDED, u32 *min_possible_feerate UNNEEDED, u32 *max_possible_feerate UNNEEDED, struct pubkey **possible_remote_per_commit_point UNNEEDED, bool *option_static_remotekey UNNEEDED, bool *option_anchor_outputs UNNEEDED, bool *is_replay UNNEEDED) +bool fromwire_onchain_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct shachain *shachain UNNEEDED, const struct chainparams **chainparams UNNEEDED, struct amount_sat *funding_amount_satoshi UNNEEDED, struct amount_msat *our_msat UNNEEDED, struct pubkey *old_remote_per_commitment_point UNNEEDED, struct pubkey *remote_per_commitment_point UNNEEDED, u32 *local_to_self_delay UNNEEDED, u32 *remote_to_self_delay UNNEEDED, u32 *delayed_to_us_feerate UNNEEDED, u32 *htlc_feerate UNNEEDED, u32 *penalty_feerate UNNEEDED, struct amount_sat *local_dust_limit_satoshi UNNEEDED, struct bitcoin_txid *our_broadcast_txid UNNEEDED, u8 **local_scriptpubkey UNNEEDED, u8 **remote_scriptpubkey UNNEEDED, struct pubkey *ourwallet_pubkey UNNEEDED, enum side *opener UNNEEDED, struct basepoints *local_basepoints UNNEEDED, struct basepoints *remote_basepoints UNNEEDED, struct tx_parts **tx_parts UNNEEDED, u32 *locktime UNNEEDED, u32 *tx_blockheight UNNEEDED, u32 *reasonable_depth UNNEEDED, struct bitcoin_signature **htlc_signature UNNEEDED, u64 *num_htlcs UNNEEDED, u32 *min_possible_feerate UNNEEDED, u32 *max_possible_feerate UNNEEDED, struct pubkey **possible_remote_per_commit_point UNNEEDED, struct pubkey *local_funding_pubkey UNNEEDED, struct pubkey *remote_funding_pubkey UNNEEDED, bool *option_static_remotekey UNNEEDED, bool *option_anchor_outputs UNNEEDED, bool *is_replay UNNEEDED) { fprintf(stderr, "fromwire_onchain_init called!\n"); abort(); } /* Generated stub for fromwire_onchain_known_preimage */ bool fromwire_onchain_known_preimage(const void *p UNNEEDED, struct preimage *preimage UNNEEDED, bool *is_replay UNNEEDED)