mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
lightningd/channel: send and receive update_commit
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
0197353bd9
commit
82a467f131
@ -10,6 +10,7 @@
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <ccan/time/time.h>
|
||||
#include <daemon/routing.h>
|
||||
#include <daemon/timeout.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <lightningd/channel.h>
|
||||
@ -20,6 +21,7 @@
|
||||
#include <lightningd/daemon_conn.h>
|
||||
#include <lightningd/debug.h>
|
||||
#include <lightningd/derive_basepoints.h>
|
||||
#include <lightningd/htlc_tx.h>
|
||||
#include <lightningd/key_derive.h>
|
||||
#include <lightningd/msg_queue.h>
|
||||
#include <lightningd/peer_failed.h>
|
||||
@ -71,6 +73,10 @@ struct peer {
|
||||
struct daemon_conn gossip_client;
|
||||
struct daemon_conn master;
|
||||
|
||||
struct timers timers;
|
||||
struct oneshot *commit_timer;
|
||||
u32 commit_msec;
|
||||
|
||||
/* Announcement related information */
|
||||
struct pubkey node_ids[NUM_SIDES];
|
||||
struct short_channel_id short_channel_ids[NUM_SIDES];
|
||||
@ -254,6 +260,208 @@ static void handle_peer_add_htlc(struct peer *peer, const u8 *msg)
|
||||
"Bad peer_add_htlc: %u", add_err);
|
||||
}
|
||||
|
||||
static void send_commit(struct peer *peer)
|
||||
{
|
||||
tal_t *tmpctx = tal_tmpctx(peer);
|
||||
u8 *msg;
|
||||
secp256k1_ecdsa_signature commit_sig, *htlc_sigs;
|
||||
size_t i;
|
||||
struct bitcoin_tx **txs;
|
||||
const u8 **wscripts;
|
||||
const struct htlc **htlc_map;
|
||||
struct pubkey localkey;
|
||||
struct privkey local_secretkey;
|
||||
|
||||
/* Timer has expired. */
|
||||
peer->commit_timer = NULL;
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT send a `commitment_signed` message which does not
|
||||
* include any updates.
|
||||
*/
|
||||
if (!channel_sent_commit(peer->channel)) {
|
||||
tal_free(tmpctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!derive_simple_privkey(&peer->our_secrets.payment_basepoint_secret,
|
||||
&peer->channel->basepoints[LOCAL].payment,
|
||||
&peer->next_per_commit[REMOTE],
|
||||
&local_secretkey))
|
||||
status_failed(WIRE_CHANNEL_CRYPTO_FAILED,
|
||||
"Deriving local_secretkey");
|
||||
|
||||
if (!derive_simple_key(&peer->channel->basepoints[LOCAL].payment,
|
||||
&peer->next_per_commit[REMOTE],
|
||||
&localkey))
|
||||
status_failed(WIRE_CHANNEL_CRYPTO_FAILED,
|
||||
"Deriving localkey");
|
||||
|
||||
txs = channel_txs(tmpctx, &htlc_map, &wscripts, peer->channel,
|
||||
&peer->next_per_commit[REMOTE], REMOTE);
|
||||
|
||||
sign_tx_input(txs[0], 0, NULL,
|
||||
wscripts[0],
|
||||
&peer->our_secrets.funding_privkey,
|
||||
&peer->channel->funding_pubkey[LOCAL],
|
||||
&commit_sig);
|
||||
|
||||
status_trace("Creating commit_sig signature %s for tx %s wscript %s key %s",
|
||||
type_to_string(trc, secp256k1_ecdsa_signature,
|
||||
&commit_sig),
|
||||
type_to_string(trc, struct bitcoin_tx, txs[0]),
|
||||
tal_hex(trc, wscripts[0]),
|
||||
type_to_string(trc, struct pubkey,
|
||||
&peer->channel->funding_pubkey[LOCAL]));
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST include one `htlc-signature` for every HTLC transaction
|
||||
* corresponding to BIP69 lexicographic ordering of the commitment
|
||||
* transaction.
|
||||
*/
|
||||
htlc_sigs = tal_arr(tmpctx, secp256k1_ecdsa_signature,
|
||||
tal_count(txs) - 1);
|
||||
|
||||
for (i = 0; i < tal_count(htlc_sigs); i++) {
|
||||
sign_tx_input(txs[1 + i], 0,
|
||||
NULL,
|
||||
wscripts[1 + i],
|
||||
&local_secretkey, &localkey,
|
||||
&htlc_sigs[i]);
|
||||
status_trace("Creating HTLC signature %s for tx %s wscript %s key %s",
|
||||
type_to_string(trc, secp256k1_ecdsa_signature,
|
||||
&htlc_sigs[i]),
|
||||
type_to_string(trc, struct bitcoin_tx, txs[1+i]),
|
||||
tal_hex(trc, wscripts[1+i]),
|
||||
type_to_string(trc, struct pubkey, &localkey));
|
||||
assert(check_tx_sig(txs[1+i], 0, NULL, wscripts[1+i],
|
||||
&localkey, &htlc_sigs[i]));
|
||||
}
|
||||
status_trace("Sending commit_sig with %zu htlc sigs",
|
||||
tal_count(htlc_sigs));
|
||||
msg = towire_commitment_signed(tmpctx, &peer->channel_id,
|
||||
&commit_sig, htlc_sigs);
|
||||
msg_enqueue(&peer->peer_out, take(msg));
|
||||
tal_free(tmpctx);
|
||||
}
|
||||
|
||||
static void start_commit_timer(struct peer *peer)
|
||||
{
|
||||
/* Already armed? */
|
||||
if (peer->commit_timer)
|
||||
return;
|
||||
|
||||
peer->commit_timer = new_reltimer(&peer->timers, peer,
|
||||
time_from_msec(peer->commit_msec),
|
||||
send_commit, peer);
|
||||
}
|
||||
|
||||
static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
|
||||
{
|
||||
tal_t *tmpctx = tal_tmpctx(peer);
|
||||
struct channel_id channel_id;
|
||||
secp256k1_ecdsa_signature commit_sig, *htlc_sigs;
|
||||
struct pubkey remotekey;
|
||||
struct bitcoin_tx **txs;
|
||||
const struct htlc **htlc_map;
|
||||
const u8 **wscripts;
|
||||
size_t i;
|
||||
|
||||
if (!channel_rcvd_commit(peer->channel)) {
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A node MUST NOT send a `commitment_signed` message which
|
||||
* does not include any updates.
|
||||
*/
|
||||
peer_failed(io_conn_fd(peer->peer_conn),
|
||||
&peer->pcs.cs,
|
||||
&peer->channel_id,
|
||||
WIRE_CHANNEL_PEER_BAD_MESSAGE,
|
||||
"commit_sig with no changes");
|
||||
}
|
||||
|
||||
if (!fromwire_commitment_signed(tmpctx, msg, NULL,
|
||||
&channel_id, &commit_sig, &htlc_sigs))
|
||||
peer_failed(io_conn_fd(peer->peer_conn),
|
||||
&peer->pcs.cs,
|
||||
&peer->channel_id,
|
||||
WIRE_CHANNEL_PEER_BAD_MESSAGE,
|
||||
"Bad commit_sig %s", tal_hex(msg, msg));
|
||||
|
||||
txs = channel_txs(tmpctx, &htlc_map, &wscripts, peer->channel,
|
||||
&peer->next_per_commit[LOCAL], LOCAL);
|
||||
|
||||
if (!derive_simple_key(&peer->channel->basepoints[REMOTE].payment,
|
||||
&peer->next_per_commit[LOCAL],
|
||||
&remotekey))
|
||||
status_failed(WIRE_CHANNEL_CRYPTO_FAILED,
|
||||
"Deriving remotekey");
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A receiving node MUST fail the channel if `signature` is not valid
|
||||
* for its local commitment transaction once all pending updates are
|
||||
* applied.
|
||||
*/
|
||||
if (!check_tx_sig(txs[0], 0, NULL, wscripts[0],
|
||||
&peer->channel->funding_pubkey[REMOTE], &commit_sig))
|
||||
peer_failed(io_conn_fd(peer->peer_conn),
|
||||
&peer->pcs.cs,
|
||||
&peer->channel_id,
|
||||
WIRE_CHANNEL_PEER_BAD_MESSAGE,
|
||||
"Bad commit_sig signature %s for tx %s wscript %s key %s",
|
||||
type_to_string(msg, secp256k1_ecdsa_signature,
|
||||
&commit_sig),
|
||||
type_to_string(msg, struct bitcoin_tx, txs[0]),
|
||||
tal_hex(msg, wscripts[0]),
|
||||
type_to_string(msg, struct pubkey,
|
||||
&peer->channel->funding_pubkey
|
||||
[REMOTE]));
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A receiving node MUST fail the channel if `num-htlcs` is not equal
|
||||
* to the number of HTLC outputs in the local commitment transaction
|
||||
* once all pending updates are applied.
|
||||
*/
|
||||
if (tal_count(htlc_sigs) != tal_count(txs) - 1)
|
||||
peer_failed(io_conn_fd(peer->peer_conn),
|
||||
&peer->pcs.cs,
|
||||
&peer->channel_id,
|
||||
WIRE_CHANNEL_PEER_BAD_MESSAGE,
|
||||
"Expected %zu htlc sigs, not %zu",
|
||||
tal_count(txs) - 1, tal_count(htlc_sigs));
|
||||
|
||||
/* BOLT #2:
|
||||
*
|
||||
* A receiving node MUST fail
|
||||
* the channel if any `htlc-signature` is not valid for the
|
||||
* corresponding HTLC transaction.
|
||||
*/
|
||||
for (i = 0; i < tal_count(htlc_sigs); i++) {
|
||||
if (!check_tx_sig(txs[1+i], 0, NULL, wscripts[1+i],
|
||||
&remotekey, &htlc_sigs[i]))
|
||||
peer_failed(io_conn_fd(peer->peer_conn),
|
||||
&peer->pcs.cs,
|
||||
&peer->channel_id,
|
||||
WIRE_CHANNEL_PEER_BAD_MESSAGE,
|
||||
"Bad commit_sig signature %s for htlc %s wscript %s key %s",
|
||||
type_to_string(msg, secp256k1_ecdsa_signature, &htlc_sigs[i]),
|
||||
type_to_string(msg, struct bitcoin_tx, txs[1+i]),
|
||||
tal_hex(msg, wscripts[1+i]),
|
||||
type_to_string(msg, struct pubkey, &remotekey));
|
||||
}
|
||||
|
||||
status_trace("Received commit_sig with %zu htlc sigs",
|
||||
tal_count(htlc_sigs));
|
||||
|
||||
/* This may have triggered changes, so restart timer. */
|
||||
start_commit_timer(peer);
|
||||
tal_free(tmpctx);
|
||||
}
|
||||
|
||||
static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg)
|
||||
{
|
||||
enum wire_type type = fromwire_peektype(msg);
|
||||
@ -287,11 +495,12 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg)
|
||||
/* Forward to gossip daemon */
|
||||
daemon_conn_send(&peer->gossip_client, msg);
|
||||
goto done;
|
||||
|
||||
case WIRE_UPDATE_ADD_HTLC:
|
||||
handle_peer_add_htlc(peer, msg);
|
||||
goto done;
|
||||
|
||||
case WIRE_COMMITMENT_SIGNED:
|
||||
handle_peer_commit_sig(peer, msg);
|
||||
goto done;
|
||||
case WIRE_INIT:
|
||||
case WIRE_ERROR:
|
||||
case WIRE_OPEN_CHANNEL:
|
||||
@ -305,7 +514,6 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg)
|
||||
case WIRE_UPDATE_FULFILL_HTLC:
|
||||
case WIRE_UPDATE_FAIL_HTLC:
|
||||
case WIRE_UPDATE_FAIL_MALFORMED_HTLC:
|
||||
case WIRE_COMMITMENT_SIGNED:
|
||||
case WIRE_REVOKE_AND_ACK:
|
||||
case WIRE_UPDATE_FEE:
|
||||
peer_failed(io_conn_fd(peer->peer_conn),
|
||||
@ -368,7 +576,8 @@ static void init_channel(struct peer *peer, const u8 *msg)
|
||||
&feerate, &funding_satoshi, &push_msat,
|
||||
&seed,
|
||||
&peer->node_ids[LOCAL],
|
||||
&peer->node_ids[REMOTE]))
|
||||
&peer->node_ids[REMOTE],
|
||||
&peer->commit_msec))
|
||||
status_failed(WIRE_CHANNEL_BAD_COMMAND, "%s",
|
||||
tal_hex(msg, msg));
|
||||
|
||||
@ -419,11 +628,6 @@ static void handle_funding_announce_depth(struct peer *peer, const u8 *msg)
|
||||
send_announcement_signatures(peer);
|
||||
}
|
||||
|
||||
static void start_commit_timer(struct peer *peer)
|
||||
{
|
||||
/* FIXME! */
|
||||
}
|
||||
|
||||
static void handle_offer_htlc(struct peer *peer, const u8 *inmsg)
|
||||
{
|
||||
u8 *msg;
|
||||
@ -589,6 +793,7 @@ static struct io_plan *req_in(struct io_conn *conn, struct daemon_conn *master)
|
||||
|
||||
case WIRE_CHANNEL_BAD_COMMAND:
|
||||
case WIRE_CHANNEL_HSM_FAILED:
|
||||
case WIRE_CHANNEL_CRYPTO_FAILED:
|
||||
case WIRE_CHANNEL_PEER_WRITE_FAILED:
|
||||
case WIRE_CHANNEL_PEER_READ_FAILED:
|
||||
case WIRE_CHANNEL_RECEIVED_FUNDING_LOCKED:
|
||||
@ -629,6 +834,8 @@ int main(int argc, char *argv[])
|
||||
daemon_conn_init(peer, &peer->master, REQ_FD, req_in);
|
||||
peer->channel = NULL;
|
||||
peer->htlc_id = 0;
|
||||
timers_init(&peer->timers, time_mono());
|
||||
peer->commit_timer = NULL;
|
||||
|
||||
status_setup_async(&peer->master);
|
||||
msg_queue_init(&peer->peer_out, peer);
|
||||
@ -639,8 +846,15 @@ int main(int argc, char *argv[])
|
||||
init_peer_crypto_state(peer, &peer->pcs);
|
||||
peer->funding_locked[LOCAL] = peer->funding_locked[REMOTE] = false;
|
||||
|
||||
/* We don't expect to exit here. */
|
||||
io_loop(NULL, NULL);
|
||||
for (;;) {
|
||||
struct timer *expired = NULL;
|
||||
io_loop(&peer->timers, &expired);
|
||||
|
||||
if (!expired)
|
||||
break;
|
||||
timer_expired(peer, expired);
|
||||
}
|
||||
|
||||
tal_free(peer);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
channel_bad_command,0x8000
|
||||
# Also shouldn't happen
|
||||
channel_hsm_failed,0x8001
|
||||
channel_crypto_failed,0x8002
|
||||
|
||||
# These are due to peer.
|
||||
channel_peer_write_failed,0x8010
|
||||
@ -37,6 +38,7 @@ channel_init,488,push_msat,8
|
||||
channel_init,496,seed,struct privkey
|
||||
channel_init,529,local_node_id,struct pubkey
|
||||
channel_init,562,remote_node_id,struct pubkey
|
||||
channel_init,595,commit_msec,4
|
||||
|
||||
# Tx is deep enough, go!
|
||||
channel_funding_locked,2
|
||||
|
|
@ -640,6 +640,7 @@ static size_t update_channel_status(struct subd *sd,
|
||||
/* We never see fatal ones. */
|
||||
case WIRE_CHANNEL_BAD_COMMAND:
|
||||
case WIRE_CHANNEL_HSM_FAILED:
|
||||
case WIRE_CHANNEL_CRYPTO_FAILED:
|
||||
case WIRE_CHANNEL_PEER_WRITE_FAILED:
|
||||
case WIRE_CHANNEL_PEER_READ_FAILED:
|
||||
case WIRE_CHANNEL_PEER_BAD_MESSAGE:
|
||||
@ -704,7 +705,9 @@ static void peer_start_channeld(struct peer *peer, bool am_funder,
|
||||
peer->push_msat,
|
||||
peer->seed,
|
||||
&peer->ld->dstate.id,
|
||||
peer->id);
|
||||
peer->id,
|
||||
time_to_msec(peer->ld->dstate.config
|
||||
.commit_time));
|
||||
|
||||
/* We don't expect a response: we are triggered by funding_depth_cb. */
|
||||
subd_send_msg(peer->owner, take(msg));
|
||||
|
Loading…
Reference in New Issue
Block a user