Skip to content

Commit

Permalink
common/channel_type: wrapper for generated 'struct channel_type'.
Browse files Browse the repository at this point in the history
We make it a first-class citizen internally, even though we won't use
it over the wire (at least, non-experimental builds).  This scheme
follows the latest draft, in which features are flagged compulsory.

We also add several helper functions.

Since uses the *even* bits (as per latest spec), not the *odd* bits,
we have some other fixups.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
rustyrussell authored and cdecker committed Sep 13, 2021
1 parent 1b85519 commit cb22015
Show file tree
Hide file tree
Showing 74 changed files with 404 additions and 122 deletions.
1 change: 1 addition & 0 deletions channeld/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ CHANNELD_COMMON_OBJS := \
common/blockheight_states.o \
common/channel_config.o \
common/channel_id.o \
common/channel_type.o \
common/crypto_state.o \
common/crypto_sync.o \
common/cryptomsg.o \
Expand Down
20 changes: 5 additions & 15 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
#include <common/billboard.h>
#include <common/blinding.h>
#include <common/bolt12.h>
#include <common/channel_type.h>
#include <common/coin_mvt.h>
#include <common/crypto_sync.h>
#include <common/dev_disconnect.h>
#include <common/ecdh_hsmd.h>
#include <common/features.h>
#include <common/gossip_constants.h>
#include <common/gossip_store.h>
#include <common/htlc_tx.h>
Expand Down Expand Up @@ -360,12 +360,6 @@ static bool handle_master_request_later(struct peer *peer, const u8 *msg)
return false;
}

static bool channel_type_eq(const struct channel_type *a,
const struct channel_type *b)
{
return featurebits_eq(a->features, b->features);
}

static bool match_type(const struct channel_type *desired,
const struct channel_type *current,
struct channel_type **upgradable)
Expand All @@ -377,18 +371,13 @@ static bool match_type(const struct channel_type *desired,
if (channel_type_eq(desired, current))
return true;

for (size_t i = 0; i < tal_count(upgradable); i++) {
if (channel_type_eq(desired, upgradable[i]))
return true;
}

return false;
return channel_type_eq_any(desired, upgradable);
}

