shachain: clarify design in terms of binary tree, reverse indexes.
[ccan] / ccan / crypto / shachain / shachain.h
index 39d6f3c4c6897b73112fa6ba02646c3dfb5e5115..ba4ba11cd64c02d1d66a362d35bac98e39a2f0bc 100644 (file)
 #define shachain_index_t uint64_t
 #endif
 
+/**
+ * shachain_from_seed - Generate an unpredictable SHA from a seed value.
+ * @seed: (secret) seed value to use
+ * @index: index of value to generate (0 == seed)
+ * @hash: value generated
+ *
+ * There will be no way to derive the result from that generated for
+ * any *greater* index.
+ *
+ * Example:
+ * #include <time.h>
+ *
+ * static void next_hash(struct sha256 *hash)
+ * {
+ *     static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
+ *     static struct sha256 seed;
+ *
+ *     // First time, initialize seed.
+ *     if (index == 0xFFFFFFFFFFFFFFFFULL) {
+ *             // DO NOT DO THIS!  Very predictable!
+ *             time_t now = time(NULL);
+ *             memcpy(&seed, &now, sizeof(now));
+ *     }
+ *
+ *     shachain_from_seed(&seed, index--, hash);
+ * }
+ */
 void shachain_from_seed(const struct sha256 *seed, shachain_index_t index,
                        struct sha256 *hash);
 
+/**
+ * shachain - structure for recording/deriving decrementing chain members
+ * @min_index: minimum index value successfully shachain_add_hash()ed.
+ * @num_valid: number of known[] array valid.  If non-zero, @min_index valid.
+ * @known: known values to allow us to derive those >= @min_index.
+ *
+ * This is sufficient storage to derive any shachain hash value previously
+ * added.
+ */
 struct shachain {
+       shachain_index_t min_index;
        unsigned int num_valid;
        struct {
                shachain_index_t index;
                struct sha256 hash;
-       } known[sizeof(shachain_index_t) * 8];
+       } known[sizeof(shachain_index_t) * 8 + 1];
 };
 
-void shachain_init(struct shachain *shachain);
+/**
+ * shachain_init - initialize an shachain
+ * @chain: the chain to initialize
+ *
+ * Alternately, ensure that it's all zero.
+ */
+void shachain_init(struct shachain *chain);
 
-bool shachain_add_hash(struct shachain *shachain,
+/**
+ * shachain_add_hash - record the hash for the next index.
+ * @chain: the chain to add to
+ * @index: the index of the hash
+ * @hash: the hash value.
+ *
+ * You can only add index 0xFFFFFFFFFFFFFFFF (for a freshly
+ * initialized chain), or one less than the previously successfully
+ * added value.
+ *
+ * This can fail (return false without altering @chain) if the hash
+ * for this index isn't consistent with previous hashes (ie. wasn't
+ * generated from the same seed), though it can't always detect that.
+ * If the hash is inconsistent yet undetected, the next addition will
+ * fail.
+ *
+ * Example:
+ * static void next_hash(const struct sha256 *hash)
+ * {
+ *     static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
+ *     static struct shachain chain;
+ *
+ *     if (!shachain_add_hash(&chain, index--, hash))
+ *             errx(1, "Corrupted hash value?");
+ * }
+ */
+bool shachain_add_hash(struct shachain *chain,
                       shachain_index_t index, const struct sha256 *hash);
 
-bool shachain_get_hash(const struct shachain *shachain,
+/**
+ * shachain_get_hash - get the hash for a given index.
+ * @chain: the chain query
+ * @index: the index of the hash to get
+ * @hash: the hash value.
+ *
+ * This will return true and set @hash to that given in the successful
+ * shachain_get_hash() call for that index.  If there was no
+ * successful shachain_get_hash() for that index, it will return
+ * false.
+ *
+ * Example:
+ * #include <ccan/structeq/structeq.h>
+ *
+ * static void next_hash(const struct sha256 *hash)
+ * {
+ *     static uint64_t index = 0xFFFFFFFFFFFFFFFFULL;
+ *     static struct shachain chain;
+ *
+ *     if (!shachain_add_hash(&chain, index--, hash))
+ *             errx(1, "Corrupted hash value?");
+ *     else {
+ *             struct sha256 check;
+ *             assert(shachain_get_hash(&chain, index+1, &check));
+ *             assert(structeq(&check, hash));
+ *     }
+ * }
+ */
+bool shachain_get_hash(const struct shachain *chain,
                       shachain_index_t index, struct sha256 *hash);
 #endif /* CCAN_CRYPTO_SHACHAIN_H */