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))