Merge ElementsProject/elements#1519: simplicity: update to d1905055

87c0b44f78 Squashed 'src/simplicity/' changes from 6d503ea4f8..49b96499a6 (Byron Hambly)
73d1e521bf docs: add simplicity code update instructions (Byron Hambly)

Pull request description:

  Updates Simplicity C source subtree from current master BlockstreamResearch/Simplicity@d190505509

  Adds new document describing the process.

  Pushed the C-master branch subtree split to my repo [delta1/simplicity/tree/C-master](https://github.com/delta1/simplicity/tree/C-master) and upstreamed in BlockstreamResearch/Simplicity#330

ACKs for top commit:
  delta1:
    ACK 4539002bee; compiled and tested locally

Tree-SHA512: e9fab8baa728ac122597bf2e3c5ae4fe1c5956c655fc336e1cc7a2be591f1deebcab32004a8b6b4ad359c51154ad47bca5f40c21d06823d5d059a6d66efb15af
This commit is contained in:
merge-script 2026-01-13 09:04:55 +02:00
commit 9a74bc9e2d
No known key found for this signature in database
GPG key ID: DE8F6EA20A661697
25 changed files with 5725 additions and 91 deletions

View file

@ -0,0 +1,39 @@
# Updating Simplicity C code in Elements
This document describes how to update the Simplicity C code subtree in the Elements repository.
Reference: https://github.com/BlockstreamResearch/simplicity/issues/329#issuecomment-3715844042
## Simplicity
- Clone or pull the latest `master` branch of the [Simplicity](https://github.com/BlockstreamResearch/simplicity) repository.
- Split out a new subtree of the Simplicity `C` source to the `C-master` branch.
```
git subtree split -P C -b C-master
```
- Push the `C-master` branch to a public remote.
```
git push <remote> C-master
```
## Elements
- Add a reference to the above simplicity remote in your Elements repo.
```
git remote add <new-remote-name> git@github.com:<user>/simplicity.git
```
- Pull and squash the `C-master` branch subtree into the `src/simplicity` directory in Elements.
```
git subtree pull --prefix src/simplicity <new-remote-name> C-master --squash
```
- Run build and tests.
- Create a new PR to Elements.

View file

@ -1,4 +1,6 @@
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
CORE_OBJS := bitstream.o dag.o deserialize.o eval.o frame.o jets.o jets-secp256k1.o rsort.o sha256.o type.o typeInference.o
BITCOIN_OBJS := bitcoin/env.o bitcoin/ops.o bitcoin/bitcoinJets.o bitcoin/primitive.o bitcoin/txEnv.o
ELEMENTS_OBJS := 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
@ -18,18 +20,21 @@ elements/elementsJets.o: elements/elementsJets.c
$(CC) -c $(CFLAGS) $(CWARN) -Wno-switch-enum -Wswitch $(CPPFLAGS) -o $@ $<
sha256.o: sha256.c
$(CC) -c $(CFLAGS) -msha -msse4 $(CWARN) -Wno-cast-align -Wno-sign-conversion $(CPPFLAGS) -o $@ $<
$(CC) -c $(CFLAGS) $(X86_SHANI_CXXFLAGS) $(CWARN) -Wno-cast-align -Wno-sign-conversion $(CPPFLAGS) -o $@ $<
%.o: %.c
$(CC) -c $(CFLAGS) $(CWARN) $(CPPFLAGS) -o $@ $<
libElementsSimplicity.a: $(OBJS)
libBitcoinSimplicity.a: $(CORE_OBJS) $(BITCOIN_OBJS)
ar rcs $@ $^
libElementsSimplicity.a: $(CORE_OBJS) $(ELEMENTS_OBJS)
ar rcs $@ $^
test: $(TEST_OBJS) libElementsSimplicity.a
$(CC) $^ -o $@ $(LDFLAGS)
install: libElementsSimplicity.a
install: libBitcoinSimplicity.a libElementsSimplicity.a
mkdir -p $(out)/lib
cp $^ $(out)/lib/
cp -R include $(out)/include

View file

@ -0,0 +1,610 @@
#include "bitcoinJets.h"
#include "ops.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.
*
* Precondition: '*src' is a valid read frame for 256 more cells;
* NULL != h;
*/
static void readHash(sha256_midstate* h, frameItem *src) {
read32s(h->s, 8, src);
}
/* Write a 256-bit hash value to the 'dst' frame, advancing the cursor 256 cells.
*
* Precondition: '*dst' is a valid write frame for 256 more cells;
* NULL != h;
*/
static void writeHash(frameItem* dst, const sha256_midstate* h) {
write32s(dst, h->s, 8);
}
/* Write an outpoint value to the 'dst' frame, advancing the cursor 288 cells.
*
* Precondition: '*dst' is a valid write frame for 288 more cells;
* NULL != op;
*/
static void prevOutpoint(frameItem* dst, const outpoint* op) {
writeHash(dst, &op->txid);
simplicity_write32(dst, op->ix);
}
static uint_fast32_t lockHeight(const bitcoinTransaction* tx) {
return !tx->isFinal && tx->lockTime < 500000000U ? tx->lockTime : 0;
}
static uint_fast32_t lockTime(const bitcoinTransaction* tx) {
return !tx->isFinal && 500000000U <= tx->lockTime ? tx->lockTime : 0;
}
static uint_fast16_t lockDistance(const bitcoinTransaction* tx, uint_fast32_t ix) {
simplicity_assert(ix < tx->numInputs);
if (2 <= tx->version &&
tx->input[ix].sequence < 0x80000000 &&
!(tx->input[ix].sequence & ((uint_fast32_t)1 << 22))) {
return tx->input[ix].sequence & 0xffff;
} else {
return 0;
}
}
static uint_fast16_t lockDuration(const bitcoinTransaction* tx, uint_fast32_t ix) {
simplicity_assert(ix < tx->numInputs);
if (2 <= tx->version &&
tx->input[ix].sequence < 0x80000000 &&
!!(tx->input[ix].sequence & ((uint_fast32_t)1 << 22))) {
return tx->input[ix].sequence & 0xffff;
} else {
return 0;
}
}
/* version : ONE |- TWO^32 */
bool simplicity_bitcoin_version(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write32(dst, env->tx->version);
return true;
}
/* lock_time : ONE |- TWO^32 */
bool simplicity_bitcoin_lock_time(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write32(dst, env->tx->lockTime);
return true;
}
/* input_prev_outpoint : TWO^32 |- S (TWO^256 * TWO^32) */
bool simplicity_bitcoin_input_prev_outpoint(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
prevOutpoint(dst, &env->tx->input[i].prevOutpoint);
} else {
skipBits(dst, 288);
}
return true;
}
/* input_value : TWO^32 |- S TWO^64 */
bool simplicity_bitcoin_input_value(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
simplicity_write64(dst, env->tx->input[i].txo.value);
} else {
skipBits(dst, 64);
}
return true;
}
/* input_script_hash : TWO^32 |- S TWO^256 */
bool simplicity_bitcoin_input_script_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
writeHash(dst, &env->tx->input[i].txo.scriptPubKey);
} else {
skipBits(dst, 256);
}
return true;
}
/* input_sequence : TWO^32 |- S TWO^32 */
bool simplicity_bitcoin_input_sequence(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
simplicity_write32(dst, env->tx->input[i].sequence);
} else {
skipBits(dst, 32);
}
return true;
}
/* input_annex_hash : TWO^32 |- S (S (TWO^256)) */
bool simplicity_bitcoin_input_annex_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
if (writeBit(dst, env->tx->input[i].hasAnnex)) {
writeHash(dst, &env->tx->input[i].annexHash);
} else {
skipBits(dst, 256);
}
} else {
skipBits(dst, 257);
}
return true;
}
/* input_script_sig_hash : TWO^32 |- (S (TWO^256) */
bool simplicity_bitcoin_input_script_sig_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
writeHash(dst, &env->tx->input[i].scriptSigHash);
} else {
skipBits(dst, 256);
}
return true;
}
/* output_value : TWO^32 |- S (TWO^64) */
bool simplicity_bitcoin_output_value(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numOutputs)) {
simplicity_write64(dst, env->tx->output[i].value);
} else {
skipBits(dst, 64);
}
return true;
}
/* output_script_hash : TWO^32 |- S TWO^256 */
bool simplicity_bitcoin_output_script_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numOutputs)) {
writeHash(dst, &env->tx->output[i].scriptPubKey);
} else {
skipBits(dst, 256);
}
return true;
}
/* fee : ONE |- TWO^64 */
bool simplicity_bitcoin_fee(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write64(dst, env->tx->totalInputValue - env->tx->totalOutputValue);
return true;
}
/* total_input_value : ONE |- TWO^64 */
bool simplicity_bitcoin_total_input_value(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write64(dst, env->tx->totalInputValue);
return true;
}
/* total_output_value : ONE |- TWO^64 */
bool simplicity_bitcoin_total_output_value(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write64(dst, env->tx->totalOutputValue);
return true;
}
/* script_cmr : ONE |- TWO^256 */
bool simplicity_bitcoin_script_cmr(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
write32s(dst, env->taproot->scriptCMR.s, 8);
return true;
}
/* transaction_id : ONE |- TWO^256 */
bool simplicity_bitcoin_transaction_id(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
write32s(dst, env->tx->txid.s, 8);
return true;
}
/* current_index : ONE |- TWO^32 */
bool simplicity_bitcoin_current_index(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write32(dst, env->ix);
return true;
}
/* current_prev_outpoint : ONE |- TWO^256 * TWO^32 */
bool simplicity_bitcoin_current_prev_outpoint(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
prevOutpoint(dst, &env->tx->input[env->ix].prevOutpoint);
return true;
}
/* current_value : ONE |- (TWO^64) */
bool simplicity_bitcoin_current_value(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
simplicity_write64(dst, env->tx->input[env->ix].txo.value);
return true;
}
/* current_script_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_current_script_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
writeHash(dst, &env->tx->input[env->ix].txo.scriptPubKey);
return true;
}
/* current_sequence : ONE |- TWO^32 */
bool simplicity_bitcoin_current_sequence(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
simplicity_write32(dst, env->tx->input[env->ix].sequence);
return true;
}
/* current_script_sig_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_current_script_sig_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
writeHash(dst, &env->tx->input[env->ix].scriptSigHash);
return true;
}
/* current_annex_hash : ONE |- S (TWO^256) */
bool simplicity_bitcoin_current_annex_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
if (writeBit(dst, env->tx->input[env->ix].hasAnnex)) {
writeHash(dst, &env->tx->input[env->ix].annexHash);
} else {
skipBits(dst, 256);
}
return true;
}
/* tapleaf_version : ONE |- TWO^8 */
bool simplicity_bitcoin_tapleaf_version(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write8(dst, env->taproot->leafVersion);
return true;
}
/* tappath : TWO^8 |- S (TWO^256) */
bool simplicity_bitcoin_tappath(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast8_t i = simplicity_read8(&src);
if (writeBit(dst, i < env->taproot->pathLen)) {
writeHash(dst, &env->taproot->path[i]);
} else {
skipBits(dst, 256);
}
return true;
}
/* internal_key : ONE |- TWO^256 */
bool simplicity_bitcoin_internal_key(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->taproot->internalKey);
return true;
}
/* num_inputs : ONE |- TWO^32 */
bool simplicity_bitcoin_num_inputs(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write32(dst, env->tx->numInputs);
return true;
}
/* num_outputs : ONE |- TWO^32 */
bool simplicity_bitcoin_num_outputs(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write32(dst, env->tx->numOutputs);
return true;
}
/* tx_is_final : ONE |- TWO */
bool simplicity_bitcoin_tx_is_final(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeBit(dst, env->tx->isFinal);
return true;
}
/* tx_lock_height : ONE |- TWO^32 */
bool simplicity_bitcoin_tx_lock_height(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write32(dst, lockHeight(env->tx));
return true;
}
/* tx_lock_time : ONE |- TWO^32 */
bool simplicity_bitcoin_tx_lock_time(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write32(dst, lockTime(env->tx));
return true;
}
/* tx_lock_distance : ONE |- TWO^16 */
bool simplicity_bitcoin_tx_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
simplicity_write16(dst, lockDistance(env->tx, env->ix));
return true;
}
/* tx_lock_duration : ONE |- TWO^16 */
bool simplicity_bitcoin_tx_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
if (env->tx->numInputs <= env->ix) return false;
simplicity_write16(dst, lockDuration(env->tx, env->ix));
return true;
}
/* check_lock_height : TWO^32 |- ONE */
bool simplicity_bitcoin_check_lock_height(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; // dst is unused;
uint_fast32_t x = simplicity_read32(&src);
return x <= lockHeight(env->tx);
}
/* check_lock_time : TWO^32 |- ONE */
bool simplicity_bitcoin_check_lock_time(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; // dst is unused;
uint_fast32_t x = simplicity_read32(&src);
return x <= lockTime(env->tx);
}
/* check_lock_distance : TWO^16 |- ONE */
bool simplicity_bitcoin_check_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; // dst is unused;
if (env->tx->numInputs <= env->ix) return false;
uint_fast16_t x = simplicity_read16(&src);
return x <= lockDistance(env->tx, env->ix);
}
/* check_lock_duration : TWO^16 |- ONE */
bool simplicity_bitcoin_check_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; // dst is unused;
if (env->tx->numInputs <= env->ix) return false;
uint_fast16_t x = simplicity_read16(&src);
return x <= lockDuration(env->tx, env->ix);
}
/* build_tapleaf_simplicity : TWO^256 |- TWO^256 */
bool simplicity_bitcoin_build_tapleaf_simplicity(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; // env is unused.
sha256_midstate cmr;
readHash(&cmr, &src);
sha256_midstate result = simplicity_bitcoin_make_tapleaf(0xbe, &cmr);
writeHash(dst, &result);
return true;
}
/* build_tapbranch : TWO^256 * TWO^256 |- TWO^256 */
bool simplicity_bitcoin_build_tapbranch(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; // env is unused.
sha256_midstate a, b;
readHash(&a, &src);
readHash(&b, &src);
sha256_midstate result = simplicity_bitcoin_make_tapbranch(&a, &b);
writeHash(dst, &result);
return true;
}
/* build_taptweak : PUBKEY * TWO^256 |- PUBKEY */
bool simplicity_bitcoin_build_taptweak(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; // env is unused.
static unsigned char taptweak[] = "TapTweak";
return simplicity_generic_taptweak(dst, &src, taptweak, sizeof(taptweak)-1);
}
/* outpoint_hash : CTX8 * TWO^256 * TWO^32 |- CTX8 */
bool simplicity_bitcoin_outpoint_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; // env is unused.
sha256_midstate midstate;
unsigned char buf[36];
sha256_context ctx = {.output = midstate.s};
/* Read a SHA-256 context. */
if (!simplicity_read_sha256_context(&ctx, &src)) return false;
/* Read an outpoint (hash and index). */
read8s(buf, 36, &src);
sha256_uchars(&ctx, buf, 36);
return simplicity_write_sha256_context(dst, &ctx);
}
/* annex_hash : CTX8 * S TWO^256 |- CTX8 */
bool simplicity_bitcoin_annex_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; // env is unused.
sha256_midstate midstate;
unsigned char buf[32];
sha256_context ctx = {.output = midstate.s};
/* Read a SHA-256 context. */
if (!simplicity_read_sha256_context(&ctx, &src)) return false;
/* Read an optional hash. (257 bits) */
if (readBit(&src)) {
/* Read a hash. (256 bits) */
read8s(buf, 32, &src);
sha256_uchar(&ctx, 0x01);
sha256_uchars(&ctx, buf, 32);
} else {
/* No hash. */
sha256_uchar(&ctx, 0x00);
}
return simplicity_write_sha256_context(dst, &ctx);
}
/* output_amounts_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_output_values_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->outputValuesHash);
return true;
}
/* output_scripts_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_output_scripts_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->outputScriptsHash);
return true;
}
/* outputs_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_outputs_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->outputsHash);
return true;
}
/* output_hash : TWO^32 |- S TWO^256 */
bool simplicity_bitcoin_output_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numOutputs)) {
const sigOutput* output = &env->tx->output[i];
sha256_midstate midstate;
sha256_context ctx = sha256_init(midstate.s);
sha256_u64be(&ctx, output->value);
sha256_hash(&ctx, &output->scriptPubKey);
sha256_finalize(&ctx);
writeHash(dst, &midstate);
} else {
skipBits(dst, 256);
}
return true;
}
/* input_outpoints_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_input_outpoints_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputOutpointsHash);
return true;
}
/* input_values_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_input_values_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputValuesHash);
return true;
}
/* input_scripts_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_input_scripts_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputScriptsHash);
return true;
}
/* input_utxos_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_input_utxos_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputUTXOsHash);
return true;
}
/* input_utxo_hash : TWO^32 |- S TWO^256 */
bool simplicity_bitcoin_input_utxo_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
const sigOutput* txo = &env->tx->input[i].txo;
sha256_midstate midstate;
sha256_context ctx = sha256_init(midstate.s);
sha256_u64be(&ctx, txo->value);
sha256_hash(&ctx, &txo->scriptPubKey);
sha256_finalize(&ctx);
writeHash(dst, &midstate);
} else {
skipBits(dst, 256);
}
return true;
}
/* input_sequences_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_input_sequences_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputSequencesHash);
return true;
}
/* input_annexes_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_input_annexes_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputAnnexesHash);
return true;
}
/* input_script_sigs_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_input_script_sigs_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputScriptSigsHash);
return true;
}
/* inputs_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_inputs_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->inputsHash);
return true;
}
/* input_hash : TWO^32 |- S TWO^256 */
bool simplicity_bitcoin_input_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = simplicity_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
const sigInput* input = &env->tx->input[i];
sha256_midstate midstate;
sha256_context ctx = sha256_init(midstate.s);
sha256_hash(&ctx, &input->prevOutpoint.txid);
sha256_u32be(&ctx, input->prevOutpoint.ix);
sha256_u32be(&ctx, input->sequence);
if (input->hasAnnex) {
sha256_uchar(&ctx, 1);
sha256_hash(&ctx, &input->annexHash);
} else {
sha256_uchar(&ctx, 0);
}
sha256_finalize(&ctx);
writeHash(dst, &midstate);
} else {
skipBits(dst, 256);
}
return true;
}
/* tx_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_tx_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->tx->txHash);
return true;
}
/* tapleaf_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_tapleaf_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->taproot->tapLeafHash);
return true;
}
/* tappath_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_tappath_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->taproot->tappathHash);
return true;
}
/* tap_env_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_tap_env_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->taproot->tapEnvHash);
return true;
}
/* sig_all_hash : ONE |- TWO^256 */
bool simplicity_bitcoin_sig_all_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
writeHash(dst, &env->sigAllHash);
return true;
}

