Skip to content

Commit 505cdfb

Browse files
authored
Merge pull request #5862 from bestmike007/feat/immutable-tracker-data
feat: compute_cost should borrow immutable TrackerData
2 parents 957dbc7 + 348c9cf commit 505cdfb

File tree

3 files changed

+42
-24
lines changed

3 files changed

+42
-24
lines changed

clarity/src/vm/contexts.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,11 @@ impl<'a, 'hooks> OwnedEnvironment<'a, 'hooks> {
799799
self.context.cost_track.get_total()
800800
}
801801

802+
#[cfg(any(test, feature = "testing"))]
803+
pub fn mut_cost_tracker(&mut self) -> &mut LimitedCostTracker {
804+
&mut self.context.cost_track
805+
}
806+
802807
/// Destroys this environment, returning ownership of its database reference.
803808
/// If the context wasn't top-level (i.e., it had uncommitted data), return None,
804809
/// because the database is not guaranteed to be in a sane state.

clarity/src/vm/costs/mod.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use crate::vm::types::Value::UInt;
3838
use crate::vm::types::{
3939
FunctionType, PrincipalData, QualifiedContractIdentifier, TupleData, TypeSignature,
4040
};
41-
use crate::vm::{eval_all, ClarityName, SymbolicExpression, Value};
41+
use crate::vm::{CallStack, ClarityName, Environment, LocalContext, SymbolicExpression, Value};
4242

4343
pub mod constants;
4444
pub mod cost_functions;
@@ -331,7 +331,7 @@ pub struct TrackerData {
331331
/// if the cost tracker is non-free, this holds the StacksEpochId that should be used to evaluate
332332
/// the Clarity cost functions. If the tracker *is* free, then those functions do not need to be
333333
/// evaluated, so no epoch identifier is necessary.
334-
epoch: StacksEpochId,
334+
pub epoch: StacksEpochId,
335335
mainnet: bool,
336336
chain_id: u32,
337337
}
@@ -1053,8 +1053,8 @@ pub fn parse_cost(
10531053

10541054
// TODO: add tests from mutation testing results #4832
10551055
#[cfg_attr(test, mutants::skip)]
1056-
fn compute_cost(
1057-
cost_tracker: &mut TrackerData,
1056+
pub fn compute_cost(
1057+
cost_tracker: &TrackerData,
10581058
cost_function_reference: ClarityCostFunctionReference,
10591059
input_sizes: &[u64],
10601060
eval_in_epoch: StacksEpochId,
@@ -1073,7 +1073,7 @@ fn compute_cost(
10731073

10741074
let cost_contract = cost_tracker
10751075
.cost_contracts
1076-
.get_mut(&cost_function_reference.contract_id)
1076+
.get(&cost_function_reference.contract_id)
10771077
.ok_or(CostErrors::CostComputationFailed(format!(
10781078
"CostFunction not found: {cost_function_reference}"
10791079
)))?;
@@ -1088,14 +1088,23 @@ fn compute_cost(
10881088
)));
10891089
}
10901090

1091-
let function_invocation = [SymbolicExpression::list(program)];
1091+
let function_invocation = SymbolicExpression::list(program);
1092+
let eval_result = global_context.execute(|global_context| {
1093+
let context = LocalContext::new();
1094+
let mut call_stack = CallStack::new();
1095+
let publisher: PrincipalData = cost_contract.contract_identifier.issuer.clone().into();
1096+
let mut env = Environment::new(
1097+
global_context,
1098+
cost_contract,
1099+
&mut call_stack,
1100+
Some(publisher.clone()),
1101+
Some(publisher.clone()),
1102+
None,
1103+
);
10921104

1093-
let eval_result = eval_all(
1094-
&function_invocation,
1095-
cost_contract,
1096-
&mut global_context,
1097-
None,
1098-
);
1105+
let result = super::eval(&function_invocation, &mut env, &context)?;
1106+
Ok(Some(result))
1107+
});
10991108

11001109
parse_cost(&cost_function_reference.to_string(), eval_result)
11011110
}

stackslib/src/clarity_vm/tests/costs.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ use clarity::vm::contexts::{
2424
use clarity::vm::contracts::Contract;
2525
use clarity::vm::costs::cost_functions::ClarityCostFunction;
2626
use clarity::vm::costs::{
27-
parse_cost, ClarityCostFunctionEvaluator, ClarityCostFunctionReference, CostErrors,
28-
DefaultVersion, ExecutionCost, LimitedCostTracker, COSTS_1_NAME, COSTS_2_NAME, COSTS_3_NAME,
27+
compute_cost, parse_cost, ClarityCostFunctionEvaluator, ClarityCostFunctionReference,
28+
CostErrors, DefaultVersion, ExecutionCost, LimitedCostTracker, COSTS_1_NAME, COSTS_2_NAME,
29+
COSTS_3_NAME,
2930
};
3031
use clarity::vm::database::{ClarityDatabase, MemoryBackingStore};
3132
use clarity::vm::errors::{CheckErrors, Error, RuntimeErrorType};
@@ -885,19 +886,16 @@ fn eval_cost_fn(
885886
let mainnet = owned_env.is_mainnet();
886887
let boot_costs_id = boot_code_id(cost_contract_name, mainnet);
887888
let cost_fn_name = cost_fn.get_name_str();
888-
889-
let exec = format!("({cost_fn_name} u{argument})");
890-
891-
let exec_result = owned_env
892-
.eval_read_only(&boot_costs_id, &exec)
893-
.map(|(value, _, _)| Some(value));
894-
889+
let cost_tracker = owned_env.mut_cost_tracker();
890+
let data = match cost_tracker {
891+
LimitedCostTracker::Free => panic!(),
892+
LimitedCostTracker::Limited(data) => data,
893+
};
895894
let clarity_cost_fn_ref = ClarityCostFunctionReference {
896895
contract_id: boot_costs_id,
897896
function_name: cost_fn_name.to_string(),
898897
};
899-
900-
parse_cost(&clarity_cost_fn_ref.to_string(), exec_result)
898+
compute_cost(data, clarity_cost_fn_ref, &[argument], data.epoch)
901899
}
902900

903901
fn eval_replaced_cost_fn(
@@ -926,7 +924,13 @@ fn proptest_cost_fn(cost_fn: &ClarityCostFunction, cost_contract_name: &str) {
926924
inputs.push(2u64.pow(i) + 1);
927925
});
928926
for use_mainnet in [true, false] {
929-
with_owned_env(StacksEpochId::latest(), use_mainnet, |mut owned_env| {
927+
let epoch = match cost_contract_name {
928+
COSTS_1_NAME => StacksEpochId::Epoch20,
929+
COSTS_2_NAME => StacksEpochId::Epoch2_05,
930+
COSTS_3_NAME => StacksEpochId::latest(),
931+
_ => panic!(),
932+
};
933+
with_owned_env(epoch, use_mainnet, |mut owned_env| {
930934
for i in inputs.iter() {
931935
eprintln!("Evaluating {cost_contract_name}.{cost_fn}({i})");
932936
let clar_evaled = eval_cost_fn(&mut owned_env, cost_contract_name, cost_fn, *i);

0 commit comments

Comments
 (0)