|
|
|
#include "wire.h"
|
|
|
|
#include <assert.h>
|
|
|
|
#include <bitcoin/chainparams.h>
|
|
|
|
#include <bitcoin/preimage.h>
|
|
|
|
#include <bitcoin/pubkey.h>
|
|
|
|
#include <bitcoin/shadouble.h>
|
|
|
|
#include <bitcoin/tx.h>
|
|
|
|
#include <ccan/build_assert/build_assert.h>
|
|
|
|
#include <ccan/crypto/siphash24/siphash24.h>
|
|
|
|
#include <ccan/endian/endian.h>
|
|
|
|
#include <ccan/mem/mem.h>
|
|
|
|
#include <ccan/tal/str/str.h>
|
|
|
|
#include <common/amount.h>
|
common/node_id: new type.
Node ids are pubkeys, but we only use them as pubkeys for routing and checking
gossip messages. So we're packing and unpacking them constantly, and wasting
some space and time.
This introduces a new type, explicitly the SEC1 compressed encoding
(33 bytes). We ensure its validity when we load from the db, or get it
from JSON. We still use 'struct pubkey' for peer messages, which checks
validity.
Results from 5 runs, min-max(mean +/- stddev):
store_load_msec,vsz_kb,store_rewrite_sec,listnodes_sec,listchannels_sec,routing_sec,peer_write_all_sec
39475-39572(39518+/-36),2880732,41.150000-41.390000(41.298+/-0.085),2.260000-2.550000(2.336+/-0.11),44.390000-65.150000(58.648+/-7.5),32.740000-33.020000(32.89+/-0.093),44.130000-45.090000(44.566+/-0.32)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
6 years ago
|
|
|
#include <common/node_id.h>
|
|
|
|
#include <common/type_to_string.h>
|
|
|
|
#include <common/utils.h>
|
|
|
|
|
|
|
|
#ifndef SUPERVERBOSE
|
|
|
|
#define SUPERVERBOSE(...)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Sets *cursor to NULL and returns NULL when extraction fails. */
|
|
|
|
const void *fromwire_fail(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
*cursor = NULL;
|
|
|
|
*max = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u8 *fromwire(const u8 **cursor, size_t *max, void *copy, size_t n)
|
|
|
|
{
|
|
|
|
const u8 *p = *cursor;
|
|
|
|
|
|
|
|
if (*max < n) {
|
|
|
|
/* Just make sure we don't leak uninitialized mem! */
|
|
|
|
if (copy)
|
|
|
|
memset(copy, 0, n);
|
|
|
|
if (*cursor)
|
|
|
|
SUPERVERBOSE("less than encoding length");
|
|
|
|
return fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
*cursor += n;
|
|
|
|
*max -= n;
|
|
|
|
if (copy)
|
|
|
|
memcpy(copy, p, n);
|
|
|
|
return memcheck(p, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fromwire_peektype(const u8 *cursor)
|
|
|
|
{
|
|
|
|
be16 be_type;
|
|
|
|
size_t max = tal_count(cursor);
|
|
|
|
|
|
|
|
fromwire(&cursor, &max, &be_type, sizeof(be_type));
|
|
|
|
if (!cursor)
|
|
|
|
return -1;
|
|
|
|
return be16_to_cpu(be_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 fromwire_u8(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
u8 ret;
|
|
|
|
|
|
|
|
if (!fromwire(cursor, max, &ret, sizeof(ret)))
|
|
|
|
return 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 fromwire_u16(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
be16 ret;
|
|
|
|
|
|
|
|
if (!fromwire(cursor, max, &ret, sizeof(ret)))
|
|
|
|
return 0;
|
|
|
|
return be16_to_cpu(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 fromwire_u32(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
be32 ret;
|
|
|
|
|
|
|
|
if (!fromwire(cursor, max, &ret, sizeof(ret)))
|
|
|
|
return 0;
|
|
|
|
return be32_to_cpu(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 fromwire_u64(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
be64 ret;
|
|
|
|
|
|
|
|
if (!fromwire(cursor, max, &ret, sizeof(ret)))
|
|
|
|
return 0;
|
|
|
|
return be64_to_cpu(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static u64 fromwire_tlv_uint(const u8 **cursor, size_t *max, size_t maxlen)
|
|
|
|
{
|
|
|
|
u8 bytes[8];
|
|
|
|
size_t length;
|
|
|
|
be64 val;
|
|
|
|
|
|
|
|
assert(maxlen <= sizeof(bytes));
|
|
|
|
|
|
|
|
/* BOLT-EXPERIMENTAL #1:
|
|
|
|
*
|
|
|
|
* - if `length` is not exactly equal to that required for the
|
|
|
|
* known encoding for `type`:
|
|
|
|
* - MUST fail to parse the `tlv_stream`.
|
|
|
|
*/
|
|
|
|
length = *max;
|
|
|
|
if (length > maxlen) {
|
|
|
|
SUPERVERBOSE("greater than encoding length");
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(bytes, 0, sizeof(bytes));
|
|
|
|
fromwire(cursor, max, bytes + sizeof(bytes) - length, length);
|
|
|
|
|
|
|
|
/* BOLT-EXPERIMENTAL #1:
|
|
|
|
* - if variable-length fields within the known encoding for `type` are
|
|
|
|
* not minimal:
|
|
|
|
* - MUST fail to parse the `tlv_stream`.
|
|
|
|
*/
|
|
|
|
if (length > 0 && bytes[sizeof(bytes) - length] == 0) {
|
|
|
|
SUPERVERBOSE("not minimal");
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
BUILD_ASSERT(sizeof(val) == sizeof(bytes));
|
|
|
|
memcpy(&val, bytes, sizeof(bytes));
|
|
|
|
return be64_to_cpu(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 fromwire_tu16(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
return fromwire_tlv_uint(cursor, max, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 fromwire_tu32(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
return fromwire_tlv_uint(cursor, max, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 fromwire_tu64(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
return fromwire_tlv_uint(cursor, max, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_double(const u8 **cursor, size_t *max, double *ret)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, ret, sizeof(*ret));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool fromwire_bool(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
u8 ret;
|
|
|
|
|
|
|
|
if (!fromwire(cursor, max, &ret, sizeof(ret)))
|
|
|
|
return false;
|
|
|
|
if (ret != 0 && ret != 1)
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 fromwire_bigsize(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
u8 flag = fromwire_u8(cursor, max);
|
|
|
|
u64 ret;
|
|
|
|
|
|
|
|
switch(flag) {
|
|
|
|
case 0xff:
|
|
|
|
ret = fromwire_u64(cursor, max);
|
|
|
|
if ((ret >> 32) == 0) {
|
|
|
|
SUPERVERBOSE("not minimal encoded");
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0xfe:
|
|
|
|
ret = fromwire_u32(cursor, max);
|
|
|
|
if ((ret >> 16) == 0) {
|
|
|
|
SUPERVERBOSE("not minimal encoded");
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0xfd:
|
|
|
|
ret = fromwire_u16(cursor, max);
|
|
|
|
if (ret < 0xfd) {
|
|
|
|
SUPERVERBOSE("not minimal encoded");
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = flag;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_pubkey(const u8 **cursor, size_t *max, struct pubkey *pubkey)
|
|
|
|
{
|
pubkey: rename PUBKEY_DER_LEN to PUBKEY_CMPR_LEN.
Pubkeys are not not actually DER encoding, but Pieter Wuille corrected
me: it's SEC 1 documented encoding.
Results from 5 runs, min-max(mean +/- stddev):
store_load_msec,vsz_kb,store_rewrite_sec,listnodes_sec,listchannels_sec,routing_sec,peer_write_all_sec
38922-39297(39180.6+/-1.3e+02),2880728,41.040000-41.160000(41.106+/-0.05),2.270000-2.530000(2.338+/-0.097),44.570000-53.980000(49.696+/-3),32.840000-33.080000(32.95+/-0.095),43.060000-44.950000(43.696+/-0.72)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
6 years ago
|
|
|
u8 der[PUBKEY_CMPR_LEN];
|
|
|
|
|
|
|
|
if (!fromwire(cursor, max, der, sizeof(der)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!pubkey_from_der(der, sizeof(der), pubkey)) {
|
|
|
|
SUPERVERBOSE("not a valid point");
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
common/node_id: new type.
Node ids are pubkeys, but we only use them as pubkeys for routing and checking
gossip messages. So we're packing and unpacking them constantly, and wasting
some space and time.
This introduces a new type, explicitly the SEC1 compressed encoding
(33 bytes). We ensure its validity when we load from the db, or get it
from JSON. We still use 'struct pubkey' for peer messages, which checks
validity.
Results from 5 runs, min-max(mean +/- stddev):
store_load_msec,vsz_kb,store_rewrite_sec,listnodes_sec,listchannels_sec,routing_sec,peer_write_all_sec
39475-39572(39518+/-36),2880732,41.150000-41.390000(41.298+/-0.085),2.260000-2.550000(2.336+/-0.11),44.390000-65.150000(58.648+/-7.5),32.740000-33.020000(32.89+/-0.093),44.130000-45.090000(44.566+/-0.32)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
6 years ago
|
|
|
void fromwire_node_id(const u8 **cursor, size_t *max, struct node_id *id)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, &id->k, sizeof(id->k));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_secret(const u8 **cursor, size_t *max, struct secret *secret)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, secret->data, sizeof(secret->data));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_privkey(const u8 **cursor, size_t *max, struct privkey *privkey)
|
|
|
|
{
|
|
|
|
fromwire_secret(cursor, max, &privkey->secret);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_secp256k1_ecdsa_signature(const u8 **cursor,
|
|
|
|
size_t *max, secp256k1_ecdsa_signature *sig)
|
|
|
|
{
|
|
|
|
u8 compact[64];
|
|
|
|
|
|
|
|
if (!fromwire(cursor, max, compact, sizeof(compact)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (secp256k1_ecdsa_signature_parse_compact(secp256k1_ctx, sig, compact)
|
|
|
|
!= 1)
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_secp256k1_ecdsa_recoverable_signature(const u8 **cursor,
|
|
|
|
size_t *max,
|
|
|
|
secp256k1_ecdsa_recoverable_signature *rsig)
|
|
|
|
{
|
|
|
|
u8 compact[64];
|
|
|
|
int recid;
|
|
|
|
|
|
|
|
fromwire(cursor, max, compact, sizeof(compact));
|
|
|
|
recid = fromwire_u8(cursor, max);
|
|
|
|
|
|
|
|
if (secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_ctx,
|
|
|
|
rsig, compact,
|
|
|
|
recid) != 1)
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_channel_id(const u8 **cursor, size_t *max,
|
|
|
|
struct channel_id *channel_id)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, channel_id, sizeof(*channel_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_short_channel_id(const u8 **cursor, size_t *max,
|
|
|
|
struct short_channel_id *short_channel_id)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, sha256, sizeof(*sha256));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_sha256_double(const u8 **cursor, size_t *max,
|
|
|
|
struct sha256_double *sha256d)
|
|
|
|
{
|
|
|
|
fromwire_sha256(cursor, max, &sha256d->sha);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_bitcoin_txid(const u8 **cursor, size_t *max,
|
|
|
|
struct bitcoin_txid *txid)
|
|
|
|
{
|
|
|
|
fromwire_sha256_double(cursor, max, &txid->shad);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_bitcoin_signature(const u8 **cursor, size_t *max,
|
|
|
|
struct bitcoin_signature *sig)
|
|
|
|
{
|
|
|
|
fromwire_secp256k1_ecdsa_signature(cursor, max, &sig->s);
|
|
|
|
sig->sighash_type = fromwire_u8(cursor, max);
|
|
|
|
if (!sighash_type_valid(sig->sighash_type))
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_bitcoin_blkid(const u8 **cursor, size_t *max,
|
|
|
|
struct bitcoin_blkid *blkid)
|
|
|
|
{
|
|
|
|
fromwire_sha256_double(cursor, max, &blkid->shad);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_preimage(const u8 **cursor, size_t *max, struct preimage *preimage)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, preimage, sizeof(*preimage));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_ripemd160(const u8 **cursor, size_t *max, struct ripemd160 *ripemd)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, ripemd, sizeof(*ripemd));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_u8_array(const u8 **cursor, size_t *max, u8 *arr, size_t num)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, arr, num);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_pad(const u8 **cursor, size_t *max, size_t num)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, NULL, num);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't allow control chars except spaces: we only use this for stuff
|
|
|
|
* from subdaemons, who shouldn't do that.
|
|
|
|
*/
|
|
|
|
char *fromwire_wirestring(const tal_t *ctx, const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < *max; i++) {
|
|
|
|
if ((*cursor)[i] == '\0') {
|
|
|
|
char *str = tal_arr(ctx, char, i + 1);
|
|
|
|
fromwire(cursor, max, str, i + 1);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
if ((*cursor)[i] < ' ')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fromwire_fail(cursor, max);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
REGISTER_TYPE_TO_HEXSTR(channel_id);
|
|
|
|
|
|
|
|
/* BOLT #2:
|
|
|
|
*
|
|
|
|
* This message introduces the `channel_id` to identify the channel. It's
|
|
|
|
* derived from the funding transaction by combining the `funding_txid` and
|
|
|
|
* the `funding_output_index`, using big-endian exclusive-OR
|
|
|
|
* (i.e. `funding_output_index` alters the last 2 bytes).
|
|
|
|
*/
|
|
|
|
void derive_channel_id(struct channel_id *channel_id,
|
|
|
|
const struct bitcoin_txid *txid, u16 txout)
|
|
|
|
{
|
|
|
|
BUILD_ASSERT(sizeof(*channel_id) == sizeof(*txid));
|
|
|
|
memcpy(channel_id, txid, sizeof(*channel_id));
|
|
|
|
channel_id->id[sizeof(*channel_id)-2] ^= txout >> 8;
|
|
|
|
channel_id->id[sizeof(*channel_id)-1] ^= txout;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct bitcoin_tx *fromwire_bitcoin_tx(const tal_t *ctx,
|
|
|
|
const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
return pull_bitcoin_tx(ctx, cursor, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_siphash_seed(const u8 **cursor, size_t *max,
|
|
|
|
struct siphash_seed *seed)
|
|
|
|
{
|
|
|
|
fromwire(cursor, max, seed, sizeof(*seed));
|
|
|
|
}
|
|
|
|
|
|
|
|
struct amount_msat fromwire_amount_msat(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
struct amount_msat msat;
|
|
|
|
|
|
|
|
msat.millisatoshis = fromwire_u64(cursor, max); /* Raw: primitive */
|
|
|
|
return msat;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct amount_sat fromwire_amount_sat(const u8 **cursor, size_t *max)
|
|
|
|
{
|
|
|
|
struct amount_sat sat;
|
|
|
|
|
|
|
|
sat.satoshis = fromwire_u64(cursor, max); /* Raw: primitive */
|
|
|
|
return sat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_bip32_key_version(const u8** cursor, size_t *max,
|
|
|
|
struct bip32_key_version *version)
|
|
|
|
{
|
|
|
|
version->bip32_pubkey_version = fromwire_u32(cursor, max);
|
|
|
|
version->bip32_privkey_version = fromwire_u32(cursor, max);
|
|
|
|
}
|