diff --git a/goat/src/assert_scripts.rs b/goat/src/assert_scripts.rs index 153e3702..e06d56ef 100644 --- a/goat/src/assert_scripts.rs +++ b/goat/src/assert_scripts.rs @@ -1,4 +1,4 @@ -use crate::wots::{Wots, Wots64, Wots96}; +use crate::wots::{Wots, Wots96}; use bitvm::{signatures::WinternitzSecret, treepp::*}; use serde::{Deserialize, Serialize}; @@ -49,54 +49,17 @@ pub fn wrongly_challenged_hashlocks_script(hashlocks: &[LabelHash]) -> Script { } } -pub fn verify_prover_assert_script_512_wire( - prover_wots_pubkey: &::PublicKey, +pub fn verify_prover_assert_script_768_wire( + prover_wots_pubkey: &::PublicKey, ) -> Script { script! { - { Wots64::checksig_verify_and_clear_stack(prover_wots_pubkey) } + OP_DROP + { Wots96::checksig_verify_and_clear_stack(prover_wots_pubkey) } OP_TRUE } } -pub fn verify_verifier_assert_script_512_wire( - prover_wots_pubkey: &::PublicKey, - label_hashes: &[WireHash; 512], -) -> Script { - script! { - for byte_hashes in label_hashes.chunks(8).rev() { - for wire_hashes in byte_hashes.chunks(4).rev() { - { 0 } - for (bit_index, wire_hash) in wire_hashes.iter().enumerate().rev() { - OP_SWAP - OP_DUP - { label_hash_script() } - { wire_hash.true_label_hash.to_vec() } - OP_EQUAL - OP_IF - OP_DROP - { 1 << bit_index } - OP_ADD - OP_ELSE - { label_hash_script() } - { wire_hash.false_label_hash.to_vec() } - OP_EQUALVERIFY - OP_ENDIF - } - OP_TOALTSTACK - } - } - { Wots64::checksig_verify(prover_wots_pubkey) } - for _ in 0..(Wots64::MSG_BYTE_LEN * 2) { - OP_FROMALTSTACK - OP_EQUALVERIFY - } - OP_TRUE - } -} - -pub fn verify_prover_assert_script_768_wire( - prover_wots_pubkey: &::PublicKey, -) -> Script { +pub fn verify_prover_pubin_script(prover_wots_pubkey: &::PublicKey) -> Script { script! { { Wots96::checksig_verify_and_clear_stack(prover_wots_pubkey) } OP_TRUE @@ -143,67 +106,6 @@ mod tests { use bitvm::execute_script; use rand::RngCore; - #[test] - fn test_verify_verifier_assert_script_512_wire() { - let secret = Wots64::generate_secret_key(); - let public_key = Wots64::generate_public_key(&secret); - - let true_labels: Vec> = (0..512) - .map(|i| { - let mut label = vec![0x54; 20]; - label[0] = (i & 0xff) as u8; - label[1] = (i >> 8) as u8; - label - }) - .collect(); - let false_labels: Vec> = (0..512) - .map(|i| { - let mut label = vec![0x46; 20]; - label[0] = (i & 0xff) as u8; - label[1] = (i >> 8) as u8; - label - }) - .collect(); - - let mut msg: [u8; 64] = [0; 64]; - rand::thread_rng().fill_bytes(&mut msg); - - let mut bits = [false; 512]; - for i in 0..512 { - bits[i] = (msg[i / 8] >> (i % 8)) & 1 == 1; - } - - let label_hashes = std::array::from_fn(|i| WireHash { - true_label_hash: label_hash(&true_labels[i]), - false_label_hash: label_hash(&false_labels[i]), - }); - let selected_labels: Vec> = (0..512) - .map(|i| { - if bits[i] { - true_labels[i].clone() - } else { - false_labels[i].clone() - } - }) - .collect(); - - let s = script! { - { Wots64::sign_to_raw_witness(&secret, &msg) } - for wire_index in 0..512 { - { selected_labels[wire_index].clone() } - } - { verify_verifier_assert_script_512_wire(&public_key, &label_hashes) } - }; - println!("verifier assert full script size: {}", s.len()); - let result = execute_script(s); - println!( - "verifier assert max stack item size: {:?}", - result.stats.max_nb_stack_items - ); - assert!(result.success); - assert_eq!(result.final_stack.len(), 1); - } - #[test] fn test_wrongly_challenged_script_accepts_any_hashlock_preimage() { let labels = [ diff --git a/goat/src/connectors/connector_c.rs b/goat/src/connectors/connector_c.rs index 07bb3cbd..ecdb64c2 100644 --- a/goat/src/connectors/connector_c.rs +++ b/goat/src/connectors/connector_c.rs @@ -54,22 +54,28 @@ impl ConnectorC { &self, sk: &OperatorAssertSecretKey, proof: &[u8; 96], + extra_data: &[u8], ) -> Result>, Error> { let witness = Wots96::sign_to_raw_witness(sk, proof); let witness_script = script! { { witness.clone() } + { extra_data.to_vec() } }; let verification_script = witness_script.push_script(self.generate_taproot_leaf_1_script()); let exec_result = execute_script(verification_script); match exec_result.success { - true => Ok(witness.to_vec()), + true => { + let mut unlock_data = witness.to_vec(); + unlock_data.push(extra_data.to_vec()); + Ok(unlock_data) + } false => Err(Error::Other("Invalid WOTS secret-key for Connector-C.")), } } pub fn extract_leaf_1_raw_witness(&self, txin: &TxIn) -> Result { let witness = txin.witness.to_vec(); - if witness.len() != PROVER_SIG_LEN + 2 { + if witness.len() != PROVER_SIG_LEN + 3 { return Err(Error::Other( "Invalid witness length for Connector-C leaf 1.", )); diff --git a/goat/src/connectors/connector_e.rs b/goat/src/connectors/connector_e.rs index 4bd6b662..b536dd9a 100644 --- a/goat/src/connectors/connector_e.rs +++ b/goat/src/connectors/connector_e.rs @@ -1,7 +1,7 @@ use crate::{ assert_scripts::{ - verify_prover_assert_script_768_wire, OperatorCommitPubinPublicKey, - OperatorCommitPubinSecretKey, PROVER_SIG_LEN, + verify_prover_pubin_script, OperatorCommitPubinPublicKey, OperatorCommitPubinSecretKey, + PROVER_SIG_LEN, }, constants::TimelockConfig, utils::remove_script_and_control_block_from_witness, @@ -46,7 +46,7 @@ impl ConnectorE { } fn generate_taproot_leaf_0_script(&self) -> ScriptBuf { - verify_prover_assert_script_768_wire(&self.operator_commit_pubin_wots_public_key).compile() + verify_prover_pubin_script(&self.operator_commit_pubin_wots_public_key).compile() } fn generate_taproot_leaf_0_tx_in(&self, input: &Input) -> TxIn { diff --git a/goat/src/transactions/assert.rs b/goat/src/transactions/assert.rs index 623176ef..e77c6360 100644 --- a/goat/src/transactions/assert.rs +++ b/goat/src/transactions/assert.rs @@ -123,10 +123,11 @@ impl OperatorAssertTransaction { wots_sk: &OperatorAssertSecretKey, connector_c: &ConnectorC, proof: &[u8; 96], + extra_data: &[u8], ) -> Result<(), Error> { let input_index = 0; let leaf_index = 1; - match connector_c.generate_leaf_1_unlock_data(wots_sk, proof) { + match connector_c.generate_leaf_1_unlock_data(wots_sk, proof, extra_data) { Ok(wit) => { populate_taproot_input_witness( self.tx_mut(),