Skip to content

Conversation

Antonio95
Copy link
Contributor

Currently Execution storage costs are computed by generating a proof for the Authorization and checking its size, which creates an undesirable double-proving workflow (because the storage cost is an input when computing the fee-transaction proof). This PR adds:

  • A method which, given a list of batch sizes, computes the size of the corresponding (batched) Varuna proof.
  • An Authorization::proof_size method which computes the size of the Varuna proof for self by calculating the expected batch sizes and then calling the method above.
  • A consistency check to ensure the inclusion batch size from the method above coincides with that in prepare_verifier_inputs (for futureproofing)
  • An update of existing execution tests to VarunaVersion::V2 and the addition to those tests of a proof-size check (i. e. ensuring that the size of the serialized proof, once computed, coincides with the predicted size given the Authorization). In the tested cases, the predicted size is an exact match.

Since testing has happened only for a limited time of example Authorizations available in the code, any issues should be reported when this starts being tested in more complex, real-world Authorizations.

@Antonio95 Antonio95 requested review from Copilot, d0cd and vicsn October 7, 2025 15:16
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a method to compute the size of Execution proofs without needing to generate the actual proof, addressing the double-proving workflow issue where storage costs are computed by generating proofs. The key changes include:

  • Adding a proof size prediction method for Varuna proofs based on batch sizes
  • Implementing an Authorization::proof_size method that calculates expected batch sizes and predicts proof size
  • Adding consistency checks between predicted and actual batch sizes
  • Updating existing tests to use VarunaVersion::V2 and verify proof size predictions match actual serialized proof sizes

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
synthesizer/process/src/trace/mod.rs Adds consistency check for inclusion batch sizes and makes transitions iterator cloneable
synthesizer/process/src/tests/test_execute.rs Updates tests to use VarunaVersion::V2 and adds proof size validation checks
synthesizer/process/src/stack/authorization/mod.rs Implements proof_size method and number_of_input_records helper for Authorization
ledger/block/src/transaction/execution/mod.rs Makes transitions iterator cloneable to support new functionality
algorithms/src/snark/varuna/tests.rs Adds proof size validation test for Varuna V2
algorithms/src/snark/varuna/data_structures/proof.rs Implements proof_size function to calculate Varuna proof size without generating proof

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@Antonio95 Antonio95 marked this pull request as draft October 7, 2025 15:17
@Antonio95
Copy link
Contributor Author

(converted to draft due to likely conflicts with PR #2948 , fixing soon)

@Antonio95 Antonio95 marked this pull request as ready for review October 8, 2025 13:14
Copy link
Collaborator

@vicsn vicsn left a comment

Choose a reason for hiding this comment

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

LGTM besides the documentation nits

Antonio95 and others added 2 commits October 8, 2025 15:48
Co-authored-by: vicsn <victor.s.nicolaas@protonmail.com>
Signed-off-by: Antonio Mejías Gil <anmegi.95@gmail.com>
Comment on lines 409 to 412
// - batch sizes: (boils down to CanonicalSerialize for [usize])
// + one u64 for the length (the number of circuits) followed that many usize
// This contains the size information for the vectors in all other fields,
// which are therefore serialised without their length
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// - batch sizes: (boils down to CanonicalSerialize for [usize])
// + one u64 for the length (the number of circuits) followed that many usize
// This contains the size information for the vectors in all other fields,
// which are therefore serialised without their length
// - batch sizes: one `usize` for each batch size plus one `u64` for the number of batches.
// This contains the size information for all other vectors in the `Proof`, allowing them to be serialized without a length prefix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed

impl<N: Network> Eq for Authorization<N> {}

impl<N: Network> Authorization<N> {
/// Returns the (exact) predicted size of the Varuna proof of an Authorization
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
/// Returns the (exact) predicted size of the Varuna proof of an Authorization
/// Returns the size of the Varuna proof of an `Authorization`

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(function gone in later commits)

/// - `Some(size)` for `VarunaVersion::V2`, where `size` is the size of the proof in bytes.
/// - `None` for `VarunaVersion::V1`.
///
// The value returned coincides with `Proof<N: Network>::write_le()`, which
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// The value returned coincides with `Proof<N: Network>::write_le()`, which
// The value returned is equal to the number of bytes returned by `Proof<N: Network>::write_le()`, which

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(function gone in later commits)

}
}

/// Total number of inputs to the passed `Transition`s that are of type
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
/// Total number of inputs to the passed `Transition`s that are of type
/// Returns the total number of inputs to the passed `Transition`s that are of type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(addressed and also fixed other parts of the same documentation that had become outdated due to the interface change)

