onchaind: don't rely on knowing option_static_remotekey for unknown commitments.

Just always handle both cases.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2021-06-04 11:23:43 +09:30
parent 2fea448498
commit 7d666e9bfd

View file

@ -3594,79 +3594,86 @@ static void handle_unknown_commitment(const struct tx_parts *tx,
bool is_replay)
{
int to_us_output = -1;
u8 *local_script;
/* We have two possible local scripts, depending on options */
u8 *local_scripts[2];
struct amount_sat amt_salvaged = AMOUNT_SAT(0);
onchain_annotate_txin(&tx->txid, 0, TX_CHANNEL_UNILATERAL | TX_THEIRS);
resolved_by_other(outs[0], &tx->txid, UNKNOWN_UNILATERAL);
/* If they don't give us a per-commitment point and we rotate keys,
* we're out of luck. */
if (!possible_remote_per_commitment_point
&& !option_static_remotekey) {
goto search_done;
}
if (!option_static_remotekey) {
/* This is the not-option_static_remotekey case, if we got a hint
* from them about the per-commitment point */
if (possible_remote_per_commitment_point) {
struct keyset *ks = tal(tmpctx, struct keyset);
if (!derive_keyset(possible_remote_per_commitment_point,
&basepoints[REMOTE],
&basepoints[LOCAL],
option_static_remotekey,
false,
ks))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Deriving keyset for possible_remote_per_commitment_point %s",
type_to_string(tmpctx, struct pubkey,
possible_remote_per_commitment_point));
local_script = scriptpubkey_p2wpkh(tmpctx,
&ks->other_payment_key);
local_scripts[0] = scriptpubkey_p2wpkh(tmpctx,
&ks->other_payment_key);
} else {
local_script = scriptpubkey_to_remote(tmpctx,
&basepoints[LOCAL].payment);
local_scripts[0] = NULL;
}
/* Other possible local script is for option_static_remotekey */
local_scripts[1] = scriptpubkey_to_remote(tmpctx,
&basepoints[LOCAL].payment);
for (size_t i = 0; i < tal_count(tx->outputs); i++) {
struct tracked_output *out;
struct amount_asset asset = wally_tx_output_get_amount(tx->outputs[i]);
struct amount_sat amt;
int which_script;
assert(amount_asset_is_main(&asset));
amt = amount_asset_to_sat(&asset);
if (local_script
&& wally_tx_output_scripteq(tx->outputs[i],
local_script)) {
/* BOLT #5:
*
* - MAY take no action in regard to the associated
* `to_remote`, which is simply a P2WPKH output to
* the *local node*.
* - Note: `to_remote` is considered *resolved* by the
* commitment transaction itself.
*/
out = new_tracked_output(&outs, &tx->txid, tx_blockheight,
UNKNOWN_UNILATERAL,
i, amt,
OUTPUT_TO_US, NULL, NULL, NULL);
ignore_output(out);
/* Elements can have empty output scripts (fee output) */
if (local_scripts[0]
&& wally_tx_output_scripteq(tx->outputs[i], local_scripts[0]))
which_script = 0;
else if (local_scripts[1]
&& wally_tx_output_scripteq(tx->outputs[i],
local_scripts[1]))
which_script = 1;
else
continue;
if (!is_replay)
record_channel_withdrawal(&tx->txid, tx_blockheight, out);
/* BOLT #5:
*
* - MAY take no action in regard to the associated
* `to_remote`, which is simply a P2WPKH output to
* the *local node*.
* - Note: `to_remote` is considered *resolved* by the
* commitment transaction itself.
*/
out = new_tracked_output(&outs, &tx->txid, tx_blockheight,
UNKNOWN_UNILATERAL,
i, amt,
OUTPUT_TO_US, NULL, NULL, NULL);
ignore_output(out);
add_amt(&amt_salvaged, amt);
if (!is_replay)
record_channel_withdrawal(&tx->txid, tx_blockheight, out);
tell_wallet_to_remote(tx, i,
tx_blockheight,
local_script,
possible_remote_per_commitment_point,
option_static_remotekey);
local_script = NULL;
to_us_output = i;
}
add_amt(&amt_salvaged, amt);
tell_wallet_to_remote(tx, i,
tx_blockheight,
local_scripts[which_script],
possible_remote_per_commitment_point,
which_script == 1);
local_scripts[0] = local_scripts[1] = NULL;
to_us_output = i;
}
search_done:
if (to_us_output == -1) {
status_broken("FUNDS LOST. Unknown commitment #%"PRIu64"!",
commit_num);