mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
devtools/mkgossip: tool to create gossip msgs for testing.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
a46e880f1d
commit
8ef996d56e
2
devtools/.gitignore
vendored
2
devtools/.gitignore
vendored
@ -5,3 +5,5 @@ dump-gossipstore
|
||||
gossipwith
|
||||
mkcommit
|
||||
mkfunding
|
||||
mkclose
|
||||
mkgossip
|
||||
|
@ -1,6 +1,6 @@
|
||||
DEVTOOLS_SRC := devtools/gen_print_wire.c devtools/gen_print_onion_wire.c devtools/print_wire.c
|
||||
DEVTOOLS_OBJS := $(DEVTOOLS_SRC:.c=.o)
|
||||
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose
|
||||
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose devtools/mkgossip
|
||||
DEVTOOLS_TOOL_SRC := $(DEVTOOLS:=.c)
|
||||
DEVTOOLS_TOOL_OBJS := $(DEVTOOLS_TOOL_SRC:.c=.o)
|
||||
|
||||
@ -72,6 +72,8 @@ devtools/mkfunding: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fr
|
||||
|
||||
devtools/mkclose: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o devtools/mkclose.o
|
||||
|
||||
devtools/mkgossip: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o common/funding_tx.o common/utxo.o common/permute_tx.o common/key_derive.o devtools/mkgossip.o
|
||||
|
||||
# Make sure these depend on everything.
|
||||
ALL_PROGRAMS += $(DEVTOOLS)
|
||||
ALL_OBJS += $(DEVTOOLS_OBJS) $(DEVTOOLS_TOOL_OBJS)
|
||||
|
@ -1,6 +1,10 @@
|
||||
/* For example, in the spec tests we use the following keys:
|
||||
*
|
||||
* lightning/devtools/mkfunding 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b 1 0.01btc 253 76edf0c303b9e692da9cb491abedef46ca5b81d32f102eb4648461b239cb0f99 0000000000000000000000000000000000000000000000000000000000000010 0000000000000000000000000000000000000000000000000000000000000020
|
||||
*
|
||||
* lightning/devtools/mkfunding 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b 0 0.02btc 253 bc2f48a76a6b8815940accaf01981d3b6347a68fbe844f81c50ecbadf27cd179 0000000000000000000000000000000000000000000000000000000000000030 0000000000000000000000000000000000000000000000000000000000000040
|
||||
*
|
||||
* lightning/devtools/mkfunding 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b 3 0.03btc 253 16c5027616e940d1e72b4c172557b3b799a93c0582f924441174ea556aadd01c 0000000000000000000000000000000000000000000000000000000000000050 0000000000000000000000000000000000000000000000000000000000000060
|
||||
*/
|
||||
#include <bitcoin/address.h>
|
||||
#include <bitcoin/script.h>
|
||||
|
328
devtools/mkgossip.c
Normal file
328
devtools/mkgossip.c
Normal file
@ -0,0 +1,328 @@
|
||||
/* For example, in the spec tests we use the following channels:
|
||||
*
|
||||
* lightning/devtools/mkgossip 103x1x0 06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f 0000000000000000000000000000000000000000000000000000000000000002 0000000000000000000000000000000000000000000000000000000000000003 0000000000000000000000000000000000000000000000000000000000000010 0000000000000000000000000000000000000000000000000000000000000020 "" 1565587763 144 0 1000 10 "" "01080808082607" 1565587763 48 0 100 11 100000 "0151b6887026070220014c4e1cc141001e6f65fffec8a825260703c43068ceb641d7b25c3a26070441cf248da2034dfa9351a9e946d71ce86f561f50b67753fd8e385d44647bf62cdb91032607"
|
||||
*
|
||||
* lightning/devtools/mkgossip 109x1x0 06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f 0000000000000000000000000000000000000000000000000000000000000004 0000000000000000000000000000000000000000000000000000000000000005 0000000000000000000000000000000000000000000000000000000000000030 0000000000000000000000000000000000000000000000000000000000000040 "" 1565587764 144 0 1000 10 "" "" 1565587765 48 0 100 11 100000 022a03b0c0000300d000000000240020012607
|
||||
*
|
||||
* lightning/devtools/mkgossip 115x1x0 06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f 0000000000000000000000000000000000000000000000000000000000000003 0000000000000000000000000000000000000000000000000000000000000004 0000000000000000000000000000000000000000000000000000000000000050 0000000000000000000000000000000000000000000000000000000000000060 "" 1565597764 144 0 1000 10 "" "0441cf248da2034dfa9351a9e946d71ce86f561f50b67753fd8e385d44647bf62cdb91032607" 1565597765 48 0 100 11 100000 ""
|
||||
*/
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <bitcoin/address.h>
|
||||
#include <bitcoin/script.h>
|
||||
#include <bitcoin/short_channel_id.h>
|
||||
#include <bitcoin/tx.h>
|
||||
#include <ccan/crc32c/crc32c.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <common/utils.h>
|
||||
#include <gossipd/gossip_constants.h>
|
||||
#include <inttypes.h>
|
||||
#include <wire/gen_peer_wire.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct update_opts {
|
||||
u32 timestamp;
|
||||
u32 cltv_expiry_delta;
|
||||
struct amount_msat min;
|
||||
struct amount_msat feebase;
|
||||
u32 fee_proportional_millionths;
|
||||
struct amount_msat *max;
|
||||
u8 *addresses;
|
||||
};
|
||||
|
||||
static int parse_options(char *argv[], struct update_opts *opts,
|
||||
const char *desc)
|
||||
{
|
||||
int argnum = 0;
|
||||
|
||||
opts->timestamp = atol(argv[argnum++]);
|
||||
if (!opts->timestamp)
|
||||
errx(1, "Bad %s.timestamp", desc);
|
||||
opts->cltv_expiry_delta = atol(argv[argnum++]);
|
||||
if (!opts->cltv_expiry_delta)
|
||||
errx(1, "Bad %s.cltv_expiry_delta", desc);
|
||||
if (!parse_amount_msat(&opts->min, argv[argnum], strlen(argv[argnum])))
|
||||
errx(1, "Bad %s.min", desc);
|
||||
argnum++;
|
||||
if (!parse_amount_msat(&opts->feebase,
|
||||
argv[argnum], strlen(argv[argnum])))
|
||||
errx(1, "Bad %s.feebase", desc);
|
||||
argnum++;
|
||||
opts->fee_proportional_millionths = atol(argv[argnum++]);
|
||||
if (!opts->fee_proportional_millionths)
|
||||
errx(1, "Bad %s.fee_proportional_millionths", desc);
|
||||
|
||||
if (streq(argv[argnum], ""))
|
||||
opts->max = NULL;
|
||||
else {
|
||||
opts->max = tal(NULL, struct amount_msat);
|
||||
if (!parse_amount_msat(opts->max,
|
||||
argv[argnum], strlen(argv[argnum])))
|
||||
errx(1, "Bad %s.max", desc);
|
||||
}
|
||||
argnum++;
|
||||
opts->addresses = tal_hexdata(NULL, argv[argnum], strlen(argv[argnum]));
|
||||
if (!opts->addresses)
|
||||
errx(1, "Bad %s.addresses", desc);
|
||||
argnum++;
|
||||
return argnum;
|
||||
}
|
||||
|
||||
static char *sig_as_hex(const secp256k1_ecdsa_signature *sig)
|
||||
{
|
||||
u8 compact_sig[64];
|
||||
|
||||
secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx,
|
||||
compact_sig,
|
||||
sig);
|
||||
return tal_hexstr(NULL, compact_sig, sizeof(compact_sig));
|
||||
}
|
||||
|
||||
/* BOLT-61a1365a45cc8b463ddbbe3429d350f8eac787dd #7:
|
||||
*
|
||||
* The checksum of a `channel_update` is the CRC32C checksum as specified in
|
||||
* [RFC3720](https://tools.ietf.org/html/rfc3720#appendix-B.4) of this
|
||||
* `channel_update` without its `signature` and `timestamp` fields.
|
||||
*/
|
||||
static u32 crc32_of_update(const u8 *channel_update)
|
||||
{
|
||||
u32 sum;
|
||||
|
||||
/* BOLT #7:
|
||||
*
|
||||
* 1. type: 258 (`channel_update`)
|
||||
* 2. data:
|
||||
* * [`signature`:`signature`]
|
||||
* * [`chain_hash`:`chain_hash`]
|
||||
* * [`short_channel_id`:`short_channel_id`]
|
||||
* * [`u32`:`timestamp`]
|
||||
*...
|
||||
*/
|
||||
/* We already checked it's valid before accepting */
|
||||
assert(tal_count(channel_update) > 2 + 64 + 32 + 8 + 4);
|
||||
sum = crc32c(0, channel_update + 2 + 64, 32 + 8);
|
||||
sum = crc32c(sum, channel_update + 2 + 64 + 32 + 8 + 4,
|
||||
tal_count(channel_update) - (64 + 2 + 32 + 8 + 4));
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void print_update(const struct bitcoin_blkid *chainhash,
|
||||
const struct short_channel_id *scid,
|
||||
const struct update_opts *opts,
|
||||
bool is_lesser_key,
|
||||
const struct privkey *privkey)
|
||||
{
|
||||
/* 2 bytes msg type + 64 bytes of signature */
|
||||
const size_t channel_update_offset = 2 + 64;
|
||||
struct sha256_double hash;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
u8 *cupdate;
|
||||
|
||||
memset(&sig, 0, sizeof(sig));
|
||||
if (opts->max) {
|
||||
cupdate = towire_channel_update_option_channel_htlc_max
|
||||
(NULL, &sig, chainhash, scid, opts->timestamp,
|
||||
ROUTING_OPT_HTLC_MAX_MSAT,
|
||||
is_lesser_key ? 0 : ROUTING_FLAGS_DIRECTION,
|
||||
opts->cltv_expiry_delta,
|
||||
opts->min,
|
||||
opts->feebase.millisatoshis, /* Raw: devtools code */
|
||||
opts->fee_proportional_millionths,
|
||||
*opts->max);
|
||||
} else {
|
||||
cupdate = towire_channel_update
|
||||
(NULL, &sig, chainhash, scid, opts->timestamp,
|
||||
0,
|
||||
is_lesser_key ? 0 : ROUTING_FLAGS_DIRECTION,
|
||||
opts->cltv_expiry_delta,
|
||||
opts->min,
|
||||
opts->feebase.millisatoshis, /* Raw: devtools code */
|
||||
opts->fee_proportional_millionths);
|
||||
}
|
||||
sha256_double(&hash, cupdate + channel_update_offset,
|
||||
tal_count(cupdate) - channel_update_offset);
|
||||
sign_hash(privkey, &hash, &sig);
|
||||
|
||||
printf("type=channel_update\n");
|
||||
printf(" signature=%s\n", sig_as_hex(&sig));
|
||||
printf(" chain_hash=%s\n", tal_hexstr(NULL, chainhash, sizeof(*chainhash)));
|
||||
printf(" short_channel_id=%s\n", short_channel_id_to_str(NULL, scid));
|
||||
printf(" timestamp=%u\n", opts->timestamp);
|
||||
printf(" message_flags=%u\n",
|
||||
opts->max ? ROUTING_OPT_HTLC_MAX_MSAT : 0);
|
||||
printf(" channel_flags=%u\n",
|
||||
is_lesser_key ? 0 : ROUTING_FLAGS_DIRECTION);
|
||||
printf(" cltv_expiry_delta=%u\n",
|
||||
opts->cltv_expiry_delta);
|
||||
printf(" htlc_minimum_msat=%"PRIu64"\n",
|
||||
opts->min.millisatoshis); /* Raw: devtools code */
|
||||
printf(" fee_base_msat=%"PRIu64"\n",
|
||||
opts->feebase.millisatoshis); /* Raw: devtools code */
|
||||
printf(" fee_proportional_millionths=%u\n",
|
||||
opts->fee_proportional_millionths);
|
||||
if (opts->max)
|
||||
printf(" htlc_maximum_msat=%"PRIu64"\n",
|
||||
opts->max->millisatoshis); /* Raw: devtools code */
|
||||
printf("# crc32c checksum: %08x\n", crc32_of_update(cupdate));
|
||||
}
|
||||
|
||||
static void print_nannounce(const struct node_id *nodeid,
|
||||
const struct update_opts *opts,
|
||||
const struct privkey *privkey)
|
||||
{
|
||||
/* 2 bytes msg type + 64 bytes of signature */
|
||||
const size_t node_announcement_offset = 2 + 64;
|
||||
struct sha256_double hash;
|
||||
secp256k1_ecdsa_signature sig;
|
||||
char alias[33];
|
||||
u8 *nannounce;
|
||||
|
||||
memset(&sig, 0, sizeof(sig));
|
||||
assert(hex_str_size(sizeof(*nodeid)) >= sizeof(alias));
|
||||
hex_encode(nodeid, hex_data_size(sizeof(alias)), alias, sizeof(alias));
|
||||
nannounce = towire_node_announcement(NULL, &sig, NULL, opts->timestamp,
|
||||
nodeid, nodeid->k, (u8 *)alias,
|
||||
opts->addresses);
|
||||
sha256_double(&hash, nannounce + node_announcement_offset,
|
||||
tal_count(nannounce) - node_announcement_offset);
|
||||
sign_hash(privkey, &hash, &sig);
|
||||
|
||||
printf("type=node_announcement\n");
|
||||
printf(" signature=%s\n", sig_as_hex(&sig));
|
||||
printf(" features=%s\n", tal_hex(NULL, NULL));
|
||||
printf(" timestamp=%u\n", opts->timestamp);
|
||||
printf(" node_id=%s\n", node_id_to_hexstr(NULL, nodeid));
|
||||
printf(" rgb_color=%s\n", tal_hexstr(NULL, nodeid->k, 3));
|
||||
printf(" alias=%s\n", tal_hexstr(NULL, alias, 32));
|
||||
printf(" addresses=%s\n", tal_hex(NULL, opts->addresses));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct privkey node_privkey[2], funding_privkey[2];
|
||||
struct pubkey node[2], bitcoin[2];
|
||||
struct node_id nodeid[2];
|
||||
int lesser_key;
|
||||
struct short_channel_id scid;
|
||||
struct bitcoin_blkid chainhash;
|
||||
secp256k1_ecdsa_signature nodesig[2], bitcoinsig[2];
|
||||
const u8 *features;
|
||||
u8 *cannounce;
|
||||
/* 2 bytes msg type + 256 bytes of signatures */
|
||||
const size_t channel_announcement_offset = 2 + 256;
|
||||
int argnum;
|
||||
struct sha256_double hash;
|
||||
struct update_opts opts[2];
|
||||
|
||||
setup_locale();
|
||||
|
||||
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|
||||
SECP256K1_CONTEXT_SIGN);
|
||||
|
||||
if (argc != 8 + 7 * 2)
|
||||
errx(1, "Usage: mkgossip <scid> <chainhash> <node-privkey1> <node-privkey2> <node1-funding-privkey> <node2-funding-privkey> <features-hex> update-opts-1 update-opts-2\n"
|
||||
"Where <update-opts> is:\n"
|
||||
" <timestamp>\n"
|
||||
" <cltv_expiry_delta>\n"
|
||||
" <htlc_minimum_msat>\n"
|
||||
" <fee_base_msat>\n"
|
||||
" <fee_proportional_millionths>\n"
|
||||
" <htlc_maximum_msat-or-empty>\n"
|
||||
" <hex-addrstr>");
|
||||
|
||||
argnum = 1;
|
||||
if (!short_channel_id_from_str(argv[argnum], strlen(argv[argnum]), &scid))
|
||||
errx(1, "Bad scid");
|
||||
argnum++;
|
||||
/* Don't do endian-reversing insanity here! */
|
||||
if (!hex_decode(argv[argnum], strlen(argv[argnum]),
|
||||
&chainhash, sizeof(chainhash)))
|
||||
errx(1, "Parsing chainhash");
|
||||
argnum++;
|
||||
if (!hex_decode(argv[argnum], strlen(argv[argnum]),
|
||||
&node_privkey[0], sizeof(node_privkey[0])))
|
||||
errx(1, "Parsing node-privkey1");
|
||||
argnum++;
|
||||
if (!hex_decode(argv[argnum], strlen(argv[argnum]),
|
||||
&node_privkey[1], sizeof(node_privkey[2])))
|
||||
errx(1, "Parsing node-privkey2");
|
||||
argnum++;
|
||||
if (!hex_decode(argv[argnum], strlen(argv[argnum]),
|
||||
&funding_privkey[0], sizeof(funding_privkey[0])))
|
||||
errx(1, "Parsing funding-privkey1");
|
||||
argnum++;
|
||||
if (!hex_decode(argv[argnum], strlen(argv[argnum]),
|
||||
&funding_privkey[1], sizeof(funding_privkey[2])))
|
||||
errx(1, "Parsing funding-privkey2");
|
||||
argnum++;
|
||||
features = tal_hexdata(NULL, argv[argnum], strlen(argv[argnum]));
|
||||
if (!features)
|
||||
errx(1, "Parsing hexfeatures");
|
||||
argnum++;
|
||||
|
||||
argnum += parse_options(argv + argnum, &opts[0], "update-opts1");
|
||||
argnum += parse_options(argv + argnum, &opts[1], "update-opts2");
|
||||
|
||||
if (!pubkey_from_privkey(&node_privkey[0], &node[0])
|
||||
|| !pubkey_from_privkey(&node_privkey[1], &node[1])
|
||||
|| !pubkey_from_privkey(&funding_privkey[0], &bitcoin[0])
|
||||
|| !pubkey_from_privkey(&funding_privkey[1], &bitcoin[1]))
|
||||
errx(1, "Bad privkeys");
|
||||
|
||||
lesser_key = pubkey_idx(&node[0], &node[1]);
|
||||
node_id_from_pubkey(&nodeid[0], &node[0]);
|
||||
node_id_from_pubkey(&nodeid[1], &node[1]);
|
||||
|
||||
/* First make msg with dummy sigs. */
|
||||
memset(nodesig, 0, sizeof(nodesig));
|
||||
memset(bitcoinsig, 0, sizeof(bitcoinsig));
|
||||
|
||||
cannounce = towire_channel_announcement(NULL,
|
||||
&nodesig[lesser_key],
|
||||
&nodesig[!lesser_key],
|
||||
&bitcoinsig[lesser_key],
|
||||
&bitcoinsig[!lesser_key],
|
||||
features, &chainhash,
|
||||
&scid,
|
||||
&nodeid[lesser_key],
|
||||
&nodeid[!lesser_key],
|
||||
&bitcoin[lesser_key],
|
||||
&bitcoin[!lesser_key]);
|
||||
sha256_double(&hash, cannounce + channel_announcement_offset,
|
||||
tal_count(cannounce) - channel_announcement_offset);
|
||||
sign_hash(&node_privkey[0], &hash, &nodesig[0]);
|
||||
sign_hash(&funding_privkey[0], &hash, &bitcoinsig[0]);
|
||||
sign_hash(&node_privkey[1], &hash, &nodesig[1]);
|
||||
sign_hash(&funding_privkey[1], &hash, &bitcoinsig[1]);
|
||||
|
||||
printf("type=channel_announcement\n");
|
||||
printf(" node_signature_1=%s\n", sig_as_hex(&nodesig[lesser_key]));
|
||||
printf(" node_signature_2=%s\n", sig_as_hex(&nodesig[!lesser_key]));
|
||||
printf(" bitcoin_signature_1=%s\n", sig_as_hex(&bitcoinsig[lesser_key]));
|
||||
printf(" bitcoin_signature_2=%s\n", sig_as_hex(&bitcoinsig[!lesser_key]));
|
||||
printf(" features=%s\n", tal_hex(NULL, features));
|
||||
printf(" chain_hash=%s\n", tal_hexstr(NULL, &chainhash, sizeof(chainhash)));
|
||||
printf(" short_channel_id=%s\n", short_channel_id_to_str(NULL, &scid));
|
||||
printf(" node_id_1=%s\n",
|
||||
node_id_to_hexstr(NULL, &nodeid[lesser_key]));
|
||||
printf(" node_id_2=%s\n",
|
||||
node_id_to_hexstr(NULL, &nodeid[!lesser_key]));
|
||||
printf(" bitcoin_key_1=%s\n",
|
||||
pubkey_to_hexstr(NULL, &bitcoin[lesser_key]));
|
||||
printf(" bitcoin_key_2=%s\n",
|
||||
pubkey_to_hexstr(NULL, &bitcoin[!lesser_key]));
|
||||
|
||||
printf("\n#Node 1:\n");
|
||||
print_update(&chainhash, &scid, &opts[0], lesser_key == 0,
|
||||
&node_privkey[0]);
|
||||
print_nannounce(&nodeid[0], &opts[0], &node_privkey[0]);
|
||||
|
||||
printf("\n#Node 2:\n");
|
||||
print_update(&chainhash, &scid, &opts[1], lesser_key == 1,
|
||||
&node_privkey[1]);
|
||||
|
||||
print_nannounce(&nodeid[1], &opts[1], &node_privkey[1]);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user