Skip to content

Commit

Permalink
hsmd: implement the hsmd outpoint check
Browse files Browse the repository at this point in the history
Tihis commit is implementing a 2-phase commit between
the signer the node and the peer.

The main reason for this is that everybody must agree on the lock,
otherwise one of them will want N signatures (on the splice candidates),
and another will produce only 1 signature.

check_outpoint is the "prepare" for the signer, and lock_outpoint is the
"commit". if check_outpoint returns true, lock_outpoint must not fail.

Link: #6722
Suggested-by: @devrandom
Co-Developed-by: Ken Sedgwick <[email protected]>
Signed-off-by: Vincenzo Palazzo <[email protected]>
  • Loading branch information
ksedgwic authored and rustyrussell committed Oct 26, 2023
1 parent 485cabb commit 44798e2
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 3 deletions.
46 changes: 46 additions & 0 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,48 @@ static bool channel_announcement_negotiate(struct peer *peer)
return sent_announcement;
}

static void lock_signer_outpoint(const struct bitcoin_outpoint *outpoint)
{
const u8 *msg;
bool is_buried = false;

/* FIXME(vincenzopalazzo): Sleeping in a deamon of cln should be never fine
* howerver the core deamon of cln will never trigger the sleep.
*
* I think that the correct solution for this is a timer base solution, but this
* required a little bit of refactoring */
do {
/* Make sure the hsmd agrees that this outpoint is
* sufficiently buried. */
msg = towire_hsmd_check_outpoint(NULL, &outpoint->txid, outpoint->n);
msg = hsm_req(tmpctx, take(msg));
if (!fromwire_hsmd_check_outpoint_reply(msg, &is_buried))
status_failed(STATUS_FAIL_HSM_IO,
"Bad hsmd_check_outpoint_reply: %s",
tal_hex(tmpctx, msg));

/* the signer should have a shorter buried height requirement so
* it almost always will be ready ahead of us.*/
if (!is_buried)
sleep(10);
} while (!is_buried);

/* tell the signer that we are now locked */
msg = towire_hsmd_lock_outpoint(NULL, &outpoint->txid, outpoint->n);
msg = hsm_req(tmpctx, take(msg));
if (!fromwire_hsmd_lock_outpoint_reply(msg))
status_failed(STATUS_FAIL_HSM_IO,
"Bad hsmd_lock_outpoint_reply: %s",
tal_hex(tmpctx, msg));
}

/* Call this method when channel_ready status are changed. */
static void check_mutual_channel_ready(const struct peer *peer)
{
if (peer->channel_ready[LOCAL] && peer->channel_ready[REMOTE])
lock_signer_outpoint(&peer->channel->funding);
}

/* Call this method when splice_locked status are changed. If both sides have
* splice_locked'ed than this function consumes the `splice_locked_ready` values
* and considers the channel funding to be switched to the splice tx. */
Expand Down Expand Up @@ -733,6 +775,9 @@ static void check_mutual_splice_locked(struct peer *peer)
status_debug("mutual splice_locked, channel updated to: %s",
type_to_string(tmpctx, struct channel, peer->channel));

/* ensure the signer is locking at the same time */
lock_signer_outpoint(&inflight->outpoint);

msg = towire_channeld_got_splice_locked(NULL, inflight->amnt,
inflight->splice_amnt,
&inflight->outpoint.txid);
Expand Down Expand Up @@ -808,6 +853,7 @@ static void handle_peer_channel_ready(struct peer *peer, const u8 *msg)