View file

@ -0,0 +1,70 @@
/* This module defines primitives and jets that are specific to the Bitcoin application for Simplicity.
*/
#ifndef SIMPLICITY_BITCOIN_BITCOINJETS_H
#define SIMPLICITY_BITCOIN_BITCOINJETS_H
#include "../jets.h"
/* Jets for the Bitcoin application of Simplicity. */
bool simplicity_bitcoin_version(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_lock_time(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_prev_outpoint(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_value(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_script_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_sequence(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_annex_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_script_sig_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_output_value(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_output_script_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_fee(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_total_input_value(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_total_output_value(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_script_cmr(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_transaction_id(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_current_index(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_current_prev_outpoint(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_current_value(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_current_script_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_current_sequence(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_current_annex_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_current_script_sig_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tapleaf_version(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tappath(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_internal_key(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_num_inputs(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_num_outputs(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tx_is_final(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tx_lock_height(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tx_lock_time(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tx_lock_distance(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tx_lock_duration(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_check_lock_height(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_check_lock_time(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_check_lock_distance(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_check_lock_duration(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_build_tapleaf_simplicity(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_build_tapbranch(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_build_taptweak(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_outpoint_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_annex_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_output_values_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_output_scripts_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_outputs_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_output_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_outpoints_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_values_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_scripts_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_utxos_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_utxo_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_sequences_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_annexes_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_script_sigs_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_inputs_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_input_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tx_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tapleaf_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tappath_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_tap_env_hash(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_bitcoin_sig_all_hash(frameItem* dst, frameItem src, const txEnv* env);
#endif

View file

@ -0,0 +1,87 @@
/* This file has been automatically generated. */
{
int32_t code;
code = simplicity_decodeUptoMaxInt(stream);
if (code < 0) return (simplicity_err)code;
switch (code) {
case 1:
code = simplicity_decodeUptoMaxInt(stream);
if (code < 0) return (simplicity_err)code;
switch (code) {
case 1: *result = SIG_ALL_HASH; return SIMPLICITY_NO_ERROR;
case 2: *result = TX_HASH; return SIMPLICITY_NO_ERROR;
case 3: *result = TAP_ENV_HASH; return SIMPLICITY_NO_ERROR;
case 4: *result = OUTPUTS_HASH; return SIMPLICITY_NO_ERROR;
case 5: *result = INPUTS_HASH; return SIMPLICITY_NO_ERROR;
case 6: *result = INPUT_UTXOS_HASH; return SIMPLICITY_NO_ERROR;
case 7: *result = OUTPUT_HASH; return SIMPLICITY_NO_ERROR;
case 8: *result = OUTPUT_VALUES_HASH; return SIMPLICITY_NO_ERROR;
case 9: *result = OUTPUT_SCRIPTS_HASH; return SIMPLICITY_NO_ERROR;
case 10: *result = INPUT_HASH; return SIMPLICITY_NO_ERROR;
case 11: *result = INPUT_OUTPOINTS_HASH; return SIMPLICITY_NO_ERROR;
case 12: *result = INPUT_SEQUENCES_HASH; return SIMPLICITY_NO_ERROR;
case 13: *result = INPUT_ANNEXES_HASH; return SIMPLICITY_NO_ERROR;
case 14: *result = INPUT_SCRIPT_SIGS_HASH; return SIMPLICITY_NO_ERROR;
case 15: *result = INPUT_UTXO_HASH; return SIMPLICITY_NO_ERROR;
case 16: *result = INPUT_VALUES_HASH; return SIMPLICITY_NO_ERROR;
case 17: *result = INPUT_SCRIPTS_HASH; return SIMPLICITY_NO_ERROR;
case 18: *result = TAPLEAF_HASH; return SIMPLICITY_NO_ERROR;
case 19: *result = TAPPATH_HASH; return SIMPLICITY_NO_ERROR;
case 20: *result = OUTPOINT_HASH; return SIMPLICITY_NO_ERROR;
case 21: *result = ANNEX_HASH; return SIMPLICITY_NO_ERROR;
case 22: *result = BUILD_TAPLEAF_SIMPLICITY; return SIMPLICITY_NO_ERROR;
case 23: *result = BUILD_TAPBRANCH; return SIMPLICITY_NO_ERROR;
case 24: *result = BUILD_TAPTWEAK; return SIMPLICITY_NO_ERROR;
}
break;
case 2:
code = simplicity_decodeUptoMaxInt(stream);
if (code < 0) return (simplicity_err)code;
switch (code) {
case 1: *result = CHECK_LOCK_HEIGHT; return SIMPLICITY_NO_ERROR;
case 2: *result = CHECK_LOCK_TIME; return SIMPLICITY_NO_ERROR;
case 3: *result = CHECK_LOCK_DISTANCE; return SIMPLICITY_NO_ERROR;
case 4: *result = CHECK_LOCK_DURATION; return SIMPLICITY_NO_ERROR;
case 5: *result = TX_LOCK_HEIGHT; return SIMPLICITY_NO_ERROR;
case 6: *result = TX_LOCK_TIME; return SIMPLICITY_NO_ERROR;
case 7: *result = TX_LOCK_DISTANCE; return SIMPLICITY_NO_ERROR;
case 8: *result = TX_LOCK_DURATION; return SIMPLICITY_NO_ERROR;
case 9: *result = TX_IS_FINAL; return SIMPLICITY_NO_ERROR;
}
break;
case 3:
code = simplicity_decodeUptoMaxInt(stream);
if (code < 0) return (simplicity_err)code;
switch (code) {
case 1: *result = SCRIPT_CMR; return SIMPLICITY_NO_ERROR;
case 2: *result = INTERNAL_KEY; return SIMPLICITY_NO_ERROR;
case 3: *result = CURRENT_INDEX; return SIMPLICITY_NO_ERROR;
case 4: *result = NUM_INPUTS; return SIMPLICITY_NO_ERROR;
case 5: *result = NUM_OUTPUTS; return SIMPLICITY_NO_ERROR;
case 6: *result = LOCK_TIME; return SIMPLICITY_NO_ERROR;
case 7: *result = FEE; return SIMPLICITY_NO_ERROR;
case 8: *result = OUTPUT_VALUE; return SIMPLICITY_NO_ERROR;
case 9: *result = OUTPUT_SCRIPT_HASH; return SIMPLICITY_NO_ERROR;
case 10: *result = TOTAL_OUTPUT_VALUE; return SIMPLICITY_NO_ERROR;
case 11: *result = CURRENT_PREV_OUTPOINT; return SIMPLICITY_NO_ERROR;
case 12: *result = CURRENT_VALUE; return SIMPLICITY_NO_ERROR;
case 13: *result = CURRENT_SCRIPT_HASH; return SIMPLICITY_NO_ERROR;
case 14: *result = CURRENT_SEQUENCE; return SIMPLICITY_NO_ERROR;
case 15: *result = CURRENT_ANNEX_HASH; return SIMPLICITY_NO_ERROR;
case 16: *result = CURRENT_SCRIPT_SIG_HASH; return SIMPLICITY_NO_ERROR;
case 17: *result = INPUT_PREV_OUTPOINT; return SIMPLICITY_NO_ERROR;
case 18: *result = INPUT_VALUE; return SIMPLICITY_NO_ERROR;
case 19: *result = INPUT_SCRIPT_HASH; return SIMPLICITY_NO_ERROR;
case 20: *result = INPUT_SEQUENCE; return SIMPLICITY_NO_ERROR;
case 21: *result = INPUT_ANNEX_HASH; return SIMPLICITY_NO_ERROR;
case 22: *result = INPUT_SCRIPT_SIG_HASH; return SIMPLICITY_NO_ERROR;
case 23: *result = TOTAL_INPUT_VALUE; return SIMPLICITY_NO_ERROR;
case 24: *result = TAPLEAF_VERSION; return SIMPLICITY_NO_ERROR;
case 25: *result = TAPPATH; return SIMPLICITY_NO_ERROR;
case 26: *result = VERSION; return SIMPLICITY_NO_ERROR;
case 27: *result = TRANSACTION_ID; return SIMPLICITY_NO_ERROR;
}
break;
}
}

View file

@ -0,0 +1,260 @@
#include <simplicity/bitcoin/env.h>
#include <stdalign.h>
#include <stddef.h>
#include <string.h>
#include "txEnv.h"
#include "ops.h"
#include "../sha256.h"
#include "../simplicity_assert.h"
#include "../simplicity_alloc.h"
#define PADDING(alignType, allocated) ((alignof(alignType) - (allocated) % alignof(alignType)) % alignof(alignType))
/* Compute the SHA-256 hash of a scriptPubKey and write it into 'result'.
*
* Precondition: NULL != result;
* NULL != scriptPubKey;
*/
static void hashBuffer(sha256_midstate* result, const rawBitcoinBuffer* buffer) {
sha256_context ctx = sha256_init(result->s);
sha256_uchars(&ctx, buffer->buf, buffer->len);
sha256_finalize(&ctx);
}
/* Initialize a 'sigOutput' from a 'rawOutput', copying or hashing the data as needed.
*
* Precondition: NULL != result;
* NULL != output;
*/
static void copyOutput(sigOutput* result, const rawBitcoinOutput* output) {
hashBuffer(&result->scriptPubKey, &output->scriptPubKey);
result->value = output->value;
}
/* Initialize a 'sigInput' from a 'rawBitcoinInput', copying or hashing the data as needed.
*
* Precondition: NULL != result;
* NULL != input;
*/
static void copyInput(sigInput* result, const rawBitcoinInput* input) {
*result = (sigInput){ .prevOutpoint = { .ix = input->prevIx }
, .sequence = input->sequence
, .hasAnnex = !!input->annex
};
if (input->annex) hashBuffer(&result->annexHash, input->annex);
sha256_toMidstate(result->prevOutpoint.txid.s, input->prevTxid);
copyOutput(&result->txo, &input->txo);
hashBuffer(&result->scriptSigHash, &input->scriptSig);
}
/* Allocate and initialize a 'bitcoinTransaction' from a 'rawBitcoinTransaction', 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 bitcoinTransaction* simplicity_bitcoin_mallocTransaction(const rawBitcoinTransaction* rawTx) {
if (!rawTx) return NULL;
size_t allocationSize = sizeof(bitcoinTransaction);
const size_t pad1 = PADDING(sigInput, allocationSize);
if (SIZE_MAX - allocationSize < pad1) return NULL;
allocationSize += pad1;
/* Multiply by (size_t)1 to disable type-limits warning. */
if (SIZE_MAX / sizeof(sigInput) < (size_t)1 * rawTx->numInputs) return NULL;
if (SIZE_MAX - allocationSize < rawTx->numInputs * sizeof(sigInput)) return NULL;
allocationSize += rawTx->numInputs * sizeof(sigInput);
const size_t pad2 = PADDING(sigOutput, allocationSize);
if (SIZE_MAX - allocationSize < pad2) return NULL;
allocationSize += pad2;
/* Multiply by (size_t)1 to disable type-limits warning. */
if (SIZE_MAX / sizeof(sigOutput) < (size_t)1 * rawTx->numOutputs) return NULL;
if (SIZE_MAX - allocationSize < rawTx->numOutputs * sizeof(sigOutput)) return NULL;
allocationSize += rawTx->numOutputs * sizeof(sigOutput);
char *allocation = simplicity_malloc(allocationSize);
if (!allocation) return NULL;
/* Casting through void* to avoid warning about pointer alignment.
* Our padding is done carefully to ensure alignment.
*/
bitcoinTransaction* const tx = (bitcoinTransaction*)(void*)allocation;
allocation += sizeof(bitcoinTransaction) + pad1;
sigInput* const input = (sigInput*)(void*)allocation;
allocation += rawTx->numInputs * sizeof(sigInput) + pad2;
sigOutput* const output = (sigOutput*)(void*)allocation;
*tx = (bitcoinTransaction){ .input = input
, .output = output
, .numInputs = rawTx->numInputs
, .numOutputs = rawTx->numOutputs
, .version = rawTx->version
, .lockTime = rawTx->lockTime
, .isFinal = true
};
sha256_toMidstate(tx->txid.s, rawTx->txid);
{
sha256_context ctx_inputOutpointsHash = sha256_init(tx->inputOutpointsHash.s);
sha256_context ctx_inputValuesHash = sha256_init(tx->inputValuesHash.s);
sha256_context ctx_inputScriptsHash = sha256_init(tx->inputScriptsHash.s);
sha256_context ctx_inputUTXOsHash = sha256_init(tx->inputUTXOsHash.s);
sha256_context ctx_inputSequencesHash = sha256_init(tx->inputSequencesHash.s);
sha256_context ctx_inputAnnexesHash = sha256_init(tx->inputAnnexesHash.s);
sha256_context ctx_inputScriptSigsHash = sha256_init(tx->inputScriptSigsHash.s);
sha256_context ctx_inputsHash = sha256_init(tx->inputsHash.s);
for (uint_fast32_t i = 0; i < tx->numInputs; ++i) {
copyInput(&input[i], &rawTx->input[i]);
tx->totalInputValue += input[i].txo.value;
if (input[i].sequence < 0xffffffff) { tx->isFinal = false; }
sha256_hash(&ctx_inputOutpointsHash, &input[i].prevOutpoint.txid);
sha256_u32be(&ctx_inputOutpointsHash, input[i].prevOutpoint.ix);
sha256_u64be(&ctx_inputValuesHash, input[i].txo.value);
sha256_hash(&ctx_inputScriptsHash, &input[i].txo.scriptPubKey);
sha256_u32be(&ctx_inputSequencesHash, input[i].sequence);
if (input[i].hasAnnex) {
sha256_uchar(&ctx_inputAnnexesHash, 1);
sha256_hash(&ctx_inputAnnexesHash, &input[i].annexHash);
} else {
sha256_uchar(&ctx_inputAnnexesHash, 0);
}
sha256_hash(&ctx_inputScriptSigsHash, &input[i].scriptSigHash);
}
sha256_finalize(&ctx_inputOutpointsHash);
sha256_finalize(&ctx_inputValuesHash);
sha256_finalize(&ctx_inputScriptsHash);
sha256_finalize(&ctx_inputSequencesHash);
sha256_finalize(&ctx_inputAnnexesHash);
sha256_finalize(&ctx_inputScriptSigsHash);
sha256_hash(&ctx_inputUTXOsHash, &tx->inputValuesHash);
sha256_hash(&ctx_inputUTXOsHash, &tx->inputScriptsHash);
sha256_finalize(&ctx_inputUTXOsHash);
sha256_hash(&ctx_inputsHash, &tx->inputOutpointsHash);
sha256_hash(&ctx_inputsHash, &tx->inputSequencesHash);
sha256_hash(&ctx_inputsHash, &tx->inputAnnexesHash);
sha256_finalize(&ctx_inputsHash);
}
{
sha256_context ctx_outputValuesHash = sha256_init(tx->outputValuesHash.s);
sha256_context ctx_outputScriptsHash = sha256_init(tx->outputScriptsHash.s);
sha256_context ctx_outputsHash = sha256_init(tx->outputsHash.s);
for (uint_fast32_t i = 0; i < tx->numOutputs; ++i) {
copyOutput(&output[i], &rawTx->output[i]);
tx->totalOutputValue += output[i].value;
sha256_u64be(&ctx_outputValuesHash, output[i].value);
sha256_hash(&ctx_outputScriptsHash, &output[i].scriptPubKey);
}
sha256_finalize(&ctx_outputValuesHash);
sha256_finalize(&ctx_outputScriptsHash);
sha256_hash(&ctx_outputsHash, &tx->outputValuesHash);
sha256_hash(&ctx_outputsHash, &tx->outputScriptsHash);
sha256_finalize(&ctx_outputsHash);
}
{
sha256_context ctx_txHash = sha256_init(tx->txHash.s);
sha256_u32be(&ctx_txHash, tx->version);
sha256_u32be(&ctx_txHash, tx->lockTime);
sha256_hash(&ctx_txHash, &tx->inputsHash);
sha256_hash(&ctx_txHash, &tx->outputsHash);
sha256_hash(&ctx_txHash, &tx->inputUTXOsHash);
sha256_finalize(&ctx_txHash);
}
return tx;
}
/* Free a pointer to 'bitcoinTransaction'.
*/
extern void simplicity_bitcoin_freeTransaction(bitcoinTransaction* tx) {
simplicity_free(tx);
}
/* Allocate and initialize a 'bitcoinTapEnv' from a 'rawBitcoinTapEnv', 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 bitcoinTapEnv* simplicity_bitcoin_mallocTapEnv(const rawBitcoinTapEnv* rawEnv) {
if (!rawEnv) return NULL;
if (128 < rawEnv->pathLen) return NULL;
size_t allocationSize = sizeof(bitcoinTapEnv);
const size_t numMidstate = rawEnv->pathLen;
const size_t pad1 = PADDING(sha256_midstate, allocationSize);
if (numMidstate) {
if (SIZE_MAX - allocationSize < pad1) return NULL;
allocationSize += pad1;
if (SIZE_MAX / sizeof(sha256_midstate) < numMidstate) return NULL;
if (SIZE_MAX - allocationSize < numMidstate * sizeof(sha256_midstate)) return NULL;
allocationSize += numMidstate * sizeof(sha256_midstate);
}
char *allocation = simplicity_malloc(allocationSize);
if (!allocation) return NULL;
/* Casting through void* to avoid warning about pointer alignment.
* Our padding is done carefully to ensure alignment.
*/
bitcoinTapEnv* const env = (bitcoinTapEnv*)(void*)allocation;
sha256_midstate* path = NULL;
sha256_midstate internalKey;
sha256_toMidstate(internalKey.s, &rawEnv->controlBlock[1]);
if (numMidstate) {
allocation += sizeof(bitcoinTapEnv) + pad1;
if (rawEnv->pathLen) {
path = (sha256_midstate*)(void*)allocation;
}
}
*env = (bitcoinTapEnv){ .leafVersion = rawEnv->controlBlock[0] & 0xfe
, .internalKey = internalKey
, .path = path
, .pathLen = rawEnv->pathLen
};
sha256_toMidstate(env->scriptCMR.s, rawEnv->scriptCMR);
{
sha256_context ctx = sha256_init(env->tappathHash.s);
for (int i = 0; i < env->pathLen; ++i) {
sha256_toMidstate(path[i].s, &rawEnv->controlBlock[33+32*i]);
sha256_hash(&ctx, &path[i]);
}
sha256_finalize(&ctx);
}
env->tapLeafHash = simplicity_bitcoin_make_tapleaf(env->leafVersion, &env->scriptCMR);
{
sha256_context ctx = sha256_init(env->tapEnvHash.s);
sha256_hash(&ctx, &env->tapLeafHash);
sha256_hash(&ctx, &env->tappathHash);
sha256_hash(&ctx, &env->internalKey);
sha256_finalize(&ctx);
}
return env;
}
/* Free a pointer to 'bitcoinTapEnv'.
*/
extern void simplicity_bitcoin_freeTapEnv(bitcoinTapEnv* env) {
simplicity_free(env);
}

View file

@ -0,0 +1,56 @@
#include "ops.h"
/* Compute Bitcoins's tapleaf hash from a tapleaf version and a 256-bit script value.
* A reimplementation of ComputeTapleafHash from Bitcoin's 'interpreter.cpp'.
* Only 256-bit script values are supported as that is the size used for Simplicity CMRs.
*
* Precondition: NULL != cmr;
*/
sha256_midstate simplicity_bitcoin_make_tapleaf(unsigned char version, const sha256_midstate* cmr) {
sha256_midstate result;
sha256_midstate tapleafTag;
{
static unsigned char tagName[] = "TapLeaf";
sha256_context ctx = sha256_init(tapleafTag.s);
sha256_uchars(&ctx, tagName, sizeof(tagName) - 1);
sha256_finalize(&ctx);
}
sha256_context ctx = sha256_init(result.s);
sha256_hash(&ctx, &tapleafTag);
sha256_hash(&ctx, &tapleafTag);
sha256_uchar(&ctx, version);
sha256_uchar(&ctx, 32);
sha256_hash(&ctx, cmr);
sha256_finalize(&ctx);
return result;
}
/* Compute Bitcoins's tapbrach hash from two branches.
*
* Precondition: NULL != a;
* NULL != b;
*/
sha256_midstate simplicity_bitcoin_make_tapbranch(const sha256_midstate* a, const sha256_midstate* b) {
sha256_midstate result;
sha256_midstate tapbranchTag;
{
static unsigned char tagName[] = "TapBranch";
sha256_context ctx = sha256_init(tapbranchTag.s);
sha256_uchars(&ctx, tagName, sizeof(tagName) - 1);
sha256_finalize(&ctx);
}
sha256_context ctx = sha256_init(result.s);
sha256_hash(&ctx, &tapbranchTag);
sha256_hash(&ctx, &tapbranchTag);
if (sha256_cmp_be(a, b) < 0) {
sha256_hash(&ctx, a);
sha256_hash(&ctx, b);
} else {
sha256_hash(&ctx, b);
sha256_hash(&ctx, a);
}
sha256_finalize(&ctx);
return result;
}

View file

@ -0,0 +1,23 @@
/* This module defines operations used in the construction the environment ('txEnv') and some jets.
*/
#ifndef SIMPLICITY_BITCOIN_OPS_H
#define SIMPLICITY_BITCOIN_OPS_H
#include "../sha256.h"
/* Compute Bitcoin's tapleaf hash from a tapleaf version and a 256-bit script value.
* A reimplementation of ComputeTapleafHash from Bitcoin's 'interpreter.cpp'.
* Only 256-bit script values are supported as that is the size used for Simplicity CMRs.
*
* Precondition: NULL != cmr;
*/
sha256_midstate simplicity_bitcoin_make_tapleaf(unsigned char version, const sha256_midstate* cmr);
/* Compute an Bitcoin's tapbrach hash from two branches.
*
* Precondition: NULL != a;
* NULL != b;
*/
sha256_midstate simplicity_bitcoin_make_tapbranch(const sha256_midstate* a, const sha256_midstate* b);
#endif

View file

@ -0,0 +1,107 @@
/* This module implements the 'primitive.h' interface for the Bitcoin application of Simplicity.
*/
#include "primitive.h"
#include "bitcoinJets.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 {
#include "primitiveEnumTy.inc"
NumberOfTypeNames
};
/* 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',
* 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'
*/
size_t simplicity_bitcoin_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");
static_assert(NumberOfTypeNames + 6*DAG_LEN_MAX <= SIZE_MAX/sizeof(unification_var) , "bound_var array too large");
static_assert(NumberOfTypeNames + 6*DAG_LEN_MAX - 1 <= UINT32_MAX, "bound_var array index doesn't fit in uint32_t");
simplicity_assert(extra_var_len <= 6*DAG_LEN_MAX);
*bound_var = simplicity_malloc((NumberOfTypeNames + extra_var_len) * sizeof(unification_var));
if (!(*bound_var)) return 0;
#include "primitiveInitTy.inc"
*word256_ix = ty_w256;
*extra_var_start = NumberOfTypeNames;
/* 'ty_u' is a trivial binding, so we made 'NumberOfTypeNames - 1' non-trivial bindings. */
return NumberOfTypeNames - 1;
};
/* An enumeration of the names of Bitcoin specific jets and primitives. */
typedef enum jetName
{
#include "primitiveEnumJet.inc"
NUMBER_OF_JET_NAMES
} jetName;
/* Decode an Bitcoin specific jet name from 'stream' into 'result'.
* 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, 'result' may be modified.
* Returns 'SIMPLICITY_NO_ERROR' if successful.
*
* Precondition: NULL != result
* NULL != stream
*/
static simplicity_err decodePrimitive(jetName* result, bitstream* stream) {
int32_t bit = read1Bit(stream);
if (bit < 0) return (simplicity_err)bit;
if (!bit) {
/* Core jets */
#include "../decodeCoreJets.inc"
return SIMPLICITY_ERR_DATA_OUT_OF_RANGE;
} else {
/* Bitcoin jets */
#include "decodeBitcoinJets.inc"
return SIMPLICITY_ERR_DATA_OUT_OF_RANGE;
}
}
/* Return a copy of the Simplicity node corresponding to the given Bitcoin specific jet 'name'. */
static dag_node jetNode(jetName name) {
static const dag_node jet_node[] = {
#include "primitiveJetNode.inc"
};
return jet_node[name];
}
/* Decode a Bitcoin 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_ERR' if successful.
*
* Precondition: NULL != node
* NULL != stream
*/
simplicity_err simplicity_bitcoin_decodeJet(dag_node* node, bitstream* stream) {
jetName name;
simplicity_err error = decodePrimitive(&name, stream);
if (!IS_OK(error)) return error;
*node = jetNode(name);
return SIMPLICITY_NO_ERROR;
}

View file

@ -0,0 +1,41 @@
/* Implements the primitive.h interface for the Bitcoin Simplicity application.
*/
#ifndef SIMPLICITY_BITCOIN_PRIMITIVE_H
#define SIMPLICITY_BITCOIN_PRIMITIVE_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',
* 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'
*/
size_t simplicity_bitcoin_mallocBoundVars(unification_var** bound_var, size_t* word256_ix, size_t* extra_var_start, size_t extra_var_len);
/* Decode a Bitcoin 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
*/
simplicity_err simplicity_bitcoin_decodeJet(dag_node* node, bitstream* stream);
#endif

View file

@ -0,0 +1,429 @@
/* This file has been automatically generated. */
ADD_16,
ADD_32,
ADD_64,
ADD_8,
ALL_16,
ALL_32,
ALL_64,
ALL_8,
AND_1,
AND_16,
AND_32,
AND_64,
AND_8,
ANNEX_HASH,
BIP_0340_VERIFY,
BUILD_TAPBRANCH,
BUILD_TAPLEAF_SIMPLICITY,
BUILD_TAPTWEAK,
CH_1,
CH_16,
CH_32,
CH_64,
CH_8,
CHECK_LOCK_DISTANCE,
CHECK_LOCK_DURATION,
CHECK_LOCK_HEIGHT,
CHECK_LOCK_TIME,
CHECK_SIG_VERIFY,
COMPLEMENT_1,
COMPLEMENT_16,
COMPLEMENT_32,
COMPLEMENT_64,
COMPLEMENT_8,
CURRENT_ANNEX_HASH,
CURRENT_INDEX,
CURRENT_PREV_OUTPOINT,
CURRENT_SCRIPT_HASH,
CURRENT_SCRIPT_SIG_HASH,
CURRENT_SEQUENCE,
CURRENT_VALUE,
DECOMPRESS,
DECREMENT_16,
DECREMENT_32,
DECREMENT_64,
DECREMENT_8,
DIV_MOD_128_64,
DIV_MOD_16,
DIV_MOD_32,
DIV_MOD_64,
DIV_MOD_8,
DIVIDE_16,
DIVIDE_32,
DIVIDE_64,
DIVIDE_8,
DIVIDES_16,
DIVIDES_32,
DIVIDES_64,
DIVIDES_8,
EQ_1,
EQ_16,
EQ_256,
EQ_32,
EQ_64,
EQ_8,
FE_ADD,
FE_INVERT,
FE_IS_ODD,
FE_IS_ZERO,
FE_MULTIPLY,
FE_MULTIPLY_BETA,
FE_NEGATE,
FE_NORMALIZE,
FE_SQUARE,
FE_SQUARE_ROOT,
FEE,
FULL_ADD_16,
FULL_ADD_32,
FULL_ADD_64,
FULL_ADD_8,
FULL_DECREMENT_16,
FULL_DECREMENT_32,
FULL_DECREMENT_64,
FULL_DECREMENT_8,
FULL_INCREMENT_16,
FULL_INCREMENT_32,
FULL_INCREMENT_64,
FULL_INCREMENT_8,
FULL_LEFT_SHIFT_16_1,
FULL_LEFT_SHIFT_16_2,
FULL_LEFT_SHIFT_16_4,
FULL_LEFT_SHIFT_16_8,
FULL_LEFT_SHIFT_32_1,
FULL_LEFT_SHIFT_32_16,
FULL_LEFT_SHIFT_32_2,
FULL_LEFT_SHIFT_32_4,
FULL_LEFT_SHIFT_32_8,
FULL_LEFT_SHIFT_64_1,
FULL_LEFT_SHIFT_64_16,
FULL_LEFT_SHIFT_64_2,
FULL_LEFT_SHIFT_64_32,
FULL_LEFT_SHIFT_64_4,
FULL_LEFT_SHIFT_64_8,
FULL_LEFT_SHIFT_8_1,
FULL_LEFT_SHIFT_8_2,
FULL_LEFT_SHIFT_8_4,
FULL_MULTIPLY_16,
FULL_MULTIPLY_32,
FULL_MULTIPLY_64,
FULL_MULTIPLY_8,
FULL_RIGHT_SHIFT_16_1,
FULL_RIGHT_SHIFT_16_2,
FULL_RIGHT_SHIFT_16_4,
FULL_RIGHT_SHIFT_16_8,
FULL_RIGHT_SHIFT_32_1,
FULL_RIGHT_SHIFT_32_16,
FULL_RIGHT_SHIFT_32_2,
FULL_RIGHT_SHIFT_32_4,
FULL_RIGHT_SHIFT_32_8,
FULL_RIGHT_SHIFT_64_1,
FULL_RIGHT_SHIFT_64_16,
FULL_RIGHT_SHIFT_64_2,
FULL_RIGHT_SHIFT_64_32,
FULL_RIGHT_SHIFT_64_4,
FULL_RIGHT_SHIFT_64_8,
FULL_RIGHT_SHIFT_8_1,
FULL_RIGHT_SHIFT_8_2,
FULL_RIGHT_SHIFT_8_4,
FULL_SUBTRACT_16,
FULL_SUBTRACT_32,
FULL_SUBTRACT_64,
FULL_SUBTRACT_8,
GE_IS_ON_CURVE,
GE_NEGATE,
GEJ_ADD,
GEJ_DOUBLE,
GEJ_EQUIV,
GEJ_GE_ADD,
GEJ_GE_ADD_EX,
GEJ_GE_EQUIV,
GEJ_INFINITY,
GEJ_IS_INFINITY,
GEJ_IS_ON_CURVE,
GEJ_NEGATE,
GEJ_NORMALIZE,
GEJ_RESCALE,
GEJ_X_EQUIV,
GEJ_Y_IS_ODD,
GENERATE,
HASH_TO_CURVE,
HIGH_1,
HIGH_16,
HIGH_32,
HIGH_64,
HIGH_8,
INCREMENT_16,
INCREMENT_32,
INCREMENT_64,
INCREMENT_8,
INPUT_ANNEX_HASH,
INPUT_ANNEXES_HASH,
INPUT_HASH,
INPUT_OUTPOINTS_HASH,
INPUT_PREV_OUTPOINT,
INPUT_SCRIPT_HASH,
INPUT_SCRIPT_SIG_HASH,
INPUT_SCRIPT_SIGS_HASH,
INPUT_SCRIPTS_HASH,
INPUT_SEQUENCE,
INPUT_SEQUENCES_HASH,
INPUT_UTXO_HASH,
INPUT_UTXOS_HASH,
INPUT_VALUE,
INPUT_VALUES_HASH,
INPUTS_HASH,
INTERNAL_KEY,
IS_ONE_16,
IS_ONE_32,
IS_ONE_64,
IS_ONE_8,
IS_ZERO_16,
IS_ZERO_32,
IS_ZERO_64,
IS_ZERO_8,
LE_16,
LE_32,
LE_64,
LE_8,
LEFT_EXTEND_16_32,
LEFT_EXTEND_16_64,
LEFT_EXTEND_1_16,
LEFT_EXTEND_1_32,
LEFT_EXTEND_1_64,
LEFT_EXTEND_1_8,
LEFT_EXTEND_32_64,
LEFT_EXTEND_8_16,
LEFT_EXTEND_8_32,
LEFT_EXTEND_8_64,
LEFT_PAD_HIGH_16_32,
LEFT_PAD_HIGH_16_64,
LEFT_PAD_HIGH_1_16,
LEFT_PAD_HIGH_1_32,
LEFT_PAD_HIGH_1_64,
LEFT_PAD_HIGH_1_8,
LEFT_PAD_HIGH_32_64,
LEFT_PAD_HIGH_8_16,
LEFT_PAD_HIGH_8_32,
LEFT_PAD_HIGH_8_64,
LEFT_PAD_LOW_16_32,
LEFT_PAD_LOW_16_64,
LEFT_PAD_LOW_1_16,
LEFT_PAD_LOW_1_32,
LEFT_PAD_LOW_1_64,
LEFT_PAD_LOW_1_8,
LEFT_PAD_LOW_32_64,
LEFT_PAD_LOW_8_16,
LEFT_PAD_LOW_8_32,
LEFT_PAD_LOW_8_64,
LEFT_ROTATE_16,
LEFT_ROTATE_32,
LEFT_ROTATE_64,
LEFT_ROTATE_8,
LEFT_SHIFT_16,
LEFT_SHIFT_32,
LEFT_SHIFT_64,
LEFT_SHIFT_8,
LEFT_SHIFT_WITH_16,
LEFT_SHIFT_WITH_32,
LEFT_SHIFT_WITH_64,
LEFT_SHIFT_WITH_8,
LEFTMOST_16_1,
LEFTMOST_16_2,
LEFTMOST_16_4,
LEFTMOST_16_8,
LEFTMOST_32_1,
LEFTMOST_32_16,
LEFTMOST_32_2,
LEFTMOST_32_4,
LEFTMOST_32_8,
LEFTMOST_64_1,
LEFTMOST_64_16,
LEFTMOST_64_2,
LEFTMOST_64_32,
LEFTMOST_64_4,
LEFTMOST_64_8,
LEFTMOST_8_1,
LEFTMOST_8_2,
LEFTMOST_8_4,
LINEAR_COMBINATION_1,
LINEAR_VERIFY_1,
LOCK_TIME,
LOW_1,
LOW_16,
LOW_32,
LOW_64,
LOW_8,
LT_16,
LT_32,
LT_64,
LT_8,
MAJ_1,
MAJ_16,
MAJ_32,
MAJ_64,
MAJ_8,
MAX_16,
MAX_32,
MAX_64,
MAX_8,
MEDIAN_16,
MEDIAN_32,
MEDIAN_64,
MEDIAN_8,
MIN_16,
MIN_32,
MIN_64,
MIN_8,
MODULO_16,
MODULO_32,
MODULO_64,
MODULO_8,
MULTIPLY_16,
MULTIPLY_32,
MULTIPLY_64,
MULTIPLY_8,
NEGATE_16,
NEGATE_32,
NEGATE_64,
NEGATE_8,
NUM_INPUTS,
NUM_OUTPUTS,
ONE_16,
ONE_32,
ONE_64,
ONE_8,
OR_1,
OR_16,
OR_32,
OR_64,
OR_8,
OUTPOINT_HASH,
OUTPUT_HASH,
OUTPUT_SCRIPT_HASH,
OUTPUT_SCRIPTS_HASH,
OUTPUT_VALUE,
OUTPUT_VALUES_HASH,
OUTPUTS_HASH,
PARSE_LOCK,
PARSE_SEQUENCE,
POINT_VERIFY_1,
RIGHT_EXTEND_16_32,
RIGHT_EXTEND_16_64,
RIGHT_EXTEND_32_64,
RIGHT_EXTEND_8_16,
RIGHT_EXTEND_8_32,
RIGHT_EXTEND_8_64,
RIGHT_PAD_HIGH_16_32,
RIGHT_PAD_HIGH_16_64,
RIGHT_PAD_HIGH_1_16,
RIGHT_PAD_HIGH_1_32,
RIGHT_PAD_HIGH_1_64,
RIGHT_PAD_HIGH_1_8,
RIGHT_PAD_HIGH_32_64,
RIGHT_PAD_HIGH_8_16,
RIGHT_PAD_HIGH_8_32,
RIGHT_PAD_HIGH_8_64,
RIGHT_PAD_LOW_16_32,
RIGHT_PAD_LOW_16_64,
RIGHT_PAD_LOW_1_16,
RIGHT_PAD_LOW_1_32,
RIGHT_PAD_LOW_1_64,
RIGHT_PAD_LOW_1_8,
RIGHT_PAD_LOW_32_64,
RIGHT_PAD_LOW_8_16,
RIGHT_PAD_LOW_8_32,
RIGHT_PAD_LOW_8_64,
RIGHT_ROTATE_16,
RIGHT_ROTATE_32,
RIGHT_ROTATE_64,
RIGHT_ROTATE_8,
RIGHT_SHIFT_16,
RIGHT_SHIFT_32,
RIGHT_SHIFT_64,
RIGHT_SHIFT_8,
RIGHT_SHIFT_WITH_16,
RIGHT_SHIFT_WITH_32,
RIGHT_SHIFT_WITH_64,
RIGHT_SHIFT_WITH_8,
RIGHTMOST_16_1,
RIGHTMOST_16_2,
RIGHTMOST_16_4,
RIGHTMOST_16_8,
RIGHTMOST_32_1,
RIGHTMOST_32_16,
RIGHTMOST_32_2,
RIGHTMOST_32_4,
RIGHTMOST_32_8,
RIGHTMOST_64_1,
RIGHTMOST_64_16,
RIGHTMOST_64_2,
RIGHTMOST_64_32,
RIGHTMOST_64_4,
RIGHTMOST_64_8,
RIGHTMOST_8_1,
RIGHTMOST_8_2,
RIGHTMOST_8_4,
SCALAR_ADD,
SCALAR_INVERT,
SCALAR_IS_ZERO,
SCALAR_MULTIPLY,
SCALAR_MULTIPLY_LAMBDA,
SCALAR_NEGATE,
SCALAR_NORMALIZE,
SCALAR_SQUARE,
SCALE,
SCRIPT_CMR,
SHA_256_BLOCK,
SHA_256_CTX_8_ADD_1,
SHA_256_CTX_8_ADD_128,
SHA_256_CTX_8_ADD_16,
SHA_256_CTX_8_ADD_2,
SHA_256_CTX_8_ADD_256,
SHA_256_CTX_8_ADD_32,
SHA_256_CTX_8_ADD_4,
SHA_256_CTX_8_ADD_512,
SHA_256_CTX_8_ADD_64,
SHA_256_CTX_8_ADD_8,
SHA_256_CTX_8_ADD_BUFFER_511,
SHA_256_CTX_8_FINALIZE,
SHA_256_CTX_8_INIT,
SHA_256_IV,
SIG_ALL_HASH,
SOME_1,
SOME_16,
SOME_32,
SOME_64,
SOME_8,
SUBTRACT_16,
SUBTRACT_32,
SUBTRACT_64,
SUBTRACT_8,
SWU,
TAP_ENV_HASH,
TAPDATA_INIT,
TAPLEAF_HASH,
TAPLEAF_VERSION,
TAPPATH,
TAPPATH_HASH,
TOTAL_INPUT_VALUE,
TOTAL_OUTPUT_VALUE,
TRANSACTION_ID,
TX_HASH,
TX_IS_FINAL,
TX_LOCK_DISTANCE,
TX_LOCK_DURATION,
TX_LOCK_HEIGHT,
TX_LOCK_TIME,
VERIFY,
VERSION,
XOR_1,
XOR_16,
XOR_32,
XOR_64,
XOR_8,
XOR_XOR_1,
XOR_XOR_16,
XOR_XOR_32,
XOR_XOR_64,
XOR_XOR_8,

View file

@ -0,0 +1,130 @@
/* This file has been automatically generated. */
ty_u = 0,
ty_b = 1,
ty_w2 = 2,
ty_w4 = 3,
ty_w8 = 4,
ty_w16 = 5,
ty_w32 = 6,
ty_w64 = 7,
ty_w128 = 8,
ty_w256 = 9,
ty_w512 = 10,
ty_w1Ki = 11,
ty_w2Ki = 12,
ty_w4Ki = 13,
ty_w8Ki = 14,
ty_w16Ki = 15,
ty_w32Ki = 16,
ty_w64Ki = 17,
ty_w128Ki = 18,
ty_w256Ki = 19,
ty_w512Ki = 20,
ty_w1Mi = 21,
ty_w2Mi = 22,
ty_w4Mi = 23,
ty_w8Mi = 24,
ty_w16Mi = 25,
ty_w32Mi = 26,
ty_w64Mi = 27,
ty_w128Mi = 28,
ty_w256Mi = 29,
ty_w512Mi = 30,
ty_w1Gi = 31,
ty_w2Gi = 32,
ty_mw8,
ty_mw16,
ty_mw32,
ty_mw64,
ty_mw128,
ty_mw256,
ty_mw512,
ty_mw1Ki,
ty_mw2Ki,
ty_mmw256,
ty_msw16w16,
ty_mpw256w32,
ty_sw16w16,
ty_sw32w32,
ty_pbw2,
ty_pbw8,
ty_pbw16,
ty_pbw32,
ty_pbw64,
ty_pbw128,
ty_pbw256,
ty_pbpw4w8,
ty_pbpw4w16,
ty_pbpw8w32,
ty_pbpw8w64,
ty_pw2w8,
ty_pw2w16,
ty_pw2w32,
ty_pw2w64,
ty_pw4w8,
ty_pw4w16,
ty_pw4w32,
ty_pw4w64,
ty_pw8b,
ty_pw8w2,
ty_pw8w4,
ty_pw8w16,
ty_pw8w32,
ty_pw8w64,
ty_pw16b,
ty_pw16w2,
ty_pw16w4,
ty_pw16w8,
ty_pw16w32,
ty_pw16w64,
ty_pw32b,
ty_pw32w2,
ty_pw32w4,
ty_pw32w8,
ty_pw32w16,
ty_pw32w64,
ty_pw64b,
ty_pw64w2,
ty_pw64w4,
ty_pw64w8,
ty_pw64w16,
ty_pw64w32,
ty_pw64w128,
ty_pw64w256,
ty_pw128w64,
ty_pw256w32,
ty_pw256w512,
ty_pw256pbw256,
ty_pw256pw512w256,
ty_pw512w256,
ty_pmw16mw8,
ty_pmw32pmw16mw8,
ty_pmw64pmw32pmw16mw8,
ty_pmw128pmw64pmw32pmw16mw8,
ty_pmw256pmw128pmw64pmw32pmw16mw8,
ty_pmw512pmw256pmw128pmw64pmw32pmw16mw8,
ty_pmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8,
ty_pmw2Kipmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8,
ty_ppw256w512w256,
ty_ppw256w512w512,
ty_ppw256pbw256w256,
ty_ppw256pw512w256w256,
ty_ppw512w256w256,
ty_ppw512w256w512,
ty_ppw512w256pw512w256,
ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256,
ty_pppw256w512w256w512,
ty_pppw256pbw256w256pbw256,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w8,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w16,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w32,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w64,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w128,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w256,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w512,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w1Ki,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w2Ki,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w4Ki,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256mw256,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256pw256w32,
ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256pmw2Kipmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8,

View file

@ -0,0 +1,130 @@
/* This file has been automatically generated. */
(*bound_var)[ty_u] = (unification_var){ .isBound = true, .bound = { .kind = ONE }};
(*bound_var)[ty_b] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_u] } }};
(*bound_var)[ty_w2] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_b] } }};
(*bound_var)[ty_w4] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w2], &(*bound_var)[ty_w2] } }};
(*bound_var)[ty_w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w4], &(*bound_var)[ty_w4] } }};
(*bound_var)[ty_w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_w128] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w128], &(*bound_var)[ty_w128] } }};
(*bound_var)[ty_w512] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w256], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_w1Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w512], &(*bound_var)[ty_w512] } }};
(*bound_var)[ty_w2Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w1Ki], &(*bound_var)[ty_w1Ki] } }};
(*bound_var)[ty_w4Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w2Ki], &(*bound_var)[ty_w2Ki] } }};
(*bound_var)[ty_w8Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w4Ki], &(*bound_var)[ty_w4Ki] } }};
(*bound_var)[ty_w16Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8Ki], &(*bound_var)[ty_w8Ki] } }};
(*bound_var)[ty_w32Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16Ki], &(*bound_var)[ty_w16Ki] } }};
(*bound_var)[ty_w64Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32Ki], &(*bound_var)[ty_w32Ki] } }};
(*bound_var)[ty_w128Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64Ki], &(*bound_var)[ty_w64Ki] } }};
(*bound_var)[ty_w256Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w128Ki], &(*bound_var)[ty_w128Ki] } }};
(*bound_var)[ty_w512Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w256Ki], &(*bound_var)[ty_w256Ki] } }};
(*bound_var)[ty_w1Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w512Ki], &(*bound_var)[ty_w512Ki] } }};
(*bound_var)[ty_w2Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w1Mi], &(*bound_var)[ty_w1Mi] } }};
(*bound_var)[ty_w4Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w2Mi], &(*bound_var)[ty_w2Mi] } }};
(*bound_var)[ty_w8Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w4Mi], &(*bound_var)[ty_w4Mi] } }};
(*bound_var)[ty_w16Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8Mi], &(*bound_var)[ty_w8Mi] } }};
(*bound_var)[ty_w32Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16Mi], &(*bound_var)[ty_w16Mi] } }};
(*bound_var)[ty_w64Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32Mi], &(*bound_var)[ty_w32Mi] } }};
(*bound_var)[ty_w128Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64Mi], &(*bound_var)[ty_w64Mi] } }};
(*bound_var)[ty_w256Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w128Mi], &(*bound_var)[ty_w128Mi] } }};
(*bound_var)[ty_w512Mi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w256Mi], &(*bound_var)[ty_w256Mi] } }};
(*bound_var)[ty_w1Gi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w512Mi], &(*bound_var)[ty_w512Mi] } }};
(*bound_var)[ty_w2Gi] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w1Gi], &(*bound_var)[ty_w1Gi] } }};
(*bound_var)[ty_mw8] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_mw16] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_mw32] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_mw64] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_mw128] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w128] } }};
(*bound_var)[ty_mw256] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_mw512] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w512] } }};
(*bound_var)[ty_mw1Ki] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w1Ki] } }};
(*bound_var)[ty_mw2Ki] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_w2Ki] } }};
(*bound_var)[ty_mmw256] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_mw256] } }};
(*bound_var)[ty_msw16w16] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_sw16w16] } }};
(*bound_var)[ty_mpw256w32] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_u], &(*bound_var)[ty_pw256w32] } }};
(*bound_var)[ty_sw16w16] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_sw32w32] = (unification_var){ .isBound = true, .bound = { .kind = SUM, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pbw2] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_w2] } }};
(*bound_var)[ty_pbw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_pbw16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_pbw32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pbw64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pbw128] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_w128] } }};
(*bound_var)[ty_pbw256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_pbpw4w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_pw4w8] } }};
(*bound_var)[ty_pbpw4w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_pw4w16] } }};
(*bound_var)[ty_pbpw8w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_pw8w32] } }};
(*bound_var)[ty_pbpw8w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_b], &(*bound_var)[ty_pw8w64] } }};
(*bound_var)[ty_pw2w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w2], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_pw2w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w2], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_pw2w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w2], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pw2w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w2], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pw4w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w4], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_pw4w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w4], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_pw4w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w4], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pw4w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w4], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pw8b] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8], &(*bound_var)[ty_b] } }};
(*bound_var)[ty_pw8w2] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8], &(*bound_var)[ty_w2] } }};
(*bound_var)[ty_pw8w4] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8], &(*bound_var)[ty_w4] } }};
(*bound_var)[ty_pw8w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_pw8w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pw8w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w8], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pw16b] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_b] } }};
(*bound_var)[ty_pw16w2] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_w2] } }};
(*bound_var)[ty_pw16w4] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_w4] } }};
(*bound_var)[ty_pw16w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_pw16w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pw16w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w16], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pw32b] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_b] } }};
(*bound_var)[ty_pw32w2] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_w2] } }};
(*bound_var)[ty_pw32w4] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_w4] } }};
(*bound_var)[ty_pw32w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_pw32w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_pw32w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w32], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pw64b] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_b] } }};
(*bound_var)[ty_pw64w2] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w2] } }};
(*bound_var)[ty_pw64w4] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w4] } }};
(*bound_var)[ty_pw64w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_pw64w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_pw64w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pw64w128] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w128] } }};
(*bound_var)[ty_pw64w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w64], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_pw128w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w128], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pw256w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w256], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pw256w512] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w256], &(*bound_var)[ty_w512] } }};
(*bound_var)[ty_pw256pbw256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w256], &(*bound_var)[ty_pbw256] } }};
(*bound_var)[ty_pw256pw512w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w256], &(*bound_var)[ty_pw512w256] } }};
(*bound_var)[ty_pw512w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_w512], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw16], &(*bound_var)[ty_mw8] } }};
(*bound_var)[ty_pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw32], &(*bound_var)[ty_pmw16mw8] } }};
(*bound_var)[ty_pmw64pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw64], &(*bound_var)[ty_pmw32pmw16mw8] } }};
(*bound_var)[ty_pmw128pmw64pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw128], &(*bound_var)[ty_pmw64pmw32pmw16mw8] } }};
(*bound_var)[ty_pmw256pmw128pmw64pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw256], &(*bound_var)[ty_pmw128pmw64pmw32pmw16mw8] } }};
(*bound_var)[ty_pmw512pmw256pmw128pmw64pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw512], &(*bound_var)[ty_pmw256pmw128pmw64pmw32pmw16mw8] } }};
(*bound_var)[ty_pmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw1Ki], &(*bound_var)[ty_pmw512pmw256pmw128pmw64pmw32pmw16mw8] } }};
(*bound_var)[ty_pmw2Kipmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_mw2Ki], &(*bound_var)[ty_pmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8] } }};
(*bound_var)[ty_ppw256w512w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pw256w512], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_ppw256w512w512] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pw256w512], &(*bound_var)[ty_w512] } }};
(*bound_var)[ty_ppw256pbw256w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pw256pbw256], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_ppw256pw512w256w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pw256pw512w256], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_ppw512w256w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pw512w256], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_ppw512w256w512] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pw512w256], &(*bound_var)[ty_w512] } }};
(*bound_var)[ty_ppw512w256pw512w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pw512w256], &(*bound_var)[ty_pw512w256] } }};
(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_pmw256pmw128pmw64pmw32pmw16mw8], &(*bound_var)[ty_pw64w256] } }};
(*bound_var)[ty_pppw256w512w256w512] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppw256w512w256], &(*bound_var)[ty_w512] } }};
(*bound_var)[ty_pppw256pbw256w256pbw256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppw256pbw256w256], &(*bound_var)[ty_pbw256] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w8] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w16] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w16] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w32] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w64] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w64] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w128] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w128] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w256] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w512] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w512] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w1Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w1Ki] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w2Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w2Ki] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256w4Ki] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_w4Ki] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256mw256] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_mw256] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256pw256w32] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_pw256w32] } }};
(*bound_var)[ty_pppmw256pmw128pmw64pmw32pmw16mw8pw64w256pmw2Kipmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8] = (unification_var){ .isBound = true, .bound = { .kind = PRODUCT, .arg = { &(*bound_var)[ty_ppmw256pmw128pmw64pmw32pmw16mw8pw64w256], &(*bound_var)[ty_pmw2Kipmw1Kipmw512pmw256pmw128pmw64pmw32pmw16mw8] } }};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
#include "txEnv.h"
/* Construct a txEnv structure from its components.
* This function will precompute any cached values.
*
* Precondition: NULL != tx
* NULL != taproot
* ix < tx->numInputs
*/
txEnv simplicity_bitcoin_build_txEnv(const bitcoinTransaction* tx, const bitcoinTapEnv* taproot, uint_fast32_t ix) {
txEnv result = { .tx = tx
, .taproot = taproot
, .ix = ix
};
sha256_context ctx = sha256_init(result.sigAllHash.s);
sha256_hash(&ctx, &tx->txHash);
sha256_hash(&ctx, &taproot->tapEnvHash);
sha256_u32be(&ctx, ix);
sha256_finalize(&ctx);
return result;
}

