Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify address parsing #2608

Merged
merged 3 commits into from
May 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 11 additions & 27 deletions bitcoin/base58.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,40 +67,24 @@ 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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it worth preserving this method (and the ones below) if they're just a wrapper for another?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was tempted to remove them, however the type-safety that this method gives (struct bitcoin_address wraps struct ripemd160) is worth it I think.

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)

bool p2sh_from_base58(u8 *version, struct ripemd160 *p2sh, const char *base58,
size_t len)
{
u8 version;

if (!from_base58(&version, p2sh, base58, len))
return false;
return from_base58(version, p2sh, base58, len);
}

if (version == 196)
*test_net = true;
else if (version == 5)
*test_net = false;
else
return false;
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,
Expand Down
12 changes: 7 additions & 5 deletions bitcoin/base58.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@ 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);

/* 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 */
10 changes: 10 additions & 0 deletions bitcoin/chainparams.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -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}}
};
Expand Down
2 changes: 2 additions & 0 deletions bitcoin/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
34 changes: 15 additions & 19 deletions lightningd/jsonrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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. */
Expand Down