peer->tx_sigs_allowed = false;
peer->channel_ready[REMOTE] = true;
check_mutual_channel_ready(peer);
if (tlvs->short_channel_id != NULL) {
status_debug(
"Peer told us that they'll use alias=%s for this channel",
Expand Down
3 changes: 2 additions & 1 deletion lightningd/channel_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,8 @@ bool peer_start_channeld(struct channel *channel,
| HSM_PERM_SIGN_REMOTE_TX
| HSM_PERM_SIGN_ONCHAIN_TX
| HSM_PERM_SIGN_CLOSING_TX
| HSM_PERM_SIGN_SPLICE_TX);
| HSM_PERM_SIGN_SPLICE_TX
| HSM_PERM_LOCK_OUTPOINT);

channel_set_owner(channel,
new_channel_subd(channel, ld,
Expand Down
6 changes: 4 additions & 2 deletions lightningd/dual_open_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -3809,7 +3809,8 @@ bool peer_start_dualopend(struct peer *peer,
hsmfd = hsm_get_client_fd(peer->ld, &peer->id, channel->unsaved_dbid,
HSM_PERM_COMMITMENT_POINT
| HSM_PERM_SIGN_REMOTE_TX
| HSM_PERM_SIGN_WILL_FUND_OFFER);
| HSM_PERM_SIGN_WILL_FUND_OFFER
| HSM_PERM_LOCK_OUTPOINT);

channel->owner = new_channel_subd(channel,
peer->ld,
Expand Down Expand Up @@ -3881,7 +3882,8 @@ bool peer_restart_dualopend(struct peer *peer,
hsmfd = hsm_get_client_fd(peer->ld, &peer->id, channel->dbid,
HSM_PERM_COMMITMENT_POINT
| HSM_PERM_SIGN_REMOTE_TX
| HSM_PERM_SIGN_WILL_FUND_OFFER);
| HSM_PERM_SIGN_WILL_FUND_OFFER
| HSM_PERM_LOCK_OUTPOINT);

channel_set_owner(channel,
new_channel_subd(channel, peer->ld,
Expand Down
47 changes: 47 additions & 0 deletions openingd/dualopend.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,51 @@ static void billboard_update(struct state *state)
peer_billboard(false, update);
}

static void lock_signer_outpoint(const struct bitcoin_outpoint *outpoint)
{
const u8 *msg;
bool is_buried = false;


/* FIXME(vincenzopalazzo): Sleeping in a deamon of cln should be never fine
* howerver the core deamon of cln will never trigger the sleep.
*
* I think that the correct solution for this is a timer base solution, but this
* required to implement all the timers in the deamon. */
do {
/* Make sure the hsmd agrees that this outpoint is
* sufficiently buried. */
msg = towire_hsmd_check_outpoint(NULL, &outpoint->txid, outpoint->n);
wire_sync_write(HSM_FD, take(msg));
msg = wire_sync_read(tmpctx, HSM_FD);
if (!fromwire_hsmd_check_outpoint_reply(msg, &is_buried))
status_failed(STATUS_FAIL_HSM_IO,
"Bad hsmd_check_outpoint_reply: %s",
tal_hex(tmpctx, msg));

/* the signer should have a shorter buried height requirement so
* it almost always will be ready ahead of us.*/
if (!is_buried)
sleep(10);
} while (!is_buried);

/* tell the signer that we are now locked */
msg = towire_hsmd_lock_outpoint(NULL, &outpoint->txid, outpoint->n);
wire_sync_write(HSM_FD, take(msg));
msg = wire_sync_read(tmpctx, HSM_FD);
if (!fromwire_hsmd_lock_outpoint_reply(msg))
status_failed(STATUS_FAIL_HSM_IO,
"Bad hsmd_lock_outpoint_reply: %s",
tal_hex(tmpctx, msg));
}

/* Call this method when channel_ready status are changed. */
static void check_mutual_channel_ready(const struct state *state)
{
if (state->channel_ready[LOCAL] && state->channel_ready[REMOTE])
lock_signer_outpoint(&state->channel->funding);
}

static void send_shutdown(struct state *state, const u8 *final_scriptpubkey)
{
u8 *msg;
Expand Down Expand Up @@ -1265,6 +1310,7 @@ static u8 *handle_channel_ready(struct state *state, u8 *msg)
}

state->channel_ready[REMOTE] = true;
check_mutual_channel_ready(state);
billboard_update(state);

if (state->channel_ready[LOCAL])
Expand Down Expand Up @@ -3789,6 +3835,7 @@ static void send_channel_ready(struct state *state)
peer_write(state->pps, take(msg));

state->channel_ready[LOCAL] = true;
check_mutual_channel_ready(state);
billboard_update(state);
}

Expand Down

0 comments on commit 44798e2

Please sign in to comment.