Merge branch 'next' into mutants/optimisations

This commit is contained in:
ASuciuX
2024-02-28 15:10:27 +02:00
committed by GitHub
26 changed files with 142 additions and 125 deletions

View File

@@ -237,14 +237,13 @@ pub struct ContractInterfaceFunctionArg {
impl ContractInterfaceFunctionArg {
pub fn from_function_args(fnArgs: &[FunctionArg]) -> Vec<ContractInterfaceFunctionArg> {
let mut args: Vec<ContractInterfaceFunctionArg> = 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()
}
}

View File

@@ -526,7 +526,7 @@ impl<'a, 'b> TypeChecker<'a, 'b> {
args: &[SymbolicExpression],
context: &TypingContext,
) -> CheckResult<Vec<TypeSignature>> {
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)?)

View File

@@ -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| {

View File

@@ -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) => {

View File

@@ -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<Vec<TypeSignature>> {
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)?)

View File

@@ -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,

View File

@@ -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) => {

View File

@@ -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::<Vec<_>>();
let error = ParseError::new(ParseErrors::CircularReference(functions_names));
return Err(error);

View File

@@ -894,12 +894,14 @@ impl<'a> Parser<'a> {
Some(expr)
}
Token::Utf8String(s) => {
let mut data: Vec<Vec<u8>> = 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<Vec<u8>> = 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,

View File

@@ -65,7 +65,7 @@ impl SugarExpander {
pre_exprs_iter: PreExpressionsDrain,
contract_ast: &mut ContractAST,
) -> ParseResult<Vec<SymbolicExpression>> {
let mut expressions: Vec<SymbolicExpression> = Vec::new();
let mut expressions: Vec<SymbolicExpression> = Vec::with_capacity(pre_exprs_iter.len());
#[cfg(feature = "developer-mode")]
let mut comments = Vec::new();

View File

@@ -95,6 +95,10 @@ impl PreExpressionsDrain {
index: 0,
}
}
pub fn len(&self) -> usize {
self.len
}
}
impl Iterator for PreExpressionsDrain {

View File

@@ -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::<Vec<_>>();
executed_lines.sort_by_key(|f| f.0);
coverage.insert(contract.to_string(), executed_lines);

View File

@@ -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 {

View File

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

View File

@@ -701,7 +701,7 @@ pub fn parse_eval_bindings(
env: &mut Environment,
context: &LocalContext,
) -> Result<Vec<(ClarityName, Value)>> {
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)))
})?;

View File

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

View File

@@ -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<u8> = 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::<Vec<_>>();
// check the string size
StringUTF8Length::try_from(data.len())?;

View File

@@ -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)?;

View File

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

View File

@@ -180,7 +180,10 @@ const C32_CHARACTERS_MAP: [Option<u8>; 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<Vec<u8>, Error> {
}
fn c32_decode_ascii(input_str: &str) -> Result<Vec<u8>, 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::<u8>::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<Vec<u8>, 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;

View File

@@ -599,7 +599,8 @@ fn verify_checksum(hrp: &[u8], data: &[u5]) -> Option<Variant> {
}
fn hrp_expand(hrp: &[u8]) -> Vec<u5> {
let mut v: Vec<u5> = Vec::new();
let size = (hrp.len() * 2) + 1;
let mut v: Vec<u5> = 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"));
}

View File

@@ -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<u8> {
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::<usize>() + 1);
while abs > 0xFF {
v.push((abs & 0xFF) as u8);
abs >>= 8;

View File

@@ -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<u8> {
// 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)
}

View File

@@ -419,8 +419,9 @@ pub fn bitcoin_merkle_root(data: Vec<Sha256dHash>) -> 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![]));

View File

@@ -190,14 +190,12 @@ impl PoxId {
impl FromStr for PoxId {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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::<Vec<_>>();
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())
}
}

View File

@@ -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::<Vec<_>>();
H::from_tagged_data(MERKLE_PATH_NODE_TAG, &buf)
}
/// Find a given hash in a merkle tree row