diff --git a/src/script/interface_ops.rs b/src/script/interface_ops.rs index 7b9875b..ba2179c 100644 --- a/src/script/interface_ops.rs +++ b/src/script/interface_ops.rs @@ -601,7 +601,7 @@ pub fn op_cat(stack: &mut Stack) -> bool { error_item_size(op); return false; } - let cat = [s1, s2].join(""); + let cat = [s1, s2].concat(); stack.push(StackEntry::Bytes(cat)) } @@ -648,6 +648,10 @@ pub fn op_substr(stack: &mut Stack) -> bool { return false; } }; + // TODO: As this was previously a hex string, the indices don't exactly correspond to what + // they did originally. However, I don't think there are any existing transactions + // on the chain which actually use this opcode, so I'm fairly confident it won't + // matter. Double-check that this is the case before merging! if n1 >= s.len() { error_item_index(op); return false; @@ -660,7 +664,7 @@ pub fn op_substr(stack: &mut Stack) -> bool { error_item_index(op); return false; } - let substr = s[n1..n1 + n2].to_string(); + let substr = s[n1..n1 + n2].to_vec(); stack.push(StackEntry::Bytes(substr)) } @@ -700,7 +704,11 @@ pub fn op_left(stack: &mut Stack) -> bool { if n >= s.len() { stack.push(StackEntry::Bytes(s)) } else { - let left = s[..n].to_string(); + // TODO: As this was previously a hex string, the indices don't exactly correspond to what + // they did originally. However, I don't think there are any existing transactions + // on the chain which actually use this opcode, so I'm fairly confident it won't + // matter. Double-check that this is the case before merging! + let left = s[..n].to_vec(); stack.push(StackEntry::Bytes(left)) } } @@ -739,9 +747,13 @@ pub fn op_right(stack: &mut Stack) -> bool { } }; if n >= s.len() { - stack.push(StackEntry::Bytes("".to_string())) + stack.push(StackEntry::Bytes(Vec::new())) } else { - let right = s[n..].to_string(); + // TODO: As this was previously a hex string, the indices don't exactly correspond to what + // they did originally. However, I don't think there are any existing transactions + // on the chain which actually use this opcode, so I'm fairly confident it won't + // matter. Double-check that this is the case before merging! + let right = s[n..].to_vec(); stack.push(StackEntry::Bytes(right)) } } @@ -756,8 +768,8 @@ pub fn op_right(stack: &mut Stack) -> bool { pub fn op_size(stack: &mut Stack) -> bool { let (op, desc) = (OPSIZE, OPSIZE_DESC); trace(op, desc); - let s = match stack.last() { - Some(StackEntry::Bytes(s)) => s, + let len = match stack.last() { + Some(StackEntry::Bytes(s)) => s.len(), Some(_) => { error_item_type(op); return false; @@ -767,7 +779,11 @@ pub fn op_size(stack: &mut Stack) -> bool { return false; } }; - stack.push(StackEntry::Num(s.len())) + // TODO: As this was previously a hex string, the length doesn't exactly correspond to what + // it did originally. However, I don't think there are any existing transactions + // on the chain which actually use this opcode, so I'm fairly confident it won't + // matter. Double-check that this is the case before merging! + stack.push(StackEntry::Num(len)) } /*---- BITWISE LOGIC OPS ----*/ @@ -1924,7 +1940,11 @@ pub fn op_sha3(stack: &mut Stack) -> bool { let data = match stack.pop() { Some(StackEntry::Signature(sig)) => sig.as_ref().to_owned(), Some(StackEntry::PubKey(pk)) => pk.as_ref().to_owned(), - Some(StackEntry::Bytes(s)) => s.as_bytes().to_owned(), + Some(StackEntry::Bytes(s)) => { + // For legacy reasons, the hashed data is the hex representation of the data rather than + // the data itself. + hex::encode(&s).as_bytes().to_owned() + }, Some(_) => { error_item_type(op); return false; @@ -1934,7 +1954,8 @@ pub fn op_sha3(stack: &mut Stack) -> bool { return false; } }; - let hash = hex::encode(sha3_256::digest(&data)); + let hash = sha3_256::digest(&data).to_vec(); + // TODO: Originally, the hash was converted back to hex! stack.push(StackEntry::Bytes(hash)) } @@ -1960,7 +1981,7 @@ pub fn op_hash256(stack: &mut Stack) -> bool { } }; let addr = construct_address(&pk); - stack.push(StackEntry::Bytes(addr)) + stack.push(StackEntry::Bytes(hex::decode(addr).unwrap())) } /// OP_HASH256_V0: Creates v0 address from public key and pushes it onto the stack @@ -1989,7 +2010,7 @@ pub fn op_hash256_v0(stack: &mut Stack) -> bool { } }; let addr_v0 = construct_address_v0(&pk); - stack.push(StackEntry::Bytes(addr_v0)) + stack.push(StackEntry::Bytes(hex::decode(addr_v0).unwrap())) } /// OP_HASH256_TEMP: Creates temporary address from public key and pushes it onto the stack @@ -2018,7 +2039,7 @@ pub fn op_hash256_temp(stack: &mut Stack) -> bool { } }; let addr_temp = construct_address_temp(&pk); - stack.push(StackEntry::Bytes(addr_temp)) + stack.push(StackEntry::Bytes(hex::decode(addr_temp).unwrap())) } /// OP_CHECKSIG: Pushes ONE onto the stack if the signature is valid, ZERO otherwise @@ -2067,8 +2088,13 @@ pub fn op_checksig(stack: &mut Stack) -> bool { return false; } }; - trace!("Signature: {:?}", hex::encode(sig)); - if (!sign::verify_detached(&sig, msg.as_bytes(), &pk)) { + + // For legacy reasons, the signed message is the hex representation of the message rather than + // the message itself. + let msg_hex = hex::encode(msg); + + trace!("Signature: {:?}", msg_hex); + if (!sign::verify_detached(&sig, msg_hex.as_bytes(), &pk)) { trace!("Signature verification failed"); stack.push(StackEntry::Num(ZERO)) } else { @@ -2121,8 +2147,13 @@ pub fn op_checksigverify(stack: &mut Stack) -> bool { return false; } }; - trace!("Signature: {:?}", hex::encode(sig)); - if (!sign::verify_detached(&sig, msg.as_bytes(), &pk)) { + + // For legacy reasons, the signed message is the hex representation of the message rather than + // the message itself. + let msg_hex = hex::encode(msg); + + trace!("Signature: {:?}", msg_hex); + if (!sign::verify_detached(&sig, msg_hex.as_bytes(), &pk)) { trace!("Signature verification failed"); error_invalid_signature(op); return false; @@ -2298,13 +2329,17 @@ pub fn op_checkmultisigverify(stack: &mut Stack) -> bool { /// * `sigs` - signatures to verify /// * `msg` - data to verify against /// * `pks` - public keys to match against -fn verify_multisig(sigs: &[Signature], msg: &String, pks: &mut Vec) -> bool { +fn verify_multisig(sigs: &[Signature], msg: &[u8], pks: &mut Vec) -> bool { + // For legacy reasons, the signed message is the hex representation of the message rather than + // the message itself. + let msg_hex = hex::encode(msg); + let mut num_valid_sigs = ZERO; for sig in sigs { if let Some((index, _)) = pks .iter() .enumerate() - .find(|(_, pk)| sign::verify_detached(sig, msg.as_bytes(), pk)) + .find(|(_, pk)| sign::verify_detached(sig, msg_hex.as_bytes(), pk)) { num_valid_sigs += ONE; pks.remove(index); diff --git a/src/script/lang.rs b/src/script/lang.rs index 259465e..4ee2014 100644 --- a/src/script/lang.rs +++ b/src/script/lang.rs @@ -10,7 +10,6 @@ use crate::utils::error_utils::*; use crate::utils::transaction_utils::{construct_address, construct_address_for}; use bincode::serialize; use bytes::Bytes; -use hex::encode; use serde::{Deserialize, Serialize}; use tracing::{error, warn}; @@ -375,7 +374,7 @@ impl Script { StackEntry::Op(OpCodes::OP_CREATE), StackEntry::Num(block_number as usize), StackEntry::Op(OpCodes::OP_DROP), - StackEntry::Bytes(asset_hash), + StackEntry::Bytes(hex::decode(asset_hash).expect("asset_hash contains non-hex characters")), StackEntry::Signature(signature), StackEntry::PubKey(pub_key), StackEntry::Op(OpCodes::OP_CHECKSIG), @@ -391,7 +390,7 @@ impl Script { /// * `signature` - Signature of check data /// * `pub_key` - Public key of the payer pub fn pay2pkh( - check_data: String, + check_data: Vec, signature: Signature, pub_key: PublicKey, address_version: Option, @@ -407,7 +406,8 @@ impl Script { StackEntry::PubKey(pub_key), StackEntry::Op(OpCodes::OP_DUP), StackEntry::Op(op_hash_256), - StackEntry::Bytes(construct_address_for(&pub_key, address_version)), + StackEntry::Bytes(hex::decode(construct_address_for(&pub_key, address_version)) + .expect("address contains non-hex characters?")), StackEntry::Op(OpCodes::OP_EQUALVERIFY), StackEntry::Op(OpCodes::OP_CHECKSIG), ]; @@ -421,7 +421,7 @@ impl Script { /// * `check_data` - Data to be signed for verification /// * `pub_key` - Public key of this party /// * `signature` - Signature of this party - pub fn member_multisig(check_data: String, pub_key: PublicKey, signature: Signature) -> Self { + pub fn member_multisig(check_data: Vec, pub_key: PublicKey, signature: Signature) -> Self { let stack = vec![ StackEntry::Bytes(check_data), StackEntry::Signature(signature), @@ -439,7 +439,7 @@ impl Script { /// * `n` - Number of valid signatures total /// * `check_data` - Data to have checked against signatures /// * `pub_keys` - The constituent public keys - pub fn multisig_lock(m: usize, n: usize, check_data: String, pub_keys: Vec) -> Self { + pub fn multisig_lock(m: usize, n: usize, check_data: Vec, pub_keys: Vec) -> Self { let mut stack = vec![StackEntry::Bytes(check_data), StackEntry::Num(m)]; stack.append(&mut pub_keys.iter().map(|e| StackEntry::PubKey(*e)).collect()); stack.push(StackEntry::Num(n)); @@ -453,7 +453,7 @@ impl Script { /// /// * `check_data` - Data to have signed /// * `signatures` - Signatures to unlock with - pub fn multisig_unlock(check_data: String, signatures: Vec) -> Self { + pub fn multisig_unlock(check_data: Vec, signatures: Vec) -> Self { let mut stack = vec![StackEntry::Bytes(check_data)]; stack.append( &mut signatures @@ -475,7 +475,7 @@ impl Script { pub fn multisig_validation( m: usize, n: usize, - check_data: String, + check_data: Vec, signatures: Vec, pub_keys: Vec, ) -> Self { diff --git a/src/script/mod.rs b/src/script/mod.rs index 3063a46..e7c6ca2 100644 --- a/src/script/mod.rs +++ b/src/script/mod.rs @@ -12,8 +12,9 @@ pub enum StackEntry { Op(OpCodes), Signature(Signature), PubKey(PublicKey), + // TODO: This should probably be u64, as usize doesn't have a consistent range on all platforms Num(usize), - Bytes(String), + Bytes(Vec), } /// Opcodes enum diff --git a/src/utils/mod.rs b/src/utils/mod.rs index adb6987..aa17b53 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -51,3 +51,105 @@ pub fn add_btreemap( }); m1 } + +/// A trait which indicates that it is possible to acquire a "placeholder" value +/// of a type, which can be used for test purposes. +#[cfg(test)] +pub trait Placeholder : Sized { + /// Gets a placeholder value of this type which can be used for test purposes. + fn placeholder() -> Self; + + /// Gets an array of placeholder values of this type which can be used for test purposes. + fn placeholder_array() -> [Self; N] { + core::array::from_fn(|_| Self::placeholder()) + } +} + +/// A trait which indicates that it is possible to acquire a "placeholder" value +/// of a type, which can be used for test purposes. These placeholder values are consistent +/// across program runs. +#[cfg(test)] +pub trait PlaceholderSeed: Sized + PartialEq { + /// Gets a dummy valid of this type which can be used for test purposes. + /// + /// This allows acquiring multiple distinct placeholder values which are still consistent + /// between runs. + /// + /// ### Arguments + /// + /// * `seed_parts` - the parts of the seed for the placeholder value to obtain. Two placeholder + /// values generated from the same seed are guaranteed to be equal (even + /// across multiple test runs, so long as the value format doesn't change). + fn placeholder_seed_parts<'a>(seed_parts: impl IntoIterator) -> Self; + + /// Gets a dummy valid of this type which can be used for test purposes. + /// + /// This allows acquiring multiple distinct placeholder values which are still consistent + /// between runs. + /// + /// ### Arguments + /// + /// * `seed` - the seed for the placeholder value to obtain. Two placeholder + /// values generated from the same seed are guaranteed to be equal (even + /// across multiple test runs, so long as the value format doesn't change). + fn placeholder_seed(seed: impl AsRef<[u8]>) -> Self { + Self::placeholder_seed_parts([ seed.as_ref() ]) + } + + /// Gets a dummy valid of this type which can be used for test purposes. + /// + /// This allows acquiring multiple distinct placeholder values which are still consistent + /// between runs. + /// + /// ### Arguments + /// + /// * `index` - the index of the placeholder value to obtain. Two placeholder values generated + /// from the same index are guaranteed to be equal (even across multiple test runs, + /// so long as the value format doesn't change). + fn placeholder_indexed(index: u64) -> Self { + Self::placeholder_seed_parts([ index.to_le_bytes().as_slice() ]) + } + + /// Gets an array of placeholder values of this type which can be used for test purposes. + fn placeholder_array_seed(seed: impl AsRef<[u8]>) -> [Self; N] { + core::array::from_fn(|n| Self::placeholder_seed_parts( + [ seed.as_ref(), &(n as u64).to_le_bytes() ] + )) + } + + /// Gets an array of placeholder values of this type which can be used for test purposes. + fn placeholder_array_indexed(base_index: u64) -> [Self; N] { + Self::placeholder_array_seed(base_index.to_le_bytes()) + } +} + +#[cfg(test)] +impl Placeholder for T { + fn placeholder() -> Self { + ::placeholder_seed_parts([]) + } +} + +/// Generates the given number of pseudorandom bytes based on the given seed. +/// +/// This is intended to be used in tests, where random but reproducible placeholder values are often +/// required. +/// +/// ### Arguments +/// +/// * `seed_parts` - the parts of the seed, which will be concatenated to form the RNG seed +#[cfg(test)] +pub fn placeholder_bytes<'a, const N: usize>( + seed_parts: impl IntoIterator +) -> [u8; N] { + // Use Shake-256 to generate an arbitrarily large number of random bytes based on the given seed. + let mut shake256 = sha3::Shake256::default(); + for slice in seed_parts { + sha3::digest::Update::update(&mut shake256, slice); + } + let mut reader = sha3::digest::ExtendableOutput::finalize_xof(shake256); + + let mut res = [0u8; N]; + sha3::digest::XofReader::read(&mut reader, &mut res); + res +} diff --git a/src/utils/script_utils.rs b/src/utils/script_utils.rs index a2cd085..3fc07c1 100644 --- a/src/utils/script_utils.rs +++ b/src/utils/script_utils.rs @@ -193,7 +193,11 @@ pub fn tx_has_valid_create_script(script: &Script, asset: &Asset) -> bool { it.next(), it.next(), ) { - if b == &asset_hash && script.interpret() { + // For legacy reasons, the hashed data is the hex representation of the data rather than + // the data itself. + let b_hex = hex::encode(b); + + if b_hex == asset_hash && script.interpret() { return true; } } @@ -209,6 +213,7 @@ pub fn tx_has_valid_create_script(script: &Script, asset: &Asset) -> bool { /// * `script` - Script to validate /// * `outpoint_hash` - Hash of the corresponding outpoint /// * `tx_out_pub_key` - Public key of the previous tx_out +// TODO: The last two operands should be converted to the corresponding types fn tx_has_valid_p2pkh_sig(script: &Script, outpoint_hash: &str, tx_out_pub_key: &str) -> bool { let mut it = script.stack.iter(); @@ -238,7 +243,13 @@ fn tx_has_valid_p2pkh_sig(script: &Script, outpoint_hash: &str, tx_out_pub_key: it.next(), ) { debug!("b: {:?}, h: {:?}", b, h); - if h == tx_out_pub_key && b == outpoint_hash && script.interpret() { + + // For legacy reasons, the hashed data is the hex representation of the data rather than + // the data itself. + let h_hex = hex::encode(h); + let b_hex = hex::encode(b); + + if h_hex == tx_out_pub_key && b_hex == outpoint_hash && script.interpret() { return true; } } @@ -359,7 +370,7 @@ mod tests { assert_eq!(cond_stack.first_false_pos, Some(0)); /// error item type let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(String::new())); + stack.push(StackEntry::Bytes(Vec::new())); let mut cond_stack = ConditionStack::new(); let b = op_if(&mut stack, &mut cond_stack); assert!(!b); @@ -404,7 +415,7 @@ mod tests { assert_eq!(cond_stack.first_false_pos, Some(0)); /// error item type let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(String::new())); + stack.push(StackEntry::Bytes(Vec::new())); let mut cond_stack = ConditionStack::new(); let b = op_notif(&mut stack, &mut cond_stack); assert!(!b); @@ -847,7 +858,7 @@ mod tests { /// op_pick([1,"hello"]) -> fail let mut stack = Stack::new(); stack.push(StackEntry::Num(1)); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); let b = op_pick(&mut stack); assert!(!b); /// op_pick([1,1]) -> fail @@ -895,7 +906,7 @@ mod tests { /// op_roll([1,"hello"]) -> fail let mut stack = Stack::new(); stack.push(StackEntry::Num(1)); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); let b = op_roll(&mut stack); assert!(!b); /// op_roll([1,1]) -> fail @@ -977,36 +988,36 @@ mod tests { fn test_cat() { /// op_cat(["hello","world"]) -> ["helloworld"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); - stack.push(StackEntry::Bytes("world".to_string())); - let mut v: Vec = vec![StackEntry::Bytes("helloworld".to_string())]; + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); + stack.push(StackEntry::Bytes("world".as_bytes().to_vec())); + let mut v: Vec = vec![StackEntry::Bytes("helloworld".as_bytes().to_vec())]; op_cat(&mut stack); assert_eq!(stack.main_stack, v); /// op_cat(["hello",""]) -> ["hello"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); - stack.push(StackEntry::Bytes("".to_string())); - let mut v: Vec = vec![StackEntry::Bytes("hello".to_string())]; + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); + stack.push(StackEntry::Bytes("".as_bytes().to_vec())); + let mut v: Vec = vec![StackEntry::Bytes("hello".as_bytes().to_vec())]; op_cat(&mut stack); assert_eq!(stack.main_stack, v); /// op_cat(["a","a"*MAX_SCRIPT_ITEM_SIZE]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("a".to_string())); + stack.push(StackEntry::Bytes("a".as_bytes().to_vec())); let mut s = String::new(); for i in 1..=MAX_SCRIPT_ITEM_SIZE { s.push('a'); } - stack.push(StackEntry::Bytes(s.to_string())); + stack.push(StackEntry::Bytes(s.as_bytes().to_vec())); let b = op_cat(&mut stack); assert!(!b); /// op_cat(["hello"]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); let b = op_cat(&mut stack); assert!(!b); /// op_cat(["hello", 1]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(1)); let b = op_cat(&mut stack); assert!(!b) @@ -1017,62 +1028,62 @@ mod tests { fn test_substr() { /// op_substr(["hello",1,2]) -> ["el"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); for i in 1..=2 { stack.push(StackEntry::Num(i)); } - let mut v: Vec = vec![StackEntry::Bytes("el".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("el".as_bytes().to_vec())]; op_substr(&mut stack); assert_eq!(stack.main_stack, v); /// op_substr(["hello",0,0]) -> [""] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); for i in 1..=2 { stack.push(StackEntry::Num(0)); } - let mut v: Vec = vec![StackEntry::Bytes("".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("".as_bytes().to_vec())]; op_substr(&mut stack); assert_eq!(stack.main_stack, v); /// op_substr(["hello",0,5]) -> ["hello"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(0)); stack.push(StackEntry::Num(5)); - let mut v: Vec = vec![StackEntry::Bytes("hello".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("hello".as_bytes().to_vec())]; op_substr(&mut stack); assert_eq!(stack.main_stack, v); /// op_substr(["hello",5,0]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(5)); stack.push(StackEntry::Num(0)); let b = op_substr(&mut stack); assert!(!b); /// op_substr(["hello",1,5]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(1)); stack.push(StackEntry::Num(5)); let b = op_substr(&mut stack); assert!(!b); /// op_substr(["hello",1]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(1)); let b = op_substr(&mut stack); assert!(!b); /// op_substr(["hello",1,usize::MAX]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(1)); stack.push(StackEntry::Num(usize::MAX)); let b = op_substr(&mut stack); assert!(!b); /// op_substr(["hello",1,""]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(1)); - stack.push(StackEntry::Bytes("".to_string())); + stack.push(StackEntry::Bytes("".as_bytes().to_vec())); let b = op_substr(&mut stack); assert!(!b) } @@ -1082,34 +1093,34 @@ mod tests { fn test_left() { /// op_left(["hello",2]) -> ["he"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(2)); - let mut v: Vec = vec![StackEntry::Bytes("he".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("he".as_bytes().to_vec())]; op_left(&mut stack); assert_eq!(stack.main_stack, v); /// op_left(["hello",0]) -> [""] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(0)); - let mut v: Vec = vec![StackEntry::Bytes("".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("".as_bytes().to_vec())]; op_left(&mut stack); assert_eq!(stack.main_stack, v); /// op_left(["hello",5]) -> ["hello"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(5)); - let mut v: Vec = vec![StackEntry::Bytes("hello".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("hello".as_bytes().to_vec())]; op_left(&mut stack); assert_eq!(stack.main_stack, v); /// op_left(["hello",""]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); - stack.push(StackEntry::Bytes("".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); + stack.push(StackEntry::Bytes("".as_bytes().to_vec())); let b = op_left(&mut stack); assert!(!b); /// op_left(["hello"]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); let b = op_left(&mut stack); assert!(!b) } @@ -1119,34 +1130,34 @@ mod tests { fn test_right() { /// op_right(["hello",0]) -> ["hello"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(0)); - let mut v: Vec = vec![StackEntry::Bytes("hello".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("hello".as_bytes().to_vec())]; op_right(&mut stack); assert_eq!(stack.main_stack, v); /// op_right(["hello",2]) -> ["llo"] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(2)); - let mut v: Vec = vec![StackEntry::Bytes("llo".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("llo".as_bytes().to_vec())]; op_right(&mut stack); assert_eq!(stack.main_stack, v); /// op_right(["hello",5]) -> [""] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); stack.push(StackEntry::Num(5)); - let mut v: Vec = vec![StackEntry::Bytes("".to_string())]; + let mut v: Vec = vec![StackEntry::Bytes("".as_bytes().to_vec())]; op_right(&mut stack); assert_eq!(stack.main_stack, v); /// op_right(["hello",""]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); - stack.push(StackEntry::Bytes("".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); + stack.push(StackEntry::Bytes("".as_bytes().to_vec())); let b = op_right(&mut stack); assert!(!b); /// op_right(["hello"]) -> fail let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); let b = op_right(&mut stack); assert!(!b) } @@ -1156,15 +1167,15 @@ mod tests { fn test_size() { /// op_size(["hello"]) -> ["hello",5] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); let mut v: Vec = - vec![StackEntry::Bytes("hello".to_string()), StackEntry::Num(5)]; + vec![StackEntry::Bytes("hello".as_bytes().to_vec()), StackEntry::Num(5)]; op_size(&mut stack); assert_eq!(stack.main_stack, v); /// op_size([""]) -> ["",0] let mut stack = Stack::new(); - stack.push(StackEntry::Bytes("".to_string())); - let mut v: Vec = vec![StackEntry::Bytes("".to_string()), StackEntry::Num(0)]; + stack.push(StackEntry::Bytes("".as_bytes().to_vec())); + let mut v: Vec = vec![StackEntry::Bytes("".as_bytes().to_vec()), StackEntry::Num(0)]; op_size(&mut stack); assert_eq!(stack.main_stack, v); /// op_size([1]) -> fail @@ -1263,7 +1274,7 @@ mod tests { /// op_equal(["hello","hello"]) -> [1] let mut stack = Stack::new(); for i in 1..=2 { - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); } let mut v: Vec = vec![StackEntry::Num(1)]; op_equal(&mut stack); @@ -1289,7 +1300,7 @@ mod tests { /// op_equalverify(["hello","hello"]) -> [] let mut stack = Stack::new(); for i in 1..=2 { - stack.push(StackEntry::Bytes("hello".to_string())); + stack.push(StackEntry::Bytes("hello".as_bytes().to_vec())); } let mut v: Vec = vec![]; op_equalverify(&mut stack); @@ -1898,22 +1909,22 @@ mod tests { let (pk, sk) = sign::gen_keypair(); let msg = hex::encode(vec![0, 0, 0]); let sig = sign::sign_detached(msg.as_bytes(), &sk); - let h = hex::encode(sha3_256::digest(sig.as_ref())); + let h = sha3_256::digest(sig.as_ref()).to_vec(); let mut stack = Stack::new(); stack.push(StackEntry::Signature(sig)); let mut v: Vec = vec![StackEntry::Bytes(h)]; op_sha3(&mut stack); assert_eq!(stack.main_stack, v); /// op_sha3([pk]) -> [sha3_256(pk)] - let h = hex::encode(sha3_256::digest(pk.as_ref())); + let h = sha3_256::digest(pk.as_ref()).to_vec(); let mut stack = Stack::new(); stack.push(StackEntry::PubKey(pk)); let mut v: Vec = vec![StackEntry::Bytes(h)]; op_sha3(&mut stack); assert_eq!(stack.main_stack, v); /// op_sha3(["hello"]) -> [sha3_256("hello")] - let s = "hello".to_string(); - let h = hex::encode(sha3_256::digest(s.as_bytes())); + let s = "hello".as_bytes().to_vec(); + let h = sha3_256::digest(hex::encode(&s).as_bytes()).to_vec(); let mut stack = Stack::new(); stack.push(StackEntry::Bytes(s)); let mut v: Vec = vec![StackEntry::Bytes(h)]; @@ -1937,7 +1948,7 @@ mod tests { let (pk, sk) = sign::gen_keypair(); let mut stack = Stack::new(); stack.push(StackEntry::PubKey(pk)); - let mut v: Vec = vec![StackEntry::Bytes(construct_address(&pk))]; + let mut v: Vec = vec![StackEntry::Bytes(hex::decode(construct_address(&pk)).unwrap())]; op_hash256(&mut stack); assert_eq!(stack.main_stack, v); /// op_hash256([]) -> fail @@ -1953,7 +1964,7 @@ mod tests { let (pk, sk) = sign::gen_keypair(); let mut stack = Stack::new(); stack.push(StackEntry::PubKey(pk)); - let mut v: Vec = vec![StackEntry::Bytes(construct_address_v0(&pk))]; + let mut v: Vec = vec![StackEntry::Bytes(hex::decode(construct_address_v0(&pk)).unwrap())]; op_hash256_v0(&mut stack); assert_eq!(stack.main_stack, v); /// op_hash256([]) -> fail @@ -1969,7 +1980,7 @@ mod tests { let (pk, sk) = sign::gen_keypair(); let mut stack = Stack::new(); stack.push(StackEntry::PubKey(pk)); - let mut v: Vec = vec![StackEntry::Bytes(construct_address_temp(&pk))]; + let mut v: Vec = vec![StackEntry::Bytes(hex::decode(construct_address_temp(&pk)).unwrap())]; op_hash256_temp(&mut stack); assert_eq!(stack.main_stack, v); /// op_hash256([]) -> fail @@ -1986,7 +1997,7 @@ mod tests { let msg = hex::encode(vec![0, 0, 0]); let sig = sign::sign_detached(msg.as_bytes(), &sk); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig)); stack.push(StackEntry::PubKey(pk)); let mut v: Vec = vec![StackEntry::Num(1)]; @@ -1996,7 +2007,7 @@ mod tests { /// op_checksig([msg',sig,pk]) -> [0] let msg = hex::encode(vec![0, 0, 1]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig)); stack.push(StackEntry::PubKey(pk)); let mut v: Vec = vec![StackEntry::Num(0)]; @@ -2007,7 +2018,7 @@ mod tests { let (pk, sk) = sign::gen_keypair(); let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig)); stack.push(StackEntry::PubKey(pk)); let mut v: Vec = vec![StackEntry::Num(0)]; @@ -2030,7 +2041,7 @@ mod tests { let msg = hex::encode(vec![0, 0, 0]); let sig = sign::sign_detached(msg.as_bytes(), &sk); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig)); stack.push(StackEntry::PubKey(pk)); let mut v: Vec = vec![]; @@ -2040,7 +2051,7 @@ mod tests { /// op_checksigverify([msg',sig,pk]) -> fail let msg = hex::encode(vec![0, 0, 1]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig)); stack.push(StackEntry::PubKey(pk)); let b = op_checksigverify(&mut stack); @@ -2050,7 +2061,7 @@ mod tests { let (pk, sk) = sign::gen_keypair(); let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig)); stack.push(StackEntry::PubKey(pk)); let b = op_checksigverify(&mut stack); @@ -2076,7 +2087,7 @@ mod tests { let sig1 = sign::sign_detached(msg.as_bytes(), &sk1); let sig2 = sign::sign_detached(msg.as_bytes(), &sk2); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Signature(sig2)); stack.push(StackEntry::Num(2)); @@ -2091,7 +2102,7 @@ mod tests { /// op_checkmultisig([msg,0,pk1,pk2,pk3,3]) -> [1] let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Num(0)); stack.push(StackEntry::PubKey(pk1)); stack.push(StackEntry::PubKey(pk2)); @@ -2104,7 +2115,7 @@ mod tests { /// op_checkmultisig([msg,0,0]) -> [1] let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Num(0)); stack.push(StackEntry::Num(0)); let mut v: Vec = vec![StackEntry::Num(1)]; @@ -2114,7 +2125,7 @@ mod tests { /// op_checkmultisig([msg,sig1,1,pk1,1]) -> [1] let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Num(1)); stack.push(StackEntry::PubKey(pk1)); @@ -2127,7 +2138,7 @@ mod tests { let msg = hex::encode(vec![0, 0, 0]); let sig3 = sign::sign_detached(msg.as_bytes(), &sk3); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig3)); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Num(2)); @@ -2142,7 +2153,7 @@ mod tests { /// op_checkmultisig([msg',sig1,sig2,2,pk1,pk2,pk3,3]) -> [0] let msg = hex::encode(vec![0, 0, 1]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Signature(sig2)); stack.push(StackEntry::Num(2)); @@ -2157,7 +2168,7 @@ mod tests { /// op_checkmultisig([msg,sig1,sig1,2,pk1,pk2,pk3,3]) -> [0] let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Num(2)); @@ -2229,7 +2240,7 @@ mod tests { let sig1 = sign::sign_detached(msg.as_bytes(), &sk1); let sig2 = sign::sign_detached(msg.as_bytes(), &sk2); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Signature(sig2)); stack.push(StackEntry::Num(2)); @@ -2244,7 +2255,7 @@ mod tests { /// op_checkmultisigverify([msg,0,pk1,pk2,pk3,3]) -> [] let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Num(0)); stack.push(StackEntry::PubKey(pk1)); stack.push(StackEntry::PubKey(pk2)); @@ -2257,7 +2268,7 @@ mod tests { /// op_checkmultisig([msg,0,0]) -> [] let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Num(0)); stack.push(StackEntry::Num(0)); let mut v: Vec = vec![]; @@ -2267,7 +2278,7 @@ mod tests { /// op_checkmultisigverify([msg,sig1,1,pk1,1]) -> [] let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Num(1)); stack.push(StackEntry::PubKey(pk1)); @@ -2280,7 +2291,7 @@ mod tests { let msg = hex::encode(vec![0, 0, 0]); let sig3 = sign::sign_detached(msg.as_bytes(), &sk3); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig3)); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Num(2)); @@ -2295,7 +2306,7 @@ mod tests { /// op_checkmultisigverify([msg',sig1,sig2,2,pk1,pk2,pk3,3]) -> fail let msg = hex::encode(vec![0, 0, 1]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Signature(sig2)); stack.push(StackEntry::Num(2)); @@ -2309,7 +2320,7 @@ mod tests { /// op_checkmultisigverify([msg,sig1,sig1,2,pk1,pk2,pk3,3]) -> fail let msg = hex::encode(vec![0, 0, 0]); let mut stack = Stack::new(); - stack.push(StackEntry::Bytes(msg)); + stack.push(StackEntry::Bytes(hex::decode(msg).unwrap())); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Signature(sig1)); stack.push(StackEntry::Num(2)); @@ -2375,11 +2386,11 @@ mod tests { let script = Script::from(v); assert!(script.is_valid()); // script length <= 10000 bytes - let v = vec![StackEntry::Bytes("a".repeat(500)); 20]; + let v = vec![StackEntry::Bytes("a".repeat(500).as_bytes().to_vec()); 20]; let script = Script::from(v); assert!(script.is_valid()); // script length > 10000 bytes - let v = vec![StackEntry::Bytes("a".repeat(500)); 21]; + let v = vec![StackEntry::Bytes("a".repeat(500).as_bytes().to_vec()); 21]; let script = Script::from(v); assert!(!script.is_valid()); // # opcodes <= 201 @@ -2433,11 +2444,11 @@ mod tests { let script = Script::from(v); assert!(script.interpret()); // script length <= 10000 bytes - let v = vec![StackEntry::Bytes("a".repeat(500)); 20]; + let v = vec![StackEntry::Bytes("a".repeat(500).as_bytes().to_vec()); 20]; let script = Script::from(v); assert!(script.interpret()); // script length > 10000 bytes - let v = vec![StackEntry::Bytes("a".repeat(500)); 21]; + let v = vec![StackEntry::Bytes("a".repeat(500).as_bytes().to_vec()); 21]; let script = Script::from(v); assert!(!script.interpret()); // # opcodes <= 201 @@ -2642,7 +2653,7 @@ mod tests { new_tx_in.script_signature = Script::multisig_validation( m, entry.pub_keys.len(), - entry.previous_out.t_hash.clone(), + hex::decode(&entry.previous_out.t_hash).unwrap(), entry.signatures, entry.pub_keys, ); @@ -2661,7 +2672,7 @@ mod tests { for entry in tx_values { let mut new_tx_in = TxIn::new(); new_tx_in.script_signature = Script::member_multisig( - entry.previous_out.t_hash.clone(), + hex::decode(&entry.previous_out.t_hash).unwrap(), entry.pub_keys[0], entry.signatures[0], ); @@ -2953,7 +2964,7 @@ mod tests { new_tx_in .script_signature .stack - .push(StackEntry::Bytes("".to_string())); + .push(StackEntry::Bytes("".as_bytes().to_vec())); new_tx_in.previous_out = Some(entry.previous_out); tx_ins.push(new_tx_in); @@ -3080,19 +3091,19 @@ mod tests { // 0. Happy case: valid test ( vec![ - StackEntry::Bytes(valid_bytes), + StackEntry::Bytes(hex::decode(valid_bytes).unwrap()), StackEntry::Signature(valid_sig), StackEntry::PubKey(pk), StackEntry::Op(OpCodes::OP_DUP), StackEntry::Op(op_hash256), - StackEntry::Bytes(script_public_key), + StackEntry::Bytes(hex::decode(script_public_key).unwrap()), StackEntry::Op(OpCodes::OP_EQUALVERIFY), StackEntry::Op(OpCodes::OP_CHECKSIG), ], true, ), // 2. Empty script - (vec![StackEntry::Bytes("".to_string())], false), + (vec![StackEntry::Bytes("".as_bytes().to_vec())], false), ]; // diff --git a/src/utils/test_utils.rs b/src/utils/test_utils.rs index 0c8fcef..ebe46d4 100644 --- a/src/utils/test_utils.rs +++ b/src/utils/test_utils.rs @@ -66,7 +66,7 @@ pub fn generate_tx_with_ins_and_outs_assets( let signature = sign::sign_detached(signable_hash.as_bytes(), &sk); let tx_in = TxIn::new_from_input( tx_previous_out.clone(), - Script::pay2pkh(signable_hash, signature, pk, None), + Script::pay2pkh(hex::decode(&signable_hash).unwrap(), signature, pk, None), ); utxo_set.insert(tx_previous_out, tx_in_previous_out); tx.inputs.push(tx_in); diff --git a/src/utils/transaction_utils.rs b/src/utils/transaction_utils.rs index 8e9fd99..cae01cc 100644 --- a/src/utils/transaction_utils.rs +++ b/src/utils/transaction_utils.rs @@ -162,7 +162,7 @@ pub fn get_stack_entry_signable_string(entry: &StackEntry) -> String { } StackEntry::PubKey(pub_key) => format!("PubKey:{}", hex::encode(pub_key.as_ref())), StackEntry::Num(num) => format!("Num:{num}"), - StackEntry::Bytes(bytes) => format!("Bytes:{bytes}"), + StackEntry::Bytes(bytes) => format!("Bytes:{}", hex::encode(bytes)), } } @@ -578,7 +578,7 @@ pub fn update_input_signatures(tx_ins: &[TxIn], tx_outs: &[TxOut], key_material: let sk = &key_material.get(&previous_out.unwrap()).unwrap().1; let script_signature = Script::pay2pkh( - signable_hash.clone(), + hex::decode(&signable_hash).unwrap(), sign_detached(signable_hash.as_bytes(), sk), pk, None, @@ -1472,7 +1472,7 @@ mod tests { Signature::from_slice(hex::decode(signatures[n]).unwrap().as_ref()).unwrap(); let pk = PublicKey::from_slice(hex::decode(pub_keys[n]).unwrap().as_ref()).unwrap(); - let script = Script::pay2pkh(sig_data, sig, pk, None); + let script = Script::pay2pkh(hex::decode(&sig_data).unwrap(), sig, pk, None); let out_p = previous_out_points[n].clone(); TxIn::new_from_input(out_p, script)