#include "bitcoinJets.h"
#include "ops.h"
#include "txEnv.h"
#include "../taptweak.h"
#include "../simplicity_assert.h"
static void readHash(sha256_midstate* h, frameItem *src) {
read32s(h->s, 8, src);
}
static void writeHash(frameItem* dst, const sha256_midstate* h) {
write32s(dst, h->s, 8);
}
static void prevOutpoint(frameItem* dst, const outpoint* op) {
writeHash(dst, &op->txid);
rustsimplicity_0_7_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) {
rustsimplicity_0_7_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) {
rustsimplicity_0_7_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;
}
}
bool rustsimplicity_0_7_bitcoin_version(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write32(dst, env->tx->version);
return true;
}
bool rustsimplicity_0_7_bitcoin_lock_time(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write32(dst, env->tx->lockTime);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_prev_outpoint(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
prevOutpoint(dst, &env->tx->input[i].prevOutpoint);
} else {
skipBits(dst, 288);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_input_value(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
rustsimplicity_0_7_write64(dst, env->tx->input[i].txo.value);
} else {
skipBits(dst, 64);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_input_script_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
writeHash(dst, &env->tx->input[i].txo.scriptPubKey);
} else {
skipBits(dst, 256);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_input_sequence(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
rustsimplicity_0_7_write32(dst, env->tx->input[i].sequence);
} else {
skipBits(dst, 32);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_input_annex_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_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;
}
bool rustsimplicity_0_7_bitcoin_input_script_sig_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_read32(&src);
if (writeBit(dst, i < env->tx->numInputs)) {
writeHash(dst, &env->tx->input[i].scriptSigHash);
} else {
skipBits(dst, 256);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_output_value(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_read32(&src);
if (writeBit(dst, i < env->tx->numOutputs)) {
rustsimplicity_0_7_write64(dst, env->tx->output[i].value);
} else {
skipBits(dst, 64);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_output_script_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_read32(&src);
if (writeBit(dst, i < env->tx->numOutputs)) {
writeHash(dst, &env->tx->output[i].scriptPubKey);
} else {
skipBits(dst, 256);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_fee(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write64(dst, env->tx->totalInputValue - env->tx->totalOutputValue);
return true;
}
bool rustsimplicity_0_7_bitcoin_total_input_value(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write64(dst, env->tx->totalInputValue);
return true;
}
bool rustsimplicity_0_7_bitcoin_total_output_value(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write64(dst, env->tx->totalOutputValue);
return true;
}
bool rustsimplicity_0_7_bitcoin_script_cmr(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; write32s(dst, env->taproot->scriptCMR.s, 8);
return true;
}
bool rustsimplicity_0_7_bitcoin_transaction_id(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; write32s(dst, env->tx->txid.s, 8);
return true;
}
bool rustsimplicity_0_7_bitcoin_current_index(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write32(dst, env->ix);
return true;
}
bool rustsimplicity_0_7_bitcoin_current_prev_outpoint(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; if (env->tx->numInputs <= env->ix) return false;
prevOutpoint(dst, &env->tx->input[env->ix].prevOutpoint);
return true;
}
bool rustsimplicity_0_7_bitcoin_current_value(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; if (env->tx->numInputs <= env->ix) return false;
rustsimplicity_0_7_write64(dst, env->tx->input[env->ix].txo.value);
return true;
}
bool rustsimplicity_0_7_bitcoin_current_script_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; if (env->tx->numInputs <= env->ix) return false;
writeHash(dst, &env->tx->input[env->ix].txo.scriptPubKey);
return true;
}
bool rustsimplicity_0_7_bitcoin_current_sequence(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; if (env->tx->numInputs <= env->ix) return false;
rustsimplicity_0_7_write32(dst, env->tx->input[env->ix].sequence);
return true;
}
bool rustsimplicity_0_7_bitcoin_current_script_sig_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; if (env->tx->numInputs <= env->ix) return false;
writeHash(dst, &env->tx->input[env->ix].scriptSigHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_current_annex_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; 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;
}
bool rustsimplicity_0_7_bitcoin_tapleaf_version(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write8(dst, env->taproot->leafVersion);
return true;
}
bool rustsimplicity_0_7_bitcoin_tappath(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast8_t i = rustsimplicity_0_7_read8(&src);
if (writeBit(dst, i < env->taproot->pathLen)) {
writeHash(dst, &env->taproot->path[i]);
} else {
skipBits(dst, 256);
}
return true;
}
bool rustsimplicity_0_7_bitcoin_internal_key(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->taproot->internalKey);
return true;
}
bool rustsimplicity_0_7_bitcoin_num_inputs(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write32(dst, env->tx->numInputs);
return true;
}
bool rustsimplicity_0_7_bitcoin_num_outputs(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write32(dst, env->tx->numOutputs);
return true;
}
bool rustsimplicity_0_7_bitcoin_tx_is_final(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeBit(dst, env->tx->isFinal);
return true;
}
bool rustsimplicity_0_7_bitcoin_tx_lock_height(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write32(dst, lockHeight(env->tx));
return true;
}
bool rustsimplicity_0_7_bitcoin_tx_lock_time(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; rustsimplicity_0_7_write32(dst, lockTime(env->tx));
return true;
}
bool rustsimplicity_0_7_bitcoin_tx_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; if (env->tx->numInputs <= env->ix) return false;
rustsimplicity_0_7_write16(dst, lockDistance(env->tx, env->ix));
return true;
}
bool rustsimplicity_0_7_bitcoin_tx_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; if (env->tx->numInputs <= env->ix) return false;
rustsimplicity_0_7_write16(dst, lockDuration(env->tx, env->ix));
return true;
}
bool rustsimplicity_0_7_bitcoin_check_lock_height(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; uint_fast32_t x = rustsimplicity_0_7_read32(&src);
return x <= lockHeight(env->tx);
}
bool rustsimplicity_0_7_bitcoin_check_lock_time(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; uint_fast32_t x = rustsimplicity_0_7_read32(&src);
return x <= lockTime(env->tx);
}
bool rustsimplicity_0_7_bitcoin_check_lock_distance(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; if (env->tx->numInputs <= env->ix) return false;
uint_fast16_t x = rustsimplicity_0_7_read16(&src);
return x <= lockDistance(env->tx, env->ix);
}
bool rustsimplicity_0_7_bitcoin_check_lock_duration(frameItem* dst, frameItem src, const txEnv* env) {
(void) dst; if (env->tx->numInputs <= env->ix) return false;
uint_fast16_t x = rustsimplicity_0_7_read16(&src);
return x <= lockDuration(env->tx, env->ix);
}
bool rustsimplicity_0_7_bitcoin_build_tapleaf_simplicity(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; sha256_midstate cmr;
readHash(&cmr, &src);
sha256_midstate result = rustsimplicity_0_7_bitcoin_make_tapleaf(0xbe, &cmr);
writeHash(dst, &result);
return true;
}
bool rustsimplicity_0_7_bitcoin_build_tapbranch(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; sha256_midstate a, b;
readHash(&a, &src);
readHash(&b, &src);
sha256_midstate result = rustsimplicity_0_7_bitcoin_make_tapbranch(&a, &b);
writeHash(dst, &result);
return true;
}
bool rustsimplicity_0_7_bitcoin_build_taptweak(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; static unsigned char taptweak[] = "TapTweak";
return rustsimplicity_0_7_generic_taptweak(dst, &src, taptweak, sizeof(taptweak)-1);
}
bool rustsimplicity_0_7_bitcoin_outpoint_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; sha256_midstate midstate;
unsigned char buf[36];
sha256_context ctx = {.output = midstate.s};
if (!rustsimplicity_0_7_read_sha256_context(&ctx, &src)) return false;
read8s(buf, 36, &src);
sha256_uchars(&ctx, buf, 36);
return rustsimplicity_0_7_write_sha256_context(dst, &ctx);
}
bool rustsimplicity_0_7_bitcoin_annex_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) env; sha256_midstate midstate;
unsigned char buf[32];
sha256_context ctx = {.output = midstate.s};
if (!rustsimplicity_0_7_read_sha256_context(&ctx, &src)) return false;
if (readBit(&src)) {
read8s(buf, 32, &src);
sha256_uchar(&ctx, 0x01);
sha256_uchars(&ctx, buf, 32);
} else {
sha256_uchar(&ctx, 0x00);
}
return rustsimplicity_0_7_write_sha256_context(dst, &ctx);
}
bool rustsimplicity_0_7_bitcoin_output_values_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->outputValuesHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_output_scripts_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->outputScriptsHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_outputs_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->outputsHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_output_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_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;
}
bool rustsimplicity_0_7_bitcoin_input_outpoints_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputOutpointsHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_values_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputValuesHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_scripts_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputScriptsHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_utxos_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputUTXOsHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_utxo_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_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;
}
bool rustsimplicity_0_7_bitcoin_input_sequences_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputSequencesHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_annexes_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputAnnexesHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_script_sigs_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputScriptSigsHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_inputs_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->inputsHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_input_hash(frameItem* dst, frameItem src, const txEnv* env) {
uint_fast32_t i = rustsimplicity_0_7_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;
}
bool rustsimplicity_0_7_bitcoin_tx_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->tx->txHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_tapleaf_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->taproot->tapLeafHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_tappath_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->taproot->tappathHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_tap_env_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->taproot->tapEnvHash);
return true;
}
bool rustsimplicity_0_7_bitcoin_sig_all_hash(frameItem* dst, frameItem src, const txEnv* env) {
(void) src; writeHash(dst, &env->sigAllHash);
return true;
}