-
Notifications
You must be signed in to change notification settings - Fork 49
Bitcoin Application for Simplicity #324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
roconnor-blockstream
wants to merge
9
commits into
master
Choose a base branch
from
bitcoin
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
82eafa9
Implementation of exec.c for bitcoin
roconnor-blockstream 184d279
Implementation of cmr.c for bitcoin
roconnor-blockstream 65ca616
Update GenRustJets to generate Bitcoin Jets
roconnor-blockstream 13c6fdf
Add basic CMake build support for libBitcoinSimplicity
roconnor-blockstream 86970f8
cmake: add cmr and bitcoin/cmr to build
delta1 afe87d1
misc: minor changes from #324 review
delta1 5458e28
nix: add cmake build
delta1 27a5815
ci: add nix cmake build
delta1 af063a8
Merge BlockstreamResearch/Simplicity#342: bitcoin: minor fixes and ad…
apoelstra File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| cmake_minimum_required(VERSION 3.16) | ||
|
|
||
| project(BitcoinSimplicity) | ||
|
|
||
| set(CMAKE_C_STANDARD 11) | ||
| set(CMAKE_C_EXTENSIONS OFF) | ||
|
|
||
| add_library(BitcoinSimplicity STATIC | ||
| bitstream.c | ||
| cmr.c | ||
| dag.c | ||
| deserialize.c | ||
| eval.c | ||
| frame.c | ||
| jets-secp256k1.c | ||
| jets.c | ||
| rsort.c | ||
| sha256.c | ||
| type.c | ||
| typeInference.c | ||
| bitcoin/env.c | ||
| bitcoin/exec.c | ||
| bitcoin/bitcoinJets.c | ||
| bitcoin/cmr.c | ||
| bitcoin/ops.c | ||
| bitcoin/primitive.c | ||
| bitcoin/txEnv.c | ||
| ) | ||
|
|
||
| option(PRODUCTION "Enable production build" ON) | ||
| if (PRODUCTION) | ||
| target_compile_definitions(BitcoinSimplicity PRIVATE "PRODUCTION") | ||
| endif() | ||
|
|
||
| target_include_directories(BitcoinSimplicity PUBLIC | ||
| $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> | ||
| $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #include <simplicity/bitcoin/cmr.h> | ||
|
|
||
| #include "../cmr.h" | ||
| #include "primitive.h" | ||
|
|
||
| /* Deserialize a Simplicity 'program' and compute its CMR. | ||
| * | ||
| * Caution: no typechecking is performed, only a well-formedness check. | ||
| * | ||
| * If at any time malloc fails then '*error' is set to 'SIMPLICITY_ERR_MALLOC' and 'false' is returned, | ||
| * Otherwise, 'true' is returned indicating that the result was successfully computed and returned in the '*error' value. | ||
| * | ||
| * If the operation completes successfully then '*error' is set to 'SIMPLICITY_NO_ERROR', and the 'cmr' array is filled in with the program's computed CMR. | ||
| * | ||
| * Precondition: NULL != error; | ||
| * unsigned char cmr[32] | ||
| * unsigned char program[program_len] | ||
| */ | ||
| bool simplicity_bitcoin_computeCmr( simplicity_err* error, unsigned char* cmr | ||
| , const unsigned char* program, size_t program_len) { | ||
| return simplicity_computeCmr(error, cmr, simplicity_bitcoin_decodeJet, program, program_len); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| #include <simplicity/bitcoin/exec.h> | ||
|
|
||
| #include <stdalign.h> | ||
| #include <string.h> | ||
| #include "primitive.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`. | ||
| * | ||
| * If at any time malloc fails then '*error' is set to 'SIMPLICITY_ERR_MALLOC' and 'false' is returned, | ||
| * meaning we were unable to determine the result of the simplicity program. | ||
| * 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'. | ||
| * | ||
| * Otherwise '*error' is set to 'SIMPLICITY_NO_ERROR'. | ||
| * | ||
| * If 'ihr != NULL' and '*error' is set to 'SIMPLICITY_NO_ERROR', then the identity hash of the root of the decoded expression is written to 'ihr'. | ||
| * Otherwise if 'ihr != NULL' and '*error' is not set to 'SIMPLICITY_NO_ERROR', then 'ihr' may or may not be written to. | ||
| * | ||
| * Precondition: NULL != error; | ||
| * NULL != ihr implies unsigned char ihr[32] | ||
| * NULL != tx; | ||
| * NULL != taproot; | ||
| * 0 <= minCost <= budget; | ||
| * NULL != amr implies unsigned char amr[32] | ||
| * unsigned char program[program_len] | ||
| * unsigned char witness[witness_len] | ||
| */ | ||
| extern bool simplicity_bitcoin_execSimplicity( simplicity_err* error, unsigned char* ihr | ||
| , const bitcoinTransaction* tx, uint_fast32_t ix, const bitcoinTapEnv* taproot | ||
| , 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) { | ||
| simplicity_assert(NULL != error); | ||
| simplicity_assert(NULL != tx); | ||
| simplicity_assert(NULL != taproot); | ||
| simplicity_assert(0 <= minCost); | ||
| simplicity_assert(minCost <= budget); | ||
| simplicity_assert(NULL != program || 0 == program_len); | ||
| simplicity_assert(NULL != witness || 0 == witness_len); | ||
|
|
||
| combinator_counters census; | ||
| dag_node* dag = NULL; | ||
| int_fast32_t dag_len; | ||
| sha256_midstate amr_hash; | ||
|
|
||
| if (amr) sha256_toMidstate(amr_hash.s, amr); | ||
|
|
||
| { | ||
| bitstream stream = initializeBitstream(program, program_len); | ||
| dag_len = simplicity_decodeMallocDag(&dag, simplicity_bitcoin_decodeJet, &census, &stream); | ||
| if (dag_len <= 0) { | ||
| simplicity_assert(dag_len < 0); | ||
| *error = (simplicity_err)dag_len; | ||
| return IS_PERMANENT(*error); | ||
| } | ||
| simplicity_assert(NULL != dag); | ||
| simplicity_assert((uint_fast32_t)dag_len <= DAG_LEN_MAX); | ||
| *error = simplicity_closeBitstream(&stream); | ||
| } | ||
|
|
||
| if (IS_OK(*error)) { | ||
| if (0 != memcmp(taproot->scriptCMR.s, dag[dag_len-1].cmr.s, sizeof(uint32_t[8]))) { | ||
| *error = SIMPLICITY_ERR_CMR; | ||
| } | ||
| } | ||
|
|
||
| if (IS_OK(*error)) { | ||
| type* type_dag = NULL; | ||
| *error = simplicity_mallocTypeInference(&type_dag, simplicity_bitcoin_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) { | ||
| *error = SIMPLICITY_ERR_TYPE_INFERENCE_NOT_PROGRAM; | ||
| } | ||
| } | ||
| if (IS_OK(*error)) { | ||
| bitstream witness_stream = initializeBitstream(witness, witness_len); | ||
| *error = simplicity_fillWitnessData(dag, type_dag, (uint_fast32_t)dag_len, &witness_stream); | ||
| if (IS_OK(*error)) { | ||
| *error = simplicity_closeBitstream(&witness_stream); | ||
| if (SIMPLICITY_ERR_BITSTREAM_TRAILING_BYTES == *error) *error = SIMPLICITY_ERR_WITNESS_TRAILING_BYTES; | ||
| if (SIMPLICITY_ERR_BITSTREAM_ILLEGAL_PADDING == *error) *error = SIMPLICITY_ERR_WITNESS_ILLEGAL_PADDING; | ||
| } | ||
| } | ||
| if (IS_OK(*error)) { | ||
| sha256_midstate ihr_buf; | ||
| *error = simplicity_verifyNoDuplicateIdentityHashes(&ihr_buf, dag, type_dag, (uint_fast32_t)dag_len); | ||
| if (IS_OK(*error) && ihr) sha256_fromMidstate(ihr, ihr_buf.s); | ||
| } | ||
| if (IS_OK(*error) && amr) { | ||
| static_assert(DAG_LEN_MAX <= SIZE_MAX / sizeof(analyses), "analysis array too large."); | ||
| static_assert(1 <= DAG_LEN_MAX, "DAG_LEN_MAX is zero."); | ||
| static_assert(DAG_LEN_MAX - 1 <= UINT32_MAX, "analysis array index does not fit in uint32_t."); | ||
| analyses *analysis = simplicity_malloc((size_t)dag_len * sizeof(analyses)); | ||
| if (analysis) { | ||
| simplicity_computeAnnotatedMerkleRoot(analysis, dag, type_dag, (uint_fast32_t)dag_len); | ||
| if (0 != memcmp(amr_hash.s, analysis[dag_len-1].annotatedMerkleRoot.s, sizeof(uint32_t[8]))) { | ||
| *error = SIMPLICITY_ERR_AMR; | ||
| } | ||
| } else { | ||
| /* malloc failed which counts as a transient error. */ | ||
| *error = SIMPLICITY_ERR_MALLOC; | ||
| } | ||
| simplicity_free(analysis); | ||
| } | ||
| if (IS_OK(*error)) { | ||
| txEnv env = simplicity_bitcoin_build_txEnv(tx, taproot, ix); | ||
| static_assert(BUDGET_MAX <= UBOUNDED_MAX, "BUDGET_MAX doesn't fit in ubounded."); | ||
| *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); | ||
| } | ||
|
|
||
| simplicity_free(dag); | ||
| return IS_PERMANENT(*error); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| #include "cmr.h" | ||
|
|
||
| #include "limitations.h" | ||
| #include "simplicity_alloc.h" | ||
| #include "simplicity_assert.h" | ||
|
|
||
| /* Deserialize a Simplicity 'program' and compute its CMR. | ||
| * | ||
| * Caution: no typechecking is performed, only a well-formedness check. | ||
| * | ||
| * If at any time malloc fails then '*error' is set to 'SIMPLICITY_ERR_MALLOC' and 'false' is returned, | ||
| * Otherwise, 'true' is returned indicating that the result was successfully computed and returned in the '*error' value. | ||
| * | ||
| * If the operation completes successfully then '*error' is set to 'SIMPLICITY_NO_ERROR', and the 'cmr' array is filled in with the program's computed CMR. | ||
| * | ||
| * Precondition: NULL != error; | ||
| * unsigned char cmr[32] | ||
| * unsigned char program[program_len] | ||
| */ | ||
| bool simplicity_computeCmr( simplicity_err* error, unsigned char* cmr, simplicity_callback_decodeJet decodeJet | ||
| , 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, decodeJet, NULL, &stream); | ||
| if (dag_len <= 0) { | ||
| simplicity_assert(dag_len < 0); | ||
| *error = (simplicity_err)dag_len; | ||
| } else { | ||
| simplicity_assert(NULL != dag); | ||
| simplicity_assert((uint_fast32_t)dag_len <= DAG_LEN_MAX); | ||
| *error = simplicity_closeBitstream(&stream); | ||
| sha256_fromMidstate(cmr, dag[dag_len-1].cmr.s); | ||
| } | ||
|
|
||
| simplicity_free(dag); | ||
| return IS_PERMANENT(*error); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #ifndef SIMPLICITY_CMR_H | ||
| #define SIMPLICITY_CMR_H | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #include <simplicity/errorCodes.h> | ||
| #include "deserialize.h" | ||
|
|
||
| /* Deserialize a Simplicity 'program' and compute its CMR. | ||
| * | ||
| * Caution: no typechecking is performed, only a well-formedness check. | ||
| * | ||
| * If at any time malloc fails then '*error' is set to 'SIMPLICITY_ERR_MALLOC' and 'false' is returned, | ||
| * Otherwise, 'true' is returned indicating that the result was successfully computed and returned in the '*error' value. | ||
| * | ||
| * If the operation completes successfully then '*error' is set to 'SIMPLICITY_NO_ERROR', and the 'cmr' array is filled in with the program's computed CMR. | ||
| * | ||
| * Precondition: NULL != error; | ||
| * unsigned char cmr[32] | ||
| * unsigned char program[program_len] | ||
| */ | ||
| extern bool simplicity_computeCmr( simplicity_err* error, unsigned char* cmr, simplicity_callback_decodeJet decodeJet | ||
| , const unsigned char* program, size_t program_len); | ||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #ifndef SIMPLICITY_BITCOIN_CMR_H | ||
| #define SIMPLICITY_BITCOIN_CMR_H | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #include <simplicity/errorCodes.h> | ||
|
|
||
| /* Deserialize a Simplicity 'program' and compute its CMR. | ||
| * | ||
| * Caution: no typechecking is performed, only a well-formedness check. | ||
| * | ||
| * If at any time malloc fails then '*error' is set to 'SIMPLICITY_ERR_MALLOC' and 'false' is returned, | ||
| * Otherwise, 'true' is returned indicating that the result was successfully computed and returned in the '*error' value. | ||
| * | ||
| * If the operation completes successfully then '*error' is set to 'SIMPLICITY_NO_ERROR', and the 'cmr' array is filled in with the program's computed CMR. | ||
| * | ||
| * Precondition: NULL != error; | ||
| * unsigned char cmr[32] | ||
| * unsigned char program[program_len] | ||
| */ | ||
| extern bool simplicity_bitcoin_computeCmr( simplicity_err* error, unsigned char* cmr | ||
| , const unsigned char* program, size_t program_len); | ||
| #endif |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in 13c6fdf: I think
cmr.candbitcoin/cmr.care missing here?