Use libbase58 for base58 decoding

This commit is contained in:
Luke Dashjr 2014-08-22 19:07:56 +00:00
parent 4b87cfeeaa
commit d46062c7e6
5 changed files with 28 additions and 87 deletions

View File

@ -15,7 +15,12 @@ libblkmaker_@LIBBLKMAKER_API_VERSION@_la_SOURCES = \
hex.c \
private.h
libblkmaker_@LIBBLKMAKER_API_VERSION@_la_LDFLAGS = -version-info $(LIBBLKMAKER_SO_VERSION) -no-undefined
libblkmaker_@LIBBLKMAKER_API_VERSION@_la_CFLAGS = \
$(libbase58_CFLAGS)
libblkmaker_@LIBBLKMAKER_API_VERSION@_la_LDFLAGS = \
$(libbase58_LIBS) \
-no-undefined \
-version-info $(LIBBLKMAKER_SO_VERSION)
libblkmaker_includedir = $(includedir)/libblkmaker-$(LIBBLKMAKER_API_VERSION)
libblkmaker_include_HEADERS = \

View File

@ -15,6 +15,8 @@
#include <stdint.h>
#include <string.h>
#include <libbase58.h>
#include <blkmaker.h>
#include "private.h"
@ -31,96 +33,28 @@ static const int8_t b58digits[] = {
};
bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz) {
const unsigned char *b58u = (void*)b58;
unsigned char *binu = bin;
size_t outisz = (binsz + 3) / 4;
uint32_t outi[outisz];
uint64_t t;
uint32_t c;
size_t i, j;
uint8_t bytesleft = binsz % 4;
uint32_t zeromask = ~((1 << ((bytesleft ?: 4) * 8)) - 1);
if (!b58sz)
b58sz = strlen(b58);
memset(outi, 0, outisz * sizeof(*outi));
for (i = 0; i < b58sz; ++i)
{
if (b58u[i] & 0x80)
// High-bit set on invalid digit
return false;
if (b58digits[b58u[i]] == -1)
// Invalid base58 digit
return false;
c = b58digits[b58u[i]];
for (j = outisz; j--; )
{
t = ((uint64_t)outi[j]) * 58 + c;
c = (t & 0x3f00000000) >> 32;
outi[j] = t & 0xffffffff;
}
if (c)
// Output number too big (carry to the next int32)
return false;
if (outi[0] & zeromask)
// Output number too big (last int32 filled too far)
return false;
}
j = 0;
switch (bytesleft) {
case 3:
*(binu++) = (outi[0] & 0xff0000) >> 16;
case 2:
*(binu++) = (outi[0] & 0xff00) >> 8;
case 1:
*(binu++) = (outi[0] & 0xff);
++j;
default:
break;
}
for (; j < outisz; ++j)
{
*(binu++) = outi[j] >> 0x18;
*(binu++) = outi[j] >> 0x10;
*(binu++) = outi[j] >> 8;
*(binu++) = outi[j];
}
return true;
return b58tobin(bin, &binsz, b58, b58sz);
}
int _blkmk_b58check(void *bin, size_t binsz, const char *base58str) {
unsigned char buf[32];
unsigned char *binc = bin;
unsigned i;
if (binsz < 4)
return -4;
if (!_blkmk_dblsha256(buf, bin, binsz - 4))
return -2;
if (memcmp(&binc[binsz - 4], buf, 4))
return -1;
// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i)
{} // Just finding the end of zeros, nothing to do in loop
if (binc[i] == '\0' || base58str[i] == '1')
return -3;
return binc[0];
if (!b58_sha256_impl)
b58_sha256_impl = blkmk_sha256_impl;
return b58check(bin, binsz, base58str, 34);
}
size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) {
unsigned char addrbin[25];
unsigned char *cout = out;
const size_t b58sz = strlen(addr);
int addrver;
size_t rv;
if (!_blkmk_b58tobin(addrbin, sizeof(addrbin), addr, 0))
rv = sizeof(addrbin);
if (!b58_sha256_impl)
b58_sha256_impl = blkmk_sha256_impl;
if (!b58tobin(addrbin, &rv, addr, b58sz))
return 0;
addrver = _blkmk_b58check(addrbin, sizeof(addrbin), addr);
addrver = b58check(addrbin, sizeof(addrbin), addr, b58sz);
switch (addrver) {
case 0: // Bitcoin pubkey hash
case 111: // Testnet pubkey hash

View File

@ -47,6 +47,8 @@ PKG_CHECK_MODULES([JANSSON],[jansson],[
AC_SUBST(JANSSON_CFLAGS)
AC_SUBST(JANSSON_LIBS)
PKG_CHECK_MODULES([libbase58],[libbase58])
AC_CHECK_LIB([ws2_32], [strchr])
AC_OUTPUT

View File

@ -12,6 +12,7 @@
#include <arpa/inet.h>
#include <gcrypt.h>
#include <libbase58.h>
#include <blkmaker.h>
#include <blkmaker_jansson.h>
@ -23,20 +24,23 @@ void testb58() {
int rv;
const char *iaddr = "11Baf75Ferj6A7AoN565gCQj9kGWbDMHfN9";
const char *addr = &iaddr[1];
const size_t addrlen = strlen(addr);
size_t actuallen;
char bufx[26] = {'\xff'};
char *buf = &bufx[1];
if (!_blkmk_b58tobin(buf, 25, addr, 0))
actuallen = 25;
if (!b58tobin(buf, &actuallen, addr, addrlen))
exit(1);
if (bufx[0] != '\xff')
exit(2);
char cbuf[51];
_blkmk_bin2hex(cbuf, buf, 25);
printf("Base58 raw data: %s\n", cbuf);
assert((rv = _blkmk_b58check(buf, 25, addr)) == 0);
assert((rv = b58check(buf, 25, addr, addrlen)) == 0);
printf("Base58 check: %d\n", rv);
assert((rv = _blkmk_b58check(buf, 25, &addr[1])) < 0);
assert((rv = b58check(buf, 25, &addr[1], addrlen)) < 0);
printf("Base58 check (invalid/ unpadded): %d\n", rv);
assert((rv = _blkmk_b58check(buf, 25, iaddr)) < 0);
assert((rv = b58check(buf, 25, iaddr, addrlen + 1)) < 0);
printf("Base58 check (invalid/extra padded): %d\n", rv);
}

View File

@ -14,10 +14,6 @@ extern void _blktxn_free(struct blktxn_t *);
extern void _blkmk_bin2hex(char *out, const void *data, size_t datasz);
extern bool _blkmk_hex2bin(void *o, const char *x, size_t len);
// base58.c
extern bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz);
extern int _blkmk_b58check(void *bin, size_t binsz, const char *b58);
// inline
// NOTE: This must return 0 for 0