diff --git a/channeld/channeld.c b/channeld/channeld.c index 212c68ba7ba6..bfd2d665937e 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -346,6 +346,50 @@ static bool handle_master_request_later(struct peer *peer, const u8 *msg) } return false; } + +static bool channel_type_eq(const struct channel_type *a, + const struct channel_type *b) +{ + return featurebits_eq(a->features, b->features); +} + +static bool match_type(const struct channel_type *desired, + const struct channel_type *current, + struct channel_type **upgradable) +{ + /* Missing fields are possible. */ + if (!desired || !current) + return false; + + if (channel_type_eq(desired, current)) + return true; + + for (size_t i = 0; i < tal_count(upgradable); i++) { + if (channel_type_eq(desired, upgradable[i])) + return true; + } + + return false; +} + +static void set_channel_type(struct channel *channel, + const struct channel_type *type) +{ + const struct channel_type *cur = channel_type(tmpctx, channel); + + if (channel_type_eq(cur, type)) + return; + + /* We only allow one upgrade at the moment, so that's it. */ + assert(!channel->option_static_remotekey); + assert(feature_offered(type->features, OPT_STATIC_REMOTEKEY)); + + /* Do upgrade, tell master. */ + channel->option_static_remotekey = true; + status_unusual("Upgraded channel to [%s]", + fmt_featurebits(tmpctx, type->features)); + wire_sync_write(MASTER_FD, take(towire_channeld_upgraded(NULL, true))); +} #else /* !EXPERIMENTAL_FEATURES */ static bool handle_master_request_later(struct peer *peer, const u8 *msg) { @@ -2477,7 +2521,8 @@ static void peer_reconnect(struct peer *peer, &my_current_per_commitment_point, NULL); #if EXPERIMENTAL_FEATURES - send_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx); + /* Subtle: we free tmpctx below as we loop, so tal off peer */ + send_tlvs = tlv_channel_reestablish_tlvs_new(peer); /* BOLT-upgrade_protocol #2: * A node sending `channel_reestablish`, if it supports upgrading channels: * - MUST set `next_to_send` the commitment number of the next @@ -2491,7 +2536,8 @@ static void peer_reconnect(struct peer *peer, * channel. */ if (peer->channel->opener == LOCAL) - send_tlvs->desired_type = channel_type(send_tlvs, peer->channel); + send_tlvs->desired_type = channel_desired_type(send_tlvs, + peer->channel); else { /* BOLT-upgrade_protocol #2: * - otherwise: @@ -2775,6 +2821,71 @@ static void peer_reconnect(struct peer *peer, fmt_featurebits(tmpctx, recv_tlvs->upgradable[i]->features)); } + + /* BOLT-upgrade_protocol #2: + * + * A node receiving `channel_reestablish`: + * - if it has to retransmit `commitment_signed` or `revoke_and_ack`: + * - MUST consider the channel feature change failed. + */ + if (retransmit_commitment_signed || retransmit_revoke_and_ack) { + status_debug("No upgrade: we retransmitted"); + /* BOLT-upgrade_protocol #2: + * + * - if `next_to_send` is missing, or not equal to the + * `next_commitment_number` it sent: + * - MUST consider the channel feature change failed. + */ + } else if (!recv_tlvs->next_to_send) { + status_debug("No upgrade: no next_to_send received"); + } else if (*recv_tlvs->next_to_send != peer->next_index[LOCAL]) { + status_debug("No upgrade: they're retransmitting"); + /* BOLT-upgrade_protocol #2: + * + * - if updates are pending on either sides' commitment transaction: + * - MUST consider the channel feature change failed. + */ + /* Note that we can have HTLCs we *want* to add or remove + * but haven't yet: thats OK! */ + } else if (pending_updates(peer->channel, LOCAL, true) + || pending_updates(peer->channel, REMOTE, true)) { + status_debug("No upgrade: pending changes"); + } else { + const struct tlv_channel_reestablish_tlvs *initr, *ninitr; + const struct channel_type *type; + + if (peer->channel->opener == LOCAL) { + initr = send_tlvs; + ninitr = recv_tlvs; + } else { + initr = recv_tlvs; + ninitr = send_tlvs; + } + + /* BOLT-upgrade_protocol #2: + * + * - if `desired_type` matches `current_type` or any + * `upgradable` `upgrades`: + * - MUST consider the channel type to be `desired_type`. + * - otherwise: + * - MUST consider the channel feature change failed. + * - if there is a `current_type` field: + * - MUST consider the channel type to be `current_type`. + */ + /* Note: returns NULL on missing fields, aka NULL */ + if (match_type(initr->desired_type, + ninitr->current_type, ninitr->upgradable)) + type = initr->desired_type; + else if (ninitr->current_type) + type = ninitr->current_type; + else + type = NULL; + + if (type) + set_channel_type(peer->channel, type); + } + tal_free(send_tlvs); + #endif /* EXPERIMENTAL_FEATURES */ /* Corner case: we didn't send shutdown before because update_add_htlc @@ -3223,6 +3334,7 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_DEV_MEMLEAK_REPLY: case WIRE_CHANNELD_SEND_ERROR_REPLY: case WIRE_CHANNELD_DEV_QUIESCE_REPLY: + case WIRE_CHANNELD_UPGRADED: break; } diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index a376f5a6536f..8af0756a34a1 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -221,3 +221,7 @@ msgtype,channeld_send_error_reply,1108 # Ask channeld to quiesce. msgtype,channeld_dev_quiesce,1009 msgtype,channeld_dev_quiesce_reply,1109 + +# Tell master we're upgrading the commitment tx. +msgtype,channeld_upgraded,1011 +msgdata,channeld_upgraded,option_static_remotekey,bool, diff --git a/channeld/channeld_wiregen.c b/channeld/channeld_wiregen.c index ebf2efcae2f2..0a4d375bc327 100644 --- a/channeld/channeld_wiregen.c +++ b/channeld/channeld_wiregen.c @@ -48,6 +48,7 @@ const char *channeld_wire_name(int e) case WIRE_CHANNELD_SEND_ERROR_REPLY: return "WIRE_CHANNELD_SEND_ERROR_REPLY"; case WIRE_CHANNELD_DEV_QUIESCE: return "WIRE_CHANNELD_DEV_QUIESCE"; case WIRE_CHANNELD_DEV_QUIESCE_REPLY: return "WIRE_CHANNELD_DEV_QUIESCE_REPLY"; + case WIRE_CHANNELD_UPGRADED: return "WIRE_CHANNELD_UPGRADED"; } snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); @@ -85,6 +86,7 @@ bool channeld_wire_is_defined(u16 type) case WIRE_CHANNELD_SEND_ERROR_REPLY:; case WIRE_CHANNELD_DEV_QUIESCE:; case WIRE_CHANNELD_DEV_QUIESCE_REPLY:; + case WIRE_CHANNELD_UPGRADED:; return true; } return false; @@ -1113,4 +1115,26 @@ bool fromwire_channeld_dev_quiesce_reply(const void *p) return false; return cursor != NULL; } -// SHA256STAMP:fa8ee25e2f6082e9889962218e6e345dcb4430840b8f831b40cbb0c415b690b5 + +/* WIRE: CHANNELD_UPGRADED */ +/* Tell master we're upgrading the commitment tx. */ +u8 *towire_channeld_upgraded(const tal_t *ctx, bool option_static_remotekey) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_CHANNELD_UPGRADED); + towire_bool(&p, option_static_remotekey); + + return memcheck(p, tal_count(p)); +} +bool fromwire_channeld_upgraded(const void *p, bool *option_static_remotekey) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_CHANNELD_UPGRADED) + return false; + *option_static_remotekey = fromwire_bool(&cursor, &plen); + return cursor != NULL; +} +// SHA256STAMP:2d7b763e89512ad8c5921b90c13f37ac83ab0016384c38e8c8e831683d668651 diff --git a/channeld/channeld_wiregen.h b/channeld/channeld_wiregen.h index 1b4293a30853..3dde409668f6 100644 --- a/channeld/channeld_wiregen.h +++ b/channeld/channeld_wiregen.h @@ -73,6 +73,8 @@ enum channeld_wire { /* Ask channeld to quiesce. */ WIRE_CHANNELD_DEV_QUIESCE = 1009, WIRE_CHANNELD_DEV_QUIESCE_REPLY = 1109, + /* Tell master we're upgrading the commitment tx. */ + WIRE_CHANNELD_UPGRADED = 1011, }; const char *channeld_wire_name(int e); @@ -223,6 +225,11 @@ bool fromwire_channeld_dev_quiesce(const void *p); u8 *towire_channeld_dev_quiesce_reply(const tal_t *ctx); bool fromwire_channeld_dev_quiesce_reply(const void *p); +/* WIRE: CHANNELD_UPGRADED */ +/* Tell master we're upgrading the commitment tx. */ +u8 *towire_channeld_upgraded(const tal_t *ctx, bool option_static_remotekey); +bool fromwire_channeld_upgraded(const void *p, bool *option_static_remotekey); + #endif /* LIGHTNING_CHANNELD_CHANNELD_WIREGEN_H */ -// SHA256STAMP:fa8ee25e2f6082e9889962218e6e345dcb4430840b8f831b40cbb0c415b690b5 +// SHA256STAMP:2d7b763e89512ad8c5921b90c13f37ac83ab0016384c38e8c8e831683d668651 diff --git a/common/features.c b/common/features.c index 77c8a37addb1..b3d9365a54b3 100644 --- a/common/features.c +++ b/common/features.c @@ -478,6 +478,20 @@ u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES) return result; } +bool featurebits_eq(const u8 *f1, const u8 *f2) +{ + size_t len = tal_bytelen(f1); + + if (tal_bytelen(f2) > len) + len = tal_bytelen(f2); + + for (size_t i = 0; i < len * 8; i++) { + if (feature_is_set(f1, i) != feature_is_set(f2, i)) + return false; + } + return true; +} + struct feature_set *fromwire_feature_set(const tal_t *ctx, const u8 **cursor, size_t *max) { diff --git a/common/features.h b/common/features.h index f51acb59c563..bea34a7f7f10 100644 --- a/common/features.h +++ b/common/features.h @@ -71,6 +71,10 @@ void set_feature_bit(u8 **ptr, u32 bit); /* Given two featurebit vectors, combine them by applying a logical OR. */ u8 *featurebits_or(const tal_t *ctx, const u8 *f1 TAKES, const u8 *f2 TAKES); +/* Are these two feature bitsets functionally equal (one may have + * trailing zeroes)? */ +bool featurebits_eq(const u8 *f1, const u8 *f2); + /* Good for debugging: returns comma-separated string of bits. */ const char *fmt_featurebits(const tal_t *ctx, const u8 *featurebits); diff --git a/common/initial_channel.c b/common/initial_channel.c index e62f49d93b9a..8270f4a1bf16 100644 --- a/common/initial_channel.c +++ b/common/initial_channel.c @@ -197,6 +197,13 @@ struct channel_type **channel_upgradable_types(const tal_t *ctx, return arr; } + +struct channel_type *channel_desired_type(const tal_t *ctx, + const struct channel *channel) +{ + /* For now, we just want option_static_remotekey */ + return type_static_remotekey(ctx); +} #endif /* EXPERIMENTAL_FEATURES */ static char *fmt_channel_view(const tal_t *ctx, const struct channel_view *view) diff --git a/common/initial_channel.h b/common/initial_channel.h index f756cd0b0a21..09f2e86a16b2 100644 --- a/common/initial_channel.h +++ b/common/initial_channel.h @@ -151,6 +151,10 @@ struct channel_type *channel_type(const tal_t *ctx, /* What features can we upgrade? (Returns NULL if none). */ struct channel_type **channel_upgradable_types(const tal_t *ctx, const struct channel *channel); + +/* What features do we want? */ +struct channel_type *channel_desired_type(const tal_t *ctx, + const struct channel *channel); #endif /* EXPERIMENTAL_FEATURES */ #endif /* LIGHTNING_COMMON_INITIAL_CHANNEL_H */ diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 644b3380d491..bf3877484037 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -370,6 +370,29 @@ void forget_channel(struct channel *channel, const char *why) forget(channel); } +#if EXPERIMENTAL_FEATURES +static void handle_channel_upgrade(struct channel *channel, + const u8 *msg) +{ + bool option_static_remotekey; + + if (!fromwire_channeld_upgraded(msg, &option_static_remotekey)) { + channel_internal_error(channel, "bad handle_channel_upgrade: %s", + tal_hex(tmpctx, msg)); + return; + } + + channel->static_remotekey_start[LOCAL] = channel->next_index[LOCAL]; + channel->static_remotekey_start[REMOTE] = channel->next_index[REMOTE]; + log_debug(channel->log, + "option_static_remotekey enabled at %"PRIu64"/%"PRIu64, + channel->static_remotekey_start[LOCAL], + channel->static_remotekey_start[REMOTE]); + + wallet_channel_save(channel->peer->ld->wallet, channel); +} +#endif /* EXPERIMENTAL_FEATURES */ + static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) { enum channeld_wire t = fromwire_peektype(msg); @@ -405,6 +428,13 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_SEND_ERROR_REPLY: handle_error_channel(sd->channel, msg); break; +#if EXPERIMENTAL_FEATURES + case WIRE_CHANNELD_UPGRADED: + handle_channel_upgrade(sd->channel, msg); + break; +#else + case WIRE_CHANNELD_UPGRADED: +#endif /* And we never get these from channeld. */ case WIRE_CHANNELD_INIT: case WIRE_CHANNELD_FUNDING_DEPTH: diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index dccea85484d5..0ac6ceae0287 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -694,8 +694,8 @@ enum watch_result onchaind_funding_spent(struct channel *channel, channel->future_per_commitment_point, &channel->local_funding_pubkey, &channel->channel_info.remote_fundingkey, - /* FIXME! onchaind needs start numbers! */ - channel->static_remotekey_start[LOCAL] == 0, + channel->static_remotekey_start[LOCAL], + channel->static_remotekey_start[REMOTE], channel->option_anchor_outputs, is_replay, feerate_min(ld, NULL)); diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 441bc40c95d7..834b5e80200a 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -84,8 +84,8 @@ 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; +/* At what commit number does option_static_remotekey apply? */ +static u64 static_remotekey_start[NUM_SIDES]; /* Does option_anchor_outputs apply to this commitment tx? */ static bool option_anchor_outputs; @@ -2615,7 +2615,7 @@ static void handle_our_unilateral(const struct tx_parts *tx, if (!derive_keyset(&local_per_commitment_point, &basepoints[LOCAL], &basepoints[REMOTE], - option_static_remotekey, + commit_num >= static_remotekey_start[LOCAL], ks)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Deriving keyset for %"PRIu64, commit_num); @@ -3050,7 +3050,7 @@ static void handle_their_cheat(const struct tx_parts *tx, if (!derive_keyset(remote_per_commitment_point, &basepoints[REMOTE], &basepoints[LOCAL], - option_static_remotekey, + commit_num >= static_remotekey_start[REMOTE], ks)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Deriving keyset for %"PRIu64, commit_num); @@ -3063,7 +3063,7 @@ static void handle_their_cheat(const struct tx_parts *tx, " other_payment_key: %s" " self_htlc_key: %s" " other_htlc_key: %s" - " (option_static_remotekey = %i)", + " (static_remotekey = %"PRIu64"/%"PRIu64")", commit_num, type_to_string(tmpctx, struct pubkey, &keyset->self_revocation_key), @@ -3077,7 +3077,8 @@ static void handle_their_cheat(const struct tx_parts *tx, &keyset->self_htlc_key), type_to_string(tmpctx, struct pubkey, &keyset->other_htlc_key), - option_static_remotekey); + static_remotekey_start[LOCAL], + static_remotekey_start[REMOTE]); remote_wscript = to_self_wscript(tmpctx, to_self_delay[REMOTE], keyset); @@ -3154,7 +3155,7 @@ static void handle_their_cheat(const struct tx_parts *tx, tx_blockheight, script[LOCAL], remote_per_commitment_point, - option_static_remotekey); + commit_num >= static_remotekey_start[REMOTE]); script[LOCAL] = NULL; add_amt(&total_outs, amt); continue; @@ -3334,7 +3335,7 @@ static void handle_their_unilateral(const struct tx_parts *tx, if (!derive_keyset(remote_per_commitment_point, &basepoints[REMOTE], &basepoints[LOCAL], - option_static_remotekey, + commit_num >= static_remotekey_start[REMOTE], ks)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Deriving keyset for %"PRIu64, commit_num); @@ -3434,7 +3435,7 @@ static void handle_their_unilateral(const struct tx_parts *tx, tx_blockheight, script[LOCAL], remote_per_commitment_point, - option_static_remotekey); + commit_num >= static_remotekey_start[REMOTE]); script[LOCAL] = NULL; add_amt(&our_outs, amt); continue; @@ -3634,10 +3635,13 @@ static void handle_unknown_commitment(const struct tx_parts *tx, assert(amount_asset_is_main(&asset)); amt = amount_asset_to_sat(&asset); - if (wally_tx_output_scripteq(tx->outputs[i], local_scripts[0])) + /* Elements can have empty output scripts it seems. */ + if (local_scripts[0] + && wally_tx_output_scripteq(tx->outputs[i], local_scripts[0])) which_script = 0; - else if (wally_tx_output_scripteq(tx->outputs[i], - local_scripts[1])) + else if (local_scripts[1] + && wally_tx_output_scripteq(tx->outputs[i], + local_scripts[1])) which_script = 1; else continue; @@ -3666,8 +3670,8 @@ static void handle_unknown_commitment(const struct tx_parts *tx, local_scripts[which_script], possible_remote_per_commitment_point, which_script == 1); - local_scripts[0] = local_scripts[1] = NULL; to_us_output = i; + break; } if (to_us_output == -1) { @@ -3772,7 +3776,8 @@ int main(int argc, char *argv[]) &possible_remote_per_commitment_point, &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], - &option_static_remotekey, + &static_remotekey_start[LOCAL], + &static_remotekey_start[REMOTE], &option_anchor_outputs, &open_is_replay, &min_relay_feerate)) { diff --git a/onchaind/onchaind_wire.csv b/onchaind/onchaind_wire.csv index d0e88eef2889..926ffb3924de 100644 --- a/onchaind/onchaind_wire.csv +++ b/onchaind/onchaind_wire.csv @@ -46,7 +46,8 @@ msgdata,onchaind_init,max_possible_feerate,u32, msgdata,onchaind_init,possible_remote_per_commit_point,?pubkey, msgdata,onchaind_init,local_funding_pubkey,pubkey, msgdata,onchaind_init,remote_funding_pubkey,pubkey, -msgdata,onchaind_init,option_static_remotekey,bool, +msgdata,onchaind_init,local_static_remotekey_start,u64, +msgdata,onchaind_init,remote_static_remotekey_start,u64, msgdata,onchaind_init,option_anchor_outputs,bool, msgdata,onchaind_init,is_replay,bool, # We need this for BIP125 rule 4 diff --git a/onchaind/onchaind_wiregen.c b/onchaind/onchaind_wiregen.c index 27797ad01bc7..381c0376cdd6 100644 --- a/onchaind/onchaind_wiregen.c +++ b/onchaind/onchaind_wiregen.c @@ -76,7 +76,7 @@ bool onchaind_wire_is_defined(u16 type) /* WIRE: ONCHAIND_INIT */ /* Begin! Here's the onchain tx which spends funding tx */ -u8 *towire_onchaind_init(const tal_t *ctx, const struct shachain *shachain, const struct chainparams *chainparams, struct amount_sat funding_amount_satoshi, struct amount_msat our_msat, const struct pubkey *old_remote_per_commitment_point, const struct pubkey *remote_per_commitment_point, u32 local_to_self_delay, u32 remote_to_self_delay, u32 delayed_to_us_feerate, u32 htlc_feerate, u32 penalty_feerate, struct amount_sat local_dust_limit_satoshi, const struct bitcoin_txid *our_broadcast_txid, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, const struct pubkey *ourwallet_pubkey, enum side opener, const struct basepoints *local_basepoints, const struct basepoints *remote_basepoints, const struct tx_parts *tx_parts, u32 locktime, u32 tx_blockheight, u32 reasonable_depth, const struct bitcoin_signature *htlc_signature, u64 num_htlcs, u32 min_possible_feerate, u32 max_possible_feerate, const struct pubkey *possible_remote_per_commit_point, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, bool option_anchor_outputs, bool is_replay, u32 min_relay_feerate) +u8 *towire_onchaind_init(const tal_t *ctx, const struct shachain *shachain, const struct chainparams *chainparams, struct amount_sat funding_amount_satoshi, struct amount_msat our_msat, const struct pubkey *old_remote_per_commitment_point, const struct pubkey *remote_per_commitment_point, u32 local_to_self_delay, u32 remote_to_self_delay, u32 delayed_to_us_feerate, u32 htlc_feerate, u32 penalty_feerate, struct amount_sat local_dust_limit_satoshi, const struct bitcoin_txid *our_broadcast_txid, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, const struct pubkey *ourwallet_pubkey, enum side opener, const struct basepoints *local_basepoints, const struct basepoints *remote_basepoints, const struct tx_parts *tx_parts, u32 locktime, u32 tx_blockheight, u32 reasonable_depth, const struct bitcoin_signature *htlc_signature, u64 num_htlcs, u32 min_possible_feerate, u32 max_possible_feerate, const struct pubkey *possible_remote_per_commit_point, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, u64 local_static_remotekey_start, u64 remote_static_remotekey_start, bool option_anchor_outputs, bool is_replay, u32 min_relay_feerate) { u16 local_scriptpubkey_len = tal_count(local_scriptpubkey); u16 remote_scriptpubkey_len = tal_count(remote_scriptpubkey); @@ -130,7 +130,8 @@ u8 *towire_onchaind_init(const tal_t *ctx, const struct shachain *shachain, cons } towire_pubkey(&p, local_funding_pubkey); towire_pubkey(&p, remote_funding_pubkey); - towire_bool(&p, option_static_remotekey); + towire_u64(&p, local_static_remotekey_start); + towire_u64(&p, remote_static_remotekey_start); towire_bool(&p, option_anchor_outputs); towire_bool(&p, is_replay); /* We need this for BIP125 rule 4 */ @@ -138,7 +139,7 @@ u8 *towire_onchaind_init(const tal_t *ctx, const struct shachain *shachain, cons return memcheck(p, tal_count(p)); } -bool fromwire_onchaind_init(const tal_t *ctx, const void *p, struct shachain *shachain, const struct chainparams **chainparams, struct amount_sat *funding_amount_satoshi, struct amount_msat *our_msat, struct pubkey *old_remote_per_commitment_point, struct pubkey *remote_per_commitment_point, u32 *local_to_self_delay, u32 *remote_to_self_delay, u32 *delayed_to_us_feerate, u32 *htlc_feerate, u32 *penalty_feerate, struct amount_sat *local_dust_limit_satoshi, struct bitcoin_txid *our_broadcast_txid, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, struct pubkey *ourwallet_pubkey, enum side *opener, struct basepoints *local_basepoints, struct basepoints *remote_basepoints, struct tx_parts **tx_parts, u32 *locktime, u32 *tx_blockheight, u32 *reasonable_depth, struct bitcoin_signature **htlc_signature, u64 *num_htlcs, u32 *min_possible_feerate, u32 *max_possible_feerate, struct pubkey **possible_remote_per_commit_point, struct pubkey *local_funding_pubkey, struct pubkey *remote_funding_pubkey, bool *option_static_remotekey, bool *option_anchor_outputs, bool *is_replay, u32 *min_relay_feerate) +bool fromwire_onchaind_init(const tal_t *ctx, const void *p, struct shachain *shachain, const struct chainparams **chainparams, struct amount_sat *funding_amount_satoshi, struct amount_msat *our_msat, struct pubkey *old_remote_per_commitment_point, struct pubkey *remote_per_commitment_point, u32 *local_to_self_delay, u32 *remote_to_self_delay, u32 *delayed_to_us_feerate, u32 *htlc_feerate, u32 *penalty_feerate, struct amount_sat *local_dust_limit_satoshi, struct bitcoin_txid *our_broadcast_txid, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, struct pubkey *ourwallet_pubkey, enum side *opener, struct basepoints *local_basepoints, struct basepoints *remote_basepoints, struct tx_parts **tx_parts, u32 *locktime, u32 *tx_blockheight, u32 *reasonable_depth, struct bitcoin_signature **htlc_signature, u64 *num_htlcs, u32 *min_possible_feerate, u32 *max_possible_feerate, struct pubkey **possible_remote_per_commit_point, struct pubkey *local_funding_pubkey, struct pubkey *remote_funding_pubkey, u64 *local_static_remotekey_start, u64 *remote_static_remotekey_start, bool *option_anchor_outputs, bool *is_replay, u32 *min_relay_feerate) { u16 local_scriptpubkey_len; u16 remote_scriptpubkey_len; @@ -201,7 +202,8 @@ bool fromwire_onchaind_init(const tal_t *ctx, const void *p, struct shachain *sh } fromwire_pubkey(&cursor, &plen, local_funding_pubkey); fromwire_pubkey(&cursor, &plen, remote_funding_pubkey); - *option_static_remotekey = fromwire_bool(&cursor, &plen); + *local_static_remotekey_start = fromwire_u64(&cursor, &plen); + *remote_static_remotekey_start = fromwire_u64(&cursor, &plen); *option_anchor_outputs = fromwire_bool(&cursor, &plen); *is_replay = fromwire_bool(&cursor, &plen); /* We need this for BIP125 rule 4 */ @@ -635,4 +637,4 @@ bool fromwire_onchaind_notify_coin_mvt(const void *p, struct chain_coin_mvt *mvt fromwire_chain_coin_mvt(&cursor, &plen, mvt); return cursor != NULL; } -// SHA256STAMP:6884d8c13750d6bb08de384fe35050309f8f66037662671c2aad2eaa16f47463 +// SHA256STAMP:66e19538be7f5a9e9076bfe995a9bf0cbb5d303df8f6c383e427c11ef2e85e2e diff --git a/onchaind/onchaind_wiregen.h b/onchaind/onchaind_wiregen.h index 4d53b35f31ea..48692bae739b 100644 --- a/onchaind/onchaind_wiregen.h +++ b/onchaind/onchaind_wiregen.h @@ -69,8 +69,8 @@ bool onchaind_wire_is_defined(u16 type); /* WIRE: ONCHAIND_INIT */ /* Begin! Here's the onchain tx which spends funding tx */ -u8 *towire_onchaind_init(const tal_t *ctx, const struct shachain *shachain, const struct chainparams *chainparams, struct amount_sat funding_amount_satoshi, struct amount_msat our_msat, const struct pubkey *old_remote_per_commitment_point, const struct pubkey *remote_per_commitment_point, u32 local_to_self_delay, u32 remote_to_self_delay, u32 delayed_to_us_feerate, u32 htlc_feerate, u32 penalty_feerate, struct amount_sat local_dust_limit_satoshi, const struct bitcoin_txid *our_broadcast_txid, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, const struct pubkey *ourwallet_pubkey, enum side opener, const struct basepoints *local_basepoints, const struct basepoints *remote_basepoints, const struct tx_parts *tx_parts, u32 locktime, u32 tx_blockheight, u32 reasonable_depth, const struct bitcoin_signature *htlc_signature, u64 num_htlcs, u32 min_possible_feerate, u32 max_possible_feerate, const struct pubkey *possible_remote_per_commit_point, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, bool option_static_remotekey, bool option_anchor_outputs, bool is_replay, u32 min_relay_feerate); -bool fromwire_onchaind_init(const tal_t *ctx, const void *p, struct shachain *shachain, const struct chainparams **chainparams, struct amount_sat *funding_amount_satoshi, struct amount_msat *our_msat, struct pubkey *old_remote_per_commitment_point, struct pubkey *remote_per_commitment_point, u32 *local_to_self_delay, u32 *remote_to_self_delay, u32 *delayed_to_us_feerate, u32 *htlc_feerate, u32 *penalty_feerate, struct amount_sat *local_dust_limit_satoshi, struct bitcoin_txid *our_broadcast_txid, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, struct pubkey *ourwallet_pubkey, enum side *opener, struct basepoints *local_basepoints, struct basepoints *remote_basepoints, struct tx_parts **tx_parts, u32 *locktime, u32 *tx_blockheight, u32 *reasonable_depth, struct bitcoin_signature **htlc_signature, u64 *num_htlcs, u32 *min_possible_feerate, u32 *max_possible_feerate, struct pubkey **possible_remote_per_commit_point, struct pubkey *local_funding_pubkey, struct pubkey *remote_funding_pubkey, bool *option_static_remotekey, bool *option_anchor_outputs, bool *is_replay, u32 *min_relay_feerate); +u8 *towire_onchaind_init(const tal_t *ctx, const struct shachain *shachain, const struct chainparams *chainparams, struct amount_sat funding_amount_satoshi, struct amount_msat our_msat, const struct pubkey *old_remote_per_commitment_point, const struct pubkey *remote_per_commitment_point, u32 local_to_self_delay, u32 remote_to_self_delay, u32 delayed_to_us_feerate, u32 htlc_feerate, u32 penalty_feerate, struct amount_sat local_dust_limit_satoshi, const struct bitcoin_txid *our_broadcast_txid, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, const struct pubkey *ourwallet_pubkey, enum side opener, const struct basepoints *local_basepoints, const struct basepoints *remote_basepoints, const struct tx_parts *tx_parts, u32 locktime, u32 tx_blockheight, u32 reasonable_depth, const struct bitcoin_signature *htlc_signature, u64 num_htlcs, u32 min_possible_feerate, u32 max_possible_feerate, const struct pubkey *possible_remote_per_commit_point, const struct pubkey *local_funding_pubkey, const struct pubkey *remote_funding_pubkey, u64 local_static_remotekey_start, u64 remote_static_remotekey_start, bool option_anchor_outputs, bool is_replay, u32 min_relay_feerate); +bool fromwire_onchaind_init(const tal_t *ctx, const void *p, struct shachain *shachain, const struct chainparams **chainparams, struct amount_sat *funding_amount_satoshi, struct amount_msat *our_msat, struct pubkey *old_remote_per_commitment_point, struct pubkey *remote_per_commitment_point, u32 *local_to_self_delay, u32 *remote_to_self_delay, u32 *delayed_to_us_feerate, u32 *htlc_feerate, u32 *penalty_feerate, struct amount_sat *local_dust_limit_satoshi, struct bitcoin_txid *our_broadcast_txid, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, struct pubkey *ourwallet_pubkey, enum side *opener, struct basepoints *local_basepoints, struct basepoints *remote_basepoints, struct tx_parts **tx_parts, u32 *locktime, u32 *tx_blockheight, u32 *reasonable_depth, struct bitcoin_signature **htlc_signature, u64 *num_htlcs, u32 *min_possible_feerate, u32 *max_possible_feerate, struct pubkey **possible_remote_per_commit_point, struct pubkey *local_funding_pubkey, struct pubkey *remote_funding_pubkey, u64 *local_static_remotekey_start, u64 *remote_static_remotekey_start, bool *option_anchor_outputs, bool *is_replay, u32 *min_relay_feerate); /* WIRE: ONCHAIND_HTLC */ /* This is all the HTLCs: one per message */ @@ -161,4 +161,4 @@ bool fromwire_onchaind_notify_coin_mvt(const void *p, struct chain_coin_mvt *mvt #endif /* LIGHTNING_ONCHAIND_ONCHAIND_WIREGEN_H */ -// SHA256STAMP:6884d8c13750d6bb08de384fe35050309f8f66037662671c2aad2eaa16f47463 +// SHA256STAMP:66e19538be7f5a9e9076bfe995a9bf0cbb5d303df8f6c383e427c11ef2e85e2e diff --git a/onchaind/test/onchainstress-data.gz b/onchaind/test/onchainstress-data.gz index fa43fb21a13e..963d61092f34 100644 Binary files a/onchaind/test/onchainstress-data.gz and b/onchaind/test/onchainstress-data.gz differ diff --git a/onchaind/test/run-grind_feerate-bug.c b/onchaind/test/run-grind_feerate-bug.c index b38812c7558d..f6a77c2ecb62 100644 --- a/onchaind/test/run-grind_feerate-bug.c +++ b/onchaind/test/run-grind_feerate-bug.c @@ -50,7 +50,7 @@ bool fromwire_onchaind_dev_memleak(const void *p UNNEEDED) bool fromwire_onchaind_htlc(const void *p UNNEEDED, struct htlc_stub *htlc UNNEEDED, bool *tell_if_missing UNNEEDED, bool *tell_immediately UNNEEDED) { fprintf(stderr, "fromwire_onchaind_htlc called!\n"); abort(); } /* Generated stub for fromwire_onchaind_init */ -bool fromwire_onchaind_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, u32 *min_relay_feerate UNNEEDED) +bool fromwire_onchaind_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, u64 *local_static_remotekey_start UNNEEDED, u64 *remote_static_remotekey_start UNNEEDED, bool *option_anchor_outputs UNNEEDED, bool *is_replay UNNEEDED, u32 *min_relay_feerate UNNEEDED) { fprintf(stderr, "fromwire_onchaind_init called!\n"); abort(); } /* Generated stub for fromwire_onchaind_known_preimage */ bool fromwire_onchaind_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 6c794b4ad8e1..0a9b3d4ca945 100644 --- a/onchaind/test/run-grind_feerate.c +++ b/onchaind/test/run-grind_feerate.c @@ -54,7 +54,7 @@ bool fromwire_onchaind_dev_memleak(const void *p UNNEEDED) bool fromwire_onchaind_htlc(const void *p UNNEEDED, struct htlc_stub *htlc UNNEEDED, bool *tell_if_missing UNNEEDED, bool *tell_immediately UNNEEDED) { fprintf(stderr, "fromwire_onchaind_htlc called!\n"); abort(); } /* Generated stub for fromwire_onchaind_init */ -bool fromwire_onchaind_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, u32 *min_relay_feerate UNNEEDED) +bool fromwire_onchaind_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, u64 *local_static_remotekey_start UNNEEDED, u64 *remote_static_remotekey_start UNNEEDED, bool *option_anchor_outputs UNNEEDED, bool *is_replay UNNEEDED, u32 *min_relay_feerate UNNEEDED) { fprintf(stderr, "fromwire_onchaind_init called!\n"); abort(); } /* Generated stub for fromwire_onchaind_known_preimage */ bool fromwire_onchaind_known_preimage(const void *p UNNEEDED, struct preimage *preimage UNNEEDED, bool *is_replay UNNEEDED) diff --git a/tests/test_connection.py b/tests/test_connection.py index eb245f9fcb1a..9f099e90f372 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -3300,7 +3300,166 @@ def test_upgrade_statickey(node_factory, executor): l1.daemon.wait_for_logs([r"They sent current_type \[\]", r"They offered upgrade to \[13\]"]) - l2.daemon.wait_for_log(r"They sent desired_type \[\]") + l2.daemon.wait_for_log(r"They sent desired_type \[13\]") + + l1.daemon.wait_for_log('option_static_remotekey enabled at 1/1') + l2.daemon.wait_for_log('option_static_remotekey enabled at 1/1') + + # Make sure it's committed to db! + wait_for(lambda: l1.db_query('SELECT local_static_remotekey_start, remote_static_remotekey_start FROM channels;') == [{'local_static_remotekey_start': 1, 'remote_static_remotekey_start': 1}]) + + # They will consider themselves upgraded. + l1.rpc.disconnect(l2.info['id'], force=True) + # They won't offer upgrade! + assert not l1.daemon.is_in_log("They offered upgrade", + start=l1.daemon.logsearch_start) + l1.daemon.wait_for_log(r"They sent current_type \[13\]") + l2.daemon.wait_for_log(r"They sent desired_type \[13\]") + + +@unittest.skipIf(not EXPERIMENTAL_FEATURES, "upgrade protocol not available") +@pytest.mark.developer("dev-force-features required") +def test_upgrade_statickey_onchaind(node_factory, executor, bitcoind): + """We test penalty before/after, and unilateral before/after""" + l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, + 'dev-force-features': ["-13", "-21"], + # We try to cheat! + 'allow_broken_log': True}, + {'may_reconnect': True}]) + + # TEST 1: Cheat from pre-upgrade. + tx = l1.rpc.dev_sign_last_tx(l2.info['id'])['tx'] + + l1.rpc.disconnect(l2.info['id'], force=True) + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + l1.daemon.wait_for_log('option_static_remotekey enabled at 1/1') + + # Pre-statickey penalty works. + bitcoind.rpc.sendrawtransaction(tx) + bitcoind.generate_block(1) + + l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') + bitcoind.generate_block(100) + wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 0) + + # TEST 2: Cheat from post-upgrade. + node_factory.join_nodes([l1, l2]) + l1.rpc.disconnect(l2.info['id'], force=True) + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + + l1.daemon.wait_for_log('option_static_remotekey enabled at 1/1') + l2.daemon.wait_for_log('option_static_remotekey enabled at 1/1') + + l1.pay(l2, 1000000) + + # We will try to cheat later. + tx = l1.rpc.dev_sign_last_tx(l2.info['id'])['tx'] + + l1.pay(l2, 1000000) + + # Pre-statickey penalty works. + bitcoind.rpc.sendrawtransaction(tx) + bitcoind.generate_block(1) + + l2.wait_for_onchaind_broadcast('OUR_PENALTY_TX', + 'THEIR_REVOKED_UNILATERAL/DELAYED_CHEAT_OUTPUT_TO_THEM') + bitcoind.generate_block(100) + wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 0) + + # TEST 3: Unilateral close from pre-upgrade + node_factory.join_nodes([l1, l2]) + + # Give them both something for onchain close. + l1.pay(l2, 1000000) + + # Make sure it's completely quiescent. + l1.daemon.wait_for_log("chan#3: Removing out HTLC 0 state RCVD_REMOVE_ACK_REVOCATION FULFILLED") + + l1.rpc.disconnect(l2.info['id'], force=True) + l1.daemon.wait_for_log('option_static_remotekey enabled at 3/3') + + # But this is the *pre*-update commit tx! + l2.stop() + l1.rpc.close(l2.info['id'], unilateraltimeout=1) + bitcoind.generate_block(1, wait_for_mempool=1) + l2.start() + + # They should both handle it fine. + l1.daemon.wait_for_log('Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks') + l2.daemon.wait_for_logs(['Ignoring output .*: THEIR_UNILATERAL/OUTPUT_TO_US', + 'Ignoring output .*: THEIR_UNILATERAL/DELAYED_OUTPUT_TO_THEM']) + bitcoind.generate_block(5) + bitcoind.generate_block(100, wait_for_mempool=1) + + wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 0) + + # TEST 4: Unilateral close from post-upgrade + node_factory.join_nodes([l1, l2]) + + l1.rpc.disconnect(l2.info['id'], force=True) + l1.daemon.wait_for_log('option_static_remotekey enabled at 1/1') + + # Move to static_remotekey. + l1.pay(l2, 1000000) + + l2.stop() + l1.rpc.close(l2.info['id'], unilateraltimeout=1) + bitcoind.generate_block(1, wait_for_mempool=1) + l2.start() + + # They should both handle it fine. + l1.daemon.wait_for_log('Propose handling OUR_UNILATERAL/DELAYED_OUTPUT_TO_US by OUR_DELAYED_RETURN_TO_WALLET .* after 5 blocks') + l2.daemon.wait_for_logs(['Ignoring output .*: THEIR_UNILATERAL/OUTPUT_TO_US', + 'Ignoring output .*: THEIR_UNILATERAL/DELAYED_OUTPUT_TO_THEM']) + + bitcoind.generate_block(5) + bitcoind.generate_block(100, wait_for_mempool=1) + + wait_for(lambda: len(l2.rpc.listpeers()['peers']) == 0) + + +@unittest.skipIf(not EXPERIMENTAL_FEATURES, "upgrade protocol not available") +@pytest.mark.developer("dev-force-features, dev-disconnect required") +def test_upgrade_statickey_fail(node_factory, executor, bitcoind): + """We reconnect at all points during retransmit, and we won't upgrade.""" + l1_disconnects = ['-WIRE_COMMITMENT_SIGNED', + '-WIRE_REVOKE_AND_ACK'] + l2_disconnects = ['-WIRE_REVOKE_AND_ACK', + '-WIRE_COMMITMENT_SIGNED', + '=WIRE_UPDATE_FAIL_HTLC-nocommit'] + + l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, + 'dev-no-reconnect': None, + 'disconnect': l1_disconnects, + 'dev-force-features': ["-13", "-21"], + # Don't have feerate changes! + 'feerates': (7500, 7500, 7500, 7500)}, + {'may_reconnect': True, + 'dev-no-reconnect': None, + 'disconnect': l2_disconnects}]) + + # This HTLC will fail + l1.rpc.sendpay([{'msatoshi': 1000, 'id': l2.info['id'], 'delay': 5, 'channel': '1x1x1'}], '00' * 32) + + # Each one should cause one disconnection, no upgrade. + for d in l1_disconnects + l2_disconnects[:-1]: + l1.daemon.wait_for_log('Peer connection lost') + l2.daemon.wait_for_log('Peer connection lost') + assert not l1.daemon.is_in_log('option_static_remotekey enabled') + assert not l2.daemon.is_in_log('option_static_remotekey enabled') + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + + # On the last reconnect, it retransmitted revoke_and_ack. + l1.daemon.wait_for_log('No upgrade: we retransmitted') + l2.daemon.wait_for_log('No upgrade: pending changes') + + # Now when we reconnect, despite having an HTLC, we're quiescent. + l1.rpc.disconnect(l2.info['id'], force=True) + l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + + l1.daemon.wait_for_log('option_static_remotekey enabled at 2/2') + l2.daemon.wait_for_log('option_static_remotekey enabled at 2/2') @unittest.skipIf(not EXPERIMENTAL_FEATURES, "quiescence is experimental")