clightning-dumpkeys

dump clightning output descriptors
git clone git://jb55.com/clightning-dumpkeys
Log | Files | Refs | README | LICENSE

commit 2f924e29a9c2326b9332a71b6b8f15a2472d396d
parent ce655d05afe60a05c5a959e3562ef0d6255c40a5
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 25 May 2019 06:05:36 -0700

descriptor checksums working

Diffstat:
MMakefile | 1+
Mcheck.c | 11+++++++++++
Adescriptor.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adescriptor.h | 9+++++++++
4 files changed, 104 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -15,6 +15,7 @@ OBJS += compiler.o OBJS += ec.o OBJS += hash.o OBJS += base58.o +OBJS += descriptor.o SRCS=$(OBJS:.o=.c) diff --git a/check.c b/check.c @@ -1,8 +1,19 @@ #include "bip32.h" +#include "descriptor.h" #include <stdio.h> +#include <assert.h> +#include <string.h> + +#define streq(a, b) strcmp(a, b) == 0 int main() { + char checksum[9]; + const char desc[] = "combo(xpub661MyMwAqRbcEzDwwjzJhBnXBZpv9hdqY2JYRUtwzEZU6grFRhWkXx9c3HJ4EKR1Nvdwf5U3VoekstoKSKjfcJYhRrhMYeEzZzu2h7uZAQX/1/*)"; + const char *desc_check = "j38hxvh0"; + int ok = descriptor_checksum(desc, sizeof(desc)-1, checksum, sizeof(checksum)); + assert(ok); + assert(streq(checksum, desc_check)); return 0; } diff --git a/descriptor.c b/descriptor.c @@ -0,0 +1,83 @@ + +#include "short_types.h" +#include <stdlib.h> +#include <stdio.h> + +static const char CHECKSUM_CHARSET[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; + +static const char INPUT_CHARSET[] = + "0123456789()[],'/*abcdefgh@:$%{}" + "IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~" + "ijklmnopqrstuvwxyzABCDEFGH`#\"\\ "; + +static inline int charset_find(char ch) { + for (size_t i = 0; i < sizeof(INPUT_CHARSET); i++) { + if (INPUT_CHARSET[i] == ch) + return i; + } + return -1; +} + +static u64 polymod(u64 c, int val) +{ + u8 c0 = c >> 35; + c = ((c & 0x7ffffffff) << 5) ^ val; + if (c0 & 1) c ^= 0xf5dee51989; + if (c0 & 2) c ^= 0xa9fdca3312; + if (c0 & 4) c ^= 0x1bab10e32d; + if (c0 & 8) c ^= 0x3706b1677a; + if (c0 & 16) c ^= 0x644d626ffd; + return c; +} + + +int descriptor_checksum(const char *descriptor, int desc_size, char *checksum, + int checksum_capacity) +{ + if (checksum_capacity < 8+1) + return 0; + + checksum[0] = 0; + + int j; + u64 c = 1; + int cls = 0; + int clscount = 0; + + for (int i = 0; i < desc_size; i++) { + char ch = descriptor[i]; + int pos = charset_find(ch); + if (pos == -1) { + checksum[0] = 0; + return 0; + } + // Emit a symbol for the position inside the group, for every character. + c = polymod(c, pos & 31); + + // Accumulate the group numbers + cls = cls * 3 + (pos >> 5); + + if (++clscount == 3) { + c = polymod(c, cls); + cls = 0; + clscount = 0; + } + } + + if (clscount > 0) + c = polymod(c, cls); + + // Shift further to determine the checksum. + for (j = 0; j < 8; ++j) + c = polymod(c, 0); + + // Prevent appending zeroes from not affecting the checksum. + c ^= 1; + + for (j = 0; j < 8; ++j) + checksum[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31]; + + checksum[8] = 0; + + return 8; +} diff --git a/descriptor.h b/descriptor.h @@ -0,0 +1,9 @@ + +#ifndef DESCRIPTOR_H +#define DESCRIPTOR_H + + +int descriptor_checksum(const char *descriptor, int desc_size, char *checksum, + int checksum_capacity); + +#endif /* DESCRIPTOR_H */