MCPcopy Create free account
hub / github.com/ElementsProject/elements / simplicity_evalTCOExpression

Function simplicity_evalTCOExpression

src/simplicity/eval.c:776–842  ·  view source on GitHub ↗

Run the Bit Machine on the well-typed Simplicity expression 'dag[len]' of type A |- B. * If bitSize(A) > 0, initialize the active read frame's data with 'input[ROUND_UWORD(bitSize(A))]'. * * If malloc fails, returns 'SIMPLICITY_ERR_MALLOC'. * When a budget is given, if static analysis results determines the bound on cpu requirements exceed the allowed budget, returns 'SIMPLICITY_ERR_EXEC_BUDGE

Source from the content-addressed store, hash-verified

774 * if 'dag[len]' represents a Simplicity expression with primitives then 'NULL != env';
775 */
776simplicity_err simplicity_evalTCOExpression( flags_type anti_dos_checks, UWORD* output, const UWORD* input
777 , const dag_node* dag, type* type_dag, size_t len, ubounded minCost, const ubounded* budget, const txEnv* env
778 ) {
779 simplicity_assert(1 <= len);
780 simplicity_assert(len <= DAG_LEN_MAX);
781 if (budget) {
782 simplicity_assert(*budget <= BUDGET_MAX);
783 simplicity_assert(minCost <= *budget);
784 }
785 simplicity_assert(minCost <= BUDGET_MAX);
786 static_assert(1 <= UBOUNDED_MAX, "UBOUNDED_MAX is zero.");
787 static_assert(BUDGET_MAX <= (UBOUNDED_MAX - 1) / 1000, "BUDGET_MAX is too large.");
788 static_assert(CELLS_MAX < UBOUNDED_MAX, "CELLS_MAX is too large.");
789 ubounded cellsBound, UWORDBound, frameBound, costBound;
790 simplicity_err result = simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, CELLS_MAX, minCost*1000, budget ? *budget*1000 : UBOUNDED_MAX, dag, type_dag, len);
791 if (!IS_OK(result)) return result;
792
793 /* frameBound is at most 2*len. */
794 static_assert(DAG_LEN_MAX <= UBOUNDED_MAX / 2, "2*DAG_LEN_MAX does not fit in size_t.");
795 simplicity_assert(frameBound <= 2*len);
796
797 /* UWORDBound * UWORD_BIT, the number of bits actually allocacted, is at most the cellBound count plus (worse case) padding bits in each frame. */
798 static_assert(1 <= UWORD_BIT, "UWORD_BIT is zero.");
799 static_assert(2*DAG_LEN_MAX <= (SIZE_MAX - CELLS_MAX) / (UWORD_BIT - 1), "cellsBound + frameBound*(UWORD_BIT - 1) doesn't fit in size_t.");
800 simplicity_assert(UWORDBound <= (cellsBound + frameBound*(UWORD_BIT - 1)) / UWORD_BIT);
801
802 /* UWORDBound, is also at most the cellsBound, with an entire UWORD per cell (the rest of the UWORD being padding). */
803 simplicity_assert(UWORDBound <= cellsBound);
804
805 /* We use calloc for 'cells' because the frame data must be initialized before we can perform bitwise operations. */
806 static_assert(CELLS_MAX - 1 <= UINT32_MAX, "cells array index does not fit in uint32_t.");
807 UWORD* cells = simplicity_calloc(UWORDBound ? UWORDBound : 1, sizeof(UWORD));
808 static_assert(2*DAG_LEN_MAX <= SIZE_MAX / sizeof(frameItem), "frames array does not fit in size_t.");
809 static_assert(1 <= DAG_LEN_MAX, "DAG_LEN_MAX is zero.");
810 static_assert(2*DAG_LEN_MAX - 1 <= UINT32_MAX, "frames array index does not fit in uint32_t.");
811 frameItem* frames = simplicity_malloc(frameBound * sizeof(frameItem));
812 call* stack = simplicity_calloc(len, sizeof(call));
813
814 result = cells && frames && stack ? SIMPLICITY_NO_ERROR : SIMPLICITY_ERR_MALLOC;
815 if (IS_OK(result)) {
816 const ubounded inputSize = type_dag[dag[len-1].sourceType].bitSize;
817 const ubounded outputSize = type_dag[dag[len-1].targetType].bitSize;
818 simplicity_assert(NULL != input || 0 == inputSize);
819 if (inputSize) memcpy(cells, input, ROUND_UWORD(inputSize) * sizeof(UWORD));
820
821 evalState state =
822 { .activeReadFrame = frames
823 , .activeWriteFrame = frames + (frameBound - 1)
824 };
825 *(state.activeReadFrame) = initReadFrame(inputSize, cells);
826 *(state.activeWriteFrame) = initWriteFrame(outputSize, cells + UWORDBound);
827
828 result = runTCO(state, stack, dag, type_dag, len, env);
829
830 if (IS_OK(result)) {
831 simplicity_assert(NULL != output || 0 == outputSize);
832 if (outputSize) memcpy(output, state.activeWriteFrame->edge, ROUND_UWORD(outputSize) * sizeof(UWORD));
833

Callers 2

test_hashBlockFunction · 0.85
evalTCOProgramFunction · 0.85

Calls 6

simplicity_analyseBoundsFunction · 0.85
IS_OKFunction · 0.85
initReadFrameFunction · 0.85
initWriteFrameFunction · 0.85
runTCOFunction · 0.85
antiDosFunction · 0.85

Tested by 1

test_hashBlockFunction · 0.68