short_channel_id_dir: new primitive for one direction of short_channel_id

Currently only used by gossipd for channel elimination.

Also print them in canonical form (/[01]), so tests need to be
changed.

Suggested-by: @cdecker
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2019-01-15 14:41:27 +10:30
committed by Christian Decker
parent 80753bfbd5
commit 9f1f79587e
16 changed files with 109 additions and 69 deletions

View File

@@ -61,3 +61,29 @@ char *short_channel_id_to_str(const tal_t *ctx, const struct short_channel_id *s
short_channel_id_txnum(scid), short_channel_id_txnum(scid),
short_channel_id_outnum(scid)); short_channel_id_outnum(scid));
} }
bool short_channel_id_dir_from_str(const char *str, size_t strlen,
struct short_channel_id_dir *scidd)
{
const char *slash = memchr(str, '/', strlen);
if (!slash || slash + 2 != str + strlen)
return false;
if (!short_channel_id_from_str(str, slash - str, &scidd->scid))
return false;
if (slash[1] == '0')
scidd->dir = 0;
else if (slash[1] == '1')
scidd->dir = 1;
else
return false;
return true;
}
char *short_channel_id_dir_to_str(const tal_t *ctx,
const struct short_channel_id_dir *scidd)
{
char *str, *scidstr = short_channel_id_to_str(NULL, &scidd->scid);
str = tal_fmt(ctx, "%s/%u", scidstr, scidd->dir);
tal_free(scidstr);
return str;
}

View File

