shachain: allow overriding of number of bits, add cmdline tool.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 5 Dec 2016 05:48:20 +0000 (16:18 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 5 Dec 2016 05:53:26 +0000 (16:23 +1030)
lightning uses 48 bits, so this provides a quick utility for our test
vectors, and provides a nice example.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/crypto/shachain/shachain.c
ccan/crypto/shachain/shachain.h
ccan/crypto/shachain/tools/.gitignore [new file with mode: 0644]
ccan/crypto/shachain/tools/Makefile [new file with mode: 0644]
ccan/crypto/shachain/tools/shachain48.c [new file with mode: 0644]

index c6bd37e8f55c76cd72a2720669e8083d4d4585fe..2c9cb3d5464c42855d7e9d3dc0c18455ed6907ea 100644 (file)
@@ -5,8 +5,6 @@
 #include <string.h>
 #include <assert.h>
 
 #include <string.h>
 #include <assert.h>
 
-#define INDEX_BITS ((sizeof(shachain_index_t)) * CHAR_BIT)
-
 static void change_bit(unsigned char *arr, size_t index)
 {
        arr[index / CHAR_BIT] ^= (1 << (index % CHAR_BIT));
 static void change_bit(unsigned char *arr, size_t index)
 {
        arr[index / CHAR_BIT] ^= (1 << (index % CHAR_BIT));
@@ -15,11 +13,11 @@ static void change_bit(unsigned char *arr, size_t index)
 static unsigned int count_trailing_zeroes(shachain_index_t index)
 {
 #if HAVE_BUILTIN_CTZLL
 static unsigned int count_trailing_zeroes(shachain_index_t index)
 {
 #if HAVE_BUILTIN_CTZLL
-       return index ? (unsigned int)__builtin_ctzll(index) : INDEX_BITS;
+       return index ? (unsigned int)__builtin_ctzll(index) : SHACHAIN_BITS;
 #else
        unsigned int i;
 
 #else
        unsigned int i;
 
-       for (i = 0; i < INDEX_BITS; i++) {
+       for (i = 0; i < SHACHAIN_BITS; i++) {
                if (index & (1ULL << i))
                        break;
        }
                if (index & (1ULL << i))
                        break;
        }
@@ -81,7 +79,8 @@ bool shachain_add_hash(struct shachain *chain,
 
        /* You have to insert them in order! */
        assert(index == chain->min_index - 1 ||
 
        /* You have to insert them in order! */
        assert(index == chain->min_index - 1 ||
-              (index == (shachain_index_t)(-1ULL) && chain->num_valid == 0));
+              (index == (shachain_index_t)(UINT64_MAX >> (64 - SHACHAIN_BITS))
+               && chain->num_valid == 0));
 
        pos = count_trailing_zeroes(index);
 
 
        pos = count_trailing_zeroes(index);
 
index ba4ba11cd64c02d1d66a362d35bac98e39a2f0bc..90f2380ed39b89d8277db3542e669fcc22f7176e 100644 (file)
 #define shachain_index_t uint64_t
 #endif
 
 #define shachain_index_t uint64_t
 #endif
 
+#ifndef SHACHAIN_BITS
+#define SHACHAIN_BITS (sizeof(shachain_index_t) * 8)
+#endif
+
 /**
  * shachain_from_seed - Generate an unpredictable SHA from a seed value.
  * @seed: (secret) seed value to use
 /**
  * shachain_from_seed - Generate an unpredictable SHA from a seed value.
  * @seed: (secret) seed value to use
@@ -56,7 +60,7 @@ struct shachain {
        struct {
                shachain_index_t index;
                struct sha256 hash;
        struct {
                shachain_index_t index;
                struct sha256 hash;
-       } known[sizeof(shachain_index_t) * 8 + 1];
+       } known[SHACHAIN_BITS + 1];
 };
 
 /**
 };
 
 /**
diff --git a/ccan/crypto/shachain/tools/.gitignore b/ccan/crypto/shachain/tools/.gitignore
new file mode 100644 (file)
index 0000000..883658e
--- /dev/null
@@ -0,0 +1 @@
+shachain48
diff --git a/ccan/crypto/shachain/tools/Makefile b/ccan/crypto/shachain/tools/Makefile
new file mode 100644 (file)
index 0000000..a1b0177
--- /dev/null
@@ -0,0 +1,39 @@
+#! /usr/bin/make
+
+CCANDIR=../../../..
+CFLAGS=-Wall -Werror -O3 -I$(CCANDIR) -DSHACHAIN_BITS=48
+#CFLAGS=-Wall -Werror -g3 -I$(CCANDIR) -DSHACHAIN_BITS=48
+
+# 48 bit index for shachain.  This is what lightning uses.
+CCAN_OBJS:=ccan-str.o ccan-err.o ccan-hex.o ccan-shachain.o ccan-sha256.o ccan-rbuf.o
+
+all: shachain48
+
+shachain48: shachain48.o $(CCAN_OBJS)
+
+shachain48.o: $(CCANDIR)/ccan/crypto/shachain/shachain.h       \
+       $(CCANDIR)/ccan/str/hex/hex.h                   \
+       $(CCANDIR)/ccan/str/str.h                               \
+       $(CCANDIR)/ccan/err/err.h                               \
+       $(CCANDIR)/ccan/rbuf/rbuf.h
+
+shachain48.o $(CCAN_OBJS): $(CCANDIR)/config.h
+
+$(CCANDIR)/config.h:
+       $(MAKE) -C $(CCANDIR) config.h
+
+clean:
+       rm -f shachain *.o
+
+ccan-err.o: $(CCANDIR)/ccan/err/err.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+ccan-hex.o: $(CCANDIR)/ccan/str/hex/hex.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+ccan-str.o: $(CCANDIR)/ccan/str/str.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+ccan-shachain.o: $(CCANDIR)/ccan/crypto/shachain/shachain.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+ccan-sha256.o: $(CCANDIR)/ccan/crypto/sha256/sha256.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+ccan-rbuf.o: $(CCANDIR)/ccan/rbuf/rbuf.c
+       $(CC) $(CFLAGS) -c -o $@ $<
diff --git a/ccan/crypto/shachain/tools/shachain48.c b/ccan/crypto/shachain/tools/shachain48.c
new file mode 100644 (file)
index 0000000..5cc9109
--- /dev/null
@@ -0,0 +1,58 @@
+#include <ccan/crypto/shachain/shachain.h>
+#include <ccan/str/hex/hex.h>
+#include <ccan/str/str.h>
+#include <ccan/err/err.h>
+#include <ccan/rbuf/rbuf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+       if (argc == 2 && streq(argv[1], "--store")) {
+               struct shachain s;
+               struct rbuf rbuf;
+               size_t size = rbuf_good_size(STDIN_FILENO);
+               char *p;
+
+               shachain_init(&s);
+               rbuf_init(&rbuf, STDIN_FILENO, malloc(size), size);
+
+               while ((p = rbuf_read_str(&rbuf, '\n', realloc)) != NULL) {
+                       struct sha256 hash;
+                       unsigned long long idx;
+
+                       if (strstarts(p, "0x"))
+                               p += 2;
+                       if (!hex_decode(p, 64, &hash, sizeof(hash)))
+                               errx(2, "%.*s is not 64 chars of hex", 64, p);
+                       p += 64;
+                       p += strspn(p, " \t");
+                       idx = strtoull(p, NULL, 0);
+                       if (shachain_add_hash(&s, idx, &hash))
+                               printf("OK\n");
+                       else
+                               printf("ERROR\n");
+               }
+       } else if (argc == 3) {
+               struct sha256 seed, hash;
+               const char *p;
+               unsigned long long idx;
+               char hex[65];
+
+               if (strstarts(argv[1], "0x"))
+                       p = argv[1] + 2;
+               else
+                       p = argv[1];
+               idx = strtoull(argv[2], NULL, 0);
+
+               if (!hex_decode(p, 64, &seed, sizeof(seed)))
+                       errx(2, "%s is not 64 chars of hex", p);
+
+               shachain_from_seed(&seed, idx, &hash);
+               hex_encode(&hash, sizeof(hash), hex, sizeof(hex));
+               printf("0x%s\n", hex);
+       } else
+               errx(1, "Usage: shachain --store OR shachain <seed> <index>");
+       return 0;
+}