packages feed

KpqC-0.1.0: cbits/third_party/AIMer/tree.c

// SPDX-License-Identifier: MIT

#include "tree.h"
#include "hash.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>

void expand_tree(uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE],
                 const uint8_t salt[AIMER_SALT_SIZE], size_t rep_index,
                 const uint8_t seed[AIMER_SEED_SIZE])
{
  size_t node_index;
  hash_instance ctx;
  uint8_t rep_byte = (uint8_t)rep_index;

  memcpy(nodes[0], seed, AIMER_SEED_SIZE);
  for (node_index = 1; node_index < AIMER_N; node_index++)
  {
    uint8_t node_byte = (uint8_t)node_index;

    hash_init_prefix(&ctx, HASH_PREFIX_4);
    hash_update(&ctx, salt, AIMER_SALT_SIZE);
    hash_update(&ctx, &rep_byte, sizeof(rep_byte));
    hash_update(&ctx, &node_byte, sizeof(node_byte));
    hash_update(&ctx, nodes[node_index - 1], AIMER_SEED_SIZE);
    hash_final(&ctx);

    hash_squeeze(&ctx, nodes[2 * node_index - 1], AIMER_SEED_SIZE << 1);
    hash_ctx_release(&ctx);
  }
}

void reveal_all_but(uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE],
                    const uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE],
                    size_t cover_index)
{
  size_t index = cover_index + AIMER_N;
  for (size_t depth = 0; depth < AIMER_LOGN; depth++)
  {
    // index ^ 1 is sibling index
    memcpy(reveal_path[depth], nodes[(index ^ 1) - 1], AIMER_SEED_SIZE);

    // go to parent node
    index >>= 1;
  }
}

void reconstruct_tree(uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE],
                      const uint8_t salt[AIMER_SALT_SIZE],
                      const uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE],
                      size_t rep_index, size_t cover_index)
{
  size_t index, depth, path;
  hash_instance ctx;
  uint8_t rep_byte = (uint8_t)rep_index;

  for (depth = 1; depth < AIMER_LOGN; depth++)
  {
    path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1;
    memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE);

    for (index = (1U << depth); index < (2U << depth); index++)
    {
      uint8_t index_byte = (uint8_t)index;

      hash_init_prefix(&ctx, HASH_PREFIX_4);
      hash_update(&ctx, salt, AIMER_SALT_SIZE);
      hash_update(&ctx, &rep_byte, sizeof(rep_byte));
      hash_update(&ctx, &index_byte, sizeof(index_byte));
      hash_update(&ctx, nodes[index - 2], AIMER_SEED_SIZE);
      hash_final(&ctx);

      hash_squeeze(&ctx, nodes[2 * index - 2], AIMER_SEED_SIZE << 1);
      hash_ctx_release(&ctx);
    }
  }

  path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1;
  memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE);
}