#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 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;
- for (i = 0; i < INDEX_BITS; i++) {
+ for (i = 0; i < SHACHAIN_BITS; i++) {
if (index & (1ULL << i))
break;
}
/* 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);
#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
struct {
shachain_index_t index;
struct sha256 hash;
- } known[sizeof(shachain_index_t) * 8 + 1];
+ } known[SHACHAIN_BITS + 1];
};
/**
--- /dev/null
+shachain48
--- /dev/null
+#! /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 $@ $<
--- /dev/null
+#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;
+}