@@ -15,6 +15,23 @@ struct short_channel_id {
/* Define short_channel_id_eq (no padding) */ /* Define short_channel_id_eq (no padding) */
STRUCTEQ_DEF(short_channel_id, 0, u64); STRUCTEQ_DEF(short_channel_id, 0, u64);
/* BOLT #7:
*
* - MUST set `node_id_1` and `node_id_2` to the public keys of the two nodes
* operating the channel, such that `node_id_1` is the numerically-lesser of the
* two DER-encoded keys sorted in ascending numerical order.
*...
* - if the origin node is `node_id_1` in the message:
* - MUST set the `direction` bit of `channel_flags` to 0.
* - otherwise:
* - MUST set the `direction` bit of `channel_flags` to 1.
*/
struct short_channel_id_dir {
struct short_channel_id scid;
/* 0 == from lesser id node, 1 == to lesser id node */
int dir;
};
static inline u32 short_channel_id_blocknum(const struct short_channel_id *scid) static inline u32 short_channel_id_blocknum(const struct short_channel_id *scid)
{ {
return scid->u64 >> 40; return scid->u64 >> 40;
@@ -38,4 +55,10 @@ bool short_channel_id_from_str(const char *str, size_t strlen,
char *short_channel_id_to_str(const tal_t *ctx, const struct short_channel_id *scid); char *short_channel_id_to_str(const tal_t *ctx, const struct short_channel_id *scid);
bool short_channel_id_dir_from_str(const char *str, size_t strlen,
struct short_channel_id_dir *scidd);
char *short_channel_id_dir_to_str(const tal_t *ctx,
const struct short_channel_id_dir *scidd);
#endif /* LIGHTNING_BITCOIN_SHORT_CHANNEL_ID_H */ #endif /* LIGHTNING_BITCOIN_SHORT_CHANNEL_ID_H */

View File

@@ -24,6 +24,7 @@ union printable_types {
const secp256k1_pubkey *secp256k1_pubkey; const secp256k1_pubkey *secp256k1_pubkey;
const struct channel_id *channel_id; const struct channel_id *channel_id;
const struct short_channel_id *short_channel_id; const struct short_channel_id *short_channel_id;
const struct short_channel_id_dir *short_channel_id_dir;
const struct secret *secret; const struct secret *secret;
const struct privkey *privkey; const struct privkey *privkey;
const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature; const secp256k1_ecdsa_signature *secp256k1_ecdsa_signature;

View File

@@ -33,8 +33,7 @@ gossip_getroute_request,,riskfactor,u16
gossip_getroute_request,,final_cltv,u32 gossip_getroute_request,,final_cltv,u32
gossip_getroute_request,,fuzz,double gossip_getroute_request,,fuzz,double
gossip_getroute_request,,num_excluded,u16 gossip_getroute_request,,num_excluded,u16
gossip_getroute_request,,excluded,num_excluded*struct short_channel_id gossip_getroute_request,,excluded,num_excluded*struct short_channel_id_dir
gossip_getroute_request,,excluded_dir,num_excluded*bool
gossip_getroute_request,,max_hops,u32 gossip_getroute_request,,max_hops,u32
gossip_getroute_reply,3106 gossip_getroute_reply,3106
1 #include <common/cryptomsg.h>
33 gossip_getroute_request,,excluded_dir,num_excluded*bool gossip_getroute_request,,max_hops,u32
34 gossip_getroute_request,,max_hops,u32 gossip_getroute_reply,3106
35 gossip_getroute_reply,3106 gossip_getroute_reply,,num_hops,u16
36 gossip_getroute_reply,,num_hops,u16 gossip_getroute_reply,,hops,num_hops*struct route_hop
gossip_getroute_reply,,hops,num_hops*struct route_hop
37 gossip_getchannels_request,3007
38 gossip_getchannels_request,,short_channel_id,?struct short_channel_id
39 gossip_getchannels_request,,source,?struct pubkey

View File

@@ -1871,8 +1871,7 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
u8 *out; u8 *out;
struct route_hop *hops; struct route_hop *hops;
double fuzz; double fuzz;
struct short_channel_id *excluded; struct short_channel_id_dir *excluded;
bool *excluded_dir;
/* To choose between variations, we need to know how much we're /* To choose between variations, we need to know how much we're
* sending (eliminates too-small channels, and also effects the fees * sending (eliminates too-small channels, and also effects the fees
@@ -1884,7 +1883,7 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
&source, &destination, &source, &destination,
&msatoshi, &riskfactor, &msatoshi, &riskfactor,
&final_cltv, &fuzz, &final_cltv, &fuzz,
&excluded, &excluded_dir, &excluded,
&max_hops)) &max_hops))
master_badmsg(WIRE_GOSSIP_GETROUTE_REQUEST, msg); master_badmsg(WIRE_GOSSIP_GETROUTE_REQUEST, msg);
@@ -1895,7 +1894,7 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
/* routing.c does all the hard work; can return NULL. */ /* routing.c does all the hard work; can return NULL. */
hops = get_route(tmpctx, daemon->rstate, &source, &destination, hops = get_route(tmpctx, daemon->rstate, &source, &destination,
msatoshi, riskfactor, final_cltv, msatoshi, riskfactor, final_cltv,
fuzz, siphash_seed(), excluded, excluded_dir, max_hops); fuzz, siphash_seed(), excluded, max_hops);
out = towire_gossip_getroute_reply(NULL, hops); out = towire_gossip_getroute_reply(NULL, hops);
daemon_conn_send(daemon->master, take(out)); daemon_conn_send(daemon->master, take(out));

View File

@@ -1003,7 +1003,7 @@ static void update_pending(struct pending_cannouncement *pending,
u32 timestamp, const u8 *update, u32 timestamp, const u8 *update,
const u8 direction) const u8 direction)
{ {
SUPERVERBOSE("Deferring update for pending channel %s(%d)", SUPERVERBOSE("Deferring update for pending channel %s/%d",
type_to_string(tmpctx, struct short_channel_id, type_to_string(tmpctx, struct short_channel_id,
&pending->short_channel_id), direction); &pending->short_channel_id), direction);
@@ -1043,12 +1043,12 @@ static void set_connection_values(struct chan *chan,
/* If it was temporarily unroutable, re-enable */ /* If it was temporarily unroutable, re-enable */
c->unroutable_until = 0; c->unroutable_until = 0;
SUPERVERBOSE("Channel %s(%d) was updated.", SUPERVERBOSE("Channel %s/%d was updated.",
type_to_string(tmpctx, struct short_channel_id, &chan->scid), type_to_string(tmpctx, struct short_channel_id, &chan->scid),
idx); idx);
if (c->proportional_fee >= MAX_PROPORTIONAL_FEE) { if (c->proportional_fee >= MAX_PROPORTIONAL_FEE) {
status_trace("Channel %s(%d) massive proportional fee %u:" status_trace("Channel %s/%d massive proportional fee %u:"
" disabling.", " disabling.",
type_to_string(tmpctx, struct short_channel_id, type_to_string(tmpctx, struct short_channel_id,
&chan->scid), &chan->scid),
@@ -1272,7 +1272,7 @@ u8 *handle_channel_update(struct routing_state *rstate, const u8 *update TAKES,
return err; return err;
} }
status_trace("Received channel_update for channel %s(%d) now %s was %s (from %s)", status_trace("Received channel_update for channel %s/%d now %s was %s (from %s)",
type_to_string(tmpctx, struct short_channel_id, type_to_string(tmpctx, struct short_channel_id,
&short_channel_id), &short_channel_id),
channel_flags & 0x01, channel_flags & 0x01,
@@ -1506,8 +1506,7 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
const u64 msatoshi, double riskfactor, const u64 msatoshi, double riskfactor,
u32 final_cltv, u32 final_cltv,
double fuzz, const struct siphash_seed *base_seed, double fuzz, const struct siphash_seed *base_seed,
const struct short_channel_id *excluded, const struct short_channel_id_dir *excluded,
const bool *excluded_dir,
size_t max_hops) size_t max_hops)
{ {
struct chan **route; struct chan **route;
@@ -1518,17 +1517,16 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
struct node *n; struct node *n;
u64 *saved_capacity; u64 *saved_capacity;
assert(tal_count(excluded) == tal_count(excluded_dir));
saved_capacity = tal_arr(tmpctx, u64, tal_count(excluded)); saved_capacity = tal_arr(tmpctx, u64, tal_count(excluded));
/* Temporarily set excluded channels' capacity to zero. */ /* Temporarily set excluded channels' capacity to zero. */
for (size_t i = 0; i < tal_count(excluded); i++) { for (size_t i = 0; i < tal_count(excluded); i++) {
struct chan *chan = get_channel(rstate, &excluded[i]); struct chan *chan = get_channel(rstate, &excluded[i].scid);
if (!chan) if (!chan)
continue; continue;
saved_capacity[i] saved_capacity[i]
= chan->half[excluded_dir[i]].htlc_maximum_msat; = chan->half[excluded[i].dir].htlc_maximum_msat;
chan->half[excluded_dir[i]].htlc_maximum_msat = 0; chan->half[excluded[i].dir].htlc_maximum_msat = 0;
} }
route = find_route(ctx, rstate, source, destination, msatoshi, route = find_route(ctx, rstate, source, destination, msatoshi,
@@ -1537,10 +1535,10 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
/* Now restore the capacity. */ /* Now restore the capacity. */
for (size_t i = 0; i < tal_count(excluded); i++) { for (size_t i = 0; i < tal_count(excluded); i++) {
struct chan *chan = get_channel(rstate, &excluded[i]); struct chan *chan = get_channel(rstate, &excluded[i].scid);
if (!chan) if (!chan)
continue; continue;
chan->half[excluded_dir[i]].htlc_maximum_msat chan->half[excluded[i].dir].htlc_maximum_msat
= saved_capacity[i]; = saved_capacity[i];
} }

View File

@@ -268,8 +268,7 @@ struct route_hop *get_route(const tal_t *ctx, struct routing_state *rstate,
u32 final_cltv, u32 final_cltv,
double fuzz, double fuzz,
const struct siphash_seed *base_seed, const struct siphash_seed *base_seed,
const struct short_channel_id *excluded, const struct short_channel_id_dir *excluded,
const bool *excluded_dir,
size_t max_hops); size_t max_hops);
/* Disable channel(s) based on the given routing failure. */ /* Disable channel(s) based on the given routing failure. */
void routing_failure(struct routing_state *rstate, void routing_failure(struct routing_state *rstate,

View File

@@ -292,27 +292,6 @@ static void json_getroute_reply(struct subd *gossip UNUSED, const u8 *reply, con
was_pending(command_success(cmd, response)); was_pending(command_success(cmd, response));
} }
static bool json_to_short_channel_id_with_dir(const char *buffer,
const jsmntok_t *tok,
struct short_channel_id *scid,
bool *dir)
{
/* Ends in /0 or /1 */
if (tok->end - tok->start < 2)
return false;
if (buffer[tok->end - 2] != '/')
return false;
if (buffer[tok->end - 1] == '0')
*dir = false;
else if (buffer[tok->end - 1] == '1')
*dir = true;
else
return false;
return short_channel_id_from_str(buffer + tok->start,
tok->end - tok->start - 2, scid);
}
static struct command_result *json_getroute(struct command *cmd, static struct command_result *json_getroute(struct command *cmd,
const char *buffer, const char *buffer,
const jsmntok_t *obj UNNEEDED, const jsmntok_t *obj UNNEEDED,
@@ -325,8 +304,7 @@ static struct command_result *json_getroute(struct command *cmd,
u64 *msatoshi; u64 *msatoshi;
unsigned *cltv; unsigned *cltv;
double *riskfactor; double *riskfactor;
struct short_channel_id *excluded; struct short_channel_id_dir *excluded;
bool *excluded_dir;
u32 *max_hops; u32 *max_hops;
/* Higher fuzz means that some high-fee paths can be discounted /* Higher fuzz means that some high-fee paths can be discounted
@@ -356,16 +334,15 @@ static struct command_result *json_getroute(struct command *cmd,
const jsmntok_t *t, *end = json_next(excludetok); const jsmntok_t *t, *end = json_next(excludetok);
size_t i; size_t i;
excluded = tal_arr(cmd, struct short_channel_id, excluded = tal_arr(cmd, struct short_channel_id_dir,
excludetok->size); excludetok->size);
excluded_dir = tal_arr(cmd, bool, excludetok->size);
for (i = 0, t = excludetok + 1; for (i = 0, t = excludetok + 1;
t < end; t < end;
t = json_next(t), i++) { t = json_next(t), i++) {
if (!json_to_short_channel_id_with_dir(buffer, t, if (!short_channel_id_dir_from_str(buffer + t->start,
&excluded[i], t->end - t->start,
&excluded_dir[i])) { &excluded[i])) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS, return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%.*s is not a valid" "%.*s is not a valid"
" short_channel_id/direction", " short_channel_id/direction",
@@ -375,13 +352,12 @@ static struct command_result *json_getroute(struct command *cmd,
} }
} else { } else {
excluded = NULL; excluded = NULL;
excluded_dir = NULL;
} }
u8 *req = towire_gossip_getroute_request(cmd, source, destination, u8 *req = towire_gossip_getroute_request(cmd, source, destination,
*msatoshi, *riskfactor * 1000, *msatoshi, *riskfactor * 1000,
*cltv, fuzz, *cltv, fuzz,
excluded, excluded_dir, excluded,
*max_hops); *max_hops);
subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd); subd_req(ld->gossip, ld->gossip, req, -1, 0, json_getroute_reply, cmd);
return command_still_pending(cmd); return command_still_pending(cmd);

View File

@@ -557,7 +557,7 @@ static struct command_result *json_pay_try(struct pay *pay)
pay->msatoshi + overpayment, pay->msatoshi + overpayment,
pay->riskfactor, pay->riskfactor,
pay->min_final_cltv_expiry, pay->min_final_cltv_expiry,
&pay->fuzz, NULL, NULL, &pay->fuzz, NULL,
ROUTING_MAX_HOPS); ROUTING_MAX_HOPS);
subd_req(pay->try_parent, cmd->ld->gossip, req, -1, 0, json_pay_getroute_reply, pay); subd_req(pay->try_parent, cmd->ld->gossip, req, -1, 0, json_pay_getroute_reply, pay);

View File

@@ -1446,23 +1446,23 @@ def test_restart_many_payments(node_factory):
l1_logs = [] l1_logs = []
for i in range(len(innodes)): for i in range(len(innodes)):
scid = inchans[i] scid = inchans[i]
l1_logs += [r'update for channel {}\(0\) now ACTIVE'.format(scid), l1_logs += [r'update for channel {}/0 now ACTIVE'.format(scid),
r'update for channel {}\(1\) now ACTIVE'.format(scid), r'update for channel {}/1 now ACTIVE'.format(scid),
'to CHANNELD_NORMAL'] 'to CHANNELD_NORMAL']
innodes[i].daemon.wait_for_logs([r'update for channel {}\(0\) now ACTIVE' innodes[i].daemon.wait_for_logs([r'update for channel {}/0 now ACTIVE'
.format(scid), .format(scid),
r'update for channel {}\(1\) now ACTIVE' r'update for channel {}/1 now ACTIVE'
.format(scid), .format(scid),
'to CHANNELD_NORMAL']) 'to CHANNELD_NORMAL'])
for i in range(len(outnodes)): for i in range(len(outnodes)):
scid = outchans[i] scid = outchans[i]
l1_logs += [r'update for channel {}\(0\) now ACTIVE'.format(scid), l1_logs += [r'update for channel {}/0 now ACTIVE'.format(scid),
r'update for channel {}\(1\) now ACTIVE'.format(scid), r'update for channel {}/1 now ACTIVE'.format(scid),
'to CHANNELD_NORMAL'] 'to CHANNELD_NORMAL']
outnodes[i].daemon.wait_for_logs([r'update for channel {}\(0\) now ACTIVE' outnodes[i].daemon.wait_for_logs([r'update for channel {}/0 now ACTIVE'
.format(scid), .format(scid),
r'update for channel {}\(1\) now ACTIVE' r'update for channel {}/1 now ACTIVE'
.format(scid), .format(scid),
'to CHANNELD_NORMAL']) 'to CHANNELD_NORMAL'])

View File

@@ -978,9 +978,9 @@ def test_getroute_exclude(node_factory, bitcoind):
bitcoind.generate_block(5) bitcoind.generate_block(5)
# We don't wait above, because we care about it hitting l1. # We don't wait above, because we care about it hitting l1.
l1.daemon.wait_for_logs([r'update for channel {}\(0\) now ACTIVE' l1.daemon.wait_for_logs([r'update for channel {}/0 now ACTIVE'
.format(scid), .format(scid),
r'update for channel {}\(1\) now ACTIVE' r'update for channel {}/1 now ACTIVE'
.format(scid)]) .format(scid)])
# l3 id is > l2 id, so 1 means l3->l2 # l3 id is > l2 id, so 1 means l3->l2

View File

@@ -151,7 +151,7 @@ def test_pay_get_error_with_update(node_factory):
l1.daemon.wait_for_log(r'Extracted channel_update 0102.*from onionreply 10070088[0-9a-fA-F]{88}') l1.daemon.wait_for_log(r'Extracted channel_update 0102.*from onionreply 10070088[0-9a-fA-F]{88}')
# And now monitor for l1 to apply the channel_update we just extracted # And now monitor for l1 to apply the channel_update we just extracted
l1.daemon.wait_for_log(r'Received channel_update for channel {}\(.\) now DISABLED was ACTIVE \(from error\)'.format(chanid2)) l1.daemon.wait_for_log(r'Received channel_update for channel {}/. now DISABLED was ACTIVE \(from error\)'.format(chanid2))
def test_pay_optional_args(node_factory): def test_pay_optional_args(node_factory):

View File

@@ -536,14 +536,14 @@ class LightningNode(object):
if wait_for_active: if wait_for_active:
# We wait until gossipd sees both local updates, as well as status NORMAL, # We wait until gossipd sees both local updates, as well as status NORMAL,
# so it can definitely route through. # so it can definitely route through.
self.daemon.wait_for_logs([r'update for channel {}\(0\) now ACTIVE' self.daemon.wait_for_logs([r'update for channel {}/0 now ACTIVE'
.format(scid), .format(scid),
r'update for channel {}\(1\) now ACTIVE' r'update for channel {}/1 now ACTIVE'
.format(scid), .format(scid),
'to CHANNELD_NORMAL']) 'to CHANNELD_NORMAL'])
l2.daemon.wait_for_logs([r'update for channel {}\(0\) now ACTIVE' l2.daemon.wait_for_logs([r'update for channel {}/0 now ACTIVE'
.format(scid), .format(scid),
r'update for channel {}\(1\) now ACTIVE' r'update for channel {}/1 now ACTIVE'
.format(scid), .format(scid),
'to CHANNELD_NORMAL']) 'to CHANNELD_NORMAL'])
return scid return scid
@@ -596,9 +596,9 @@ class LightningNode(object):
# (or for local channels, at least a local announcement) # (or for local channels, at least a local announcement)
def wait_for_routes(self, channel_ids): def wait_for_routes(self, channel_ids):
# Could happen in any order... # Could happen in any order...
self.daemon.wait_for_logs(['Received channel_update for channel {}\\(0\\)'.format(c) self.daemon.wait_for_logs(['Received channel_update for channel {}/0'.format(c)
for c in channel_ids] for c in channel_ids]
+ ['Received channel_update for channel {}\\(1\\)'.format(c) + ['Received channel_update for channel {}/1'.format(c)
for c in channel_ids]) for c in channel_ids])
def pay(self, dst, amt, label=None): def pay(self, dst, amt, label=None):
@@ -829,7 +829,7 @@ class NodeFactory(object):
for src, dst in connections: for src, dst in connections:
wait_for(lambda: src.channel_state(dst) == 'CHANNELD_NORMAL') wait_for(lambda: src.channel_state(dst) == 'CHANNELD_NORMAL')
scid = src.get_channel_scid(dst) scid = src.get_channel_scid(dst)
src.daemon.wait_for_log(r'Received channel_update for channel {scid}\(.\) now ACTIVE'.format(scid=scid)) src.daemon.wait_for_log(r'Received channel_update for channel {scid}/. now ACTIVE'.format(scid=scid))
scids.append(scid) scids.append(scid)
if not wait_for_announce: if not wait_for_announce:

View File

@@ -161,6 +161,13 @@ void fromwire_short_channel_id(const u8 **cursor, size_t *max,
short_channel_id->u64 = fromwire_u64(cursor, max); short_channel_id->u64 = fromwire_u64(cursor, max);
} }
void fromwire_short_channel_id_dir(const u8 **cursor, size_t *max,
struct short_channel_id_dir *scidd)
{
fromwire_short_channel_id(cursor, max, &scidd->scid);
scidd->dir = fromwire_bool(cursor, max);
}
void fromwire_sha256(const u8 **cursor, size_t *max, struct sha256 *sha256) void fromwire_sha256(const u8 **cursor, size_t *max, struct sha256 *sha256)
{ {
fromwire(cursor, max, sha256, sizeof(*sha256)); fromwire(cursor, max, sha256, sizeof(*sha256));
@@ -235,6 +242,7 @@ char *fromwire_wirestring(const tal_t *ctx, const u8 **cursor, size_t *max)
} }
REGISTER_TYPE_TO_STRING(short_channel_id, short_channel_id_to_str); REGISTER_TYPE_TO_STRING(short_channel_id, short_channel_id_to_str);
REGISTER_TYPE_TO_STRING(short_channel_id_dir, short_channel_id_dir_to_str);
REGISTER_TYPE_TO_HEXSTR(channel_id); REGISTER_TYPE_TO_HEXSTR(channel_id);
/* BOLT #2: /* BOLT #2:

View File

@@ -109,6 +109,13 @@ void towire_short_channel_id(u8 **pptr,
towire_u64(pptr, short_channel_id->u64); towire_u64(pptr, short_channel_id->u64);
} }
void towire_short_channel_id_dir(u8 **pptr,
const struct short_channel_id_dir *scidd)
{
towire_short_channel_id(pptr, &scidd->scid);
towire_bool(pptr, scidd->dir);
}
void towire_sha256(u8 **pptr, const struct sha256 *sha256) void towire_sha256(u8 **pptr, const struct sha256 *sha256)
{ {
towire(pptr, sha256, sizeof(*sha256)); towire(pptr, sha256, sizeof(*sha256));

View File

@@ -47,6 +47,8 @@ void towire_secp256k1_ecdsa_recoverable_signature(u8 **pptr,
void towire_channel_id(u8 **pptr, const struct channel_id *channel_id); void towire_channel_id(u8 **pptr, const struct channel_id *channel_id);
void towire_short_channel_id(u8 **pptr, void towire_short_channel_id(u8 **pptr,
const struct short_channel_id *short_channel_id); const struct short_channel_id *short_channel_id);
void towire_short_channel_id_dir(u8 **pptr,
const struct short_channel_id_dir *scidd);
void towire_sha256(u8 **pptr, const struct sha256 *sha256); void towire_sha256(u8 **pptr, const struct sha256 *sha256);
void towire_sha256_double(u8 **pptr, const struct sha256_double *sha256d); void towire_sha256_double(u8 **pptr, const struct sha256_double *sha256d);
void towire_bitcoin_txid(u8 **pptr, const struct bitcoin_txid *txid); void towire_bitcoin_txid(u8 **pptr, const struct bitcoin_txid *txid);
@@ -87,6 +89,8 @@ void fromwire_channel_id(const u8 **cursor, size_t *max,
struct channel_id *channel_id); struct channel_id *channel_id);
void fromwire_short_channel_id(const u8 **cursor, size_t *max, void fromwire_short_channel_id(const u8 **cursor, size_t *max,
struct short_channel_id *short_channel_id); struct short_channel_id *short_channel_id);
void fromwire_short_channel_id_dir(const u8 **cursor, size_t *max,
struct short_channel_id_dir *scidd);
void fromwire_sha256(const u8 **cursor, size_t *max, struct sha256 *sha256); void fromwire_sha256(const u8 **cursor, size_t *max, struct sha256 *sha256);
void fromwire_sha256_double(const u8 **cursor, size_t *max, void fromwire_sha256_double(const u8 **cursor, size_t *max,
struct sha256_double *sha256d); struct sha256_double *sha256d);