diff --git a/src/actor.rs b/src/actor.rs index e5cfc6d..5337ad1 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -1,13 +1,11 @@ use bitcoin::hashes::sha256; -use bitcoin::opcodes::all::*; use bitcoin::TapNodeHash; use bitcoin::{ hashes::Hash, - script::Builder, secp256k1::{ rand, schnorr::Signature, All, Keypair, Message, Secp256k1, SecretKey, XOnlyPublicKey, }, - Address, ScriptBuf, TapSighash, TapTweakHash, + Address, TapSighash, TapTweakHash, }; use rand::Rng; @@ -47,15 +45,6 @@ impl Actor { } } - pub fn generate_timelock_script(&self, block_count: u32) -> ScriptBuf { - Builder::new() - .push_int(block_count as i64) - .push_opcode(OP_CSV) - .push_x_only_key(&self.public_key) - .push_opcode(OP_CHECKSIG) - .into_script() - } - pub fn sign_with_tweak( &self, sighash: TapSighash, @@ -94,15 +83,6 @@ impl Actor { self.challenge_preimages.push(preimages); challenge_hashes } - - pub fn generate_challenge_script(&self, challenge_hash: &HashValue) -> ScriptBuf { - Builder::new() - .push_slice(challenge_hash) - .push_opcode(OP_EQUALVERIFY) - .push_x_only_key(&self.public_key) - .push_opcode(OP_CHECKSIG) - .into_script() - } } #[cfg(test)] diff --git a/src/circuit.rs b/src/circuit.rs index bf1d1f0..238b761 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -3,18 +3,11 @@ use std::collections::BTreeMap; use std::iter::zip; use std::rc::Rc; -use bitcoin::secp256k1::All; -use bitcoin::secp256k1::Secp256k1; -use bitcoin::taproot::TaprootSpendInfo; -use bitcoin::{Address, ScriptBuf}; - -use crate::actor::Actor; -use crate::utils::taproot_address_from_script_leaves; use crate::wire::HashTuple; -use crate::wire::HashValue; + use crate::{ gates::{AndGate, NotGate, XorGate}, - traits::{circuit::CircuitTrait, gate::GateTrait, wire::WireTrait}, + traits::gate::GateTrait, utils::read_lines, wire::Wire, }; @@ -28,27 +21,16 @@ pub struct Circuit { impl Default for Circuit { fn default() -> Self { - Self::new() + Self::from_bristol("bristol/test.txt") } } impl Circuit { - pub fn new() -> Self { - Circuit { - input_sizes: vec![32, 32], - output_sizes: vec![32], - gates: vec![Box::new(NotGate::new(vec![], vec![]))], - wires: vec![], - } - } -} - -impl CircuitTrait for Circuit { - fn num_gates(&self) -> usize { + pub fn num_gates(&self) -> usize { self.gates.len() } - fn evaluate(&mut self, inputs: Vec>) -> Vec> { + pub fn evaluate(&mut self, inputs: Vec>) -> Vec> { assert_eq!( inputs.len(), self.input_sizes.len(), @@ -84,7 +66,7 @@ impl CircuitTrait for Circuit { output } - fn get_wire_hashes(&self) -> Vec { + pub fn get_wire_hashes(&self) -> Vec { self.wires .iter() .map(|wire_rcref| { @@ -94,7 +76,7 @@ impl CircuitTrait for Circuit { .collect::>() } - fn from_bristol(file: &str) -> Self { + pub fn from_bristol(file: &str) -> Self { let mut nog: usize = 0; // number of gates let mut now: usize = 0; // number of wires let mut input_sizes = Vec::::new(); @@ -195,69 +177,26 @@ impl CircuitTrait for Circuit { .collect::>>>(), }; } - - fn generate_response_tree( - &self, - secp: &Secp256k1, - _prover: &Actor, - verifier: &Actor, - challenge_hashes: Vec, - ) -> (Address, TaprootSpendInfo) { - assert_eq!( - challenge_hashes.len(), - self.gates.len(), - "wrong number of challenge hashes" - ); - let mut scripts = self - .gates - .iter() - .zip(challenge_hashes.iter()) - .map(|(gate, hash)| gate.create_response_script(*hash)) - .collect::>(); - scripts.push(verifier.generate_timelock_script(10)); - taproot_address_from_script_leaves(secp, scripts) - } - - fn generate_challenge_tree( - &self, - secp: &Secp256k1, - prover: &Actor, - verifier: &Actor, - challenge_hashes: Vec, - ) -> (Address, TaprootSpendInfo) { - assert_eq!( - challenge_hashes.len(), - self.gates.len(), - "wrong number of challenge hashes" - ); - let mut scripts = challenge_hashes - .iter() - .map(|x| verifier.generate_challenge_script(x)) - .collect::>(); - // let mut reveal_challenge_scripts = - scripts.extend(self.wires.iter().map(|wire_rcref| { - wire_rcref - .try_borrow_mut() - .unwrap() - .generate_anti_contradiction_script(verifier.public_key) - })); - scripts.push(prover.generate_timelock_script(10)); - taproot_address_from_script_leaves(secp, scripts) - } } #[cfg(test)] mod tests { + use bitcoin::secp256k1::Secp256k1; use bitcoin::taproot::LeafVersion; use super::*; use crate::actor::Actor; use crate::utils::{bool_array_to_number, number_to_bool_array}; + use crate::transactions::{ + generate_anti_contradiction_script, generate_challenge_address_and_info, + generate_timelock_script, + }; + #[test] fn test_circuit() { - let circuit = Circuit::new(); - assert!(circuit.output_sizes[0] == 32); + let circuit = Circuit::default(); + assert!(circuit.output_sizes[0] == 1); } #[test] @@ -288,11 +227,17 @@ mod tests { let challenge_hashes = verifier.generate_challenge_hashes(circuit.num_gates()); - let (_address, tree_info) = - circuit.generate_challenge_tree(&secp, &prover, &verifier, challenge_hashes); + let (_address, tree_info) = generate_challenge_address_and_info( + &secp, + &circuit, + prover.public_key, + verifier.public_key, + challenge_hashes, + ); for wire_rcref in circuit.wires.iter() { let wire = wire_rcref.try_borrow_mut().unwrap(); - let script = wire.generate_anti_contradiction_script(verifier.public_key); + let script = + generate_anti_contradiction_script(wire.get_hash_pair(), verifier.public_key); let ctrl_block = tree_info .control_block(&(script.clone(), LeafVersion::TapScript)) .unwrap(); @@ -303,7 +248,7 @@ mod tests { )); } // TODO: add tests for reveral challenge scripts - let p10_script = prover.generate_timelock_script(10); + let p10_script = generate_timelock_script(prover.public_key, 10); let p10_ctrl_block = tree_info .control_block(&(p10_script.clone(), LeafVersion::TapScript)) .unwrap(); diff --git a/src/gates.rs b/src/gates.rs index 7fa8e03..02e908a 100644 --- a/src/gates.rs +++ b/src/gates.rs @@ -4,7 +4,7 @@ use bitcoin::opcodes::all::{ use bitcoin::script::Builder; use bitcoin::ScriptBuf; -use crate::traits::wire::WireTrait; +use crate::transactions::add_bit_commitment_script; use crate::wire::HashValue; use crate::{traits::gate::GateTrait, wire::Wire}; use std::cell::RefCell; @@ -40,15 +40,15 @@ impl GateTrait for NotGate { .push_opcode(OP_SHA256) .push_slice(lock_hash) .push_opcode(OP_EQUALVERIFY); - let builder = self.output_wires[0] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder) - .push_opcode(OP_TOALTSTACK); - let builder = self.input_wires[0] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder); + let builder = add_bit_commitment_script( + self.output_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ) + .push_opcode(OP_TOALTSTACK); + let builder = add_bit_commitment_script( + self.input_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ); builder .push_opcode(OP_NOT) .push_opcode(OP_FROMALTSTACK) @@ -87,20 +87,20 @@ impl GateTrait for AndGate { .push_opcode(OP_SHA256) .push_slice(lock_hash) .push_opcode(OP_EQUALVERIFY); - let builder = self.output_wires[0] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder) - .push_opcode(OP_TOALTSTACK); - let builder = self.input_wires[0] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder) - .push_opcode(OP_TOALTSTACK); - let builder = self.input_wires[1] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder); + let builder = add_bit_commitment_script( + self.output_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ) + .push_opcode(OP_TOALTSTACK); + let builder = add_bit_commitment_script( + self.input_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ) + .push_opcode(OP_TOALTSTACK); + let builder = add_bit_commitment_script( + self.input_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ); builder .push_opcode(OP_FROMALTSTACK) .push_opcode(OP_AND) @@ -140,20 +140,20 @@ impl GateTrait for XorGate { .push_opcode(OP_SHA256) .push_slice(lock_hash) .push_opcode(OP_EQUALVERIFY); - let builder = self.output_wires[0] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder) - .push_opcode(OP_TOALTSTACK); - let builder = self.input_wires[0] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder) - .push_opcode(OP_TOALTSTACK); - let builder = self.input_wires[1] - .try_borrow() - .unwrap() - .add_bit_commitment_script(builder); + let builder = add_bit_commitment_script( + self.output_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ) + .push_opcode(OP_TOALTSTACK); + let builder = add_bit_commitment_script( + self.input_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ) + .push_opcode(OP_TOALTSTACK); + let builder = add_bit_commitment_script( + self.input_wires[0].try_borrow().unwrap().get_hash_pair(), + builder, + ); builder .push_opcode(OP_FROMALTSTACK) .push_opcode(OP_XOR) diff --git a/src/lib.rs b/src/lib.rs index 89f0e94..ce1edc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,5 +3,6 @@ pub mod circuit; pub mod communication; pub mod gates; pub mod traits; +pub mod transactions; pub mod utils; pub mod wire; diff --git a/src/main.rs b/src/main.rs index 31383db..061e689 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,9 +9,11 @@ use bitcoin::{Amount, OutPoint, ScriptBuf, TapLeafHash, Transaction, TxIn, TxOut use bitcoincore_rpc::{Auth, Client, RpcApi}; use bitvm::actor::Actor; -use bitvm::traits::wire::WireTrait; -use bitvm::{circuit::Circuit, traits::circuit::CircuitTrait}; +use bitvm::circuit::Circuit; +use bitvm::transactions::{ + generate_anti_contradiction_script, generate_challenge_address_and_info, +}; use std::borrow::BorrowMut; @@ -71,8 +73,13 @@ fn main() { let challenge_hashes = vicky.generate_challenge_hashes(circuit.num_gates()); - let (address, kickoff_taproot_info) = - circuit.generate_challenge_tree(&secp, &paul, &vicky, challenge_hashes); + let (address, kickoff_taproot_info) = generate_challenge_address_and_info( + &secp, + &circuit, + paul.public_key, + vicky.public_key, + challenge_hashes, + ); let mut tx = Transaction { version: bitcoin::transaction::Version::TWO, @@ -128,7 +135,7 @@ fn main() { let vout: u32 = 0; - let script = wire.generate_anti_contradiction_script(vicky.public_key); + let script = generate_anti_contradiction_script(wire.get_hash_pair(), vicky.public_key); let mut tx = Transaction { version: bitcoin::transaction::Version::TWO, diff --git a/src/prover.rs b/src/prover.rs index f85a426..e64bd7d 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -4,7 +4,6 @@ use bitcoin::XOnlyPublicKey; use bitvm::{ circuit::Circuit, communication::{receive_message, send_message}, - traits::circuit::CircuitTrait, wire::HashTuple, }; diff --git a/src/traits/bit_commitment.rs b/src/traits/bit_commitment.rs deleted file mode 100644 index e6e336d..0000000 --- a/src/traits/bit_commitment.rs +++ /dev/null @@ -1 +0,0 @@ -pub trait BitCommitmentTrait {} diff --git a/src/traits/circuit.rs b/src/traits/circuit.rs deleted file mode 100644 index c8dc816..0000000 --- a/src/traits/circuit.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::{ - actor::Actor, - wire::{HashTuple, HashValue}, -}; -use bitcoin::{ - secp256k1::{All, Secp256k1}, - taproot::TaprootSpendInfo, - Address, -}; - -// This trait defines the behavior of a circuit. -pub trait CircuitTrait { - fn num_gates(&self) -> usize; - - fn evaluate(&mut self, inputs: Vec>) -> Vec>; - - fn get_wire_hashes(&self) -> Vec; - - fn from_bristol(file: &str) -> Self; - - fn generate_challenge_tree( - &self, - secp: &Secp256k1, - prover: &Actor, - verifier: &Actor, - challenge_hashes: Vec, - ) -> (Address, TaprootSpendInfo); - - fn generate_response_tree( - &self, - secp: &Secp256k1, - prover: &Actor, - verifier: &Actor, - challenge_hashes: Vec, - ) -> (Address, TaprootSpendInfo); -} diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 311a838..a468fa3 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -1,4 +1 @@ -pub mod bit_commitment; -pub mod circuit; pub mod gate; -pub mod wire; diff --git a/src/traits/wire.rs b/src/traits/wire.rs deleted file mode 100644 index a0e445e..0000000 --- a/src/traits/wire.rs +++ /dev/null @@ -1,9 +0,0 @@ -use bitcoin::{script::Builder, ScriptBuf, XOnlyPublicKey}; - -use crate::wire::HashTuple; - -pub trait WireTrait { - fn get_hash_pair(&self) -> HashTuple; - fn generate_anti_contradiction_script(&self, verifier_pk: XOnlyPublicKey) -> ScriptBuf; - fn add_bit_commitment_script(&self, builder: Builder) -> Builder; -} diff --git a/src/transactions.rs b/src/transactions.rs new file mode 100644 index 0000000..8e7f279 --- /dev/null +++ b/src/transactions.rs @@ -0,0 +1,140 @@ +use std::str::FromStr; + +use bitcoin::secp256k1::{All, Secp256k1}; +use bitcoin::taproot::{TaprootBuilder, TaprootSpendInfo}; +use bitcoin::{Address, ScriptBuf, XOnlyPublicKey}; + +use bitcoin::blockdata::script::Builder; +use bitcoin::opcodes::all::*; + +use crate::wire::{HashTuple, HashValue}; + +use crate::circuit::Circuit; + +pub fn taproot_address_from_script_leaves( + secp: &Secp256k1, + scripts: Vec, +) -> (Address, TaprootSpendInfo) { + let n = scripts.len(); + assert!(n > 1, "more than one script is required"); + let m: u8 = ((n - 1).ilog2() + 1) as u8; // m = ceil(log(n)) + let k = 2_usize.pow(m.into()) - n; + let taproot = (0..n).fold(TaprootBuilder::new(), |acc, i| { + acc.add_leaf(m - ((i >= n - k) as u8), scripts[i].clone()) + .unwrap() + }); + let internal_key = XOnlyPublicKey::from_str( + "93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51", + ) + .unwrap(); + let tree_info = taproot.finalize(secp, internal_key).unwrap(); + let address = Address::p2tr( + secp, + internal_key, + tree_info.merkle_root(), + bitcoin::Network::Regtest, + ); + (address, tree_info) +} + +pub fn generate_response_address_and_info( + secp: &Secp256k1, + circuit: &Circuit, + verifier_pk: XOnlyPublicKey, + challenge_hashes: Vec, +) -> (Address, TaprootSpendInfo) { + assert_eq!( + challenge_hashes.len(), + circuit.gates.len(), + "wrong number of challenge hashes" + ); + let mut scripts = circuit + .gates + .iter() + .zip(challenge_hashes.iter()) + .map(|(gate, hash)| gate.create_response_script(*hash)) + .collect::>(); + scripts.push(generate_timelock_script(verifier_pk, 10)); + taproot_address_from_script_leaves(secp, scripts) +} + +pub fn generate_challenge_address_and_info( + secp: &Secp256k1, + circuit: &Circuit, + prover_pk: XOnlyPublicKey, + verifier_pk: XOnlyPublicKey, + challenge_hashes: Vec, +) -> (Address, TaprootSpendInfo) { + assert_eq!( + challenge_hashes.len(), + circuit.gates.len(), + "wrong number of challenge hashes" + ); + let mut scripts = challenge_hashes + .iter() + .map(|x| generate_challenge_script(prover_pk, verifier_pk, x)) + .collect::>(); + // let mut reveal_challenge_scripts = + scripts.extend(circuit.wires.iter().map(|wire_rcref| { + generate_anti_contradiction_script( + wire_rcref.try_borrow_mut().unwrap().get_hash_pair(), + verifier_pk, + ) + })); + scripts.push(generate_timelock_script(prover_pk, 10)); + taproot_address_from_script_leaves(secp, scripts) +} + +pub fn generate_anti_contradiction_script( + wire_bit_hashes: HashTuple, + verifier_pk: XOnlyPublicKey, +) -> ScriptBuf { + Builder::new() + .push_opcode(OP_SHA256) + .push_slice(wire_bit_hashes.zero) + .push_opcode(OP_EQUALVERIFY) + .push_opcode(OP_SHA256) + .push_slice(wire_bit_hashes.one) + .push_opcode(OP_EQUALVERIFY) + .push_x_only_key(&verifier_pk) + .push_opcode(OP_CHECKSIG) + .into_script() +} + +pub fn add_bit_commitment_script(wire_bit_hashes: HashTuple, builder: Builder) -> Builder { + builder + .push_opcode(OP_SHA256) + .push_opcode(OP_DUP) + .push_slice(wire_bit_hashes.one) + .push_opcode(OP_EQUAL) + .push_opcode(OP_DUP) + .push_opcode(OP_ROT) + .push_slice(wire_bit_hashes.zero) + .push_opcode(OP_EQUAL) + .push_opcode(OP_BOOLOR) + .push_opcode(OP_VERIFY) +} + +pub fn generate_challenge_script( + prover_pk: XOnlyPublicKey, + verifier_pk: XOnlyPublicKey, + challenge_hash: &HashValue, +) -> ScriptBuf { + Builder::new() + .push_slice(challenge_hash) + .push_opcode(OP_EQUALVERIFY) + .push_x_only_key(&prover_pk) + .push_opcode(OP_CHECKSIGVERIFY) + .push_x_only_key(&verifier_pk) + .push_opcode(OP_CHECKSIG) + .into_script() +} + +pub fn generate_timelock_script(actor_pk: XOnlyPublicKey, block_count: u32) -> ScriptBuf { + Builder::new() + .push_int(block_count as i64) + .push_opcode(OP_CSV) + .push_x_only_key(&actor_pk) + .push_opcode(OP_CHECKSIG) + .into_script() +} diff --git a/src/utils.rs b/src/utils.rs index 46d42a2..0ac82dd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,11 +1,6 @@ use std::fs::File; use std::io::{self, BufRead, Write}; use std::path::Path; -use std::str::FromStr; - -use bitcoin::secp256k1::{All, Secp256k1}; -use bitcoin::taproot::{TaprootBuilder, TaprootSpendInfo}; -use bitcoin::{Address, ScriptBuf, XOnlyPublicKey}; pub fn read_lines

