Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sierra gas resource tracking #3049

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

THenry14
Copy link
Contributor

@THenry14 THenry14 commented Mar 6, 2025

Related to #2977

This PR stack aims to add support for new resource tracking (sierra-gas) and new gas representation (GasVector triplet instead of single l1 gas value).

--> (This PR) Add sierra gas tracking
-- (#3050) Run already existing tests with CairoSteps set explicitly
-- (#3051) Add support for sierra gas in --detailed-resources
-- (#3052) Add support for sierra gas in --save-trace-data
-- (#3053) Add sierra version assertion
-- (#3054) Introduce new gas representation
-- (#3055) Add gas tests for sierra-gas tracking
-- (#3056) Update docs with sierra-gas related changes

@THenry14 THenry14 force-pushed the szymczyk/sg-1-add-sierra-gas-tracking branch from 56e4694 to 6169638 Compare March 6, 2025 12:56
Comment on lines 801 to 830
fn n_steps_to_sierra_gas(n_steps: usize, versioned_constants: &VersionedConstants) -> GasAmount {
let n_steps_u64 = u64_from_usize(n_steps);
let gas_per_step = versioned_constants
.os_constants
.gas_costs
.base
.step_gas_cost;
let n_steps_gas_cost = n_steps_u64.checked_mul(gas_per_step).unwrap_or_else(|| {
panic!(
"Multiplication overflow while converting steps to gas. steps: {n_steps}, gas per step: {gas_per_step}."
)
});
GasAmount(n_steps_gas_cost)
}

#[must_use]
pub fn vm_resources_to_sierra_gas(
resources: &ExecutionResources,
versioned_constants: &VersionedConstants,
) -> GasAmount {
let builtins_gas_cost =
builtins_to_sierra_gas(&resources.prover_builtins(), versioned_constants);
let n_steps_gas_cost = n_steps_to_sierra_gas(resources.total_n_steps(), versioned_constants);
n_steps_gas_cost.checked_add(builtins_gas_cost).unwrap_or_else(|| {
panic!(
"Addition overflow while converting vm resources to gas. steps gas: {n_steps_gas_cost}, \
builtins gas: {builtins_gas_cost}."
)
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Sierra gas calculated this way exactly the same as real Sierra gas calculated when executing with Cairo-native?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question was not related to the conversion logic. I was wondering because what we generally do is not exactly tracking Sierra resources, but rather tracking VM resources and then converting them to Sierra resources. So my question is, are we sure that executing the same transaction with cairo-native will result in exactly the same Sierra gas as calculated in snforge with the current logic? According to the starknet documentation, it seems that this may not necessarily be the case. Please correct me if I am wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not really true - we are tracking sierra resources, but the execution comes through the vm (because at the moment, we do not support cairo native execution in forge; I believe it is not even yet planned). We are converting things here, because vm has some pre-defined "spin-up" cost that is given in steps and builtins - which are not the way to describe execution cost when tracking sierra gas; when going through native the same cost would be described in sierra gas.

Regarding the docs you've linked (and answering the question) - we are as sure as we can be running thrugh vm. The cost when tracking sierra gas should not differ regardless of the environment, but we'll never be 100% sure as long as we do not support native, I guess. To reiterate my point from the previous paragraph - we are not tracking cairo steps and converting them; we are tracking sierra gas, and take them as they are reported by the vm, no conversion there. The docs state that there will be some mismatch because of the cost of the resources and max vs sum approach - which is true and you can actually observe it in the tests I added in #3055, where identical tests yield different costs depending on the tracked resource.

Hope that answers your question, but if something still seems off please let me know 🙏

Comment on lines +192 to +195
match &context
.tracked_resource_stack
.last()
.expect("Unexpected empty tracked resource.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, but maybe these should be passed as an argument to this function instead of taking them of the stack? For me it's like a post execution callback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite the contrast from this comment by Darek #3049 (comment) :D

My rationale for doing this here was that we already have a context, so there was really no need to do it this way, but I'm fine with either one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't have a strong opinion on this, we can keep this as is

resources -= &versioned_constants.get_additional_os_syscall_resources(syscall_counter);
}
TrackedResource::SierraGas => {
let syscalls_consumed_gas: u64 = syscall_counter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should already rebase ourselves to new changes to main-0.13.4 branch in blockifier (rebase my fork).

They've removed the syscall_counter and replaced it with a similar structure with different name and layout.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any changes on our side regarding this? if not I'd rather not, as this is out od scope of what this PR is supposed to do. If yes, I can add a PR to this stack with required changes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just this but didn't verify in details. They actually already have main-0.13.5 branch now.

l1_handler_payload_lengths,
l2_to_l1_payload_lengths,
}
}

fn n_steps_to_sierra_gas(n_steps: usize, versioned_constants: &VersionedConstants) -> GasAmount {
let n_steps_u64 = u64_from_usize(n_steps);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What it does exactly? Why not just unwrap/expect here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does exactly what you said it should. But hey have a helper for this in blockifier (and use it), so I figured - what the heck I'll use it too. If you rather not, I can change it to regular expect(). 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean maybe there is a reason they do that. I'm fine with either.

Comment on lines +770 to +776
let syscalls_consumed_gas: u64 = top_call_syscalls
.iter()
.map(|(name, count)| {
versioned_constants.get_syscall_gas_cost(name) * (*count as u64)
})
.sum();
sierra_gas_consumed += syscalls_consumed_gas;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar code is used in remove_syscall_resources_and_exit_success_call. Maybe it'd make sense to reuse it as a function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be sure - You only mean the part of fetching consumed gas by syscalls, right?
I can do it if you think this will bring us some gains, but personaly I find it too trivial and not really worth it to make a separate function out of 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole logic. It's not necessary, but we are kind of repeating ourselves with this.

Suggested change
let syscalls_consumed_gas: u64 = top_call_syscalls
.iter()
.map(|(name, count)| {
versioned_constants.get_syscall_gas_cost(name) * (*count as u64)
})
.sum();
sierra_gas_consumed += syscalls_consumed_gas;
let syscalls_consumed_gas: u64 = top_call_syscalls
.iter()
.map(|(name, count)| {
versioned_constants.get_syscall_gas_cost(name) * (*count as u64)
})
.sum();
sierra_gas_consumed += syscalls_consumed_gas;

@@ -83,7 +87,7 @@ pub fn run_config_pass(
let string_to_hint = hints_by_representation(&assembled_program);
let hints_dict = hints_to_params(&assembled_program);

let mut context = build_context(&block_info, None);
let mut context = build_context(&block_info, None, &TrackedResource::from(tracked_resource));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it matters for config pass anyway. But if you already added the logic to provide correct resource here, we can keep it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm not sure I follow :( Can you rephrase or specify please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is specifically for the so called 'configuration run' which doesn't execute any tests and only collect configuration from attributes. Tracking resources here does not matter as they are not counted for anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is true 👍 But I still don't know if any/what action is needed from me here :D

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that you probably didn't need to provide correct tracked_resource here and could just hardcode some value. But no need to change that.

Copy link
Member

@cptartur cptartur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just please address the comments if needed

Comment on lines +192 to +195
match &context
.tracked_resource_stack
.last()
.expect("Unexpected empty tracked resource.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't have a strong opinion on this, we can keep this as is

resources -= &versioned_constants.get_additional_os_syscall_resources(syscall_counter);
}
TrackedResource::SierraGas => {
let syscalls_consumed_gas: u64 = syscall_counter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just this but didn't verify in details. They actually already have main-0.13.5 branch now.

Comment on lines +770 to +776
let syscalls_consumed_gas: u64 = top_call_syscalls
.iter()
.map(|(name, count)| {
versioned_constants.get_syscall_gas_cost(name) * (*count as u64)
})
.sum();
sierra_gas_consumed += syscalls_consumed_gas;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole logic. It's not necessary, but we are kind of repeating ourselves with this.

Suggested change
let syscalls_consumed_gas: u64 = top_call_syscalls
.iter()
.map(|(name, count)| {
versioned_constants.get_syscall_gas_cost(name) * (*count as u64)
})
.sum();
sierra_gas_consumed += syscalls_consumed_gas;
let syscalls_consumed_gas: u64 = top_call_syscalls
.iter()
.map(|(name, count)| {
versioned_constants.get_syscall_gas_cost(name) * (*count as u64)
})
.sum();
sierra_gas_consumed += syscalls_consumed_gas;

l1_handler_payload_lengths,
l2_to_l1_payload_lengths,
}
}

fn n_steps_to_sierra_gas(n_steps: usize, versioned_constants: &VersionedConstants) -> GasAmount {
let n_steps_u64 = u64_from_usize(n_steps);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean maybe there is a reason they do that. I'm fine with either.

Comment on lines +822 to +823
// region: Modified blockifier code
// https://github.com/starkware-libs/sequencer/blob/main-v0.13.4/crates/blockifier/src/bouncer.rs#L320
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit but maybe we can just do that

Suggested change
// region: Modified blockifier code
// https://github.com/starkware-libs/sequencer/blob/main-v0.13.4/crates/blockifier/src/bouncer.rs#L320
// Based on https://github.com/starkware-libs/sequencer/blob/main-v0.13.4/crates/blockifier/src/bouncer.rs#L320

if we aren't marking specific modified parts anyway. Or you can mark the modified parts in code

@@ -83,7 +87,7 @@ pub fn run_config_pass(
let string_to_hint = hints_by_representation(&assembled_program);
let hints_dict = hints_to_params(&assembled_program);

let mut context = build_context(&block_info, None);
let mut context = build_context(&block_info, None, &TrackedResource::from(tracked_resource));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that you probably didn't need to provide correct tracked_resource here and could just hardcode some value. But no need to change that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants