Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export EXPERIMENTAL_FEATURES=${EXPERIMENTAL_FEATURES:-0}
export SOURCE_CHECK_ONLY=${SOURCE_CHECK_ONLY:-"false"}
export COMPAT=${COMPAT:-1}
export PATH=$CWD/dependencies/bin:"$HOME"/.local/bin:"$PATH"
export TIMEOUT=180
export PYTEST_PAR=2
export PYTHONPATH=$PWD/contrib/pylightning:$PYTHONPATH
# If we're not in developer mode, tests spend a lot of time waiting for gossip!
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ clean:
find . -name '*gcno' -delete
find . -name '*.nccout' -delete

update-mocks: $(ALL_GEN_HEADERS)
update-mocks/%: %
@MAKE=$(MAKE) tools/update-mocks.sh "$*"

Expand Down
4 changes: 3 additions & 1 deletion channeld/channel_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ msgdata,channel_init,upfront_shutdown_script,u8,upfront_shutdown_script_len
msgdata,channel_init,remote_ann_node_sig,?secp256k1_ecdsa_signature,
msgdata,channel_init,remote_ann_bitcoin_sig,?secp256k1_ecdsa_signature,
msgdata,channel_init,announce_delay,u32,
msgdata,channel_init,option_static_remotekey,bool,

# master->channeld funding hit new depth(funding locked if >= lock depth)
msgtype,channel_funding_depth,1002
Expand Down Expand Up @@ -185,7 +186,8 @@ msgdata,channel_dev_memleak_reply,leak,bool,

# Peer presented proof it was from the future.
msgtype,channel_fail_fallen_behind,1028
msgdata,channel_fail_fallen_behind,remote_per_commitment_point,pubkey,
# This is NULL if option_static_remotekey.
msgdata,channel_fail_fallen_behind,remote_per_commitment_point,?pubkey,

# Handle a channel specific feerate base ppm configuration
msgtype,channel_specific_feerates,1029
Expand Down
100 changes: 82 additions & 18 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -2013,10 +2013,15 @@ static void resend_commitment(struct peer *peer, const struct changed_htlc *last
peer->revocations_received);
}

