From f77441d49cff09029c0191359f3223eaf6741659 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Thu, 27 May 2021 10:04:10 -0300 Subject: [PATCH] Fix scriptCode serialization and sighash test vectors (#2198) * Fix scriptCode serialization and sighash test vectors The scriptCode was being serialized without the compact size prefix, and the test vectors included the prefix in the script, which cancelled each other --- zebra-chain/src/transaction/sighash.rs | 10 +++++----- zebra-chain/src/transparent/address.rs | 6 +++--- zebra-chain/src/transparent/script.rs | 21 ++++++++++++++++++++- zebra-script/src/lib.rs | 22 +++++++++++----------- 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/zebra-chain/src/transaction/sighash.rs b/zebra-chain/src/transaction/sighash.rs index d635571f..8d65d14f 100644 --- a/zebra-chain/src/transaction/sighash.rs +++ b/zebra-chain/src/transaction/sighash.rs @@ -359,7 +359,7 @@ impl<'a> SigHasher<'a> { .as_ref() .expect("caller verifies input is not none"); - writer.write_all(&lock_script.0)?; + lock_script.zcash_serialize(&mut writer)?; Ok(()) } @@ -621,7 +621,7 @@ mod test { let transaction = ZIP143_2.zcash_deserialize_into::()?; let value = hex::decode("2f6e04963b4c0100")?.zcash_deserialize_into::>()?; - let lock_script = Script(hex::decode("0153")?); + let lock_script = Script::new(&hex::decode("53")?); let input_ind = 1; let hasher = SigHasher::new( @@ -782,7 +782,7 @@ mod test { let transaction = ZIP243_2.zcash_deserialize_into::()?; let value = hex::decode("adedf02996510200")?.zcash_deserialize_into::>()?; - let lock_script = Script(hex::decode("00")?); + let lock_script = Script::new(&[]); let input_ind = 1; let hasher = SigHasher::new( @@ -880,8 +880,8 @@ mod test { let transaction = ZIP243_3.zcash_deserialize_into::()?; let value = hex::decode("80f0fa0200000000")?.zcash_deserialize_into::>()?; - let lock_script = Script(hex::decode( - "1976a914507173527b4c3318a2aecd793bf1cfed705950cf88ac", + let lock_script = Script::new(&hex::decode( + "76a914507173527b4c3318a2aecd793bf1cfed705950cf88ac", )?); let input_ind = 0; diff --git a/zebra-chain/src/transparent/address.rs b/zebra-chain/src/transparent/address.rs index 6d70c4eb..7cc31ee7 100644 --- a/zebra-chain/src/transparent/address.rs +++ b/zebra-chain/src/transparent/address.rs @@ -177,7 +177,7 @@ impl ToAddressWithNetwork for Script { fn to_address(&self, network: Network) -> Address { Address::PayToScriptHash { network, - script_hash: Address::hash_payload(&self.0[..]), + script_hash: Address::hash_payload(self.as_raw_bytes()), } } } @@ -289,7 +289,7 @@ mod tests { fn empty_script_mainnet() { zebra_test::init(); - let script = Script(vec![0; 20]); + let script = Script::new(&[0u8; 20]); let t_addr = script.to_address(Network::Mainnet); @@ -300,7 +300,7 @@ mod tests { fn empty_script_testnet() { zebra_test::init(); - let script = Script(vec![0; 20]); + let script = Script::new(&[0; 20]); let t_addr = script.to_address(Network::Testnet); diff --git a/zebra-chain/src/transparent/script.rs b/zebra-chain/src/transparent/script.rs index 75d78484..6b7e9a18 100644 --- a/zebra-chain/src/transparent/script.rs +++ b/zebra-chain/src/transparent/script.rs @@ -12,7 +12,26 @@ use std::{fmt, io}; any(test, feature = "proptest-impl"), derive(proptest_derive::Arbitrary) )] -pub struct Script(pub Vec); +pub struct Script(Vec); + +impl Script { + /// Create a new Bitcoin script from its raw bytes. + /// The raw bytes must not contain the length prefix. + pub fn new(raw_bytes: &[u8]) -> Self { + Script(raw_bytes.to_vec()) + } + + /// Return the raw bytes of the script without the length prefix. + /// + /// # Correctness + /// + /// These raw bytes do not have a length prefix. + /// The Zcash serialization format requires a length prefix; use `zcash_serialize` + /// and `zcash_deserialize` to create byte data with a length prefix. + pub fn as_raw_bytes(&self) -> &[u8] { + &self.0 + } +} impl fmt::Debug for Script { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/zebra-script/src/lib.rs b/zebra-script/src/lib.rs index 28e82f51..b1a21868 100644 --- a/zebra-script/src/lib.rs +++ b/zebra-script/src/lib.rs @@ -100,7 +100,7 @@ impl CachedFfiTransaction { (input_index, previous_output): (u32, transparent::Output), ) -> Result<(), Error> { let transparent::Output { value, lock_script } = previous_output; - let script_pub_key: &[u8] = lock_script.0.as_ref(); + let script_pub_key: &[u8] = lock_script.as_raw_bytes(); let n_in = input_index as _; let script_ptr = script_pub_key.as_ptr(); @@ -201,7 +201,7 @@ mod tests { let amount = 212 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; let input_index = 0; let branch_id = Blossom @@ -224,7 +224,7 @@ mod tests { let amount = 211 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()[..]), }; let input_index = 0; let branch_id = Blossom @@ -257,14 +257,14 @@ mod tests { let amount = 212 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier.is_valid(branch_id, (input_index, output))?; let amount = 212 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier.is_valid(branch_id, (input_index, output))?; @@ -289,14 +289,14 @@ mod tests { let amount = 212 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier.is_valid(branch_id, (input_index, output))?; let amount = 211 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier .is_valid(branch_id, (input_index, output)) @@ -323,7 +323,7 @@ mod tests { let amount = 211 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier .is_valid(branch_id, (input_index, output)) @@ -332,7 +332,7 @@ mod tests { let amount = 212 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier.is_valid(branch_id, (input_index, output))?; @@ -357,7 +357,7 @@ mod tests { let amount = 211 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier .is_valid(branch_id, (input_index, output)) @@ -366,7 +366,7 @@ mod tests { let amount = 210 * coin; let output = transparent::Output { value: amount.try_into()?, - lock_script: transparent::Script(SCRIPT_PUBKEY.clone()), + lock_script: transparent::Script::new(&SCRIPT_PUBKEY.clone()), }; verifier .is_valid(branch_id, (input_index, output))