#ifndef SIGSUM_QUORUM_H_INCLUDED
#define SIGSUM_QUORUM_H_INCLUDED

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

/* Quorum evaluation is one part of applying a Sigsum trust policy:
   "the rule that determines whether or not a subset of witnesses that
   have cosigned a tree head is strong enough to consider the tree
   head to be valid" (see
   https://git.glasklar.is/sigsum/core/sigsum-go/-/blob/main/doc/policy.md).
   A simple example of a quorum rule is to require at least k valid
   cosignatures out of n trusted witnesses, but Sigsum trust policies
   can be more complex than that, organized as a tree of witness
   groups.

   This library represents the quorum rule using a very simple stack
   machine, see doc/quorum-bytecode.md.
*/

enum bytecode_op
  {
    BYTECODE_OP_MISC = 0,
    BYTECODE_OP_X_P = 1,
    BYTECODE_OP_GE_K = 2,
    BYTECODE_OP_PREFIX = 3,
  };

/*  Instructions with BYTECODE_OP_MISC. */
#define BYTECODE_INSTR_ADD 0x01
#define BYTECODE_INSTR_TRUE 0x02

static inline enum bytecode_op
quorum_bytecode_op (uint8_t instr)
{
  return instr >> 6;
}

static inline size_t
quorum_bytecode_imm (size_t prefix, uint8_t instr)
{
  return (prefix << 6) | (instr & 0x3f);
}

/* Evaluates a quorum bytecode program. Each entry of the witnesses
   array is true if the witness with that index has provided a valid
   cosignature, otherwise false. The needed stack size depends on the
   quorum program, and should be provided by the compiler. */
bool
_sigsum_quorum_eval (size_t quorum_length, const uint8_t *quorum,
		     size_t num_witnesses, const bool *witnesses,
		     size_t stack_alloc, uint8_t *stack);

#endif /* SIGSUM_QUORUM_H_INCLUDED */
