From 976800b419c67ff150cf710f42ad4b27c4ceec54 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Mon, 29 Apr 2019 20:09:06 +0200 Subject: [PATCH 1/3] chainparams: Add p2pkh and p2sh versions to chinparams Signed-off-by: Christian Decker Co-authored-by: bisoge --- bitcoin/chainparams.c | 10 ++++++++++ bitcoin/chainparams.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/bitcoin/chainparams.c b/bitcoin/chainparams.c index 871ea82059ee..7dd9db9dd531 100644 --- a/bitcoin/chainparams.c +++ b/bitcoin/chainparams.c @@ -28,6 +28,8 @@ const struct chainparams networks[] = { .max_payment = AMOUNT_MSAT_INIT(0xFFFFFFFFULL), /* "Lightning Charge Powers Developers & Blockstream Store" */ .when_lightning_became_cool = 504500, + .p2pkh_version = 0, + .p2sh_version = 5, .testnet = false, .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_MAIN_PUBLIC, .bip32_privkey_version = BIP32_VER_MAIN_PRIVATE}}, {.network_name = "regtest", @@ -40,6 +42,8 @@ const struct chainparams networks[] = { .max_funding = AMOUNT_SAT_INIT((1 << 24) - 1), .max_payment = AMOUNT_MSAT_INIT(0xFFFFFFFFULL), .when_lightning_became_cool = 1, + .p2pkh_version = 111, + .p2sh_version = 196, .testnet = true, .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC, .bip32_privkey_version = BIP32_VER_TEST_PRIVATE}}, {.network_name = "testnet", @@ -51,6 +55,8 @@ const struct chainparams networks[] = { .dust_limit = { 546 }, .max_funding = AMOUNT_SAT_INIT((1 << 24) - 1), .max_payment = AMOUNT_MSAT_INIT(0xFFFFFFFFULL), + .p2pkh_version = 111, + .p2sh_version = 196, .testnet = true, .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC, .bip32_privkey_version = BIP32_VER_TEST_PRIVATE}}, {.network_name = "litecoin", @@ -63,6 +69,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, + .p2pkh_version = 48, + .p2sh_version = 50, .testnet = false, .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_MAIN_PUBLIC, .bip32_privkey_version = BIP32_VER_MAIN_PRIVATE}}, {.network_name = "litecoin-testnet", @@ -75,6 +83,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, + .p2pkh_version = 111, + .p2sh_version = 58, .testnet = true, .bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC, .bip32_privkey_version = BIP32_VER_TEST_PRIVATE}} }; diff --git a/bitcoin/chainparams.h b/bitcoin/chainparams.h index 42e62d431324..493c6a9d5403 100644 --- a/bitcoin/chainparams.h +++ b/bitcoin/chainparams.h @@ -23,6 +23,8 @@ struct chainparams { const struct amount_sat max_funding; const struct amount_msat max_payment; const u32 when_lightning_became_cool; + const u8 p2pkh_version; + const u8 p2sh_version; /* Whether this is a test network or not */ const bool testnet; From 60ed8c1aa1a2b27371541f2b87a55eac78dab8a5 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 30 Apr 2019 20:43:18 +0200 Subject: [PATCH 2/3] base58: Add function to just parse a ripemd160 hash This is an intermediate step since the only difference between p2pkh and p2sh is the argument that the parsing functions take, and parsing twice for that reason alone is quite useless. Signed-off-by: Christian Decker --- bitcoin/base58.c | 6 ++++++ bitcoin/base58.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/bitcoin/base58.c b/bitcoin/base58.c index 65281af024e0..056739871cb5 100644 --- a/bitcoin/base58.c +++ b/bitcoin/base58.c @@ -103,6 +103,12 @@ bool p2sh_from_base58(bool *test_net, return true; } +bool ripemd160_from_base58(u8 *version, struct ripemd160 *rmd, + const char *base58, size_t base58_len) +{ + return from_base58(version, rmd, base58, base58_len); +} + bool key_from_base58(const char *base58, size_t base58_len, bool *test_net, struct privkey *priv, struct pubkey *key) { diff --git a/bitcoin/base58.h b/bitcoin/base58.h index cff8f85e944a..939eac27b563 100644 --- a/bitcoin/base58.h +++ b/bitcoin/base58.h @@ -29,4 +29,8 @@ bool p2sh_from_base58(bool *test_net, bool key_from_base58(const char *base58, size_t base58_len, bool *test_net, struct privkey *priv, struct pubkey *key); +/* Decode a p2pkh or p2sh into the ripemd160 hash */ +bool ripemd160_from_base58(u8 *version, struct ripemd160 *rmd, + const char *base58, size_t base58_len); + #endif /* LIGHTNING_BITCOIN_BASE58_H */ From 6d3fd191b4e8bbc5805173b9b50bb681803bfb31 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 30 Apr 2019 22:10:50 +0200 Subject: [PATCH 3/3] base58: Simplified the address parsing We were deciding whether an address is a testnet address or not in the parser, and then checking whether it matches our expectation outside as well. This just returns the address version instead, and still checks it against our expectation, but without having the parser need to know about address types. Signed-off-by: Christian Decker --- bitcoin/base58.c | 34 ++++++---------------------------- bitcoin/base58.h | 8 +++----- lightningd/jsonrpc.c | 34 +++++++++++++++------------------- 3 files changed, 24 insertions(+), 52 deletions(-) diff --git a/bitcoin/base58.c b/bitcoin/base58.c index 056739871cb5..fe1226867eac 100644 --- a/bitcoin/base58.c +++ b/bitcoin/base58.c @@ -67,40 +67,18 @@ static bool from_base58(u8 *version, return true; } -bool bitcoin_from_base58(bool *test_net, - struct bitcoin_address *addr, +bool bitcoin_from_base58(u8 *version, struct bitcoin_address *addr, const char *base58, size_t len) { - u8 version; - - if (!from_base58(&version, &addr->addr, base58, len)) - return false; - - if (version == 111) - *test_net = true; - else if (version == 0) - *test_net = false; - else - return false; - return true; + return from_base58(version, &addr->addr, base58, len); } -bool p2sh_from_base58(bool *test_net, - struct ripemd160 *p2sh, - const char *base58, size_t len) -{ - u8 version; - if (!from_base58(&version, p2sh, base58, len)) - return false; +bool p2sh_from_base58(u8 *version, struct ripemd160 *p2sh, const char *base58, + size_t len) +{ - if (version == 196) - *test_net = true; - else if (version == 5) - *test_net = false; - else - return false; - return true; + return from_base58(version, p2sh, base58, len); } bool ripemd160_from_base58(u8 *version, struct ripemd160 *rmd, diff --git a/bitcoin/base58.h b/bitcoin/base58.h index 939eac27b563..4154b6a3d4db 100644 --- a/bitcoin/base58.h +++ b/bitcoin/base58.h @@ -15,16 +15,14 @@ struct bitcoin_address; /* Bitcoin address encoded in base58, with version and checksum */ char *bitcoin_to_base58(const tal_t *ctx, bool test_net, const struct bitcoin_address *addr); -bool bitcoin_from_base58(bool *test_net, - struct bitcoin_address *addr, +bool bitcoin_from_base58(u8 *version, struct bitcoin_address *addr, const char *base58, size_t len); /* P2SH address encoded as base58, with version and checksum */ char *p2sh_to_base58(const tal_t *ctx, bool test_net, const struct ripemd160 *p2sh); -bool p2sh_from_base58(bool *test_net, - struct ripemd160 *p2sh, - const char *base58, size_t len); +bool p2sh_from_base58(u8 *version, struct ripemd160 *p2sh, const char *base58, + size_t len); bool key_from_base58(const char *base58, size_t base58_len, bool *test_net, struct privkey *priv, struct pubkey *key); diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index 7e9af5c8d1b3..283fed0cab9e 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -957,8 +957,7 @@ json_tok_address_scriptpubkey(const tal_t *cxt, const char *buffer, const jsmntok_t *tok, const u8 **scriptpubkey) { - struct bitcoin_address p2pkh_destination; - struct ripemd160 p2sh_destination; + struct bitcoin_address destination; int witness_version; /* segwit_addr_net_decode requires a buffer of size 40, and will * not write to the buffer if the address is too long, so a buffer @@ -971,27 +970,24 @@ json_tok_address_scriptpubkey(const tal_t *cxt, bool parsed; bool right_network; - bool testnet; - - parsed = false; - if (bitcoin_from_base58(&testnet, &p2pkh_destination, - buffer + tok->start, tok->end - tok->start)) { - *scriptpubkey = scriptpubkey_p2pkh(cxt, &p2pkh_destination); - parsed = true; - right_network = (testnet == chainparams->testnet); - } else if (p2sh_from_base58(&testnet, &p2sh_destination, - buffer + tok->start, tok->end - tok->start)) { - *scriptpubkey = scriptpubkey_p2sh_hash(cxt, &p2sh_destination); - parsed = true; - right_network = (testnet == chainparams->testnet); - } - /* Insert other parsers that accept pointer+len here. */ + u8 addr_version; + + parsed = + ripemd160_from_base58(&addr_version, &destination.addr, + buffer + tok->start, tok->end - tok->start); if (parsed) { - if (right_network) + if (addr_version == chainparams->p2pkh_version) { + *scriptpubkey = scriptpubkey_p2pkh(cxt, &destination); return ADDRESS_PARSE_SUCCESS; - else + } else if (addr_version == chainparams->p2sh_version) { + *scriptpubkey = + scriptpubkey_p2sh_hash(cxt, &destination.addr); + return ADDRESS_PARSE_SUCCESS; + } else { return ADDRESS_PARSE_WRONG_NETWORK; + } + /* Insert other parsers that accept pointer+len here. */ } /* Generate null-terminated address. */