[Pettycoin-dev] [raw_decode_base_n PATCH 2/3] Add function raw_decode_base_n

Nelson Castillo nelsoneci at gmail.com
Thu Aug 14 20:28:50 EST 2014


Generalize raw_decode_base58 and make raw_decode_base58 depend on
raw_decode_base_n.

This will make it decoding from other bases easier in the future.

Signed-off-by: Nelson Castillo <nelsoneci at gmail.com>
---
 base58.c             |   43 ++++++++++++++++++++++++++++++++++---------
 base58.h             |    1 +
 test/run-01-base58.c |   10 +++++-----
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/base58.c b/base58.c
index bdf5ea2..cd3f960 100644
--- a/base58.c
+++ b/base58.c
@@ -12,16 +12,17 @@
 #include <openssl/sha.h>
 #include <string.h>
 
-static const char enc[] =
+static const char enc_16[] = "0123456789abcdef";
+static const char enc_58[] =
 	"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
 
-static char encode_char(unsigned long val)
+static char encode_char(unsigned long val, const char *enc)
 {
 	assert(val < strlen(enc));
 	return enc[val];
 }
 
-static int decode_char(char c)
+static int decode_char(char c, const char *enc)
 {
 	const char *pos = strchr(enc, c);
 	if (!pos)
@@ -58,7 +59,7 @@ static char *encode_base58(char *buf, size_t buflen,
 			p = NULL;
 			goto out;
 		}
-		*p = encode_char(rem);
+		*p = encode_char(rem, enc_58);
 	}
 
 	/* Now, this is really weird.  We pad with zeroes, but not at
@@ -69,7 +70,7 @@ static char *encode_base58(char *buf, size_t buflen,
 			p = NULL;
 			goto out;
 		}
-		*p = encode_char(0);
+		*p = encode_char(0, enc_58);
 		data_len--;
 		data++;
 	}
@@ -80,19 +81,35 @@ out:
 }
 
 /*
- * Decode a base58-encoded string into a byte sequence.
+ * Decode a base_n-encoded string into a byte sequence.
  */
-bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len)
+bool raw_decode_base_n(BIGNUM *bn, const char *src, size_t len, int base)
 {
+	const char *enc;
+
 	BN_zero(bn);
 
+	assert(base == 16 || base == 58);
+	switch (base) {
+	case 16:
+		enc = enc_16;
+		break;
+	case 58:
+		enc = enc_58;
+		break;
+	}
+
 	while (len) {
-		int val = decode_char(*src);
+		char current = *src;
+
+		if (base == 16)
+			current = tolower(current);	/* TODO: Not in ccan. */
+		int val = decode_char(current, enc);
 		if (val < 0) {
 			BN_free(bn);
 			return false;
 		}
-		BN_mul_word(bn, 58);
+		BN_mul_word(bn, base);
 		BN_add_word(bn, val);
 		src++;
 		len--;
@@ -101,6 +118,14 @@ bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len)
 	return true;
 }
 
+/*
+ * Decode a base58-encoded string into a byte sequence.
+ */
+bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len)
+{
+	return raw_decode_base_n(bn, src, len, 58);
+}
+
 void base58_get_checksum(u8 csum[4], const u8 buf[], size_t buflen)
 {
 	SHA256_CTX sha256;
diff --git a/base58.h b/base58.h
index bcaa211..d324049 100644
--- a/base58.h
+++ b/base58.h
@@ -42,6 +42,7 @@ char *key_to_base58(const tal_t *ctx, bool test_net, EC_KEY *key,
 EC_KEY *key_from_base58(const char *base58, size_t base58_len,
 			bool *test_net, struct protocol_pubkey *key);
 
+bool raw_decode_base_n(BIGNUM *bn, const char *src, size_t len, int base);
 bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len);
 void base58_get_checksum(u8 csum[4], const u8 buf[], size_t buflen);
 
diff --git a/test/run-01-base58.c b/test/run-01-base58.c
index 1fbc7bf..f0a4e79 100644
--- a/test/run-01-base58.c
+++ b/test/run-01-base58.c
@@ -18,7 +18,7 @@ int main(void)
 	assert(tal_parent(p) == ctx);
 	assert(p[0] == 'P');
 	assert(strlen(p) < BASE58_ADDR_MAX_LEN);
-	assert(strspn(p, enc) == strlen(p));
+	assert(strspn(p, enc_58) == strlen(p));
 	memset(&addr2, 0, sizeof(addr2));
 	assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
 	assert(test_net == false);
@@ -29,7 +29,7 @@ int main(void)
 	assert(tal_parent(p) == ctx);
 	assert(p[0] == 'q');
 	assert(strlen(p) < BASE58_ADDR_MAX_LEN);
-	assert(strspn(p, enc) == strlen(p));
+	assert(strspn(p, enc_58) == strlen(p));
 	memset(&addr2, 0, sizeof(addr2));
 	assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
 	assert(test_net == true);
@@ -40,7 +40,7 @@ int main(void)
 	assert(tal_parent(p) == ctx);
 	assert(strstarts(p, "P-1"));
 	assert(strlen(p) < BASE58_ADDR_MAX_LEN + 2);
-	assert(strspn(p+2, enc) == strlen(p+2));
+	assert(strspn(p+2, enc_58) == strlen(p+2));
 	memset(&addr2, 0, sizeof(addr2));
 	assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
 	assert(test_net == false);
@@ -51,7 +51,7 @@ int main(void)
 	assert(tal_parent(p) == ctx);
 	assert(strstarts(p, "P-m") || strstarts(p, "P-n"));
 	assert(strlen(p) < BASE58_ADDR_MAX_LEN + 2);
-	assert(strspn(p+2, enc) == strlen(p+2));
+	assert(strspn(p+2, enc_58) == strlen(p+2));
 	memset(&addr2, 0, sizeof(addr2));
 	assert(pettycoin_from_base58(&test_net, &addr2, p, strlen(p)));
 	assert(test_net == true);
@@ -75,7 +75,7 @@ int main(void)
 
 	/* Now, turn it into pettcoin-style key. */
 	p = key_to_base58(ctx, true, key, false);
-	assert(strspn(p, enc) == strlen(p));
+	assert(strspn(p, enc_58) == strlen(p));
 
 	/* Convert back, check it is OK. */
 	EC_KEY_free(key);



More information about the Pettycoin-dev mailing list