Browse Source

lightningd/channel: send and receive update_commit

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 8 years ago
parent
commit
82a467f131
  1. 236
      lightningd/channel/channel.c
  2. 2
      lightningd/channel/channel_wire.csv
  3. 5
      lightningd/peer_control.c

236
lightningd/channel/channel.c

@ -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
lightningd/channel/channel_wire.csv

@ -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

Can't render this file because it has a wrong number of fields in line 2.

5
lightningd/peer_control.c

@ -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…
Cancel
Save