diff --git a/clarity/src/vm/analysis/contract_interface_builder/mod.rs b/clarity/src/vm/analysis/contract_interface_builder/mod.rs index c9bc3c71c..63cf11993 100644 --- a/clarity/src/vm/analysis/contract_interface_builder/mod.rs +++ b/clarity/src/vm/analysis/contract_interface_builder/mod.rs @@ -237,14 +237,13 @@ pub struct ContractInterfaceFunctionArg { impl ContractInterfaceFunctionArg { pub fn from_function_args(fnArgs: &[FunctionArg]) -> Vec { - let mut args: Vec = Vec::new(); - for fnArg in fnArgs.iter() { - args.push(ContractInterfaceFunctionArg { + fnArgs + .iter() + .map(|fnArg| ContractInterfaceFunctionArg { name: fnArg.name.to_string(), type_f: ContractInterfaceAtomType::from_type_signature(&fnArg.signature), - }); - } - args + }) + .collect() } } diff --git a/clarity/src/vm/analysis/type_checker/v2_05/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/mod.rs index cc6d7e906..7c6b58755 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/mod.rs @@ -526,7 +526,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { args: &[SymbolicExpression], context: &TypingContext, ) -> CheckResult> { - let mut result = Vec::new(); + let mut result = Vec::with_capacity(args.len()); for arg in args.iter() { // don't use map here, since type_check has side-effects. result.push(self.type_check(arg, context)?) diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs index 18663329f..46830a876 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs @@ -187,14 +187,11 @@ pub fn check_special_tuple_cons( context: &TypingContext, ) -> TypeResult { check_arguments_at_least(1, args)?; + let len = args.len(); - let mut tuple_type_data = Vec::new(); + runtime_cost(ClarityCostFunction::AnalysisCheckTupleCons, checker, len)?; - runtime_cost( - ClarityCostFunction::AnalysisCheckTupleCons, - checker, - args.len(), - )?; + let mut tuple_type_data = Vec::with_capacity(len); handle_binding_list(args, |var_name, var_sexp| { checker.type_check(var_sexp, context).and_then(|var_type| { diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs index 49a29e8d3..81d52bb23 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs @@ -74,9 +74,10 @@ pub fn check_special_map( args.len(), )?; - let mut func_args = vec![]; + let iter = args[1..].iter(); + let mut func_args = Vec::with_capacity(iter.len()); let mut min_args = u32::MAX; - for arg in args[1..].iter() { + for arg in iter { let argument_type = checker.type_check(arg, context)?; let entry_type = match argument_type { TypeSignature::SequenceType(sequence) => { diff --git a/clarity/src/vm/analysis/type_checker/v2_1/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/mod.rs index 38cf3c767..44aab0b4f 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/mod.rs @@ -459,7 +459,7 @@ impl FunctionType { } } } else { - let mut arg_types = Vec::new(); + let mut arg_types = Vec::with_capacity(func_args.len()); for arg in func_args { arg_types.push(self.principal_to_callable_type(arg, 1, clarity_version)?); } @@ -1028,7 +1028,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> { args: &[SymbolicExpression], context: &TypingContext, ) -> CheckResult> { - let mut result = Vec::new(); + let mut result = Vec::with_capacity(args.len()); for arg in args.iter() { // don't use map here, since type_check has side-effects. result.push(self.type_check(arg, context)?) diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs index fd1f45604..1c30eb779 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs @@ -195,7 +195,7 @@ pub fn check_special_tuple_cons( ) -> TypeResult { check_arguments_at_least(1, args)?; - let mut tuple_type_data = Vec::new(); + let mut tuple_type_data = Vec::with_capacity(args.len()); runtime_cost( ClarityCostFunction::AnalysisCheckTupleCons, diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs index 9eb2ae17c..52ceca66b 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs @@ -74,9 +74,10 @@ pub fn check_special_map( args.len(), )?; - let mut func_args = vec![]; + let iter = args[1..].iter(); + let mut func_args = Vec::with_capacity(iter.len()); let mut min_args = u32::MAX; - for arg in args[1..].iter() { + for arg in iter { let argument_type = checker.type_check(arg, context)?; let entry_type = match argument_type { TypeSignature::SequenceType(sequence) => { diff --git a/clarity/src/vm/ast/definition_sorter/mod.rs b/clarity/src/vm/ast/definition_sorter/mod.rs index 36dfb2166..a48bfd0e3 100644 --- a/clarity/src/vm/ast/definition_sorter/mod.rs +++ b/clarity/src/vm/ast/definition_sorter/mod.rs @@ -91,14 +91,14 @@ impl DefinitionSorter { let sorted_indexes = walker.get_sorted_dependencies(&self.graph)?; if let Some(deps) = walker.get_cycling_dependencies(&self.graph, &sorted_indexes) { - let mut deps_props = vec![]; - for i in deps.iter() { - let exp = &contract_ast.pre_expressions[*i]; - if let Some(def) = self.find_expression_definition(exp) { - deps_props.push(def); - } - } - let functions_names = deps_props.iter().map(|i| i.0.to_string()).collect(); + let functions_names = deps + .into_iter() + .filter_map(|i| { + let exp = &contract_ast.pre_expressions[i]; + self.find_expression_definition(exp) + }) + .map(|i| i.0.to_string()) + .collect::>(); let error = ParseError::new(ParseErrors::CircularReference(functions_names)); return Err(error); diff --git a/clarity/src/vm/ast/parser/v2/mod.rs b/clarity/src/vm/ast/parser/v2/mod.rs index 75a622a7c..6238af138 100644 --- a/clarity/src/vm/ast/parser/v2/mod.rs +++ b/clarity/src/vm/ast/parser/v2/mod.rs @@ -894,12 +894,14 @@ impl<'a> Parser<'a> { Some(expr) } Token::Utf8String(s) => { - let mut data: Vec> = Vec::new(); - for ch in s.chars() { - let mut bytes = vec![0; ch.len_utf8()]; - ch.encode_utf8(&mut bytes); - data.push(bytes); - } + let data: Vec> = s + .chars() + .map(|ch| { + let mut bytes = vec![0; ch.len_utf8()]; + ch.encode_utf8(&mut bytes); + bytes + }) + .collect(); let val = Value::Sequence(SequenceData::String(CharType::UTF8(UTF8Data { data, diff --git a/clarity/src/vm/ast/sugar_expander/mod.rs b/clarity/src/vm/ast/sugar_expander/mod.rs index 481e1039d..cf070548a 100644 --- a/clarity/src/vm/ast/sugar_expander/mod.rs +++ b/clarity/src/vm/ast/sugar_expander/mod.rs @@ -65,7 +65,7 @@ impl SugarExpander { pre_exprs_iter: PreExpressionsDrain, contract_ast: &mut ContractAST, ) -> ParseResult> { - let mut expressions: Vec = Vec::new(); + let mut expressions: Vec = Vec::with_capacity(pre_exprs_iter.len()); #[cfg(feature = "developer-mode")] let mut comments = Vec::new(); diff --git a/clarity/src/vm/ast/types.rs b/clarity/src/vm/ast/types.rs index e8183220a..87ab844b8 100644 --- a/clarity/src/vm/ast/types.rs +++ b/clarity/src/vm/ast/types.rs @@ -95,6 +95,10 @@ impl PreExpressionsDrain { index: 0, } } + + pub fn len(&self) -> usize { + self.len + } } impl Iterator for PreExpressionsDrain { diff --git a/clarity/src/vm/coverage.rs b/clarity/src/vm/coverage.rs index 6f2de9f5c..ea6298169 100644 --- a/clarity/src/vm/coverage.rs +++ b/clarity/src/vm/coverage.rs @@ -74,10 +74,11 @@ impl CoverageReporter { let f = File::create(filename)?; let mut coverage = HashMap::new(); for (contract, execution_map) in self.executed_lines.iter() { - let mut executed_lines = vec![]; - for (line, count) in execution_map.iter() { - executed_lines.push((*line, *count)); - } + let mut executed_lines = execution_map + .iter() + .map(|(line, count)| (*line, *count)) + .collect::>(); + executed_lines.sort_by_key(|f| f.0); coverage.insert(contract.to_string(), executed_lines); diff --git a/clarity/src/vm/docs/mod.rs b/clarity/src/vm/docs/mod.rs index 50ca695e4..205fdc617 100644 --- a/clarity/src/vm/docs/mod.rs +++ b/clarity/src/vm/docs/mod.rs @@ -2609,20 +2609,18 @@ pub fn make_define_reference(define_type: &DefineFunctions) -> FunctionAPI { fn make_all_api_reference() -> ReferenceAPIs { let mut functions: Vec<_> = NativeFunctions::ALL .iter() - .map(|x| make_api_reference(x)) + .map(make_api_reference) .collect(); for data_type in DefineFunctions::ALL.iter() { functions.push(make_define_reference(data_type)) } functions.sort_by(|x, y| x.name.cmp(&y.name)); - let mut keywords = Vec::new(); - for variable in NativeVariables::ALL.iter() { - let output = make_keyword_reference(variable); - if let Some(api_ref) = output { - keywords.push(api_ref) - } - } + let mut keywords: Vec<_> = NativeVariables::ALL + .iter() + .filter_map(make_keyword_reference) + .collect(); + keywords.sort_by(|x, y| x.name.cmp(&y.name)); ReferenceAPIs { diff --git a/clarity/src/vm/functions/database.rs b/clarity/src/vm/functions/database.rs index d036dd27c..e52ac57b5 100644 --- a/clarity/src/vm/functions/database.rs +++ b/clarity/src/vm/functions/database.rs @@ -75,9 +75,11 @@ pub fn special_contract_call( runtime_cost(ClarityCostFunction::ContractCall, env, 0)?; let function_name = args[1].match_atom().ok_or(CheckErrors::ExpectedName)?; - let mut rest_args = vec![]; - let mut rest_args_sizes = vec![]; - for arg in args[2..].iter() { + let rest_args_slice = &args[2..]; + let rest_args_len = rest_args_slice.len(); + let mut rest_args = Vec::with_capacity(rest_args_len); + let mut rest_args_sizes = Vec::with_capacity(rest_args_len); + for arg in rest_args_slice.iter() { let evaluated_arg = eval(arg, env, context)?; rest_args_sizes.push(evaluated_arg.size()? as u64); rest_args.push(SymbolicExpression::atom_value(evaluated_arg)); diff --git a/clarity/src/vm/functions/mod.rs b/clarity/src/vm/functions/mod.rs index a523db864..7c3647c2f 100644 --- a/clarity/src/vm/functions/mod.rs +++ b/clarity/src/vm/functions/mod.rs @@ -701,7 +701,7 @@ pub fn parse_eval_bindings( env: &mut Environment, context: &LocalContext, ) -> Result> { - let mut result = Vec::new(); + let mut result = Vec::with_capacity(bindings.len()); handle_binding_list(bindings, |var_name, var_sexp| { eval(var_sexp, env, context).map(|value| result.push((var_name.clone(), value))) })?; diff --git a/clarity/src/vm/mod.rs b/clarity/src/vm/mod.rs index 7231ad584..45d71cf22 100644 --- a/clarity/src/vm/mod.rs +++ b/clarity/src/vm/mod.rs @@ -257,7 +257,7 @@ pub fn apply( resp } else { let mut used_memory = 0; - let mut evaluated_args = vec![]; + let mut evaluated_args = Vec::with_capacity(args.len()); env.call_stack.incr_apply_depth(); for arg_x in args.iter() { let arg_value = match eval(arg_x, env, context) { diff --git a/clarity/src/vm/types/mod.rs b/clarity/src/vm/types/mod.rs index 06eea0896..cc3cbeeba 100644 --- a/clarity/src/vm/types/mod.rs +++ b/clarity/src/vm/types/mod.rs @@ -1034,12 +1034,14 @@ impl Value { Ok(string) => string, _ => return Err(CheckErrors::InvalidCharactersDetected.into()), }; - let mut data = vec![]; - for char in validated_utf8_str.chars() { - let mut encoded_char: Vec = vec![0; char.len_utf8()]; - char.encode_utf8(&mut encoded_char[..]); - data.push(encoded_char); - } + let data = validated_utf8_str + .chars() + .map(|char| { + let mut encoded_char = vec![0u8; char.len_utf8()]; + char.encode_utf8(&mut encoded_char); + encoded_char + }) + .collect::>(); // check the string size StringUTF8Length::try_from(data.len())?; diff --git a/clarity/src/vm/types/serialization.rs b/clarity/src/vm/types/serialization.rs index 32cf9cf9f..69a662e6b 100644 --- a/clarity/src/vm/types/serialization.rs +++ b/clarity/src/vm/types/serialization.rs @@ -1249,7 +1249,7 @@ impl Value { if l.len().ok()? > lt.get_max_len() { return None; } - let mut sanitized_items = vec![]; + let mut sanitized_items = Vec::with_capacity(l.data.len()); let mut did_sanitize_children = false; for item in l.data.into_iter() { let (sanitized_item, did_sanitize) = @@ -1266,11 +1266,12 @@ impl Value { TypeSignature::TupleType(tt) => tt, _ => return None, }; - let mut sanitized_tuple_entries = vec![]; + let type_map = tt.get_type_map(); + let mut sanitized_tuple_entries = Vec::with_capacity(type_map.len()); let original_tuple_len = tuple_data.len(); let mut tuple_data_map = tuple_data.data_map; let mut did_sanitize_children = false; - for (key, expect_key_type) in tt.get_type_map().iter() { + for (key, expect_key_type) in type_map.iter() { let field_data = tuple_data_map.remove(key)?; let (sanitized_field, did_sanitize) = Self::sanitize_value(epoch, expect_key_type, field_data)?; diff --git a/clarity/src/vm/types/signatures.rs b/clarity/src/vm/types/signatures.rs index f906ada18..c6838eb3f 100644 --- a/clarity/src/vm/types/signatures.rs +++ b/clarity/src/vm/types/signatures.rs @@ -981,10 +981,12 @@ impl FunctionSignature { } pub fn canonicalize(&self, epoch: &StacksEpochId) -> FunctionSignature { - let mut canonicalized_args = vec![]; - for arg in &self.args { - canonicalized_args.push(arg.canonicalize(epoch)); - } + let canonicalized_args = self + .args + .iter() + .map(|arg| arg.canonicalize(epoch)) + .collect(); + FunctionSignature { args: canonicalized_args, returns: self.returns.canonicalize(epoch), @@ -1644,8 +1646,8 @@ impl TypeSignature { let fn_args_exprs = args[1] .match_list() .ok_or(CheckErrors::DefineTraitBadSignature)?; - let mut fn_args = vec![]; - for arg_type in fn_args_exprs.iter() { + let mut fn_args = Vec::with_capacity(fn_args_exprs.len()); + for arg_type in fn_args_exprs.into_iter() { let arg_t = TypeSignature::parse_type_repr(epoch, arg_type, accounting)?; fn_args.push(arg_t); } @@ -2064,8 +2066,9 @@ mod test { // set k = 4033 let first_tuple = TypeSignature::from_string("(tuple (a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 bool))", version, epoch); - let mut keys = vec![]; - for i in 0..4033 { + let len = 4033; + let mut keys = Vec::with_capacity(len); + for i in 0..len { let key_name = ClarityName::try_from(format!("a{:0127}", i)).unwrap(); let key_val = first_tuple.clone(); keys.push((key_name, key_val)); diff --git a/stacks-common/src/address/c32.rs b/stacks-common/src/address/c32.rs index 20eb64e11..67a0504b3 100644 --- a/stacks-common/src/address/c32.rs +++ b/stacks-common/src/address/c32.rs @@ -180,7 +180,10 @@ const C32_CHARACTERS_MAP: [Option; 128] = [ ]; fn c32_encode(input_bytes: &[u8]) -> String { - let mut result = vec![]; + // ASCII characters are 8-bits and c32-encoding encodes 5-bits per + // character, so the c32-encoded size should be ceil((ascii size) * 8 / 5) + let size = input_bytes.len().saturating_mul(8).div_ceil(5); + let mut result = Vec::with_capacity(size); let mut carry = 0; let mut carry_bits = 0; @@ -234,10 +237,6 @@ fn c32_decode(input_str: &str) -> Result, Error> { } fn c32_decode_ascii(input_str: &str) -> Result, Error> { - let mut result = vec![]; - let mut carry: u16 = 0; - let mut carry_bits = 0; // can be up to 5 - let mut iter_c32_digits = Vec::::with_capacity(input_str.len()); for x in input_str.as_bytes().iter().rev() { @@ -251,6 +250,14 @@ fn c32_decode_ascii(input_str: &str) -> Result, Error> { return Err(Error::InvalidCrockford32); } + // c32-encoding encodes 5 bits into each character, while ASCII encodes + // 8-bits into each character. So, the ASCII-encoded size should be + // ceil((c32 size) * 5 / 8) + let size = iter_c32_digits.len().saturating_mul(5).div_ceil(8); + let mut result = Vec::with_capacity(size); + let mut carry: u16 = 0; + let mut carry_bits = 0; // can be up to 5 + for current_5bit in &iter_c32_digits { carry += (*current_5bit as u16) << carry_bits; carry_bits += 5; diff --git a/stacks-common/src/deps_common/bech32/mod.rs b/stacks-common/src/deps_common/bech32/mod.rs index 515126796..99f95e9cd 100644 --- a/stacks-common/src/deps_common/bech32/mod.rs +++ b/stacks-common/src/deps_common/bech32/mod.rs @@ -599,7 +599,8 @@ fn verify_checksum(hrp: &[u8], data: &[u5]) -> Option { } fn hrp_expand(hrp: &[u8]) -> Vec { - let mut v: Vec = Vec::new(); + let size = (hrp.len() * 2) + 1; + let mut v: Vec = Vec::with_capacity(size); for b in hrp { v.push(u5::try_from_u8(*b >> 5).expect("can't be out of range, max. 7")); } diff --git a/stacks-common/src/deps_common/bitcoin/blockdata/script.rs b/stacks-common/src/deps_common/bitcoin/blockdata/script.rs index 748f9e2ee..f055316f2 100644 --- a/stacks-common/src/deps_common/bitcoin/blockdata/script.rs +++ b/stacks-common/src/deps_common/bitcoin/blockdata/script.rs @@ -25,6 +25,7 @@ //! use std::default::Default; +use std::mem::size_of; use std::{error, fmt}; use serde; @@ -201,8 +202,8 @@ fn build_scriptint(n: i64) -> Vec { let neg = n < 0; - let mut abs = if neg { -n } else { n } as usize; - let mut v = vec![]; + let mut abs = n.abs() as usize; + let mut v = Vec::with_capacity(size_of::() + 1); while abs > 0xFF { v.push((abs & 0xFF) as u8); abs >>= 8; diff --git a/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs b/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs index 87708334f..f92a11cd1 100644 --- a/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs +++ b/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs @@ -313,7 +313,7 @@ impl Transaction { // sha256d of the concatenation of the nSequences let mut raw_vec = vec![]; for inp in self.input.iter() { - raw_vec.append(&mut inp.sequence.to_le_bytes().to_vec()); + raw_vec.extend_from_slice(&inp.sequence.to_le_bytes()); } Sha256dHash::from_data(&raw_vec) } @@ -323,26 +323,27 @@ impl Transaction { /// does not work for codeseparator fn segwit_script_pubkey_bytes(&self, script: &Script) -> Vec { // bizarrely, if this is a p2wpkh, we have to convert it into a p2pkh - let script_bytes = script.clone().into_bytes(); + let script_bytes = script.as_bytes(); if script_bytes.len() == 22 && script_bytes[0..2] == [0x00, 0x14] { // p2wpkh --> length-prefixed p2pkh - let mut converted_script_bytes = vec![]; - converted_script_bytes.append(&mut vec![0x19, 0x76, 0xa9, 0x14]); - converted_script_bytes.append(&mut script_bytes[2..22].to_vec()); - converted_script_bytes.append(&mut vec![0x88, 0xac]); + let mut converted_script_bytes = Vec::with_capacity(26); + converted_script_bytes.extend_from_slice(&[0x19, 0x76, 0xa9, 0x14]); + converted_script_bytes.extend_from_slice(&script_bytes[2..22]); + converted_script_bytes.extend_from_slice(&[0x88, 0xac]); converted_script_bytes } else { // p2wsh or p2tr // codeseparator is not supported // prefix the script bytes with a varint length - let mut length_script = vec![]; - let mut script_bytes = script.clone().into_bytes(); - let script_len = VarInt(script_bytes.len() as u64); + let script_bytes_len = script_bytes.len(); + let script_len = VarInt(script_bytes_len as u64); + let mut length_script = + Vec::with_capacity(script_len.encoded_length() as usize + script_bytes_len); let mut script_len_bytes = serialize(&script_len).expect("FATAL: failed to encode varint"); length_script.append(&mut script_len_bytes); - length_script.append(&mut script_bytes); + length_script.extend_from_slice(&script_bytes); length_script } } @@ -353,28 +354,31 @@ impl Transaction { // hash of all output amounts and scriptpubkeys let mut raw_vec = vec![]; for outp in self.output.iter() { - raw_vec.append(&mut outp.value.to_le_bytes().to_vec()); + raw_vec.extend_from_slice(&outp.value.to_le_bytes()); - let mut script_bytes = outp.script_pubkey.clone().into_bytes(); + let script_bytes = outp.script_pubkey.as_bytes(); let script_len = VarInt(script_bytes.len() as u64); let mut script_len_bytes = serialize(&script_len).expect("FATAL: failed to encode varint"); raw_vec.append(&mut script_len_bytes); - raw_vec.append(&mut script_bytes); + raw_vec.extend_from_slice(&script_bytes); } Sha256dHash::from_data(&raw_vec) } else if sighash_type == SigHashType::Single && input_index < self.output.len() { // hash of just the output indexed by the input index - let mut raw_vec = vec![]; - let mut script_bytes = self.output[input_index].script_pubkey.clone().into_bytes(); - let script_len = VarInt(script_bytes.len() as u64); + let script_bytes = self.output[input_index].script_pubkey.as_bytes(); + let script_bytes_len = script_bytes.len(); + let script_len = VarInt(script_bytes_len as u64); + + let mut raw_vec = + Vec::with_capacity(script_len.encoded_length() as usize + script_bytes_len); let mut script_len_bytes = serialize(&script_len).expect("FATAL: failed to encode varint"); raw_vec.append(&mut script_len_bytes); - raw_vec.append(&mut script_bytes); + raw_vec.extend_from_slice(script_bytes); Sha256dHash::from_data(&raw_vec) } else { Sha256dHash([0u8; 32]) @@ -406,15 +410,15 @@ impl Transaction { SigHashType::from_u32(sighash_u32).split_anyonecanpay_flag(); // nVersion - raw_vec.append(&mut self.version.to_le_bytes().to_vec()); + raw_vec.extend_from_slice(&self.version.to_le_bytes()); // hashPrevouts let prevouts_hash = self.segwit_prevouts_hash(anyone_can_pay); - raw_vec.append(&mut prevouts_hash.as_bytes().to_vec()); + raw_vec.extend_from_slice(prevouts_hash.as_bytes()); // hashSequence let hash_sequence = self.segwit_sequence_hash(sighash, anyone_can_pay); - raw_vec.append(&mut hash_sequence.as_bytes().to_vec()); + raw_vec.extend_from_slice(hash_sequence.as_bytes()); // outpoint in question let mut outpoint_to_sign = serialize(&self.input[input_index].previous_output) @@ -426,20 +430,20 @@ impl Transaction { raw_vec.append(&mut script_code); // value sent - raw_vec.append(&mut amount.to_le_bytes().to_vec()); + raw_vec.extend_from_slice(&amount.to_le_bytes()); // input sequence - raw_vec.append(&mut self.input[input_index].sequence.to_le_bytes().to_vec()); + raw_vec.extend_from_slice(&self.input[input_index].sequence.to_le_bytes()); // hashed outputs let outputs_hash = self.segwit_outputs_hash(input_index, sighash); - raw_vec.append(&mut outputs_hash.as_bytes().to_vec()); + raw_vec.extend_from_slice(outputs_hash.as_bytes()); // locktime - raw_vec.append(&mut self.lock_time.to_le_bytes().to_vec()); + raw_vec.extend_from_slice(&self.lock_time.to_le_bytes()); // sighash - raw_vec.append(&mut sighash_u32.to_le_bytes().to_vec()); + raw_vec.extend_from_slice(&sighash_u32.to_le_bytes()); Sha256dHash::from_data(&raw_vec) } diff --git a/stacks-common/src/deps_common/bitcoin/util/hash.rs b/stacks-common/src/deps_common/bitcoin/util/hash.rs index 2c64dca01..364b5f609 100644 --- a/stacks-common/src/deps_common/bitcoin/util/hash.rs +++ b/stacks-common/src/deps_common/bitcoin/util/hash.rs @@ -419,8 +419,9 @@ pub fn bitcoin_merkle_root(data: Vec) -> Sha256dHash { return data[0]; } // Recursion - let mut next = vec![]; - for idx in 0..((data.len() + 1) / 2) { + let iterations = (data.len() + 1) / 2; + let mut next = Vec::with_capacity(iterations); + for idx in 0..iterations { let idx1 = 2 * idx; let idx2 = min(idx1 + 1, data.len() - 1); let mut encoder = RawEncoder::new(Cursor::new(vec![])); diff --git a/stacks-common/src/types/chainstate.rs b/stacks-common/src/types/chainstate.rs index ac6849dfc..d41e21225 100644 --- a/stacks-common/src/types/chainstate.rs +++ b/stacks-common/src/types/chainstate.rs @@ -190,14 +190,12 @@ impl PoxId { impl FromStr for PoxId { type Err = &'static str; fn from_str(s: &str) -> Result { - let mut result = vec![]; - for i in s.chars() { - if i == '1' { - result.push(true); - } else if i == '0' { - result.push(false); - } else { - return Err("Unexpected character in PoX ID serialization"); + let mut result = Vec::with_capacity(s.len()); + for c in s.chars() { + match c { + '0' => result.push(false), + '1' => result.push(true), + _ => return Err("Unexpected character in PoX ID serialization"), } } Ok(PoxId::new(result)) @@ -363,9 +361,7 @@ impl BlockHeaderHash { pub fn from_serialized_header(buf: &[u8]) -> BlockHeaderHash { let h = Sha512Trunc256Sum::from_data(buf); - let mut b = [0u8; 32]; - b.copy_from_slice(h.as_bytes()); - BlockHeaderHash(b) + BlockHeaderHash(h.to_bytes()) } } @@ -379,8 +375,7 @@ impl BurnchainHeaderHash { } pub fn to_bitcoin_hash(&self) -> Sha256dHash { - let mut bytes = self.0.to_vec(); - bytes.reverse(); + let bytes = self.0.iter().rev().copied().collect::>(); let mut buf = [0u8; 32]; buf.copy_from_slice(&bytes[0..32]); Sha256dHash(buf) @@ -401,10 +396,7 @@ impl BurnchainHeaderHash { bytes.extend_from_slice(index_root.as_bytes()); bytes.extend_from_slice(&noise.to_be_bytes()); let h = DoubleSha256::from_data(&bytes[..]); - let mut hb = [0u8; 32]; - hb.copy_from_slice(h.as_bytes()); - - BurnchainHeaderHash(hb) + BurnchainHeaderHash(h.to_bytes()) } } diff --git a/stacks-common/src/util/hash.rs b/stacks-common/src/util/hash.rs index c1d538f35..634cbf485 100644 --- a/stacks-common/src/util/hash.rs +++ b/stacks-common/src/util/hash.rs @@ -451,10 +451,10 @@ where /// Get a non-leaf hash pub fn get_node_hash(left: &H, right: &H) -> H { - let mut buf = vec![]; - buf.extend_from_slice(left.bits()); - buf.extend_from_slice(right.bits()); - H::from_tagged_data(MERKLE_PATH_NODE_TAG, &buf[..]) + let iter = left.bits().iter(); + let iter = iter.chain(right.bits().iter()); + let buf = iter.copied().collect::>(); + H::from_tagged_data(MERKLE_PATH_NODE_TAG, &buf) } /// Find a given hash in a merkle tree row