Browse Source

lightningd: new peer state CLOSINGD_COMPLETE.

This is a transitional state, while we're waiting to see the
closing tx onchain (which is To Be Implemented).

The simplest way to do re-transmission is to re-use closingd, and just
disallow any updates.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 8 years ago
parent
commit
87232ec25c
  1. 39
      lightningd/peer_control.c
  2. 3
      lightningd/peer_state.h
  3. 18
      tests/test_lightningd.py

39
lightningd/peer_control.c

@ -299,7 +299,8 @@ static bool get_peer_gossipfd_closingd_reply(struct subd *subd, const u8 *msg,
goto close_gossipfd;
}
if (peer->state != CLOSINGD_SIGEXCHANGE) {
if (peer->state != CLOSINGD_SIGEXCHANGE
&& peer->state != CLOSINGD_COMPLETE) {
log_unusual(subd->log, "Gossipd gave fd, but peer %s %s",
type_to_string(ggf, struct pubkey, &ggf->id),
peer_state_name(peer->state));
@ -401,6 +402,7 @@ static bool peer_reconnected(struct lightningd *ld,
return true;
case CLOSINGD_SIGEXCHANGE:
case CLOSINGD_COMPLETE:
/* We need the gossipfd now */
get_gossip_fd_for_closingd_reconnect(ld, id, peer->unique_id, fd, cs);
return true;
@ -1181,6 +1183,18 @@ static int peer_received_closing_signature(struct peer *peer, const u8 *msg)
return -1;
}
/* If we were only doing this to retransmit, we should only send one. */
if (peer->state == CLOSINGD_COMPLETE) {
if (fee_satoshi != peer->closing_fee_sent) {
peer_internal_error(peer,
"CLOSINGD_COMPLETE:"
" Bad offer %"PRIu64
" not %"PRIu64,
fee_satoshi, peer->closing_fee_sent);
return -1;
}
}
/* FIXME: Make sure offer is in useful range! */
/* FIXME: Make sure signature is correct! */
/* FIXME: save to db. */
@ -1207,14 +1221,21 @@ static int peer_offered_closing_signature(struct peer *peer, const u8 *msg)
return -1;
}
/* FIXME: Make sure offer is in useful range! */
/* FIXME: Make sure signature is correct! */
/* FIXME: save to db. */
/* If we were only doing this to retransmit, we ignore its offer. */
if (peer->state == CLOSINGD_COMPLETE) {
log_debug(peer->log,
"CLOSINGD_COMPLETE: Ignoring their offer %"PRIu64,
fee_satoshi);
} else {
/* FIXME: Make sure offer is in useful range! */
/* FIXME: Make sure signature is correct! */
/* FIXME: save to db. */
peer->closing_fee_sent = fee_satoshi;
tal_free(peer->closing_sig_sent);
peer->closing_sig_sent
= tal_dup(peer, secp256k1_ecdsa_signature, &sig);
peer->closing_fee_sent = fee_satoshi;
tal_free(peer->closing_sig_sent);
peer->closing_sig_sent
= tal_dup(peer, secp256k1_ecdsa_signature, &sig);
}
/* OK, you can continue now. */
subd_send_msg(peer->owner,
@ -1285,7 +1306,7 @@ static int peer_closing_complete(struct peer *peer, const u8 *msg)
* if they beat us to the broadcast). */
broadcast_tx(peer->ld->topology, peer, tx, NULL);
/* FIXME: Set state. */
peer_set_condition(peer, CLOSINGD_SIGEXCHANGE, CLOSINGD_COMPLETE);
return -1;
}

3
lightningd/peer_state.h

@ -23,6 +23,9 @@ enum peer_state {
/* Exchanging signatures on closing tx. */
CLOSINGD_SIGEXCHANGE,
/* Waiting for onchain event. */
CLOSINGD_COMPLETE,
/* Various onchain states. */
ONCHAIND_CHEATED,
ONCHAIND_THEIR_UNILATERAL,

18
tests/test_lightningd.py

@ -718,11 +718,12 @@ class LightningDTests(BaseLightningDTests):
l1.daemon.wait_for_log('-> CLOSINGD_SIGEXCHANGE')
l2.daemon.wait_for_log('-> CLOSINGD_SIGEXCHANGE')
# And should put closing into mempool.
l1.daemon.wait_for_log('sendrawtx exit 0')
l2.daemon.wait_for_log('sendrawtx exit 0')
# And should put closing into mempool (happens async, so
# CLOSINGD_COMPLETE may come first).
l1.daemon.wait_for_logs(['sendrawtx exit 0', '-> CLOSINGD_COMPLETE'])
l2.daemon.wait_for_logs(['sendrawtx exit 0', '-> CLOSINGD_COMPLETE'])
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 1
def test_closing_negotiation_reconnect(self):
disconnects = ['-WIRE_CLOSING_SIGNED',
'@WIRE_CLOSING_SIGNED',
@ -744,11 +745,12 @@ class LightningDTests(BaseLightningDTests):
l1.daemon.wait_for_log('-> CLOSINGD_SIGEXCHANGE')
l2.daemon.wait_for_log('-> CLOSINGD_SIGEXCHANGE')
# And should put closing into mempool.
l1.daemon.wait_for_log('sendrawtx exit 0')
l2.daemon.wait_for_log('sendrawtx exit 0')
# And should put closing into mempool (happens async, so
# CLOSINGD_COMPLETE may come first).
l1.daemon.wait_for_logs(['sendrawtx exit 0', '-> CLOSINGD_COMPLETE'])
l2.daemon.wait_for_logs(['sendrawtx exit 0', '-> CLOSINGD_COMPLETE'])
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 1
def test_json_addfunds(self):
sat = 10**6
l1 = self.node_factory.get_node(legacy=False)

Loading…
Cancel
Save