Skip to content

Commit 23fce5f

Browse files
committed
use lookup_reserved_functions
1 parent d6228b0 commit 23fce5f

File tree

2 files changed

+29
-165
lines changed

2 files changed

+29
-165
lines changed

clarity/src/vm/ast/static_cost/mod.rs

Lines changed: 20 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -6,163 +6,24 @@ pub use trait_counter::{
66
TraitCount, TraitCountCollector, TraitCountContext, TraitCountPropagator, TraitCountVisitor,
77
};
88

9+
use crate::vm::callables::CallableType;
910
use crate::vm::costs::analysis::{
1011
CostAnalysisNode, CostExprNode, StaticCost, SummingExecutionCost,
1112
};
12-
use crate::vm::costs::cost_functions::{linear, CostValues};
13+
use crate::vm::costs::cost_functions::linear;
1314
use crate::vm::costs::costs_1::Costs1;
1415
use crate::vm::costs::costs_2::Costs2;
1516
use crate::vm::costs::costs_3::Costs3;
1617
use crate::vm::costs::costs_4::Costs4;
1718
use crate::vm::costs::ExecutionCost;
1819
use crate::vm::errors::VmExecutionError;
19-
use crate::vm::functions::NativeFunctions;
20+
use crate::vm::functions::{lookup_reserved_functions, NativeFunctions};
2021
use crate::vm::representations::ClarityName;
2122
use crate::vm::{ClarityVersion, Value};
2223

2324
const STRING_COST_BASE: u64 = 36;
2425
const STRING_COST_MULTIPLIER: u64 = 3;
2526