/* BOLT #2:
/* BOLT-531c8d7d9b01ab610b8a73a0deba1b9e9c83e1ed #2:
*
* A receiving node:
* - if it supports `option_data_loss_protect`, AND the
* - if `option_static_remotekey` applies to the commitment transaction:
* - if `next_revocation_number` is greater than expected above, AND
* `your_last_per_commitment_secret` is correct for that
* `next_revocation_number` minus 1:
*...
* - otherwise, if it supports `option_data_loss_protect`, AND the
* `option_data_loss_protect` fields are present:
* - if `next_revocation_number` is greater than expected above,
* AND `your_last_per_commitment_secret` is correct for that
Expand All @@ -2025,6 +2030,7 @@ static void resend_commitment(struct peer *peer, const struct changed_htlc *last
static void check_future_dataloss_fields(struct peer *peer,
u64 next_revocation_number,
const struct secret *last_local_per_commit_secret,
/* This is NULL if option_static_remotekey */
const struct pubkey *remote_current_per_commitment_point)
{
const u8 *msg;
Expand Down Expand Up @@ -2070,10 +2076,14 @@ static void check_future_dataloss_fields(struct peer *peer,
peer_failed(peer->pps, &peer->channel_id, "Awaiting unilateral close");
}

/* BOLT #2:
/* BOLT-531c8d7d9b01ab610b8a73a0deba1b9e9c83e1ed #2:
*
* A receiving node:
* - if it supports `option_data_loss_protect`, AND the
* - if `option_static_remotekey` applies to the commitment transaction:
* ...
* - if `your_last_per_commitment_secret` does not match the expected values:
* - SHOULD fail the channel.
* - otherwise, if it supports `option_data_loss_protect`, AND the
* `option_data_loss_protect` fields are present:
*...
* - otherwise (`your_last_per_commitment_secret` or
Expand All @@ -2084,6 +2094,7 @@ static void check_current_dataloss_fields(struct peer *peer,
u64 next_revocation_number,
u64 next_commitment_number,
const struct secret *last_local_per_commit_secret,
/* NULL if option_static_remotekey */
const struct pubkey *remote_current_per_commitment_point)
{
struct secret old_commit_secret;
Expand Down Expand Up @@ -2130,6 +2141,11 @@ static void check_current_dataloss_fields(struct peer *peer,
type_to_string(tmpctx, struct secret,
&old_commit_secret));

if (!remote_current_per_commitment_point) {
status_debug("option_static_remotekey: fields are correct");
return;
}

status_debug("Reestablish, comparing commitments. Remote's next local commitment number"
" is %"PRIu64". Our next remote is %"PRIu64" with %"PRIu64
" revocations received",
Expand Down Expand Up @@ -2207,18 +2223,22 @@ static void peer_reconnect(struct peer *peer,
struct pubkey my_current_per_commitment_point,
remote_current_per_commitment_point;
struct secret last_local_per_commitment_secret;
bool dataloss_protect;
bool dataloss_protect, check_extra_fields;
const u8 **premature_msgs = tal_arr(peer, const u8 *, 0);

dataloss_protect = local_feature_negotiated(peer->localfeatures,
LOCAL_DATA_LOSS_PROTECT);

/* Both these options give us extra fields to check. */
check_extra_fields
= dataloss_protect || peer->channel->option_static_remotekey;

/* Our current per-commitment point is the commitment point in the last
* received signed commitment */
get_per_commitment_point(peer->next_index[LOCAL] - 1,
&my_current_per_commitment_point, NULL);

/* BOLT #2:
/* BOLT-531c8d7d9b01ab610b8a73a0deba1b9e9c83e1ed #2:
*
* - upon reconnection:
* - if a channel is in an error state:
Expand All @@ -2234,18 +2254,34 @@ static void peer_reconnect(struct peer *peer,
* of the next `commitment_signed` it expects to receive.
* - MUST set `next_revocation_number` to the commitment number
* of the next `revoke_and_ack` message it expects to receive.
* - if it supports `option_data_loss_protect`:
* - MUST set `my_current_per_commitment_point` to its commitment
* point for the last signed commitment it received from its
* channel peer (i.e. the commitment_point corresponding to the
* commitment transaction the sender would use to unilaterally
* close).
* - if `option_static_remotekey` applies to the commitment transaction:
* - MUST set `my_current_per_commitment_point` to a valid point.
* - otherwise, if it supports `option_data_loss_protect`:
* - MUST set `my_current_per_commitment_point` to its commitment
* point for the last signed commitment it received from its
* channel peer (i.e. the commitment_point corresponding to the
* commitment transaction the sender would use to unilaterally
* close).
* - if `option_static_remotekey` applies to the commitment
* transaction, or the sending node supports
* `option_data_loss_protect`:
* - if `next_revocation_number` equals 0:
* - MUST set `your_last_per_commitment_secret` to all zeroes
* - otherwise:
* - MUST set `your_last_per_commitment_secret` to the last
* `per_commitment_secret` it received
*/
#if EXPERIMENTAL_FEATURES
if (peer->channel->option_static_remotekey) {
msg = towire_channel_reestablish_option_static_remotekey
(NULL, &peer->channel_id,
peer->next_index[LOCAL],
peer->revocations_received,
last_remote_per_commit_secret,
/* Can send any (valid) point here */
&peer->remote_per_commit);
} else
#endif /* EXPERIMENTAL_FEATURES */
if (dataloss_protect) {
msg = towire_channel_reestablish_option_data_loss_protect
(NULL, &peer->channel_id,
Expand Down Expand Up @@ -2273,6 +2309,23 @@ static void peer_reconnect(struct peer *peer,
} while (handle_peer_gossip_or_error(peer->pps, &peer->channel_id, msg)
|| capture_premature_msg(&premature_msgs, msg));

#if EXPERIMENTAL_FEATURES
if (peer->channel->option_static_remotekey) {
struct pubkey ignore;
if (!fromwire_channel_reestablish_option_static_remotekey(msg,
&channel_id,
&next_commitment_number,
&next_revocation_number,
&last_local_per_commitment_secret,
&ignore)) {
peer_failed(peer->pps,
&peer->channel_id,
"bad reestablish static_remotekey msg: %s %s",
wire_type_name(fromwire_peektype(msg)),
tal_hex(msg, msg));
}
} else
#endif /* EXPERIMENTAL_FEATURES */
if (dataloss_protect) {
if (!fromwire_channel_reestablish_option_data_loss_protect(msg,
&channel_id,
Expand Down Expand Up @@ -2361,9 +2414,10 @@ static void peer_reconnect(struct peer *peer,
next_revocation_number,
peer->next_index[LOCAL]);
} else if (next_revocation_number > peer->next_index[LOCAL] - 1) {
if (!dataloss_protect)
/* They don't support option_data_loss_protect, we
* fail it due to unexpected number */
if (!check_extra_fields)
/* They don't support option_data_loss_protect or
* option_static_remotekey, we fail it due to
* unexpected number */
peer_failed(peer->pps,
&peer->channel_id,
"bad reestablish revocation_number: %"PRIu64
Expand All @@ -2376,6 +2430,7 @@ static void peer_reconnect(struct peer *peer,
check_future_dataloss_fields(peer,
next_revocation_number,
&last_local_per_commitment_secret,
peer->channel->option_static_remotekey ? NULL :
&remote_current_per_commitment_point);
} else
retransmit_revoke_and_ack = false;
Expand Down Expand Up @@ -2418,12 +2473,14 @@ static void peer_reconnect(struct peer *peer,
retransmit_commitment_signed = false;

/* After we checked basic sanity, we check dataloss fields if any */
if (dataloss_protect)
if (check_extra_fields)
check_current_dataloss_fields(peer,
next_revocation_number,
next_commitment_number,
&last_local_per_commitment_secret,
&remote_current_per_commitment_point);
peer->channel->option_static_remotekey
? NULL
: &remote_current_per_commitment_point);

/* We have to re-send in the same order we sent originally:
* revoke_and_ack (usually) alters our next commitment. */
Expand Down Expand Up @@ -2866,6 +2923,7 @@ static void init_channel(struct peer *peer)
struct secret last_remote_per_commit_secret;
secp256k1_ecdsa_signature *remote_ann_node_sig;
secp256k1_ecdsa_signature *remote_ann_bitcoin_sig;
bool option_static_remotekey;

assert(!(fcntl(MASTER_FD, F_GETFL) & O_NONBLOCK));

Expand Down Expand Up @@ -2924,7 +2982,8 @@ static void init_channel(struct peer *peer)
&peer->remote_upfront_shutdown_script,
&remote_ann_node_sig,
&remote_ann_bitcoin_sig,
&peer->announce_delay)) {
&peer->announce_delay,
&option_static_remotekey)) {
master_badmsg(WIRE_CHANNEL_INIT, msg);
}
/* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = HSM */
Expand All @@ -2945,6 +3004,10 @@ static void init_channel(struct peer *peer)
feerate_per_kw[LOCAL], feerate_per_kw[REMOTE],
peer->feerate_min, peer->feerate_max);

#if EXPERIMENTAL_FEATURES
status_debug("option_static_remotekey = %u", option_static_remotekey);
#endif

if(remote_ann_node_sig && remote_ann_bitcoin_sig) {
peer->announcement_node_sigs[REMOTE] = *remote_ann_node_sig;
peer->announcement_bitcoin_sigs[REMOTE] = *remote_ann_bitcoin_sig;
Expand Down Expand Up @@ -2980,6 +3043,7 @@ static void init_channel(struct peer *peer)
&points[LOCAL], &points[REMOTE],
&funding_pubkey[LOCAL],
&funding_pubkey[REMOTE],
option_static_remotekey,
funder);

if (!channel_force_htlcs(peer->channel, htlcs, hstates,
Expand Down
3 changes: 3 additions & 0 deletions channeld/full_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct channel *new_full_channel(const tal_t *ctx,
const struct basepoints *remote_basepoints,
const struct pubkey *local_funding_pubkey,
const struct pubkey *remote_funding_pubkey,
bool option_static_remotekey,
enum side funder)
{
struct channel *channel = new_initial_channel(ctx,
Expand All @@ -61,6 +62,7 @@ struct channel *new_full_channel(const tal_t *ctx,
remote_basepoints,
local_funding_pubkey,
remote_funding_pubkey,
option_static_remotekey,
funder);

if (channel) {
Expand Down Expand Up @@ -271,6 +273,7 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx,
if (!derive_keyset(per_commitment_point,
&channel->basepoints[side],
&channel->basepoints[!side],
channel->option_static_remotekey,
&keyset))
return NULL;

Expand Down
2 changes: 2 additions & 0 deletions channeld/full_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* @remote_basepoints: remote basepoints.
* @local_fundingkey: local funding key
* @remote_fundingkey: remote funding key
* @option_static_remotekey: use `option_static_remotekey`.
* @funder: which side initiated it.
*
* Returns state, or NULL if malformed.
Expand All @@ -42,6 +43,7 @@ struct channel *new_full_channel(const tal_t *ctx,
const struct basepoints *remote_basepoints,
const struct pubkey *local_funding_pubkey,
const struct pubkey *remote_funding_pubkey,
bool option_static_remotekey,
enum side funder);

/**
Expand Down
4 changes: 2 additions & 2 deletions channeld/test/run-full_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ int main(void)
&localbase, &remotebase,
&local_funding_pubkey,
&remote_funding_pubkey,
LOCAL);
false, LOCAL);
rchannel = new_full_channel(tmpctx,
&chainparams->genesis_blockhash,
&funding_txid, funding_output_index, 0,
Expand All @@ -484,7 +484,7 @@ int main(void)
&remotebase, &localbase,
&remote_funding_pubkey,
&local_funding_pubkey,
REMOTE);
false, REMOTE);

/* BOLT #3:
*
Expand Down
6 changes: 4 additions & 2 deletions common/features.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ static const u32 our_localfeatures[] = {
OPTIONAL_FEATURE(LOCAL_UPFRONT_SHUTDOWN_SCRIPT),
OPTIONAL_FEATURE(LOCAL_GOSSIP_QUERIES),
#if EXPERIMENTAL_FEATURES
OPTIONAL_FEATURE(LOCAL_GOSSIP_QUERIES_EX)
OPTIONAL_FEATURE(LOCAL_GOSSIP_QUERIES_EX),
OPTIONAL_FEATURE(LOCAL_STATIC_REMOTEKEY),
#endif
};

Expand Down Expand Up @@ -160,7 +161,8 @@ static const char *feature_name(const tal_t *ctx, size_t f)
"option_upfront_shutdown_script",
"option_gossip_queries",
"option_var_onion_optin",
"option_gossip_queries_ex" };
"option_gossip_queries_ex",
"option_static_remotekey" };

assert(f / 2 < ARRAY_SIZE(fnames));
return tal_fmt(ctx, "%s/%s",
Expand Down
6 changes: 4 additions & 2 deletions common/features.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const char **list_supported_features(const tal_t *ctx);
bool feature_is_set(const u8 *features, size_t bit);
void set_feature_bit(u8 **ptr, u32 bit);

/* BOLT #9:
/* BOLT-531c8d7d9b01ab610b8a73a0deba1b9e9c83e1ed #9:
*
* Flags are numbered from the least-significant bit, at bit 0 (i.e. 0x1,
* an _even_ bit). They are generally assigned in pairs so that features
Expand All @@ -36,7 +36,7 @@ void set_feature_bit(u8 **ptr, u32 bit);
#define COMPULSORY_FEATURE(x) ((x) & 0xFFFFFFFE)
#define OPTIONAL_FEATURE(x) ((x) | 1)

/* BOLT #9:
/* BOLT-531c8d7d9b01ab610b8a73a0deba1b9e9c83e1ed #9:
*
* ## Assigned `localfeatures` flags
*...
Expand All @@ -45,11 +45,13 @@ void set_feature_bit(u8 **ptr, u32 bit);
* | 3 | `initial_routing_sync` |...
* | 4/5 | `option_upfront_shutdown_script` |...
* | 6/7 | `gossip_queries` |...
* | 12/13| `option_static_remotekey` |...
*/
#define LOCAL_DATA_LOSS_PROTECT 0
#define LOCAL_INITIAL_ROUTING_SYNC 2
#define LOCAL_UPFRONT_SHUTDOWN_SCRIPT 4
#define LOCAL_GOSSIP_QUERIES 6
#define LOCAL_STATIC_REMOTEKEY 12

/* BOLT-927c96daab2338b716708a57cd75c84a2d169e0e #9:
* | Bits | Name |...
Expand Down
5 changes: 4 additions & 1 deletion common/initial_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct channel *new_initial_channel(const tal_t *ctx,
const struct basepoints *remote_basepoints,
const struct pubkey *local_funding_pubkey,
const struct pubkey *remote_funding_pubkey,
bool option_static_remotekey,
enum side funder)
{
struct channel *channel = tal(ctx, struct channel);
Expand Down Expand Up @@ -65,6 +66,7 @@ struct channel *new_initial_channel(const tal_t *ctx,
if (channel->chainparams == NULL)
return tal_free(channel);

channel->option_static_remotekey = option_static_remotekey;
return channel;
}

Expand All @@ -84,7 +86,8 @@ struct bitcoin_tx *initial_channel_tx(const tal_t *ctx,
if (!derive_keyset(per_commitment_point,
&channel->basepoints[side],
&channel->basepoints[!side],
&keyset)){
channel->option_static_remotekey,
&keyset)) {
*err_reason = "Cannot derive keyset";
return NULL;
}
Expand Down
Loading