lightningd: update feerate upon receiving revoke_and_ack from fundee.

1. l1     update_fee ->    l2
2. l1 commitment_signed -> l2 (using new feerate)
3. l1  <- revoke_and_ack   l2
4. l1 <- commitment_signed l2 (using new feerate)
5. l1  -> revoke_and_ack   l2

When we break the connection after #3, the reconnection causes #4 to
be retransmitted, but it turns out l1 wasn't telling the master to set
the local feerate until it received the commitment_signed, so on
reconnect it uses the old feerate, with predictable results (bad
signature).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2018-08-22 09:39:57 +09:30 committed by Christian Decker
parent c106fa1b4f
commit 9f175deecd
4 changed files with 19 additions and 6 deletions

View File

@ -1272,7 +1272,7 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
dump_htlcs(peer->channel, "receiving commit_sig"); dump_htlcs(peer->channel, "receiving commit_sig");
peer_failed(&peer->cs, peer_failed(&peer->cs,
&peer->channel_id, &peer->channel_id,
"Bad commit_sig signature %"PRIu64" %s for tx %s wscript %s key %s", "Bad commit_sig signature %"PRIu64" %s for tx %s wscript %s key %s feerate %u",
peer->next_index[LOCAL], peer->next_index[LOCAL],
type_to_string(msg, secp256k1_ecdsa_signature, type_to_string(msg, secp256k1_ecdsa_signature,
&commit_sig), &commit_sig),
@ -1280,7 +1280,8 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
tal_hex(msg, wscripts[0]), tal_hex(msg, wscripts[0]),
type_to_string(msg, struct pubkey, type_to_string(msg, struct pubkey,
&peer->channel->funding_pubkey &peer->channel->funding_pubkey
[REMOTE])); [REMOTE]),
peer->channel->view[LOCAL].feerate_per_kw);
} }
/* BOLT #2: /* BOLT #2:
@ -1332,7 +1333,8 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
static u8 *got_revoke_msg(const tal_t *ctx, u64 revoke_num, static u8 *got_revoke_msg(const tal_t *ctx, u64 revoke_num,
const struct secret *per_commitment_secret, const struct secret *per_commitment_secret,
const struct pubkey *next_per_commit_point, const struct pubkey *next_per_commit_point,
const struct htlc **changed_htlcs) const struct htlc **changed_htlcs,
u32 feerate)
{ {
u8 *msg; u8 *msg;
struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0); struct changed_htlc *changed = tal_arr(tmpctx, struct changed_htlc, 0);
@ -1350,7 +1352,7 @@ static u8 *got_revoke_msg(const tal_t *ctx, u64 revoke_num,
} }
msg = towire_channel_got_revoke(ctx, revoke_num, per_commitment_secret, msg = towire_channel_got_revoke(ctx, revoke_num, per_commitment_secret,
next_per_commit_point, changed); next_per_commit_point, feerate, changed);
return msg; return msg;
} }
@ -1409,7 +1411,8 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg)
/* Tell master about things this locks in, wait for response */ /* Tell master about things this locks in, wait for response */
msg = got_revoke_msg(NULL, peer->revocations_received++, msg = got_revoke_msg(NULL, peer->revocations_received++,
&old_commit_secret, &next_per_commit, &old_commit_secret, &next_per_commit,
changed_htlcs); changed_htlcs,
channel_feerate(peer->channel, LOCAL));
master_wait_sync_reply(tmpctx, peer, take(msg), master_wait_sync_reply(tmpctx, peer, take(msg),
WIRE_CHANNEL_GOT_REVOKE_REPLY); WIRE_CHANNEL_GOT_REVOKE_REPLY);
@ -1749,6 +1752,10 @@ static void resend_commitment(struct peer *peer, const struct changed_htlc *last
struct commit_sigs *commit_sigs; struct commit_sigs *commit_sigs;
u8 *msg; u8 *msg;
status_trace("Retransmitting commitment, feerate LOCAL=%u REMOTE=%u",
channel_feerate(peer->channel, LOCAL),
channel_feerate(peer->channel, REMOTE));
/* BOLT #2: /* BOLT #2:
* *
* - if `next_local_commitment_number` is equal to the commitment * - if `next_local_commitment_number` is equal to the commitment

View File

@ -137,6 +137,7 @@ channel_got_revoke,,revokenum,u64
channel_got_revoke,,per_commitment_secret,struct secret channel_got_revoke,,per_commitment_secret,struct secret
channel_got_revoke,,next_per_commit_point,struct pubkey channel_got_revoke,,next_per_commit_point,struct pubkey
# RCVD_ADD_ACK_REVOCATION, RCVD_REMOVE_ACK_REVOCATION, RCVD_ADD_REVOCATION, RCVD_REMOVE_REVOCATION # RCVD_ADD_ACK_REVOCATION, RCVD_REMOVE_ACK_REVOCATION, RCVD_ADD_REVOCATION, RCVD_REMOVE_REVOCATION
channel_got_revoke,,feerate,u32
channel_got_revoke,,num_changed,u16 channel_got_revoke,,num_changed,u16
channel_got_revoke,,changed,num_changed*struct changed_htlc channel_got_revoke,,changed,num_changed*struct changed_htlc
# Wait for reply, to make sure it's on disk before we continue # Wait for reply, to make sure it's on disk before we continue

1 #include <common/cryptomsg.h>
137 channel_got_shutdown,,scriptpubkey,scriptpubkey_len*u8 channel_got_shutdown,,scriptpubkey_len,u16
138 # Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd. channel_got_shutdown,,scriptpubkey,scriptpubkey_len*u8
139 channel_shutdown_complete,1025 # Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd.
140 channel_shutdown_complete,1025
141 channel_shutdown_complete,,crypto_state,struct crypto_state
142 # Re-enable commit timer.
143 channel_dev_reenable_commit,1026

View File

@ -1283,10 +1283,12 @@ void peer_got_revoke(struct channel *channel, const u8 *msg)
enum onion_type *failcodes; enum onion_type *failcodes;
size_t i; size_t i;
struct lightningd *ld = channel->peer->ld; struct lightningd *ld = channel->peer->ld;
u32 feerate;
if (!fromwire_channel_got_revoke(msg, msg, if (!fromwire_channel_got_revoke(msg, msg,
&revokenum, &per_commitment_secret, &revokenum, &per_commitment_secret,
&next_per_commitment_point, &next_per_commitment_point,
&feerate,
&changed)) { &changed)) {
channel_internal_error(channel, "bad fromwire_channel_got_revoke %s", channel_internal_error(channel, "bad fromwire_channel_got_revoke %s",
tal_hex(channel, msg)); tal_hex(channel, msg));
@ -1345,6 +1347,10 @@ void peer_got_revoke(struct channel *channel, const u8 *msg)
return; return;
} }
/* Update feerate: if we are funder, their revoke_and_ack has set
* this for local feerate. */
channel->channel_info.feerate_per_kw[LOCAL] = feerate;
/* FIXME: Check per_commitment_secret -> per_commit_point */ /* FIXME: Check per_commitment_secret -> per_commit_point */
update_per_commit_point(channel, &next_per_commitment_point); update_per_commit_point(channel, &next_per_commitment_point);

View File

@ -1110,7 +1110,6 @@ def test_fundee_forget_funding_tx_unconfirmed(node_factory, bitcoind):
assert len(l2.rpc.listpeers(l1.info['id'])['peers']) == 0 assert len(l2.rpc.listpeers(l1.info['id'])['peers']) == 0
@pytest.mark.xfail(strict=True)
@unittest.skipIf(not DEVELOPER, "needs --dev-disconnect") @unittest.skipIf(not DEVELOPER, "needs --dev-disconnect")
def test_funder_feerate_reconnect(node_factory, bitcoind): def test_funder_feerate_reconnect(node_factory, bitcoind):
# l1 updates fees, then reconnect so l2 retransmits commitment_signed. # l1 updates fees, then reconnect so l2 retransmits commitment_signed.