|
|
@ -48,6 +48,7 @@ struct peer { |
|
|
|
struct pubkey old_per_commit[NUM_SIDES]; |
|
|
|
struct pubkey current_per_commit[NUM_SIDES]; |
|
|
|
bool funding_locked[NUM_SIDES]; |
|
|
|
u64 commit_index[NUM_SIDES]; |
|
|
|
|
|
|
|
/* Their sig for current commit. */ |
|
|
|
secp256k1_ecdsa_signature their_commit_sig; |
|
|
@ -58,6 +59,9 @@ struct peer { |
|
|
|
/* Our shaseed for generating per-commitment-secrets. */ |
|
|
|
struct sha256 shaseed; |
|
|
|
|
|
|
|
/* Their shachain. */ |
|
|
|
struct shachain their_shachain; |
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A sending node MUST set `id` to 0 for the first HTLC it offers, and |
|
|
@ -279,6 +283,7 @@ static void send_commit(struct peer *peer) |
|
|
|
/* FIXME: Document this requirement in BOLT 2! */ |
|
|
|
/* We can't send two commits in a row. */ |
|
|
|
if (channel_awaiting_revoke_and_ack(peer->channel)) { |
|
|
|
status_trace("Can't send commit: waiting for revoke_and_ack"); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
@ -289,6 +294,7 @@ static void send_commit(struct peer *peer) |
|
|
|
* include any updates. |
|
|
|
*/ |
|
|
|
if (!channel_sending_commit(peer->channel)) { |
|
|
|
status_trace("Can't send commit: nothing to send"); |
|
|
|
tal_free(tmpctx); |
|
|
|
return; |
|
|
|
} |
|
|
@ -369,6 +375,7 @@ static void start_commit_timer(struct peer *peer) |
|
|
|
static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) |
|
|
|
{ |
|
|
|
tal_t *tmpctx = tal_tmpctx(peer); |
|
|
|
struct sha256 old_commit_secret; |
|
|
|
struct channel_id channel_id; |
|
|
|
secp256k1_ecdsa_signature commit_sig, *htlc_sigs; |
|
|
|
struct pubkey remotekey; |
|
|
@ -466,11 +473,124 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) |
|
|
|
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); |
|
|
|
struct pubkey oldpoint = peer->old_per_commit[LOCAL], test; |
|
|
|
status_trace("Sending secret for point %"PRIu64" %s", |
|
|
|
peer->commit_index[LOCAL]-1, |
|
|
|
type_to_string(trc, struct pubkey, |
|
|
|
&peer->old_per_commit[LOCAL])); |
|
|
|
|
|
|
|
peer->old_per_commit[LOCAL] = peer->current_per_commit[LOCAL]; |
|
|
|
if (!next_per_commit_point(&peer->shaseed, &old_commit_secret, |
|
|
|
&peer->current_per_commit[LOCAL], |
|
|
|
peer->commit_index[LOCAL])) |
|
|
|
status_failed(WIRE_CHANNEL_CRYPTO_FAILED, |
|
|
|
"Deriving next commit_point"); |
|
|
|
|
|
|
|
pubkey_from_privkey((struct privkey *)&old_commit_secret, &test); |
|
|
|
if (!pubkey_eq(&test, &oldpoint)) |
|
|
|
status_failed(WIRE_CHANNEL_CRYPTO_FAILED, |
|
|
|
"Invalid secret %s for commit_point", |
|
|
|
tal_hexstr(msg, &old_commit_secret, |
|
|
|
sizeof(old_commit_secret))); |
|
|
|
|
|
|
|
peer->commit_index[LOCAL]++; |
|
|
|
|
|
|
|
/* If this queues more changes on the other end, send commit. */ |
|
|
|
if (channel_sending_revoke_and_ack(peer->channel)) { |
|
|
|
status_trace("revoke_and_ack made pending: commit timer"); |
|
|
|
start_commit_timer(peer); |
|
|
|
} |
|
|
|
|
|
|
|
msg = towire_revoke_and_ack(msg, &channel_id, &old_commit_secret, |
|
|
|
&peer->current_per_commit[LOCAL]); |
|
|
|
msg_enqueue(&peer->peer_out, take(msg)); |
|
|
|
tal_free(tmpctx); |
|
|
|
} |
|
|
|
|
|
|
|
static void our_htlc_failed(const struct htlc *htlc, struct peer *peer) |
|
|
|
{ |
|
|
|
status_trace("FIXME: our htlc %"PRIu64" failed", htlc->id); |
|
|
|
} |
|
|
|
|
|
|
|
static void their_htlc_locked(const struct htlc *htlc, struct peer *peer) |
|
|
|
{ |
|
|
|
status_trace("FIXME: their htlc %"PRIu64" locked", htlc->id); |
|
|
|
} |
|
|
|
|
|
|
|
static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) |
|
|
|
{ |
|
|
|
struct sha256 old_commit_secret; |
|
|
|
struct privkey privkey; |
|
|
|
struct channel_id channel_id; |
|
|
|
struct pubkey per_commit_point, next_per_commit; |
|
|
|
|
|
|
|
if (!fromwire_revoke_and_ack(msg, NULL, &channel_id, &old_commit_secret, |
|
|
|
&next_per_commit)) { |
|
|
|
peer_failed(io_conn_fd(peer->peer_conn), |
|
|
|
&peer->pcs.cs, |
|
|
|
&peer->channel_id, |
|
|
|
WIRE_CHANNEL_PEER_BAD_MESSAGE, |
|
|
|
"Bad revoke_and_ack %s", tal_hex(msg, msg)); |
|
|
|
} |
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A receiving node MUST check that `per-commitment-secret` generates |
|
|
|
* the previous `per-commitment-point`, and MUST fail if it does |
|
|
|
* not. |
|
|
|
*/ |
|
|
|
memcpy(&privkey, &old_commit_secret, sizeof(privkey)); |
|
|
|
if (!pubkey_from_privkey(&privkey, &per_commit_point)) { |
|
|
|
peer_failed(io_conn_fd(peer->peer_conn), |
|
|
|
&peer->pcs.cs, |
|
|
|
&peer->channel_id, |
|
|
|
WIRE_CHANNEL_PEER_BAD_MESSAGE, |
|
|
|
"Bad privkey %s", |
|
|
|
type_to_string(msg, struct privkey, &privkey)); |
|
|
|
} |
|
|
|
if (!pubkey_eq(&per_commit_point, &peer->old_per_commit[REMOTE])) { |
|
|
|
peer_failed(io_conn_fd(peer->peer_conn), |
|
|
|
&peer->pcs.cs, |
|
|
|
&peer->channel_id, |
|
|
|
WIRE_CHANNEL_PEER_BAD_MESSAGE, |
|
|
|
"Wrong privkey %s for %s", |
|
|
|
type_to_string(msg, struct privkey, &privkey), |
|
|
|
type_to_string(msg, struct pubkey, |
|
|
|
&peer->old_per_commit[REMOTE])); |
|
|
|
} |
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
* |
|
|
|
* A receiving node MAY fail if the `per-commitment-secret` was not |
|
|
|
* generated by the protocol in [BOLT #3] |
|
|
|
*/ |
|
|
|
if (!shachain_add_hash(&peer->their_shachain, |
|
|
|
281474976710655ULL - peer->commit_index[REMOTE], |
|
|
|
&old_commit_secret)) { |
|
|
|
peer_failed(io_conn_fd(peer->peer_conn), |
|
|
|
&peer->pcs.cs, |
|
|
|
&peer->channel_id, |
|
|
|
WIRE_CHANNEL_PEER_BAD_MESSAGE, |
|
|
|
"Bad shachain for privkey %"PRIu64" %s ", |
|
|
|
peer->commit_index[REMOTE], |
|
|
|
type_to_string(msg, struct privkey, &privkey)); |
|
|
|
} |
|
|
|
peer->commit_index[REMOTE]++; |
|
|
|
peer->old_per_commit[REMOTE] = peer->current_per_commit[REMOTE]; |
|
|
|
peer->current_per_commit[REMOTE] = next_per_commit; |
|
|
|
|
|
|
|
/* We start timer even if this returns false: we might have delayed
|
|
|
|
* commit because we were waiting for this! */ |
|
|
|
if (channel_rcvd_revoke_and_ack(peer->channel, |
|
|
|
our_htlc_failed, their_htlc_locked, |
|
|
|
peer)) |
|
|
|
status_trace("Commits outstanding after recv revoke_and_ack"); |
|
|
|
else |
|
|
|
status_trace("No commits outstanding after recv revoke_and_ack"); |
|
|
|
|
|
|
|
start_commit_timer(peer); |
|
|
|
} |
|
|
|
|
|
|
|
static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg) |
|
|
|
{ |
|
|
|
enum wire_type type = fromwire_peektype(msg); |
|
|
@ -510,6 +630,9 @@ static struct io_plan *peer_in(struct io_conn *conn, struct peer *peer, u8 *msg) |
|
|
|
case WIRE_COMMITMENT_SIGNED: |
|
|
|
handle_peer_commit_sig(peer, msg); |
|
|
|
goto done; |
|
|
|
case WIRE_REVOKE_AND_ACK: |
|
|
|
handle_peer_revoke_and_ack(peer, msg); |
|
|
|
goto done; |
|
|
|
case WIRE_INIT: |
|
|
|
case WIRE_ERROR: |
|
|
|
case WIRE_OPEN_CHANNEL: |
|
|
@ -523,7 +646,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_REVOKE_AND_ACK: |
|
|
|
case WIRE_UPDATE_FEE: |
|
|
|
peer_failed(io_conn_fd(peer->peer_conn), |
|
|
|
&peer->pcs.cs, |
|
|
@ -593,7 +715,11 @@ static void init_channel(struct peer *peer, const u8 *msg) |
|
|
|
/* We derive everything from the one secret seed. */ |
|
|
|
derive_basepoints(&seed, &funding_pubkey[LOCAL], &points[LOCAL], |
|
|
|
&peer->our_secrets, &peer->shaseed, |
|
|
|
&peer->old_per_commit[LOCAL], 0); |
|
|
|
&peer->old_per_commit[LOCAL], |
|
|
|
peer->commit_index[LOCAL]); |
|
|
|
status_trace("First per_commit_point = %s", |
|
|
|
type_to_string(trc, struct pubkey, |
|
|
|
&peer->old_per_commit[LOCAL])); |
|
|
|
|
|
|
|
peer->channel = new_channel(peer, &funding_txid, funding_txout, |
|
|
|
funding_satoshi, push_msat, feerate, |
|
|
@ -619,7 +745,7 @@ static void handle_funding_locked(struct peer *peer, const u8 *msg) |
|
|
|
|
|
|
|
next_per_commit_point(&peer->shaseed, NULL, |
|
|
|
&peer->current_per_commit[LOCAL], |
|
|
|
0); |
|
|
|
peer->commit_index[LOCAL]++); |
|
|
|
|
|
|
|
msg = towire_funding_locked(peer, |
|
|
|
&peer->channel_id, |
|
|
@ -849,6 +975,8 @@ int main(int argc, char *argv[]) |
|
|
|
peer->htlc_id = 0; |
|
|
|
timers_init(&peer->timers, time_mono()); |
|
|
|
peer->commit_timer = NULL; |
|
|
|
peer->commit_index[LOCAL] = peer->commit_index[REMOTE] = 0; |
|
|
|
shachain_init(&peer->their_shachain); |
|
|
|
|
|
|
|
status_setup_async(&peer->master); |
|
|
|
msg_queue_init(&peer->peer_out, peer); |
|
|
|