View file

@ -0,0 +1,104 @@
/* This module defines the environment ('txEnv') for Simplicity evaluation for Bitcoin.
* 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_BITCOIN_TXENV_H
#define SIMPLICITY_BITCOIN_TXENV_H
#include <stdbool.h>
#include "../sha256.h"
/* An Bitcoin 'outpoint' consists of a transaction id and output index within that transaction.
*/
typedef struct outpoint {
sha256_midstate txid;
uint_fast32_t ix;
} outpoint;
/* A structure representing data from one output from a Bitcoin transaction.
* 'scriptPubKey' is the SHA-256 hash of the outputs scriptPubKey.
*/
typedef struct sigOutput {
uint_fast64_t value;
sha256_midstate scriptPubKey;
} sigOutput;
/* A structure representing data from one input from a Bitcoin transaction along with the utxo data of the output being redeemed.
* When 'hasAnnex' then 'annexHash' is a cache of the hash of the input's segwit annex.
*/
typedef struct sigInput {
sha256_midstate annexHash;
sha256_midstate scriptSigHash;
outpoint prevOutpoint;
sigOutput txo;
uint_fast32_t sequence;
bool hasAnnex;
} sigInput;
/* A structure representing data from a Bitcoin 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 bitcoinTransaction {
const sigInput* input;
const sigOutput* output;
sha256_midstate outputValuesHash;
sha256_midstate outputScriptsHash;
sha256_midstate outputsHash;
sha256_midstate inputOutpointsHash;
sha256_midstate inputValuesHash;
sha256_midstate inputScriptsHash;
sha256_midstate inputUTXOsHash;
sha256_midstate inputSequencesHash;
sha256_midstate inputAnnexesHash;
sha256_midstate inputScriptSigsHash;
sha256_midstate inputsHash;
sha256_midstate txHash;
sha256_midstate txid;
uint_fast64_t totalInputValue;
uint_fast64_t totalOutputValue;
uint_fast32_t numInputs;
uint_fast32_t numOutputs;
uint_fast32_t version;
uint_fast32_t lockTime;
bool isFinal;
} bitcoinTransaction;
/* A structure representing taproot spending data from a Bitcoin transaction.
*
* Invariant: pathLen <= 128
* sha256_midstate path[pathLen];
*/
typedef struct bitcoinTapEnv {
const sha256_midstate *path;
sha256_midstate tapLeafHash;
sha256_midstate tappathHash;
sha256_midstate tapEnvHash;
sha256_midstate internalKey;
sha256_midstate scriptCMR;
unsigned char pathLen;
unsigned char leafVersion;
} bitcoinTapEnv;
/* The 'txEnv' structure used by the Bitcoin application of Simplicity.
*
* It includes
* + the transaction data, which may be shared when Simplicity expressions are used for multiple inputs in the same transaction),
* + the input index under consideration,
*/
typedef struct txEnv {
const bitcoinTransaction* tx;
const bitcoinTapEnv* taproot;
sha256_midstate sigAllHash;
uint_fast32_t ix;
} txEnv;
/* Construct a txEnv structure from its components.
* This function will precompute any cached values.
*
* Precondition: NULL != tx
* NULL != taproot
* ix < tx->numInputs
*/
txEnv simplicity_bitcoin_build_txEnv(const bitcoinTransaction* tx, const bitcoinTapEnv* taproot, uint_fast32_t ix);
#endif

