Add gas accounting tests for confidential transfers - #418
Draft
ganymedio wants to merge 2 commits into
Draft
Conversation
…on gated The bulletproofs.verify.base_batch_* parameters only exist from RELEASE_V1_28. Below that version parameter resolution leaves them at zero rather than failing, so a confidential transfer is still accepted but pays nothing for verifying its two batched range proofs. Add a test that runs the same transfer at the current gas feature version and at RELEASE_V1_27, asserting the transfer succeeds either way and that the gap between the two is exactly the sum of the two parameters. RELEASE_V1_28 gates only those parameters, so the delta is fully attributable to them. Extract confidential_transfer_payload out of run_confidential_transfer so the test can submit the same payload through run_raw and read the gas charged.
Breaks a transfer's gas down by operation using the gas profiler, asserting that the two batched range proofs are charged exactly their parameters and remain the largest single line item, and printing the rest so a shift in composition is visible. The breakdown shows range-proof verification at 52% of a transfer, other ristretto255 natives at 17%, and Move interpreter overhead at 22%, the last of which is driven by large instruction counts building and copying vectors of points and scalars. Intrinsic and storage costs are negligible.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two tests for the gas accounting of a confidential transfer.
confidential_transfer_batch_rangeproof_gas_is_version_gatedruns the same transfer at the current gas feature version and atRELEASE_V1_27, asserting that it succeeds at both and that the gas difference is exactlybulletproofs.verify.base_batch_8_bits_16plusbulletproofs.verify.base_batch_4_bits_16, over the gas unit scaling factor.confidential_transfer_gas_profilebreaks a transfer down by operation with the gas profiler, asserting the two batched range proofs are charged exactly their parameters and remain the largest single line item, and printing the rest so a shift in composition is visible.Why the version gate matters
A transfer verifies two batched range proofs, over the 8 chunks of the new balance and the 4 chunks of the transfer amount. Their gas parameters are gated
RELEASE_V1_28... Below that version they are absent from the schedule, andfrom_on_chain_gas_scheduleleaves absent entries at theirzeros()initial value rather than returning an error, socharge_batch_gascharges nothing. The batch path has no base or per-byte parameter to fall back on, unlike the non-batch path.So a chain running a gas schedule below
RELEASE_V1_28accepts confidential transfers without charging for the dominant part of their verification cost. Nothing in the suite covered this, becauseMoveHarnessbuilds its schedule atLATEST_GAS_FEATURE_VERSION, so the tests have only ever exercised the priced path.RELEASE_V1_28gates the 20base_batchparameters and nothing else, so pinning one version below makes the whole delta attributable to batched range-proof verification.What the profile shows
The test prints gas in the e2e harness's units, where
gas_unit_scaling_factoris 1,000,000. Mainnet and testnet run at ~50,000, a 20x finer unit, so the right-hand column converts for scale. A transfer is 366 harness units, roughly 7,320 on mainnet.verify_batch_range_proof_internalx2ristretto255nativesOnly the first row is exact:
(120974478 + 69359728)internal gas, divided by 1,000,000 for the harness column and by 50,000 for the mainnet one. The middle rows are sums of individually-rounded line items and are approximate.The interpreter share comes from instruction counts rather than expensive instructions: 20,092
copy_loc, 18,322create_ty, 11,233move_loc, 8,245st_loc, 4,338vec_push_back, all building and copying vectors of points and scalars. The other-natives share is dominated by 110point_decompressand 93point_compresscalls, so points are round-tripped between representations rather than held in one.Intrinsic cost is negligible, so transaction payload size is not a factor despite the size of the proofs.
Also
Extracts
confidential_transfer_payloadout ofrun_confidential_transferso both tests can submit the same payload throughrun_rawandevaluate_gas_with_profiler. No behaviour change for existing callers.Verification
All 16 tests in the module pass, the 14 pre-existing ones included:
The version-gate test reports:
190 is
(120974478 + 69359728) / 1000000, matching the two parameters exactly.RUST_MIN_STACKis needed to run this module at all; the pre-existing tests overflow the default stack in a debug build without it. The value above matches what CI sets inlint-test.yaml.rustfmtandclippyare clean over the added code. The file carries pre-existing diffs from both on the base branch (lines 25, 66, 203), left untouched rather than mixed into this diff.