26-
/// Macro to dispatch to the correct Costs module based on clarity version
27-
/// returns a function pointer to the appropriate cost function
28-
macro_rules! dispatch_cost {
29-
($version:expr, $cost_fn:ident) => {
30-
match $version {
31-
ClarityVersion::Clarity1 => Costs1::$cost_fn,
32-
ClarityVersion::Clarity2 => Costs2::$cost_fn,
33-
ClarityVersion::Clarity3 => Costs3::$cost_fn,
34-
ClarityVersion::Clarity4 => Costs4::$cost_fn,
35-
}
36-
};
37-
}
38-
39-
/// NativeFunctions -> cost via appropriate cost fn
40-
pub(crate) fn get_cost_function_for_native(
41-
function: NativeFunctions,
42-
clarity_version: &ClarityVersion,
43-
) -> Option<fn(u64) -> Result<ExecutionCost, VmExecutionError>> {
44-
use crate::vm::functions::NativeFunctions::*;
45-
46-
// Map NativeFunctions enum to cost functions
47-
match function {
48-
Add => Some(dispatch_cost!(clarity_version, cost_add)),
49-
Subtract => Some(dispatch_cost!(clarity_version, cost_sub)),
50-
Multiply => Some(dispatch_cost!(clarity_version, cost_mul)),
51-
Divide => Some(dispatch_cost!(clarity_version, cost_div)),
52-
Modulo => Some(dispatch_cost!(clarity_version, cost_mod)),
53-
Power => Some(dispatch_cost!(clarity_version, cost_pow)),
54-
Sqrti => Some(dispatch_cost!(clarity_version, cost_sqrti)),
55-
Log2 => Some(dispatch_cost!(clarity_version, cost_log2)),
56-
ToInt | ToUInt => Some(dispatch_cost!(clarity_version, cost_int_cast)),
57-
Equals => Some(dispatch_cost!(clarity_version, cost_eq)),
58-
CmpGeq => Some(dispatch_cost!(clarity_version, cost_geq)),
59-
CmpLeq => Some(dispatch_cost!(clarity_version, cost_leq)),
60-
CmpGreater => Some(dispatch_cost!(clarity_version, cost_ge)),
61-
CmpLess => Some(dispatch_cost!(clarity_version, cost_le)),
62-
BitwiseXor | BitwiseXor2 => Some(dispatch_cost!(clarity_version, cost_xor)),
63-
Not | BitwiseNot => Some(dispatch_cost!(clarity_version, cost_not)),
64-
And | BitwiseAnd => Some(dispatch_cost!(clarity_version, cost_and)),
65-
Or | BitwiseOr => Some(dispatch_cost!(clarity_version, cost_or)),
66-
Concat => Some(dispatch_cost!(clarity_version, cost_concat)),
67-
Len => Some(dispatch_cost!(clarity_version, cost_len)),
68-
AsMaxLen => Some(dispatch_cost!(clarity_version, cost_as_max_len)),
69-
ListCons => Some(dispatch_cost!(clarity_version, cost_list_cons)),
70-
ElementAt | ElementAtAlias => Some(dispatch_cost!(clarity_version, cost_element_at)),
71-
IndexOf | IndexOfAlias => Some(dispatch_cost!(clarity_version, cost_index_of)),
72-
Fold => Some(dispatch_cost!(clarity_version, cost_fold)),
73-
Map => Some(dispatch_cost!(clarity_version, cost_map)),
74-
Filter => Some(dispatch_cost!(clarity_version, cost_filter)),
75-
Append => Some(dispatch_cost!(clarity_version, cost_append)),
76-
TupleGet => Some(dispatch_cost!(clarity_version, cost_tuple_get)),
77-
TupleMerge => Some(dispatch_cost!(clarity_version, cost_tuple_merge)),
78-
TupleCons => Some(dispatch_cost!(clarity_version, cost_tuple_cons)),
79-
ConsSome => Some(dispatch_cost!(clarity_version, cost_some_cons)),
80-
ConsOkay => Some(dispatch_cost!(clarity_version, cost_ok_cons)),
81-
ConsError => Some(dispatch_cost!(clarity_version, cost_err_cons)),
82-
DefaultTo => Some(dispatch_cost!(clarity_version, cost_default_to)),
83-
UnwrapRet => Some(dispatch_cost!(clarity_version, cost_unwrap_ret)),
84-
UnwrapErrRet => Some(dispatch_cost!(clarity_version, cost_unwrap_err_or_ret)),
85-
IsOkay => Some(dispatch_cost!(clarity_version, cost_is_okay)),
86-
IsNone => Some(dispatch_cost!(clarity_version, cost_is_none)),
87-
IsErr => Some(dispatch_cost!(clarity_version, cost_is_err)),
88-
IsSome => Some(dispatch_cost!(clarity_version, cost_is_some)),
89-
Unwrap => Some(dispatch_cost!(clarity_version, cost_unwrap)),
90-
UnwrapErr => Some(dispatch_cost!(clarity_version, cost_unwrap_err)),
91-
TryRet => Some(dispatch_cost!(clarity_version, cost_try_ret)),
92-
If => Some(dispatch_cost!(clarity_version, cost_if)),
93-
Match => Some(dispatch_cost!(clarity_version, cost_match)),
94-
Begin => Some(dispatch_cost!(clarity_version, cost_begin)),
95-
Let => Some(dispatch_cost!(clarity_version, cost_let)),
96-
Asserts => Some(dispatch_cost!(clarity_version, cost_asserts)),
97-
Hash160 => Some(dispatch_cost!(clarity_version, cost_hash160)),
98-
Sha256 => Some(dispatch_cost!(clarity_version, cost_sha256)),
99-
Sha512 => Some(dispatch_cost!(clarity_version, cost_sha512)),
100-
Sha512Trunc256 => Some(dispatch_cost!(clarity_version, cost_sha512t256)),
101-
Keccak256 => Some(dispatch_cost!(clarity_version, cost_keccak256)),
102-
Secp256k1Recover => Some(dispatch_cost!(clarity_version, cost_secp256k1recover)),
103-
Secp256k1Verify => Some(dispatch_cost!(clarity_version, cost_secp256k1verify)),
104-
Print => Some(dispatch_cost!(clarity_version, cost_print)),
105-
ContractCall => Some(dispatch_cost!(clarity_version, cost_contract_call)),
106-
ContractOf => Some(dispatch_cost!(clarity_version, cost_contract_of)),
107-
PrincipalOf => Some(dispatch_cost!(clarity_version, cost_principal_of)),
108-
AtBlock => Some(dispatch_cost!(clarity_version, cost_at_block)),
109-
// => Some(dispatch_cost!(clarity_version, cost_create_map)),
110-
// => Some(dispatch_cost!(clarity_version, cost_create_var)),
111-
// ContractStorage => Some(dispatch_cost!(clarity_version, cost_contract_storage)),
112-
FetchEntry => Some(dispatch_cost!(clarity_version, cost_fetch_entry)),
113-
SetEntry => Some(dispatch_cost!(clarity_version, cost_set_entry)),
114-
FetchVar => Some(dispatch_cost!(clarity_version, cost_fetch_var)),
115-
SetVar => Some(dispatch_cost!(clarity_version, cost_set_var)),
116-
GetBlockInfo => Some(dispatch_cost!(clarity_version, cost_block_info)),
117-
GetBurnBlockInfo => Some(dispatch_cost!(clarity_version, cost_burn_block_info)),
118-
GetStxBalance => Some(dispatch_cost!(clarity_version, cost_stx_balance)),
119-
StxTransfer => Some(dispatch_cost!(clarity_version, cost_stx_transfer)),
120-
StxTransferMemo => Some(dispatch_cost!(clarity_version, cost_stx_transfer_memo)),
121-
StxGetAccount => Some(dispatch_cost!(clarity_version, cost_stx_account)),
122-
MintToken => Some(dispatch_cost!(clarity_version, cost_ft_mint)),
123-
MintAsset => Some(dispatch_cost!(clarity_version, cost_nft_mint)),
124-
TransferToken => Some(dispatch_cost!(clarity_version, cost_ft_transfer)),
125-
GetTokenBalance => Some(dispatch_cost!(clarity_version, cost_ft_balance)),
126-
GetTokenSupply => Some(dispatch_cost!(clarity_version, cost_ft_get_supply)),
127-
BurnToken => Some(dispatch_cost!(clarity_version, cost_ft_burn)),
128-
TransferAsset => Some(dispatch_cost!(clarity_version, cost_nft_transfer)),
129-
GetAssetOwner => Some(dispatch_cost!(clarity_version, cost_nft_owner)),
130-
BurnAsset => Some(dispatch_cost!(clarity_version, cost_nft_burn)),
131-
BuffToIntLe => Some(dispatch_cost!(clarity_version, cost_buff_to_int_le)),
132-
BuffToUIntLe => Some(dispatch_cost!(clarity_version, cost_buff_to_uint_le)),
133-
BuffToIntBe => Some(dispatch_cost!(clarity_version, cost_buff_to_int_be)),
134-
BuffToUIntBe => Some(dispatch_cost!(clarity_version, cost_buff_to_uint_be)),
135-
ToConsensusBuff => Some(dispatch_cost!(clarity_version, cost_to_consensus_buff)),
136-
FromConsensusBuff => Some(dispatch_cost!(clarity_version, cost_from_consensus_buff)),
137-
IsStandard => Some(dispatch_cost!(clarity_version, cost_is_standard)),
138-
PrincipalDestruct => Some(dispatch_cost!(clarity_version, cost_principal_destruct)),
139-
PrincipalConstruct => Some(dispatch_cost!(clarity_version, cost_principal_construct)),
140-
AsContract | AsContractSafe => Some(dispatch_cost!(clarity_version, cost_as_contract)),
141-
StringToInt => Some(dispatch_cost!(clarity_version, cost_string_to_int)),
142-
StringToUInt => Some(dispatch_cost!(clarity_version, cost_string_to_uint)),
143-
IntToAscii => Some(dispatch_cost!(clarity_version, cost_int_to_ascii)),
144-
IntToUtf8 => Some(dispatch_cost!(clarity_version, cost_int_to_utf8)),
145-
BitwiseLShift => Some(dispatch_cost!(clarity_version, cost_bitwise_left_shift)),
146-
BitwiseRShift => Some(dispatch_cost!(clarity_version, cost_bitwise_right_shift)),
147-
Slice => Some(dispatch_cost!(clarity_version, cost_slice)),
148-
ReplaceAt => Some(dispatch_cost!(clarity_version, cost_replace_at)),
149-
GetStacksBlockInfo => Some(dispatch_cost!(clarity_version, cost_block_info)),
150-
GetTenureInfo => Some(dispatch_cost!(clarity_version, cost_block_info)),
151-
ContractHash => Some(dispatch_cost!(clarity_version, cost_contract_hash)),
152-
ToAscii => Some(dispatch_cost!(clarity_version, cost_to_ascii)),
153-
InsertEntry => Some(dispatch_cost!(clarity_version, cost_set_entry)),
154-
DeleteEntry => Some(dispatch_cost!(clarity_version, cost_set_entry)),
155-
StxBurn => Some(dispatch_cost!(clarity_version, cost_stx_transfer)),
156-
Secp256r1Verify => Some(dispatch_cost!(clarity_version, cost_secp256r1verify)),
157-
RestrictAssets => Some(dispatch_cost!(clarity_version, cost_restrict_assets)),
158-
AllowanceWithStx => None, // TODO: add cost function
159-
AllowanceWithFt => None, // TODO: add cost function
160-
AllowanceWithNft => None, // TODO: add cost function
161-
AllowanceWithStacking => None, // TODO: add cost function
162-
AllowanceAll => None, // TODO: add cost function
163-
}
164-
}
165-
16627
pub(crate) fn calculate_function_cost(
16728
function_name: String,
16829
cost_map: &HashMap<String, Option<StaticCost>>,
@@ -238,14 +99,24 @@ pub(crate) fn calculate_function_cost_from_native_function(
23899
arg_count: u64,
239100
clarity_version: &ClarityVersion,
240101
) -> Result<StaticCost, String> {
241-
let cost_function = match get_cost_function_for_native(native_function, clarity_version) {
242-
Some(cost_fn) => cost_fn,
243-
None => {
244-
return Ok(StaticCost::ZERO);
245-
}
246-
};
102+
let cost_function =
103+
match lookup_reserved_functions(native_function.to_string().as_str(), clarity_version) {
104+
Some(CallableType::NativeFunction(_, _, cost_fn)) => cost_fn,
105+
Some(CallableType::NativeFunction205(_, _, cost_fn, _)) => cost_fn,
106+
Some(CallableType::SpecialFunction(_, _)) => return Ok(StaticCost::ZERO),
107+
Some(CallableType::UserFunction(_)) => return Ok(StaticCost::ZERO), // TODO ?
108+
None => {
109+
return Ok(StaticCost::ZERO);
110+
}
111+
};
247112

248-
let cost = get_costs(cost_function, arg_count)?;
113+
let cost = match clarity_version {
114+
ClarityVersion::Clarity1 => cost_function.eval::<Costs1>(arg_count),
115+
ClarityVersion::Clarity2 => cost_function.eval::<Costs2>(arg_count),
116+
ClarityVersion::Clarity3 => cost_function.eval::<Costs3>(arg_count),
117+
ClarityVersion::Clarity4 => cost_function.eval::<Costs4>(arg_count),
118+
}
119+
.map_err(|e| format!("Cost calculation error: {:?}", e))?;
249120
Ok(StaticCost {
250121
min: cost.clone(),
251122
max: cost,

clarity/src/vm/costs/analysis.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -681,35 +681,28 @@ mod tests {
681681
let source = r#"(concat "hello" "world")"#;
682682
let cost = static_cost_native_test(source, &ClarityVersion::Clarity3).unwrap();
683683

684-
// For concat with 2 arguments:
685-
// linear(2, 37, 220) = 37*2 + 220 = 294
686-
assert_eq!(cost.min.runtime, 294);
687-
assert_eq!(cost.max.runtime, 294);
684+
assert_eq!(cost.min.runtime, 366);
685+
assert_eq!(cost.max.runtime, 366);
688686
}
689687

690688
#[test]
691689
fn test_string_len_min_max() {
692690
let source = r#"(len "hello")"#;
693691
let cost = static_cost_native_test(source, &ClarityVersion::Clarity3).unwrap();
694692

695-
// cost: 429 (constant) - len doesn't depend on string size
696-
assert_eq!(cost.min.runtime, 429);
697-
assert_eq!(cost.max.runtime, 429);
693+
assert_eq!(cost.min.runtime, 612);
694+
assert_eq!(cost.max.runtime, 612);
698695
}
699696

700697
#[test]
701698
fn test_branching() {
702699
let source = "(if (> 3 0) (ok (concat \"hello\" \"world\")) (ok \"asdf\"))";
703700
let cost = static_cost_native_test(source, &ClarityVersion::Clarity3).unwrap();
704-
// min: 147 raw string
705-
// max: 294 (concat)
706-
707-
// ok = 199
708-
// if = 168
709-
// ge = (linear(n, 7, 128)))
710-
let base_cost = 168 + ((2 * 7) + 128) + 199;
711-
assert_eq!(cost.min.runtime, base_cost + 147);
712-
assert_eq!(cost.max.runtime, base_cost + 294);
701+
// min: raw string
702+
// max: concat
703+
704+
assert_eq!(cost.min.runtime, 346);
705+
assert_eq!(cost.max.runtime, 565);
713706
}
714707

715708
// ---- ExprTreee building specific tests

0 commit comments

Comments
 (0)