View file

@ -52,12 +52,12 @@
switch (code) {
case 1: *result = CHECK_LOCK_HEIGHT; return SIMPLICITY_NO_ERROR;
case 2: *result = CHECK_LOCK_TIME; return SIMPLICITY_NO_ERROR;
case 3: *result = CHECK_LOCK_DISTANCE; return SIMPLICITY_NO_ERROR;
case 4: *result = CHECK_LOCK_DURATION; return SIMPLICITY_NO_ERROR;
case 3: *result = BROKEN_DO_NOT_USE_CHECK_LOCK_DISTANCE; return SIMPLICITY_NO_ERROR;
case 4: *result = BROKEN_DO_NOT_USE_CHECK_LOCK_DURATION; return SIMPLICITY_NO_ERROR;
case 5: *result = TX_LOCK_HEIGHT; return SIMPLICITY_NO_ERROR;
case 6: *result = TX_LOCK_TIME; return SIMPLICITY_NO_ERROR;
case 7: *result = TX_LOCK_DISTANCE; return SIMPLICITY_NO_ERROR;
case 8: *result = TX_LOCK_DURATION; return SIMPLICITY_NO_ERROR;
case 7: *result = BROKEN_DO_NOT_USE_TX_LOCK_DISTANCE; return SIMPLICITY_NO_ERROR;
case 8: *result = BROKEN_DO_NOT_USE_TX_LOCK_DURATION; return SIMPLICITY_NO_ERROR;
case 9: *result = TX_IS_FINAL; return SIMPLICITY_NO_ERROR;
}
break;

