From 04fd2c861fc70d9dd18d6c5f3115d76f6a09983e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 22 Jan 2016 06:41:46 +1030 Subject: [PATCH] bitcoin/base58: p2sh address support. Signed-off-by: Rusty Russell --- bitcoin/base58.c | 76 ++++++++++++++++++++++++++++++++++++------------ bitcoin/base58.h | 7 +++++ 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/bitcoin/base58.c b/bitcoin/base58.c index eee46a491..89980e0b7 100644 --- a/bitcoin/base58.c +++ b/bitcoin/base58.c @@ -140,30 +140,39 @@ void base58_get_checksum(u8 csum[4], const u8 buf[], size_t buflen) memcpy(csum, sha_result.sha.u.u8, 4); } -char *bitcoin_to_base58(const tal_t *ctx, bool test_net, - const struct bitcoin_address *addr) +static char *to_base58(const tal_t *ctx, u8 version, + const struct ripemd160 *rmd) { - u8 buf[1 + sizeof(addr->addr) + 4]; + u8 buf[1 + sizeof(*rmd) + 4]; char out[BASE58_ADDR_MAX_LEN + 2], *p; - buf[0] = test_net ? 111 : 0; - - BUILD_ASSERT(sizeof(addr->addr) == sizeof(struct ripemd160)); - memcpy(buf+1, addr, sizeof(addr->addr)); + buf[0] = version; + memcpy(buf+1, rmd, sizeof(*rmd)); /* Append checksum */ - base58_get_checksum(buf + 1 + sizeof(addr->addr), - buf, 1 + sizeof(addr->addr)); + base58_get_checksum(buf + 1 + sizeof(*rmd), buf, 1 + sizeof(*rmd)); p = encode_base58(out, BASE58_ADDR_MAX_LEN, buf, sizeof(buf)); return tal_strdup(ctx, p); } -bool bitcoin_from_base58(bool *test_net, - struct bitcoin_address *addr, - const char *base58, size_t base58_len) +char *bitcoin_to_base58(const tal_t *ctx, bool test_net, + const struct bitcoin_address *addr) { - u8 buf[1 + sizeof(addr->addr) + 4]; + return to_base58(ctx, test_net ? 111 : 0, &addr->addr); +} + +char *p2sh_to_base58(const tal_t *ctx, bool test_net, + const struct ripemd160 *p2sh) +{ + return to_base58(ctx, test_net ? 196 : 5, p2sh); +} + +static bool from_base58(u8 *version, + struct ripemd160 *rmd, + const char *base58, size_t base58_len) +{ + u8 buf[1 + sizeof(*rmd) + 4]; BIGNUM bn; size_t len; u8 csum[4]; @@ -180,18 +189,49 @@ bool bitcoin_from_base58(bool *test_net, BN_bn2bin(&bn, buf + sizeof(buf) - len); BN_free(&bn); - if (buf[0] == 111) + *version = buf[0]; + + base58_get_checksum(csum, buf, 1 + sizeof(*rmd)); + if (memcmp(csum, buf + 1 + sizeof(*rmd), sizeof(csum)) != 0) + return false; + + memcpy(rmd, buf+1, sizeof(*rmd)); + return true; +} + +bool bitcoin_from_base58(bool *test_net, + 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 (buf[0] == 0) + else if (version == 0) *test_net = false; else return false; + return true; +} + +bool p2sh_from_base58(bool *test_net, + struct ripemd160 *p2sh, + const char *base58, size_t len) +{ + u8 version; - base58_get_checksum(csum, buf, 1 + sizeof(addr->addr)); - if (memcmp(csum, buf + 1 + sizeof(addr->addr), sizeof(csum)) != 0) + if (!from_base58(&version, p2sh, base58, len)) return false; - memcpy(&addr->addr, buf+1, sizeof(addr->addr)); + if (version == 196) + *test_net = true; + else if (version == 5) + *test_net = false; + else + return false; return true; } diff --git a/bitcoin/base58.h b/bitcoin/base58.h index 7111361d3..1c37cb337 100644 --- a/bitcoin/base58.h +++ b/bitcoin/base58.h @@ -31,6 +31,13 @@ bool bitcoin_from_base58(bool *test_net, 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 ripemd_from_base58(u8 *version, struct ripemd160 *ripemd160, const char *base58);