static void set_channel_type(struct channel *channel,
const struct channel_type *type)
{
const struct channel_type *cur = channel_type(tmpctx, channel);
const struct channel_type *cur = current_channel_type(tmpctx, channel);

if (channel_type_eq(cur, type))
return;
Expand Down Expand Up @@ -2744,7 +2733,8 @@ static void peer_reconnect(struct peer *peer,
* to.
* - MAY not set `upgradable` if it would be empty.
*/
send_tlvs->current_type = channel_type(send_tlvs, peer->channel);
send_tlvs->current_type
= current_channel_type(send_tlvs, peer->channel);
send_tlvs->upgradable = channel_upgradable_types(send_tlvs,
peer->channel);
}
Expand Down
2 changes: 1 addition & 1 deletion channeld/channeld_wiregen.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion channeld/channeld_wiregen.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions channeld/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ALL_TEST_PROGRAMS += $(CHANNELD_TEST_PROGRAMS)

CHANNELD_TEST_COMMON_OBJS := \
common/amount.o \
common/channel_type.o \
common/daemon_conn.o \
common/htlc_state.o \
common/htlc_trim.o \
Expand Down
17 changes: 17 additions & 0 deletions channeld/test/run-commit_tx.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <inttypes.h>
#include <stdio.h>
#include <common/channel_type.h>
#include <common/type_to_string.h>
static bool print_superverbose;
#define SUPERVERBOSE(...) \
Expand All @@ -22,6 +23,19 @@ static bool print_superverbose;
/*#define DEBUG */

/* AUTOGENERATED MOCKS START */
/* Generated stub for feature_is_set */
bool feature_is_set(const u8 *features UNNEEDED, size_t bit UNNEEDED)
{ fprintf(stderr, "feature_is_set called!\n"); abort(); }
/* Generated stub for feature_negotiated */
bool feature_negotiated(const struct feature_set *our_features UNNEEDED,
const u8 *their_features UNNEEDED, size_t f UNNEEDED)
{ fprintf(stderr, "feature_negotiated called!\n"); abort(); }
/* Generated stub for feature_offered */
bool feature_offered(const u8 *features UNNEEDED, size_t f UNNEEDED)
{ fprintf(stderr, "feature_offered called!\n"); abort(); }
/* Generated stub for featurebits_eq */
bool featurebits_eq(const u8 *f1 UNNEEDED, const u8 *f2 UNNEEDED)
{ fprintf(stderr, "featurebits_eq called!\n"); abort(); }
/* Generated stub for fromwire_bigsize */
bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_bigsize called!\n"); abort(); }
Expand All @@ -32,6 +46,9 @@ void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for set_feature_bit */
void set_feature_bit(u8 **ptr UNNEEDED, u32 bit UNNEEDED)
{ fprintf(stderr, "set_feature_bit called!\n"); abort(); }
/* Generated stub for status_fmt */
void status_fmt(enum log_level level UNNEEDED,
const struct node_id *peer UNNEEDED,
Expand Down
13 changes: 13 additions & 0 deletions channeld/test/run-full_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@
#include <wally_core.h>

/* AUTOGENERATED MOCKS START */
/* Generated stub for feature_is_set */
bool feature_is_set(const u8 *features UNNEEDED, size_t bit UNNEEDED)
{ fprintf(stderr, "feature_is_set called!\n"); abort(); }
/* Generated stub for feature_negotiated */
bool feature_negotiated(const struct feature_set *our_features UNNEEDED,
const u8 *their_features UNNEEDED, size_t f UNNEEDED)
{ fprintf(stderr, "feature_negotiated called!\n"); abort(); }
/* Generated stub for feature_offered */
bool feature_offered(const u8 *features UNNEEDED, size_t f UNNEEDED)
{ fprintf(stderr, "feature_offered called!\n"); abort(); }
/* Generated stub for featurebits_eq */
bool featurebits_eq(const u8 *f1 UNNEEDED, const u8 *f2 UNNEEDED)
{ fprintf(stderr, "featurebits_eq called!\n"); abort(); }
/* Generated stub for fromwire_bigsize */
bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_bigsize called!\n"); abort(); }
Expand Down
2 changes: 1 addition & 1 deletion closingd/closingd_wiregen.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion closingd/closingd_wiregen.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ COMMON_SRC_NOGEN := \
common/bolt12_merkle.c \
common/channel_config.c \
common/channel_id.c \
common/channel_type.c \
common/coin_mvt.c \
common/close_tx.c \
common/configdir.c \
Expand Down
143 changes: 143 additions & 0 deletions common/channel_type.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include <ccan/array_size/array_size.h>
#include <common/channel_type.h>

/* BOLT-channel-types #2:
* Channel types are an explicit enumeration: for convenience of future
* definitions they reuse even feature bits, but they are not an
* arbitrary combination (they represent the persistent features which
* affect the channel operation).
*
* The currently defined types are:
* - no features (no bits set)
* - `option_static_remotekey` (bit 12)
* - `option_anchor_outputs` and `option_static_remotekey` (bits 20 and 12)
* - `option_anchors_zero_fee_htlc_tx` and `option_static_remotekey` (bits 22
* and 12)
*/
struct channel_type *channel_type_none(const tal_t *ctx)
{
struct channel_type *type = tal(ctx, struct channel_type);

type->features = tal_arr(type, u8, 0);
return type;
}

struct channel_type *channel_type_static_remotekey(const tal_t *ctx)
{
struct channel_type *type = channel_type_none(ctx);

set_feature_bit(&type->features,
COMPULSORY_FEATURE(OPT_STATIC_REMOTEKEY));
return type;
}

struct channel_type *channel_type_anchor_outputs(const tal_t *ctx)
{
struct channel_type *type = channel_type_none(ctx);

set_feature_bit(&type->features,
COMPULSORY_FEATURE(OPT_ANCHOR_OUTPUTS));
set_feature_bit(&type->features,
COMPULSORY_FEATURE(OPT_STATIC_REMOTEKEY));
return type;
}

struct channel_type *default_channel_type(const tal_t *ctx,
const struct feature_set *our_features,
const u8 *their_features)
{
/* BOLT-channel-types #2:
* Both peers:
* - if `channel_type` was present in both `open_channel` and `accept_channel`:
* - This is the `channel_type` (they must be equal, required above)
* - otherwise:
*/
/* BOLT-channel-types #2:
* - otherwise, if `option_anchor_outputs` was negotiated:
* - the `channel_type` is `option_anchor_outputs` and
* `option_static_remotekey` (bits 20 and 12)
*/
if (feature_negotiated(our_features, their_features,
OPT_ANCHOR_OUTPUTS))
return channel_type_anchor_outputs(ctx);
/* BOLT-channel-types #2:
* - otherwise, if `option_static_remotekey` was negotiated:
* - the `channel_type` is `option_static_remotekey` (bit 12)
*/
else if (feature_negotiated(our_features, their_features,
OPT_STATIC_REMOTEKEY))
return channel_type_static_remotekey(ctx);
/* BOLT-channel-types #2:
* - otherwise:
* - the `channel_type` is empty
*/
else
return channel_type_none(ctx);
}

bool channel_type_has(const struct channel_type *type, int feature)
{
return feature_offered(type->features, feature);
}

bool channel_type_eq(const struct channel_type *a,
const struct channel_type *b)
{
return featurebits_eq(a->features, b->features);
}

bool channel_type_eq_any(const struct channel_type *t,
struct channel_type **arr)
{
for (size_t i = 0; i < tal_count(arr); i++) {
if (channel_type_eq(t, arr[i]))
return true;
}
return false;
}

struct channel_type *channel_type_dup(const tal_t *ctx,
const struct channel_type *t)
{
struct channel_type *ret = tal(ctx, struct channel_type);
ret->features = tal_dup_talarr(ret, u8, t->features);
return ret;
}

struct channel_type *channel_type_accept(const tal_t *ctx,
const u8 *t,
const struct feature_set *our_features,
const u8 *their_features)
{
struct channel_type *ctype;
static const size_t feats[] = { OPT_ANCHOR_OUTPUTS,
OPT_STATIC_REMOTEKEY };

for (size_t i = 0; i < ARRAY_SIZE(feats); i++) {
size_t f = feats[i];

if (feature_offered(t, f)) {
/* If we don't offer a feature, we don't allow it. */
if (!feature_offered(our_features->bits[INIT_FEATURE], f))
return NULL;
} else {
/* We assume that if we *require* a feature, we require
* channels have that. */
if (feature_is_set(our_features->bits[INIT_FEATURE],
COMPULSORY_FEATURE(f)))
return NULL;
}
}

/* Otherwise, just needs to be a known channel type. */
ctype = channel_type_none(tmpctx);
if (featurebits_eq(t, ctype->features))
return tal_steal(ctx, ctype);
ctype = channel_type_static_remotekey(tmpctx);
if (featurebits_eq(t, ctype->features))
return tal_steal(ctx, ctype);
ctype = channel_type_anchor_outputs(tmpctx);
if (featurebits_eq(t, ctype->features))
return tal_steal(ctx, ctype);
return NULL;
}
38 changes: 38 additions & 0 deletions common/channel_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* This represents a channel type: i.e. the sticky feature bits. */
#ifndef LIGHTNING_COMMON_CHANNEL_TYPE_H
#define LIGHTNING_COMMON_CHANNEL_TYPE_H
#include "config.h"
#include <common/features.h>
#include <wire/channel_type_wiregen.h>

/* Explicit channel types */
struct channel_type *channel_type_none(const tal_t *ctx);
struct channel_type *channel_type_static_remotekey(const tal_t *ctx);
struct channel_type *channel_type_anchor_outputs(const tal_t *ctx);

/* Duplicate a channel_type */
struct channel_type *channel_type_dup(const tal_t *ctx,
const struct channel_type *t);

/* Derive channel type from feature negotiation */
struct channel_type *default_channel_type(const tal_t *ctx,
const struct feature_set *our_features,
const u8 *their_features);

/* Does this type include this feature? */
bool channel_type_has(const struct channel_type *type, int feature);

/* Are these two channel_types equivalent? */
bool channel_type_eq(const struct channel_type *a,
const struct channel_type *b);

/* Is channel_type_eq() for any type in this array? */
bool channel_type_eq_any(const struct channel_type *t,
struct channel_type **arr);

/* Return channel_type if this is acceptable, otherwise NULL */
struct channel_type *channel_type_accept(const tal_t *ctx,
const u8 *t,
const struct feature_set *our_features,
const u8 *their_features);
#endif /* LIGHTNING_COMMON_CHANNEL_TYPE_H */
Loading

0 comments on commit cb22015

Please sign in to comment.