View file

@ -153,12 +153,12 @@ static uint_fast32_t lockTime(const elementsTransaction* tx) {
return !tx->isFinal && 500000000U <= tx->lockTime ? tx->lockTime : 0;
}
static uint_fast16_t lockDistance(const elementsTransaction* tx) {
return 2 <= tx->version ? tx->lockDistance : 0;
static uint_fast16_t obsolete_lockDistance(const elementsTransaction* tx) {
return 2 <= tx->version ? tx->obsolete_lockDistance : 0;
}
static uint_fast16_t lockDuration(const elementsTransaction* tx) {
return 2 <= tx->version ? tx->lockDuration : 0;
static uint_fast16_t obsolete_lockDuration(const elementsTransaction* tx) {
return 2 <= tx->version ? tx->obsolete_lockDuration : 0;
}
static bool isFee(const sigOutput* output) {
@ -733,16 +733,16 @@ bool simplicity_tx_lock_time(frameItem* dst, frameItem src, const txEnv* env) {
}
/* tx_lock_distance : ONE |- TWO^16 */
bool simplicity_tx_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
bool simplicity_broken_do_not_use_tx_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write16(dst, lockDistance(env->tx));
simplicity_write16(dst, obsolete_lockDistance(env->tx));
return true;
}
/* tx_lock_duration : ONE |- TWO^16 */
bool simplicity_tx_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
bool simplicity_broken_do_not_use_tx_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; // src is unused;
simplicity_write16(dst, lockDuration(env->tx));
simplicity_write16(dst, obsolete_lockDuration(env->tx));
return true;
}
@ -761,17 +761,17 @@ bool simplicity_check_lock_time(frameItem* dst, frameItem src, const txEnv* env)
}
/* check_lock_distance : TWO^16 |- ONE */
bool simplicity_check_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
bool simplicity_broken_do_not_use_check_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; // dst is unused;
uint_fast16_t x = simplicity_read16(&src);
return x <= lockDistance(env->tx);
return x <= obsolete_lockDistance(env->tx);
}
/* check_lock_duration : TWO^16 |- ONE */
bool simplicity_check_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
bool simplicity_broken_do_not_use_check_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; // dst is unused;
uint_fast16_t x = simplicity_read16(&src);
return x <= lockDuration(env->tx);
return x <= obsolete_lockDuration(env->tx);
}
/* calculate_issuance_entropy : TWO^256 * TWO^32 * TWO^256 |- TWO^256 */

