diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d930423..23d857406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,6 +103,9 @@ provide appropriate suffixes for JSON input fields. - You can no longer make giant unpayable "wumbo" invoices. - CLTV of total route now correctly evaluated when finding best route. - `riskfactor` arguments to `pay` and `getroute` now have an effect. +- Fixed the version of bip32 private_key to BIP32_VER_MAIN_PRIVATE: we used + BIP32_VER_MAIN_PRIVATE for bitcoin/litecoin mainnet, and BIP32_VER_TEST_PRIVATE + for others. (PR #2436) ### Security diff --git a/bitcoin/chainparams.c b/bitcoin/chainparams.c index ef070e8e7..871ea8205 100644 --- a/bitcoin/chainparams.c +++ b/bitcoin/chainparams.c @@ -3,6 +3,13 @@ #include #include +/* Version codes for BIP32 extended keys in libwally-core. + * Stolen from wally_bip32.h in libwally-core*/ +#define BIP32_VER_MAIN_PUBLIC 0x0488B21E +#define BIP32_VER_MAIN_PRIVATE 0x0488ADE4 +#define BIP32_VER_TEST_PUBLIC 0x043587CF +#define BIP32_VER_TEST_PRIVATE 0x04358394 + const struct chainparams networks[] = { {.network_name = "bitcoin", .bip173_name = "bc", @@ -21,7 +28,8 @@ const struct chainparams networks[] = { .max_payment = AMOUNT_MSAT_INIT(0xFFFFFFFFULL), /* "Lightning Charge Powers Developers & Blockstream Store" */ .when_lightning_became_cool = 504500, - .testnet = false}, + .testnet = false, + .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_MAIN_PUBLIC, .bip32_privkey_version = BIP32_VER_MAIN_PRIVATE}}, {.network_name = "regtest", .bip173_name = "bcrt", .genesis_blockhash = {{{.u.u8 = {0x06, 0x22, 0x6e, 0x46, 0x11, 0x1a, 0x0b, 0x59, 0xca, 0xaf, 0x12, 0x60, 0x43, 0xeb, 0x5b, 0xbf, 0x28, 0xc3, 0x4f, 0x3a, 0x5e, 0x33, 0x2a, 0x1f, 0xc7, 0xb2, 0xb7, 0x3c, 0xf1, 0x88, 0x91, 0x0f}}}}, @@ -32,7 +40,8 @@ const struct chainparams networks[] = { .max_funding = AMOUNT_SAT_INIT((1 << 24) - 1), .max_payment = AMOUNT_MSAT_INIT(0xFFFFFFFFULL), .when_lightning_became_cool = 1, - .testnet = true}, + .testnet = true, + .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC, .bip32_privkey_version = BIP32_VER_TEST_PRIVATE}}, {.network_name = "testnet", .bip173_name = "tb", .genesis_blockhash = {{{.u.u8 = {0x43, 0x49, 0x7f, 0xd7, 0xf8, 0x26, 0x95, 0x71, 0x08, 0xf4, 0xa3, 0x0f, 0xd9, 0xce, 0xc3, 0xae, 0xba, 0x79, 0x97, 0x20, 0x84, 0xe9, 0x0e, 0xad, 0x01, 0xea, 0x33, 0x09, 0x00, 0x00, 0x00, 0x00}}}}, @@ -42,7 +51,8 @@ const struct chainparams networks[] = { .dust_limit = { 546 }, .max_funding = AMOUNT_SAT_INIT((1 << 24) - 1), .max_payment = AMOUNT_MSAT_INIT(0xFFFFFFFFULL), - .testnet = true}, + .testnet = true, + .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC, .bip32_privkey_version = BIP32_VER_TEST_PRIVATE}}, {.network_name = "litecoin", .bip173_name = "ltc", .genesis_blockhash = {{{.u.u8 = {0xe2, 0xbf, 0x04, 0x7e, 0x7e, 0x5a, 0x19, 0x1a, 0xa4, 0xef, 0x34, 0xd3, 0x14, 0x97, 0x9d, 0xc9, 0x98, 0x6e, 0x0f, 0x19, 0x25, 0x1e, 0xda, 0xba, 0x59, 0x40, 0xfd, 0x1f, 0xe3, 0x65, 0xa7, 0x12 }}}}, @@ -53,7 +63,8 @@ const struct chainparams networks[] = { .max_funding = AMOUNT_SAT_INIT(60 * ((1 << 24) - 1)), .max_payment = AMOUNT_MSAT_INIT(60 * 0xFFFFFFFFULL), .when_lightning_became_cool = 1320000, - .testnet = false}, + .testnet = false, + .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_MAIN_PUBLIC, .bip32_privkey_version = BIP32_VER_MAIN_PRIVATE}}, {.network_name = "litecoin-testnet", .bip173_name = "tltc", .genesis_blockhash = {{{.u.u8 = { 0xa0, 0x29, 0x3e, 0x4e, 0xeb, 0x3d, 0xa6, 0xe6, 0xf5, 0x6f, 0x81, 0xed, 0x59, 0x5f, 0x57, 0x88, 0x0d, 0x1a, 0x21, 0x56, 0x9e, 0x13, 0xee, 0xfd, 0xd9, 0x51, 0x28, 0x4b, 0x5a, 0x62, 0x66, 0x49 }}}}, @@ -64,7 +75,8 @@ const struct chainparams networks[] = { .max_funding = AMOUNT_SAT_INIT(60 * ((1 << 24) - 1)), .max_payment = AMOUNT_MSAT_INIT(60 * 0xFFFFFFFFULL), .when_lightning_became_cool = 1, - .testnet = true} + .testnet = true, + .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC, .bip32_privkey_version = BIP32_VER_TEST_PRIVATE}} }; const struct chainparams *chainparams_for_network(const char *network_name) diff --git a/bitcoin/chainparams.h b/bitcoin/chainparams.h index 715e37b52..42e62d431 100644 --- a/bitcoin/chainparams.h +++ b/bitcoin/chainparams.h @@ -7,6 +7,11 @@ #include #include +struct bip32_key_version { + u32 bip32_pubkey_version; + u32 bip32_privkey_version; +}; + struct chainparams { const char *network_name; const char *bip173_name; @@ -21,6 +26,9 @@ struct chainparams { /* Whether this is a test network or not */ const bool testnet; + + /* Version codes for BIP32 extended keys in libwally-core*/ + const struct bip32_key_version bip32_key_version; }; /** diff --git a/hsmd/hsm_wire.csv b/hsmd/hsm_wire.csv index 88f523d91..7b25eddb0 100644 --- a/hsmd/hsm_wire.csv +++ b/hsmd/hsm_wire.csv @@ -5,8 +5,10 @@ hsmstatus_client_bad_request,,description,wirestring hsmstatus_client_bad_request,,len,u16 hsmstatus_client_bad_request,,msg,len*u8 +#include # Start the HSM. hsm_init,11 +hsm_init,,bip32_key_version,struct bip32_key_version #include hsm_init_reply,111 diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 1a079f697..79f7a13bb 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -66,6 +66,11 @@ static struct { struct ext_key bip32; } secretstuff; +/* Version codes for BIP32 extended keys in libwally-core. + * It's not suitable to add this struct into client struct, + * so set it static.*/ +static struct bip32_key_version bip32_key_version; + /*~ We keep track of clients, but there's not much to keep. */ struct client { /* The ccan/io async io connection for this client: it closes, we die. */ @@ -351,7 +356,16 @@ static void populate_secretstuff(void) u32 salt = 0; struct ext_key master_extkey, child_extkey; + assert(bip32_key_version.bip32_pubkey_version == BIP32_VER_MAIN_PUBLIC + || bip32_key_version.bip32_pubkey_version == BIP32_VER_TEST_PUBLIC); + + assert(bip32_key_version.bip32_privkey_version == BIP32_VER_MAIN_PRIVATE + || bip32_key_version.bip32_privkey_version == BIP32_VER_TEST_PRIVATE); + /* Fill in the BIP32 tree for bitcoin addresses. */ + /* In libwally-core, the version BIP32_VER_TEST_PRIVATE is for testnet/regtest, + * and BIP32_VER_MAIN_PRIVATE is for mainnet. For litecoin, we also set it like + * bitcoin else.*/ do { hkdf_sha256(bip32_seed, sizeof(bip32_seed), &salt, sizeof(salt), @@ -360,7 +374,7 @@ static void populate_secretstuff(void) "bip32 seed", strlen("bip32 seed")); salt++; } while (bip32_key_from_seed(bip32_seed, sizeof(bip32_seed), - BIP32_VER_TEST_PRIVATE, + bip32_key_version.bip32_privkey_version, 0, &master_extkey) != WALLY_OK); /* BIP 32: @@ -380,7 +394,8 @@ static void populate_secretstuff(void) * separate keychains for these should use the external one for * everything. * - * - m/iH/0/k corresponds to the k'th keypair of the external chain of account number i of the HDW derived from master m. + * - m/iH/0/k corresponds to the k'th keypair of the external chain of + * account number i of the HDW derived from master m. */ /* Hence child 0, then child 0 again to get extkey to derive from. */ if (bip32_key_from_parent(&master_extkey, 0, BIP32_FLAG_KEY_PRIVATE, @@ -522,7 +537,7 @@ static struct io_plan *init_hsm(struct io_conn *conn, * definitions in hsm_client_wire.csv. The format of those files is * an extension of the simple comma-separated format output by the * BOLT tools/extract-formats.py tool. */ - if (!fromwire_hsm_init(msg_in)) + if (!fromwire_hsm_init(msg_in, &bip32_key_version)) return bad_req(conn, c, msg_in); maybe_create_new_hsm(); diff --git a/lightningd/hsm_control.c b/lightningd/hsm_control.c index 030f165ea..ec8575384 100644 --- a/lightningd/hsm_control.c +++ b/lightningd/hsm_control.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -92,7 +93,8 @@ void hsm_init(struct lightningd *ld) err(1, "Could not subd hsm"); ld->hsm_fd = fds[0]; - if (!wire_sync_write(ld->hsm_fd, towire_hsm_init(tmpctx))) + if (!wire_sync_write(ld->hsm_fd, towire_hsm_init(tmpctx, + &ld->topology->bitcoind->chainparams->bip32_key_version))) err(1, "Writing init msg to hsm"); ld->wallet->bip32_base = tal(ld->wallet, struct ext_key); diff --git a/wire/fromwire.c b/wire/fromwire.c index 4490fe11d..b7d5a6ad1 100644 --- a/wire/fromwire.c +++ b/wire/fromwire.c @@ -1,4 +1,5 @@ #include "wire.h" +#include #include #include #include @@ -288,3 +289,9 @@ struct amount_sat fromwire_amount_sat(const u8 **cursor, size_t *max) 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); +} diff --git a/wire/towire.c b/wire/towire.c index 9b71d1193..35bcb6bcd 100644 --- a/wire/towire.c +++ b/wire/towire.c @@ -1,5 +1,6 @@ #include "wire.h" #include +#include #include #include #include @@ -193,3 +194,9 @@ void towire_amount_sat(u8 **pptr, const struct amount_sat sat) { towire_u64(pptr, sat.satoshis); /* Raw: primitive */ } + +void towire_bip32_key_version(u8 **pptr, const struct bip32_key_version *version) +{ + towire_u32(pptr, version->bip32_pubkey_version); + towire_u32(pptr, version->bip32_privkey_version); +} \ No newline at end of file diff --git a/wire/wire.h b/wire/wire.h index c615a8660..c72c350a2 100644 --- a/wire/wire.h +++ b/wire/wire.h @@ -2,6 +2,7 @@ #define LIGHTNING_WIRE_WIRE_H #include "config.h" #include +#include #include #include #include @@ -73,6 +74,8 @@ void towire_bitcoin_tx(u8 **pptr, const struct bitcoin_tx *tx); void towire_wirestring(u8 **pptr, const char *str); void towire_siphash_seed(u8 **cursor, const struct siphash_seed *seed); +void towire_bip32_key_version(u8 **cursor, const struct bip32_key_version *version); + const u8 *fromwire(const u8 **cursor, size_t *max, void *copy, size_t n); u8 fromwire_u8(const u8 **cursor, size_t *max); u16 fromwire_u16(const u8 **cursor, size_t *max); @@ -115,4 +118,6 @@ struct bitcoin_tx *fromwire_bitcoin_tx(const tal_t *ctx, const u8 **cursor, size_t *max); void fromwire_siphash_seed(const u8 **cursor, size_t *max, struct siphash_seed *seed); +void fromwire_bip32_key_version(const u8 **cursor, size_t *max, + struct bip32_key_version *version); #endif /* LIGHTNING_WIRE_WIRE_H */