(filename: P) -> io::Result>> where @@ -73,29 +68,3 @@ pub fn bool_array_to_hex_string(bool_array: Vec) -> String { } v.into_iter().collect::() } - -pub fn taproot_address_from_script_leaves( - secp: &Secp256k1, - scripts: Vec, -) -> (Address, TaprootSpendInfo) { - let n = scripts.len(); - assert!(n > 1, "more than one script is required"); - let m: u8 = ((n - 1).ilog2() + 1) as u8; // m = ceil(log(n)) - let k = 2_usize.pow(m.into()) - n; - let taproot = (0..n).fold(TaprootBuilder::new(), |acc, i| { - acc.add_leaf(m - ((i >= n - k) as u8), scripts[i].clone()) - .unwrap() - }); - let internal_key = XOnlyPublicKey::from_str( - "93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51", - ) - .unwrap(); - let tree_info = taproot.finalize(secp, internal_key).unwrap(); - let address = Address::p2tr( - secp, - internal_key, - tree_info.merkle_root(), - bitcoin::Network::Regtest, - ); - (address, tree_info) -} diff --git a/src/wire.rs b/src/wire.rs index 6e5e8a1..3bacb8a 100644 --- a/src/wire.rs +++ b/src/wire.rs @@ -1,12 +1,7 @@ use std::fmt::Debug; -use crate::traits::wire::WireTrait; -use bitcoin::blockdata::script::Builder; use bitcoin::hashes::sha256; use bitcoin::hashes::Hash; -use bitcoin::opcodes::all::*; -use bitcoin::ScriptBuf; -use bitcoin::XOnlyPublicKey; use rand::Rng; use serde::Deserialize; use serde::Serialize; @@ -69,49 +64,15 @@ impl Wire { index: Some(index), } } -} -impl WireTrait for Wire { - fn get_hash_pair(&self) -> HashTuple { + pub fn get_hash_pair(&self) -> HashTuple { self.hashes } - - fn generate_anti_contradiction_script(&self, verifier_pk: XOnlyPublicKey) -> ScriptBuf { - Builder::new() - .push_opcode(OP_SHA256) - .push_slice(self.hashes.zero) - .push_opcode(OP_EQUALVERIFY) - .push_opcode(OP_SHA256) - .push_slice(self.hashes.one) - .push_opcode(OP_EQUALVERIFY) - .push_x_only_key(&verifier_pk) - .push_opcode(OP_CHECKSIG) - .into_script() - } - - fn add_bit_commitment_script(&self, builder: Builder) -> Builder { - builder - .push_opcode(OP_SHA256) - .push_opcode(OP_DUP) - .push_slice(self.hashes.one) - .push_opcode(OP_EQUAL) - .push_opcode(OP_DUP) - .push_opcode(OP_ROT) - .push_slice(self.hashes.zero) - .push_opcode(OP_EQUAL) - .push_opcode(OP_BOOLOR) - .push_opcode(OP_VERIFY) - } } #[cfg(test)] mod tests { use super::*; - use bitcoin::secp256k1::Secp256k1; - use bitcoin::TapLeafHash; - use bitcoin::Transaction; - use bitcoin_scriptexec::*; - use rand::thread_rng; #[test] fn test_wire() { @@ -119,49 +80,4 @@ mod tests { assert!(wire.preimages.is_some()); assert!(wire.selector.is_none()); } - - #[test] - fn test_generate_anti_contradiction_script() { - let wire = Wire::new(0); - let secp = Secp256k1::new(); - let mut rng = thread_rng(); - let (_sk, pk) = secp.generate_keypair(&mut rng); - let verifier_pk = XOnlyPublicKey::from(pk); - let script = wire.generate_anti_contradiction_script(verifier_pk); - - let preimages_vec = if let Some(preimages) = wire.preimages { - vec![preimages.one.to_vec(), preimages.zero.to_vec()] - } else { - panic!("wire preimages are None") - }; - - let mut exec = Exec::new( - ExecCtx::Tapscript, - Options::default(), - TxTemplate { - tx: Transaction { - version: bitcoin::transaction::Version::TWO, - lock_time: bitcoin::locktime::absolute::LockTime::ZERO, - input: vec![], - output: vec![], - }, - prevouts: vec![], - input_idx: 0, - taproot_annex_scriptleaf: Some((TapLeafHash::all_zeros(), None)), - }, - script, - preimages_vec, - ) - .expect("error creating exec"); - - loop { - if exec.exec_next().is_err() { - break; - } - } - - let res = exec.result().unwrap().clone(); - - assert_eq!(res.error, None); - } }