#ifndef SIMPLICITY_DAG_H
#define SIMPLICITY_DAG_H
#include <stddef.h>
#include <stdint.h>
#include <simplicity/errorCodes.h>
#include "bitstream.h"
#include "bitstring.h"
#include "bounded.h"
#include "jets.h"
#include "simplicity_assert.h"
#include "type.h"
typedef enum tag_t
{ COMP
, CASE
, ASSERTL
, ASSERTR
, PAIR
, DISCONNECT
, INJL
, INJR
, TAKE
, DROP
, IDEN
, UNIT
, HIDDEN
, WITNESS
, JET
, WORD
} tag_t;
typedef struct combinator_counters {
size_t comp_cnt, case_cnt, pair_cnt, disconnect_cnt,
injl_cnt, injr_cnt, take_cnt, drop_cnt;
} combinator_counters;
static inline void enumerator(combinator_counters* census, tag_t tag) {
if (!census) return;
switch (tag) {
case COMP: census->comp_cnt++; return;
case ASSERTL:
case ASSERTR:
case CASE: census->case_cnt++; return;
case PAIR: census->pair_cnt++; return;
case DISCONNECT: census->disconnect_cnt++; return;
case INJL: census->injl_cnt++; return;
case INJR: census->injr_cnt++; return;
case TAKE: census->take_cnt++; return;
case DROP: census->drop_cnt++; return;
case IDEN:
case UNIT:
case HIDDEN:
case WITNESS:
case JET:
case WORD:
return;
}
}
static inline size_t numChildren(tag_t tag) {
switch (tag) {
case COMP:
case ASSERTL:
case ASSERTR:
case CASE:
case PAIR:
case DISCONNECT:
return 2;
case INJL:
case INJR:
case TAKE:
case DROP:
return 1;
case IDEN:
case UNIT:
case HIDDEN:
case WITNESS:
case JET:
case WORD:
return 0;
}
}
sha256_midstate rustsimplicity_0_6_computeWordCMR(const bitstring* value, size_t n);
typedef struct dag_node {
jet_ptr jet;
sha256_midstate cmr;
union {
uint_fast32_t aux;
struct {
size_t sourceType, targetType;
};
};
union {
struct {
size_t sourceIx;
};
struct {
uint_fast32_t child[2];
};
bitstring compactValue;
};
size_t targetIx;
ubounded cost;
tag_t tag;
} dag_node;
static inline size_t IDEN_A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(IDEN == dag[i].tag);
return dag[i].sourceType;
}
static inline size_t UNIT_A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(UNIT == dag[i].tag);
return dag[i].sourceType;
}
static inline size_t COMP_A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(COMP == dag[i].tag);
return dag[i].sourceType;
}
static inline size_t COMP_B(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(COMP == dag[i].tag);
return dag[dag[i].child[1]].sourceType;
}
static inline size_t COMP_C(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(COMP == dag[i].tag);
return dag[i].targetType;
}
static inline size_t CASE_A(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(CASE == dag[i].tag || ASSERTL == dag[i].tag || ASSERTR == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].sourceType].kind);
rustsimplicity_0_6_debug_assert(SUM == type_dag[type_dag[dag[i].sourceType].typeArg[0]].kind);
return type_dag[type_dag[dag[i].sourceType].typeArg[0]].typeArg[0];
}
static inline size_t CASE_B(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(CASE == dag[i].tag || ASSERTL == dag[i].tag || ASSERTR == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].sourceType].kind);
rustsimplicity_0_6_debug_assert(SUM == type_dag[type_dag[dag[i].sourceType].typeArg[0]].kind);
return type_dag[type_dag[dag[i].sourceType].typeArg[0]].typeArg[1];
}
static inline size_t CASE_C(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(CASE == dag[i].tag || ASSERTL == dag[i].tag || ASSERTR == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].sourceType].kind);
return type_dag[dag[i].sourceType].typeArg[1];
}
static inline size_t CASE_D(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(CASE == dag[i].tag || ASSERTL == dag[i].tag || ASSERTR == dag[i].tag);
return dag[i].targetType;
}
static inline size_t PAIR_A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(PAIR == dag[i].tag);
return dag[i].sourceType;
}
static inline size_t PAIR_B(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(PAIR == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].targetType].kind);
return type_dag[dag[i].targetType].typeArg[0];
}
static inline size_t PAIR_C(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(PAIR == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].targetType].kind);
return type_dag[dag[i].targetType].typeArg[1];
}
static inline size_t DISCONNECT_A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(DISCONNECT == dag[i].tag);
return dag[i].sourceType;
}
static inline size_t DISCONNECT_B(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(DISCONNECT == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].targetType].kind);
return type_dag[dag[i].targetType].typeArg[0];
}
static inline size_t DISCONNECT_C(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(DISCONNECT == dag[i].tag);
return dag[dag[i].child[1]].sourceType;
}
static inline size_t DISCONNECT_D(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(DISCONNECT == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].targetType].kind);
return type_dag[dag[i].targetType].typeArg[1];
}
static inline size_t DISCONNECT_W256A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(DISCONNECT == dag[i].tag);
return dag[dag[i].child[0]].sourceType;
}
static inline size_t DISCONNECT_BC(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(DISCONNECT == dag[i].tag);
return dag[dag[i].child[0]].targetType;
}
static inline size_t INJ_A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(INJL == dag[i].tag || INJR == dag[i].tag);
return dag[i].sourceType;
}
static inline size_t INJ_B(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(INJL == dag[i].tag || INJR == dag[i].tag);
rustsimplicity_0_6_debug_assert(SUM == type_dag[dag[i].targetType].kind);
return type_dag[dag[i].targetType].typeArg[0];
}
static inline size_t INJ_C(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(INJL == dag[i].tag || INJR == dag[i].tag);
rustsimplicity_0_6_debug_assert(SUM == type_dag[dag[i].targetType].kind);
return type_dag[dag[i].targetType].typeArg[1];
}
static inline size_t PROJ_A(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(TAKE == dag[i].tag || DROP == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].sourceType].kind);
return type_dag[dag[i].sourceType].typeArg[0];
}
static inline size_t PROJ_B(const dag_node* dag, const type* type_dag, size_t i) {
rustsimplicity_0_6_debug_assert(TAKE == dag[i].tag || DROP == dag[i].tag);
rustsimplicity_0_6_debug_assert(PRODUCT == type_dag[dag[i].sourceType].kind);
return type_dag[dag[i].sourceType].typeArg[1];
}
static inline size_t PROJ_C(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(TAKE == dag[i].tag || DROP == dag[i].tag);
return dag[i].targetType;
}
static inline size_t WITNESS_A(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(WITNESS == dag[i].tag);
return dag[i].sourceType;
}
static inline size_t WITNESS_B(const dag_node* dag, const type* type_dag, size_t i) {
(void)type_dag;
rustsimplicity_0_6_debug_assert(WITNESS == dag[i].tag);
return dag[i].targetType;
}
typedef struct analyses {
sha256_midstate annotatedMerkleRoot;
} analyses;
void rustsimplicity_0_6_computeCommitmentMerkleRoot(dag_node* dag, uint_fast32_t i);
void rustsimplicity_0_6_computeAnnotatedMerkleRoot(analyses* analysis, const dag_node* dag, const type* type_dag, uint_fast32_t len);
simplicity_err rustsimplicity_0_6_verifyCanonicalOrder(dag_node* dag, const uint_fast32_t len);
simplicity_err rustsimplicity_0_6_fillWitnessData(dag_node* dag, type* type_dag, const uint_fast32_t len, bitstream *witness);
simplicity_err rustsimplicity_0_6_verifyNoDuplicateIdentityHashes(sha256_midstate* ihr, const dag_node* dag, const type* type_dag, const uint_fast32_t dag_len);
#endif