Skip to content

Commit ae9f7bd

Browse files
committed
make static_cost functions return trait counts also
1 parent 51d8ba9 commit ae9f7bd

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

clarity/src/vm/costs/analysis.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,11 @@ fn make_ast(
207207

208208
/// STatic execution cost for functions within Environment
209209
/// returns the top level cost for specific functions
210-
/// {function_name: cost}
210+
/// {some-function-name: (CostAnalysisNode, Some({some-function-name: (1,1)}))}
211211
pub fn static_cost(
212212
env: &mut Environment,
213213
contract_identifier: &QualifiedContractIdentifier,
214-
) -> Result<HashMap<String, StaticCost>, String> {
214+
) -> Result<HashMap<String, (CostAnalysisNode, Option<TraitCount>)>, String> {
215215
let contract_source = env
216216
.global_context
217217
.database
@@ -234,19 +234,15 @@ pub fn static_cost(
234234
let epoch = env.global_context.epoch_id;
235235
let ast = make_ast(&contract_source, epoch, clarity_version)?;
236236

237-
let costs = static_cost_from_ast(&ast, clarity_version)?;
238-
Ok(costs
239-
.into_iter()
240-
.map(|(name, (cost, _trait_count))| (name, cost))
241-
.collect())
237+
static_cost_tree_from_ast(&ast, clarity_version)
242238
}
243239

244240
/// same idea as `static_cost` but returns the root of the cost analysis tree for each function
245241
/// Useful if you need to analyze specific nodes in the cost tree
246242
pub fn static_cost_tree(
247243
env: &mut Environment,
248244
contract_identifier: &QualifiedContractIdentifier,
249-
) -> Result<HashMap<String, CostAnalysisNode>, String> {
245+
) -> Result<HashMap<String, (CostAnalysisNode, Option<TraitCount>)>, String> {
250246
let contract_source = env
251247
.global_context
252248
.database
@@ -276,16 +272,23 @@ pub fn static_cost_from_ast(
276272
contract_ast: &crate::vm::ast::ContractAST,
277273
clarity_version: &ClarityVersion,
278274
) -> Result<HashMap<String, (StaticCost, Option<TraitCount>)>, String> {
279-
let cost_trees = static_cost_tree_from_ast(contract_ast, clarity_version)?;
275+
let cost_trees_with_traits = static_cost_tree_from_ast(contract_ast, clarity_version)?;
280276

281-
let trait_count = get_trait_count(&cost_trees);
282-
let costs: HashMap<String, StaticCost> = cost_trees
277+
// Extract trait_count from the first entry (all entries have the same trait_count)
278+
let trait_count = cost_trees_with_traits
279+
.values()
280+
.next()
281+
.and_then(|(_, trait_count)| trait_count.clone());
282+
283+
// Convert CostAnalysisNode to StaticCost
284+
let costs: HashMap<String, StaticCost> = cost_trees_with_traits
283285
.into_iter()
284-
.map(|(name, cost_analysis_node)| {
286+
.map(|(name, (cost_analysis_node, _))| {
285287
let summing_cost = calculate_total_cost_with_branching(&cost_analysis_node);
286288
(name, summing_cost.into())
287289
})
288290
.collect();
291+
289292
Ok(costs
290293
.into_iter()
291294
.map(|(name, cost)| (name, (cost, trait_count.clone())))
@@ -295,26 +298,39 @@ pub fn static_cost_from_ast(
295298
pub(crate) fn static_cost_tree_from_ast(
296299
ast: &crate::vm::ast::ContractAST,
297300
clarity_version: &ClarityVersion,
298-
) -> Result<HashMap<String, CostAnalysisNode>, String> {
301+
) -> Result<HashMap<String, (CostAnalysisNode, Option<TraitCount>)>, String> {
299302
let exprs = &ast.expressions;
300303
let user_args = UserArgumentsContext::new();
301304
let costs_map: HashMap<String, Option<StaticCost>> = HashMap::new();
302305
let mut costs: HashMap<String, Option<CostAnalysisNode>> = HashMap::new();
306+
// first pass extracts the function names
303307
for expr in exprs {
304308
if let Some(function_name) = extract_function_name(expr) {
305309
costs.insert(function_name, None);
306310
}
307311
}
312+
// second pass computes the cost
308313
for expr in exprs {
309314
if let Some(function_name) = extract_function_name(expr) {
310315
let (_, cost_analysis_tree) =
311316
build_cost_analysis_tree(expr, &user_args, &costs_map, clarity_version)?;
312317
costs.insert(function_name, Some(cost_analysis_tree));
313318
}
314319
}
315-
Ok(costs
320+
321+
// Build the final map with cost analysis nodes
322+
let cost_trees: HashMap<String, CostAnalysisNode> = costs
316323
.into_iter()
317324
.filter_map(|(name, cost)| cost.map(|c| (name, c)))
325+
.collect();
326+
327+
// Compute trait_count while creating the root CostAnalysisNode
328+
let trait_count = get_trait_count(&cost_trees);
329+
330+
// Return each node with its trait_count
331+
Ok(cost_trees
332+
.into_iter()
333+
.map(|(name, node)| (name, (node, trait_count.clone())))
318334
.collect())
319335
}
320336

clarity/src/vm/tests/analysis.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use stacks_common::types::StacksEpochId;
77

88
use crate::vm::contexts::OwnedEnvironment;
99
use crate::vm::costs::analysis::{
10-
build_cost_analysis_tree, get_trait_count, static_cost_from_ast, static_cost_tree_from_ast,
11-
UserArgumentsContext,
10+
build_cost_analysis_tree, static_cost_from_ast, static_cost_tree_from_ast, UserArgumentsContext,
1211
};
1312
use crate::vm::costs::ExecutionCost;
1413
use crate::vm::types::{PrincipalData, QualifiedContractIdentifier};
@@ -106,7 +105,11 @@ fn test_get_trait_count_direct() {
106105

107106
let costs = static_cost_tree_from_ast(&ast, &ClarityVersion::Clarity3).unwrap();
108107

109-
let trait_count = get_trait_count(&costs);
108+
// Extract trait_count from the result (all entries have the same trait_count)
109+
let trait_count = costs
110+
.values()
111+
.next()
112+
.and_then(|(_, trait_count)| trait_count.clone());
110113

111114
let expected = {
112115
let mut map = HashMap::new();

0 commit comments

Comments
 (0)