View file

@ -59,12 +59,12 @@ bool simplicity_num_outputs(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_tx_is_final(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_tx_lock_height(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_tx_lock_time(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_tx_lock_distance(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_tx_lock_duration(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_broken_do_not_use_tx_lock_distance(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_broken_do_not_use_tx_lock_duration(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_check_lock_height(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_check_lock_time(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_check_lock_distance(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_check_lock_duration(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_broken_do_not_use_check_lock_distance(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_broken_do_not_use_check_lock_duration(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_calculate_issuance_entropy(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_calculate_asset(frameItem* dst, frameItem src, const txEnv* env);
bool simplicity_calculate_explicit_token(frameItem* dst, frameItem src, const txEnv* env);

View file

@ -408,12 +408,12 @@ extern elementsTransaction* simplicity_elements_mallocTransaction(const rawEleme
copyInput(&input[i], &rawTx->input[i]);
if (input[i].sequence < 0xffffffff) { tx->isFinal = false; }
if (input[i].sequence < 0x80000000) {
const uint_fast16_t maskedSequence = input[i].sequence & 0xffff;
if (input[i].sequence & ((uint_fast32_t)1 << 22)) {
if (tx->lockDuration < maskedSequence) tx->lockDuration = maskedSequence;
} else {
if (tx->lockDistance < maskedSequence) tx->lockDistance = maskedSequence;
}
const uint_fast16_t maskedSequence = input[i].sequence & 0xffff;
if (input[i].sequence & ((uint_fast32_t)1 << 22)) {
if (tx->obsolete_lockDuration < maskedSequence) tx->obsolete_lockDuration = maskedSequence;
} else {
if (tx->obsolete_lockDistance < maskedSequence) tx->obsolete_lockDistance = maskedSequence;
}
}
if (input[i].isPegin) {
sha256_uchar(&ctx_inputOutpointsHash, 1);

View file

@ -15,6 +15,10 @@ AND_8,
ANNEX_HASH,
ASSET_AMOUNT_HASH,
BIP_0340_VERIFY,
BROKEN_DO_NOT_USE_CHECK_LOCK_DISTANCE,
BROKEN_DO_NOT_USE_CHECK_LOCK_DURATION,
BROKEN_DO_NOT_USE_TX_LOCK_DISTANCE,
BROKEN_DO_NOT_USE_TX_LOCK_DURATION,
BUILD_TAPBRANCH,
BUILD_TAPLEAF_SIMPLICITY,
BUILD_TAPTWEAK,
@ -27,8 +31,6 @@ CH_16,
CH_32,
CH_64,
CH_8,
CHECK_LOCK_DISTANCE,
CHECK_LOCK_DURATION,
CHECK_LOCK_HEIGHT,
CHECK_LOCK_TIME,
CHECK_SIG_VERIFY,
@ -454,8 +456,6 @@ TOTAL_FEE,
TRANSACTION_ID,
TX_HASH,
TX_IS_FINAL,
TX_LOCK_DISTANCE,
TX_LOCK_DURATION,
TX_LOCK_HEIGHT,
TX_LOCK_TIME,
VERIFY,

View file

@ -127,6 +127,38 @@
, .targetIx = ty_u
, .cost = 49087 /* milli weight units */
}
,[BROKEN_DO_NOT_USE_CHECK_LOCK_DISTANCE] =
{ .tag = JET
, .jet = simplicity_broken_do_not_use_check_lock_distance
, .cmr = {{0x7f78c7a7u, 0x7a25ada2u, 0x23267d23u, 0x9a5922f7u, 0x64b8ac0cu, 0x2fcef68eu, 0xb93c0d92u, 0xda4af515u}}
, .sourceIx = ty_w16
, .targetIx = ty_u
, .cost = 105 /* milli weight units */
}
,[BROKEN_DO_NOT_USE_CHECK_LOCK_DURATION] =
{ .tag = JET
, .jet = simplicity_broken_do_not_use_check_lock_duration
, .cmr = {{0x73dac8e2u, 0x5d87eaf3u, 0x82c2a772u, 0x06ad38b9u, 0x384361e7u, 0xd0dc87c0u, 0xfa7af7eau, 0x524597b7u}}
, .sourceIx = ty_w16
, .targetIx = ty_u
, .cost = 102 /* milli weight units */
}
,[BROKEN_DO_NOT_USE_TX_LOCK_DISTANCE] =
{ .tag = JET
, .jet = simplicity_broken_do_not_use_tx_lock_distance
, .cmr = {{0x4c7773b8u, 0x18cb7ee5u, 0xf54f925au, 0xad015677u, 0xa043a72fu, 0x316a187cu, 0xc28c696cu, 0xfcb90807u}}
, .sourceIx = ty_u
, .targetIx = ty_w16
, .cost = 91 /* milli weight units */
}
,[BROKEN_DO_NOT_USE_TX_LOCK_DURATION] =
{ .tag = JET
, .jet = simplicity_broken_do_not_use_tx_lock_duration
, .cmr = {{0xcc9c64c8u, 0xb6eb4bf0u, 0x9694af5au, 0x35d957a4u, 0x05e66c1bu, 0x35224ed6u, 0x75878918u, 0x452440b2u}}
, .sourceIx = ty_u
, .targetIx = ty_w16
, .cost = 84 /* milli weight units */
}
,[BUILD_TAPBRANCH] =
{ .tag = JET
, .jet = simplicity_build_tapbranch
@ -223,22 +255,6 @@
, .targetIx = ty_w8
, .cost = 77 /* milli weight units */
}
,[CHECK_LOCK_DISTANCE] =
{ .tag = JET
, .jet = simplicity_check_lock_distance
, .cmr = {{0x7f78c7a7u, 0x7a25ada2u, 0x23267d23u, 0x9a5922f7u, 0x64b8ac0cu, 0x2fcef68eu, 0xb93c0d92u, 0xda4af515u}}
, .sourceIx = ty_w16
, .targetIx = ty_u
, .cost = 105 /* milli weight units */
}
,[CHECK_LOCK_DURATION] =
{ .tag = JET
, .jet = simplicity_check_lock_duration
, .cmr = {{0x73dac8e2u, 0x5d87eaf3u, 0x82c2a772u, 0x06ad38b9u, 0x384361e7u, 0xd0dc87c0u, 0xfa7af7eau, 0x524597b7u}}
, .sourceIx = ty_w16
, .targetIx = ty_u
, .cost = 102 /* milli weight units */
}
,[CHECK_LOCK_HEIGHT] =
{ .tag = JET
, .jet = simplicity_check_lock_height
@ -3639,22 +3655,6 @@
, .targetIx = ty_b
, .cost = 71 /* milli weight units */
}
,[TX_LOCK_DISTANCE] =
{ .tag = JET
, .jet = simplicity_tx_lock_distance
, .cmr = {{0x4c7773b8u, 0x18cb7ee5u, 0xf54f925au, 0xad015677u, 0xa043a72fu, 0x316a187cu, 0xc28c696cu, 0xfcb90807u}}
, .sourceIx = ty_u
, .targetIx = ty_w16
, .cost = 91 /* milli weight units */
}
,[TX_LOCK_DURATION] =
{ .tag = JET
, .jet = simplicity_tx_lock_duration
, .cmr = {{0xcc9c64c8u, 0xb6eb4bf0u, 0x9694af5au, 0x35d957a4u, 0x05e66c1bu, 0x35224ed6u, 0x75878918u, 0x452440b2u}}
, .sourceIx = ty_u
, .targetIx = ty_w16
, .cost = 84 /* milli weight units */
}
,[TX_LOCK_HEIGHT] =
{ .tag = JET
, .jet = simplicity_tx_lock_height

View file

@ -224,11 +224,9 @@ typedef struct elementsTransaction {
uint_fast32_t numFees;
uint_fast32_t version;
uint_fast32_t lockTime;
/* lockDuration and lockDistance values are set even when the version is 0 or 1.
* This is similar to lockTime whose value is also set, even when the transaction is final.
*/
uint_fast16_t lockDistance;
uint_fast16_t lockDuration; /* Units of 512 seconds */
/* These two fields are used to implement broken jets and only remain here for consensus purposes. */
uint_fast16_t obsolete_lockDistance;
uint_fast16_t obsolete_lockDuration;
bool isFinal;
} elementsTransaction;

View file

@ -0,0 +1,98 @@
#ifndef SIMPLICITY_BITCOIN_ENV_H
#define SIMPLICITY_BITCOIN_ENV_H
#include <stdbool.h>
#include <stdint.h>
/* This section builds the 'rawBitcoinTransaction' structure which is the transaction data needed to build a Bitcoin 'txEnv' environment
* for evaluating Simplicity expressions within.
* The 'rawBitcoinTransaction' is copied into an opaque 'bitcoinTransaction' structure that can be reused within evaluating Simplicity on multiple
* inputs within the same transaction.
*/
/* A type for an unparsed buffer
*
* Invariant: if 0 < len then unsigned char buf[len]
*/
typedef struct rawBitcoinBuffer {
const unsigned char* buf;
uint32_t len;
} rawBitcoinBuffer;
/* A structure representing data for one output from a Bitcoin transaction.
*/
typedef struct rawBitcoinOutput {
uint64_t value;
rawBitcoinBuffer scriptPubKey;
} rawBitcoinOutput;
/* A structure representing data for one input from a Bitcoin transaction, including its taproot annex,
* plus the TXO data of the output being redeemed.
*
* Invariant: unsigned char prevTxid[32];
*/
typedef struct rawInput {
const rawBitcoinBuffer* annex;
const unsigned char* prevTxid;
rawBitcoinOutput txo;
rawBitcoinBuffer scriptSig;
uint32_t prevIx;
uint32_t sequence;
} rawBitcoinInput;
/* A structure representing data for a Bitcoin transaction, including the TXO data of each output being redeemed.
*
* Invariant: unsigned char txid[32];
* rawBitcoinInput input[numInputs];
* rawBitcoinOutput output[numOutputs];
*/
typedef struct rawBitcoinTransaction {
const unsigned char* txid; /* While in theory we could recompute the txid ourselves, it is easier and safer for it to be provided. */
const rawBitcoinInput* input;
const rawBitcoinOutput* output;
uint32_t numInputs;
uint32_t numOutputs;
uint32_t version;
uint32_t lockTime;
} rawBitcoinTransaction;
/* A forward declaration for the structure containing a copy (and digest) of the rawTransaction data */
typedef struct bitcoinTransaction bitcoinTransaction;
/* Allocate and initialize a 'bitcoinTransaction' from a 'rawBitcoinTransaction', 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 bitcoinTransaction* simplicity_bitcoin_mallocTransaction(const rawBitcoinTransaction* rawTx);
/* Free a pointer to 'bitcoinTransaction'.
*/
extern void simplicity_bitcoin_freeTransaction(bitcoinTransaction* tx);
/* A structure representing taproot spending data for a Bitcoin transaction.
*
* Invariant: pathLen <= 128;
* unsigned char controlBlock[33+pathLen*32];
* unsigned char scriptCMR[32];
*/
typedef struct rawBitcoinTapEnv {
const unsigned char* controlBlock;
const unsigned char* scriptCMR;
unsigned char pathLen;
} rawBitcoinTapEnv;
/* A forward declaration for the structure containing a copy (and digest) of the rawBitcoinTapEnv data */
typedef struct bitcoinTapEnv bitcoinTapEnv;
/* Allocate and initialize a 'bitcoinTapEnv' from a 'rawBitcoinTapEnv', 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 bitcoinTapEnv* simplicity_bitcoin_mallocTapEnv(const rawBitcoinTapEnv* rawEnv);
/* Free a pointer to 'bitcoinTapEnv'.
*/
extern void simplicity_bitcoin_freeTapEnv(bitcoinTapEnv* env);
#endif

View file

@ -356,9 +356,9 @@ static void test_elements(void) {
sha256_fromMidstate(cmr, elementsCheckSigHashAllTx1_cmr);
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";
unsigned char genesisHash[32] = {0x0f, 0x91, 0x88, 0xf1, 0x3c, 0xb7, 0xb2, 0xc7, 0x1f, 0x2a, 0x33, 0x5e, 0x3a, 0x4f, 0xc3, 0x28, 0xbf, 0x5b, 0xeb, 0x43, 0x60, 0x12, 0xaf, 0xca, 0x59, 0x0b, 0x1a, 0x11, 0x46, 0x6e, 0x22, 0x06};
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"}
{ .controlBlock = (unsigned char [33]){0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x78, 0xce, 0x56, 0x3f, 0x89, 0xa0, 0xed, 0x94, 0x14, 0xf5, 0xaa, 0x28, 0xad, 0x0d, 0x96, 0xd6, 0x79, 0x5f, 0x9c, 0x63}
, .pathLen = 0
, .scriptCMR = cmr
};
@ -367,28 +367,28 @@ static void test_elements(void) {
printf("Test elements\n");
{
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"}
{ .txid = (unsigned char[32]){0xdb, 0x9a, 0x3d, 0xe0, 0xb6, 0xb8, 0xcc, 0x74, 0x1e, 0x4d, 0x6c, 0x8f, 0x19, 0xce, 0x75, 0xec, 0x0d, 0xfd, 0x01, 0x02, 0xdb, 0x9c, 0xb5, 0xcd, 0x27, 0xa4, 0x1a, 0x66, 0x91, 0x66, 0x3a, 0x07}
, .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"}
, .prevTxid = (unsigned char[32]){0xeb, 0x04, 0xb6, 0x8e, 0x9a, 0x26, 0xd1, 0x16, 0x04, 0x6c, 0x76, 0xe8, 0xff, 0x47, 0x33, 0x2f, 0xb7, 0x1d, 0xda, 0x90, 0xff, 0x4b, 0xef, 0x53, 0x70, 0xf2, 0x52, 0x26, 0xd3, 0xbc, 0x09, 0xfc}
, .prevIx = 0
, .sequence = 0xfffffffe
, .issuance = {0}
, .scriptSig = {0}
, .txo = { .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\xe4\x00"}
, .txo = { .asset = (unsigned char[33]){0x01, 0x23, 0x0f, 0x4f, 0x5d, 0x4b, 0x7c, 0x6f, 0xa8, 0x45, 0x80, 0x6e, 0xe4, 0xf6, 0x77, 0x13, 0x45, 0x9e, 0x1b, 0x69, 0xe8, 0xe6, 0x0f, 0xce, 0xe2, 0xe4, 0x94, 0x0c, 0x7a, 0x0d, 0x5d, 0xe1, 0xb2}
, .value = (unsigned char[9]){0x01, 0x00, 0x00, 0x00, 0x02, 0x54, 0x0b, 0xe4, 0x00}
, .scriptPubKey = {0}
} } }
, .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"}
{ { .asset = (unsigned char[33]){0x01, 0x23, 0x0f, 0x4f, 0x5d, 0x4b, 0x7c, 0x6f, 0xa8, 0x45, 0x80, 0x6e, 0xe4, 0xf6, 0x77, 0x13, 0x45, 0x9e, 0x1b, 0x69, 0xe8, 0xe6, 0x0f, 0xce, 0xe2, 0xe4, 0x94, 0x0c, 0x7a, 0x0d, 0x5d, 0xe1, 0xb2}
, .value = (unsigned char[9]){0x01, 0x00, 0x00, 0x00, 0x02, 0x54, 0x0b, 0xd7, 0x1c}
, .nonce = NULL
, .scriptPubKey = { .buf = (unsigned char [26]){"\x19\x76\xa9\x14\x48\x63\x3e\x2c\x0e\xe9\x49\x5d\xd3\xf9\xc4\x37\x32\xc4\x7f\x47\x02\xa3\x62\xc8\x88\xac"}
, .scriptPubKey = { .buf = (unsigned char [26]){0x19, 0x76, 0xa9, 0x14, 0x48, 0x63, 0x3e, 0x2c, 0x0e, 0xe9, 0x49, 0x5d, 0xd3, 0xf9, 0xc4, 0x37, 0x32, 0xc4, 0x7f, 0x47, 0x02, 0xa3, 0x62, 0xc8, 0x88, 0xac}
, .len = 26
}
}
, { .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\x00\x00\x00\x0c\xe4"}
, { .asset = (unsigned char[33]){0x01, 0x23, 0x0f, 0x4f, 0x5d, 0x4b, 0x7c, 0x6f, 0xa8, 0x45, 0x80, 0x6e, 0xe4, 0xf6, 0x77, 0x13, 0x45, 0x9e, 0x1b, 0x69, 0xe8, 0xe6, 0x0f, 0xce, 0xe2, 0xe4, 0x94, 0x0c, 0x7a, 0x0d, 0x5d, 0xe1, 0xb2}
, .value = (unsigned char[9]){0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xe4}
, .nonce = NULL
, .scriptPubKey = {0}
} }
@ -462,26 +462,26 @@ static void test_elements(void) {
/* test a modified transaction with the same signature. */
{
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"}
{ .txid = (unsigned char[32]){0xdb, 0x9a, 0x3d, 0xe0, 0xb6, 0xb8, 0xcc, 0x74, 0x1e, 0x4d, 0x6c, 0x8f, 0x19, 0xce, 0x75, 0xec, 0x0d, 0xfd, 0x01, 0x02, 0xdb, 0x9c, 0xb5, 0xcd, 0x27, 0xa4, 0x1a, 0x66, 0x91, 0x66, 0x3a, 0x07}
, .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"}
{ { .prevTxid = (unsigned char[32]){0xeb, 0x04, 0xb6, 0x8e, 0x9a, 0x26, 0xd1, 0x16, 0x04, 0x6c, 0x76, 0xe8, 0xff, 0x47, 0x33, 0x2f, 0xb7, 0x1d, 0xda, 0x90, 0xff, 0x4b, 0xef, 0x53, 0x70, 0xf2, 0x52, 0x26, 0xd3, 0xbc, 0x09, 0xfc}
, .prevIx = 0
, .sequence = 0xffffffff /* Here is the modification. */
, .issuance = {0}
, .txo = { .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\xe4\x00"}
, .txo = { .asset = (unsigned char[33]){0x01, 0x23, 0x0f, 0x4f, 0x5d, 0x4b, 0x7c, 0x6f, 0xa8, 0x45, 0x80, 0x6e, 0xe4, 0xf6, 0x77, 0x13, 0x45, 0x9e, 0x1b, 0x69, 0xe8, 0xe6, 0x0f, 0xce, 0xe2, 0xe4, 0x94, 0x0c, 0x7a, 0x0d, 0x5d, 0xe1, 0xb2}
, .value = (unsigned char[9]){0x01, 0x00, 0x00, 0x00, 0x02, 0x54, 0x0b, 0xe4, 0x00}
, .scriptPubKey = {0}
} } }
, .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"}
{ { .asset = (unsigned char[33]){0x01, 0x23, 0x0f, 0x4f, 0x5d, 0x4b, 0x7c, 0x6f, 0xa8, 0x45, 0x80, 0x6e, 0xe4, 0xf6, 0x77, 0x13, 0x45, 0x9e, 0x1b, 0x69, 0xe8, 0xe6, 0x0f, 0xce, 0xe2, 0xe4, 0x94, 0x0c, 0x7a, 0x0d, 0x5d, 0xe1, 0xb2}
, .value = (unsigned char[9]){0x01, 0x00, 0x00, 0x00, 0x02, 0x54, 0x0b, 0xd7, 0x1c}
, .nonce = NULL
, .scriptPubKey = { .buf = (unsigned char [26]){"\x19\x76\xa9\x14\x48\x63\x3e\x2c\x0e\xe9\x49\x5d\xd3\xf9\xc4\x37\x32\xc4\x7f\x47\x02\xa3\x62\xc8\x88\xac"}
, .scriptPubKey = { .buf = (unsigned char [26]){0x19, 0x76, 0xa9, 0x14, 0x48, 0x63, 0x3e, 0x2c, 0x0e, 0xe9, 0x49, 0x5d, 0xd3, 0xf9, 0xc4, 0x37, 0x32, 0xc4, 0x7f, 0x47, 0x02, 0xa3, 0x62, 0xc8, 0x88, 0xac}
, .len = 26
}
}
, { .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\x00\x00\x00\x0c\xe4"}
, { .asset = (unsigned char[33]){0x01, 0x23, 0x0f, 0x4f, 0x5d, 0x4b, 0x7c, 0x6f, 0xa8, 0x45, 0x80, 0x6e, 0xe4, 0xf6, 0x77, 0x13, 0x45, 0x9e, 0x1b, 0x69, 0xe8, 0xe6, 0x0f, 0xce, 0xe2, 0xe4, 0x94, 0x0c, 0x7a, 0x0d, 0x5d, 0xe1, 0xb2}
, .value = (unsigned char[9]){0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xe4}
, .nonce = NULL
, .scriptPubKey = {0}
} }