Inclusion::prepare_verifier_inputs(global_state_root, inclusion_version, transitions)?;
Inclusion::prepare_verifier_inputs(global_state_root, inclusion_version, transitions.clone())?;

let expected_n_inclusions = Authorization::number_of_input_records(transitions.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

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

You might not need the second clone of transitions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you, fixed

vicsn and others added 3 commits October 14, 2025 18:24
Co-authored-by: d0cd <23022326+d0cd@users.noreply.github.com>
Signed-off-by: vicsn <victor.s.nicolaas@protonmail.com>
@Antonio95
Copy link
Contributor Author

Hi @d0cd! Quite a few things have changed in the last commits:

  1. After some discussion with @vicsn, it seems the best interface for the envisioned use cases is

    pub fn execution_cost_for_authorization<N: Network>(
         process: &Process<N>,
         authorization: &Authorization<N>,
         consensus_version: ConsensusVersion,
    )
    

    which has been implemented and placed at the same location and level as

    pub fn execution_cost<N: Network>(
        process: &Process<N>,
        execution: &Execution<N>,
        consensus_version: ConsensusVersion,
    )
    

    Let me know if that looks good or you think there might be a better design (@niklaslong might also have an informed opinion on this).

  2. The Authorization::proof_size introduced in the previous commit has been removed, as it is not particularly useful given the new interface from point 1.

  3. For some reasons (*) it was convenient to create an auxiliary execution_cost_with_size() which behaved exactly like execution_cost() but received the size of the Execution instead of computing it internally. So this has been added next to execution_cost(), which now wraps around the new function but computes the size of the Execution first. This caused a prototype change in execution_cost_v1(), execution_cost_v2() and execution_cost_v3(), which have been fixed and made private (they were only used in tests). This has all been discussed with Victor.

    (*) The reasons, feel free to skip: because the storage cost is not directly execution.size_in_bytes() but a transformation of that under execution_storage_cost(), the new execution_cost_for_authorization could not simply read the storage cost returned by execution_cost() and add the proof size (because the returned value may have been non-additively modified by execution_storage_cost()). Therefore, on top of calling execution_cost(), execution_cost_for_authorization() would need to also call execution.size_in_bytes() and serialisation would thus happen twice for the same Execution. execution_cost_with_size() was introduced in order to avoid this.

  4. None of my previous fee-estimation tests involved Transitions with input records. Victor helped me find some test Executions involving such Transitions in test_vm_execute_and_finalize.rs. Since in that test there is only direct access to the Execution object (not the Authorization), I have created a test-only method

    #[cfg(feature = "test")]
    impl<N: Network> Authorization<N> {
        pub fn from_unchecked((requests, transitions): (Vec<Request<N>>, Vec<Transition<N>>)) -> Self {
            ...
        }
    }
    

    in synthesizer/process/src/stack/authorization/mod.rs in order to avoid having to create the actual Requests corresponding to the Transitions in the Execution.

  5. Small important plot twist to point 4: the only test with input records in synthesizer/tests/tests/vm/execute_and_finalize/ is mint_and_split (cf. here), which never actually consumes the records: the two calls to split are meant to fail for different reasons (visible in the expected output here). Therefore, a third call to split has been added to that test which correctly consumes a record.

With the above modifications, execute_fee_for_authorization always predicts the correct cost in all tests (including in the case where a record is consumed).

Copy link
Collaborator

@d0cd d0cd 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 to me overall!
There are a few minor nits on improving the clarity of comments. Your call on if you think these are worth addressing.

@vicsn
Copy link
Collaborator

vicsn commented Oct 16, 2025

Almost there! Besides fixing the last open comments can you merge in staging?

@vicsn
Copy link
Collaborator

vicsn commented Oct 16, 2025

I'm still seeing "This branch has conflicts that must be resolved". Can you try: git fetch origin staging && git merge origin/staging

@Antonio95
Copy link
Contributor Author

I'm still seeing "This branch has conflicts that must be resolved". Can you try: git fetch origin staging && git merge origin/staging

Yes! It's taken some effort to merge (staging had quite a few changes on the same functions I touched in the costs.rs file), but it's done now. I think it's ready to go now!

Copy link
Collaborator

@vicsn vicsn left a comment

Choose a reason for hiding this comment

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

LGTM!

@vicsn vicsn merged commit 93635d0 into staging Oct 16, 2025
6 of 7 checks passed
@vicsn vicsn deleted the proof_size branch October 16, 2025 16:45
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.

3 participants