mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-13 12:33:42 +02:00
Merge pull request #1459 from ElementsProject/simplicity
Update Simplicity integeration
This commit is contained in:
commit
b379bb2465
40 changed files with 474 additions and 301 deletions
|
|
@ -9,7 +9,6 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\simplicity\bitstream.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\cmr.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\dag.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\deserialize.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\eval.c" />
|
||||
|
|
@ -20,11 +19,13 @@
|
|||
<ClCompile Include="..\..\src\simplicity\sha256.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\type.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\typeInference.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\primitive\elements\env.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\primitive\elements\exec.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\primitive\elements\elementsJets.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\primitive\elements\ops.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\primitive\elements\primitive.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\elements\cmr.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\elements\env.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\elements\exec.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\elements\elementsJets.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\elements\ops.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\elements\primitive.c" />
|
||||
<ClCompile Include="..\..\src\simplicity\elements\txEnv.c" />
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
|
|
|
|||
|
|
@ -2601,8 +2601,8 @@ void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent
|
|||
m_spent_output_spk_single_hashes = GetSpentScriptPubKeysSHA256(m_spent_outputs);
|
||||
m_output_spk_single_hashes = GetOutputScriptPubKeysSHA256(txTo);
|
||||
|
||||
std::vector<rawBuffer> simplicityRawAnnex(txTo.witness.vtxinwit.size());
|
||||
std::vector<rawInput> simplicityRawInput(txTo.vin.size());
|
||||
std::vector<rawElementsBuffer> simplicityRawAnnex(txTo.witness.vtxinwit.size());
|
||||
std::vector<rawElementsInput> simplicityRawInput(txTo.vin.size());
|
||||
for (size_t i = 0; i < txTo.vin.size(); ++i) {
|
||||
simplicityRawInput[i].prevTxid = txTo.vin[i].prevout.hash.begin();
|
||||
simplicityRawInput[i].prevIx = txTo.vin[i].prevout.n;
|
||||
|
|
@ -2639,7 +2639,7 @@ void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<rawOutput> simplicityRawOutput(txTo.vout.size());
|
||||
std::vector<rawElementsOutput> simplicityRawOutput(txTo.vout.size());
|
||||
for (size_t i = 0; i < txTo.vout.size(); ++i) {
|
||||
simplicityRawOutput[i].asset = txTo.vout[i].nAsset.vchCommitment.empty() ? NULL : txTo.vout[i].nAsset.vchCommitment.data();
|
||||
simplicityRawOutput[i].value = txTo.vout[i].nValue.vchCommitment.empty() ? NULL : txTo.vout[i].nValue.vchCommitment.data();
|
||||
|
|
@ -2659,7 +2659,7 @@ void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent
|
|||
}
|
||||
}
|
||||
|
||||
rawTransaction simplicityRawTx;
|
||||
rawElementsTransaction simplicityRawTx;
|
||||
uint256 rawHash = txTo.GetHash();
|
||||
simplicityRawTx.txid = rawHash.begin();
|
||||
simplicityRawTx.input = simplicityRawInput.data();
|
||||
|
|
@ -3114,14 +3114,14 @@ uint32_t GenericTransactionSignatureChecker<T>::GetnIn() const
|
|||
}
|
||||
|
||||
template <class T>
|
||||
bool GenericTransactionSignatureChecker<T>::CheckSimplicity(const valtype& program, const valtype& witness, const rawTapEnv& simplicityRawTap, int64_t budget, ScriptError* serror) const
|
||||
bool GenericTransactionSignatureChecker<T>::CheckSimplicity(const valtype& program, const valtype& witness, const rawElementsTapEnv& simplicityRawTap, int64_t budget, ScriptError* serror) const
|
||||
{
|
||||
simplicity_err error;
|
||||
tapEnv* simplicityTapEnv = simplicity_elements_mallocTapEnv(&simplicityRawTap);
|
||||
elementsTapEnv* simplicityTapEnv = simplicity_elements_mallocTapEnv(&simplicityRawTap);
|
||||
|
||||
assert(txdata->m_simplicity_tx_data);
|
||||
assert(simplicityTapEnv);
|
||||
if (!simplicity_elements_execSimplicity(&error, 0, txdata->m_simplicity_tx_data.get(), nIn, simplicityTapEnv, txdata->m_hash_genesis_block.data(), budget, 0, program.data(), program.size(), witness.data(), witness.size())) {
|
||||
if (!simplicity_elements_execSimplicity(&error, 0, txdata->m_simplicity_tx_data.get(), nIn, simplicityTapEnv, txdata->m_hash_genesis_block.data(), 0, budget, 0, program.data(), program.size(), witness.data(), witness.size())) {
|
||||
assert(!"simplicity_elements_execSimplicity internal error");
|
||||
}
|
||||
simplicity_elements_freeTapEnv(simplicityTapEnv);
|
||||
|
|
@ -3154,6 +3154,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSimplicity(const valtype& progr
|
|||
case SIMPLICITY_ERR_ANTIDOS: return set_error(serror, SCRIPT_ERR_SIMPLICITY_ANTIDOS);
|
||||
case SIMPLICITY_ERR_HIDDEN_ROOT: return set_error(serror, SCRIPT_ERR_SIMPLICITY_HIDDEN_ROOT);
|
||||
case SIMPLICITY_ERR_AMR: return set_error(serror, SCRIPT_ERR_SIMPLICITY_AMR);
|
||||
case SIMPLICITY_ERR_OVERWEIGHT: return set_error(serror, SCRIPT_ERR_SIMPLICITY_OVERWEIGHT);
|
||||
default: return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
|
|
@ -3312,7 +3313,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
|
|||
const valtype& simplicity_program = SpanPopBack(stack);
|
||||
const valtype& simplicity_witness = SpanPopBack(stack);
|
||||
const int64_t budget = ::GetSerializeSize(witness.stack, PROTOCOL_VERSION) + VALIDATION_WEIGHT_OFFSET;
|
||||
rawTapEnv simplicityRawTap;
|
||||
rawElementsTapEnv simplicityRawTap;
|
||||
simplicityRawTap.controlBlock = control.data();
|
||||
simplicityRawTap.pathLen = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
|
||||
simplicityRawTap.scriptCMR = script_bytes.data();
|
||||
|
|
|
|||
|
|
@ -171,12 +171,12 @@ bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned i
|
|||
|
||||
struct SimplicityTransactionDeleter
|
||||
{
|
||||
void operator()(transaction* ptr)
|
||||
void operator()(elementsTransaction* ptr)
|
||||
{
|
||||
simplicity_elements_freeTransaction(ptr);
|
||||
}
|
||||
};
|
||||
using SimplicityTransactionUniquePtr = std::unique_ptr<transaction, SimplicityTransactionDeleter>;
|
||||
using SimplicityTransactionUniquePtr = std::unique_ptr<elementsTransaction, SimplicityTransactionDeleter>;
|
||||
|
||||
struct PrecomputedTransactionData
|
||||
{
|
||||
|
|
@ -345,7 +345,7 @@ public:
|
|||
return std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
||||
virtual bool CheckSimplicity(const std::vector<unsigned char>& witness, const std::vector<unsigned char>& program, const rawTapEnv& simplicityRawTap, int64_t budget, ScriptError* serror) const
|
||||
virtual bool CheckSimplicity(const std::vector<unsigned char>& witness, const std::vector<unsigned char>& program, const rawElementsTapEnv& simplicityRawTap, int64_t budget, ScriptError* serror) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -393,7 +393,7 @@ public:
|
|||
|
||||
const PrecomputedTransactionData* GetPrecomputedTransactionData() const override;
|
||||
uint32_t GetnIn() const override;
|
||||
bool CheckSimplicity(const std::vector<unsigned char>& program, const std::vector<unsigned char>& witness, const rawTapEnv& simplicityRawTap, int64_t budget, ScriptError* serror) const override;
|
||||
bool CheckSimplicity(const std::vector<unsigned char>& program, const std::vector<unsigned char>& witness, const rawElementsTapEnv& simplicityRawTap, int64_t budget, ScriptError* serror) const override;
|
||||
};
|
||||
|
||||
using TransactionSignatureChecker = GenericTransactionSignatureChecker<CTransaction>;
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ std::string ScriptErrorString(const ScriptError serror)
|
|||
return SIMPLICITY_ERR_MSG(SIMPLICITY_ERR_HIDDEN_ROOT);
|
||||
case SCRIPT_ERR_SIMPLICITY_AMR:
|
||||
return SIMPLICITY_ERR_MSG(SIMPLICITY_ERR_AMR);
|
||||
case SCRIPT_ERR_SIMPLICITY_OVERWEIGHT:
|
||||
return SIMPLICITY_ERR_MSG(SIMPLICITY_ERR_OVERWEIGHT);
|
||||
case SCRIPT_ERR_UNKNOWN_ERROR:
|
||||
case SCRIPT_ERR_ERROR_COUNT:
|
||||
default: break;
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ typedef enum ScriptError_t
|
|||
SCRIPT_ERR_SIMPLICITY_ANTIDOS,
|
||||
SCRIPT_ERR_SIMPLICITY_HIDDEN_ROOT,
|
||||
SCRIPT_ERR_SIMPLICITY_AMR,
|
||||
SCRIPT_ERR_SIMPLICITY_OVERWEIGHT,
|
||||
|
||||
/* Must go last */
|
||||
SCRIPT_ERR_ERROR_COUNT
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
OBJS := bitstream.o cmr.o dag.o deserialize.o eval.o frame.o jets.o jets-secp256k1.o rsort.o sha256.o type.o typeInference.o primitive/elements/env.o primitive/elements/exec.o primitive/elements/ops.o primitive/elements/elementsJets.o primitive/elements/primitive.o
|
||||
TEST_OBJS := test.o ctx8Pruned.o ctx8Unpruned.o hashBlock.o regression4.o schnorr0.o schnorr6.o typeSkipTest.o primitive/elements/checkSigHashAllTx1.o
|
||||
OBJS := bitstream.o dag.o deserialize.o eval.o frame.o jets.o jets-secp256k1.o rsort.o sha256.o type.o typeInference.o elements/env.o elements/exec.o elements/ops.o elements/elementsJets.o elements/primitive.o elements/cmr.o elements/txEnv.o
|
||||
TEST_OBJS := test.o ctx8Pruned.o ctx8Unpruned.o hashBlock.o regression4.o schnorr0.o schnorr6.o typeSkipTest.o elements/checkSigHashAllTx1.o
|
||||
|
||||
# From https://fastcompression.blogspot.com/2019/01/compiler-warnings.html
|
||||
CWARN := -Werror -Wall -Wextra -Wcast-qual -Wcast-align -Wstrict-aliasing -Wpointer-arith -Winit-self -Wshadow -Wswitch-enum -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wfloat-equal -Wundef -Wconversion
|
||||
|
|
@ -14,7 +14,7 @@ CFLAGS := $(CFLAGS) -I include
|
|||
jets-secp256k1.o: jets-secp256k1.c
|
||||
$(CC) -c $(CFLAGS) $(CWARN) -Wno-conversion $(CPPFLAGS) -o $@ $<
|
||||
|
||||
primitive/elements/elementsJets.o: primitive/elements/elementsJets.c
|
||||
elements/elementsJets.o: elements/elementsJets.c
|
||||
$(CC) -c $(CFLAGS) $(CWARN) -Wno-switch-enum -Wswitch $(CPPFLAGS) -o $@ $<
|
||||
|
||||
sha256.o: sha256.c
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <limits.h>
|
||||
#include "limitations.h"
|
||||
#include "primitive.h"
|
||||
#include "simplicity_alloc.h"
|
||||
#include "simplicity_assert.h"
|
||||
|
||||
|
|
@ -55,7 +54,7 @@ static simplicity_err getHash(sha256_midstate* result, bitstream* stream) {
|
|||
* i < 2^31 - 1
|
||||
* NULL != stream
|
||||
*/
|
||||
static simplicity_err decodeNode(dag_node* dag, uint_fast32_t i, bitstream* stream) {
|
||||
static simplicity_err decodeNode(dag_node* dag, simplicity_callback_decodeJet decodeJet, uint_fast32_t i, bitstream* stream) {
|
||||
int32_t bit = read1Bit(stream);
|
||||
if (bit < 0) return (simplicity_err)bit;
|
||||
dag[i] = (dag_node){0};
|
||||
|
|
@ -63,7 +62,7 @@ static simplicity_err decodeNode(dag_node* dag, uint_fast32_t i, bitstream* stre
|
|||
bit = read1Bit(stream);
|
||||
if (bit < 0) return (simplicity_err)bit;
|
||||
if (bit) {
|
||||
return simplicity_decodeJet(&dag[i], stream);
|
||||
return decodeJet(&dag[i], stream);
|
||||
} else {
|
||||
/* Decode WORD. */
|
||||
int32_t depth = simplicity_decodeUptoMaxInt(stream);
|
||||
|
|
@ -153,9 +152,9 @@ static simplicity_err decodeNode(dag_node* dag, uint_fast32_t i, bitstream* stre
|
|||
* len < 2^31
|
||||
* NULL != stream
|
||||
*/
|
||||
static simplicity_err decodeDag(dag_node* dag, const uint_fast32_t len, combinator_counters* census, bitstream* stream) {
|
||||
static simplicity_err decodeDag(dag_node* dag, simplicity_callback_decodeJet decodeJet, const uint_fast32_t len, combinator_counters* census, bitstream* stream) {
|
||||
for (uint_fast32_t i = 0; i < len; ++i) {
|
||||
simplicity_err error = decodeNode(dag, i, stream);
|
||||
simplicity_err error = decodeNode(dag, decodeJet, i, stream);
|
||||
if (!IS_OK(error)) return error;
|
||||
|
||||
enumerator(census, dag[i].tag);
|
||||
|
|
@ -186,7 +185,7 @@ static simplicity_err decodeDag(dag_node* dag, const uint_fast32_t len, combinat
|
|||
* of the function is positive and when NULL != census;
|
||||
* NULL == *dag when the return value is negative.
|
||||
*/
|
||||
int_fast32_t simplicity_decodeMallocDag(dag_node** dag, combinator_counters* census, bitstream* stream) {
|
||||
int_fast32_t simplicity_decodeMallocDag(dag_node** dag, simplicity_callback_decodeJet decodeJet, combinator_counters* census, bitstream* stream) {
|
||||
*dag = NULL;
|
||||
int32_t dagLen = simplicity_decodeUptoMaxInt(stream);
|
||||
if (dagLen <= 0) return dagLen;
|
||||
|
|
@ -199,7 +198,7 @@ int_fast32_t simplicity_decodeMallocDag(dag_node** dag, combinator_counters* cen
|
|||
if (!*dag) return SIMPLICITY_ERR_MALLOC;
|
||||
|
||||
if (census) *census = (combinator_counters){0};
|
||||
simplicity_err error = decodeDag(*dag, (uint_fast32_t)dagLen, census, stream);
|
||||
simplicity_err error = decodeDag(*dag, decodeJet, (uint_fast32_t)dagLen, census, stream);
|
||||
|
||||
if (IS_OK(error)) {
|
||||
error = HIDDEN == (*dag)[dagLen - 1].tag
|
||||
|
|
|
|||
|
|
@ -6,6 +6,18 @@
|
|||
#include "bitstream.h"
|
||||
#include "dag.h"
|
||||
|
||||
/* Decode an application specific jet from 'stream' into 'node'.
|
||||
* All jets begin with a bit prefix of '1' which needs to have already been consumed from the 'stream'.
|
||||
* Returns 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' if the stream's prefix doesn't match any valid code for a jet.
|
||||
* Returns 'SIMPLICITY_ERR_BITSTRING_EOF' if not enough bits are available in the 'stream'.
|
||||
* In the above error cases, 'dag' may be modified.
|
||||
* Returns 'SIMPLICITY_NO_ERROR' if successful.
|
||||
*
|
||||
* Precondition: NULL != node
|
||||
* NULL != stream
|
||||
*/
|
||||
typedef simplicity_err (*simplicity_callback_decodeJet)(dag_node* node, bitstream* stream);
|
||||
|
||||
/* Decode a length-prefixed Simplicity DAG from 'stream'.
|
||||
* Returns 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' the length prefix's value is too large.
|
||||
* Returns 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' if some node's child isn't a reference to one of the preceding nodes.
|
||||
|
|
@ -28,6 +40,6 @@
|
|||
* of the function is positive and when NULL != census;
|
||||
* NULL == *dag when the return value is negative.
|
||||
*/
|
||||
int_fast32_t simplicity_decodeMallocDag(dag_node** dag, combinator_counters* census, bitstream* stream);
|
||||
int_fast32_t simplicity_decodeMallocDag(dag_node** dag, simplicity_callback_decodeJet decodeJet, combinator_counters* census, bitstream* stream);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,14 +5,13 @@
|
|||
ELEMENTS_SIMPLICITY_INCLUDE_DIR_INT = %reldir%/include
|
||||
|
||||
ELEMENTS_SIMPLICITY_DIST_HEADERS_INT =
|
||||
ELEMENTS_SIMPLICITY_DIST_HEADERS_INT += %reldir%/include/simplicity/cmr.h
|
||||
ELEMENTS_SIMPLICITY_DIST_HEADERS_INT += %reldir%/include/simplicity/errorCodes.h
|
||||
ELEMENTS_SIMPLICITY_DIST_HEADERS_INT += %reldir%/include/simplicity/elements/cmr.h
|
||||
ELEMENTS_SIMPLICITY_DIST_HEADERS_INT += %reldir%/include/simplicity/elements/env.h
|
||||
ELEMENTS_SIMPLICITY_DIST_HEADERS_INT += %reldir%/include/simplicity/elements/exec.h
|
||||
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT =
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/bitstream.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/cmr.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/dag.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/deserialize.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/eval.c
|
||||
|
|
@ -24,11 +23,13 @@ ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/sha256.c
|
|||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/type.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/typeInference.c
|
||||
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/primitive/elements/env.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/primitive/elements/exec.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/primitive/elements/elementsJets.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/primitive/elements/ops.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/primitive/elements/primitive.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/elements/cmr.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/elements/env.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/elements/exec.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/elements/elementsJets.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/elements/ops.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/elements/primitive.c
|
||||
ELEMENTS_SIMPLICITY_LIB_SOURCES_INT += %reldir%/elements/txEnv.c
|
||||
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT =
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/bitstream.h
|
||||
|
|
@ -42,7 +43,6 @@ ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/frame.h
|
|||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/jets.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/limitations.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/precomputed.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/rsort.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/sha256.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/sha256_x86.inc
|
||||
|
|
@ -89,11 +89,12 @@ ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/secp256k1/secp256k1.h
|
|||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/secp256k1/secp256k1_impl.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/secp256k1/util.h
|
||||
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/decodeElementsJets.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/elementsJets.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/ops.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/primitive.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/primitiveEnumJet.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/primitiveEnumTy.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/primitiveInitTy.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/primitive/elements/primitiveJetNode.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/decodeElementsJets.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/elementsJets.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/ops.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/primitive.h
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/primitiveEnumJet.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/primitiveEnumTy.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/primitiveInitTy.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/primitiveJetNode.inc
|
||||
ELEMENTS_SIMPLICITY_LIB_HEADERS_INT += %reldir%/elements/txEnv.h
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef SIMPLICITY_PRIMITIVE_ELEMENTS_CHECKSIGHASHALLTX1_H
|
||||
#define SIMPLICITY_PRIMITIVE_ELEMENTS_CHECKSIGHASHALLTX1_H
|
||||
#ifndef SIMPLICITY_ELEMENTS_CHECKSIGHASHALLTX1_H
|
||||
#define SIMPLICITY_ELEMENTS_CHECKSIGHASHALLTX1_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "../../bounded.h"
|
||||
#include "../bounded.h"
|
||||
|
||||
/* A length-prefixed encoding of the following Simplicity program:
|
||||
* Simplicity.Programs.CheckSig.Lib.checkSigVerify' Simplicity.Elements.Programs.SigHash.Lib.sigAllHash
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
#include <simplicity/cmr.h>
|
||||
#include <simplicity/elements/cmr.h>
|
||||
|
||||
#include "deserialize.h"
|
||||
#include "limitations.h"
|
||||
#include "simplicity_alloc.h"
|
||||
#include "simplicity_assert.h"
|
||||
#include "../deserialize.h"
|
||||
#include "../limitations.h"
|
||||
#include "../simplicity_alloc.h"
|
||||
#include "../simplicity_assert.h"
|
||||
#include "primitive.h"
|
||||
|
||||
/* Deserialize a Simplicity 'program' and compute its CMR.
|
||||
*
|
||||
|
|
@ -18,15 +19,15 @@
|
|||
* unsigned char cmr[32]
|
||||
* unsigned char program[program_len]
|
||||
*/
|
||||
bool simplicity_computeCmr( simplicity_err* error, unsigned char* cmr
|
||||
, const unsigned char* program, size_t program_len) {
|
||||
bool simplicity_elements_computeCmr( simplicity_err* error, unsigned char* cmr
|
||||
, const unsigned char* program, size_t program_len) {
|
||||
simplicity_assert(NULL != error);
|
||||
simplicity_assert(NULL != cmr);
|
||||
simplicity_assert(NULL != program || 0 == program_len);
|
||||
|
||||
bitstream stream = initializeBitstream(program, program_len);
|
||||
dag_node* dag = NULL;
|
||||
int_fast32_t dag_len = simplicity_decodeMallocDag(&dag, NULL, &stream);
|
||||
int_fast32_t dag_len = simplicity_decodeMallocDag(&dag, simplicity_elements_decodeJet, NULL, &stream);
|
||||
if (dag_len <= 0) {
|
||||
simplicity_assert(dag_len < 0);
|
||||
*error = (simplicity_err)dag_len;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#include "elementsJets.h"
|
||||
|
||||
#include "ops.h"
|
||||
#include "primitive.h"
|
||||
#include "../../taptweak.h"
|
||||
#include "../../simplicity_assert.h"
|
||||
#include "txEnv.h"
|
||||
#include "../taptweak.h"
|
||||
#include "../simplicity_assert.h"
|
||||
|
||||
/* Read a 256-bit hash value from the 'src' frame, advancing the cursor 256 cells.
|
||||
*
|
||||
|
|
@ -145,19 +145,19 @@ static void issuanceTokenAmt(frameItem* dst, const assetIssuance* issuance) {
|
|||
}
|
||||
}
|
||||
|
||||
static uint_fast32_t lockHeight(const transaction* tx) {
|
||||
static uint_fast32_t lockHeight(const elementsTransaction* tx) {
|
||||
return !tx->isFinal && tx->lockTime < 500000000U ? tx->lockTime : 0;
|
||||
}
|
||||
|
||||
static uint_fast32_t lockTime(const transaction* tx) {
|
||||
static uint_fast32_t lockTime(const elementsTransaction* tx) {
|
||||
return !tx->isFinal && 500000000U <= tx->lockTime ? tx->lockTime : 0;
|
||||
}
|
||||
|
||||
static uint_fast16_t lockDistance(const transaction* tx) {
|
||||
static uint_fast16_t lockDistance(const elementsTransaction* tx) {
|
||||
return 2 <= tx->version ? tx->lockDistance : 0;
|
||||
}
|
||||
|
||||
static uint_fast16_t lockDuration(const transaction* tx) {
|
||||
static uint_fast16_t lockDuration(const elementsTransaction* tx) {
|
||||
return 2 <= tx->version ? tx->lockDuration : 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
/* This module defines primitives and jets that are specific to the Elements application for Simplicity.
|
||||
*/
|
||||
#ifndef SIMPLICITY_PRIMITIVE_ELEMENTS_JETS_H
|
||||
#define SIMPLICITY_PRIMITIVE_ELEMENTS_JETS_H
|
||||
#ifndef SIMPLICITY_ELEMENTS_ELEMENTSJETS_H
|
||||
#define SIMPLICITY_ELEMENTS_ELEMENTSJETS_H
|
||||
|
||||
#include "../../jets.h"
|
||||
#include "../jets.h"
|
||||
|
||||
/* Jets for the Elements application of Simplicity. */
|
||||
bool simplicity_version(frameItem* dst, frameItem src, const txEnv* env);
|
||||
|
|
@ -3,12 +3,12 @@
|
|||
#include <stdalign.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "primitive.h"
|
||||
#include "txEnv.h"
|
||||
#include "ops.h"
|
||||
#include "../../rsort.h"
|
||||
#include "../../sha256.h"
|
||||
#include "../../simplicity_assert.h"
|
||||
#include "../../simplicity_alloc.h"
|
||||
#include "../rsort.h"
|
||||
#include "../sha256.h"
|
||||
#include "../simplicity_assert.h"
|
||||
#include "../simplicity_alloc.h"
|
||||
|
||||
#define PADDING(alignType, allocated) ((alignof(alignType) - (allocated) % alignof(alignType)) % alignof(alignType))
|
||||
|
||||
|
|
@ -17,13 +17,13 @@
|
|||
* Precondition: NULL != result;
|
||||
* NULL != scriptPubKey;
|
||||
*/
|
||||
static void hashBuffer(sha256_midstate* result, const rawBuffer* buffer) {
|
||||
static void hashBuffer(sha256_midstate* result, const rawElementsBuffer* buffer) {
|
||||
sha256_context ctx = sha256_init(result->s);
|
||||
sha256_uchars(&ctx, buffer->buf, buffer->len);
|
||||
sha256_finalize(&ctx);
|
||||
}
|
||||
|
||||
/* Initialize a 'confidential' asset or 'confidential' nonce from an unsigned char array from a 'rawTransaction'.
|
||||
/* Initialize a 'confidential' asset or 'confidential' nonce from an unsigned char array from a 'rawElementsTransaction'.
|
||||
*
|
||||
* Precondition: NULL != conf;
|
||||
* unsigned char rawConf[33] or rawConf == NULL;
|
||||
|
|
@ -40,7 +40,7 @@ static void copyRawConfidential(confidential* conf, const unsigned char* rawConf
|
|||
}
|
||||
}
|
||||
|
||||
/* Initialize a 'confAmount' from an unsigned char array from a 'rawTransaction'.
|
||||
/* Initialize a 'confAmount' from an unsigned char array from a 'rawElementsTransaction'.
|
||||
*
|
||||
* Precondition: NULL != amt;
|
||||
* unsigned char rawAmt[rawAmt[0] == 0x01 ? 9 : 33] or rawAmt == NULL
|
||||
|
|
@ -60,12 +60,12 @@ static void copyRawAmt(confAmount* amt, const unsigned char* rawAmt) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Initialize a 'sigInput' from a 'rawInput', copying or hashing the data as needed.
|
||||
/* Initialize a 'sigInput' from a 'rawElementsInput', copying or hashing the data as needed.
|
||||
*
|
||||
* Precondition: NULL != result;
|
||||
* NULL != input;
|
||||
*/
|
||||
static void copyInput(sigInput* result, const rawInput* input) {
|
||||
static void copyInput(sigInput* result, const rawElementsInput* input) {
|
||||
*result = (sigInput){ .prevOutpoint = { .ix = input->prevIx }
|
||||
, .sequence = input->sequence
|
||||
, .isPegin = !!input->pegin
|
||||
|
|
@ -79,8 +79,8 @@ static void copyInput(sigInput* result, const rawInput* input) {
|
|||
copyRawConfidential(&result->txo.asset, input->txo.asset);
|
||||
copyRawAmt(&result->txo.amt, input->txo.value);
|
||||
hashBuffer(&result->scriptSigHash, &input->scriptSig);
|
||||
hashBuffer(&result->issuance.assetRangeProofHash, &(rawBuffer){0});
|
||||
hashBuffer(&result->issuance.tokenRangeProofHash, &(rawBuffer){0});
|
||||
hashBuffer(&result->issuance.assetRangeProofHash, &(rawElementsBuffer){0});
|
||||
hashBuffer(&result->issuance.tokenRangeProofHash, &(rawElementsBuffer){0});
|
||||
if (input->issuance.amount || input->issuance.inflationKeys) {
|
||||
sha256_toMidstate(result->issuance.blindingNonce.s, input->issuance.blindingNonce);
|
||||
copyRawAmt(&result->issuance.assetAmt, input->issuance.amount);
|
||||
|
|
@ -104,13 +104,13 @@ static void copyInput(sigInput* result, const rawInput* input) {
|
|||
}
|
||||
|
||||
/* As specified in https://github.com/ElementsProject/elements/blob/de942511a67c3a3fcbdf002a8ee7e9ba49679b78/src/primitives/transaction.h#L304-L307. */
|
||||
static bool isFee(const rawOutput* output) {
|
||||
static bool isFee(const rawElementsOutput* output) {
|
||||
return 0 == output->scriptPubKey.len && /* Empty scriptPubKey */
|
||||
NULL != output->asset && 0x01 == output->asset[0] && /* Explicit asset */
|
||||
NULL != output->value && 0x01 == output->value[0]; /* Explicit amount */
|
||||
}
|
||||
|
||||
static uint_fast32_t countFeeOutputs(const rawTransaction* rawTx) {
|
||||
static uint_fast32_t countFeeOutputs(const rawElementsTransaction* rawTx) {
|
||||
uint_fast32_t result = 0;
|
||||
for (uint_fast32_t i = 0; i < rawTx->numOutputs; ++i) {
|
||||
result += isFee(&rawTx->output[i]);
|
||||
|
|
@ -126,7 +126,7 @@ static uint_fast32_t countFeeOutputs(const rawTransaction* rawTx) {
|
|||
*
|
||||
* Precondition: NULL != scriptPubKey
|
||||
*/
|
||||
static uint_fast32_t countNullDataCodes(const rawBuffer* scriptPubKey) {
|
||||
static uint_fast32_t countNullDataCodes(const rawElementsBuffer* scriptPubKey) {
|
||||
if (0 == scriptPubKey->len || 0x6a != scriptPubKey->buf[0] ) return 0;
|
||||
|
||||
uint_fast32_t result = 0;
|
||||
|
|
@ -161,7 +161,7 @@ static uint_fast32_t countNullDataCodes(const rawBuffer* scriptPubKey) {
|
|||
*
|
||||
* Precondition: NULL != rawTx
|
||||
*/
|
||||
static uint_fast64_t countTotalNullDataCodes(const rawTransaction* rawTx) {
|
||||
static uint_fast64_t countTotalNullDataCodes(const rawElementsTransaction* rawTx) {
|
||||
uint_fast64_t result = 0;
|
||||
for (uint_fast32_t i = 0; i < rawTx->numOutputs; ++i) {
|
||||
result += countNullDataCodes(&rawTx->output[i].scriptPubKey);
|
||||
|
|
@ -186,7 +186,7 @@ static uint_fast64_t countTotalNullDataCodes(const rawTransaction* rawTx) {
|
|||
* NULL != scriptPubKey;
|
||||
* countNullDataCodes(scriptPubKey) <= *allocationLen
|
||||
*/
|
||||
static void parseNullData(parsedNullData* result, opcode** allocation, size_t* allocationLen, const rawBuffer* scriptPubKey) {
|
||||
static void parseNullData(parsedNullData* result, opcode** allocation, size_t* allocationLen, const rawElementsBuffer* scriptPubKey) {
|
||||
*result = (parsedNullData){ .op = *allocation };
|
||||
|
||||
if (0 == scriptPubKey->len || 0x6a != scriptPubKey->buf[0] ) { result->op = NULL; return; }
|
||||
|
|
@ -233,7 +233,7 @@ static void parseNullData(parsedNullData* result, opcode** allocation, size_t* a
|
|||
*allocationLen -= result->len;
|
||||
}
|
||||
|
||||
/* Initialize a 'sigOutput' from a 'rawOutput', copying or hashing the data as needed.
|
||||
/* Initialize a 'sigOutput' from a 'rawElementsOutput', copying or hashing the data as needed.
|
||||
*
|
||||
* '*allocation' is incremented by 'countNullDataCodes(&output->scriptPubKey)'
|
||||
* '*allocationLen' is decremented by 'countNullDataCodes(&output->scriptPubKey)'.
|
||||
|
|
@ -245,7 +245,7 @@ static void parseNullData(parsedNullData* result, opcode** allocation, size_t* a
|
|||
* NULL != output;
|
||||
* countNullDataCodes(&output->scriptPubKey) <= *allocationLen
|
||||
*/
|
||||
static void copyOutput(sigOutput* result, opcode** allocation, size_t* allocationLen, const rawOutput* output) {
|
||||
static void copyOutput(sigOutput* result, opcode** allocation, size_t* allocationLen, const rawElementsOutput* output) {
|
||||
hashBuffer(&result->scriptPubKey, &output->scriptPubKey);
|
||||
result->emptyScript = 0 == output->scriptPubKey.len;
|
||||
copyRawConfidential(&result->asset, output->asset);
|
||||
|
|
@ -253,8 +253,8 @@ static void copyOutput(sigOutput* result, opcode** allocation, size_t* allocatio
|
|||
copyRawConfidential(&result->nonce, output->nonce);
|
||||
parseNullData(&result->pnd, allocation, allocationLen, &output->scriptPubKey);
|
||||
result->isNullData = NULL != result->pnd.op;
|
||||
hashBuffer(&result->surjectionProofHash, is_confidential(result->asset.prefix) ? &output->surjectionProof : &(rawBuffer){0});
|
||||
hashBuffer(&result->rangeProofHash, is_confidential(result->amt.prefix) ? &output->rangeProof : &(rawBuffer){0});
|
||||
hashBuffer(&result->surjectionProofHash, is_confidential(result->asset.prefix) ? &output->surjectionProof : &(rawElementsBuffer){0});
|
||||
hashBuffer(&result->rangeProofHash, is_confidential(result->amt.prefix) ? &output->rangeProof : &(rawElementsBuffer){0});
|
||||
result->assetFee = 0;
|
||||
}
|
||||
|
||||
|
|
@ -306,15 +306,15 @@ static uint_fast32_t sumFees(sigOutput** feeOutputs, uint_fast32_t numFees) {
|
|||
return result + 1;
|
||||
}
|
||||
|
||||
/* Allocate and initialize a 'transaction' from a 'rawTransaction', copying or hashing the data as needed.
|
||||
/* Allocate and initialize a 'elementsTransaction' from a 'rawElementsTransaction', copying or hashing the data as needed.
|
||||
* Returns NULL if malloc fails (or if malloc cannot be called because we require an allocation larger than SIZE_MAX).
|
||||
*
|
||||
* Precondition: NULL != rawTx
|
||||
*/
|
||||
extern transaction* simplicity_elements_mallocTransaction(const rawTransaction* rawTx) {
|
||||
extern elementsTransaction* simplicity_elements_mallocTransaction(const rawElementsTransaction* rawTx) {
|
||||
if (!rawTx) return NULL;
|
||||
|
||||
size_t allocationSize = sizeof(transaction);
|
||||
size_t allocationSize = sizeof(elementsTransaction);
|
||||
|
||||
const size_t pad1 = PADDING(sigInput, allocationSize);
|
||||
if (SIZE_MAX - allocationSize < pad1) return NULL;
|
||||
|
|
@ -360,8 +360,8 @@ extern transaction* simplicity_elements_mallocTransaction(const rawTransaction*
|
|||
/* Casting through void* to avoid warning about pointer alignment.
|
||||
* Our padding is done carefully to ensure alignment.
|
||||
*/
|
||||
transaction* const tx = (transaction*)(void*)allocation;
|
||||
allocation += sizeof(transaction) + pad1;
|
||||
elementsTransaction* const tx = (elementsTransaction*)(void*)allocation;
|
||||
allocation += sizeof(elementsTransaction) + pad1;
|
||||
|
||||
sigInput* const input = (sigInput*)(void*)allocation;
|
||||
allocation += rawTx->numInputs * sizeof(sigInput) + pad2;
|
||||
|
|
@ -379,15 +379,15 @@ extern transaction* simplicity_elements_mallocTransaction(const rawTransaction*
|
|||
but C forgoes the complicated specification of C++. Therefore we must make an explicit cast of feeOutputs in C.
|
||||
See <https://c-faq.com/ansi/constmismatch.html> for details.
|
||||
*/
|
||||
*tx = (transaction){ .input = input
|
||||
, .output = output
|
||||
, .feeOutputs = (sigOutput const * const *)feeOutputs
|
||||
, .numInputs = rawTx->numInputs
|
||||
, .numOutputs = rawTx->numOutputs
|
||||
, .version = rawTx->version
|
||||
, .lockTime = rawTx->lockTime
|
||||
, .isFinal = true
|
||||
};
|
||||
*tx = (elementsTransaction){ .input = input
|
||||
, .output = output
|
||||
, .feeOutputs = (sigOutput const * const *)feeOutputs
|
||||
, .numInputs = rawTx->numInputs
|
||||
, .numOutputs = rawTx->numOutputs
|
||||
, .version = rawTx->version
|
||||
, .lockTime = rawTx->lockTime
|
||||
, .isFinal = true
|
||||
};
|
||||
|
||||
sha256_toMidstate(tx->txid.s, rawTx->txid);
|
||||
{
|
||||
|
|
@ -569,22 +569,22 @@ extern transaction* simplicity_elements_mallocTransaction(const rawTransaction*
|
|||
return tx;
|
||||
}
|
||||
|
||||
/* Free a pointer to 'transaction'.
|
||||
/* Free a pointer to 'elementsTransaction'.
|
||||
*/
|
||||
extern void simplicity_elements_freeTransaction(transaction* tx) {
|
||||
extern void simplicity_elements_freeTransaction(elementsTransaction* tx) {
|
||||
simplicity_free(tx);
|
||||
}
|
||||
|
||||
/* Allocate and initialize a 'tapEnv' from a 'rawTapEnv', copying or hashing the data as needed.
|
||||
/* Allocate and initialize a 'elementsTapEnv' from a 'rawElementsTapEnv', copying or hashing the data as needed.
|
||||
* Returns NULL if malloc fails (or if malloc cannot be called because we require an allocation larger than SIZE_MAX).
|
||||
*
|
||||
* Precondition: *rawEnv is well-formed (i.e. rawEnv->pathLen <= 128.)
|
||||
*/
|
||||
extern tapEnv* simplicity_elements_mallocTapEnv(const rawTapEnv* rawEnv) {
|
||||
extern elementsTapEnv* simplicity_elements_mallocTapEnv(const rawElementsTapEnv* rawEnv) {
|
||||
if (!rawEnv) return NULL;
|
||||
if (128 < rawEnv->pathLen) return NULL;
|
||||
|
||||
size_t allocationSize = sizeof(tapEnv);
|
||||
size_t allocationSize = sizeof(elementsTapEnv);
|
||||
|
||||
const size_t numMidstate = rawEnv->pathLen;
|
||||
const size_t pad1 = PADDING(sha256_midstate, allocationSize);
|
||||
|
|
@ -604,25 +604,25 @@ extern tapEnv* simplicity_elements_mallocTapEnv(const rawTapEnv* rawEnv) {
|
|||
/* Casting through void* to avoid warning about pointer alignment.
|
||||
* Our padding is done carefully to ensure alignment.
|
||||
*/
|
||||
tapEnv* const env = (tapEnv*)(void*)allocation;
|
||||
elementsTapEnv* const env = (elementsTapEnv*)(void*)allocation;
|
||||
sha256_midstate* path = NULL;
|
||||
sha256_midstate internalKey;
|
||||
|
||||
sha256_toMidstate(internalKey.s, &rawEnv->controlBlock[1]);
|
||||
|
||||
if (numMidstate) {
|
||||
allocation += sizeof(tapEnv) + pad1;
|
||||
allocation += sizeof(elementsTapEnv) + pad1;
|
||||
|
||||
if (rawEnv->pathLen) {
|
||||
path = (sha256_midstate*)(void*)allocation;
|
||||
}
|
||||
}
|
||||
|
||||
*env = (tapEnv){ .leafVersion = rawEnv->controlBlock[0] & 0xfe
|
||||
, .internalKey = internalKey
|
||||
, .path = path
|
||||
, .pathLen = rawEnv->pathLen
|
||||
};
|
||||
*env = (elementsTapEnv){ .leafVersion = rawEnv->controlBlock[0] & 0xfe
|
||||
, .internalKey = internalKey
|
||||
, .path = path
|
||||
, .pathLen = rawEnv->pathLen
|
||||
};
|
||||
sha256_toMidstate(env->scriptCMR.s, rawEnv->scriptCMR);
|
||||
|
||||
{
|
||||
|
|
@ -646,33 +646,8 @@ extern tapEnv* simplicity_elements_mallocTapEnv(const rawTapEnv* rawEnv) {
|
|||
return env;
|
||||
}
|
||||
|
||||
/* Free a pointer to 'tapEnv'.
|
||||
/* Free a pointer to 'elementsTapEnv'.
|
||||
*/
|
||||
extern void simplicity_elements_freeTapEnv(tapEnv* env) {
|
||||
extern void simplicity_elements_freeTapEnv(elementsTapEnv* env) {
|
||||
simplicity_free(env);
|
||||
}
|
||||
|
||||
/* Construct a txEnv structure from its components.
|
||||
* This function will precompute any cached values.
|
||||
*
|
||||
* Precondition: NULL != tx
|
||||
* NULL != taproot
|
||||
* NULL != genesisHash
|
||||
* ix < tx->numInputs
|
||||
*/
|
||||
txEnv simplicity_build_txEnv(const transaction* tx, const tapEnv* taproot, const sha256_midstate* genesisHash, uint_fast32_t ix) {
|
||||
txEnv result = { .tx = tx
|
||||
, .taproot = taproot
|
||||
, .genesisHash = *genesisHash
|
||||
, .ix = ix
|
||||
};
|
||||
sha256_context ctx = sha256_init(result.sigAllHash.s);
|
||||
sha256_hash(&ctx, genesisHash);
|
||||
sha256_hash(&ctx, genesisHash);
|
||||
sha256_hash(&ctx, &tx->txHash);
|
||||
sha256_hash(&ctx, &taproot->tapEnvHash);
|
||||
sha256_u32be(&ctx, ix);
|
||||
sha256_finalize(&ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3,12 +3,13 @@
|
|||
#include <stdalign.h>
|
||||
#include <string.h>
|
||||
#include "primitive.h"
|
||||
#include "../../deserialize.h"
|
||||
#include "../../eval.h"
|
||||
#include "../../limitations.h"
|
||||
#include "../../simplicity_alloc.h"
|
||||
#include "../../simplicity_assert.h"
|
||||
#include "../../typeInference.h"
|
||||
#include "txEnv.h"
|
||||
#include "../deserialize.h"
|
||||
#include "../eval.h"
|
||||
#include "../limitations.h"
|
||||
#include "../simplicity_alloc.h"
|
||||
#include "../simplicity_assert.h"
|
||||
#include "../typeInference.h"
|
||||
|
||||
/* Deserialize a Simplicity 'program' with its 'witness' data and execute it in the environment of the 'ix'th input of 'tx' with `taproot`.
|
||||
*
|
||||
|
|
@ -17,6 +18,12 @@
|
|||
* Otherwise, 'true' is returned indicating that the result was successfully computed and returned in the '*error' value.
|
||||
*
|
||||
* If deserialization, analysis, or execution fails, then '*error' is set to some simplicity_err.
|
||||
* In particular, if the cost analysis exceeds the budget, or exceeds BUDGET_MAX, then '*error' is set to 'SIMPLICITY_ERR_EXEC_BUDGET'.
|
||||
* On the other hand, if the cost analysis is less than or equal to minCost, then '*error' is set to 'SIMPLICITY_ERR_OVERWEIGHT'.
|
||||
*
|
||||
* Note that minCost and budget parameters are in WU, while the cost analysis will be performed in milliWU.
|
||||
* Thus the minCost and budget specify a half open interval (minCost, budget] of acceptable cost values in milliWU.
|
||||
* Setting minCost to 0 effectively disables the minCost check as every Simplicity program has a non-zero cost analysis.
|
||||
*
|
||||
* If 'amr != NULL' and the annotated Merkle root of the decoded expression doesn't match 'amr' then '*error' is set to 'SIMPLICITY_ERR_AMR'.
|
||||
*
|
||||
|
|
@ -30,15 +37,15 @@
|
|||
* NULL != tx;
|
||||
* NULL != taproot;
|
||||
* unsigned char genesisBlockHash[32]
|
||||
* 0 <= budget;
|
||||
* 0 <= minCost <= budget;
|
||||
* NULL != amr implies unsigned char amr[32]
|
||||
* unsigned char program[program_len]
|
||||
* unsigned char witness[witness_len]
|
||||
*/
|
||||
extern bool simplicity_elements_execSimplicity( simplicity_err* error, unsigned char* ihr
|
||||
, const transaction* tx, uint_fast32_t ix, const tapEnv* taproot
|
||||
, const elementsTransaction* tx, uint_fast32_t ix, const elementsTapEnv* taproot
|
||||
, const unsigned char* genesisBlockHash
|
||||
, int64_t budget
|
||||
, int64_t minCost, int64_t budget
|
||||
, const unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len) {
|
||||
|
|
@ -46,7 +53,8 @@ extern bool simplicity_elements_execSimplicity( simplicity_err* error, unsigned
|
|||
simplicity_assert(NULL != tx);
|
||||
simplicity_assert(NULL != taproot);
|
||||
simplicity_assert(NULL != genesisBlockHash);
|
||||
simplicity_assert(0 <= budget);
|
||||
simplicity_assert(0 <= minCost);
|
||||
simplicity_assert(minCost <= budget);
|
||||
simplicity_assert(NULL != program || 0 == program_len);
|
||||
simplicity_assert(NULL != witness || 0 == witness_len);
|
||||
|
||||
|
|
@ -60,7 +68,7 @@ extern bool simplicity_elements_execSimplicity( simplicity_err* error, unsigned
|
|||
|
||||
{
|
||||
bitstream stream = initializeBitstream(program, program_len);
|
||||
dag_len = simplicity_decodeMallocDag(&dag, &census, &stream);
|
||||
dag_len = simplicity_decodeMallocDag(&dag, simplicity_elements_decodeJet, &census, &stream);
|
||||
if (dag_len <= 0) {
|
||||
simplicity_assert(dag_len < 0);
|
||||
*error = (simplicity_err)dag_len;
|
||||
|
|
@ -79,7 +87,7 @@ extern bool simplicity_elements_execSimplicity( simplicity_err* error, unsigned
|
|||
|
||||
if (IS_OK(*error)) {
|
||||
type* type_dag = NULL;
|
||||
*error = simplicity_mallocTypeInference(&type_dag, dag, (uint_fast32_t)dag_len, &census);
|
||||
*error = simplicity_mallocTypeInference(&type_dag, simplicity_elements_mallocBoundVars, dag, (uint_fast32_t)dag_len, &census);
|
||||
if (IS_OK(*error)) {
|
||||
simplicity_assert(NULL != type_dag);
|
||||
if (0 != dag[dag_len-1].sourceType || 0 != dag[dag_len-1].targetType) {
|
||||
|
|
@ -117,9 +125,12 @@ extern bool simplicity_elements_execSimplicity( simplicity_err* error, unsigned
|
|||
simplicity_free(analysis);
|
||||
}
|
||||
if (IS_OK(*error)) {
|
||||
txEnv env = simplicity_build_txEnv(tx, taproot, &genesis_hash, ix);
|
||||
txEnv env = simplicity_elements_build_txEnv(tx, taproot, &genesis_hash, ix);
|
||||
static_assert(BUDGET_MAX <= UBOUNDED_MAX, "BUDGET_MAX doesn't fit in ubounded.");
|
||||
*error = evalTCOProgram(dag, type_dag, (size_t)dag_len, &(ubounded){budget <= BUDGET_MAX ? (ubounded)budget : BUDGET_MAX}, &env);
|
||||
*error = evalTCOProgram( dag, type_dag, (size_t)dag_len
|
||||
, minCost <= BUDGET_MAX ? (ubounded)minCost : BUDGET_MAX
|
||||
, &(ubounded){budget <= BUDGET_MAX ? (ubounded)budget : BUDGET_MAX}
|
||||
, &env);
|
||||
}
|
||||
simplicity_free(type_dag);
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
/* This module defines operations used in the construction the environment ('txEnv') and some jets.
|
||||
*/
|
||||
#ifndef SIMPLICITY_PRIMITIVE_ELEMENTS_OPS_H
|
||||
#define SIMPLICITY_PRIMITIVE_ELEMENTS_OPS_H
|
||||
#ifndef SIMPLICITY_ELEMENTS_OPS_H
|
||||
#define SIMPLICITY_ELEMENTS_OPS_H
|
||||
|
||||
#include "../../sha256.h"
|
||||
#include "primitive.h"
|
||||
#include "../sha256.h"
|
||||
#include "txEnv.h"
|
||||
|
||||
/* Add an 'confidential' value to be consumed by an ongoing SHA-256 evaluation.
|
||||
* If the 'confidential' value is blinded, then the 'evenPrefix' used if the y coordinate is even,
|
||||
|
|
@ -1,12 +1,9 @@
|
|||
/* This module implements the 'primitive.h' interface for the Elements application of Simplicity.
|
||||
*/
|
||||
#include "primitive.h"
|
||||
|
||||
#include "elementsJets.h"
|
||||
#include "../../limitations.h"
|
||||
#include "../../primitive.h"
|
||||
#include "../../simplicity_alloc.h"
|
||||
#include "../../simplicity_assert.h"
|
||||
#include "../limitations.h"
|
||||
#include "../simplicity_alloc.h"
|
||||
#include "../simplicity_assert.h"
|
||||
|
||||
/* An enumeration of all the types we need to construct to specify the input and output types of all jets created by 'decodeJet'. */
|
||||
enum TypeNamesForJets {
|
||||
|
|
@ -32,7 +29,7 @@ enum TypeNamesForJets {
|
|||
* '(*bound_var)[i]' is bound to 'A' and '(*bound_var)[j]' is bound to 'B'
|
||||
* and, '*word256_ix < *extra_var_start' and '(*bound_var)[*word256_ix]' is bound the type 'TWO^256'
|
||||
*/
|
||||
size_t simplicity_mallocBoundVars(unification_var** bound_var, size_t* word256_ix, size_t* extra_var_start, size_t extra_var_len) {
|
||||
size_t simplicity_elements_mallocBoundVars(unification_var** bound_var, size_t* word256_ix, size_t* extra_var_start, size_t extra_var_len) {
|
||||
static_assert(1 <= NumberOfTypeNames, "Missing TypeNamesForJets.");
|
||||
static_assert(NumberOfTypeNames <= NUMBER_OF_TYPENAMES_MAX, "Too many TypeNamesForJets.");
|
||||
static_assert(DAG_LEN_MAX <= (SIZE_MAX - NumberOfTypeNames) / 6, "NumberOfTypeNames + 6*DAG_LEN_MAX doesn't fit in size_t");
|
||||
|
|
@ -71,7 +68,7 @@ static simplicity_err decodePrimitive(jetName* result, bitstream* stream) {
|
|||
if (bit < 0) return (simplicity_err)bit;
|
||||
if (!bit) {
|
||||
/* Core jets */
|
||||
#include "../../decodeCoreJets.inc"
|
||||
#include "../decodeCoreJets.inc"
|
||||
return SIMPLICITY_ERR_DATA_OUT_OF_RANGE;
|
||||
} else {
|
||||
/* Elements jets */
|
||||
|
|
@ -94,12 +91,12 @@ static dag_node jetNode(jetName name) {
|
|||
* Returns 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' if the stream's prefix doesn't match any valid code for a jet.
|
||||
* Returns 'SIMPLICITY_ERR_BITSTRING_EOF' if not enough bits are available in the 'stream'.
|
||||
* In the above error cases, 'dag' may be modified.
|
||||
* Returns 'SIMPLICITY_NO_ERR' if successful.
|
||||
* Returns 'SIMPLICITY_NO_ERROR' if successful.
|
||||
*
|
||||
* Precondition: NULL != node
|
||||
* NULL != stream
|
||||
*/
|
||||
simplicity_err simplicity_decodeJet(dag_node* node, bitstream* stream) {
|
||||
simplicity_err simplicity_elements_decodeJet(dag_node* node, bitstream* stream) {
|
||||
jetName name;
|
||||
simplicity_err error = decodePrimitive(&name, stream);
|
||||
if (!IS_OK(error)) return error;
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
/* This module defines the interface that each Simplicity application must implement.
|
||||
/* Implements the required callbacks for the Elements Simplicity application.
|
||||
*/
|
||||
#ifndef SIMPLICITY_PRIMITIVE_H
|
||||
#define SIMPLICITY_PRIMITIVE_H
|
||||
#ifndef SIMPLICITY_ELEMENTS_PRIMITIVE_H
|
||||
#define SIMPLICITY_ELEMENTS_PRIMITIVE_H
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "typeInference.h"
|
||||
#include "../bitstream.h"
|
||||
#include "../typeInference.h"
|
||||
|
||||
/* Allocate a fresh set of unification variables bound to at least all the types necessary
|
||||
* for all the jets that can be created by 'decodeJet', and also the type 'TWO^256',
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
* '(*bound_var)[i]' is bound to 'A' and '(*bound_var)[j]' is bound to 'B'
|
||||
* and, '*word256_ix < *extra_var_start' and '(*bound_var)[*word256_ix]' is bound the type 'TWO^256'
|
||||
*/
|
||||
size_t simplicity_mallocBoundVars(unification_var** bound_var, size_t* word256_ix, size_t* extra_var_start, size_t extra_var_len);
|
||||
size_t simplicity_elements_mallocBoundVars(unification_var** bound_var, size_t* word256_ix, size_t* extra_var_start, size_t extra_var_len);
|
||||
|
||||
/* Decode an Elements specific jet from 'stream' into 'node'.
|
||||
* All jets begin with a bit prefix of '1' which needs to have already been consumed from the 'stream'.
|
||||
|
|
@ -36,6 +36,6 @@ size_t simplicity_mallocBoundVars(unification_var** bound_var, size_t* word256_i
|
|||
* Precondition: NULL != node
|
||||
* NULL != stream
|
||||
*/
|
||||
simplicity_err simplicity_decodeJet(dag_node* node, bitstream* stream);
|
||||
simplicity_err simplicity_elements_decodeJet(dag_node* node, bitstream* stream);
|
||||
|
||||
#endif
|
||||
26
src/simplicity/elements/txEnv.c
Normal file
26
src/simplicity/elements/txEnv.c
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#include "txEnv.h"
|
||||
|
||||
/* Construct a txEnv structure from its components.
|
||||
* This function will precompute any cached values.
|
||||
*
|
||||
* Precondition: NULL != tx
|
||||
* NULL != taproot
|
||||
* NULL != genesisHash
|
||||
* ix < tx->numInputs
|
||||
*/
|
||||
txEnv simplicity_elements_build_txEnv(const elementsTransaction* tx, const elementsTapEnv* taproot, const sha256_midstate* genesisHash, uint_fast32_t ix) {
|
||||
txEnv result = { .tx = tx
|
||||
, .taproot = taproot
|
||||
, .genesisHash = *genesisHash
|
||||
, .ix = ix
|
||||
};
|
||||
sha256_context ctx = sha256_init(result.sigAllHash.s);
|
||||
sha256_hash(&ctx, genesisHash);
|
||||
sha256_hash(&ctx, genesisHash);
|
||||
sha256_hash(&ctx, &tx->txHash);
|
||||
sha256_hash(&ctx, &taproot->tapEnvHash);
|
||||
sha256_u32be(&ctx, ix);
|
||||
sha256_finalize(&ctx);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
* It includes the transaction data and input index of the input whose Simplicity program is being executed.
|
||||
* It also includes the commitment Merkle root of the program being executed.
|
||||
*/
|
||||
#ifndef SIMPLICITY_PRIMITIVE_ELEMENTS_H
|
||||
#define SIMPLICITY_PRIMITIVE_ELEMENTS_H
|
||||
#ifndef SIMPLICITY_ELEMENTS_TXENV_H
|
||||
#define SIMPLICITY_ELEMENTS_TXENV_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../../sha256.h"
|
||||
#include "../sha256.h"
|
||||
|
||||
/* An Elements 'outpoint' consists of a transaction id and output index within that transaction.
|
||||
* The transaction id can be a either a transaction within the chain, or the transaction id from another chain in case of a peg-in.
|
||||
|
|
@ -194,7 +194,7 @@ typedef struct sigInput {
|
|||
/* A structure representing data from an Elements transaction (along with the utxo data of the outputs being redeemed).
|
||||
* Includes a variety of cached hash values that are used in signature hash jets.
|
||||
*/
|
||||
typedef struct transaction {
|
||||
typedef struct elementsTransaction {
|
||||
const sigInput* input;
|
||||
const sigOutput* output;
|
||||
const sigOutput* const * feeOutputs;
|
||||
|
|
@ -230,14 +230,14 @@ typedef struct transaction {
|
|||
uint_fast16_t lockDistance;
|
||||
uint_fast16_t lockDuration; /* Units of 512 seconds */
|
||||
bool isFinal;
|
||||
} transaction;
|
||||
} elementsTransaction;
|
||||
|
||||
/* A structure representing taproot spending data from an Elements transaction.
|
||||
*
|
||||
* Invariant: pathLen <= 128
|
||||
* sha256_midstate path[pathLen];
|
||||
*/
|
||||
typedef struct tapEnv {
|
||||
typedef struct elementsTapEnv {
|
||||
const sha256_midstate *path;
|
||||
sha256_midstate tapLeafHash;
|
||||
sha256_midstate tappathHash;
|
||||
|
|
@ -246,7 +246,7 @@ typedef struct tapEnv {
|
|||
sha256_midstate scriptCMR;
|
||||
unsigned char pathLen;
|
||||
unsigned char leafVersion;
|
||||
} tapEnv;
|
||||
} elementsTapEnv;
|
||||
|
||||
/* The 'txEnv' structure used by the Elements application of Simplicity.
|
||||
*
|
||||
|
|
@ -256,8 +256,8 @@ typedef struct tapEnv {
|
|||
* + the hash of the genesis block for the chain,
|
||||
*/
|
||||
typedef struct txEnv {
|
||||
const transaction* tx;
|
||||
const tapEnv* taproot;
|
||||
const elementsTransaction* tx;
|
||||
const elementsTapEnv* taproot;
|
||||
sha256_midstate genesisHash;
|
||||
sha256_midstate sigAllHash;
|
||||
uint_fast32_t ix;
|
||||
|
|
@ -271,6 +271,6 @@ typedef struct txEnv {
|
|||
* NULL != genesisHash
|
||||
* ix < tx->numInputs
|
||||
*/
|
||||
txEnv simplicity_build_txEnv(const transaction* tx, const tapEnv* taproot, const sha256_midstate* genesisHash, uint_fast32_t ix);
|
||||
txEnv simplicity_elements_build_txEnv(const elementsTransaction* tx, const elementsTapEnv* taproot, const sha256_midstate* genesisHash, uint_fast32_t ix);
|
||||
|
||||
#endif
|
||||
|
|
@ -571,6 +571,7 @@ typedef struct boundsAnalysis {
|
|||
* When maxCells < UBOUNDED_MAX, if the bounds on the number of cells needed for evaluation of 'dag' on an idealized Bit Machine exceeds maxCells,
|
||||
* then return SIMPLICITY_ERR_EXEC_MEMORY.
|
||||
* When maxCost < UBOUNDED_MAX, if the bounds on the dag's CPU cost exceeds 'maxCost', then return SIMPLICITY_ERR_EXEC_BUDGET.
|
||||
* If the bounds on the dag's CPU cost is less than or equal to 'minCost', then return SIMPLICITY_ERR_OVERWEIGHT.
|
||||
* Otherwise returns SIMPLICITY_NO_ERR.
|
||||
*
|
||||
* Precondition: NULL != cellsBound
|
||||
|
|
@ -583,11 +584,9 @@ typedef struct boundsAnalysis {
|
|||
* and if maxCells < UBOUNDED_MAX then '*cellsBound' bounds the number of cells needed for evaluation of 'dag' on an idealized Bit Machine
|
||||
* and if maxCells < UBOUNDED_MAX then '*UWORDBound' bounds the number of UWORDs needed for the frames during evaluation of 'dag'
|
||||
* and if maxCells < UBOUNDED_MAX then '*frameBound' bounds the number of stack frames needed during execution of 'dag'.
|
||||
*
|
||||
* :TODO: The cost calculations below are estimated and need to be replaced by experimental data.
|
||||
*/
|
||||
simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBound, ubounded *frameBound, ubounded *costBound
|
||||
, ubounded maxCells, ubounded maxCost, const dag_node* dag, const type* type_dag, const size_t len) {
|
||||
, ubounded maxCells, ubounded minCost, ubounded maxCost, const dag_node* dag, const type* type_dag, const size_t len) {
|
||||
static_assert(DAG_LEN_MAX <= SIZE_MAX / sizeof(boundsAnalysis), "bound array too large.");
|
||||
static_assert(1 <= DAG_LEN_MAX, "DAG_LEN_MAX is zero.");
|
||||
static_assert(DAG_LEN_MAX - 1 <= UINT32_MAX, "bound array index does not fit in uint32_t.");
|
||||
|
|
@ -741,6 +740,7 @@ simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBo
|
|||
*/
|
||||
return (maxCells < *cellsBound) ? SIMPLICITY_ERR_EXEC_MEMORY
|
||||
: (maxCost < *costBound) ? SIMPLICITY_ERR_EXEC_BUDGET
|
||||
: (*costBound <= minCost) ? SIMPLICITY_ERR_OVERWEIGHT
|
||||
: SIMPLICITY_NO_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -748,11 +748,16 @@ simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBo
|
|||
* 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_BUDGET'
|
||||
* If static analysis results determines the bound on memory allocation requirements exceed the allowed limits, returns 'SIMPLICITY_ERR_EXEC_MEMORY'
|
||||
* When a budget is given, if static analysis results determines the bound on cpu requirements exceed the allowed budget, returns 'SIMPLICITY_ERR_EXEC_BUDGET'.
|
||||
* If static analysis results determines the bound on cpu requirements is less than or equal to the minCost, returns 'SIMPLICITY_ERR_OVERWEIGHT'.
|
||||
* If static analysis results determines the bound on memory allocation requirements exceed the allowed limits, returns 'SIMPLICITY_ERR_EXEC_MEMORY'.
|
||||
* If during execution some jet execution fails, returns 'SIMPLICITY_ERR_EXEC_JET'.
|
||||
* If during execution some 'assertr' or 'assertl' combinator fails, returns 'SIMPLICITY_ERR_EXEC_ASESRT'.
|
||||
*
|
||||
* Note that minCost and budget parameters are in WU, while the cost analysis will be performed in milliWU.
|
||||
* Thus the minCost and budget specify a half open interval (minCost, budget] of acceptable cost values in milliWU.
|
||||
* Setting minCost to 0 effectively disables the minCost check as every Simplicity program has a non-zero cost analysis.
|
||||
*
|
||||
* If none of the above conditions fail and bitSize(B) > 0, then a copy the final active write frame's data is written to 'output[roundWord(bitSize(B))]'.
|
||||
*
|
||||
* If 'anti_dos_checks' includes the 'CHECK_EXEC' flag, and not every non-HIDDEN dag node is executed, returns 'SIMPLICITY_ERR_ANTIDOS'
|
||||
|
|
@ -764,19 +769,25 @@ simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBo
|
|||
* bitSize(A) == 0 or UWORD input[ROUND_UWORD(bitSize(A))];
|
||||
* bitSize(B) == 0 or UWORD output[ROUND_UWORD(bitSize(B))];
|
||||
* if NULL != budget then *budget <= BUDGET_MAX
|
||||
* if NULL != budget then minCost <= *budget
|
||||
* minCost <= BUDGET_MAX
|
||||
* if 'dag[len]' represents a Simplicity expression with primitives then 'NULL != env';
|
||||
*/
|
||||
simplicity_err simplicity_evalTCOExpression( flags_type anti_dos_checks, UWORD* output, const UWORD* input
|
||||
, const dag_node* dag, type* type_dag, size_t len, const ubounded* budget, const txEnv* env
|
||||
) {
|
||||
, const dag_node* dag, type* type_dag, size_t len, ubounded minCost, const ubounded* budget, const txEnv* env
|
||||
) {
|
||||
simplicity_assert(1 <= len);
|
||||
simplicity_assert(len <= DAG_LEN_MAX);
|
||||
if (budget) { simplicity_assert(*budget <= BUDGET_MAX); }
|
||||
if (budget) {
|
||||
simplicity_assert(*budget <= BUDGET_MAX);
|
||||
simplicity_assert(minCost <= *budget);
|
||||
}
|
||||
simplicity_assert(minCost <= BUDGET_MAX);
|
||||
static_assert(1 <= UBOUNDED_MAX, "UBOUNDED_MAX is zero.");
|
||||
static_assert(BUDGET_MAX <= (UBOUNDED_MAX - 1) / 1000, "BUDGET_MAX is too large.");
|
||||
static_assert(CELLS_MAX < UBOUNDED_MAX, "CELLS_MAX is too large.");
|
||||
ubounded cellsBound, UWORDBound, frameBound, costBound;
|
||||
simplicity_err result = simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, CELLS_MAX, budget ? *budget*1000 : UBOUNDED_MAX, dag, type_dag, len);
|
||||
simplicity_err result = simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, CELLS_MAX, minCost*1000, budget ? *budget*1000 : UBOUNDED_MAX, dag, type_dag, len);
|
||||
if (!IS_OK(result)) return result;
|
||||
|
||||
/* frameBound is at most 2*len. */
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ typedef unsigned char flags_type;
|
|||
* When maxCells < UBOUNDED_MAX, if the bounds on the number of cells needed for evaluation of 'dag' on an idealized Bit Machine exceeds maxCells,
|
||||
* then return SIMPLICITY_ERR_EXEC_MEMORY.
|
||||
* When maxCost < UBOUNDED_MAX, if the bounds on the dag's CPU cost exceeds 'maxCost', then return SIMPLICITY_ERR_EXEC_BUDGET.
|
||||
* If the bounds on the dag's CPU cost is less than or equal to 'minCost', then return SIMPLICITY_ERR_OVERWEIGHT.
|
||||
* Otherwise returns SIMPLICITY_NO_ERR.
|
||||
*
|
||||
* Precondition: NULL != cellsBound
|
||||
|
|
@ -32,17 +33,22 @@ typedef unsigned char flags_type;
|
|||
* and if maxCells < UBOUNDED_MAX then '*frameBound' bounds the number of stack frames needed during execution of 'dag'.
|
||||
*/
|
||||
simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBound, ubounded *frameBound, ubounded *costBound
|
||||
, ubounded maxCells, ubounded maxCost, const dag_node* dag, const type* type_dag, const size_t len);
|
||||
, ubounded maxCells, ubounded minCost, ubounded maxCost, const dag_node* dag, const type* type_dag, const size_t len);
|
||||
|
||||
/* 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_BUDGET'
|
||||
* If static analysis results determines the bound on memory allocation requirements exceed the allowed limits, returns 'SIMPLICITY_ERR_EXEC_MEMORY'
|
||||
* When a budget is given, if static analysis results determines the bound on cpu requirements exceed the allowed budget, returns 'SIMPLICITY_ERR_EXEC_BUDGET'.
|
||||
* If static analysis results determines the bound on cpu requirements is less than or equal to the minCost, returns 'SIMPLICITY_ERR_OVERWEIGHT'.
|
||||
* If static analysis results determines the bound on memory allocation requirements exceed the allowed limits, returns 'SIMPLICITY_ERR_EXEC_MEMORY'.
|
||||
* If during execution some jet execution fails, returns 'SIMPLICITY_ERR_EXEC_JET'.
|
||||
* If during execution some 'assertr' or 'assertl' combinator fails, returns 'SIMPLICITY_ERR_EXEC_ASESRT'.
|
||||
*
|
||||
* Note that minCost and budget parameters are in WU, while the cost analysis will be performed in milliWU.
|
||||
* Thus the minCost and budget specify a half open interval (minCost, budget] of acceptable cost values in milliWU.
|
||||
* Setting minCost to 0 effectively disables the minCost check as every Simplicity program has a non-zero cost analysis.
|
||||
*
|
||||
* If none of the above conditions fail and bitSize(B) > 0, then a copy the final active write frame's data is written to 'output[roundWord(bitSize(B))]'.
|
||||
*
|
||||
* If 'anti_dos_checks' includes the 'CHECK_EXEC' flag, and not every non-HIDDEN dag node is executed, returns 'SIMPLICITY_ERR_ANTIDOS'
|
||||
|
|
@ -54,19 +60,27 @@ simplicity_err simplicity_analyseBounds( ubounded *cellsBound, ubounded *UWORDBo
|
|||
* bitSize(A) == 0 or UWORD input[ROUND_UWORD(bitSize(A))];
|
||||
* bitSize(B) == 0 or UWORD output[ROUND_UWORD(bitSize(B))];
|
||||
* if NULL != budget then *budget <= BUDGET_MAX
|
||||
* if NULL != budget then minCost <= *budget
|
||||
* minCost <= BUDGET_MAX
|
||||
* if 'dag[len]' represents a Simplicity expression with primitives then 'NULL != env';
|
||||
*/
|
||||
simplicity_err simplicity_evalTCOExpression( flags_type anti_dos_checks, UWORD* output, const UWORD* input
|
||||
, const dag_node* dag, type* type_dag, size_t len, const ubounded* budget, const txEnv* env
|
||||
);
|
||||
, const dag_node* dag, type* type_dag, size_t len, ubounded minCost, const ubounded* budget, const txEnv* env
|
||||
);
|
||||
|
||||
/* Run the Bit Machine on the well-typed Simplicity program 'dag[len]'.
|
||||
*
|
||||
* 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_BUDGET'
|
||||
* If static analysis results determines the bound on memory allocation requirements exceed the allowed limits, returns 'SIMPLICITY_ERR_EXEC_MEMORY'
|
||||
* When a budget is given, if static analysis results determines the bound on cpu requirements exceed the allowed budget, returns 'SIMPLICITY_ERR_EXEC_BUDGET'.
|
||||
* If static analysis results determines the bound on cpu requirements is less than or equal to the minCost, returns 'SIMPLICITY_ERR_OVERWEIGHT'.
|
||||
* If static analysis results determines the bound on memory allocation requirements exceed the allowed limits, returns 'SIMPLICITY_ERR_EXEC_MEMORY'.
|
||||
* If during execution some jet execution fails, returns 'SIMPLICITY_ERR_EXEC_JET'.
|
||||
* If during execution some 'assertr' or 'assertl' combinator fails, returns 'SIMPLICITY_ERR_EXEC_ASESRT'.
|
||||
*
|
||||
* Note that minCost and budget parameters are in WU, while the cost analysis will be performed in milliWU.
|
||||
* Thus the minCost and budget specify a half open interval (minCost, budget] of acceptable cost values in milliWU.
|
||||
* Setting minCost to 0 effectively disables the minCost check as every Simplicity program has a non-zero cost analysis.
|
||||
*
|
||||
* If not every non-HIDDEN dag node is executed, returns 'SIMPLICITY_ERR_ANTIDOS'
|
||||
* If not every case node has both branches executed, returns 'SIMPLICITY_ERR_ANTIDOS'
|
||||
*
|
||||
|
|
@ -74,9 +88,11 @@ simplicity_err simplicity_evalTCOExpression( flags_type anti_dos_checks, UWORD*
|
|||
*
|
||||
* Precondition: dag_node dag[len] and 'dag' is well-typed with 'type_dag' for an expression of type ONE |- ONE;
|
||||
* if NULL != budget then *budget <= BUDGET_MAX
|
||||
* if NULL != budget then minCost <= *budget
|
||||
* minCost <= BUDGET_MAX
|
||||
* if 'dag[len]' represents a Simplicity expression with primitives then 'NULL != env';
|
||||
*/
|
||||
static inline simplicity_err evalTCOProgram(const dag_node* dag, type* type_dag, size_t len, const ubounded* budget, const txEnv* env) {
|
||||
return simplicity_evalTCOExpression(CHECK_ALL, NULL, NULL, dag, type_dag, len, budget, env);
|
||||
static inline simplicity_err evalTCOProgram(const dag_node* dag, type* type_dag, size_t len, ubounded minCost, const ubounded* budget, const txEnv* env) {
|
||||
return simplicity_evalTCOExpression(CHECK_ALL, NULL, NULL, dag, type_dag, len, minCost, budget, env);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef SIMPLICITY_CMR_H
|
||||
#define SIMPLICITY_CMR_H
|
||||
#ifndef SIMPLICITY_ELEMENTS_CMR_H
|
||||
#define SIMPLICITY_ELEMENTS_CMR_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
|
@ -18,6 +18,6 @@
|
|||
* unsigned char cmr[32]
|
||||
* unsigned char program[program_len]
|
||||
*/
|
||||
extern bool simplicity_computeCmr( simplicity_err* error, unsigned char* cmr
|
||||
, const unsigned char* program, size_t program_len);
|
||||
extern bool simplicity_elements_computeCmr( simplicity_err* error, unsigned char* cmr
|
||||
, const unsigned char* program, size_t program_len);
|
||||
#endif
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* This section builds the 'rawTransaction' structure which is the transaction data needed to build an Elements 'txEnv' environment
|
||||
/* This section builds the 'rawElementsTransaction' structure which is the transaction data needed to build an Elements 'txEnv' environment
|
||||
* for evaluating Simplicity expressions within.
|
||||
* The 'rawTransaction' is copied into an opaque 'transaction' structure that can be reused within evaluating Simplicity on multiple
|
||||
* The 'rawElementsTransaction' is copied into an opaque 'elementsTransaction' structure that can be reused within evaluating Simplicity on multiple
|
||||
* inputs within the same transaction.
|
||||
*/
|
||||
|
||||
|
|
@ -14,10 +14,10 @@
|
|||
*
|
||||
* Invariant: if 0 < len then unsigned char buf[len]
|
||||
*/
|
||||
typedef struct rawBuffer {
|
||||
typedef struct rawElementsBuffer {
|
||||
const unsigned char* buf;
|
||||
uint32_t len;
|
||||
} rawBuffer;
|
||||
} rawElementsBuffer;
|
||||
|
||||
/* A structure representing data for one output from an Elements transaction.
|
||||
*
|
||||
|
|
@ -25,14 +25,14 @@ typedef struct rawBuffer {
|
|||
* unsigned char value[value[0] == 1 ? 9 : 33] or value == NULL;
|
||||
* unsigned char nonce[33] or nonce == NULL;
|
||||
*/
|
||||
typedef struct rawOutput {
|
||||
typedef struct rawElementsOutput {
|
||||
const unsigned char* asset;
|
||||
const unsigned char* value;
|
||||
const unsigned char* nonce;
|
||||
rawBuffer scriptPubKey;
|
||||
rawBuffer surjectionProof;
|
||||
rawBuffer rangeProof;
|
||||
} rawOutput;
|
||||
rawElementsBuffer scriptPubKey;
|
||||
rawElementsBuffer surjectionProof;
|
||||
rawElementsBuffer rangeProof;
|
||||
} rawElementsOutput;
|
||||
|
||||
/* A structure representing data for one input from an Elements transaction, including its taproot annex,
|
||||
* plus the TXO data of the output being redeemed.
|
||||
|
|
@ -46,8 +46,8 @@ typedef struct rawOutput {
|
|||
* unsigned char txo.asset[33] or txo.asset == NULL;
|
||||
* unsigned char txo.value[txo.value[0] == 1 ? 9 : 33] or txo.value == NULL;
|
||||
*/
|
||||
typedef struct rawInput {
|
||||
const rawBuffer* annex;
|
||||
typedef struct rawElementsInput {
|
||||
const rawElementsBuffer* annex;
|
||||
const unsigned char* prevTxid;
|
||||
const unsigned char* pegin;
|
||||
struct {
|
||||
|
|
@ -55,48 +55,48 @@ typedef struct rawInput {
|
|||
const unsigned char* assetEntropy;
|
||||
const unsigned char* amount;
|
||||
const unsigned char* inflationKeys;
|
||||
rawBuffer amountRangePrf;
|
||||
rawBuffer inflationKeysRangePrf;
|
||||
rawElementsBuffer amountRangePrf;
|
||||
rawElementsBuffer inflationKeysRangePrf;
|
||||
} issuance;
|
||||
struct {
|
||||
const unsigned char* asset;
|
||||
const unsigned char* value;
|
||||
rawBuffer scriptPubKey;
|
||||
rawElementsBuffer scriptPubKey;
|
||||
} txo;
|
||||
rawBuffer scriptSig;
|
||||
rawElementsBuffer scriptSig;
|
||||
uint32_t prevIx;
|
||||
uint32_t sequence;
|
||||
} rawInput;
|
||||
} rawElementsInput;
|
||||
|
||||
/* A structure representing data for an Elements transaction, including the TXO data of each output being redeemed.
|
||||
*
|
||||
* Invariant: unsigned char txid[32];
|
||||
* rawInput input[numInputs];
|
||||
* rawOutput output[numOutputs];
|
||||
* rawElementsInput input[numInputs];
|
||||
* rawElementsOutput output[numOutputs];
|
||||
*/
|
||||
typedef struct rawTransaction {
|
||||
typedef struct rawElementsTransaction {
|
||||
const unsigned char* txid; /* While in theory we could recompute the txid ourselves, it is easier and safer for it to be provided. */
|
||||
const rawInput* input;
|
||||
const rawOutput* output;
|
||||
const rawElementsInput* input;
|
||||
const rawElementsOutput* output;
|
||||
uint32_t numInputs;
|
||||
uint32_t numOutputs;
|
||||
uint32_t version;
|
||||
uint32_t lockTime;
|
||||
} rawTransaction;
|
||||
} rawElementsTransaction;
|
||||
|
||||
/* A forward declaration for the structure containing a copy (and digest) of the rawTransaction data */
|
||||
typedef struct transaction transaction;
|
||||
/* A forward declaration for the structure containing a copy (and digest) of the rawElementsTransaction data */
|
||||
typedef struct elementsTransaction elementsTransaction;
|
||||
|
||||
/* Allocate and initialize a 'transaction' from a 'rawTransaction', copying or hashing the data as needed.
|
||||
/* Allocate and initialize a 'elementsTransaction' from a 'rawElementsTransaction', copying or hashing the data as needed.
|
||||
* Returns NULL if malloc fails (or if malloc cannot be called because we require an allocation larger than SIZE_MAX).
|
||||
*
|
||||
* Precondition: NULL != rawTx
|
||||
*/
|
||||
extern transaction* simplicity_elements_mallocTransaction(const rawTransaction* rawTx);
|
||||
extern elementsTransaction* simplicity_elements_mallocTransaction(const rawElementsTransaction* rawTx);
|
||||
|
||||
/* Free a pointer to 'transaction'.
|
||||
/* Free a pointer to 'elementsTransaction'.
|
||||
*/
|
||||
extern void simplicity_elements_freeTransaction(transaction* tx);
|
||||
extern void simplicity_elements_freeTransaction(elementsTransaction* tx);
|
||||
|
||||
/* A structure representing taproot spending data for an Elements transaction.
|
||||
*
|
||||
|
|
@ -104,23 +104,23 @@ extern void simplicity_elements_freeTransaction(transaction* tx);
|
|||
* unsigned char controlBlock[33+pathLen*32];
|
||||
* unsigned char scriptCMR[32];
|
||||
*/
|
||||
typedef struct rawTapEnv {
|
||||
typedef struct rawElementsTapEnv {
|
||||
const unsigned char* controlBlock;
|
||||
const unsigned char* scriptCMR;
|
||||
unsigned char pathLen;
|
||||
} rawTapEnv;
|
||||
} rawElementsTapEnv;
|
||||
|
||||
/* A forward declaration for the structure containing a copy (and digest) of the rawTapEnv data */
|
||||
typedef struct tapEnv tapEnv;
|
||||
/* A forward declaration for the structure containing a copy (and digest) of the rawElementsTapEnv data */
|
||||
typedef struct elementsTapEnv elementsTapEnv;
|
||||
|
||||
/* Allocate and initialize a 'tapEnv' from a 'rawTapEnv', copying or hashing the data as needed.
|
||||
/* Allocate and initialize a 'elementsTapEnv' from a 'rawElementsTapEnv', copying or hashing the data as needed.
|
||||
* Returns NULL if malloc fails (or if malloc cannot be called because we require an allocation larger than SIZE_MAX).
|
||||
*
|
||||
* Precondition: *rawEnv is well-formed (i.e. rawEnv->pathLen <= 128.)
|
||||
*/
|
||||
extern tapEnv* simplicity_elements_mallocTapEnv(const rawTapEnv* rawEnv);
|
||||
extern elementsTapEnv* simplicity_elements_mallocTapEnv(const rawElementsTapEnv* rawEnv);
|
||||
|
||||
/* Free a pointer to 'tapEnv'.
|
||||
/* Free a pointer to 'elementsTapEnv'.
|
||||
*/
|
||||
extern void simplicity_elements_freeTapEnv(tapEnv* env);
|
||||
extern void simplicity_elements_freeTapEnv(elementsTapEnv* env);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,6 +14,12 @@
|
|||
* Otherwise, 'true' is returned indicating that the result was successfully computed and returned in the '*error' value.
|
||||
*
|
||||
* If deserialization, analysis, or execution fails, then '*error' is set to some simplicity_err.
|
||||
* In particular, if the cost analysis exceeds the budget, or exceeds BUDGET_MAX, then '*error' is set to 'SIMPLICITY_ERR_EXEC_BUDGET'.
|
||||
* On the other hand, if the cost analysis is less than or equal to minCost, then '*error' is set to 'SIMPLICITY_ERR_OVERWEIGHT'.
|
||||
*
|
||||
* Note that minCost and budget parameters are in WU, while the cost analysis will be performed in milliWU.
|
||||
* Thus the minCost and budget specify a half open interval (minCost, budget] of acceptable cost values in milliWU.
|
||||
* Setting minCost to 0 effectively disables the minCost check as every Simplicity program has a non-zero cost analysis.
|
||||
*
|
||||
* If 'amr != NULL' and the annotated Merkle root of the decoded expression doesn't match 'amr' then '*error' is set to 'SIMPLICITY_ERR_AMR'.
|
||||
*
|
||||
|
|
@ -27,15 +33,15 @@
|
|||
* NULL != tx;
|
||||
* NULL != taproot;
|
||||
* unsigned char genesisBlockHash[32]
|
||||
* 0 <= budget;
|
||||
* 0 <= minCost <= budget;
|
||||
* NULL != amr implies unsigned char amr[32]
|
||||
* unsigned char program[program_len]
|
||||
* unsigned char witness[witness_len]
|
||||
*/
|
||||
extern bool simplicity_elements_execSimplicity( simplicity_err* error, unsigned char* ihr
|
||||
, const transaction* tx, uint_fast32_t ix, const tapEnv* taproot
|
||||
, const elementsTransaction* tx, uint_fast32_t ix, const elementsTapEnv* taproot
|
||||
, const unsigned char* genesisBlockHash
|
||||
, int64_t budget
|
||||
, int64_t minCost, int64_t budget
|
||||
, const unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ typedef enum {
|
|||
SIMPLICITY_ERR_ANTIDOS = -42,
|
||||
SIMPLICITY_ERR_HIDDEN_ROOT = -44,
|
||||
SIMPLICITY_ERR_AMR = -46,
|
||||
SIMPLICITY_ERR_OVERWEIGHT = -48,
|
||||
} simplicity_err;
|
||||
|
||||
/* Check if failure is permanent (or success which is always permanent). */
|
||||
|
|
@ -102,6 +103,8 @@ static inline const char * SIMPLICITY_ERR_MSG(simplicity_err err) {
|
|||
return "Program's root is HIDDEN";
|
||||
case SIMPLICITY_ERR_AMR:
|
||||
return "Program's AMR does not match";
|
||||
case SIMPLICITY_ERR_OVERWEIGHT:
|
||||
return "Program's budget is too large";
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <time.h>
|
||||
#include <getopt.h>
|
||||
#include <simplicity/elements/exec.h>
|
||||
#include <simplicity/cmr.h>
|
||||
#include <simplicity/elements/cmr.h>
|
||||
#include "ctx8Pruned.h"
|
||||
#include "ctx8Unpruned.h"
|
||||
#include "dag.h"
|
||||
|
|
@ -20,7 +20,8 @@
|
|||
#include "typeSkipTest.h"
|
||||
#include "simplicity_alloc.h"
|
||||
#include "typeInference.h"
|
||||
#include "primitive/elements/checkSigHashAllTx1.h"
|
||||
#include "elements/checkSigHashAllTx1.h"
|
||||
#include "elements/primitive.h"
|
||||
|
||||
_Static_assert(CHAR_BIT == 8, "Buffers passed to fmemopen presume 8 bit chars");
|
||||
|
||||
|
|
@ -78,7 +79,7 @@ static void test_hashBlock(void) {
|
|||
simplicity_err error;
|
||||
{
|
||||
bitstream stream = initializeBitstream(hashBlock, sizeof_hashBlock);
|
||||
len = simplicity_decodeMallocDag(&dag, &census, &stream);
|
||||
len = simplicity_decodeMallocDag(&dag, simplicity_elements_decodeJet, &census, &stream);
|
||||
if (!dag) {
|
||||
simplicity_assert(len < 0);
|
||||
error = (simplicity_err)len;
|
||||
|
|
@ -105,7 +106,7 @@ static void test_hashBlock(void) {
|
|||
|
||||
type* type_dag;
|
||||
bitstream witness = initializeBitstream(hashBlock_witness, sizeof_hashBlock_witness);
|
||||
if (!IS_OK(simplicity_mallocTypeInference(&type_dag, dag, (uint_fast32_t)len, &census)) || !type_dag ||
|
||||
if (!IS_OK(simplicity_mallocTypeInference(&type_dag, simplicity_elements_mallocBoundVars, dag, (uint_fast32_t)len, &census)) || !type_dag ||
|
||||
type_dag[dag[len-1].sourceType].bitSize != 768 || type_dag[dag[len-1].targetType].bitSize != 256) {
|
||||
failures++;
|
||||
printf("Unexpected failure of type inference for hashblock\n");
|
||||
|
|
@ -152,7 +153,7 @@ static void test_hashBlock(void) {
|
|||
}
|
||||
{
|
||||
ubounded cellsBound, UWORDBound, frameBound, costBound;
|
||||
if (IS_OK(simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len))
|
||||
if (IS_OK(simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, 0, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len))
|
||||
&& hashBlock_cost == costBound) {
|
||||
successes++;
|
||||
} else {
|
||||
|
|
@ -160,7 +161,7 @@ static void test_hashBlock(void) {
|
|||
printf("Expected %d for cost, but got %d instead.\n", hashBlock_cost, costBound);
|
||||
}
|
||||
}
|
||||
simplicity_err err = simplicity_evalTCOExpression(CHECK_NONE, output, input, dag, type_dag, (uint_fast32_t)len, NULL, NULL);
|
||||
simplicity_err err = simplicity_evalTCOExpression(CHECK_NONE, output, input, dag, type_dag, (uint_fast32_t)len, 0, NULL, NULL);
|
||||
if (IS_OK(err)) {
|
||||
/* The expected result is the value 'SHA256("abc")'. */
|
||||
const uint32_t expectedHash[8] = { 0xba7816bful, 0x8f01cfeaul, 0x414140deul, 0x5dae2223ul
|
||||
|
|
@ -195,7 +196,7 @@ static void test_program(char* name, const unsigned char* program, size_t progra
|
|||
simplicity_err error;
|
||||
{
|
||||
bitstream stream = initializeBitstream(program, program_len);
|
||||
len = simplicity_decodeMallocDag(&dag, &census, &stream);
|
||||
len = simplicity_decodeMallocDag(&dag, simplicity_elements_decodeJet, &census, &stream);
|
||||
if (!dag) {
|
||||
simplicity_assert(len < 0);
|
||||
error = (simplicity_err)len;
|
||||
|
|
@ -231,7 +232,7 @@ static void test_program(char* name, const unsigned char* program, size_t progra
|
|||
}
|
||||
type* type_dag;
|
||||
bitstream witness_stream = initializeBitstream(witness, witness_len);
|
||||
if (!IS_OK(simplicity_mallocTypeInference(&type_dag, dag, (uint_fast32_t)len, &census)) || !type_dag ||
|
||||
if (!IS_OK(simplicity_mallocTypeInference(&type_dag, simplicity_elements_mallocBoundVars, dag, (uint_fast32_t)len, &census)) || !type_dag ||
|
||||
dag[len-1].sourceType != 0 || dag[len-1].targetType != 0) {
|
||||
failures++;
|
||||
printf("Unexpected failure of type inference.\n");
|
||||
|
|
@ -264,7 +265,8 @@ static void test_program(char* name, const unsigned char* program, size_t progra
|
|||
}
|
||||
if (expectedCost) {
|
||||
ubounded cellsBound, UWORDBound, frameBound, costBound;
|
||||
if (IS_OK(simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len))
|
||||
if (IS_OK(simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, 0, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len))
|
||||
&& 0 < costBound
|
||||
&& *expectedCost == costBound) {
|
||||
successes++;
|
||||
} else {
|
||||
|
|
@ -272,7 +274,8 @@ static void test_program(char* name, const unsigned char* program, size_t progra
|
|||
printf("Expected %u for cost, but got %u instead.\n", *expectedCost, costBound);
|
||||
}
|
||||
/* Analysis should pass when computed bounds are used. */
|
||||
if (IS_OK(simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, cellsBound, costBound, dag, type_dag, (uint_fast32_t)len))) {
|
||||
if (IS_OK(simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, cellsBound, costBound-1, costBound, dag, type_dag, (uint_fast32_t)len))
|
||||
&& *expectedCost == costBound) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
|
|
@ -280,7 +283,7 @@ static void test_program(char* name, const unsigned char* program, size_t progra
|
|||
}
|
||||
/* if cellsBound is non-zero, analysis should fail when smaller cellsBound is used. */
|
||||
if (0 < cellsBound) {
|
||||
if (SIMPLICITY_ERR_EXEC_MEMORY == simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, cellsBound-1, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len)) {
|
||||
if (SIMPLICITY_ERR_EXEC_MEMORY == simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, cellsBound-1, 0, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len)) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
|
|
@ -289,15 +292,24 @@ static void test_program(char* name, const unsigned char* program, size_t progra
|
|||
}
|
||||
/* Analysis should fail when smaller costBound is used. */
|
||||
if (0 < *expectedCost &&
|
||||
SIMPLICITY_ERR_EXEC_BUDGET == simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, *expectedCost-1, dag, type_dag, (uint_fast32_t)len)
|
||||
SIMPLICITY_ERR_EXEC_BUDGET == simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, 0, *expectedCost-1, dag, type_dag, (uint_fast32_t)len)
|
||||
) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
printf("Analysis with too small cost bounds failed.\n");
|
||||
}
|
||||
/* Analysis should fail when overweight. */
|
||||
if (0 < *expectedCost &&
|
||||
SIMPLICITY_ERR_OVERWEIGHT == simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, *expectedCost, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len)
|
||||
) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
printf("Analysis with too large minCost failed.\n");
|
||||
}
|
||||
}
|
||||
simplicity_err actualResult = evalTCOProgram(dag, type_dag, (uint_fast32_t)len, NULL, NULL);
|
||||
simplicity_err actualResult = evalTCOProgram(dag, type_dag, (uint_fast32_t)len, 0, NULL, NULL);
|
||||
if (expectedResult == actualResult) {
|
||||
successes++;
|
||||
} else {
|
||||
|
|
@ -319,7 +331,7 @@ static void test_occursCheck(void) {
|
|||
int_fast32_t len;
|
||||
{
|
||||
bitstream stream = initializeBitstream(buf, sizeof(buf));
|
||||
len = simplicity_decodeMallocDag(&dag, &census, &stream);
|
||||
len = simplicity_decodeMallocDag(&dag, simplicity_elements_decodeJet, &census, &stream);
|
||||
}
|
||||
if (!dag) {
|
||||
simplicity_assert(len < 0);
|
||||
|
|
@ -327,7 +339,7 @@ static void test_occursCheck(void) {
|
|||
} else {
|
||||
type* type_dag;
|
||||
simplicity_assert(0 < len);
|
||||
if (SIMPLICITY_ERR_TYPE_INFERENCE_OCCURS_CHECK == simplicity_mallocTypeInference(&type_dag, dag, (uint_fast32_t)len, &census) &&
|
||||
if (SIMPLICITY_ERR_TYPE_INFERENCE_OCCURS_CHECK == simplicity_mallocTypeInference(&type_dag, simplicity_elements_mallocBoundVars, dag, (uint_fast32_t)len, &census) &&
|
||||
!type_dag) {
|
||||
successes++;
|
||||
} else {
|
||||
|
|
@ -345,18 +357,18 @@ static void test_elements(void) {
|
|||
sha256_fromMidstate(amr, elementsCheckSigHashAllTx1_amr);
|
||||
|
||||
unsigned char genesisHash[32] = "\x0f\x91\x88\xf1\x3c\xb7\xb2\xc7\x1f\x2a\x33\x5e\x3a\x4f\xc3\x28\xbf\x5b\xeb\x43\x60\x12\xaf\xca\x59\x0b\x1a\x11\x46\x6e\x22\x06";
|
||||
rawTapEnv rawTaproot = (rawTapEnv)
|
||||
rawElementsTapEnv rawTaproot = (rawElementsTapEnv)
|
||||
{ .controlBlock = (unsigned char [33]){"\xbe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3b\x78\xce\x56\x3f\x89\xa0\xed\x94\x14\xf5\xaa\x28\xad\x0d\x96\xd6\x79\x5f\x9c\x63"}
|
||||
, .pathLen = 0
|
||||
, .scriptCMR = cmr
|
||||
};
|
||||
tapEnv* taproot = simplicity_elements_mallocTapEnv(&rawTaproot);
|
||||
elementsTapEnv* taproot = simplicity_elements_mallocTapEnv(&rawTaproot);
|
||||
|
||||
printf("Test elements\n");
|
||||
{
|
||||
rawTransaction testTx1 = (rawTransaction)
|
||||
rawElementsTransaction testTx1 = (rawElementsTransaction)
|
||||
{ .txid = (unsigned char[32]){"\xdb\x9a\x3d\xe0\xb6\xb8\xcc\x74\x1e\x4d\x6c\x8f\x19\xce\x75\xec\x0d\xfd\x01\x02\xdb\x9c\xb5\xcd\x27\xa4\x1a\x66\x91\x66\x3a\x07"}
|
||||
, .input = (rawInput[])
|
||||
, .input = (rawElementsInput[])
|
||||
{ { .annex = NULL
|
||||
, .prevTxid = (unsigned char[32]){"\xeb\x04\xb6\x8e\x9a\x26\xd1\x16\x04\x6c\x76\xe8\xff\x47\x33\x2f\xb7\x1d\xda\x90\xff\x4b\xef\x53\x70\xf2\x52\x26\xd3\xbc\x09\xfc"}
|
||||
, .prevIx = 0
|
||||
|
|
@ -367,7 +379,7 @@ static void test_elements(void) {
|
|||
, .value = (unsigned char[9]){"\x01\x00\x00\x00\x02\x54\x0b\xe4\x00"}
|
||||
, .scriptPubKey = {0}
|
||||
} } }
|
||||
, .output = (rawOutput[])
|
||||
, .output = (rawElementsOutput[])
|
||||
{ { .asset = (unsigned char[33]){"\x01\x23\x0f\x4f\x5d\x4b\x7c\x6f\xa8\x45\x80\x6e\xe4\xf6\x77\x13\x45\x9e\x1b\x69\xe8\xe6\x0f\xce\xe2\xe4\x94\x0c\x7a\x0d\x5d\xe1\xb2"}
|
||||
, .value = (unsigned char[9]){"\x01\x00\x00\x00\x02\x54\x0b\xd7\x1c"}
|
||||
, .nonce = NULL
|
||||
|
|
@ -385,13 +397,13 @@ static void test_elements(void) {
|
|||
, .version = 0x00000002
|
||||
, .lockTime = 0x00000000
|
||||
};
|
||||
transaction* tx1 = simplicity_elements_mallocTransaction(&testTx1);
|
||||
elementsTransaction* tx1 = simplicity_elements_mallocTransaction(&testTx1);
|
||||
if (tx1) {
|
||||
successes++;
|
||||
simplicity_err execResult;
|
||||
{
|
||||
unsigned char cmrResult[32];
|
||||
if (simplicity_computeCmr(&execResult, cmrResult, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1) && IS_OK(execResult)) {
|
||||
if (simplicity_elements_computeCmr(&execResult, cmrResult, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1) && IS_OK(execResult)) {
|
||||
if (0 == memcmp(cmrResult, cmr, sizeof(unsigned char[8]))) {
|
||||
successes++;
|
||||
} else {
|
||||
|
|
@ -400,12 +412,12 @@ static void test_elements(void) {
|
|||
}
|
||||
} else {
|
||||
failures++;
|
||||
printf("simplicity_computeCmr of elementsCheckSigHashAllTx1 unexpectedly produced %d.\n", execResult);
|
||||
printf("simplicity_elements_computeCmr of elementsCheckSigHashAllTx1 unexpectedly produced %d.\n", execResult);
|
||||
}
|
||||
}
|
||||
{
|
||||
unsigned char ihrResult[32];
|
||||
if (simplicity_elements_execSimplicity(&execResult, ihrResult, tx1, 0, taproot, genesisHash, (elementsCheckSigHashAllTx1_cost + 999)/1000, amr, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, elementsCheckSigHashAllTx1_witness, sizeof_elementsCheckSigHashAllTx1_witness) && IS_OK(execResult)) {
|
||||
if (simplicity_elements_execSimplicity(&execResult, ihrResult, tx1, 0, taproot, genesisHash, 0, (elementsCheckSigHashAllTx1_cost + 999)/1000, amr, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, elementsCheckSigHashAllTx1_witness, sizeof_elementsCheckSigHashAllTx1_witness) && IS_OK(execResult)) {
|
||||
sha256_midstate ihr;
|
||||
sha256_toMidstate(ihr.s, ihrResult);
|
||||
if (0 == memcmp(ihr.s, elementsCheckSigHashAllTx1_ihr, sizeof(uint32_t[8]))) {
|
||||
|
|
@ -421,7 +433,7 @@ static void test_elements(void) {
|
|||
if (elementsCheckSigHashAllTx1_cost){
|
||||
/* test the same transaction without adequate budget. */
|
||||
simplicity_assert(elementsCheckSigHashAllTx1_cost);
|
||||
if (simplicity_elements_execSimplicity(&execResult, ihrResult, tx1, 0, taproot, genesisHash, (elementsCheckSigHashAllTx1_cost - 1)/1000, amr, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, elementsCheckSigHashAllTx1_witness, sizeof_elementsCheckSigHashAllTx1_witness) && SIMPLICITY_ERR_EXEC_BUDGET == execResult) {
|
||||
if (simplicity_elements_execSimplicity(&execResult, ihrResult, tx1, 0, taproot, genesisHash, 0, (elementsCheckSigHashAllTx1_cost - 1)/1000, amr, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, elementsCheckSigHashAllTx1_witness, sizeof_elementsCheckSigHashAllTx1_witness) && SIMPLICITY_ERR_EXEC_BUDGET == execResult) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
|
|
@ -434,7 +446,7 @@ static void test_elements(void) {
|
|||
unsigned char brokenSig[sizeof_elementsCheckSigHashAllTx1_witness];
|
||||
memcpy(brokenSig, elementsCheckSigHashAllTx1_witness, sizeof_elementsCheckSigHashAllTx1_witness);
|
||||
brokenSig[sizeof_elementsCheckSigHashAllTx1_witness - 1] ^= 0x80;
|
||||
if (simplicity_elements_execSimplicity(&execResult, NULL, tx1, 0, taproot, genesisHash, BUDGET_MAX, NULL, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, brokenSig, sizeof_elementsCheckSigHashAllTx1_witness) && SIMPLICITY_ERR_EXEC_JET == execResult) {
|
||||
if (simplicity_elements_execSimplicity(&execResult, NULL, tx1, 0, taproot, genesisHash, 0, BUDGET_MAX, NULL, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, brokenSig, sizeof_elementsCheckSigHashAllTx1_witness) && SIMPLICITY_ERR_EXEC_JET == execResult) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
|
|
@ -449,9 +461,9 @@ static void test_elements(void) {
|
|||
}
|
||||
/* test a modified transaction with the same signature. */
|
||||
{
|
||||
rawTransaction testTx2 = (rawTransaction)
|
||||
rawElementsTransaction testTx2 = (rawElementsTransaction)
|
||||
{ .txid = (unsigned char[32]){"\xdb\x9a\x3d\xe0\xb6\xb8\xcc\x74\x1e\x4d\x6c\x8f\x19\xce\x75\xec\x0d\xfd\x01\x02\xdb\x9c\xb5\xcd\x27\xa4\x1a\x66\x91\x66\x3a\x07"}
|
||||
, .input = (rawInput[])
|
||||
, .input = (rawElementsInput[])
|
||||
{ { .prevTxid = (unsigned char[32]){"\xeb\x04\xb6\x8e\x9a\x26\xd1\x16\x04\x6c\x76\xe8\xff\x47\x33\x2f\xb7\x1d\xda\x90\xff\x4b\xef\x53\x70\xf2\x52\x26\xd3\xbc\x09\xfc"}
|
||||
, .prevIx = 0
|
||||
, .sequence = 0xffffffff /* Here is the modification. */
|
||||
|
|
@ -460,7 +472,7 @@ static void test_elements(void) {
|
|||
, .value = (unsigned char[9]){"\x01\x00\x00\x00\x02\x54\x0b\xe4\x00"}
|
||||
, .scriptPubKey = {0}
|
||||
} } }
|
||||
, .output = (rawOutput[])
|
||||
, .output = (rawElementsOutput[])
|
||||
{ { .asset = (unsigned char[33]){"\x01\x23\x0f\x4f\x5d\x4b\x7c\x6f\xa8\x45\x80\x6e\xe4\xf6\x77\x13\x45\x9e\x1b\x69\xe8\xe6\x0f\xce\xe2\xe4\x94\x0c\x7a\x0d\x5d\xe1\xb2"}
|
||||
, .value = (unsigned char[9]){"\x01\x00\x00\x00\x02\x54\x0b\xd7\x1c"}
|
||||
, .nonce = NULL
|
||||
|
|
@ -478,12 +490,12 @@ static void test_elements(void) {
|
|||
, .version = 0x00000002
|
||||
, .lockTime = 0x00000000
|
||||
};
|
||||
transaction* tx2 = simplicity_elements_mallocTransaction(&testTx2);
|
||||
elementsTransaction* tx2 = simplicity_elements_mallocTransaction(&testTx2);
|
||||
if (tx2) {
|
||||
successes++;
|
||||
simplicity_err execResult;
|
||||
{
|
||||
if (simplicity_elements_execSimplicity(&execResult, NULL, tx2, 0, taproot, genesisHash, BUDGET_MAX, NULL, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, elementsCheckSigHashAllTx1_witness, sizeof_elementsCheckSigHashAllTx1_witness) && SIMPLICITY_ERR_EXEC_JET == execResult) {
|
||||
if (simplicity_elements_execSimplicity(&execResult, NULL, tx2, 0, taproot, genesisHash, 0, BUDGET_MAX, NULL, elementsCheckSigHashAllTx1, sizeof_elementsCheckSigHashAllTx1, elementsCheckSigHashAllTx1_witness, sizeof_elementsCheckSigHashAllTx1_witness) && SIMPLICITY_ERR_EXEC_JET == execResult) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
|
|
@ -625,6 +637,83 @@ static void iden8mebi_test(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
static void exactBudget_test(void) {
|
||||
/* Core Simplicity program with a cost that is exactly 410000 milliWU */
|
||||
const unsigned char program[] = {
|
||||
0xe0, 0x09, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02,
|
||||
0x05, 0xb4, 0x6d, 0xa0, 0x80
|
||||
};
|
||||
const ubounded expectedCost = 410; /* in WU */
|
||||
|
||||
printf("Test exactBudget\n");
|
||||
|
||||
dag_node* dag;
|
||||
type* type_dag;
|
||||
combinator_counters census;
|
||||
int_fast32_t len;
|
||||
simplicity_err error, expected;
|
||||
sha256_midstate ihr;
|
||||
{
|
||||
bitstream stream = initializeBitstream(program, sizeof(program));
|
||||
len = simplicity_decodeMallocDag(&dag, simplicity_elements_decodeJet, &census, &stream);
|
||||
simplicity_assert(dag);
|
||||
simplicity_assert(0 < len);
|
||||
error = simplicity_closeBitstream(&stream);
|
||||
simplicity_assert(IS_OK(error));
|
||||
}
|
||||
error = simplicity_mallocTypeInference(&type_dag, simplicity_elements_mallocBoundVars, dag, (uint_fast32_t)len, &census);
|
||||
simplicity_assert(IS_OK(error));
|
||||
simplicity_assert(type_dag);
|
||||
simplicity_assert(!dag[len-1].sourceType);
|
||||
simplicity_assert(!dag[len-1].targetType);
|
||||
{
|
||||
bitstream stream = initializeBitstream(NULL, 0);
|
||||
error = simplicity_fillWitnessData(dag, type_dag, (uint_fast32_t)len, &stream);
|
||||
simplicity_assert(IS_OK(error));
|
||||
}
|
||||
error = simplicity_verifyNoDuplicateIdentityHashes(&ihr, dag, type_dag, (uint_fast32_t)len);
|
||||
simplicity_assert(IS_OK(error));
|
||||
{
|
||||
ubounded cellsBound, UWORDBound, frameBound, costBound;
|
||||
error = simplicity_analyseBounds(&cellsBound, &UWORDBound, &frameBound, &costBound, UBOUNDED_MAX, 0, UBOUNDED_MAX, dag, type_dag, (uint_fast32_t)len);
|
||||
simplicity_assert(IS_OK(error));
|
||||
simplicity_assert(1000*expectedCost == costBound);
|
||||
}
|
||||
error = evalTCOProgram(dag, type_dag, (uint_fast32_t)len, expectedCost, &expectedCost, NULL);
|
||||
expected = SIMPLICITY_ERR_OVERWEIGHT;
|
||||
if (expected == error) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
printf("Expected %d from evaluation, but got %d instead.\n", expected, error);
|
||||
}
|
||||
error = evalTCOProgram(dag, type_dag, (uint_fast32_t)len, expectedCost-1, &(ubounded){expectedCost-1}, NULL);
|
||||
expected = SIMPLICITY_ERR_EXEC_BUDGET;
|
||||
if (expected == error) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
printf("Expected %d from evaluation, but got %d instead.\n", expected, error);
|
||||
}
|
||||
error = evalTCOProgram(dag, type_dag, (uint_fast32_t)len, expectedCost, &(ubounded){expectedCost+1}, NULL);
|
||||
expected = SIMPLICITY_ERR_OVERWEIGHT;
|
||||
if (expected == error) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
printf("Expected %d from evaluation, but got %d instead.\n", expected, error);
|
||||
}
|
||||
error = evalTCOProgram(dag, type_dag, (uint_fast32_t)len, expectedCost-1, &expectedCost, NULL);
|
||||
expected = SIMPLICITY_NO_ERROR;
|
||||
if (expected == error) {
|
||||
successes++;
|
||||
} else {
|
||||
failures++;
|
||||
printf("Expected %d from evaluation, but got %d instead.\n", expected, error);
|
||||
}
|
||||
simplicity_free(type_dag);
|
||||
simplicity_free(dag);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
while (true) {
|
||||
|
|
@ -676,6 +765,7 @@ int main(int argc, char **argv) {
|
|||
test_program("schnorr6", schnorr6, sizeof_schnorr6, schnorr6_witness, sizeof_schnorr6_witness, SIMPLICITY_ERR_EXEC_JET, schnorr6_cmr, schnorr6_ihr, schnorr6_amr, &schnorr0_cost);
|
||||
test_program("typeSkipTest", typeSkipTest, sizeof_typeSkipTest, typeSkipTest_witness, sizeof_typeSkipTest_witness, SIMPLICITY_NO_ERROR, NULL, NULL, NULL, NULL);
|
||||
test_elements();
|
||||
exactBudget_test();
|
||||
regression_tests();
|
||||
iden8mebi_test();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include <stdbool.h>
|
||||
#include "bounded.h"
|
||||
#include "limitations.h"
|
||||
#include "primitive.h"
|
||||
#include "simplicity_alloc.h"
|
||||
#include "simplicity_assert.h"
|
||||
|
||||
|
|
@ -559,7 +558,7 @@ static simplicity_err freezeTypes(type* type_dag, dag_node* dag, unification_arr
|
|||
* or 'dag' is well-typed with '*type_dag' and without witness values
|
||||
* if the return value is not 'SIMPLICITY_NO_ERROR' then 'NULL == *type_dag'
|
||||
*/
|
||||
simplicity_err simplicity_mallocTypeInference(type** type_dag, dag_node* dag, const uint_fast32_t len, const combinator_counters* census) {
|
||||
simplicity_err simplicity_mallocTypeInference(type** type_dag, simplicity_callback_mallocBoundVars mallocBoundVars, dag_node* dag, const uint_fast32_t len, const combinator_counters* census) {
|
||||
*type_dag = NULL;
|
||||
static_assert(DAG_LEN_MAX <= SIZE_MAX / sizeof(unification_arrow), "arrow array too large.");
|
||||
static_assert(1 <= DAG_LEN_MAX, "DAG_LEN_MAX is zero.");
|
||||
|
|
@ -569,7 +568,7 @@ simplicity_err simplicity_mallocTypeInference(type** type_dag, dag_node* dag, co
|
|||
unification_arrow* arrow = simplicity_malloc(len * sizeof(unification_arrow));
|
||||
unification_var* bound_var = NULL;
|
||||
size_t word256_ix, extra_var_start;
|
||||
const size_t orig_bindings_used = simplicity_mallocBoundVars(&bound_var, &word256_ix, &extra_var_start, max_extra_vars(census));
|
||||
const size_t orig_bindings_used = mallocBoundVars(&bound_var, &word256_ix, &extra_var_start, max_extra_vars(census));
|
||||
size_t bindings_used = orig_bindings_used;
|
||||
|
||||
static_assert(1 <= NUMBER_OF_TYPENAMES_MAX, "NUMBER_OF_TYPENAMES_MAX is zero.");
|
||||
|
|
|
|||
|
|
@ -71,6 +71,26 @@ struct unification_var {
|
|||
bool isBound;
|
||||
};
|
||||
|
||||
/* Allocate a fresh set of unification variables bound to at least all the types necessary
|
||||
* for all the jets that can be created by 'simplicity_callbac_decodeJet', and also the type 'TWO^256',
|
||||
* and also allocate space for 'extra_var_len' many unification variables.
|
||||
* Return the number of non-trivial bindings created.
|
||||
*
|
||||
* However, if malloc fails, then return 0.
|
||||
*
|
||||
* Precondition: NULL != bound_var;
|
||||
* NULL != word256_ix;
|
||||
* NULL != extra_var_start;
|
||||
* extra_var_len <= 6*DAG_LEN_MAX;
|
||||
*
|
||||
* Postcondition: Either '*bound_var == NULL' and the function returns 0
|
||||
* or 'unification_var (*bound_var)[*extra_var_start + extra_var_len]' is an array of unification variables
|
||||
* such that for any 'jet : A |- B' there is some 'i < *extra_var_start' and 'j < *extra_var_start' such that
|
||||
* '(*bound_var)[i]' is bound to 'A' and '(*bound_var)[j]' is bound to 'B'
|
||||
* and, '*word256_ix < *extra_var_start' and '(*bound_var)[*word256_ix]' is bound the type 'TWO^256'
|
||||
*/
|
||||
typedef size_t (*simplicity_callback_mallocBoundVars)(unification_var** bound_var, size_t* word256_ix, size_t* extra_var_start, size_t extra_var_len);
|
||||
|
||||
/* If the Simplicity DAG, 'dag', has a principal type (including constraints due to sharing of subexpressions),
|
||||
* then allocate a well-formed type DAG containing all the types needed for all the subexpressions of 'dag',
|
||||
* with all free type variables instantiated at ONE, and set '*type_dag' to this allocation,
|
||||
|
|
@ -91,6 +111,6 @@ struct unification_var {
|
|||
* or 'dag' is well-typed with '*type_dag' and without witness values
|
||||
* if the return value is not 'SIMPLICITY_NO_ERROR' then 'NULL == *type_dag'
|
||||
*/
|
||||
simplicity_err simplicity_mallocTypeInference(type** type_dag, dag_node* dag, const uint_fast32_t len, const combinator_counters* census);
|
||||
simplicity_err simplicity_mallocTypeInference(type** type_dag, simplicity_callback_mallocBoundVars mallocBoundVars, dag_node* dag, const uint_fast32_t len, const combinator_counters* census);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <cstdio>
|
||||
#include <primitives/transaction.h>
|
||||
extern "C" {
|
||||
#include <simplicity/cmr.h>
|
||||
#include <simplicity/elements/cmr.h>
|
||||
#include <simplicity/elements/env.h>
|
||||
#include <simplicity/elements/exec.h>
|
||||
}
|
||||
|
|
@ -31,9 +31,9 @@ static std::vector<unsigned char> TAPROOT_ANNEX(99, 0x50);
|
|||
|
||||
// Defined in simplicity_compute_amr.c
|
||||
extern "C" {
|
||||
bool simplicity_computeAmr( simplicity_err* error, unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len);
|
||||
bool simplicity_elements_computeAmr( simplicity_err* error, unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len);
|
||||
}
|
||||
|
||||
void initialize_simplicity()
|
||||
|
|
@ -149,8 +149,8 @@ FUZZ_TARGET_INIT(simplicity, initialize_simplicity)
|
|||
simplicity_err error;
|
||||
unsigned char cmr[32];
|
||||
unsigned char amr[32];
|
||||
assert(simplicity_computeAmr(&error, amr, prog_data, prog_data_len, wit_data, wit_data_len));
|
||||
assert(simplicity_computeCmr(&error, cmr, prog_data, prog_data_len));
|
||||
assert(simplicity_elements_computeAmr(&error, amr, prog_data, prog_data_len, wit_data, wit_data_len));
|
||||
assert(simplicity_elements_computeCmr(&error, cmr, prog_data, prog_data_len));
|
||||
|
||||
// The remainder is just copy/pasted from the original fuzztest
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ FUZZ_TARGET_INIT(simplicity, initialize_simplicity)
|
|||
}
|
||||
|
||||
// 5. Set up Simplicity environment and tx environment
|
||||
rawTapEnv simplicityRawTap;
|
||||
rawElementsTapEnv simplicityRawTap;
|
||||
simplicityRawTap.controlBlock = TAPROOT_CONTROL.data();
|
||||
simplicityRawTap.pathLen = (TAPROOT_CONTROL.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
|
||||
simplicityRawTap.scriptCMR = cmr;
|
||||
|
|
@ -210,15 +210,15 @@ FUZZ_TARGET_INIT(simplicity, initialize_simplicity)
|
|||
unsigned char imr_out[32];
|
||||
unsigned char *imr = mtx.vin[0].prevout.hash.data()[2] & 2 ? imr_out : NULL;
|
||||
|
||||
const transaction* tx = txdata.m_simplicity_tx_data.get();
|
||||
tapEnv* taproot = simplicity_elements_mallocTapEnv(&simplicityRawTap);
|
||||
simplicity_elements_execSimplicity(&error, imr, tx, nIn, taproot, GENESIS_HASH.data(), budget, amr, prog_bytes.data(), prog_bytes.size(), wit_bytes.data(), wit_bytes.size());
|
||||
const elementsTransaction* tx = txdata.m_simplicity_tx_data.get();
|
||||
elementsTapEnv* taproot = simplicity_elements_mallocTapEnv(&simplicityRawTap);
|
||||
simplicity_elements_execSimplicity(&error, imr, tx, nIn, taproot, GENESIS_HASH.data(), 0, budget, amr, prog_bytes.data(), prog_bytes.size(), wit_bytes.data(), wit_bytes.size());
|
||||
|
||||
// 5. Secondary test -- try flipping a bunch of bits and check that this doesn't mess things up
|
||||
for (size_t j = 0; j < 8 * prog_bytes.size(); j++) {
|
||||
if (j > 32 && j % 23 != 0) continue; // skip most bits so this test doesn't overwhelm the fuzz time
|
||||
prog_bytes.data()[j / 8] ^= (1 << (j % 8));
|
||||
simplicity_elements_execSimplicity(&error, imr, tx, nIn, taproot, GENESIS_HASH.data(), budget, amr, prog_bytes.data(), prog_bytes.size(), wit_bytes.data(), wit_bytes.size());
|
||||
simplicity_elements_execSimplicity(&error, imr, tx, nIn, taproot, GENESIS_HASH.data(), 0, budget, amr, prog_bytes.data(), prog_bytes.size(), wit_bytes.data(), wit_bytes.size());
|
||||
}
|
||||
|
||||
// 6. Cleanup
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <simplicity/cmr.h>
|
||||
#include <simplicity/elements/cmr.h>
|
||||
#include <simplicity/dag.h>
|
||||
#include <simplicity/deserialize.h> // simplicity_decodeMallocDag
|
||||
#include <simplicity/limitations.h> // DAG_LEN_MAX
|
||||
|
|
@ -10,11 +10,12 @@
|
|||
#include <simplicity/typeInference.h> // simplicity_mallocTypeInference
|
||||
#include <simplicity/elements/env.h>
|
||||
#include <simplicity/elements/exec.h>
|
||||
#include <simplicity/elements/primitive.h>
|
||||
|
||||
// Copy of computeCmr used for AMR
|
||||
bool simplicity_computeAmr( simplicity_err* error, unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len) {
|
||||
bool simplicity_elements_computeAmr( simplicity_err* error, unsigned char* amr
|
||||
, const unsigned char* program, size_t program_len
|
||||
, const unsigned char* witness, size_t witness_len) {
|
||||
simplicity_assert(NULL != error);
|
||||
simplicity_assert(NULL != amr);
|
||||
simplicity_assert(NULL != program || 0 == program_len);
|
||||
|
|
@ -23,7 +24,7 @@ bool simplicity_computeAmr( simplicity_err* error, unsigned char* amr
|
|||
bitstream stream = initializeBitstream(program, program_len);
|
||||
dag_node* dag = NULL;
|
||||
combinator_counters census;
|
||||
int_fast32_t dag_len = simplicity_decodeMallocDag(&dag, &census, &stream);
|
||||
int_fast32_t dag_len = simplicity_decodeMallocDag(&dag, simplicity_elements_decodeJet, &census, &stream);
|
||||
if (dag_len <= 0) {
|
||||
simplicity_assert(dag_len < 0);
|
||||
*error = (simplicity_err)dag_len;
|
||||
|
|
@ -34,7 +35,7 @@ bool simplicity_computeAmr( simplicity_err* error, unsigned char* amr
|
|||
|
||||
type* type_dag = NULL;
|
||||
if (IS_OK(*error)) {
|
||||
*error = simplicity_mallocTypeInference(&type_dag, dag, (uint_fast32_t)dag_len, &census);
|
||||
*error = simplicity_mallocTypeInference(&type_dag, simplicity_elements_mallocBoundVars, dag, (uint_fast32_t)dag_len, &census);
|
||||
}
|
||||
bitstream witness_stream;
|
||||
if (IS_OK(*error)) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <script/sigcache.h>
|
||||
#include <validation.h>
|
||||
extern "C" {
|
||||
#include <simplicity/cmr.h>
|
||||
#include <simplicity/elements/cmr.h>
|
||||
#include <simplicity/elements/env.h>
|
||||
#include <simplicity/elements/exec.h>
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ FUZZ_TARGET_INIT(simplicity_tx, initialize_simplicity_tx)
|
|||
// valid transactions will work with this code).
|
||||
// Compute CMR and do some sanity checks on it (and the program)
|
||||
std::vector<unsigned char> cmr(32, 0);
|
||||
assert(simplicity_computeCmr(&error, cmr.data(), program.data(), program.size()));
|
||||
assert(simplicity_elements_computeCmr(&error, cmr.data(), program.data(), program.size()));
|
||||
if (error == SIMPLICITY_NO_ERROR) {
|
||||
if (memcmp(last_cmr, cmr.data(), sizeof(last_cmr)) == 0) {
|
||||
// If we have already seen this CMR this transaction, try mangling
|
||||
|
|
|
|||
|
|
@ -99,4 +99,4 @@ unsigned-integer-overflow:simplicity/secp256k1/group_impl.h
|
|||
# This one involves careful roconnor code
|
||||
shift-base:simplicity/frame.c
|
||||
# See comment in simplicity/primitive/elements/env.c line 303
|
||||
unsigned-integer-overflow:simplicity/primitive/elements/env.c
|
||||
unsigned-integer-overflow:simplicity/elements/env.c
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue