Skip to content

Conversation

@bogdanbear
Copy link
Contributor

@bogdanbear bogdanbear commented Nov 11, 2025

This PR adds support for conflations without any user transactions implements issue(s) #

Checklist

  • I adapted existing tests for my new core changes.
  • I have successfully ran tests, style checker and build against my new changes locally.
  • I have informed the team of any breaking changes if there are any.

Note

Introduce a dedicated ChainIDFetcher (sourcing from BlockData) and remove ChainID handling from RlpTxnFetcher, wiring it into PublicInput; update tests, discovery advices, blockdata mocks, and improve a compiler panic message.

  • Public Input / Wiring:
    • Add ChainIDFetcher and use chainIDFetcher.ChainID/NBytesChainID for PublicInput instead of RlpTxnFetcher.
    • Propagate ChainIDFetcher through AuxiliaryModules and assignment.
  • Fetchers:
    • New fetchers_arithmetization/chain_id_fetcher.go with constraints and assignment (reads blockdata.DATA_LO at ChainIDOffset).
    • Remove ChainID-related columns/constraints from RlpTxnFetcher.
  • Tests & Testdata:
    • Add chain_id_fetcher_test.go; update execution_data_collector_test.go and rlp_txn_fetcher_test.go to reflect new ChainID source.
    • Extend publicInput/testdata/blockdata_mock.csv with IS_CHAINID column and ChainID values.
  • Limitless discovery advices:
    • Add PUBLIC_INPUT_CHAIN_ID_FETCHER_N_BYTES_CHAIN_ID entry; drop PUBLIC_INPUT_RLP_TXN_FETCHER_N_BYTES_CHAIN_ID.
  • Compiler:
    • Enhance panic message in globalcs/merging.go to include domain sizes and constraint name.

Written by Cursor Bugbot for commit d50f4b1. This will update automatically on new commits. Configure here.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: ScaleUp: Incomplete Field Scaling

The ScaleUp method doesn't scale the newly added fields BIT_XOAN_U2, BIT_XOAN_U4, BIT_XOAN_U8, BIT_XOAN_U16, BIT_XOAN_U32, BIT_XOAN_U64, BIT_XOAN_U128, BIT_XOAN_U256, BYTE_16, BYTE_32, BYTE_64, BYTE_128, BYTE_256, and SIGNEXTEND. When this method is called to scale trace limits, these fields will remain at their original values while all other fields are multiplied, causing inconsistent scaling behavior.

prover/config/traces_limit.go#L207-L332

func (tl *TracesLimits) ScaleUp(by int) {
tl.Add *= by
tl.Bin *= by
tl.Blake2Fmodexpdata *= by
tl.Blockdata *= by
tl.Blockhash *= by
tl.Ecdata *= by
tl.Euc *= by
tl.Exp *= by
tl.Ext *= by
tl.Gas *= by
tl.Hub *= by
tl.Logdata *= by
tl.Loginfo *= by
tl.Mmio *= by
tl.Mmu *= by
tl.Mod *= by
tl.Mul *= by
tl.Mxp *= by
tl.Oob *= by
tl.Rlpaddr *= by
tl.Rlptxn *= by
tl.Rlptxrcpt *= by
tl.Rom *= by
tl.Romlex *= by
tl.Shakiradata *= by
tl.Shf *= by
tl.Stp *= by
tl.Trm *= by
tl.Txndata *= by
tl.Wcp *= by
tl.PrecompileEcrecoverEffectiveCalls *= by
tl.PrecompileSha2Blocks *= by
tl.PrecompileModexpEffectiveCalls *= by
tl.PrecompileModexpEffectiveCalls4096 *= by
tl.PrecompileEcaddEffectiveCalls *= by
tl.PrecompileEcmulEffectiveCalls *= by
tl.PrecompileEcpairingEffectiveCalls *= by
tl.PrecompileEcpairingMillerLoops *= by
tl.PrecompileEcpairingG2MembershipCalls *= by
tl.BlockKeccak *= by
tl.BlockTransactions *= by
tl.ShomeiMerkleProofs *= by
// Beta 4.0 internal modules
tl.BitShl256 *= by
tl.BitShl256U7 *= by
tl.BitShl256U6 *= by
tl.BitShl256U5 *= by
tl.BitShl256U4 *= by
tl.BitShl256U3 *= by
tl.BitShl256U2 *= by
tl.BitShl256U1 *= by
tl.BitShr256 *= by
tl.BitShr256U7 *= by
tl.BitShr256U6 *= by
tl.BitShr256U5 *= by
tl.BitShr256U4 *= by
tl.BitShr256U3 *= by
tl.BitShr256U2 *= by
tl.BitShr256U1 *= by
tl.BitSar256 *= by
tl.BitSar256U7 *= by
tl.BitSar256U6 *= by
tl.BitSar256U5 *= by
tl.BitSar256U4 *= by
tl.BitSar256U3 *= by
tl.BitSar256U2 *= by
tl.BitSar256U1 *= by
tl.CallGasExtra *= by
tl.FillBytesBetween *= by
tl.GasOutOfPocket *= by
tl.Log2 *= by
tl.Log2U128 *= by
tl.Log2U64 *= by
tl.Log2U32 *= by
tl.Log2U16 *= by
tl.Log2U8 *= by
tl.Log2U4 *= by
tl.Log2U2 *= by
tl.Log256 *= by
tl.Log256U128 *= by
tl.Log256U64 *= by
tl.Log256U32 *= by
tl.Log256U16 *= by
tl.Min25664 *= by
tl.SetByte256 *= by
tl.SetByte128 *= by
tl.SetByte64 *= by
tl.SetByte32 *= by
tl.SetByte16 *= by
tl.U128 *= by
tl.U127 *= by
tl.U126 *= by
tl.U125 *= by
tl.U124 *= by
tl.U123 *= by
tl.U120 *= by
tl.U119 *= by
tl.U112 *= by
tl.U111 *= by
tl.U96 *= by
tl.U95 *= by
tl.U64 *= by
tl.U63 *= by
tl.U62 *= by
tl.U61 *= by
tl.U60 *= by
tl.U59 *= by
tl.U58 *= by
tl.U56 *= by
tl.U55 *= by
tl.U48 *= by
tl.U47 *= by
tl.U36 *= by
tl.U32 *= by
tl.U31 *= by
tl.U30 *= by
tl.U29 *= by
tl.U28 *= by
tl.U27 *= by
tl.U26 *= by
tl.U24 *= by
tl.U23 *= by

Fix in Cursor Fix in Web


viper.SetDefault("traces_limits.BIT_XOAN_U32", 262144)
viper.SetDefault("traces_limits.BIT_XOAN_U4", 262144)
viper.SetDefault("traces_limits.BIT_XOAN_U64", 262144)
viper.SetDefault("traces_limits.BIT_XOAN_U8", 262144)
Copy link

Choose a reason for hiding this comment

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

Bug: Configuration Error: Large Limits Impact Regular

The default values for BIT_XOAN_* fields are being set with the traces_limits prefix instead of traces_limits_large prefix. This section is meant to configure large trace limits (as indicated by the surrounding context setting other traces_limits_large values), but incorrectly overwrites the regular trace limits instead, causing the large configuration to be incomplete and the regular configuration to have incorrect doubled values.

Fix in Cursor Fix in Web

@codecov-commenter
Copy link

codecov-commenter commented Nov 11, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.34%. Comparing base (456c3a8) to head (d50f4b1).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #1713      +/-   ##
============================================
+ Coverage     65.32%   65.34%   +0.01%     
  Complexity     1479     1479              
============================================
  Files           384      384              
  Lines         13957    13957              
  Branches       1441     1441              
============================================
+ Hits           9118     9120       +2     
+ Misses         4235     4233       -2     
  Partials        604      604              
Flag Coverage Δ *Carryforward flag
hardhat 96.20% <ø> (+0.19%) ⬆️
kotlin 62.89% <ø> (ø) Carriedforward from f00d3e9

*This pull request uses carry forward flags. Click here to find out more.
see 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: ScaleUp: Inconsistent trace limit scaling.

The ScaleUp method doesn't scale the newly added trace limit fields BIT_XOAN_U2, BIT_XOAN_U4, BIT_XOAN_U8, BIT_XOAN_U16, BIT_XOAN_U32, BIT_XOAN_U64, BIT_XOAN_U128, BIT_XOAN_U256, BYTE_16, BYTE_32, BYTE_64, BYTE_128, BYTE_256, and SIGNEXTEND. When scaling trace limits, these fields will remain at their original values instead of being multiplied by the scaling factor, causing inconsistent trace limit configurations.

prover/config/traces_limit.go#L207-L338

func (tl *TracesLimits) ScaleUp(by int) {
tl.Add *= by
tl.Bin *= by
tl.Blake2Fmodexpdata *= by
tl.Blockdata *= by
tl.Blockhash *= by
tl.Ecdata *= by
tl.Euc *= by
tl.Exp *= by
tl.Ext *= by
tl.Gas *= by
tl.Hub *= by
tl.Logdata *= by
tl.Loginfo *= by
tl.Mmio *= by
tl.Mmu *= by
tl.Mod *= by
tl.Mul *= by
tl.Mxp *= by
tl.Oob *= by
tl.Rlpaddr *= by
tl.Rlptxn *= by
tl.Rlptxrcpt *= by
tl.Rom *= by
tl.Romlex *= by
tl.Shakiradata *= by
tl.Shf *= by
tl.Stp *= by
tl.Trm *= by
tl.Txndata *= by
tl.Wcp *= by
tl.PrecompileEcrecoverEffectiveCalls *= by
tl.PrecompileSha2Blocks *= by
tl.PrecompileModexpEffectiveCalls *= by
tl.PrecompileModexpEffectiveCalls4096 *= by
tl.PrecompileEcaddEffectiveCalls *= by
tl.PrecompileEcmulEffectiveCalls *= by
tl.PrecompileEcpairingEffectiveCalls *= by
tl.PrecompileEcpairingMillerLoops *= by
tl.PrecompileEcpairingG2MembershipCalls *= by
tl.BlockKeccak *= by
tl.BlockTransactions *= by
tl.ShomeiMerkleProofs *= by
// Beta 4.0 internal modules
tl.BitShl256 *= by
tl.BitShl256U7 *= by
tl.BitShl256U6 *= by
tl.BitShl256U5 *= by
tl.BitShl256U4 *= by
tl.BitShl256U3 *= by
tl.BitShl256U2 *= by
tl.BitShl256U1 *= by
tl.BitShr256 *= by
tl.BitShr256U7 *= by
tl.BitShr256U6 *= by
tl.BitShr256U5 *= by
tl.BitShr256U4 *= by
tl.BitShr256U3 *= by
tl.BitShr256U2 *= by
tl.BitShr256U1 *= by
tl.BitSar256 *= by
tl.BitSar256U7 *= by
tl.BitSar256U6 *= by
tl.BitSar256U5 *= by
tl.BitSar256U4 *= by
tl.BitSar256U3 *= by
tl.BitSar256U2 *= by
tl.BitSar256U1 *= by
tl.CallGasExtra *= by
tl.FillBytesBetween *= by
tl.GasOutOfPocket *= by
tl.Log2 *= by
tl.Log2U128 *= by
tl.Log2U64 *= by
tl.Log2U32 *= by
tl.Log2U16 *= by
tl.Log2U8 *= by
tl.Log2U4 *= by
tl.Log2U2 *= by
tl.Log256 *= by
tl.Log256U128 *= by
tl.Log256U64 *= by
tl.Log256U32 *= by
tl.Log256U16 *= by
tl.Min25664 *= by
tl.SetByte256 *= by
tl.SetByte128 *= by
tl.SetByte64 *= by
tl.SetByte32 *= by
tl.SetByte16 *= by
tl.U128 *= by
tl.U127 *= by
tl.U126 *= by
tl.U125 *= by
tl.U124 *= by
tl.U123 *= by
tl.U120 *= by
tl.U119 *= by
tl.U112 *= by
tl.U111 *= by
tl.U96 *= by
tl.U95 *= by
tl.U64 *= by
tl.U63 *= by
tl.U62 *= by
tl.U61 *= by
tl.U60 *= by
tl.U59 *= by
tl.U58 *= by
tl.U56 *= by
tl.U55 *= by
tl.U48 *= by
tl.U47 *= by
tl.U36 *= by
tl.U32 *= by
tl.U31 *= by
tl.U30 *= by
tl.U29 *= by
tl.U28 *= by
tl.U27 *= by
tl.U26 *= by
tl.U24 *= by
tl.U23 *= by
tl.U20 *= by
// beta v4.0
tl.PrecompileBlsPointEvaluationEffectiveCalls *= by
tl.PrecompilePointEvaluationFailureEffectiveCalls *= by
tl.PrecompileBlsG1AddEffectiveCalls *= by
tl.PrecompileBlsG1MsmEffectiveCalls *= by

Fix in Cursor Fix in Web


viper.SetDefault("traces_limits.BYTE_128", 262144)
viper.SetDefault("traces_limits.BYTE_256", 262144)
// SIGNEXTEND module
viper.SetDefault("traces_limits.SIGNEXTEND", 262144)
Copy link

Choose a reason for hiding this comment

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

Bug: Large Trace Limits Misconfiguration

The configuration sets traces_limits instead of traces_limits_large for BIT_XOAN_*, BYTE_*, and SIGNEXTEND fields. These lines appear in the large traces section and use large values (262144), but incorrectly use the traces_limits prefix instead of traces_limits_large, causing the normal trace limits to be overwritten with large values and leaving the large trace limits unset for these fields.

Fix in Cursor Fix in Web

@bogdanbear bogdanbear self-assigned this Nov 11, 2025
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Dead Code: Redundant ChainID Fetching

Dead code remains in AssignRlpTxnFetcher that declares and assigns chainID and nBytesChainID variables but never uses them. This code fetches ChainID from RLP transaction data unnecessarily, since ChainID fetching was moved to the new ChainIDFetcher. The variables and the loop logic that populates them (lines 161-169) should be removed.

prover/zkevm/prover/publicInput/fetchers_arithmetization/rlp_txn_fetcher.go#L136-L169

var chainID, nBytesChainID field.Element
// counter is used to populate filter.Data and will increment every time we find a new timestamp
counter := 0
for i := 0; i < rlpTxnArith.Limb.Size(); i++ {
toHashByProver := rlpTxnArith.ToHashByProver.GetColAssignmentAt(run, i)
// process the RLP limb, by inspecting AbsTxNum, AbsTxNumMax, Limb, NBytes
// and populating a row of the fetcher with these values.
if toHashByProver.IsOne() {
arithAbsTxNum := rlpTxnArith.AbsTxNum.GetColAssignmentAt(run, i)
arithAbsTxNumMax := rlpTxnArith.AbsTxNumMax.GetColAssignmentAt(run, i)
arithLimb := rlpTxnArith.Limb.GetColAssignmentAt(run, i)
arithNBytes := rlpTxnArith.NBytes.GetColAssignmentAt(run, i)
absTxNum[counter].Set(&arithAbsTxNum)
absTxNumMax[counter].Set(&arithAbsTxNumMax)
limb[counter].Set(&arithLimb)
nBytes[counter].Set(&arithNBytes)
filterFetched[counter].SetOne()
counter++
}
// check if we have the ChainID
txnPerspective := rlpTxnArith.TxnPerspective.GetColAssignmentAt(run, i)
// fetch the ChainID from the limb column
fetchedValue := rlpTxnArith.ChainID.GetColAssignmentAt(run, i)
if txnPerspective.IsOne() && !fetchedValue.IsZero() {
chainID.Set(&fetchedValue)
// fetch the number of bytes for the ChainID
fetchedNBytes := field.NewElement(2)
nBytesChainID.Set(&fetchedNBytes)
}
}

Fix in Cursor Fix in Web


Bug: Eliminate Wasteful ChainID Computations

The SelectorZeroChainID field, ComputeSelectorZeroChainID prover action, and the entire ConstrainChainID function are no longer used after removing ChainID-related constraints from RlpTxnFetcher. These create unnecessary columns and perform wasteful computations during both constraint definition and proving (line 61 calls ConstrainChainID and line 190 runs ComputeSelectorZeroChainID), but the selector is never referenced in any constraints.

prover/zkevm/prover/publicInput/fetchers_arithmetization/rlp_txn_fetcher.go#L25-L50

// SelectorChainID is a selector that only lights up when the ChainID column is non-zero
SelectorZeroChainID ifaces.Column
ComputeSelectorZeroChainID wizard.ProverAction
}
func NewRlpTxnFetcher(comp *wizard.CompiledIOP, name string, rt *arith.RlpTxn) RlpTxnFetcher {
size := rt.Limb.Size()
res := RlpTxnFetcher{
AbsTxNum: util.CreateCol(name, "ABS_TX_NUM", size, comp),
AbsTxNumMax: util.CreateCol(name, "ABS_TX_NUM_MAX", size, comp),
Limb: util.CreateCol(name, "LIMB", size, comp),
NBytes: util.CreateCol(name, "NBYTES", size, comp),
FilterFetched: util.CreateCol(name, "FILTER_FETCHED", size, comp),
EndOfRlpSegment: util.CreateCol(name, "END_OF_RLP_SEGMENT", size, comp),
}
return res
}
// ConstrainChainID defines constraints for both ChainID and NBytesChainID columns.
func ConstrainChainID(comp *wizard.CompiledIOP, fetcher *RlpTxnFetcher, name string, rlpTxnArith *arith.RlpTxn) {
fetcher.SelectorZeroChainID, fetcher.ComputeSelectorZeroChainID = dedicated.IsZero(
comp,
ifaces.ColumnAsVariable(rlpTxnArith.ChainID),
).GetColumnAndProverAction()
}

Fix in Cursor Fix in Web


gusiri
gusiri previously approved these changes Nov 11, 2025

// require this to be a constant column
commonconstraints.MustBeConstant(comp, fetcher.NBytesChainID)
}
Copy link

Choose a reason for hiding this comment

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

Bug: Unconstrained ChainID: Data Integrity Vulnerability

The ChainID column is assigned as a constant but lacks a MustBeConstant constraint. Only position 0 is constrained via the local constraint, leaving all other positions unconstrained. A malicious prover could assign different values to positions 1 through size-1, potentially causing inconsistencies when the column is used elsewhere. The NBytesChainID column has this constraint (line 63), but ChainID is missing it.

Fix in Cursor Fix in Web

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.

5 participants