From 23b7ad7f3f116e0d2a65cedeb5eec3bd45a5aa47 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Tue, 11 Nov 2025 10:07:00 +0530 Subject: [PATCH 01/22] fix(common_constraints): merkle tests are passing --- .../common/common_constraints/common_constraints.go | 8 ++++---- prover/zkevm/prover/statemanager/accumulator/assign.go | 4 ---- prover/zkevm/prover/statemanager/accumulator/define.go | 3 ++- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/prover/zkevm/prover/common/common_constraints/common_constraints.go b/prover/zkevm/prover/common/common_constraints/common_constraints.go index b2eead14bd..b8e1b81eca 100644 --- a/prover/zkevm/prover/common/common_constraints/common_constraints.go +++ b/prover/zkevm/prover/common/common_constraints/common_constraints.go @@ -22,17 +22,17 @@ func MustZeroWhenInactive(comp *wizard.CompiledIOP, isActive any, cs ...ifaces.C if ccol, isc := isActive.(verifiercol.ConstCol); isc { - if ccol.F.IsOne() { + if ccol.Base.IsOne() { // The constraint is meaningless in that situation return } - if !ccol.F.IsZero() { - utils.Panic("activator column is not boolean: is const-col with value=%v", ccol.F.String()) + if !ccol.Base.IsZero() { + utils.Panic("activator column is not boolean: is const-col with value=%v", ccol.Base.String()) } // expectedly, the only possibility - isActive = sym.NewConstant(ccol.F) + isActive = sym.NewConstant(ccol.Base) } for _, c := range cs { diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index fa3f3b1a60..b49d6dfb62 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -7,10 +7,6 @@ import ( "github.com/consensys/linea-monorepo/prover/zkevm/prover/common" - "io" - - "github.com/consensys/linea-monorepo/prover/zkevm/prover/common" - "github.com/consensys/linea-monorepo/prover/backend/execution/statemanager" "github.com/consensys/linea-monorepo/prover/crypto/state-management/accumulator" "github.com/consensys/linea-monorepo/prover/crypto/state-management/smt" diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index 6ff97b42ed..fed698c81f 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -113,8 +113,9 @@ type LeafOpenings struct { // Module module type Module struct { - // The compiled IOP + // The state manager accumulator settings Settings + // compiled IOP comp *wizard.CompiledIOP Cols struct { Leaves [common.NbLimbU256]ifaces.Column From 0cce6ddb9488d7bc05c97d82703277c2243d817c Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Tue, 11 Nov 2025 17:50:19 +0530 Subject: [PATCH 02/22] fix(accumulator): compilation errors fixes (wip) --- prover/zkevm/prover/common/flatten_column.go | 4 + .../prover/statemanager/accumulator/assign.go | 58 +++---- .../prover/statemanager/accumulator/define.go | 142 +++++++++--------- 3 files changed, 104 insertions(+), 100 deletions(-) diff --git a/prover/zkevm/prover/common/flatten_column.go b/prover/zkevm/prover/common/flatten_column.go index 0e620f1d8e..ae90b56978 100644 --- a/prover/zkevm/prover/common/flatten_column.go +++ b/prover/zkevm/prover/common/flatten_column.go @@ -23,6 +23,10 @@ const ( NbLimbU128 = 8 // NbLimbU256 represents the number of 16-bit limbs for a 256-bit integer. NbLimbU256 = 16 + // NbElemPerHash represents the number of field elements per Posseidon hash. + NbElemPerHash = 8 + // NbElemU64 represents the number of field elements per 64-bit integers. + NbElemU64 = 16 ) // FlattenColumn flattens multiple limb columns and an accompanying mask into single columns, diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index b49d6dfb62..4c9faf3953 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -20,10 +20,10 @@ import ( // leafOpenings represents the structure for leaf openings type leafOpenings struct { - prev [common.NbLimbU64][]field.Element - next [common.NbLimbU64][]field.Element - hKey [common.NbLimbU256][]field.Element - hVal [common.NbLimbU256][]field.Element + prev [common.NbElemU64][]field.Element + next [common.NbElemU64][]field.Element + hKey [common.NbElemPerHash][]field.Element + hVal [common.NbElemPerHash][]field.Element } // assignmentBuilder is used to build the assignment of the [Module] module @@ -37,12 +37,12 @@ type assignmentBuilder struct { // leaves stores the assignment of the column holding the leaves (so the // hash of the leaf openings) for which we give the merkle proof. This corresponds to the // [Accumulator.Cols.Leaves] column. - leaves [common.NbLimbU256][]field.Element + leaves [common.NbElemPerHash][]field.Element // positions stores the positions of the leaves in the merkle tree for which we give the Merkle proof. This corresponds to the [Accumulator.Cols.Positions] column. - positions [common.NbLimbU64][]field.Element + positions [common.NbElemU64][]field.Element // roots stores the roots of the merkle tree. This corresponds // to the [Accumulator.Cols.Roots] column. - roots [common.NbLimbU256][]field.Element + roots [common.NbElemPerHash][]field.Element // proofs stores the path and siblings of the merkle proof. Those siblings corresponds // to the [Accumulator.Cols.Proofs] column. proofs []smt.Proof @@ -53,7 +53,7 @@ type assignmentBuilder struct { isActive []field.Element // accumulatorCounter counts the number of rows in the accumulator. It is used to check the // sequentiality of leaves and roots in accumulator and the merkle module - accumulatorCounter [common.NbLimbU64][]field.Element + accumulatorCounter [common.NbElemU64][]field.Element // isFirst is one at the first row of any operation. This corresponds to the [Accumulator.IsFirst] column isFirst []field.Element // isInsert is one when we have an INSERT operation. It is @@ -72,46 +72,46 @@ type assignmentBuilder struct { // zero otherwise. This corresponds to the [Accumulator.Cols.IsReadNonZero] column isReadNonZero []field.Element // hKey is the hash of the key of the trace. This corresponds to the [Accumulator.Column.HKey] - hKey [common.NbLimbU256][]field.Element + hKey [common.NbElemPerHash][]field.Element // hKeyMinus is the hash of the key of the previous leaf. This corresponds to the [Accumulator.Column.HKeyMinus] - hKeyMinus [common.NbLimbU256][]field.Element + hKeyMinus [common.NbElemPerHash][]field.Element // hKeyPlus is the hash of the key of the next leaf. This corresponds to the [Accumulator.Column.HKeyPlus] - hKeyPlus [common.NbLimbU256][]field.Element + hKeyPlus [common.NbElemPerHash][]field.Element // Pointer check columns // leafMinusIndex is the index of the minus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafMinusIndex] - leafMinusIndex [common.NbLimbU64][]field.Element + leafMinusIndex [common.NbElemU64][]field.Element // leafMinusNext is the index of the Next leaf of the minus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafMinusNext] - leafMinusNext [common.NbLimbU64][]field.Element + leafMinusNext [common.NbElemU64][]field.Element // leafMinusNext is the index of the plus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafPlusIndex] - leafPlusIndex [common.NbLimbU64][]field.Element + leafPlusIndex [common.NbElemU64][]field.Element // leafPlusPrev is the index of the Previous leaf of the plus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafPlusPrev] - leafPlusPrev [common.NbLimbU64][]field.Element + leafPlusPrev [common.NbElemU64][]field.Element // leafDeletedIndex is the index of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedIndex] - leafDeletedIndex [common.NbLimbU64][]field.Element + leafDeletedIndex [common.NbElemU64][]field.Element // leafDeletedPrev is the index of the Previous leaf of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedPrev] - leafDeletedPrev [common.NbLimbU64][]field.Element + leafDeletedPrev [common.NbElemU64][]field.Element // leafDeletedNext is the index of the Previous leaf of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedNext] - leafDeletedNext [common.NbLimbU64][]field.Element + leafDeletedNext [common.NbElemU64][]field.Element // leafOpening is a tuple of four columns containing // Prev, Next, HKey, HVal of a leaf. This corresponds to the [Accumulator.Column.LeafOpening] leafOpening leafOpenings // interm is a slice containing 3 intermediate hash states. This corresponds to the [Accumulator.Column.Interm] - interm [common.NbLimbU256][][]field.Element + interm [common.NbElemPerHash][][]field.Element // leafHash contains sequential MiMC hashes of leafOpening. It matches with Leaves except when there is empty leaf. This corresponds to the [Accumulator.Column.LeafHashes] - leafHashes [common.NbLimbU256][]field.Element + leafHashes [common.NbElemPerHash][]field.Element // isEmptyLeaf is one when Leaves contains empty leaf and does not match with LeafHash isEmptyLeaf []field.Element // nextFreeNode contains the nextFreeNode for each row of every operation - nextFreeNode [common.NbLimbU64][]field.Element + nextFreeNode [common.NbElemU64][]field.Element // insertionPath is the path of a newly inserted leaf when INSERT happens, // it is zero otherwise - insertionPath [common.NbLimbU64][]field.Element + insertionPath [common.NbElemU64][]field.Element // isInsertRow3 is one for row 3 of INSERT operation isInsertRow3 []field.Element // intermTopRoot contains the intermediate MiMC state hash - intermTopRoot [common.NbLimbU256][]field.Element + intermTopRoot [common.NbElemPerHash][]field.Element // topRoot contains the MiMC hash of SubTreeRoot and NextFreeNode - topRoot [common.NbLimbU256][]field.Element + topRoot [common.NbElemPerHash][]field.Element } // newAssignmentBuilder returns an empty builder @@ -119,7 +119,7 @@ func newAssignmentBuilder(s Settings) *assignmentBuilder { amb := assignmentBuilder{} amb.Settings = s - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { amb.roots[i] = make([]field.Element, 0, amb.NumRows()) amb.leaves[i] = make([]field.Element, 0, amb.NumRows()) amb.hKey[i] = make([]field.Element, 0, amb.NumRows()) @@ -223,11 +223,11 @@ func (am *Module) Assign( } // Sanity check on the size - if len(builder.leaves) > am.MaxNumProofs { + if len(builder.leaves[0]) > am.MaxNumProofs { exit.OnLimitOverflow( am.MaxNumProofs, - len(builder.leaves), - fmt.Errorf("we have registered %v proofs which is more than the maximum number of proofs %v", len(builder.leaves), am.MaxNumProofs), + len(builder.leaves[0]), + fmt.Errorf("we have registered %v proofs which is more than the maximum number of proofs %v", len(builder.leaves[0]), am.MaxNumProofs), ) } @@ -254,7 +254,7 @@ func (am *Module) Assign( run.AssignColumn(cols.LeafDeletedNext[i].GetColID(), smartvectors.RightZeroPadded(builder.leafDeletedNext[i], paddedSize)) } - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { run.AssignColumn(cols.Roots[i].GetColID(), smartvectors.RightZeroPadded(builder.roots[i], paddedSize)) run.AssignColumn(cols.Leaves[i].GetColID(), smartvectors.RightZeroPadded(builder.leaves[i], paddedSize)) diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index fed698c81f..2ddc5fa757 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -105,10 +105,10 @@ const ( // structure for leaf opening type LeafOpenings struct { - HKey [common.NbLimbU256]ifaces.Column - HVal [common.NbLimbU256]ifaces.Column - Prev [common.NbLimbU64]ifaces.Column - Next [common.NbLimbU64]ifaces.Column + HKey [common.NbElemPerHash]ifaces.Column + HVal [common.NbElemPerHash]ifaces.Column + Prev [common.NbElemU64]ifaces.Column + Next [common.NbElemU64]ifaces.Column } // Module module @@ -118,16 +118,16 @@ type Module struct { // compiled IOP comp *wizard.CompiledIOP Cols struct { - Leaves [common.NbLimbU256]ifaces.Column - Roots [common.NbLimbU256]ifaces.Column - Positions [common.NbLimbU64]ifaces.Column + Leaves [common.NbElemPerHash]ifaces.Column + Roots [common.NbElemPerHash]ifaces.Column + Positions [common.NbElemU64]ifaces.Column Proofs *merkle.FlatProof // Column to verify reuse of Merkle proofs in INSERT, DELETE, and UPDATE operations UseNextMerkleProof ifaces.Column // Column denoting the active area of the accumulator module IsActiveAccumulator ifaces.Column // Columns to check sequentiality of the accumulator module with Merkle module - AccumulatorCounter [common.NbLimbU64]ifaces.Column + AccumulatorCounter [common.NbElemU64]ifaces.Column // Column to verify the two equalities of intermediateRoot1 and intermediateRoot3, and empty // leafs for INSERT and DELETE operation and one equality of root in IsReadZero operation IsFirst ifaces.Column @@ -144,11 +144,11 @@ type Module struct { // Columns for the sandwitch check // Columns storing the hash of the key of the trace - HKey [common.NbLimbU256]ifaces.Column + HKey [common.NbElemPerHash]ifaces.Column // Columns storing the hash of the key of the previous leaf - HKeyMinus [common.NbLimbU256]ifaces.Column + HKeyMinus [common.NbElemPerHash]ifaces.Column // Columns storing the hash of the key of the next leaf - HKeyPlus [common.NbLimbU256]ifaces.Column + HKeyPlus [common.NbElemPerHash]ifaces.Column // HkeyHkeyMinusIsGreater contains boolean value indicating whether the HKey is greater than HKeyMinus HkeyHkeyMinusIsGreater ifaces.Column // HkeyPlusHkeyIsGreater contains boolean value indicating whether the HKeyPlus is greater than HKey @@ -156,48 +156,48 @@ type Module struct { // Columns for the pointer check // Columns storing the index of the minus leaf - LeafMinusIndex [common.NbLimbU64]ifaces.Column + LeafMinusIndex [common.NbElemU64]ifaces.Column // Columns storing the index of the next leaf of the minus leaf - LeafMinusNext [common.NbLimbU64]ifaces.Column + LeafMinusNext [common.NbElemU64]ifaces.Column // Columns storing the index of the plus leaf - LeafPlusIndex [common.NbLimbU64]ifaces.Column + LeafPlusIndex [common.NbElemU64]ifaces.Column // Columns storing the index of the previous leaf of the plus leaf - LeafPlusPrev [common.NbLimbU64]ifaces.Column + LeafPlusPrev [common.NbElemU64]ifaces.Column // Columns storing the index of the deleted leaf - LeafDeletedIndex [common.NbLimbU64]ifaces.Column + LeafDeletedIndex [common.NbElemU64]ifaces.Column // Columns storing the index of the previous leaf of the deleted leaf - LeafDeletedPrev [common.NbLimbU64]ifaces.Column + LeafDeletedPrev [common.NbElemU64]ifaces.Column // Columns storing the index of the next leaf of the deleted leaf - LeafDeletedNext [common.NbLimbU64]ifaces.Column + LeafDeletedNext [common.NbElemU64]ifaces.Column // Columns for leaf hashing check // LeafOpening contains four columns corresponding to HKey, HVal, Prev, and Next LeafOpenings LeafOpenings // Interm contains the three intermediate states corresponding to the MiMC block computation divided into limbs - Interm [common.NbLimbU256][]ifaces.Column + Interm [common.NbElemPerHash][]ifaces.Column // Zero contains the column with zero value, used in the MiMc query Zero ifaces.Column // LeafHash contains the leafHashes (the final MiMC block), equals with Leaves, except when it is empty leaf - LeafHashes [common.NbLimbU256]ifaces.Column + LeafHashes [common.NbElemPerHash]ifaces.Column // IsEmptyLeaf is one when Leaves contains empty leaf and does not match with LeafHash IsEmptyLeaf ifaces.Column // Columns to check NextFreeNode consistency // NextFreeNode stores the nextFreeNode for each row of every operation - NextFreeNode [common.NbLimbU64]ifaces.Column + NextFreeNode [common.NbElemU64]ifaces.Column // NextFreeNodeIncremented stores a value that indicates how much NextFreeNode[i] is increased // relative to the NextFreeNode[i-1] - NextFreeNodeIncremented [common.NbLimbU64]ifaces.Column + NextFreeNodeIncremented [common.NbElemU64]ifaces.Column // InsertionPath stores the index of the newly inserted leaf by INSERT - InsertionPath [common.NbLimbU64]ifaces.Column + InsertionPath [common.NbElemU64]ifaces.Column // IsInsertRow3 is one for row 3 of INSERT operation IsInsertRow3 ifaces.Column // Columns for hashing the top root // IntermTopRoot contains the intermediate MiMC state hash - IntermTopRoot [common.NbLimbU256]ifaces.Column + IntermTopRoot [common.NbElemPerHash]ifaces.Column // TopRoot contains the MiMC hash of Roots and NextFreeNode - TopRoot [common.NbLimbU256]ifaces.Column + TopRoot [common.NbElemPerHash]ifaces.Column } // MerkleProofVerification is the merkle tree verification wizard @@ -229,51 +229,51 @@ func (am *Module) define(comp *wizard.CompiledIOP, s Settings) { am.comp = comp // Initializes the columns - for i := 0; i < common.NbLimbU256; i++ { - am.Cols.Leaves[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAVES_NAME, i), am.NumRows()) - am.Cols.Roots[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_ROOTS_NAME, i), am.NumRows()) + for i := 0; i < common.NbElemPerHash; i++ { + am.Cols.Leaves[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAVES_NAME, i), am.NumRows(), true) + am.Cols.Roots[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_ROOTS_NAME, i), am.NumRows(), true) // columns for the sandwitch check - am.Cols.HKey[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_HKEY_NAME, i), am.NumRows()) - am.Cols.HKeyMinus[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_HKEY_MINUS_NAME, i), am.NumRows()) - am.Cols.HKeyPlus[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_HKEY_PLUS_NAME, i), am.NumRows()) + am.Cols.HKey[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_HKEY_NAME, i), am.NumRows(), true) + am.Cols.HKeyMinus[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_HKEY_MINUS_NAME, i), am.NumRows(), true) + am.Cols.HKeyPlus[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_HKEY_PLUS_NAME, i), am.NumRows(), true) // TopRoot hash check columns commitments - am.Cols.IntermTopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INTERM_TOP_ROOT_NAME, i), am.NumRows()) - am.Cols.TopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_TOP_ROOT_NAME, i), am.NumRows()) + am.Cols.IntermTopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INTERM_TOP_ROOT_NAME, i), am.NumRows(), true) + am.Cols.TopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_TOP_ROOT_NAME, i), am.NumRows(), true) } for i := 0; i < len(am.Cols.Positions); i++ { - am.Cols.Positions[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_POSITIONS_NAME, i), am.NumRows()) - am.Cols.NextFreeNode[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_NEXT_FREE_NODE_NAME, i), am.NumRows()) - am.Cols.InsertionPath[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INSERTION_PATH_NAME, i), am.NumRows()) - am.Cols.AccumulatorCounter[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_COUNTER_NAME, i), am.NumRows()) + am.Cols.Positions[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_POSITIONS_NAME, i), am.NumRows(), true) + am.Cols.NextFreeNode[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_NEXT_FREE_NODE_NAME, i), am.NumRows(), true) + am.Cols.InsertionPath[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INSERTION_PATH_NAME, i), am.NumRows(), true) + am.Cols.AccumulatorCounter[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_COUNTER_NAME, i), am.NumRows(), true) // columns for the pointer check - am.Cols.LeafMinusIndex[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_MINUS_INDEX_NAME, i), am.NumRows()) - am.Cols.LeafMinusNext[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_MINUS_NEXT_NAME, i), am.NumRows()) - am.Cols.LeafPlusIndex[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_PLUS_INDEX_NAME, i), am.NumRows()) - am.Cols.LeafPlusPrev[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_PLUS_PREV_NAME, i), am.NumRows()) - am.Cols.LeafDeletedIndex[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_DELETED_INDEX_NAME, i), am.NumRows()) - am.Cols.LeafDeletedPrev[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_DELETED_PREV_NAME, i), am.NumRows()) - am.Cols.LeafDeletedNext[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_DELETED_NEXT_NAME, i), am.NumRows()) + am.Cols.LeafMinusIndex[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_MINUS_INDEX_NAME, i), am.NumRows(), true) + am.Cols.LeafMinusNext[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_MINUS_NEXT_NAME, i), am.NumRows(), true) + am.Cols.LeafPlusIndex[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_PLUS_INDEX_NAME, i), am.NumRows(), true) + am.Cols.LeafPlusPrev[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_PLUS_PREV_NAME, i), am.NumRows(), true) + am.Cols.LeafDeletedIndex[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_DELETED_INDEX_NAME, i), am.NumRows(), true) + am.Cols.LeafDeletedPrev[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_DELETED_PREV_NAME, i), am.NumRows(), true) + am.Cols.LeafDeletedNext[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_DELETED_NEXT_NAME, i), am.NumRows(), true) } am.Cols.Proofs = merkle.NewProof(comp, am.Round, ACCUMULATOR_PROOFS_NAME, am.MerkleTreeDepth, am.NumRows()) - am.Cols.UseNextMerkleProof = comp.InsertCommit(am.Round, ACCUMULATOR_USE_NEXT_MERKLE_PROOF_NAME, am.NumRows()) - am.Cols.IsActiveAccumulator = comp.InsertCommit(am.Round, ACCUMULATOR_IS_ACTIVE_NAME, am.NumRows()) - am.Cols.IsFirst = comp.InsertCommit(am.Round, ACCUMULATOR_IS_FIRST_NAME, am.NumRows()) - am.Cols.IsInsert = comp.InsertCommit(am.Round, ACCUMULATOR_IS_INSERT_NAME, am.NumRows()) - am.Cols.IsDelete = comp.InsertCommit(am.Round, ACCUMULATOR_IS_DELETE_NAME, am.NumRows()) - am.Cols.IsUpdate = comp.InsertCommit(am.Round, ACCUMULATOR_IS_UPDATE_NAME, am.NumRows()) - am.Cols.IsReadZero = comp.InsertCommit(am.Round, ACCUMULATOR_IS_READ_ZERO_NAME, am.NumRows()) - am.Cols.IsReadNonZero = comp.InsertCommit(am.Round, ACCUMULATOR_IS_READ_NON_ZERO_NAME, am.NumRows()) + am.Cols.UseNextMerkleProof = comp.InsertCommit(am.Round, ACCUMULATOR_USE_NEXT_MERKLE_PROOF_NAME, am.NumRows(), true) + am.Cols.IsActiveAccumulator = comp.InsertCommit(am.Round, ACCUMULATOR_IS_ACTIVE_NAME, am.NumRows(), true) + am.Cols.IsFirst = comp.InsertCommit(am.Round, ACCUMULATOR_IS_FIRST_NAME, am.NumRows(), true) + am.Cols.IsInsert = comp.InsertCommit(am.Round, ACCUMULATOR_IS_INSERT_NAME, am.NumRows(), true) + am.Cols.IsDelete = comp.InsertCommit(am.Round, ACCUMULATOR_IS_DELETE_NAME, am.NumRows(), true) + am.Cols.IsUpdate = comp.InsertCommit(am.Round, ACCUMULATOR_IS_UPDATE_NAME, am.NumRows(), true) + am.Cols.IsReadZero = comp.InsertCommit(am.Round, ACCUMULATOR_IS_READ_ZERO_NAME, am.NumRows(), true) + am.Cols.IsReadNonZero = comp.InsertCommit(am.Round, ACCUMULATOR_IS_READ_NON_ZERO_NAME, am.NumRows(), true) // Leaf hashing columns commitments am.commitLeafHashingCols() // NextFreeNode check columns commitments - am.Cols.IsInsertRow3 = comp.InsertCommit(am.Round, ACCUMULATOR_IS_INSERT_ROW3_NAME, am.NumRows()) + am.Cols.IsInsertRow3 = comp.InsertCommit(am.Round, ACCUMULATOR_IS_INSERT_ROW3_NAME, am.NumRows(), true) // Declare constraints @@ -359,28 +359,28 @@ func (am *Module) commitLeafHashingCols() { am.Cols.Zero = verifiercol.NewConstantCol(field.Zero(), am.NumRows(), "merkle-tree-accumulator") for i := range am.Cols.LeafOpenings.Prev { - am.Cols.LeafOpenings.Prev[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_PREV, i), am.NumRows()) - am.Cols.LeafOpenings.Next[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_NEXT, i), am.NumRows()) + am.Cols.LeafOpenings.Prev[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_PREV, i), am.NumRows(), true) + am.Cols.LeafOpenings.Next[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_NEXT, i), am.NumRows(), true) } - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { am.Cols.Interm[i] = make([]ifaces.Column, 3) - am.Cols.LeafOpenings.HKey[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_HKEY, i), am.NumRows()) - am.Cols.LeafOpenings.HVal[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_HVAL, i), am.NumRows()) - am.Cols.LeafHashes[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_HASHES_NAME, i), am.NumRows()) + am.Cols.LeafOpenings.HKey[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_HKEY, i), am.NumRows(), true) + am.Cols.LeafOpenings.HVal[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_HVAL, i), am.NumRows(), true) + am.Cols.LeafHashes[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_HASHES_NAME, i), am.NumRows(), true) for j := 0; j < len(am.Cols.Interm[i]); j++ { - am.Cols.Interm[i][j] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INTERM[j], i), am.NumRows()) + am.Cols.Interm[i][j] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INTERM[j], i), am.NumRows(), true) } } - am.Cols.IsEmptyLeaf = am.comp.InsertCommit(am.Round, ACCUMULATOR_IS_EMPTY_LEAF_NAME, am.NumRows()) + am.Cols.IsEmptyLeaf = am.comp.InsertCommit(am.Round, ACCUMULATOR_IS_EMPTY_LEAF_NAME, am.NumRows(), true) } func (am *Module) checkInsert() { cols := am.Cols - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { // (Root[i+1] - Root[i+2]) * IsActiveAccumulator[i] * IsFirst[i] * IsInsert[i] = 0, The (i+1)th and (i+2)th roots are equal when there is an INSERT operation and the accumulator is active. expr1 := symbolic.Sub(column.Shift(cols.Roots[i], 1), column.Shift(cols.Roots[i], 2)) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsInsert, expr1) @@ -408,7 +408,7 @@ func (am *Module) checkInsert() { func (am *Module) checkDelete() { cols := am.Cols - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { // (Root[i+1] - Root[i+2]) * IsActiveAccumulator[i] * IsFirst[i] * IsDelete[i] = 0, The (i+1)th and (i+2)th roots are equal when there is a DELETE operation and the accumulator is active. expr1 := symbolic.Sub(column.Shift(cols.Roots[i], 1), column.Shift(cols.Roots[i], 2)) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsDelete, expr1) @@ -430,7 +430,7 @@ func (am *Module) checkDelete() { func (am *Module) checkUpdate() { cols := am.Cols - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { // HKey remains the same for an update operation, i.e, // IsActiveAccumulator[i] * IsUpdate[i] * IsFirst[i] * (HKey[i] - HKey[i+1]) expr := symbolic.Mul(cols.IsActiveAccumulator, @@ -444,7 +444,7 @@ func (am *Module) checkUpdate() { func (am *Module) checkReadZero() { cols := am.Cols - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { // (Root[i] - Root[i+1]) * IsActiveAccumulator[i] * IsFirst[i] * IsReadZero[i] = 0, The ith and (i+1)th roots are equal when there is a READ-ZERO operation and the accumulator is active. expr1 := symbolic.Sub(cols.Roots[i], column.Shift(cols.Roots[i], 1)) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsReadZero, expr1) @@ -542,7 +542,7 @@ func (am *Module) checkEmptyLeaf() { emptyLeaf := verifiercol.NewConstantCol(emptyLeafField, am.NumRows(), "accumulator-empty-leaves") cols := am.Cols - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { // (Leaf[i+2] - emptyLeaf) * IsActiveAccumulator[i] * IsFirst[i] * IsInsert[i] expr1 := symbolic.Sub(column.Shift(cols.Leaves[i], 2), emptyLeaf) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsInsert, expr1) @@ -598,7 +598,7 @@ func (am *Module) checkSandwitch() { ), ) - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { // INSERT: The HKeyMinus in the leaf minus openings is the same as HKeyMinus column i.e., // IsActiveAccumulator[i] * IsInsert[i] * IsFirst[i] * (HKeyMinus[i] - LeafOpenings.Hkey[i]) expr1 := symbolic.Mul(cols.IsActiveAccumulator, @@ -681,9 +681,9 @@ func (am *Module) checkPointer() { func (am *Module) checkLeafHashes() { cols := am.Cols - panic("TODO: change the MiMC queries and replace them by Poseidon. Also review the [common.NbLimbU256] loop") + panic("TODO: change the MiMC queries and replace them by Poseidon. Also review the [common.NbElemPerHash] loop") - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { // TODO: fix MiMC query am.comp.InsertMiMC(am.Round, am.qname("MIMC_PREV_%d", i), cols.LeafOpenings.Prev[0], cols.Zero, cols.Interm[i][0], nil) @@ -805,7 +805,7 @@ func (am *Module) checkTopRootHash() { //cols := am.Cols // - //for i := 0; i < common.NbLimbU256; i++ { + //for i := 0; i < common.NbElemPerHash; i++ { // am.comp.InsertMiMC(am.Round, am.qname("MIMC_INTERM_TOP_ROOT_%d", i), cols.NextFreeNode, cols.Zero, cols.IntermTopRoot[i], nil) // am.comp.InsertMiMC(am.Round, am.qname("MIMC_TOP_ROOT_%d", i), cols.Roots, cols.IntermTopRoot[i], cols.TopRoot[i], nil) //} @@ -813,7 +813,7 @@ func (am *Module) checkTopRootHash() { func (am *Module) checkZeroInInactive() { cols := am.Cols - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { am.colZeroAtInactive(cols.Roots[i], fmt.Sprintf("ROOTS_ZERO_IN_INACTIVE_%d", i)) am.colZeroAtInactive(cols.Leaves[i], fmt.Sprintf("LEAVES_ZERO_IN_INACTIVE_%d", i)) From 40587f478a847996ebaa8d67d41070ec475f3072 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Thu, 13 Nov 2025 11:12:42 +0530 Subject: [PATCH 03/22] fix(accumulator): fix constant --- prover/protocol/dedicated/merkle/merkle.go | 1 + prover/zkevm/prover/common/flatten_column.go | 4 +-- .../prover/statemanager/accumulator/assign.go | 26 ++++++++--------- .../prover/statemanager/accumulator/define.go | 28 +++++++++---------- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/prover/protocol/dedicated/merkle/merkle.go b/prover/protocol/dedicated/merkle/merkle.go index fd13c2fbe7..5725d058b6 100644 --- a/prover/protocol/dedicated/merkle/merkle.go +++ b/prover/protocol/dedicated/merkle/merkle.go @@ -14,6 +14,7 @@ import ( const ( width = 16 blockSize = 8 + limbPerU64 = 4 ) // Wizard gadget allowing to verify a Merkle proof diff --git a/prover/zkevm/prover/common/flatten_column.go b/prover/zkevm/prover/common/flatten_column.go index ae90b56978..2eea50bb60 100644 --- a/prover/zkevm/prover/common/flatten_column.go +++ b/prover/zkevm/prover/common/flatten_column.go @@ -25,8 +25,8 @@ const ( NbLimbU256 = 16 // NbElemPerHash represents the number of field elements per Posseidon hash. NbElemPerHash = 8 - // NbElemU64 represents the number of field elements per 64-bit integers. - NbElemU64 = 16 + // NbElemForHasingU64 represents the number of field elements per 64-bit integers. + NbElemForHasingU64 = 16 ) // FlattenColumn flattens multiple limb columns and an accompanying mask into single columns, diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index 4c9faf3953..e36163996f 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -20,8 +20,8 @@ import ( // leafOpenings represents the structure for leaf openings type leafOpenings struct { - prev [common.NbElemU64][]field.Element - next [common.NbElemU64][]field.Element + prev [common.NbElemForHasingU64][]field.Element + next [common.NbElemForHasingU64][]field.Element hKey [common.NbElemPerHash][]field.Element hVal [common.NbElemPerHash][]field.Element } @@ -39,7 +39,7 @@ type assignmentBuilder struct { // [Accumulator.Cols.Leaves] column. leaves [common.NbElemPerHash][]field.Element // positions stores the positions of the leaves in the merkle tree for which we give the Merkle proof. This corresponds to the [Accumulator.Cols.Positions] column. - positions [common.NbElemU64][]field.Element + positions [common.NbElemForHasingU64][]field.Element // roots stores the roots of the merkle tree. This corresponds // to the [Accumulator.Cols.Roots] column. roots [common.NbElemPerHash][]field.Element @@ -53,7 +53,7 @@ type assignmentBuilder struct { isActive []field.Element // accumulatorCounter counts the number of rows in the accumulator. It is used to check the // sequentiality of leaves and roots in accumulator and the merkle module - accumulatorCounter [common.NbElemU64][]field.Element + accumulatorCounter [common.NbElemForHasingU64][]field.Element // isFirst is one at the first row of any operation. This corresponds to the [Accumulator.IsFirst] column isFirst []field.Element // isInsert is one when we have an INSERT operation. It is @@ -79,19 +79,19 @@ type assignmentBuilder struct { hKeyPlus [common.NbElemPerHash][]field.Element // Pointer check columns // leafMinusIndex is the index of the minus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafMinusIndex] - leafMinusIndex [common.NbElemU64][]field.Element + leafMinusIndex [common.NbElemForHasingU64][]field.Element // leafMinusNext is the index of the Next leaf of the minus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafMinusNext] - leafMinusNext [common.NbElemU64][]field.Element + leafMinusNext [common.NbElemForHasingU64][]field.Element // leafMinusNext is the index of the plus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafPlusIndex] - leafPlusIndex [common.NbElemU64][]field.Element + leafPlusIndex [common.NbElemForHasingU64][]field.Element // leafPlusPrev is the index of the Previous leaf of the plus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafPlusPrev] - leafPlusPrev [common.NbElemU64][]field.Element + leafPlusPrev [common.NbElemForHasingU64][]field.Element // leafDeletedIndex is the index of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedIndex] - leafDeletedIndex [common.NbElemU64][]field.Element + leafDeletedIndex [common.NbElemForHasingU64][]field.Element // leafDeletedPrev is the index of the Previous leaf of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedPrev] - leafDeletedPrev [common.NbElemU64][]field.Element + leafDeletedPrev [common.NbElemForHasingU64][]field.Element // leafDeletedNext is the index of the Previous leaf of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedNext] - leafDeletedNext [common.NbElemU64][]field.Element + leafDeletedNext [common.NbElemForHasingU64][]field.Element // leafOpening is a tuple of four columns containing // Prev, Next, HKey, HVal of a leaf. This corresponds to the [Accumulator.Column.LeafOpening] leafOpening leafOpenings @@ -102,10 +102,10 @@ type assignmentBuilder struct { // isEmptyLeaf is one when Leaves contains empty leaf and does not match with LeafHash isEmptyLeaf []field.Element // nextFreeNode contains the nextFreeNode for each row of every operation - nextFreeNode [common.NbElemU64][]field.Element + nextFreeNode [common.NbElemForHasingU64][]field.Element // insertionPath is the path of a newly inserted leaf when INSERT happens, // it is zero otherwise - insertionPath [common.NbElemU64][]field.Element + insertionPath [common.NbElemForHasingU64][]field.Element // isInsertRow3 is one for row 3 of INSERT operation isInsertRow3 []field.Element // intermTopRoot contains the intermediate MiMC state hash diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index 2ddc5fa757..3f7b9432d6 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -107,8 +107,8 @@ const ( type LeafOpenings struct { HKey [common.NbElemPerHash]ifaces.Column HVal [common.NbElemPerHash]ifaces.Column - Prev [common.NbElemU64]ifaces.Column - Next [common.NbElemU64]ifaces.Column + Prev [common.NbElemForHasingU64]ifaces.Column + Next [common.NbElemForHasingU64]ifaces.Column } // Module module @@ -120,14 +120,14 @@ type Module struct { Cols struct { Leaves [common.NbElemPerHash]ifaces.Column Roots [common.NbElemPerHash]ifaces.Column - Positions [common.NbElemU64]ifaces.Column + Positions [common.NbLimbU64]ifaces.Column Proofs *merkle.FlatProof // Column to verify reuse of Merkle proofs in INSERT, DELETE, and UPDATE operations UseNextMerkleProof ifaces.Column // Column denoting the active area of the accumulator module IsActiveAccumulator ifaces.Column // Columns to check sequentiality of the accumulator module with Merkle module - AccumulatorCounter [common.NbElemU64]ifaces.Column + AccumulatorCounter [common.NbElemForHasingU64]ifaces.Column // Column to verify the two equalities of intermediateRoot1 and intermediateRoot3, and empty // leafs for INSERT and DELETE operation and one equality of root in IsReadZero operation IsFirst ifaces.Column @@ -156,19 +156,19 @@ type Module struct { // Columns for the pointer check // Columns storing the index of the minus leaf - LeafMinusIndex [common.NbElemU64]ifaces.Column + LeafMinusIndex [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the next leaf of the minus leaf - LeafMinusNext [common.NbElemU64]ifaces.Column + LeafMinusNext [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the plus leaf - LeafPlusIndex [common.NbElemU64]ifaces.Column + LeafPlusIndex [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the previous leaf of the plus leaf - LeafPlusPrev [common.NbElemU64]ifaces.Column + LeafPlusPrev [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the deleted leaf - LeafDeletedIndex [common.NbElemU64]ifaces.Column + LeafDeletedIndex [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the previous leaf of the deleted leaf - LeafDeletedPrev [common.NbElemU64]ifaces.Column + LeafDeletedPrev [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the next leaf of the deleted leaf - LeafDeletedNext [common.NbElemU64]ifaces.Column + LeafDeletedNext [common.NbElemForHasingU64]ifaces.Column // Columns for leaf hashing check // LeafOpening contains four columns corresponding to HKey, HVal, Prev, and Next @@ -184,12 +184,12 @@ type Module struct { // Columns to check NextFreeNode consistency // NextFreeNode stores the nextFreeNode for each row of every operation - NextFreeNode [common.NbElemU64]ifaces.Column + NextFreeNode [common.NbElemForHasingU64]ifaces.Column // NextFreeNodeIncremented stores a value that indicates how much NextFreeNode[i] is increased // relative to the NextFreeNode[i-1] - NextFreeNodeIncremented [common.NbElemU64]ifaces.Column + NextFreeNodeIncremented [common.NbElemForHasingU64]ifaces.Column // InsertionPath stores the index of the newly inserted leaf by INSERT - InsertionPath [common.NbElemU64]ifaces.Column + InsertionPath [common.NbElemForHasingU64]ifaces.Column // IsInsertRow3 is one for row 3 of INSERT operation IsInsertRow3 ifaces.Column From f44ffe63f411ae982315ae63c7c544cd6e8475c4 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Fri, 14 Nov 2025 19:12:53 +0530 Subject: [PATCH 04/22] feat(flat-proof): bit decompose with slices of pos columns (wip) --- .../protocol/dedicated/bits/bitdecompose.go | 127 +++++++++++++----- .../dedicated/merkle/flat_proof_test.go | 61 ++++++--- .../merkle/flat_proof_verification.go | 10 +- prover/zkevm/prover/common/flatten_column.go | 4 +- prover/zkevm/prover/common/hashing.go | 1 + prover/zkevm/prover/common/hilo.go | 2 + prover/zkevm/prover/common/round_zero.go | 2 +- 7 files changed, 153 insertions(+), 54 deletions(-) diff --git a/prover/protocol/dedicated/bits/bitdecompose.go b/prover/protocol/dedicated/bits/bitdecompose.go index cedc2bf5fb..19eb2bd65e 100644 --- a/prover/protocol/dedicated/bits/bitdecompose.go +++ b/prover/protocol/dedicated/bits/bitdecompose.go @@ -6,49 +6,67 @@ import ( "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/wizard" "github.com/consensys/linea-monorepo/prover/symbolic" + "github.com/consensys/linea-monorepo/prover/zkevm/prover/common" ) // BitDecomposed represents the output of a bit decomposition of -// a column. The struct implements the [wizard.ProverAction] interface +// a slice of columns. The struct implements the [wizard.ProverAction] interface // to self-assign itself. type BitDecomposed struct { - // Packed is the input of the bit-decomposition - Packed ifaces.Column + // packed is the input of the bit-decomposition + packed []ifaces.Column // Bits lists the decomposed bits of the "packed" column in LSbit // order. Bits []ifaces.Column + isPackedLimbNotZero []ifaces.Column } // BitDecompose generates a bit decomposition of a column and returns // a struct that implements the [wizard.ProverAction] interface to // self-assign itself. -func BitDecompose(comp *wizard.CompiledIOP, packed ifaces.Column, numBits int) *BitDecomposed { +func BitDecompose(comp *wizard.CompiledIOP, packed []ifaces.Column, numBits int) *BitDecomposed { var ( - round = packed.Round() - bitExpr = []*symbolic.Expression{} - bd = &BitDecomposed{ - Packed: packed, + round = packed[0].Round() + bd = &BitDecomposed{ + packed: packed, Bits: make([]ifaces.Column, numBits), } ) - for i := 0; i < numBits; i++ { - bd.Bits[i] = comp.InsertCommit(round, ifaces.ColIDf("%v_BIT_%v", packed.GetColID(), i), packed.Size(), true) - MustBeBoolean(comp, bd.Bits[i]) - bitExpr = append(bitExpr, symbolic.NewVariable(bd.Bits[i])) + bitExpr := []*symbolic.Expression{} + + for j := 0; j < numBits; j++ { + bd.Bits[j] = comp.InsertCommit(round, ifaces.ColIDf("%v_BIT_%v", packed[0].GetColID(), j), packed[0].Size(), true) + MustBeBoolean(comp, bd.Bits[j]) + bitExpr = append(bitExpr, symbolic.NewVariable(bd.Bits[j])) } // This constraint ensures that the recombined bits are equal to the // original column. - comp.InsertGlobal( - round, - ifaces.QueryID(packed.GetColID())+"_BIT_RECOMBINATION", - symbolic.Sub( - packed, - symbolic.NewPolyEval(symbolic.NewConstant(2), bitExpr), - ), - ) + for i := 0; i < len(packed); i++ { + bd.isPackedLimbNotZero = append(bd.isPackedLimbNotZero, comp.InsertCommit(round, ifaces.ColIDf("IS_PACKED_NOT_ZERO_%v", i), packed[0].Size(), true)) + } + + for i := len(packed) - 1; i >= 0; i-- { + ind := len(packed) - i - 1 + + if ind < len(bd.Bits)/16 { + break + } + + comp.InsertGlobal( + round, + ifaces.QueryIDf("%v_BIT_RECOMBINATION", packed[i].GetColID()), + symbolic.Mul( + bd.isPackedLimbNotZero[ind], + symbolic.Sub( + packed[i], + symbolic.NewPolyEval(symbolic.NewConstant(2), bitExpr[ind*16:ind*16+16]), + ), + ), + ) + } return bd } @@ -56,25 +74,56 @@ func BitDecompose(comp *wizard.CompiledIOP, packed ifaces.Column, numBits int) * // Run implements the [wizard.ProverAction] interface and assigns the bits // columns func (bd *BitDecomposed) Run(run *wizard.ProverRuntime) { - - v := bd.Packed.GetColAssignment(run) bits := make([][]field.Element, len(bd.Bits)) - for x := range v.IterateCompact() { + // Obtain packed elements from + var elements [][]field.Element + for i, packed := range bd.packed { + + v := packed.GetColAssignment(run) + var packedElements []field.Element + var packedElementsIsZero []field.Element + + for colElement := range v.IterateCompact() { + packedElements = append(packedElements, colElement) + + isPackedLimbNotZero := field.One() + if colElement.IsZero() { + isPackedLimbNotZero = field.Zero() + } + + packedElementsIsZero = append(packedElementsIsZero, isPackedLimbNotZero) + } + + run.AssignColumn(bd.isPackedLimbNotZero[i].GetColID(), smartvectors.RightZeroPadded(packedElementsIsZero, bd.packed[0].Size())) + + elements = append(elements, packedElements) + } + + for i := range elements[0] { + var el []field.Element + for j := range elements { + el = append(el, elements[j][i]) + } + + x := combineElements(el) - x := x.Uint64() + if !x.IsUint64() { + panic("can handle 64 bits at most") + } - for i := range bd.Bits { - if x>>i&1 == 1 { - bits[i] = append(bits[i], field.One()) + xNum := x.Uint64() + for j := range len(bd.Bits) { + if xNum>>j&1 == 1 { + bits[j] = append(bits[j], field.One()) } else { - bits[i] = append(bits[i], field.Zero()) + bits[j] = append(bits[j], field.Zero()) } } } - for i := range bd.Bits { - run.AssignColumn(bd.Bits[i].GetColID(), smartvectors.FromCompactWithShape(v, bits[i])) + for i, bitCol := range bd.Bits { + run.AssignColumn(bitCol.GetColID(), smartvectors.FromCompactWithShape(bd.packed[0].GetColAssignment(run), bits[i])) } } @@ -87,3 +136,21 @@ func MustBeBoolean(comp *wizard.CompiledIOP, col ifaces.Column) { ifaces.QueryID(col.GetColID())+"_IS_BOOLEAN", symbolic.Sub(col, symbolic.Mul(col, col))) } + +// combineElements combines an array of limb elements into a single element. +// It extracts a specific suffix of bytes from each field.Element +// in the input slice and concatenates them into a single byte slice. +// It then uses this concatenated byte slice to initialize and return a new +// field.Element. +func combineElements(elements []field.Element) field.Element { + var bytes []byte + for _, element := range elements { + elementBytes := element.Bytes() + bytes = append(bytes, elementBytes[len(elementBytes)-common.LimbBytes:]...) + } + + var res field.Element + res.SetBytes(bytes) + + return res +} diff --git a/prover/protocol/dedicated/merkle/flat_proof_test.go b/prover/protocol/dedicated/merkle/flat_proof_test.go index 95131cdfdc..6f8719793c 100644 --- a/prover/protocol/dedicated/merkle/flat_proof_test.go +++ b/prover/protocol/dedicated/merkle/flat_proof_test.go @@ -11,6 +11,7 @@ import ( "github.com/consensys/linea-monorepo/prover/protocol/compiler/dummy" "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/wizard" + "github.com/sirupsen/logrus" ) const ( @@ -64,19 +65,26 @@ type merkleTestRunnerFlat struct { // Define implements the [wizard.DefineFunc] interface func (ctx *merkleTestRunnerFlat) Define(b *wizard.Builder) { - var leaf, roots [blockSize]ifaces.Column + var ( + leaf, roots [blockSize]ifaces.Column + position [limbPerU64]ifaces.Column + ) + proofs := *NewProof(b.CompiledIOP, 0, "test", merkleTestDepth, merkleTestNumRow) for i := 0; i < blockSize; i++ { leaf[i] = b.RegisterCommit(ifaces.ColIDf("LEAF_%v", i), merkleTestNumRow) roots[i] = b.RegisterCommit(ifaces.ColIDf("ROOTS_%v", i), merkleTestNumRow) } + for i := 0; i < limbPerU64; i++ { + position[i] = b.RegisterCommit(ifaces.ColIDf("POS_LIMB_%v", i), merkleTestNumRow) + } mpvInputs := FlatProofVerificationInputs{ Name: "test", Proof: proofs, Leaf: leaf, Roots: roots, - Position: b.RegisterCommit("POS", merkleTestNumRow), + Position: position, IsActive: b.RegisterCommit("ACTIVE", merkleTestNumRow), } @@ -89,26 +97,29 @@ func (ctx *merkleTestRunnerFlat) Assign(run *wizard.ProverRuntime, data *merkleT run.AssignColumn(ifaces.ColIDf("LEAF_%v", i), smartvectors.RightZeroPadded(data.leaves[i], merkleTestNumRow)) run.AssignColumn(ifaces.ColIDf("ROOTS_%v", i), smartvectors.RightZeroPadded(data.roots[i], merkleTestNumRow)) } - run.AssignColumn("POS", smartvectors.RightZeroPadded(data.pos, merkleTestNumRow)) + for i := 0; i < limbPerU64; i++ { + logrus.Printf("Assigning POS_LIMB_%v: %v\n", i, data.pos[i]) + run.AssignColumn(ifaces.ColIDf("POS_LIMB_%v", i), smartvectors.RightZeroPadded(data.pos[i], merkleTestNumRow)) + } run.AssignColumn("ACTIVE", smartvectors.RightZeroPadded(data.isActive, merkleTestNumRow)) ctx.ctx.Proof.Assign(run, data.proofs) ctx.ctx.Run(run) - for i := 0; i < merkleTestNumRow; i++ { - for l := 0; l < merkleTestDepth; l++ { + // for i := 0; i < merkleTestNumRow; i++ { + // for l := 0; l < merkleTestDepth; l++ { - var left, right, node [blockSize]field.Element + // var left, right, node [blockSize]field.Element - for k := 0; k < blockSize; k++ { - left[k] = ctx.ctx.Lefts[l][k].Result.GetColAssignmentAt(run, i) - right[k] = ctx.ctx.Rights[l][k].Result.GetColAssignmentAt(run, i) - node[k] = ctx.ctx.Nodes[l].Result()[k].GetColAssignmentAt(run, i) - fmt.Printf("proof=%v level=%v left=%v right=%v node=%v\n", i, l, left[k].Text(16), right[k].Text(16), node[k].Text(16)) - } + // // for k := 0; k < blockSize; k++ { + // // left[k] = ctx.ctx.Lefts[l][k].Result.GetColAssignmentAt(run, i) + // // right[k] = ctx.ctx.Rights[l][k].Result.GetColAssignmentAt(run, i) + // // node[k] = ctx.ctx.Nodes[l].Result()[k].GetColAssignmentAt(run, i) + // // fmt.Printf("proof=%v level=%v left=%v right=%v node=%v\n", i, l, left[k].Text(16), right[k].Text(16), node[k].Text(16)) + // // } - } - } + // } + // } } // merkleTestCaseInstance represents either a read or a write operation to add to @@ -124,7 +135,7 @@ type merkleTestCaseInstance struct { // and is implemented like a writer. type merkleTestBuilder struct { proofs []smt.Proof - pos []field.Element + pos [limbPerU64][]field.Element roots [blockSize][]field.Element leaves [blockSize][]field.Element useNextMerkleProof []field.Element @@ -147,7 +158,7 @@ func newMerkleTestBuilder(depth int) *merkleTestBuilder { tree: *smt.BuildComplete(make([]field.Octuplet, 1<> 16) & 0xFFFF) + limbs[2] = uint64((v >> 32) & 0xFFFF) + limbs[3] = uint64((v >> 48) & 0xFFFF) + return limbs +} diff --git a/prover/protocol/dedicated/merkle/flat_proof_verification.go b/prover/protocol/dedicated/merkle/flat_proof_verification.go index 34ed4f058a..683848a5e2 100644 --- a/prover/protocol/dedicated/merkle/flat_proof_verification.go +++ b/prover/protocol/dedicated/merkle/flat_proof_verification.go @@ -24,7 +24,7 @@ type FlatProofVerificationInputs struct { // Roots contains the Merkle roots Roots [blockSize]ifaces.Column // Position contains the positions of the alleged leaves - Position ifaces.Column + Position [limbPerU64]ifaces.Column // Use for looking up and selecting only the the columns containing the // root in the ComputeMod. IsActive ifaces.Column @@ -56,7 +56,7 @@ func CheckFlatMerkleProofs(comp *wizard.CompiledIOP, inputs FlatProofVerificatio ctx := &FlatMerkleProofVerification{ FlatProofVerificationInputs: inputs, - PosBits: bits.BitDecompose(comp, inputs.Position, len(inputs.Proof.Nodes[0])), + PosBits: bits.BitDecompose(comp, inputs.Position[:], len(inputs.Proof.Nodes[0])), } prevNode := inputs.Leaf @@ -148,8 +148,10 @@ func checkColumnsAllHaveSameSize(inp *FlatProofVerificationInputs) error { return fmt.Errorf("all nodes must have the same size: root=%v leaf=%v", size, inp.Leaf[j].Size()) } } - if inp.Position.Size() != size { - return fmt.Errorf("all nodes must have the same size: root=%v position=%v", size, inp.Position.Size()) + for i := range inp.Position { + if inp.Position[i].Size() != size { + return fmt.Errorf("all nodes must have the same size: root=%v position=%v", size, inp.Position[i].Size()) + } } if inp.IsActive.Size() != size { diff --git a/prover/zkevm/prover/common/flatten_column.go b/prover/zkevm/prover/common/flatten_column.go index 2eea50bb60..52008d9617 100644 --- a/prover/zkevm/prover/common/flatten_column.go +++ b/prover/zkevm/prover/common/flatten_column.go @@ -87,7 +87,7 @@ func NewFlattenColumn(comp *wizard.CompiledIOP, nbLimbsCols int, limbs []ifaces. } res.initColumns(comp) - res.mask = comp.InsertCommit(0, res.MaskColID(), flattenSize) + res.mask = comp.InsertCommit(0, res.MaskColID(), flattenSize, true) return res } @@ -196,7 +196,7 @@ func (l *FlattenColumn) initColumns(comp *wizard.CompiledIOP) { return } - l.limbs = comp.InsertCommit(0, baseID, l.size) + l.limbs = comp.InsertCommit(0, baseID, l.size, true) l.auxProjectionMask = comp.InsertPrecomputed(auxProjectionMaskID, precomputeAuxProjectionMask(l.size, l.originalMask.Size(), l.nbLimbsCols)) } diff --git a/prover/zkevm/prover/common/hashing.go b/prover/zkevm/prover/common/hashing.go index b97e74e651..eadb6ce537 100644 --- a/prover/zkevm/prover/common/hashing.go +++ b/prover/zkevm/prover/common/hashing.go @@ -47,6 +47,7 @@ func HashOf(comp *wizard.CompiledIOP, inputCols []ifaces.Column) (ifaces.Column, round, ifaces.ColIDf("HASHING_%v_%v", ctxID, i), numRows, + true, ) comp.InsertMiMC( diff --git a/prover/zkevm/prover/common/hilo.go b/prover/zkevm/prover/common/hilo.go index bec000e333..3d09bf69a0 100644 --- a/prover/zkevm/prover/common/hilo.go +++ b/prover/zkevm/prover/common/hilo.go @@ -22,12 +22,14 @@ func NewHiLoColumns(comp *wizard.CompiledIOP, size int, name string) HiLoColumns 0, ifaces.ColIDf("STATE_SUMMARY_%v_HI_%v", name, i), size, + true, ) res.Lo[i] = comp.InsertCommit( 0, ifaces.ColIDf("STATE_SUMMARY_%v_LO_%v", name, i), size, + true, ) } diff --git a/prover/zkevm/prover/common/round_zero.go b/prover/zkevm/prover/common/round_zero.go index d03e3e9496..80e6289d98 100644 --- a/prover/zkevm/prover/common/round_zero.go +++ b/prover/zkevm/prover/common/round_zero.go @@ -14,7 +14,7 @@ func CreateColFn(comp *wizard.CompiledIOP, rootName string, size int, withPragma return func(name string, args ...interface{}) ifaces.Column { s := []string{rootName, name} v := strings.Join(s, "_") - col := comp.InsertCommit(0, ifaces.ColIDf(v, args...), size) + col := comp.InsertCommit(0, ifaces.ColIDf(v, args...), size, true) switch withPragmas { case pragmas.None: From d60b149d6d7eeb5d35c115afba3b766684dd3372 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Fri, 14 Nov 2025 19:30:53 +0530 Subject: [PATCH 05/22] fix(flat-proof): bug fix, test passing --- .../protocol/dedicated/merkle/flat_proof_test.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/prover/protocol/dedicated/merkle/flat_proof_test.go b/prover/protocol/dedicated/merkle/flat_proof_test.go index 6f8719793c..38bfbe7990 100644 --- a/prover/protocol/dedicated/merkle/flat_proof_test.go +++ b/prover/protocol/dedicated/merkle/flat_proof_test.go @@ -7,6 +7,7 @@ import ( "github.com/consensys/linea-monorepo/prover/crypto/poseidon2" "github.com/consensys/linea-monorepo/prover/crypto/state-management/smt" "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" + "github.com/consensys/linea-monorepo/prover/maths/common/vector" "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/compiler/dummy" "github.com/consensys/linea-monorepo/prover/protocol/ifaces" @@ -98,7 +99,7 @@ func (ctx *merkleTestRunnerFlat) Assign(run *wizard.ProverRuntime, data *merkleT run.AssignColumn(ifaces.ColIDf("ROOTS_%v", i), smartvectors.RightZeroPadded(data.roots[i], merkleTestNumRow)) } for i := 0; i < limbPerU64; i++ { - logrus.Printf("Assigning POS_LIMB_%v: %v\n", i, data.pos[i]) + logrus.Printf("Assigning POS_LIMB_%v: %v\n", i, vector.Prettify(data.pos[i])) run.AssignColumn(ifaces.ColIDf("POS_LIMB_%v", i), smartvectors.RightZeroPadded(data.pos[i], merkleTestNumRow)) } run.AssignColumn("ACTIVE", smartvectors.RightZeroPadded(data.isActive, merkleTestNumRow)) @@ -219,13 +220,13 @@ func (mt *merkleTestBuilder) pushRow(row merkleTestBuilderRow) { mt.isActive = append(mt.isActive, field.One()) } -// uint64To16BitLimbs splits v into four 16-bit limbs (little-endian order): -// limbs[0] = low 16 bits, limbs[3] = highest 16 bits. +// uint64To16BitLimbs splits v into four 16-bit limbs (big-endian order): +// limbs[3] = low 16 bits, limbs[0] = highest 16 bits. func uint64To16BitLimbs(v uint64) [4]uint64 { var limbs [4]uint64 - limbs[0] = uint64(v & 0xFFFF) - limbs[1] = uint64((v >> 16) & 0xFFFF) - limbs[2] = uint64((v >> 32) & 0xFFFF) - limbs[3] = uint64((v >> 48) & 0xFFFF) + limbs[3] = uint64(v & 0xFFFF) + limbs[2] = uint64((v >> 16) & 0xFFFF) + limbs[1] = uint64((v >> 32) & 0xFFFF) + limbs[0] = uint64((v >> 48) & 0xFFFF) return limbs } From f2ec52803169f2397226cb827c878c41557a2a0f Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Tue, 18 Nov 2025 16:28:40 +0530 Subject: [PATCH 06/22] minor: remove and reinstate print statements --- .../dedicated/merkle/flat_proof_test.go | 27 +++++++++---------- .../prover/statemanager/accumulator/assign.go | 27 ++++++++++--------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/prover/protocol/dedicated/merkle/flat_proof_test.go b/prover/protocol/dedicated/merkle/flat_proof_test.go index 38bfbe7990..9341f5b784 100644 --- a/prover/protocol/dedicated/merkle/flat_proof_test.go +++ b/prover/protocol/dedicated/merkle/flat_proof_test.go @@ -7,12 +7,10 @@ import ( "github.com/consensys/linea-monorepo/prover/crypto/poseidon2" "github.com/consensys/linea-monorepo/prover/crypto/state-management/smt" "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" - "github.com/consensys/linea-monorepo/prover/maths/common/vector" "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/compiler/dummy" "github.com/consensys/linea-monorepo/prover/protocol/ifaces" "github.com/consensys/linea-monorepo/prover/protocol/wizard" - "github.com/sirupsen/logrus" ) const ( @@ -99,7 +97,6 @@ func (ctx *merkleTestRunnerFlat) Assign(run *wizard.ProverRuntime, data *merkleT run.AssignColumn(ifaces.ColIDf("ROOTS_%v", i), smartvectors.RightZeroPadded(data.roots[i], merkleTestNumRow)) } for i := 0; i < limbPerU64; i++ { - logrus.Printf("Assigning POS_LIMB_%v: %v\n", i, vector.Prettify(data.pos[i])) run.AssignColumn(ifaces.ColIDf("POS_LIMB_%v", i), smartvectors.RightZeroPadded(data.pos[i], merkleTestNumRow)) } run.AssignColumn("ACTIVE", smartvectors.RightZeroPadded(data.isActive, merkleTestNumRow)) @@ -107,20 +104,20 @@ func (ctx *merkleTestRunnerFlat) Assign(run *wizard.ProverRuntime, data *merkleT ctx.ctx.Proof.Assign(run, data.proofs) ctx.ctx.Run(run) - // for i := 0; i < merkleTestNumRow; i++ { - // for l := 0; l < merkleTestDepth; l++ { + for i := 0; i < merkleTestNumRow; i++ { + for l := 0; l < merkleTestDepth; l++ { - // var left, right, node [blockSize]field.Element + var left, right, node [blockSize]field.Element - // // for k := 0; k < blockSize; k++ { - // // left[k] = ctx.ctx.Lefts[l][k].Result.GetColAssignmentAt(run, i) - // // right[k] = ctx.ctx.Rights[l][k].Result.GetColAssignmentAt(run, i) - // // node[k] = ctx.ctx.Nodes[l].Result()[k].GetColAssignmentAt(run, i) - // // fmt.Printf("proof=%v level=%v left=%v right=%v node=%v\n", i, l, left[k].Text(16), right[k].Text(16), node[k].Text(16)) - // // } + for k := 0; k < blockSize; k++ { + left[k] = ctx.ctx.Lefts[l][k].Result.GetColAssignmentAt(run, i) + right[k] = ctx.ctx.Rights[l][k].Result.GetColAssignmentAt(run, i) + node[k] = ctx.ctx.Nodes[l].Result()[k].GetColAssignmentAt(run, i) + fmt.Printf("proof=%v level=%v left=%v right=%v node=%v\n", i, l, left[k].Text(16), right[k].Text(16), node[k].Text(16)) + } - // } - // } + } + } } // merkleTestCaseInstance represents either a read or a write operation to add to @@ -159,7 +156,7 @@ func newMerkleTestBuilder(depth int) *merkleTestBuilder { tree: *smt.BuildComplete(make([]field.Octuplet, 1< Date: Tue, 18 Nov 2025 17:35:08 +0530 Subject: [PATCH 07/22] fix(accumulator): fix define column dimension --- .../prover/statemanager/accumulator/define.go | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index 3f7b9432d6..da94fb5998 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -127,7 +127,7 @@ type Module struct { // Column denoting the active area of the accumulator module IsActiveAccumulator ifaces.Column // Columns to check sequentiality of the accumulator module with Merkle module - AccumulatorCounter [common.NbElemForHasingU64]ifaces.Column + AccumulatorCounter [common.NbLimbU64]ifaces.Column // Column to verify the two equalities of intermediateRoot1 and intermediateRoot3, and empty // leafs for INSERT and DELETE operation and one equality of root in IsReadZero operation IsFirst ifaces.Column @@ -156,19 +156,19 @@ type Module struct { // Columns for the pointer check // Columns storing the index of the minus leaf - LeafMinusIndex [common.NbElemForHasingU64]ifaces.Column + LeafMinusIndex [common.NbLimbU64]ifaces.Column // Columns storing the index of the next leaf of the minus leaf - LeafMinusNext [common.NbElemForHasingU64]ifaces.Column + LeafMinusNext [common.NbLimbU64]ifaces.Column // Columns storing the index of the plus leaf - LeafPlusIndex [common.NbElemForHasingU64]ifaces.Column + LeafPlusIndex [common.NbLimbU64]ifaces.Column // Columns storing the index of the previous leaf of the plus leaf - LeafPlusPrev [common.NbElemForHasingU64]ifaces.Column + LeafPlusPrev [common.NbLimbU64]ifaces.Column // Columns storing the index of the deleted leaf - LeafDeletedIndex [common.NbElemForHasingU64]ifaces.Column + LeafDeletedIndex [common.NbLimbU64]ifaces.Column // Columns storing the index of the previous leaf of the deleted leaf - LeafDeletedPrev [common.NbElemForHasingU64]ifaces.Column + LeafDeletedPrev [common.NbLimbU64]ifaces.Column // Columns storing the index of the next leaf of the deleted leaf - LeafDeletedNext [common.NbElemForHasingU64]ifaces.Column + LeafDeletedNext [common.NbLimbU64]ifaces.Column // Columns for leaf hashing check // LeafOpening contains four columns corresponding to HKey, HVal, Prev, and Next @@ -184,12 +184,12 @@ type Module struct { // Columns to check NextFreeNode consistency // NextFreeNode stores the nextFreeNode for each row of every operation - NextFreeNode [common.NbElemForHasingU64]ifaces.Column + NextFreeNode [common.NbLimbU64]ifaces.Column // NextFreeNodeIncremented stores a value that indicates how much NextFreeNode[i] is increased // relative to the NextFreeNode[i-1] - NextFreeNodeIncremented [common.NbElemForHasingU64]ifaces.Column + NextFreeNodeIncremented [common.NbLimbU64]ifaces.Column // InsertionPath stores the index of the newly inserted leaf by INSERT - InsertionPath [common.NbElemForHasingU64]ifaces.Column + InsertionPath [common.NbLimbU64]ifaces.Column // IsInsertRow3 is one for row 3 of INSERT operation IsInsertRow3 ifaces.Column From 9c390104c2587e5703c0ebf44ed2be8dcb298fd6 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Wed, 19 Nov 2025 16:24:18 +0530 Subject: [PATCH 08/22] fix(accumulator/assign): remove mimc with posseidon2 --- .../prover/statemanager/accumulator/assign.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index 11347fc190..a1e1dec7ec 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -5,6 +5,7 @@ import ( "fmt" "io" + "github.com/consensys/gnark-crypto/field/koalabear/vortex" "github.com/consensys/linea-monorepo/prover/zkevm/prover/common" "github.com/consensys/linea-monorepo/prover/backend/execution/statemanager" @@ -311,10 +312,11 @@ func (am *Module) assignLeaf( var ( cols = am.Cols paddedSize = am.NumRows() - intermZeroLimbs = common.BlockCompression([]field.Element{field.Zero()}, []field.Element{field.Zero()}) - intermOneLimbs = common.BlockCompression(intermZeroLimbs, []field.Element{field.Zero()}) - intermTwoLimbs = common.BlockCompression(intermOneLimbs, []field.Element{field.Zero()}) - leafLimbs = common.BlockCompression(intermTwoLimbs, []field.Element{field.Zero()}) + zeroBlock field.Octuplet + intermZeroLimbs = vortex.CompressPoseidon2(zeroBlock, zeroBlock) + intermOneLimbs = vortex.CompressPoseidon2(intermZeroLimbs, zeroBlock) + intermTwoLimbs = vortex.CompressPoseidon2(intermOneLimbs, zeroBlock) + leafLimbs = vortex.CompressPoseidon2(intermTwoLimbs, zeroBlock) ) run.AssignColumn(cols.IsEmptyLeaf.GetColID(), smartvectors.RightZeroPadded(builder.isEmptyLeaf, paddedSize)) @@ -343,8 +345,9 @@ func (am *Module) assignTopRootCols( paddedSize := am.NumRows() // compute the padding values for intermTopRoot and topRoot - intermTopRootPadLimbs := common.BlockCompression([]field.Element{field.Zero()}, []field.Element{field.Zero()}) - topRootPadLimbs := common.BlockCompression(intermTopRootPadLimbs, []field.Element{field.Zero()}) + var zeroBlock field.Octuplet + intermTopRootPadLimbs := vortex.CompressPoseidon2(zeroBlock, zeroBlock) + topRootPadLimbs := vortex.CompressPoseidon2(intermTopRootPadLimbs, zeroBlock) for i := range cols.IntermTopRoot { run.AssignColumn(cols.IntermTopRoot[i].GetColID(), smartvectors.RightPadded(builder.intermTopRoot[i], intermTopRootPadLimbs[i], paddedSize)) From e3ef6d0712aa28f045e396c3d4904f712e1c74fa Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Thu, 20 Nov 2025 17:13:21 +0530 Subject: [PATCH 09/22] fix: mimc_config to poseidon2 config --- .../execution/statemanager/access_pattern.go | 4 +-- .../execution/statemanager/proof_checks.go | 8 ++--- .../statemanager/test_vectors_test.go | 30 +++++++++---------- .../execution/statemanager/worldstate.go | 8 ++--- .../prover/statemanager/accumulator/assign.go | 4 +-- .../statemanager/accumulator/assign_test.go | 15 +++++----- .../prover/statemanager/mock/basic_state.go | 2 +- .../zkevm/prover/statemanager/mock/shomei.go | 6 ++-- .../statemanager/mock/state_access_log.go | 2 +- .../prover/statemanager/state_manager.go | 2 +- .../statemanager/statesummary/account_peek.go | 2 +- 11 files changed, 42 insertions(+), 41 deletions(-) diff --git a/prover/backend/execution/statemanager/access_pattern.go b/prover/backend/execution/statemanager/access_pattern.go index 0f47cd200a..0d691cd294 100644 --- a/prover/backend/execution/statemanager/access_pattern.go +++ b/prover/backend/execution/statemanager/access_pattern.go @@ -377,8 +377,8 @@ func checkStorageTraceOrder(traces []DecodedTrace) (err error) { next = traces[i+1].Underlying currRW = curr.RWInt() nextRW = next.RWInt() - currHKey = curr.HKey(MIMC_CONFIG) - nextHKey = next.HKey(MIMC_CONFIG) + currHKey = curr.HKey(POSEIDON2_CONFIG) + nextHKey = next.HKey(POSEIDON2_CONFIG) ) if currRW > nextRW { diff --git a/prover/backend/execution/statemanager/proof_checks.go b/prover/backend/execution/statemanager/proof_checks.go index 8725cd0f8a..dedd0468eb 100644 --- a/prover/backend/execution/statemanager/proof_checks.go +++ b/prover/backend/execution/statemanager/proof_checks.go @@ -119,8 +119,8 @@ func checkProofsWorldState(traces []DecodedTrace) (oldRootHash, newRootHash Dige if i < len(traces)-1 { var ( - currHKey = traces[i].Underlying.HKey(MIMC_CONFIG) - nextHKey = traces[i+1].Underlying.HKey(MIMC_CONFIG) + currHKey = traces[i].Underlying.HKey(POSEIDON2_CONFIG) + nextHKey = traces[i+1].Underlying.HKey(POSEIDON2_CONFIG) ) if types.Bytes32Cmp(currHKey, nextHKey) > 0 { @@ -221,7 +221,7 @@ func bootstrapVerifierStateFromST(trace DecodedTrace) (vs StorageVerifier) { vs = StorageVerifier{ Location: trace.Location, - Config: MIMC_CONFIG, + Config: POSEIDON2_CONFIG, } switch t := trace.Underlying.(type) { @@ -252,7 +252,7 @@ func bootstrapVerifierStateFromWS(trace DecodedTrace) (vs AccountVerifier) { vs = AccountVerifier{ Location: trace.Location, - Config: MIMC_CONFIG, + Config: POSEIDON2_CONFIG, } switch t := trace.Underlying.(type) { diff --git a/prover/backend/execution/statemanager/test_vectors_test.go b/prover/backend/execution/statemanager/test_vectors_test.go index d01966c5d8..b904fcb0ed 100644 --- a/prover/backend/execution/statemanager/test_vectors_test.go +++ b/prover/backend/execution/statemanager/test_vectors_test.go @@ -29,7 +29,7 @@ func DummyDigest(i int) (d eth.Digest) { } func Hash(t io.WriterTo) types.Bytes32 { - hasher := eth.MIMC_CONFIG.HashFunc() + hasher := eth.POSEIDON2_CONFIG.HashFunc() t.WriteTo(hasher) return types.AsBytes32(hasher.Sum(nil)) } @@ -60,7 +60,7 @@ func TestEmptyStorageTrieHash(t *testing.T) { - Root hash of the empty world state */ func TestEmptyWorldStateMiMC(t *testing.T) { - worldstate := eth.NewWorldState(eth.MIMC_CONFIG) + worldstate := eth.NewWorldState(eth.POSEIDON2_CONFIG) // should be the top root of an empty accumulator assert.Equal(t, "0x07977874126658098c066972282d4c85f230520af3847e297fe7524f976873e5", worldstate.AccountTrie.TopRoot().Hex()) } @@ -71,11 +71,11 @@ func TestEmptyWorldStateMiMC(t *testing.T) { */ func TestWorldStateWithAnAccountMiMC(t *testing.T) { - account := eth.NewEOA(eth.MIMC_CONFIG, 65, big.NewInt(835)) + account := eth.NewEOA(eth.POSEIDON2_CONFIG, 65, big.NewInt(835)) // This gives a non-zero dummy address to the account address := DummyAddress(36) - worldstate := eth.NewWorldState(eth.MIMC_CONFIG) + worldstate := eth.NewWorldState(eth.POSEIDON2_CONFIG) worldstate.AccountTrie.InsertAndProve(address, account) // check that the hash of the inserted account matches @@ -94,14 +94,14 @@ func TestWorldStateWithAnAccountMiMC(t *testing.T) { */ func TestWorldStateWithTwoAccountMiMC(t *testing.T) { - accountA := eth.NewEOA(eth.MIMC_CONFIG, 65, big.NewInt(835)) + accountA := eth.NewEOA(eth.POSEIDON2_CONFIG, 65, big.NewInt(835)) // This gives a non-zero dummy address to the account addressA := DummyAddress(36) - accountB := eth.NewEOA(eth.MIMC_CONFIG, 42, big.NewInt(354)) + accountB := eth.NewEOA(eth.POSEIDON2_CONFIG, 42, big.NewInt(354)) addressB := DummyAddress(41) // must be a different address or the insert will panic - worldstate := eth.NewWorldState(eth.MIMC_CONFIG) + worldstate := eth.NewWorldState(eth.POSEIDON2_CONFIG) worldstate.AccountTrie.InsertAndProve(addressA, accountA) worldstate.AccountTrie.InsertAndProve(addressB, accountB) @@ -120,19 +120,19 @@ func TestWorldStateWithTwoAccountMiMC(t *testing.T) { func TestWorldStateEoaAndContractMiMC(t *testing.T) { // dummy EOA - accountA := eth.NewEOA(eth.MIMC_CONFIG, 65, big.NewInt(835)) + accountA := eth.NewEOA(eth.POSEIDON2_CONFIG, 65, big.NewInt(835)) addressA := DummyAddress(36) // dummy Account - accountB := eth.NewContractEmptyStorage(eth.MIMC_CONFIG, 41, big.NewInt(15353), DummyDigest(75), DummyFullByte(15), 7) + accountB := eth.NewContractEmptyStorage(eth.POSEIDON2_CONFIG, 41, big.NewInt(15353), DummyDigest(75), DummyFullByte(15), 7) addressB := DummyAddress(47) - worldstate := eth.NewWorldState(eth.MIMC_CONFIG) + worldstate := eth.NewWorldState(eth.POSEIDON2_CONFIG) worldstate.AccountTrie.InsertAndProve(addressA, accountA) worldstate.AccountTrie.InsertAndProve(addressB, accountB) // Give a storage trie to B - worldstate.StorageTries.InsertNew(addressB, eth.NewStorageTrie(eth.MIMC_CONFIG, addressB)) + worldstate.StorageTries.InsertNew(addressB, eth.NewStorageTrie(eth.POSEIDON2_CONFIG, addressB)) // The storage tries map stores pointers to the storage tries so we don't need to // update the map after modifying the storage however, we still need to manually @@ -190,18 +190,18 @@ insert C func TestAddAaddBdelAaddCMiMC(t *testing.T) { // dummy EOA - accountA := eth.NewEOA(eth.MIMC_CONFIG, 65, big.NewInt(835)) + accountA := eth.NewEOA(eth.POSEIDON2_CONFIG, 65, big.NewInt(835)) addressA := DummyAddress(36) // dummy Account - accountB := eth.NewContractEmptyStorage(eth.MIMC_CONFIG, 41, big.NewInt(15353), DummyDigest(75), DummyFullByte(15), 7) + accountB := eth.NewContractEmptyStorage(eth.POSEIDON2_CONFIG, 41, big.NewInt(15353), DummyDigest(75), DummyFullByte(15), 7) addressB := DummyAddress(47) // dummy Contract - accountC := eth.NewContractEmptyStorage(eth.MIMC_CONFIG, 48, big.NewInt(9835), DummyDigest(54), DummyFullByte(85), 19) + accountC := eth.NewContractEmptyStorage(eth.POSEIDON2_CONFIG, 48, big.NewInt(9835), DummyDigest(54), DummyFullByte(85), 19) addressC := DummyAddress(120) - worldstate := eth.NewWorldState(eth.MIMC_CONFIG) + worldstate := eth.NewWorldState(eth.POSEIDON2_CONFIG) worldstate.AccountTrie.InsertAndProve(addressA, accountA) worldstate.AccountTrie.InsertAndProve(addressB, accountB) worldstate.AccountTrie.DeleteAndProve(addressA) diff --git a/prover/backend/execution/statemanager/worldstate.go b/prover/backend/execution/statemanager/worldstate.go index 088f5a57f9..9614dba1ca 100644 --- a/prover/backend/execution/statemanager/worldstate.go +++ b/prover/backend/execution/statemanager/worldstate.go @@ -3,8 +3,8 @@ package statemanager import ( "math/big" + "github.com/consensys/linea-monorepo/prover/crypto/poseidon2" "github.com/consensys/linea-monorepo/prover/crypto/state-management/accumulator" - "github.com/consensys/linea-monorepo/prover/crypto/state-management/hashtypes" "github.com/consensys/linea-monorepo/prover/crypto/state-management/smt" "github.com/consensys/linea-monorepo/prover/utils/collection" "github.com/consensys/linea-monorepo/prover/utils/types" @@ -13,8 +13,8 @@ import ( const WS_LOCATION = "0x" -var MIMC_CONFIG = &smt.Config{ - HashFunc: hashtypes.Poseidon2, +var POSEIDON2_CONFIG = &smt.Config{ + HashFunc: poseidon2.Poseidon2, Depth: 40, } @@ -74,7 +74,7 @@ func NewContractEmptyStorage( } } -var MIMC_EMPTY_STORAGE = EmptyStorageTrieHash(MIMC_CONFIG) +var MIMC_EMPTY_STORAGE = EmptyStorageTrieHash(POSEIDON2_CONFIG) func NewAccountTrie(config *smt.Config) *AccountTrie { return accumulator.InitializeProverState[Address, Account](config, WS_LOCATION) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index a1e1dec7ec..3dd4d691f8 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -1140,7 +1140,7 @@ func pushReadNonZeroRows[K, V io.WriterTo]( // Generic hashing for object satisfying the io.WriterTo interface func hash[T io.WriterTo](m T) types.Bytes32 { - hasher := statemanager.MIMC_CONFIG.HashFunc() + hasher := statemanager.POSEIDON2_CONFIG.HashFunc() m.WriteTo(hasher) Bytes32 := hasher.Sum(nil) return types.AsBytes32(Bytes32) @@ -1156,7 +1156,7 @@ func computeRoot(leaf types.Bytes32, proof smt.Proof) types.Bytes32 { if idx&1 == 1 { left, right = right, left } - current = hashLR(statemanager.MIMC_CONFIG, left, right) + current = hashLR(statemanager.POSEIDON2_CONFIG, left, right) idx >>= 1 } diff --git a/prover/zkevm/prover/statemanager/accumulator/assign_test.go b/prover/zkevm/prover/statemanager/accumulator/assign_test.go index 659ebf0ae6..6be1797647 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign_test.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign_test.go @@ -1,9 +1,10 @@ package accumulator import ( - "github.com/consensys/linea-monorepo/prover/zkevm/prover/common" "testing" + "github.com/consensys/linea-monorepo/prover/zkevm/prover/common" + "github.com/consensys/linea-monorepo/prover/backend/execution/statemanager" "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" "github.com/consensys/linea-monorepo/prover/maths/common/vector" @@ -66,7 +67,7 @@ func TestAssignInsert(t *testing.T) { builder := newAssignmentBuilder(testSetting) - acc := statemanager.NewStorageTrie(statemanager.MIMC_CONFIG, types.EthAddress{}) + acc := statemanager.NewStorageTrie(statemanager.POSEIDON2_CONFIG, types.EthAddress{}) traceInsert := acc.InsertAndProve(types.FullBytes32FromHex("0x32"), types.FullBytes32FromHex("0x12")) pushInsertionRows(builder, traceInsert) @@ -110,7 +111,7 @@ func TestAssignUpdate(t *testing.T) { builder := newAssignmentBuilder(testSetting) - acc := statemanager.NewStorageTrie(statemanager.MIMC_CONFIG, types.EthAddress{}) + acc := statemanager.NewStorageTrie(statemanager.POSEIDON2_CONFIG, types.EthAddress{}) acc.InsertAndProve(types.FullBytes32FromHex("0x32"), types.FullBytes32FromHex("0x12")) traceUpdate := acc.UpdateAndProve(types.FullBytes32FromHex("0x32"), types.FullBytes32FromHex("0x20")) pushUpdateRows(builder, traceUpdate) @@ -148,7 +149,7 @@ func TestAssignDelete(t *testing.T) { builder := newAssignmentBuilder(testSetting) - acc := statemanager.NewStorageTrie(statemanager.MIMC_CONFIG, types.EthAddress{}) + acc := statemanager.NewStorageTrie(statemanager.POSEIDON2_CONFIG, types.EthAddress{}) acc.InsertAndProve(types.FullBytes32FromHex("0x32"), types.FullBytes32FromHex("0x12")) traceDelete := acc.DeleteAndProve(types.FullBytes32FromHex("0x32")) pushDeletionRows(builder, traceDelete) @@ -190,7 +191,7 @@ func TestAssignReadZero(t *testing.T) { builder := newAssignmentBuilder(testSetting) - acc := statemanager.NewStorageTrie(statemanager.MIMC_CONFIG, types.EthAddress{}) + acc := statemanager.NewStorageTrie(statemanager.POSEIDON2_CONFIG, types.EthAddress{}) traceReadZero := acc.ReadZeroAndProve(types.FullBytes32FromHex("0x32")) pushReadZeroRows(builder, traceReadZero) @@ -227,7 +228,7 @@ func TestAssignReadNonZero(t *testing.T) { builder := newAssignmentBuilder(testSetting) - acc := statemanager.NewStorageTrie(statemanager.MIMC_CONFIG, types.EthAddress{}) + acc := statemanager.NewStorageTrie(statemanager.POSEIDON2_CONFIG, types.EthAddress{}) acc.InsertAndProve(types.FullBytes32FromHex("0x32"), types.FullBytes32FromHex("0x12")) traceReadNonZero := acc.ReadNonZeroAndProve(types.FullBytes32FromHex("0x32")) pushReadNonZeroRows(builder, traceReadNonZero) @@ -265,7 +266,7 @@ func assertCorrectMerkleProof(t *testing.T, builder *assignmentBuilder) { rootBytes = append(rootBytes, rootsLimbBytes[30:]...) } - assert.Equal(t, true, proof.Verify(statemanager.MIMC_CONFIG, types.AsBytes32(leaveBytes), types.AsBytes32(rootBytes))) + assert.Equal(t, true, proof.Verify(statemanager.POSEIDON2_CONFIG, types.AsBytes32(leaveBytes), types.AsBytes32(rootBytes))) } } diff --git a/prover/zkevm/prover/statemanager/mock/basic_state.go b/prover/zkevm/prover/statemanager/mock/basic_state.go index 97586f0892..0bad61cbd6 100644 --- a/prover/zkevm/prover/statemanager/mock/basic_state.go +++ b/prover/zkevm/prover/statemanager/mock/basic_state.go @@ -50,7 +50,7 @@ func (s State) InsertEOA(a types.EthAddress, nonce int64, balance *big.Int) { s[a] = &AccountState{ Nonce: nonce, Balance: balance, - MimcCodeHash: statemanager.EmptyCodeHash(statemanager.MIMC_CONFIG), + MimcCodeHash: statemanager.EmptyCodeHash(statemanager.POSEIDON2_CONFIG), KeccakCodeHash: types.AsFullBytes32(statemanager.LEGACY_KECCAK_EMPTY_CODEHASH), CodeSize: 0, } diff --git a/prover/zkevm/prover/statemanager/mock/shomei.go b/prover/zkevm/prover/statemanager/mock/shomei.go index 5048bf0cb1..53cd7eb679 100644 --- a/prover/zkevm/prover/statemanager/mock/shomei.go +++ b/prover/zkevm/prover/statemanager/mock/shomei.go @@ -55,7 +55,7 @@ const ( func InitShomeiState(state State) *statemanager.WorldState { var ( - shomeiState = statemanager.NewWorldState(statemanager.MIMC_CONFIG) + shomeiState = statemanager.NewWorldState(statemanager.POSEIDON2_CONFIG) addresses = sortedKeysOf(state) ) @@ -63,7 +63,7 @@ func InitShomeiState(state State) *statemanager.WorldState { var ( acc = state[address] - storageTrie = statemanager.NewStorageTrie(statemanager.MIMC_CONFIG, address) + storageTrie = statemanager.NewStorageTrie(statemanager.POSEIDON2_CONFIG, address) stoKeys = sortedKeysOf(acc.Storage) ) @@ -266,7 +266,7 @@ func applyAccountSegmentToShomei(shomeiState *statemanager.WorldState, accSegmen // function `applySquashedStorageLog` because it will attempt to access // the storage trie. And in this case, the storage trie does not // pre-exists - storageTrie := statemanager.NewStorageTrie(statemanager.MIMC_CONFIG, address) + storageTrie := statemanager.NewStorageTrie(statemanager.POSEIDON2_CONFIG, address) shomeiState.StorageTries.InsertNew(address, storageTrie) // The relevant storage sub-segment is always the last one. Assertedly, diff --git a/prover/zkevm/prover/statemanager/mock/state_access_log.go b/prover/zkevm/prover/statemanager/mock/state_access_log.go index f7bb03aca6..8e596122aa 100644 --- a/prover/zkevm/prover/statemanager/mock/state_access_log.go +++ b/prover/zkevm/prover/statemanager/mock/state_access_log.go @@ -301,7 +301,7 @@ func (b *StateLogBuilder) InitEoa() *StateLogBuilder { return b.InitContract( 0, types.AsFullBytes32(statemanager.LEGACY_KECCAK_EMPTY_CODEHASH), - statemanager.EmptyCodeHash(statemanager.MIMC_CONFIG), + statemanager.EmptyCodeHash(statemanager.POSEIDON2_CONFIG), ) } diff --git a/prover/zkevm/prover/statemanager/state_manager.go b/prover/zkevm/prover/statemanager/state_manager.go index 3c79210e78..9a1e78f986 100644 --- a/prover/zkevm/prover/statemanager/state_manager.go +++ b/prover/zkevm/prover/statemanager/state_manager.go @@ -133,7 +133,7 @@ func addSkipFlags(shomeiTraces *[][]statemanager.DecodedTrace) { // prepare the search key searchKey := AddressAndKey{ address: x.Bytes(), - storageKey: trace.Underlying.HKey(statemanager.MIMC_CONFIG), + storageKey: trace.Underlying.HKey(statemanager.POSEIDON2_CONFIG), } previousIndex, isFound := traceMap[searchKey] if isFound { diff --git a/prover/zkevm/prover/statemanager/statesummary/account_peek.go b/prover/zkevm/prover/statemanager/statesummary/account_peek.go index 6a741cc530..b6eec61aa4 100644 --- a/prover/zkevm/prover/statemanager/statesummary/account_peek.go +++ b/prover/zkevm/prover/statemanager/statesummary/account_peek.go @@ -20,7 +20,7 @@ import ( ) func initEmptyCodeHash() [][]byte { - emptyCodeHashBytes := statemanager.EmptyCodeHash(statemanager.MIMC_CONFIG) + emptyCodeHashBytes := statemanager.EmptyCodeHash(statemanager.POSEIDON2_CONFIG) return common.SplitBytes(emptyCodeHashBytes[:]) } From 2f8b1dd197abfb527ac5b3ca5c2789767da3ca68 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Fri, 21 Nov 2025 14:16:06 +0530 Subject: [PATCH 10/22] fix(accumulator-assign): fixed all compilation error --- .../prover/statemanager/accumulator/assign.go | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index 3dd4d691f8..4c17e1d55b 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -395,7 +395,7 @@ func (a *assignmentBuilder) pushRow( } insPathBytes := insPath.Bytes() - insPathLimbs := divideFieldBytesToFieldLimbs(insPathBytes[24:]) + insPathLimbs := divideFieldBytesToFieldLimbs(insPathBytes[:]) a.isInsertRow3 = append(a.isInsertRow3, isInsRow3) @@ -509,6 +509,7 @@ func (a *assignmentBuilder) pushRow( } func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isEmptyLeaf bool) { + var zeroBlock field.Octuplet if !isEmptyLeaf { prevFrBytes := uint64ToBytes(uint64(leafOpening.Prev)) prevFrLimbs := divideFieldBytesToFieldLimbs(prevFrBytes) @@ -519,10 +520,10 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE hKeyFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HKey[:]) hValFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HVal[:]) - intermZeroLimbs := common.BlockCompression([]field.Element{field.Zero()}, prevFrLimbs) - intermOneLimbs := common.BlockCompression(intermZeroLimbs, nextFrLimbs) - intermTwoLimbs := common.BlockCompression(intermOneLimbs, hKeyFrLimbs) - leafLimbs := common.BlockCompression(intermTwoLimbs, hValFrLimbs) + intermZeroLimbs := vortex.CompressPoseidon2(zeroBlock, vortex.Hash(prevFrLimbs)) + intermOneLimbs := vortex.CompressPoseidon2(intermZeroLimbs, vortex.Hash(nextFrLimbs)) + intermTwoLimbs := vortex.CompressPoseidon2(intermOneLimbs, vortex.Hash(hKeyFrLimbs)) + leafLimbs := vortex.CompressPoseidon2(intermTwoLimbs, vortex.Hash(hValFrLimbs)) for i := range prevFrLimbs { a.leafOpening.prev[i] = append(a.leafOpening.prev[i], prevFrLimbs[i]) @@ -544,10 +545,10 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE isEmpty := field.Zero() a.isEmptyLeaf = append(a.isEmptyLeaf, isEmpty) } else { - intermZeroLimbs := common.BlockCompression([]field.Element{field.Zero()}, []field.Element{field.Zero()}) - intermOneLimbs := common.BlockCompression(intermZeroLimbs, []field.Element{field.Zero()}) - intermTwoLimbs := common.BlockCompression(intermOneLimbs, []field.Element{field.Zero()}) - leafHashesLimbs := common.BlockCompression(intermTwoLimbs, []field.Element{field.Zero()}) + intermZeroLimbs := vortex.CompressPoseidon2(zeroBlock, zeroBlock) + intermOneLimbs := vortex.CompressPoseidon2(intermZeroLimbs, zeroBlock) + intermTwoLimbs := vortex.CompressPoseidon2(intermOneLimbs, zeroBlock) + leafHashesLimbs := vortex.CompressPoseidon2(intermTwoLimbs, zeroBlock) for i := range a.leafOpening.prev { a.leafOpening.prev[i] = append(a.leafOpening.prev[i], field.Zero()) @@ -555,11 +556,8 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE } // We insert an empty leaf in the Leaves column in this case - emptyLeafBytes32 := types.Bytes32{} - leafLimbs := divideFieldBytesToFieldLimbs(emptyLeafBytes32[:]) - for i := range a.leaves { - a.leaves[i] = append(a.leaves[i], leafLimbs[i]) + a.leaves[i] = append(a.leaves[i], zeroBlock[i]) a.leafHashes[i] = append(a.leafHashes[i], leafHashesLimbs[i]) a.leafOpening.hKey[i] = append(a.leafOpening.hKey[i], field.Zero()) @@ -1152,7 +1150,7 @@ func computeRoot(leaf types.Bytes32, proof smt.Proof) types.Bytes32 { idx := proof.Path for _, sibling := range proof.Siblings { - left, right := current, sibling + left, right := current, types.HashToBytes32(sibling) if idx&1 == 1 { left, right = right, left } @@ -1180,17 +1178,17 @@ func hashLR(conf *smt.Config, nodeL, nodeR types.Bytes32) types.Bytes32 { // divideFieldBytesToFieldLimbs divides a byte slice representing a field element into // a slice of `field.Element`s, where each `field.Element` represents a "limb" // of the original field element. This function assumes that each limb is -// 2 bytes long and that these 2 bytes are placed at the 30th and 31st -// (0-indexed) positions within a 32-byte array before being set as a +// 4 bytes long and that these 2 bytes are placed at the 62nd and 63rd +// (0-indexed) positions within a 64-byte array before being set as a // `field.Element` in canonical form. func divideFieldBytesToFieldLimbs(elementBytes []byte) []field.Element { var res []field.Element for _, limbBytes := range common.SplitBytes(elementBytes) { var elementFr field.Element - var bytesPadded [32]byte - bytesPadded[30] = limbBytes[0] - bytesPadded[31] = limbBytes[1] + var bytesPadded [64]byte + bytesPadded[62] = limbBytes[0] + bytesPadded[63] = limbBytes[1] if err := elementFr.SetBytesCanonical(bytesPadded[:]); err != nil { panic(err) From 500469fba2e162882f423b991e52ba8553ab54c8 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Fri, 21 Nov 2025 17:26:11 +0530 Subject: [PATCH 11/22] fix(accumulator-define): fix all define compiler error to run assign test --- .../statemanager/accumulator/assign_test.go | 16 +--- .../prover/statemanager/accumulator/define.go | 77 +++++++++---------- 2 files changed, 40 insertions(+), 53 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign_test.go b/prover/zkevm/prover/statemanager/accumulator/assign_test.go index 6be1797647..1996c0ae5a 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign_test.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign_test.go @@ -256,17 +256,7 @@ func TestAssignReadNonZero(t *testing.T) { func assertCorrectMerkleProof(t *testing.T, builder *assignmentBuilder) { proofs := builder.proofs for i, proof := range proofs { - var leaveBytes []byte - var rootBytes []byte - for j := range builder.leaves { - leavesLimbBytes := builder.leaves[j][i].Bytes() - leaveBytes = append(leaveBytes, leavesLimbBytes[30:]...) - - rootsLimbBytes := builder.roots[j][i].Bytes() - rootBytes = append(rootBytes, rootsLimbBytes[30:]...) - } - - assert.Equal(t, true, proof.Verify(statemanager.POSEIDON2_CONFIG, types.AsBytes32(leaveBytes), types.AsBytes32(rootBytes))) + assert.Equal(t, true, proof.Verify(statemanager.POSEIDON2_CONFIG, field.Octuplet(builder.leaves[i]), field.Octuplet(builder.roots[i]))) } } @@ -276,8 +266,8 @@ func assertCorrectMerkleProofsUsingWizard(t *testing.T, builder *assignmentBuild merkleVerification *merkle.FlatMerkleProofVerification size = utils.NextPowerOfTwo(builder.MaxNumProofs) proofcol *merkle.FlatProof - rootscol [common.NbLimbU256]ifaces.Column - leavescol [common.NbLimbU256]ifaces.Column + rootscol [common.NbElemPerHash]ifaces.Column + leavescol [common.NbElemPerHash]ifaces.Column poscol [common.NbLimbU64]ifaces.Column useNextMerkleProofCol ifaces.Column isActiveCol ifaces.Column diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index da94fb5998..a94cbc27fa 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -1,8 +1,6 @@ package accumulator import ( - "fmt" - "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/column" @@ -316,7 +314,7 @@ func (am *Module) define(comp *wizard.CompiledIOP, s Settings) { am.checkPointer() // Check leaf hashes - am.checkLeafHashes() + // am.checkLeafHashes() // Check NextFreeNode is constant through a segment unless there is an INSERT operation am.checkNextFreeNode() @@ -493,7 +491,7 @@ func (am *Module) checkConsistency() { LimbBitSize: 16, IsBigEndian: true, }, - }, true) + }) // Booleanity of IsUpdate expr1 := symbolic.Sub( @@ -741,7 +739,7 @@ func (am *Module) checkNextFreeNode() { IsBigEndian: true, }, Mask: symbolic.Mul(am.Cols.IsActiveAccumulator, symbolic.Sub(1, cols.IsFirst)), - }, false) + }) copy(am.Cols.NextFreeNodeIncremented[:], nextFreeNodeIncremented.Limbs) am.NextFreeNodeShiftProver = nextFreeNodeShiftProver @@ -814,49 +812,47 @@ func (am *Module) checkTopRootHash() { func (am *Module) checkZeroInInactive() { cols := am.Cols for i := 0; i < common.NbElemPerHash; i++ { - am.colZeroAtInactive(cols.Roots[i], fmt.Sprintf("ROOTS_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.Leaves[i], fmt.Sprintf("LEAVES_ZERO_IN_INACTIVE_%d", i)) - - am.colZeroAtInactive(cols.LeafOpenings.HKey[i], fmt.Sprintf("LEAF_OPENING_HKEY_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafOpenings.HVal[i], fmt.Sprintf("LEAF_OPENING_HVAL_ZERO_IN_INACTIVE_%d", i)) - - am.colZeroAtInactive(cols.HKey[i], fmt.Sprintf("HKEY_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.HKeyMinus[i], fmt.Sprintf("HKEY_MINUS_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.HKeyPlus[i], fmt.Sprintf("HKEY_PLUS_ZERO_IN_INACTIVE_%d", i)) + am.colZeroAtInactive(cols.Roots[i]) + am.colZeroAtInactive(cols.Leaves[i]) + + am.colZeroAtInactive(cols.LeafOpenings.HKey[i]) + am.colZeroAtInactive(cols.LeafOpenings.HVal[i]) + am.colZeroAtInactive(cols.HKey[i]) + am.colZeroAtInactive(cols.HKeyMinus[i]) + am.colZeroAtInactive(cols.HKeyPlus[i]) } for i := 0; i < len(cols.Positions); i++ { - am.colZeroAtInactive(cols.Positions[i], fmt.Sprintf("POSITIONS_ZERO_IN_INACTIVE_%d", i)) - - am.colZeroAtInactive(cols.NextFreeNode[i], fmt.Sprintf("NEXT_FREE_NODE_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.InsertionPath[i], fmt.Sprintf("INSERTION_PATH_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.AccumulatorCounter[i], fmt.Sprintf("ACCUMULATOR_COUNTER_ZERO_IN_INACTIVE_%d", i)) - - am.colZeroAtInactive(cols.LeafMinusIndex[i], fmt.Sprintf("LEAF_MINUS_INDEX_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafMinusNext[i], fmt.Sprintf("LEAF_MINUS_NEXT_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafPlusIndex[i], fmt.Sprintf("LEAF_PLUS_INDEX_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafPlusPrev[i], fmt.Sprintf("LEAF_PLUS_PREV_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafDeletedIndex[i], fmt.Sprintf("LEAF_DELETED_INDEX_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafDeletedPrev[i], fmt.Sprintf("LEAF_DELETED_PREV_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafDeletedNext[i], fmt.Sprintf("LEAF_DELETED_NEXT_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafOpenings.Prev[i], fmt.Sprintf("LEAF_OPENING_PREV_ZERO_IN_INACTIVE_%d", i)) - am.colZeroAtInactive(cols.LeafOpenings.Next[i], fmt.Sprintf("LEAF_OPENING_NEXT_ZERO_IN_INACTIVE_%d", i)) + am.colZeroAtInactive(cols.Positions[i]) + + am.colZeroAtInactive(cols.NextFreeNode[i]) + am.colZeroAtInactive(cols.InsertionPath[i]) + am.colZeroAtInactive(cols.AccumulatorCounter[i]) + am.colZeroAtInactive(cols.LeafMinusIndex[i]) + am.colZeroAtInactive(cols.LeafMinusNext[i]) + am.colZeroAtInactive(cols.LeafPlusIndex[i]) + am.colZeroAtInactive(cols.LeafPlusPrev[i]) + am.colZeroAtInactive(cols.LeafDeletedIndex[i]) + am.colZeroAtInactive(cols.LeafDeletedPrev[i]) + am.colZeroAtInactive(cols.LeafDeletedNext[i]) + am.colZeroAtInactive(cols.LeafOpenings.Prev[i]) + am.colZeroAtInactive(cols.LeafOpenings.Next[i]) } // Skipping proof as it has unequal column length with IsActive // proof is unconstrained in this module, and the consistency check is done // in the Merkle module - am.colZeroAtInactive(cols.UseNextMerkleProof, "USE_NEXT_MERKLE_PROOF_ZERO_IN_INACTIVE") - am.colZeroAtInactive(cols.IsFirst, "IS_FIRST_ZERO_IN_INACTIVE") - am.colZeroAtInactive(cols.IsInsert, "IS_INSERT_ZERO_IN_INACTIVE") - am.colZeroAtInactive(cols.IsDelete, "IS_DELETE_ZERO_IN_INACTIVE") - am.colZeroAtInactive(cols.IsUpdate, "IS_UPDATE_ZERO_IN_INACTIVE") - am.colZeroAtInactive(cols.IsReadZero, "IS_READ_ZERO_ZERO_IN_INACTIVE") - am.colZeroAtInactive(cols.IsReadNonZero, "IS_READ_NON_ZERO_ZERO_IN_INACTIVE") + am.colZeroAtInactive(cols.UseNextMerkleProof) + am.colZeroAtInactive(cols.IsFirst) + am.colZeroAtInactive(cols.IsInsert) + am.colZeroAtInactive(cols.IsDelete) + am.colZeroAtInactive(cols.IsUpdate) + am.colZeroAtInactive(cols.IsReadZero) + am.colZeroAtInactive(cols.IsReadNonZero) // Skipping Interm, Zero, and LeafHashes as two of them contain zero hashes and // Zero is a verifier column. The padding area of Interm and LeafHashes // are already constrained by the MiMC query - am.colZeroAtInactive(cols.IsEmptyLeaf, "IS_EMPTY_LEAF_ZERO_IN_INACTIVE") - am.colZeroAtInactive(cols.IsInsertRow3, "IS_INSERT_ROW3_ZERO_IN_INACTIVE") + am.colZeroAtInactive(cols.IsEmptyLeaf) + am.colZeroAtInactive(cols.IsInsertRow3) // Again skipping IntermTopRoot and TopRoot as they contain zero hashes } @@ -866,8 +862,9 @@ func (am *Module) qname(name string, args ...any) ifaces.QueryID { } // Function inserting a query that col is zero when IsActive is zero -func (am *Module) colZeroAtInactive(col ifaces.Column, name string) { +func (am *Module) colZeroAtInactive(col ifaces.Column) { // col zero at inactive area, e.g., (1-IsActiveAccumulator[i]) * col[i] = 0 - am.comp.InsertGlobal(am.Round, am.qname(name), + name_ := string(col.GetColID() + "IN_INACTIVE") + am.comp.InsertGlobal(am.Round, am.qname(name_), symbolic.Mul(symbolic.Sub(1, am.Cols.IsActiveAccumulator), col)) } From 7ca46668eb32a4117b558e31e942f0d27d3f0b91 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Fri, 21 Nov 2025 17:32:44 +0530 Subject: [PATCH 12/22] fix(accumulator-define): fix the qname compiler error --- .../prover/statemanager/accumulator/define.go | 125 +++++++++--------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index a94cbc27fa..8870698cb7 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -1,6 +1,8 @@ package accumulator import ( + "fmt" + "github.com/consensys/linea-monorepo/prover/maths/common/smartvectors" "github.com/consensys/linea-monorepo/prover/maths/field" "github.com/consensys/linea-monorepo/prover/protocol/column" @@ -382,12 +384,12 @@ func (am *Module) checkInsert() { // (Root[i+1] - Root[i+2]) * IsActiveAccumulator[i] * IsFirst[i] * IsInsert[i] = 0, The (i+1)th and (i+2)th roots are equal when there is an INSERT operation and the accumulator is active. expr1 := symbolic.Sub(column.Shift(cols.Roots[i], 1), column.Shift(cols.Roots[i], 2)) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsInsert, expr1) - am.comp.InsertGlobal(am.Round, am.qname("ROOT_EQUALITY_INSERT_1_%d", i), expr1) + am.comp.InsertGlobal(am.Round, am.qnamef("ROOT_EQUALITY_INSERT_1_%d", i), expr1) // (Root[i+3] - Root[i+4]) * IsActiveAccumulator[i] * IsFirst[i] * IsInsert[i] = 0, The (i+3)th and (i+4)th roots are equal when there is an INSERT operation and the accumulator is active. expr2 := symbolic.Sub(column.Shift(cols.Roots[i], 3), column.Shift(cols.Roots[i], 4)) expr2 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsInsert, expr2) - am.comp.InsertGlobal(am.Round, am.qname("ROOT_EQUALITY_INSERT_2_%d", i), expr2) + am.comp.InsertGlobal(am.Round, am.qnamef("ROOT_EQUALITY_INSERT_2_%d", i), expr2) } // Booleanity of IsFirst @@ -410,12 +412,12 @@ func (am *Module) checkDelete() { // (Root[i+1] - Root[i+2]) * IsActiveAccumulator[i] * IsFirst[i] * IsDelete[i] = 0, The (i+1)th and (i+2)th roots are equal when there is a DELETE operation and the accumulator is active. expr1 := symbolic.Sub(column.Shift(cols.Roots[i], 1), column.Shift(cols.Roots[i], 2)) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsDelete, expr1) - am.comp.InsertGlobal(am.Round, am.qname("ROOT_EQUALITY_DELETE_1_%d", i), expr1) + am.comp.InsertGlobal(am.Round, am.qnamef("ROOT_EQUALITY_DELETE_1_%d", i), expr1) // (Root[i+3] - Root[i+4]) * IsActiveAccumulator[i] * IsFirst[i] * IsDelete[i] = 0, The (i+3)th and (i+4)th roots are equal when there is a DELETE operation and the accumulator is active. expr2 := symbolic.Sub(column.Shift(cols.Roots[i], 3), column.Shift(cols.Roots[i], 4)) expr2 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsDelete, expr2) - am.comp.InsertGlobal(am.Round, am.qname("ROOT_EQUALITY_DELETE_2_%d", i), expr2) + am.comp.InsertGlobal(am.Round, am.qnamef("ROOT_EQUALITY_DELETE_2_%d", i), expr2) } // Booleanity of IsDelete @@ -435,7 +437,7 @@ func (am *Module) checkUpdate() { cols.IsUpdate, cols.IsFirst, symbolic.Sub(cols.HKey[i], column.Shift(cols.HKey[i], 1))) - am.comp.InsertGlobal(am.Round, am.qname("HKEY_EQUAL_FOR_UPDATE_%d", i), expr) + am.comp.InsertGlobal(am.Round, am.qnamef("HKEY_EQUAL_FOR_UPDATE_%d", i), expr) } } @@ -446,7 +448,7 @@ func (am *Module) checkReadZero() { // (Root[i] - Root[i+1]) * IsActiveAccumulator[i] * IsFirst[i] * IsReadZero[i] = 0, The ith and (i+1)th roots are equal when there is a READ-ZERO operation and the accumulator is active. expr1 := symbolic.Sub(cols.Roots[i], column.Shift(cols.Roots[i], 1)) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsReadZero, expr1) - am.comp.InsertGlobal(am.Round, am.qname("ROOT_EQUALITY_READ_ZERO_%d", i), expr1) + am.comp.InsertGlobal(am.Round, am.qnamef("ROOT_EQUALITY_READ_ZERO_%d", i), expr1) } // Booleanity of IsReadZero @@ -544,12 +546,12 @@ func (am *Module) checkEmptyLeaf() { // (Leaf[i+2] - emptyLeaf) * IsActiveAccumulator[i] * IsFirst[i] * IsInsert[i] expr1 := symbolic.Sub(column.Shift(cols.Leaves[i], 2), emptyLeaf) expr1 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsInsert, expr1) - am.comp.InsertGlobal(am.Round, am.qname("EMPTY_LEAVES_FOR_INSERT_%d", i), expr1) + am.comp.InsertGlobal(am.Round, am.qnamef("EMPTY_LEAVES_FOR_INSERT_%d", i), expr1) // (Leaf[i+3] - emptyLeaf) * IsActiveAccumulator[i] * IsFirst[i] * IsDelete[i] expr2 := symbolic.Sub(column.Shift(cols.Leaves[i], 3), emptyLeaf) expr2 = symbolic.Mul(cols.IsActiveAccumulator, cols.IsFirst, cols.IsDelete, expr2) - am.comp.InsertGlobal(am.Round, am.qname("EMPTY_LEAVES_FOR_DELETE_%d", i), expr2) + am.comp.InsertGlobal(am.Round, am.qnamef("EMPTY_LEAVES_FOR_DELETE_%d", i), expr2) } } @@ -603,7 +605,7 @@ func (am *Module) checkSandwitch() { cols.IsInsert, cols.IsFirst, symbolic.Sub(cols.HKeyMinus[i], cols.LeafOpenings.HKey[i])) - am.comp.InsertGlobal(am.Round, am.qname("HKEY_MINUS_CONSISTENCY_INSERT_%d", i), expr1) + am.comp.InsertGlobal(am.Round, am.qnamef("HKEY_MINUS_CONSISTENCY_INSERT_%d", i), expr1) // INSERT: The HKey in the inserted leaf openings (in the fourth row) is the same as HKey column i.e., // IsActiveAccumulator[i] * IsInsert[i] * IsFirst[i] * (HKey[i] - LeafOpenings.Hkey[i+3]) @@ -611,7 +613,7 @@ func (am *Module) checkSandwitch() { cols.IsInsert, cols.IsFirst, symbolic.Sub(cols.HKey[i], column.Shift(cols.LeafOpenings.HKey[i], 3))) - am.comp.InsertGlobal(am.Round, am.qname("HKEY_CONSISTENCY_INSERT_%d", i), expr2) + am.comp.InsertGlobal(am.Round, am.qnamef("HKEY_CONSISTENCY_INSERT_%d", i), expr2) // INSERT: The HKeyPlus in the plus leaf openings is the same as HKeyPlus column i.e., // IsActiveAccumulator[i] * IsInsert[i] * IsFirst[i] * (HKeyPlus[i] - LeafOpenings.Hkey[i+4]) @@ -619,7 +621,7 @@ func (am *Module) checkSandwitch() { cols.IsInsert, cols.IsFirst, symbolic.Sub(cols.HKeyPlus[i], column.Shift(cols.LeafOpenings.HKey[i], 4))) - am.comp.InsertGlobal(am.Round, am.qname("HKEY_PLUS_CONSISTENCY_INSERT_%d", i), expr3) + am.comp.InsertGlobal(am.Round, am.qnamef("HKEY_PLUS_CONSISTENCY_INSERT_%d", i), expr3) // READ-ZERO: The HKeyMinus in the minus leaf openings is the same as HKeyMinus column i.e., // IsActiveAccumulator[i] * IsReadZero[i] * IsFirst[i] * (HKeyMinus[i] - LeafOpenings.Hkey[i]) @@ -627,7 +629,7 @@ func (am *Module) checkSandwitch() { cols.IsReadZero, cols.IsFirst, symbolic.Sub(cols.HKeyMinus[i], cols.LeafOpenings.HKey[i])) - am.comp.InsertGlobal(am.Round, am.qname("HKEY_MINUS_CONSISTENCY_READ_ZERO_%d", i), expr4) + am.comp.InsertGlobal(am.Round, am.qnamef("HKEY_MINUS_CONSISTENCY_READ_ZERO_%d", i), expr4) // READ-ZERO: The HKeyPlus in the plus leaf openings is the same as HKeyPlus column i.e., // IsActiveAccumulator[i] * IsReadZero[i] * IsFirst[i] * (HKeyPlus[i] - LeafOpenings.Hkey[i+1]) @@ -635,7 +637,7 @@ func (am *Module) checkSandwitch() { cols.IsReadZero, cols.IsFirst, symbolic.Sub(cols.HKeyPlus[i], column.Shift(cols.LeafOpenings.HKey[i], 1))) - am.comp.InsertGlobal(am.Round, am.qname("HKEY_PLUS_CONSISTENCY_READ_ZERO_%d", i), expr5) + am.comp.InsertGlobal(am.Round, am.qnamef("HKEY_PLUS_CONSISTENCY_READ_ZERO_%d", i), expr5) } } @@ -644,71 +646,68 @@ func (am *Module) checkPointer() { for i := range cols.LeafPlusIndex { // Check #1 for INSERT: IsFirst[i] * IsInsert[i] * (LeafMinusNext[i] - LeafPlusIndex[i]) expr1 := symbolic.Mul(cols.IsFirst, cols.IsInsert, symbolic.Sub(cols.LeafMinusNext[i], cols.LeafPlusIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("INSERT_POINTER_1_%d", i), expr1) + am.comp.InsertGlobal(am.Round, am.qnamef("INSERT_POINTER_1_%d", i), expr1) // Check #2 for INSERT: IsFirst[i] * IsInsert[i] *(LeafPlusPrev[i] - LeafMinusIndex[i]) expr2 := symbolic.Mul(cols.IsFirst, cols.IsInsert, symbolic.Sub(cols.LeafPlusPrev[i], cols.LeafMinusIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("INSERT_POINTER_2_%d", i), expr2) - + am.comp.InsertGlobal(am.Round, am.qnamef("INSERT_POINTER_2_%d", i), expr2) // Check #1 for DELETE: IsFirst[i] * IsDelete[i] * (LeafMinusNext[i] - LeafDeletedIndex[i]) expr3 := symbolic.Mul(cols.IsFirst, cols.IsDelete, symbolic.Sub(cols.LeafMinusNext[i], cols.LeafDeletedIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("DELETE_POINTER_1_%d", i), expr3) + am.comp.InsertGlobal(am.Round, am.qnamef("DELETE_POINTER_1_%d", i), expr3) // Check #2 for DELETE: IsFirst[i] * IsDelete[i] * (LeafDeletedPrev[i] - LeafMinusIndex[i]) expr4 := symbolic.Mul(cols.IsFirst, cols.IsDelete, symbolic.Sub(cols.LeafDeletedPrev[i], cols.LeafMinusIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("DELETE_POINTER_2_%d", i), expr4) - + am.comp.InsertGlobal(am.Round, am.qnamef("DELETE_POINTER_2_%d", i), expr4) // Check #3 for DELETE: IsFirst[i] * IsDelete[i] * (LeafDeletedNext[i] - LeafPlusIndex[i]) expr5 := symbolic.Mul(cols.IsFirst, cols.IsDelete, symbolic.Sub(cols.LeafDeletedNext[i], cols.LeafPlusIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("DELETE_POINTER_3_%d", i), expr5) + am.comp.InsertGlobal(am.Round, am.qnamef("DELETE_POINTER_3_%d", i), expr5) // Check #4 for DELETE: IsFirst[i] * IsDelete[i] * (LeafPlusPrev[i] - LeafDeletedIndex[i]) expr6 := symbolic.Mul(cols.IsFirst, cols.IsDelete, symbolic.Sub(cols.LeafPlusPrev[i], cols.LeafDeletedIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("DELETE_POINTER_4_%d", i), expr6) - + am.comp.InsertGlobal(am.Round, am.qnamef("DELETE_POINTER_4_%d", i), expr6) // Check #1 for READ-ZERO: IsFirst[i] * IsReadZero[i] * (LeafMinusNext[i] - LeafPlusIndex[i]) expr7 := symbolic.Mul(cols.IsFirst, cols.IsReadZero, symbolic.Sub(cols.LeafMinusNext[i], cols.LeafPlusIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("READ_ZERO_POINTER_1_%d", i), expr7) + am.comp.InsertGlobal(am.Round, am.qnamef("READ_ZERO_POINTER_1_%d", i), expr7) // Check #2 for READ-ZERO: IsFirst[i] * IsReadZero[i] * (LeafPlusPrev[i] - LeafMinusIndex[i]) expr8 := symbolic.Mul(cols.IsFirst, cols.IsReadZero, symbolic.Sub(cols.LeafPlusPrev[i], cols.LeafMinusIndex[i])) - am.comp.InsertGlobal(am.Round, am.qname("READ_ZERO_POINTER_2_%d", i), expr8) + am.comp.InsertGlobal(am.Round, am.qnamef("READ_ZERO_POINTER_2_%d", i), expr8) } } func (am *Module) checkLeafHashes() { - cols := am.Cols + //cols := am.Cols panic("TODO: change the MiMC queries and replace them by Poseidon. Also review the [common.NbElemPerHash] loop") - for i := 0; i < common.NbElemPerHash; i++ { - - // TODO: fix MiMC query - am.comp.InsertMiMC(am.Round, am.qname("MIMC_PREV_%d", i), cols.LeafOpenings.Prev[0], cols.Zero, cols.Interm[i][0], nil) - am.comp.InsertMiMC(am.Round, am.qname("MIMC_NEXT_%d", i), cols.LeafOpenings.Next[0], cols.Interm[i][0], cols.Interm[i][1], nil) - - // TODO: fix MiMC query - am.comp.InsertMiMC(am.Round, am.qname("MIMC_HKEY"), cols.LeafOpenings.HKey[0], cols.Interm[1][0], cols.Interm[2][0], nil) - am.comp.InsertMiMC(am.Round, am.qname("MIMC_HVAL_LEAF_%d", i), cols.LeafOpenings.HVal[0], cols.Interm[2][0], cols.LeafHashes[i], nil) - - // Global: IsActive[i] * (1 - IsEmptyLeaf[i]) * (Leaves[i] - LeafHashes[i]) - expr1 := symbolic.Sub(cols.Leaves[i], cols.LeafHashes[i]) - expr2 := symbolic.Sub(symbolic.NewConstant(1), cols.IsEmptyLeaf) - expr3 := symbolic.Mul(cols.IsActiveAccumulator, expr1, expr2) - am.comp.InsertGlobal(am.Round, am.qname("LEAF_HASH_EQUALITY_%d", i), expr3) - } - // Booleaninty of IsEmptyLeaf: IsActive[i] * (IsEmptyLeaf^2[i] - IsEmptyLeaf[i]) - expr4 := symbolic.Sub(symbolic.Square(cols.IsEmptyLeaf), cols.IsEmptyLeaf) - expr4 = symbolic.Mul(expr4, cols.IsActiveAccumulator) - am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_BOOLEANITY"), expr4) - - // IsEmptyLeaf is set to true if and only if it is the third row for INSERT, or fourth row for DELETE - // i.e. IsActiveAccumulator[i] * (IsEmptyLeaf[i] - IsFirst[i-2] * IsInsert[i-2] - IsFirst[i-3] * IsDelete[i-3]) - expr5 := symbolic.Mul(cols.IsActiveAccumulator, - symbolic.Sub(cols.IsEmptyLeaf, - symbolic.Mul(column.Shift(cols.IsFirst, -2), column.Shift(cols.IsInsert, -2)), - symbolic.Mul(column.Shift(cols.IsFirst, -3), column.Shift(cols.IsDelete, -3)))) - am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_ONE_FOR_INSERT_THIRD_ROW_AND_DELETE_FOURTH_ROW"), expr5) + // for i := 0; i < common.NbElemPerHash; i++ { + + // // TODO: fix MiMC query + // am.comp.InsertMiMC(am.Round, am.qname("MIMC_PREV_%d", i), cols.LeafOpenings.Prev[0], cols.Zero, cols.Interm[i][0], nil) + // am.comp.InsertMiMC(am.Round, am.qname("MIMC_NEXT_%d", i), cols.LeafOpenings.Next[0], cols.Interm[i][0], cols.Interm[i][1], nil) + + // // TODO: fix MiMC query + // am.comp.InsertMiMC(am.Round, am.qname("MIMC_HKEY"), cols.LeafOpenings.HKey[0], cols.Interm[1][0], cols.Interm[2][0], nil) + // am.comp.InsertMiMC(am.Round, am.qname("MIMC_HVAL_LEAF_%d", i), cols.LeafOpenings.HVal[0], cols.Interm[2][0], cols.LeafHashes[i], nil) + + // // Global: IsActive[i] * (1 - IsEmptyLeaf[i]) * (Leaves[i] - LeafHashes[i]) + // expr1 := symbolic.Sub(cols.Leaves[i], cols.LeafHashes[i]) + // expr2 := symbolic.Sub(symbolic.NewConstant(1), cols.IsEmptyLeaf) + // expr3 := symbolic.Mul(cols.IsActiveAccumulator, expr1, expr2) + // am.comp.InsertGlobal(am.Round, am.qname("LEAF_HASH_EQUALITY_%d", i), expr3) + // } + // // Booleaninty of IsEmptyLeaf: IsActive[i] * (IsEmptyLeaf^2[i] - IsEmptyLeaf[i]) + // expr4 := symbolic.Sub(symbolic.Square(cols.IsEmptyLeaf), cols.IsEmptyLeaf) + // expr4 = symbolic.Mul(expr4, cols.IsActiveAccumulator) + // am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_BOOLEANITY"), expr4) + + // // IsEmptyLeaf is set to true if and only if it is the third row for INSERT, or fourth row for DELETE + // // i.e. IsActiveAccumulator[i] * (IsEmptyLeaf[i] - IsFirst[i-2] * IsInsert[i-2] - IsFirst[i-3] * IsDelete[i-3]) + // expr5 := symbolic.Mul(cols.IsActiveAccumulator, + // symbolic.Sub(cols.IsEmptyLeaf, + // symbolic.Mul(column.Shift(cols.IsFirst, -2), column.Shift(cols.IsInsert, -2)), + // symbolic.Mul(column.Shift(cols.IsFirst, -3), column.Shift(cols.IsDelete, -3)))) + // am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_ONE_FOR_INSERT_THIRD_ROW_AND_DELETE_FOURTH_ROW"), expr5) } func (am *Module) checkNextFreeNode() { @@ -749,7 +748,7 @@ func (am *Module) checkNextFreeNode() { for i := 0; i < len(am.Cols.NextFreeNodeIncremented)-1; i++ { am.comp.InsertGlobal( am.Round, - am.qname("%v_RESULT_SUB_ONE_%d", ACCUMULATOR_NEXT_FREE_NODE_SHIFT_NAME, i), + am.qnamef("%v_RESULT_SUB_ONE_%d", ACCUMULATOR_NEXT_FREE_NODE_SHIFT_NAME, i), symbolic.Mul( am.Cols.IsActiveAccumulator, symbolic.Sub(1, cols.IsFirst), @@ -762,7 +761,7 @@ func (am *Module) checkNextFreeNode() { // Last 1 limb (least significant) has to be 1 am.comp.InsertGlobal( am.Round, - am.qname( + am.qnamef( "%v_RESULT_SUB_ONE_%d", ACCUMULATOR_NEXT_FREE_NODE_SHIFT_NAME, len(am.Cols.NextFreeNodeIncremented)-1, @@ -778,7 +777,7 @@ func (am *Module) checkNextFreeNode() { for i := 0; i < len(am.Cols.NextFreeNodeIncremented); i++ { am.comp.InsertGlobal( am.Round, - am.qname("%v_RESULT_%d", ACCUMULATOR_NEXT_FREE_NODE_SHIFT_NAME, i), + am.qnamef("%v_RESULT_%d", ACCUMULATOR_NEXT_FREE_NODE_SHIFT_NAME, i), symbolic.Mul( am.Cols.IsActiveAccumulator, symbolic.Sub(1, cols.IsFirst), @@ -856,9 +855,17 @@ func (am *Module) checkZeroInInactive() { // Again skipping IntermTopRoot and TopRoot as they contain zero hashes } -// Function returning a query name -func (am *Module) qname(name string, args ...any) ifaces.QueryID { - return ifaces.QueryIDf("%v_%v", am.Name, am.comp.SelfRecursionCount) + "_" + ifaces.QueryIDf(name, args...) +// Function returning a query name for already-formed names (no printf) +func (am *Module) qname(name string) ifaces.QueryID { + return ifaces.QueryIDf("%v_%v_%s", am.Name, am.comp.SelfRecursionCount, name) +} + +// Function returning a query name using printf-style formatting. +// Use this when the first arg is a format literal. +// nolint:printf +func (am *Module) qnamef(format string, args ...any) ifaces.QueryID { + formatted := fmt.Sprintf(format, args...) + return ifaces.QueryIDf("%v_%v_%s", am.Name, am.comp.SelfRecursionCount, formatted) } // Function inserting a query that col is zero when IsActive is zero From 43fdaa5c49f89cff724d714b0549e44cc24270d8 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Mon, 24 Nov 2025 17:31:33 +0530 Subject: [PATCH 13/22] fix: fix the poseidon encoding for u64 and fieldhash --- prover/zkevm/prover/common/flatten_column.go | 4 + prover/zkevm/prover/common/split.go | 10 +- .../prover/statemanager/accumulator/assign.go | 178 +++++++++++------- 3 files changed, 118 insertions(+), 74 deletions(-) diff --git a/prover/zkevm/prover/common/flatten_column.go b/prover/zkevm/prover/common/flatten_column.go index 52008d9617..f10c5f358f 100644 --- a/prover/zkevm/prover/common/flatten_column.go +++ b/prover/zkevm/prover/common/flatten_column.go @@ -27,6 +27,10 @@ const ( NbElemPerHash = 8 // NbElemForHasingU64 represents the number of field elements per 64-bit integers. NbElemForHasingU64 = 16 + // NbBytesForEncodingU64 represents the number of bytes for encoding a 64-bit integer. + NbBytesForEncodingU64 = 64 + // NbBytesForEncodingFieldHash represents the number of bytes for encoding a field hash. + NbBytesForEncodingFieldHash = 32 ) // FlattenColumn flattens multiple limb columns and an accompanying mask into single columns, diff --git a/prover/zkevm/prover/common/split.go b/prover/zkevm/prover/common/split.go index 301b28e070..87506d2467 100644 --- a/prover/zkevm/prover/common/split.go +++ b/prover/zkevm/prover/common/split.go @@ -6,14 +6,18 @@ import "encoding/binary" const LimbBytes = 2 // SplitBytes splits the input slice into subarrays of the provided size. -func SplitBytes(input []byte) [][]byte { +func SplitBytes(input []byte, limbBytes ...int) [][]byte { + limbSize := LimbBytes + if len(limbBytes) > 0 { + limbSize = limbBytes[0] + } if len(input) == 0 { return [][]byte{} } var result [][]byte - for i := 0; i < len(input); i += LimbBytes { - end := i + LimbBytes + for i := 0; i < len(input); i += limbSize { + end := i + limbSize if end > len(input) { end = len(input) } diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index 4c17e1d55b..1b601dab14 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -27,6 +27,15 @@ type leafOpenings struct { hVal [common.NbElemPerHash][]field.Element } +type hashType int + +const ( + // denote the hashtype for hashing u64 values + hashU64 hashType = iota + // denote the hashtype for hashing field hashes + hashFieldElements +) + // assignmentBuilder is used to build the assignment of the [Module] module // and is implemented like a writer. type assignmentBuilder struct { @@ -376,38 +385,33 @@ func (a *assignmentBuilder) pushRow( ) { // Populates leaves, leafHashes, and isEmptyLeaf from leafOpening by Posseidon2 block compression a.computeLeaf(leafOpening, isEmptyLeaf) - var rootFr field.Element - if err := rootFr.SetBytesCanonical(root[:]); err != nil { - panic(err) - } - rootFrLimbs := divideFieldBytesToFieldLimbs(root[:]) + rootFrLimbs := divideFieldBytesToFieldLimbs(root[:], hashFieldElements) for i, limb := range rootFrLimbs { a.roots[i] = append(a.roots[i], limb) } // Insert Row 3 operations isInsRow3 := field.Zero() - insPath := field.Zero() + insPath := uint64(0) if isInsertRow3 { isInsRow3 = field.One() - insPath = field.NewElement(uint64(proof.Path)) + insPath = uint64(proof.Path) } - insPathBytes := insPath.Bytes() - insPathLimbs := divideFieldBytesToFieldLimbs(insPathBytes[:]) - + insPathBytes := uint64To64Bytes(insPath) + insPathLimbs := divideFieldBytesToFieldLimbs(insPathBytes[:], hashU64) a.isInsertRow3 = append(a.isInsertRow3, isInsRow3) // accumulatorCounter will increment when a new row is pushed - accumulatorCounterBytes := uint64ToBytes(uint64(len(a.accumulatorCounter[0]))) - accumulatorCounterLimbs := divideFieldBytesToFieldLimbs(accumulatorCounterBytes) + accumulatorCounterBytes := uint64To64Bytes(uint64(len(a.accumulatorCounter[0]))) + accumulatorCounterLimbs := divideFieldBytesToFieldLimbs(accumulatorCounterBytes, hashU64) - posBytes := uint64ToBytes(uint64(proof.Path)) - posLimbs := divideFieldBytesToFieldLimbs(posBytes) + posBytes := uint64To64Bytes(uint64(proof.Path)) + posLimbs := divideFieldBytesToFieldLimbs(posBytes, hashU64) - nextFreeNodeFrBytes := uint64ToBytes(uint64(nextFreeNode)) - nextFreeNodeFrLimbs := divideFieldBytesToFieldLimbs(nextFreeNodeFrBytes) + nextFreeNodeFrBytes := uint64To64Bytes(uint64(nextFreeNode)) + nextFreeNodeFrLimbs := divideFieldBytesToFieldLimbs(nextFreeNodeFrBytes, hashU64) for i, posLimb := range posLimbs { a.positions[i] = append(a.positions[i], posLimb) @@ -511,14 +515,14 @@ func (a *assignmentBuilder) pushRow( func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isEmptyLeaf bool) { var zeroBlock field.Octuplet if !isEmptyLeaf { - prevFrBytes := uint64ToBytes(uint64(leafOpening.Prev)) - prevFrLimbs := divideFieldBytesToFieldLimbs(prevFrBytes) + prevFrBytes := uint64To64Bytes(uint64(leafOpening.Prev)) + prevFrLimbs := divideFieldBytesToFieldLimbs(prevFrBytes, hashU64) - nextFrBytes := uint64ToBytes(uint64(leafOpening.Next)) - nextFrLimbs := divideFieldBytesToFieldLimbs(nextFrBytes) + nextFrBytes := uint64To64Bytes(uint64(leafOpening.Next)) + nextFrLimbs := divideFieldBytesToFieldLimbs(nextFrBytes, hashU64) - hKeyFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HKey[:]) - hValFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HVal[:]) + hKeyFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HKey[:], hashFieldElements) + hValFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HVal[:], hashFieldElements) intermZeroLimbs := vortex.CompressPoseidon2(zeroBlock, vortex.Hash(prevFrLimbs)) intermOneLimbs := vortex.CompressPoseidon2(intermZeroLimbs, vortex.Hash(nextFrLimbs)) @@ -663,9 +667,9 @@ func pushInsertionRows[K, V io.WriterTo]( // Sandwitch assignment for row 1 hKey := hash(trace.Key) - hKeyFrLimbs := divideFieldBytesToFieldLimbs(hKey[:]) - hKeyMinusFrLimbs := divideFieldBytesToFieldLimbs(trace.OldOpenMinus.HKey[:]) - hKeyPlusFrLimbs := divideFieldBytesToFieldLimbs(trace.OldOpenPlus.HKey[:]) + hKeyFrLimbs := divideFieldBytesToFieldLimbs(hKey[:], hashFieldElements) + hKeyMinusFrLimbs := divideFieldBytesToFieldLimbs(trace.OldOpenMinus.HKey[:], hashFieldElements) + hKeyPlusFrLimbs := divideFieldBytesToFieldLimbs(trace.OldOpenPlus.HKey[:], hashFieldElements) for i := range a.hKey { a.hKey[i] = append(a.hKey[i], hKeyFrLimbs[i]) @@ -674,17 +678,17 @@ func pushInsertionRows[K, V io.WriterTo]( } // Pointer assignment for row 1 - leafMinusNextBytes := uint64ToBytes(uint64(trace.OldOpenMinus.Next)) - leafMinusNextLimbs := divideFieldBytesToFieldLimbs(leafMinusNextBytes) + leafMinusNextBytes := uint64To64Bytes(uint64(trace.OldOpenMinus.Next)) + leafMinusNextLimbs := divideFieldBytesToFieldLimbs(leafMinusNextBytes, hashU64) - leafMinusIndexBytes := uint64ToBytes(uint64(trace.ProofMinus.Path)) - leafMinusIndexLimbs := divideFieldBytesToFieldLimbs(leafMinusIndexBytes) + leafMinusIndexBytes := uint64To64Bytes(uint64(trace.ProofMinus.Path)) + leafMinusIndexLimbs := divideFieldBytesToFieldLimbs(leafMinusIndexBytes, hashU64) - leafPlusIndexBytes := uint64ToBytes(uint64(trace.ProofPlus.Path)) - leafPlusIndexLimbs := divideFieldBytesToFieldLimbs(leafPlusIndexBytes) + leafPlusIndexBytes := uint64To64Bytes(uint64(trace.ProofPlus.Path)) + leafPlusIndexLimbs := divideFieldBytesToFieldLimbs(leafPlusIndexBytes, hashU64) - leafPlusPrevBytes := uint64ToBytes(uint64(trace.OldOpenPlus.Prev)) - leafPlusPrevLimbs := divideFieldBytesToFieldLimbs(leafPlusPrevBytes) + leafPlusPrevBytes := uint64To64Bytes(uint64(trace.OldOpenPlus.Prev)) + leafPlusPrevLimbs := divideFieldBytesToFieldLimbs(leafPlusPrevBytes, hashU64) for i := range leafMinusNextLimbs { a.leafMinusNext[i] = append(a.leafMinusNext[i], leafMinusNextLimbs[i]) @@ -852,26 +856,26 @@ func pushDeletionRows[K, V io.WriterTo]( ) // Pointer assignment for row 1 - leafMinusNextBytes := uint64ToBytes(uint64(trace.OldOpenMinus.Next)) - leafMinusNextLimbs := divideFieldBytesToFieldLimbs(leafMinusNextBytes) + leafMinusNextBytes := uint64To64Bytes(uint64(trace.OldOpenMinus.Next)) + leafMinusNextLimbs := divideFieldBytesToFieldLimbs(leafMinusNextBytes, hashU64) - leafMinusIndexBytes := uint64ToBytes(uint64(trace.ProofMinus.Path)) - leafMinusIndexLimbs := divideFieldBytesToFieldLimbs(leafMinusIndexBytes) + leafMinusIndexBytes := uint64To64Bytes(uint64(trace.ProofMinus.Path)) + leafMinusIndexLimbs := divideFieldBytesToFieldLimbs(leafMinusIndexBytes, hashU64) - leafPlusIndexBytes := uint64ToBytes(uint64(trace.ProofPlus.Path)) - leafPlusIndexLimbs := divideFieldBytesToFieldLimbs(leafPlusIndexBytes) + leafPlusIndexBytes := uint64To64Bytes(uint64(trace.ProofPlus.Path)) + leafPlusIndexLimbs := divideFieldBytesToFieldLimbs(leafPlusIndexBytes, hashU64) - leafPlusPrevBytes := uint64ToBytes(uint64(trace.OldOpenPlus.Prev)) - leafPlusPrevLimbs := divideFieldBytesToFieldLimbs(leafPlusPrevBytes) + leafPlusPrevBytes := uint64To64Bytes(uint64(trace.OldOpenPlus.Prev)) + leafPlusPrevLimbs := divideFieldBytesToFieldLimbs(leafPlusPrevBytes, hashU64) - leafDeletedIndexBytes := uint64ToBytes(uint64(trace.ProofDeleted.Path)) - leafDeletedIndexLimbs := divideFieldBytesToFieldLimbs(leafDeletedIndexBytes) + leafDeletedIndexBytes := uint64To64Bytes(uint64(trace.ProofDeleted.Path)) + leafDeletedIndexLimbs := divideFieldBytesToFieldLimbs(leafDeletedIndexBytes, hashU64) - leafDeletedNextBytes := uint64ToBytes(uint64(trace.DeletedOpen.Next)) - leafDeletedNextLimbs := divideFieldBytesToFieldLimbs(leafDeletedNextBytes) + leafDeletedNextBytes := uint64To64Bytes(uint64(trace.DeletedOpen.Next)) + leafDeletedNextLimbs := divideFieldBytesToFieldLimbs(leafDeletedNextBytes, hashU64) - leafDeletedPrevBytes := uint64ToBytes(uint64(trace.DeletedOpen.Prev)) - leafDeletedPrevLimbs := divideFieldBytesToFieldLimbs(leafDeletedPrevBytes) + leafDeletedPrevBytes := uint64To64Bytes(uint64(trace.DeletedOpen.Prev)) + leafDeletedPrevLimbs := divideFieldBytesToFieldLimbs(leafDeletedPrevBytes, hashU64) for i := range leafMinusNextLimbs { a.leafMinusNext[i] = append(a.leafMinusNext[i], leafMinusNextLimbs[i]) @@ -1030,9 +1034,9 @@ func pushReadZeroRows[K, V io.WriterTo]( // Sandwitch assignment for row 1 hKey := hash(trace.Key) - hKeyFrLimbs := divideFieldBytesToFieldLimbs(hKey[:]) - hKeyMinusFrLimbs := divideFieldBytesToFieldLimbs(trace.OpeningMinus.HKey[:]) - hKeyPlusFrLimbs := divideFieldBytesToFieldLimbs(trace.OpeningPlus.HKey[:]) + hKeyFrLimbs := divideFieldBytesToFieldLimbs(hKey[:], hashFieldElements) + hKeyMinusFrLimbs := divideFieldBytesToFieldLimbs(trace.OpeningMinus.HKey[:], hashFieldElements) + hKeyPlusFrLimbs := divideFieldBytesToFieldLimbs(trace.OpeningPlus.HKey[:], hashFieldElements) for i := range a.hKey { a.hKey[i] = append(a.hKey[i], hKeyFrLimbs[i]) a.hKeyMinus[i] = append(a.hKeyMinus[i], hKeyMinusFrLimbs[i]) @@ -1041,17 +1045,17 @@ func pushReadZeroRows[K, V io.WriterTo]( // Pointer assignment for row1 - leafMinusNextBytes := uint64ToBytes(uint64(trace.OpeningMinus.Next)) - leafMinusNextLimbs := divideFieldBytesToFieldLimbs(leafMinusNextBytes) + leafMinusNextBytes := uint64To64Bytes(uint64(trace.OpeningMinus.Next)) + leafMinusNextLimbs := divideFieldBytesToFieldLimbs(leafMinusNextBytes, hashU64) - leafMinusIndexBytes := uint64ToBytes(uint64(trace.ProofMinus.Path)) - leafMinusIndexLimbs := divideFieldBytesToFieldLimbs(leafMinusIndexBytes) + leafMinusIndexBytes := uint64To64Bytes(uint64(trace.ProofMinus.Path)) + leafMinusIndexLimbs := divideFieldBytesToFieldLimbs(leafMinusIndexBytes, hashU64) - leafPlusIndexBytes := uint64ToBytes(uint64(trace.ProofPlus.Path)) - leafPlusIndexLimbs := divideFieldBytesToFieldLimbs(leafPlusIndexBytes) + leafPlusIndexBytes := uint64To64Bytes(uint64(trace.ProofPlus.Path)) + leafPlusIndexLimbs := divideFieldBytesToFieldLimbs(leafPlusIndexBytes, hashU64) - leafPlusPrevBytes := uint64ToBytes(uint64(trace.OpeningPlus.Prev)) - leafPlusPrevLimbs := divideFieldBytesToFieldLimbs(leafPlusPrevBytes) + leafPlusPrevBytes := uint64To64Bytes(uint64(trace.OpeningPlus.Prev)) + leafPlusPrevLimbs := divideFieldBytesToFieldLimbs(leafPlusPrevBytes, hashU64) for i := range leafMinusNextLimbs { a.leafMinusNext[i] = append(a.leafMinusNext[i], leafMinusNextLimbs[i]) @@ -1178,32 +1182,64 @@ func hashLR(conf *smt.Config, nodeL, nodeR types.Bytes32) types.Bytes32 { // divideFieldBytesToFieldLimbs divides a byte slice representing a field element into // a slice of `field.Element`s, where each `field.Element` represents a "limb" // of the original field element. This function assumes that each limb is -// 4 bytes long and that these 2 bytes are placed at the 62nd and 63rd -// (0-indexed) positions within a 64-byte array before being set as a -// `field.Element` in canonical form. -func divideFieldBytesToFieldLimbs(elementBytes []byte) []field.Element { +// 4 bytes long before being set as a `field.Element` in canonical form. +func divideFieldBytesToFieldLimbs(elementBytes []byte, toHash hashType) []field.Element { + // Sanity check on input length + switch toHash { + case hashU64: + if len(elementBytes) != common.NbBytesForEncodingU64 { + panic("elementBytes length for u64 is not 64") + } + case hashFieldElements: + if len(elementBytes) != common.NbBytesForEncodingFieldHash { + panic("elementBytes length for field hash is not 32") + } + default: + panic("unsupported hashType") + } + // declare the result slice of field elements var res []field.Element - for _, limbBytes := range common.SplitBytes(elementBytes) { + switch toHash { + case hashU64: + res = make([]field.Element, 0, common.NbElemForHasingU64) + case hashFieldElements: + res = make([]field.Element, 0, common.NbElemPerHash) + default: + panic("unsupported hashType") + } + // each field element is a chunk of 4 bytes + for _, limbBytes := range common.SplitBytes(elementBytes, 4) { var elementFr field.Element - var bytesPadded [64]byte - bytesPadded[62] = limbBytes[0] - bytesPadded[63] = limbBytes[1] - - if err := elementFr.SetBytesCanonical(bytesPadded[:]); err != nil { + if err := elementFr.SetBytesCanonical(limbBytes[:]); err != nil { panic(err) } res = append(res, elementFr) } + // Sanity check on output length + switch toHash { + case hashU64: + if len(res) != common.NbElemForHasingU64 { + panic("res length is not equal to NbElemForHasingU64") + } + case hashFieldElements: + if len(res) != common.NbElemPerHash { + panic("res length is not equal to NbElemPerHash") + } + default: + panic("unsupported hashType") + } return res } -// uint64ToBytes converts a `uint64` number into an 8-byte slice assuming +// uint64To64Bytes converts a `uint64` number into an 8-byte slice assuming // Big-Endian byte order. -func uint64ToBytes(num uint64) []byte { +func uint64To64Bytes(num uint64) []byte { bytes := make([]byte, 8) binary.BigEndian.PutUint64(bytes, num) - return bytes + // We copy every 2 bytes from tmp into res, left padded by 2 zero-bytes. + res := types.LeftPadded48Zeros(types.LeftPadded(bytes[:])) + return res } From b29f89c1ad86c160b420fe12cceaf9ffc58ce4ac Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Mon, 24 Nov 2025 17:49:41 +0530 Subject: [PATCH 14/22] fix: change pos from 4 to 16 limbs as it involves hashing --- .../dedicated/merkle/flat_proof_test.go | 28 +++++++++++++------ prover/protocol/dedicated/merkle/merkle.go | 2 +- .../prover/statemanager/accumulator/assign.go | 22 +++++++-------- .../statemanager/accumulator/assign_test.go | 4 +-- .../prover/statemanager/accumulator/define.go | 24 ++++++++-------- 5 files changed, 46 insertions(+), 34 deletions(-) diff --git a/prover/protocol/dedicated/merkle/flat_proof_test.go b/prover/protocol/dedicated/merkle/flat_proof_test.go index 9341f5b784..f0da89f9a2 100644 --- a/prover/protocol/dedicated/merkle/flat_proof_test.go +++ b/prover/protocol/dedicated/merkle/flat_proof_test.go @@ -208,7 +208,7 @@ func (mt *merkleTestBuilder) pushRow(row merkleTestBuilderRow) { mt.roots[i] = append(mt.roots[i], rootOct[i]) } // compute position limbs - limbs := uint64To16BitLimbs(uint64(row.pos)) + limbs := uint64To4BitLimbs(uint64(row.pos)) for i := 0; i < limbPerU64; i++ { mt.pos[i] = append(mt.pos[i], field.NewElement(limbs[i])) @@ -217,13 +217,25 @@ func (mt *merkleTestBuilder) pushRow(row merkleTestBuilderRow) { mt.isActive = append(mt.isActive, field.One()) } -// uint64To16BitLimbs splits v into four 16-bit limbs (big-endian order): +// uint64To4BitLimbs splits v into four 16-bit limbs (big-endian order): // limbs[3] = low 16 bits, limbs[0] = highest 16 bits. -func uint64To16BitLimbs(v uint64) [4]uint64 { - var limbs [4]uint64 - limbs[3] = uint64(v & 0xFFFF) - limbs[2] = uint64((v >> 16) & 0xFFFF) - limbs[1] = uint64((v >> 32) & 0xFFFF) - limbs[0] = uint64((v >> 48) & 0xFFFF) +func uint64To4BitLimbs(v uint64) [16]uint64 { + var limbs [16]uint64 + limbs[15] = uint64(v & 0xF) + limbs[14] = uint64((v >> 4) & 0xF) + limbs[13] = uint64((v >> 8) & 0xF) + limbs[12] = uint64((v >> 12) & 0xF) + limbs[11] = uint64((v >> 16) & 0xF) + limbs[10] = uint64((v >> 20) & 0xF) + limbs[9] = uint64((v >> 24) & 0xF) + limbs[8] = uint64((v >> 28) & 0xF) + limbs[7] = uint64((v >> 32) & 0xF) + limbs[6] = uint64((v >> 36) & 0xF) + limbs[5] = uint64((v >> 40) & 0xF) + limbs[4] = uint64((v >> 44) & 0xF) + limbs[3] = uint64((v >> 48) & 0xF) + limbs[2] = uint64((v >> 52) & 0xF) + limbs[1] = uint64((v >> 56) & 0xF) + limbs[0] = uint64((v >> 60) & 0xF) return limbs } diff --git a/prover/protocol/dedicated/merkle/merkle.go b/prover/protocol/dedicated/merkle/merkle.go index 5725d058b6..a53bec45cc 100644 --- a/prover/protocol/dedicated/merkle/merkle.go +++ b/prover/protocol/dedicated/merkle/merkle.go @@ -14,7 +14,7 @@ import ( const ( width = 16 blockSize = 8 - limbPerU64 = 4 + limbPerU64 = 16 ) // Wizard gadget allowing to verify a Merkle proof diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index 1b601dab14..05e7d7e607 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -49,7 +49,7 @@ type assignmentBuilder struct { // [Accumulator.Cols.Leaves] column. leaves [common.NbElemPerHash][]field.Element // positions stores the positions of the leaves in the merkle tree for which we give the Merkle proof. This corresponds to the [Accumulator.Cols.Positions] column. - positions [common.NbLimbU64][]field.Element + positions [common.NbElemForHasingU64][]field.Element // roots stores the roots of the merkle tree. This corresponds // to the [Accumulator.Cols.Roots] column. roots [common.NbElemPerHash][]field.Element @@ -63,7 +63,7 @@ type assignmentBuilder struct { isActive []field.Element // accumulatorCounter counts the number of rows in the accumulator. It is used to check the // sequentiality of leaves and roots in accumulator and the merkle module - accumulatorCounter [common.NbLimbU64][]field.Element + accumulatorCounter [common.NbElemForHasingU64][]field.Element // isFirst is one at the first row of any operation. This corresponds to the [Accumulator.IsFirst] column isFirst []field.Element // isInsert is one when we have an INSERT operation. It is @@ -89,19 +89,19 @@ type assignmentBuilder struct { hKeyPlus [common.NbElemPerHash][]field.Element // Pointer check columns // leafMinusIndex is the index of the minus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafMinusIndex] - leafMinusIndex [common.NbLimbU64][]field.Element + leafMinusIndex [common.NbElemForHasingU64][]field.Element // leafMinusNext is the index of the Next leaf of the minus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafMinusNext] - leafMinusNext [common.NbLimbU64][]field.Element + leafMinusNext [common.NbElemForHasingU64][]field.Element // leafMinusNext is the index of the plus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafPlusIndex] - leafPlusIndex [common.NbLimbU64][]field.Element + leafPlusIndex [common.NbElemForHasingU64][]field.Element // leafPlusPrev is the index of the Previous leaf of the plus leaf for INSERT, READZERO, and DELETE. This corresponds to the [Accumulator.Column.LeafPlusPrev] - leafPlusPrev [common.NbLimbU64][]field.Element + leafPlusPrev [common.NbElemForHasingU64][]field.Element // leafDeletedIndex is the index of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedIndex] - leafDeletedIndex [common.NbLimbU64][]field.Element + leafDeletedIndex [common.NbElemForHasingU64][]field.Element // leafDeletedPrev is the index of the Previous leaf of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedPrev] - leafDeletedPrev [common.NbLimbU64][]field.Element + leafDeletedPrev [common.NbElemForHasingU64][]field.Element // leafDeletedNext is the index of the Previous leaf of the Deleted leaf for DELETE. This corresponds to the [Accumulator.Column.LeafDeletedNext] - leafDeletedNext [common.NbLimbU64][]field.Element + leafDeletedNext [common.NbElemForHasingU64][]field.Element // leafOpening is a tuple of four columns containing // Prev, Next, HKey, HVal of a leaf. This corresponds to the [Accumulator.Column.LeafOpening] leafOpening leafOpenings @@ -112,10 +112,10 @@ type assignmentBuilder struct { // isEmptyLeaf is one when Leaves contains empty leaf and does not match with LeafHash isEmptyLeaf []field.Element // nextFreeNode contains the nextFreeNode for each row of every operation - nextFreeNode [common.NbLimbU64][]field.Element + nextFreeNode [common.NbElemForHasingU64][]field.Element // insertionPath is the path of a newly inserted leaf when INSERT happens, // it is zero otherwise - insertionPath [common.NbLimbU64][]field.Element + insertionPath [common.NbElemForHasingU64][]field.Element // isInsertRow3 is one for row 3 of INSERT operation isInsertRow3 []field.Element // intermTopRoot contains the intermediate MiMC state hash diff --git a/prover/zkevm/prover/statemanager/accumulator/assign_test.go b/prover/zkevm/prover/statemanager/accumulator/assign_test.go index 1996c0ae5a..05116db0be 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign_test.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign_test.go @@ -268,7 +268,7 @@ func assertCorrectMerkleProofsUsingWizard(t *testing.T, builder *assignmentBuild proofcol *merkle.FlatProof rootscol [common.NbElemPerHash]ifaces.Column leavescol [common.NbElemPerHash]ifaces.Column - poscol [common.NbLimbU64]ifaces.Column + poscol [common.NbElemForHasingU64]ifaces.Column useNextMerkleProofCol ifaces.Column isActiveCol ifaces.Column ) @@ -281,7 +281,7 @@ func assertCorrectMerkleProofsUsingWizard(t *testing.T, builder *assignmentBuild leavescol[i] = b.RegisterCommit(ifaces.ColIDf("LEAVES_%d", i), size) } - for i := 0; i < common.NbLimbU64; i++ { + for i := 0; i < common.NbElemForHasingU64; i++ { poscol[i] = b.RegisterCommit(ifaces.ColIDf("POS_%d", i), size) } diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index 8870698cb7..7bbaf448f6 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -120,14 +120,14 @@ type Module struct { Cols struct { Leaves [common.NbElemPerHash]ifaces.Column Roots [common.NbElemPerHash]ifaces.Column - Positions [common.NbLimbU64]ifaces.Column + Positions [common.NbElemForHasingU64]ifaces.Column Proofs *merkle.FlatProof // Column to verify reuse of Merkle proofs in INSERT, DELETE, and UPDATE operations UseNextMerkleProof ifaces.Column // Column denoting the active area of the accumulator module IsActiveAccumulator ifaces.Column // Columns to check sequentiality of the accumulator module with Merkle module - AccumulatorCounter [common.NbLimbU64]ifaces.Column + AccumulatorCounter [common.NbElemForHasingU64]ifaces.Column // Column to verify the two equalities of intermediateRoot1 and intermediateRoot3, and empty // leafs for INSERT and DELETE operation and one equality of root in IsReadZero operation IsFirst ifaces.Column @@ -156,19 +156,19 @@ type Module struct { // Columns for the pointer check // Columns storing the index of the minus leaf - LeafMinusIndex [common.NbLimbU64]ifaces.Column + LeafMinusIndex [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the next leaf of the minus leaf - LeafMinusNext [common.NbLimbU64]ifaces.Column + LeafMinusNext [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the plus leaf - LeafPlusIndex [common.NbLimbU64]ifaces.Column + LeafPlusIndex [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the previous leaf of the plus leaf - LeafPlusPrev [common.NbLimbU64]ifaces.Column + LeafPlusPrev [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the deleted leaf - LeafDeletedIndex [common.NbLimbU64]ifaces.Column + LeafDeletedIndex [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the previous leaf of the deleted leaf - LeafDeletedPrev [common.NbLimbU64]ifaces.Column + LeafDeletedPrev [common.NbElemForHasingU64]ifaces.Column // Columns storing the index of the next leaf of the deleted leaf - LeafDeletedNext [common.NbLimbU64]ifaces.Column + LeafDeletedNext [common.NbElemForHasingU64]ifaces.Column // Columns for leaf hashing check // LeafOpening contains four columns corresponding to HKey, HVal, Prev, and Next @@ -184,12 +184,12 @@ type Module struct { // Columns to check NextFreeNode consistency // NextFreeNode stores the nextFreeNode for each row of every operation - NextFreeNode [common.NbLimbU64]ifaces.Column + NextFreeNode [common.NbElemForHasingU64]ifaces.Column // NextFreeNodeIncremented stores a value that indicates how much NextFreeNode[i] is increased // relative to the NextFreeNode[i-1] - NextFreeNodeIncremented [common.NbLimbU64]ifaces.Column + NextFreeNodeIncremented [common.NbElemForHasingU64]ifaces.Column // InsertionPath stores the index of the newly inserted leaf by INSERT - InsertionPath [common.NbLimbU64]ifaces.Column + InsertionPath [common.NbElemForHasingU64]ifaces.Column // IsInsertRow3 is one for row 3 of INSERT operation IsInsertRow3 ifaces.Column From 2261b087d82899a494090cc0422ebd1db68e7ca9 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Mon, 24 Nov 2025 19:10:47 +0530 Subject: [PATCH 15/22] fix: debug wip --- .../prover/statemanager/accumulator/assign.go | 7 ++- .../statemanager/accumulator/assign_test.go | 46 +++++++++---------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index 05e7d7e607..539dfa411d 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -524,8 +524,11 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE hKeyFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HKey[:], hashFieldElements) hValFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HVal[:], hashFieldElements) - intermZeroLimbs := vortex.CompressPoseidon2(zeroBlock, vortex.Hash(prevFrLimbs)) - intermOneLimbs := vortex.CompressPoseidon2(intermZeroLimbs, vortex.Hash(nextFrLimbs)) + // As prevFrLimbs, nextFrLimbs are of 16 limbs, we hash them in two steps + intermZeroLimbs_ := vortex.CompressPoseidon2(zeroBlock, vortex.Hash(prevFrLimbs[0:8])) + intermZeroLimbs := vortex.CompressPoseidon2(intermZeroLimbs_, vortex.Hash(prevFrLimbs[8:16])) + intermOneLimbs_ := vortex.CompressPoseidon2(intermZeroLimbs, vortex.Hash(nextFrLimbs[0:8])) + intermOneLimbs := vortex.CompressPoseidon2(intermOneLimbs_, vortex.Hash(nextFrLimbs[8:16])) intermTwoLimbs := vortex.CompressPoseidon2(intermOneLimbs, vortex.Hash(hKeyFrLimbs)) leafLimbs := vortex.CompressPoseidon2(intermTwoLimbs, vortex.Hash(hValFrLimbs)) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign_test.go b/prover/zkevm/prover/statemanager/accumulator/assign_test.go index 05116db0be..08adf36bc1 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign_test.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign_test.go @@ -72,11 +72,11 @@ func TestAssignInsert(t *testing.T) { pushInsertionRows(builder, traceInsert) - assert.Equal(t, valuesToLimbRows(4, 0, 0, 2, 2, 1, 1), builder.positions[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 0, 2, 2, 1, 1), builder.positions[:]) assert.Equal(t, vector.ForTest(1, 0, 0, 0, 0, 0), builder.isFirst) assert.Equal(t, vector.ForTest(1, 1, 1, 1, 1, 1), builder.isInsert) - assert.Equal(t, valuesToLimbRows(4, 2, 2, 3, 3, 3, 3), builder.nextFreeNode[:]) - assert.Equal(t, valuesToLimbRows(4, 0, 0, 2, 0, 0, 0), builder.insertionPath[:]) + assert.Equal(t, valuesToLimbRows(16, 2, 2, 3, 3, 3, 3), builder.nextFreeNode[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 0, 2, 0, 0, 0), builder.insertionPath[:]) assert.Equal(t, vector.ForTest(0, 0, 1, 0, 0, 0), builder.isInsertRow3) assert.Equal(t, vector.ForTest(0, 0, 0, 0, 0, 0), builder.isDelete) assert.Equal(t, vector.ForTest(0, 0, 0, 0, 0, 0), builder.isUpdate) @@ -84,7 +84,7 @@ func TestAssignInsert(t *testing.T) { assert.Equal(t, vector.ForTest(0, 0, 0, 0, 0, 0), builder.isReadNonZero) assert.Equal(t, vector.ForTest(1, 0, 1, 0, 1, 0), builder.useNextMerkleProof) assert.Equal(t, vector.ForTest(1, 1, 1, 1, 1, 1), builder.isActive) - assert.Equal(t, valuesToLimbRows(4, 0, 1, 2, 3, 4, 5), builder.accumulatorCounter[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 1, 2, 3, 4, 5), builder.accumulatorCounter[:]) for _, leavesLimbCol := range builder.leaves { for i := range leavesLimbCol { if i == 0 { @@ -102,9 +102,9 @@ func TestAssignInsert(t *testing.T) { assert.Equal(t, getLimbsFromRow(builder.positions[:], 2), getLimbsFromRow(builder.positions[:], 3)) assert.Equal(t, getLimbsFromRow(builder.positions[:], 4), getLimbsFromRow(builder.positions[:], 5)) - assertCorrectMerkleProof(t, builder) - // Verify the Merkle proofs along with the reuse in the wizard - assertCorrectMerkleProofsUsingWizard(t, builder) + // assertCorrectMerkleProof(t, builder) + // // Verify the Merkle proofs along with the reuse in the wizard + // assertCorrectMerkleProofsUsingWizard(t, builder) } func TestAssignUpdate(t *testing.T) { @@ -116,11 +116,11 @@ func TestAssignUpdate(t *testing.T) { traceUpdate := acc.UpdateAndProve(types.FullBytes32FromHex("0x32"), types.FullBytes32FromHex("0x20")) pushUpdateRows(builder, traceUpdate) - assert.Equal(t, valuesToLimbRows(4, 2, 2), builder.positions[:]) + assert.Equal(t, valuesToLimbRows(16, 2, 2), builder.positions[:]) assert.Equal(t, vector.ForTest(1, 0), builder.isFirst) assert.Equal(t, vector.ForTest(0, 0), builder.isInsert) - assert.Equal(t, valuesToLimbRows(4, 3, 3), builder.nextFreeNode[:]) - assert.Equal(t, valuesToLimbRows(4, 0, 0), builder.insertionPath[:]) + assert.Equal(t, valuesToLimbRows(16, 3, 3), builder.nextFreeNode[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 0), builder.insertionPath[:]) assert.Equal(t, vector.ForTest(0, 0), builder.isInsertRow3) assert.Equal(t, vector.ForTest(0, 0), builder.isDelete) assert.Equal(t, vector.ForTest(1, 1), builder.isUpdate) @@ -128,7 +128,7 @@ func TestAssignUpdate(t *testing.T) { assert.Equal(t, vector.ForTest(0, 0), builder.isReadNonZero) assert.Equal(t, vector.ForTest(1, 0), builder.useNextMerkleProof) assert.Equal(t, vector.ForTest(1, 1), builder.isActive) - assert.Equal(t, valuesToLimbRows(4, 0, 1), builder.accumulatorCounter[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 1), builder.accumulatorCounter[:]) for _, leavesLimbCol := range builder.leaves { for i := range leavesLimbCol { if i == 0 { @@ -159,8 +159,8 @@ func TestAssignDelete(t *testing.T) { assert.Equal(t, getLimbsFromRow(builder.roots[:], 3), getLimbsFromRow(builder.roots[:], 4)) assert.Equal(t, vector.ForTest(1, 0, 0, 0, 0, 0), builder.isFirst) assert.Equal(t, vector.ForTest(0, 0, 0, 0, 0, 0), builder.isInsert) - assert.Equal(t, valuesToLimbRows(4, 3, 3, 3, 3, 3, 3), builder.nextFreeNode[:]) - assert.Equal(t, valuesToLimbRows(4, 0, 0, 0, 0, 0, 0), builder.insertionPath[:]) + assert.Equal(t, valuesToLimbRows(16, 3, 3, 3, 3, 3, 3), builder.nextFreeNode[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 0, 0, 0, 0, 0), builder.insertionPath[:]) assert.Equal(t, vector.ForTest(0, 0, 0, 0, 0, 0), builder.isInsertRow3) assert.Equal(t, vector.ForTest(1, 1, 1, 1, 1, 1), builder.isDelete) assert.Equal(t, vector.ForTest(0, 0, 0, 0, 0, 0), builder.isUpdate) @@ -168,7 +168,7 @@ func TestAssignDelete(t *testing.T) { assert.Equal(t, vector.ForTest(0, 0, 0, 0, 0, 0), builder.isReadNonZero) assert.Equal(t, vector.ForTest(1, 0, 1, 0, 1, 0), builder.useNextMerkleProof) assert.Equal(t, vector.ForTest(1, 1, 1, 1, 1, 1), builder.isActive) - assert.Equal(t, valuesToLimbRows(4, 0, 1, 2, 3, 4, 5), builder.accumulatorCounter[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 1, 2, 3, 4, 5), builder.accumulatorCounter[:]) for _, leavesLimbCol := range builder.leaves { for i := range leavesLimbCol { if i == 0 { @@ -196,11 +196,11 @@ func TestAssignReadZero(t *testing.T) { pushReadZeroRows(builder, traceReadZero) assert.Equal(t, getLimbsFromRow(builder.roots[:], 0), getLimbsFromRow(builder.roots[:], 1)) - assert.Equal(t, valuesToLimbRows(4, 0, 1), builder.positions[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 1), builder.positions[:]) assert.Equal(t, vector.ForTest(1, 0), builder.isFirst) assert.Equal(t, vector.ForTest(0, 0), builder.isInsert) - assert.Equal(t, valuesToLimbRows(4, 2, 2), builder.nextFreeNode[:]) - assert.Equal(t, valuesToLimbRows(4, 0, 0), builder.insertionPath[:]) + assert.Equal(t, valuesToLimbRows(16, 2, 2), builder.nextFreeNode[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 0), builder.insertionPath[:]) assert.Equal(t, vector.ForTest(0, 0), builder.isInsertRow3) assert.Equal(t, vector.ForTest(0, 0), builder.isDelete) assert.Equal(t, vector.ForTest(0, 0), builder.isUpdate) @@ -208,7 +208,7 @@ func TestAssignReadZero(t *testing.T) { assert.Equal(t, vector.ForTest(0, 0), builder.isReadNonZero) assert.Equal(t, vector.ForTest(0, 0), builder.useNextMerkleProof) assert.Equal(t, vector.ForTest(1, 1), builder.isActive) - assert.Equal(t, valuesToLimbRows(4, 0, 1), builder.accumulatorCounter[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 1), builder.accumulatorCounter[:]) for _, leavesLimbCol := range builder.leaves { for i := range leavesLimbCol { if i == 0 { @@ -234,11 +234,11 @@ func TestAssignReadNonZero(t *testing.T) { pushReadNonZeroRows(builder, traceReadNonZero) assert.Equal(t, getLimbsFromRow(builder.roots[:], 0), getLimbsFromRow(builder.roots[:], 1)) - assert.Equal(t, valuesToLimbRows(4, 2, 2), builder.positions[:]) + assert.Equal(t, valuesToLimbRows(16, 2, 2), builder.positions[:]) assert.Equal(t, vector.ForTest(1, 0), builder.isFirst) assert.Equal(t, vector.ForTest(0, 0), builder.isInsert) - assert.Equal(t, valuesToLimbRows(4, 3, 3), builder.nextFreeNode[:]) - assert.Equal(t, valuesToLimbRows(4, 0, 0), builder.insertionPath[:]) + assert.Equal(t, valuesToLimbRows(16, 3, 3), builder.nextFreeNode[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 0), builder.insertionPath[:]) assert.Equal(t, vector.ForTest(0, 0), builder.isInsertRow3) assert.Equal(t, vector.ForTest(0, 0), builder.isDelete) assert.Equal(t, vector.ForTest(0, 0), builder.isUpdate) @@ -246,7 +246,7 @@ func TestAssignReadNonZero(t *testing.T) { assert.Equal(t, vector.ForTest(1, 1), builder.isReadNonZero) assert.Equal(t, vector.ForTest(0, 0), builder.useNextMerkleProof) assert.Equal(t, vector.ForTest(1, 1), builder.isActive) - assert.Equal(t, valuesToLimbRows(4, 0, 1), builder.accumulatorCounter[:]) + assert.Equal(t, valuesToLimbRows(16, 0, 1), builder.accumulatorCounter[:]) assertCorrectMerkleProof(t, builder) // Verify the Merkle proofs along with the reuse in the wizard @@ -307,7 +307,7 @@ func assertCorrectMerkleProofsUsingWizard(t *testing.T, builder *assignmentBuild proofcol.Assign(run, builder.proofs) - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { run.AssignColumn(ifaces.ColIDf("ROOTS_%d", i), smartvectors.RightZeroPadded(builder.roots[i], size)) run.AssignColumn(ifaces.ColIDf("LEAVES_%d", i), smartvectors.RightZeroPadded(builder.leaves[i], size)) } From 663ecead864579a1275448718ff15628b4ad726e Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Mon, 24 Nov 2025 20:09:59 +0530 Subject: [PATCH 16/22] fix: debug empty leaf --- prover/zkevm/prover/statemanager/accumulator/assign.go | 10 +++++++--- .../prover/statemanager/accumulator/assign_test.go | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index 539dfa411d..b64a9a08a2 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -513,7 +513,9 @@ func (a *assignmentBuilder) pushRow( } func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isEmptyLeaf bool) { - var zeroBlock field.Octuplet + var ( + zeroBlock field.Octuplet + ) if !isEmptyLeaf { prevFrBytes := uint64To64Bytes(uint64(leafOpening.Prev)) prevFrLimbs := divideFieldBytesToFieldLimbs(prevFrBytes, hashU64) @@ -552,8 +554,10 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE isEmpty := field.Zero() a.isEmptyLeaf = append(a.isEmptyLeaf, isEmpty) } else { - intermZeroLimbs := vortex.CompressPoseidon2(zeroBlock, zeroBlock) - intermOneLimbs := vortex.CompressPoseidon2(intermZeroLimbs, zeroBlock) + intermZeroLimbs_ := vortex.CompressPoseidon2(zeroBlock, zeroBlock) + intermZeroLimbs := vortex.CompressPoseidon2(intermZeroLimbs_, zeroBlock) + intermOneLimbs_ := vortex.CompressPoseidon2(intermZeroLimbs, zeroBlock) + intermOneLimbs := vortex.CompressPoseidon2(intermOneLimbs_, zeroBlock) intermTwoLimbs := vortex.CompressPoseidon2(intermOneLimbs, zeroBlock) leafHashesLimbs := vortex.CompressPoseidon2(intermTwoLimbs, zeroBlock) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign_test.go b/prover/zkevm/prover/statemanager/accumulator/assign_test.go index 08adf36bc1..69102b6969 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign_test.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign_test.go @@ -95,7 +95,7 @@ func TestAssignInsert(t *testing.T) { } } - assert.Equal(t, valueToLimbs(16, 0), getLimbsFromRow(builder.leaves[:], 2)) + assert.Equal(t, valueToLimbs(8, 0), getLimbsFromRow(builder.leaves[:], 2)) assert.Equal(t, getLimbsFromRow(builder.roots[:], 1), getLimbsFromRow(builder.roots[:], 2)) assert.Equal(t, getLimbsFromRow(builder.roots[:], 3), getLimbsFromRow(builder.roots[:], 4)) assert.Equal(t, getLimbsFromRow(builder.positions[:], 0), getLimbsFromRow(builder.positions[:], 1)) @@ -103,7 +103,7 @@ func TestAssignInsert(t *testing.T) { assert.Equal(t, getLimbsFromRow(builder.positions[:], 4), getLimbsFromRow(builder.positions[:], 5)) // assertCorrectMerkleProof(t, builder) - // // Verify the Merkle proofs along with the reuse in the wizard + // Verify the Merkle proofs along with the reuse in the wizard // assertCorrectMerkleProofsUsingWizard(t, builder) } From df5e650d7bc2d8b01c4b537909aa4b9d652fd935 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Mon, 24 Nov 2025 20:42:24 +0530 Subject: [PATCH 17/22] fix: leaf length fixed, test passing --- .../prover/statemanager/accumulator/assign_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign_test.go b/prover/zkevm/prover/statemanager/accumulator/assign_test.go index 69102b6969..efe5b36979 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign_test.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign_test.go @@ -102,9 +102,9 @@ func TestAssignInsert(t *testing.T) { assert.Equal(t, getLimbsFromRow(builder.positions[:], 2), getLimbsFromRow(builder.positions[:], 3)) assert.Equal(t, getLimbsFromRow(builder.positions[:], 4), getLimbsFromRow(builder.positions[:], 5)) - // assertCorrectMerkleProof(t, builder) + assertCorrectMerkleProof(t, builder) // Verify the Merkle proofs along with the reuse in the wizard - // assertCorrectMerkleProofsUsingWizard(t, builder) + assertCorrectMerkleProofsUsingWizard(t, builder) } func TestAssignUpdate(t *testing.T) { @@ -256,7 +256,9 @@ func TestAssignReadNonZero(t *testing.T) { func assertCorrectMerkleProof(t *testing.T, builder *assignmentBuilder) { proofs := builder.proofs for i, proof := range proofs { - assert.Equal(t, true, proof.Verify(statemanager.POSEIDON2_CONFIG, field.Octuplet(builder.leaves[i]), field.Octuplet(builder.roots[i]))) + leaf := field.Octuplet(getLimbsFromRow(builder.leaves[:], i)) + root := field.Octuplet(getLimbsFromRow(builder.roots[:], i)) + assert.Equal(t, true, proof.Verify(statemanager.POSEIDON2_CONFIG, leaf, root)) } } @@ -276,7 +278,7 @@ func assertCorrectMerkleProofsUsingWizard(t *testing.T, builder *assignmentBuild define := func(b *wizard.Builder) { proofcol = merkle.NewProof(b.CompiledIOP, 0, "PROOF", builder.MerkleTreeDepth, size) - for i := 0; i < common.NbLimbU256; i++ { + for i := 0; i < common.NbElemPerHash; i++ { rootscol[i] = b.RegisterCommit(ifaces.ColIDf("ROOTS_%d", i), size) leavescol[i] = b.RegisterCommit(ifaces.ColIDf("LEAVES_%d", i), size) } From 9ee07699e8e0631ffa1e2a63e2489b8e7c7218a8 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Mon, 24 Nov 2025 20:45:30 +0530 Subject: [PATCH 18/22] fix: deletion test fixed, all assign tests are passing now --- prover/zkevm/prover/statemanager/accumulator/assign_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign_test.go b/prover/zkevm/prover/statemanager/accumulator/assign_test.go index efe5b36979..41835f506f 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign_test.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign_test.go @@ -154,7 +154,7 @@ func TestAssignDelete(t *testing.T) { traceDelete := acc.DeleteAndProve(types.FullBytes32FromHex("0x32")) pushDeletionRows(builder, traceDelete) - assert.Equal(t, valueToLimbs(16, 0), getLimbsFromRow(builder.leaves[:], 3)) + assert.Equal(t, valueToLimbs(8, 0), getLimbsFromRow(builder.leaves[:], 3)) assert.Equal(t, getLimbsFromRow(builder.roots[:], 1), getLimbsFromRow(builder.roots[:], 2)) assert.Equal(t, getLimbsFromRow(builder.roots[:], 3), getLimbsFromRow(builder.roots[:], 4)) assert.Equal(t, vector.ForTest(1, 0, 0, 0, 0, 0), builder.isFirst) From a81b344328fa8ae014ea3b7fee6a109ad0b921a6 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Tue, 25 Nov 2025 18:16:06 +0530 Subject: [PATCH 19/22] fix(accumulator): changing mimc to poseidon query (wip) --- .../prover/statemanager/accumulator/assign.go | 38 ++++--- .../prover/statemanager/accumulator/define.go | 100 +++++++++--------- 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index b64a9a08a2..eeb7c55081 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -105,9 +105,9 @@ type assignmentBuilder struct { // leafOpening is a tuple of four columns containing // Prev, Next, HKey, HVal of a leaf. This corresponds to the [Accumulator.Column.LeafOpening] leafOpening leafOpenings - // interm is a slice containing 3 intermediate hash states. This corresponds to the [Accumulator.Column.Interm] + // interm is a slice containing 5 intermediate hash states. This corresponds to the [Accumulator.Column.Interm] interm [common.NbElemPerHash][][]field.Element - // leafHash contains sequential MiMC hashes of leafOpening. It matches with Leaves except when there is empty leaf. This corresponds to the [Accumulator.Column.LeafHashes] + // leafHash contains sequential Poseidon2 hashes of leafOpening. It matches with Leaves except when there is empty leaf. This corresponds to the [Accumulator.Column.LeafHashes] leafHashes [common.NbElemPerHash][]field.Element // isEmptyLeaf is one when Leaves contains empty leaf and does not match with LeafHash isEmptyLeaf []field.Element @@ -118,9 +118,9 @@ type assignmentBuilder struct { insertionPath [common.NbElemForHasingU64][]field.Element // isInsertRow3 is one for row 3 of INSERT operation isInsertRow3 []field.Element - // intermTopRoot contains the intermediate MiMC state hash + // intermTopRoot contains the intermediate Poseidon2 state hash intermTopRoot [common.NbElemPerHash][]field.Element - // topRoot contains the MiMC hash of SubTreeRoot and NextFreeNode + // topRoot contains the Poseidon2 hash of SubTreeRoot and NextFreeNode topRoot [common.NbElemPerHash][]field.Element } @@ -176,7 +176,7 @@ func newAssignmentBuilder(s Settings) *assignmentBuilder { amb.intermTopRoot[i] = make([]field.Element, 0, amb.NumRows()) amb.topRoot[i] = make([]field.Element, 0, amb.NumRows()) - amb.interm[i] = make([][]field.Element, 3) + amb.interm[i] = make([][]field.Element, 5) for j := 0; j < len(amb.interm[i]); j++ { amb.interm[i][j] = make([]field.Element, 0, amb.NumRows()) } @@ -424,7 +424,7 @@ func (a *assignmentBuilder) pushRow( a.proofs = append(a.proofs, proof) - // We assign intermTopRoot = MiMC(zero, root), and topRoot = MiMC(interm, nextFreeNode) + // We assign intermTopRoot = Poseidon2(zero, root), and topRoot = Poseidon2(interm, nextFreeNode) intermTopRootFrLimbs := common.BlockCompression([]field.Element{field.Zero()}, nextFreeNodeFrLimbs) topRootFrLimbs := common.BlockCompression(intermTopRootFrLimbs, rootFrLimbs) for i := range a.intermTopRoot { @@ -527,12 +527,12 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE hValFrLimbs := divideFieldBytesToFieldLimbs(leafOpening.HVal[:], hashFieldElements) // As prevFrLimbs, nextFrLimbs are of 16 limbs, we hash them in two steps - intermZeroLimbs_ := vortex.CompressPoseidon2(zeroBlock, vortex.Hash(prevFrLimbs[0:8])) - intermZeroLimbs := vortex.CompressPoseidon2(intermZeroLimbs_, vortex.Hash(prevFrLimbs[8:16])) - intermOneLimbs_ := vortex.CompressPoseidon2(intermZeroLimbs, vortex.Hash(nextFrLimbs[0:8])) - intermOneLimbs := vortex.CompressPoseidon2(intermOneLimbs_, vortex.Hash(nextFrLimbs[8:16])) - intermTwoLimbs := vortex.CompressPoseidon2(intermOneLimbs, vortex.Hash(hKeyFrLimbs)) - leafLimbs := vortex.CompressPoseidon2(intermTwoLimbs, vortex.Hash(hValFrLimbs)) + intermZeroLimbs := vortex.CompressPoseidon2(zeroBlock, vortex.Hash(prevFrLimbs[0:common.NbElemPerHash])) + intermOneLimbs := vortex.CompressPoseidon2(intermZeroLimbs, vortex.Hash(prevFrLimbs[common.NbElemPerHash:common.NbElemForHasingU64])) + intermTwoLimbs := vortex.CompressPoseidon2(intermOneLimbs, vortex.Hash(nextFrLimbs[0:common.NbElemPerHash])) + intermThreeLimbs := vortex.CompressPoseidon2(intermTwoLimbs, vortex.Hash(nextFrLimbs[common.NbElemPerHash:common.NbElemForHasingU64])) + intermFourLimbs := vortex.CompressPoseidon2(intermThreeLimbs, vortex.Hash(hKeyFrLimbs)) + leafLimbs := vortex.CompressPoseidon2(intermFourLimbs, vortex.Hash(hValFrLimbs)) for i := range prevFrLimbs { a.leafOpening.prev[i] = append(a.leafOpening.prev[i], prevFrLimbs[i]) @@ -549,17 +549,19 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE a.interm[i][0] = append(a.interm[i][0], intermZeroLimbs[i]) a.interm[i][1] = append(a.interm[i][1], intermOneLimbs[i]) a.interm[i][2] = append(a.interm[i][2], intermTwoLimbs[i]) + a.interm[i][3] = append(a.interm[i][3], intermThreeLimbs[i]) + a.interm[i][4] = append(a.interm[i][4], intermFourLimbs[i]) } isEmpty := field.Zero() a.isEmptyLeaf = append(a.isEmptyLeaf, isEmpty) } else { - intermZeroLimbs_ := vortex.CompressPoseidon2(zeroBlock, zeroBlock) - intermZeroLimbs := vortex.CompressPoseidon2(intermZeroLimbs_, zeroBlock) - intermOneLimbs_ := vortex.CompressPoseidon2(intermZeroLimbs, zeroBlock) - intermOneLimbs := vortex.CompressPoseidon2(intermOneLimbs_, zeroBlock) + intermZeroLimbs := vortex.CompressPoseidon2(zeroBlock, zeroBlock) + intermOneLimbs := vortex.CompressPoseidon2(intermZeroLimbs, zeroBlock) intermTwoLimbs := vortex.CompressPoseidon2(intermOneLimbs, zeroBlock) - leafHashesLimbs := vortex.CompressPoseidon2(intermTwoLimbs, zeroBlock) + intermThreeLimbs := vortex.CompressPoseidon2(intermTwoLimbs, zeroBlock) + intermFourLimbs := vortex.CompressPoseidon2(intermThreeLimbs, zeroBlock) + leafHashesLimbs := vortex.CompressPoseidon2(intermFourLimbs, zeroBlock) for i := range a.leafOpening.prev { a.leafOpening.prev[i] = append(a.leafOpening.prev[i], field.Zero()) @@ -577,6 +579,8 @@ func (a *assignmentBuilder) computeLeaf(leafOpening accumulator.LeafOpening, isE a.interm[i][0] = append(a.interm[i][0], intermZeroLimbs[i]) a.interm[i][1] = append(a.interm[i][1], intermOneLimbs[i]) a.interm[i][2] = append(a.interm[i][2], intermTwoLimbs[i]) + a.interm[i][3] = append(a.interm[i][3], intermThreeLimbs[i]) + a.interm[i][4] = append(a.interm[i][4], intermFourLimbs[i]) } isEmpty := field.One() diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index 7bbaf448f6..7cf6326a10 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -31,7 +31,7 @@ The main verification steps of the Accumulator module is as follows, 1. First and foremost is to verify each of the above operations from the traces. For example, an UPDATE operation consists of two merkle proofs on the same tree: one with the old leaf and another with the new leaf. Therefore, to verify an UPDATE, we need to separately verify these two merkle proofs. We also need to verify the fact that -they are for the same Merkle tree. We call it verifying "reuse of Merkle proof". These verifications are delegated +they are for the same Merkle tree. We call it verifying the "reuse of Merkle proof". These verifications are delegated to the Merkle module and the technique for this is described in merkle/merkleproof.md. As a result, an UPDATE induces two rows in the Accumulator module. Also, INSERT and DELETE have three consicutive @@ -51,11 +51,11 @@ We use a dedicated wizard called Byte32cmp to verify this. 4. The sparse merkle tree follows a linked list structure. We need to verify that this property is maintained for every operations. For example, for INSERT, we neeed to verify that leafMinus.Next = leafPlus.Index before insertion. We call these verification the "pointer check". We have global constraints for this check for INSERT, DELETE, and READ-ZERO. -5. We check that Leave is the MiMC hash of the leaf opening, a tuple of {PREV, NEXT, HKEY, HVAL}. +5. We check that Leave is the Poseidon2 hash of the leaf opening, a tuple of {PREV, NEXT, HKEY, HVAL}. 6. We check that NextFreeNode is constant throughout the rows of each operation except INSERT. For INSERT, it is incremented by 1 in row 3. -7. We check that TopRoot is the MiMC hash of NextFreeNode and the ROOT. +7. We check that TopRoot is the Poseidon2 hash of NextFreeNode and the ROOT. 8. We constraint that every column is zero in the inactive area. */ @@ -105,10 +105,10 @@ const ( // structure for leaf opening type LeafOpenings struct { - HKey [common.NbElemPerHash]ifaces.Column - HVal [common.NbElemPerHash]ifaces.Column Prev [common.NbElemForHasingU64]ifaces.Column Next [common.NbElemForHasingU64]ifaces.Column + HKey [common.NbElemPerHash]ifaces.Column + HVal [common.NbElemPerHash]ifaces.Column } // Module module @@ -173,11 +173,11 @@ type Module struct { // Columns for leaf hashing check // LeafOpening contains four columns corresponding to HKey, HVal, Prev, and Next LeafOpenings LeafOpenings - // Interm contains the three intermediate states corresponding to the MiMC block computation divided into limbs + // Interm contains the three intermediate states corresponding to the Poseidon2 block computation divided into limbs Interm [common.NbElemPerHash][]ifaces.Column - // Zero contains the column with zero value, used in the MiMc query + // Zero contains the column with zero value, used in the Poseidon2 query Zero ifaces.Column - // LeafHash contains the leafHashes (the final MiMC block), equals with Leaves, except when it is empty leaf + // LeafHash contains the leafHashes (the final Poseidon2 block), equals with Leaves, except when it is empty leaf LeafHashes [common.NbElemPerHash]ifaces.Column // IsEmptyLeaf is one when Leaves contains empty leaf and does not match with LeafHash IsEmptyLeaf ifaces.Column @@ -194,9 +194,9 @@ type Module struct { IsInsertRow3 ifaces.Column // Columns for hashing the top root - // IntermTopRoot contains the intermediate MiMC state hash + // IntermTopRoot contains the intermediate Poseidon2 state hash IntermTopRoot [common.NbElemPerHash]ifaces.Column - // TopRoot contains the MiMC hash of Roots and NextFreeNode + // TopRoot contains the Poseidon2 hash of Roots and NextFreeNode TopRoot [common.NbElemPerHash]ifaces.Column } @@ -316,7 +316,7 @@ func (am *Module) define(comp *wizard.CompiledIOP, s Settings) { am.checkPointer() // Check leaf hashes - // am.checkLeafHashes() + am.checkLeafHashes() // Check NextFreeNode is constant through a segment unless there is an INSERT operation am.checkNextFreeNode() @@ -348,14 +348,16 @@ func (am *Module) define(comp *wizard.CompiledIOP, s Settings) { } func (am *Module) commitLeafHashingCols() { - ACCUMULATOR_INTERM := make([]ifaces.ColID, 3) + ACCUMULATOR_INTERM := make([]ifaces.ColID, 5) ACCUMULATOR_LEAF_OPENING_PREV := "ACCUMULATOR_LEAF_OPENING_PREV" ACCUMULATOR_LEAF_OPENING_NEXT := "ACCUMULATOR_LEAF_OPENING_NEXT" ACCUMULATOR_LEAF_OPENING_HKEY := "ACCUMULATOR_LEAF_OPENING_HKEY" ACCUMULATOR_LEAF_OPENING_HVAL := "ACCUMULATOR_LEAF_OPENING_HVAL" - ACCUMULATOR_INTERM[0] = "ACCUMULATOR_INTERM_PREV" - ACCUMULATOR_INTERM[1] = "ACCUMULATOR_INTERM_NEXT" - ACCUMULATOR_INTERM[2] = "ACCUMULATOR_INTERM_HKEY" + ACCUMULATOR_INTERM[0] = "ACCUMULATOR_INTERM_PREV_FIRST" + ACCUMULATOR_INTERM[1] = "ACCUMULATOR_INTERM_PREV_SECOND" + ACCUMULATOR_INTERM[2] = "ACCUMULATOR_INTERM_NEXT_FIRST" + ACCUMULATOR_INTERM[3] = "ACCUMULATOR_INTERM_NEXT_SECOND" + ACCUMULATOR_INTERM[4] = "ACCUMULATOR_INTERM_HKEY" am.Cols.Zero = verifiercol.NewConstantCol(field.Zero(), am.NumRows(), "merkle-tree-accumulator") for i := range am.Cols.LeafOpenings.Prev { @@ -364,7 +366,7 @@ func (am *Module) commitLeafHashingCols() { } for i := 0; i < common.NbElemPerHash; i++ { - am.Cols.Interm[i] = make([]ifaces.Column, 3) + am.Cols.Interm[i] = make([]ifaces.Column, 5) am.Cols.LeafOpenings.HKey[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_HKEY, i), am.NumRows(), true) am.Cols.LeafOpenings.HVal[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_HVAL, i), am.NumRows(), true) am.Cols.LeafHashes[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_HASHES_NAME, i), am.NumRows(), true) @@ -676,38 +678,36 @@ func (am *Module) checkPointer() { } func (am *Module) checkLeafHashes() { - //cols := am.Cols + cols := am.Cols - panic("TODO: change the MiMC queries and replace them by Poseidon. Also review the [common.NbElemPerHash] loop") - - // for i := 0; i < common.NbElemPerHash; i++ { - - // // TODO: fix MiMC query - // am.comp.InsertMiMC(am.Round, am.qname("MIMC_PREV_%d", i), cols.LeafOpenings.Prev[0], cols.Zero, cols.Interm[i][0], nil) - // am.comp.InsertMiMC(am.Round, am.qname("MIMC_NEXT_%d", i), cols.LeafOpenings.Next[0], cols.Interm[i][0], cols.Interm[i][1], nil) - - // // TODO: fix MiMC query - // am.comp.InsertMiMC(am.Round, am.qname("MIMC_HKEY"), cols.LeafOpenings.HKey[0], cols.Interm[1][0], cols.Interm[2][0], nil) - // am.comp.InsertMiMC(am.Round, am.qname("MIMC_HVAL_LEAF_%d", i), cols.LeafOpenings.HVal[0], cols.Interm[2][0], cols.LeafHashes[i], nil) - - // // Global: IsActive[i] * (1 - IsEmptyLeaf[i]) * (Leaves[i] - LeafHashes[i]) - // expr1 := symbolic.Sub(cols.Leaves[i], cols.LeafHashes[i]) - // expr2 := symbolic.Sub(symbolic.NewConstant(1), cols.IsEmptyLeaf) - // expr3 := symbolic.Mul(cols.IsActiveAccumulator, expr1, expr2) - // am.comp.InsertGlobal(am.Round, am.qname("LEAF_HASH_EQUALITY_%d", i), expr3) - // } - // // Booleaninty of IsEmptyLeaf: IsActive[i] * (IsEmptyLeaf^2[i] - IsEmptyLeaf[i]) - // expr4 := symbolic.Sub(symbolic.Square(cols.IsEmptyLeaf), cols.IsEmptyLeaf) - // expr4 = symbolic.Mul(expr4, cols.IsActiveAccumulator) - // am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_BOOLEANITY"), expr4) - - // // IsEmptyLeaf is set to true if and only if it is the third row for INSERT, or fourth row for DELETE - // // i.e. IsActiveAccumulator[i] * (IsEmptyLeaf[i] - IsFirst[i-2] * IsInsert[i-2] - IsFirst[i-3] * IsDelete[i-3]) - // expr5 := symbolic.Mul(cols.IsActiveAccumulator, - // symbolic.Sub(cols.IsEmptyLeaf, - // symbolic.Mul(column.Shift(cols.IsFirst, -2), column.Shift(cols.IsInsert, -2)), - // symbolic.Mul(column.Shift(cols.IsFirst, -3), column.Shift(cols.IsDelete, -3)))) - // am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_ONE_FOR_INSERT_THIRD_ROW_AND_DELETE_FOURTH_ROW"), expr5) + for i := 0; i < common.NbElemPerHash; i++ { + + // TODO: fix Poseidon2 query + am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_PREV_%d", i), cols.LeafOpenings.Prev[0], cols.Zero, cols.Interm[i][0], nil) + am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_NEXT_%d", i), cols.LeafOpenings.Next[0], cols.Interm[i][0], cols.Interm[i][1], nil) + + // TODO: fix Poseidon2 query + am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_HKEY"), cols.LeafOpenings.HKey[0], cols.Interm[1][0], cols.Interm[2][0], nil) + am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_HVAL_LEAF_%d", i), cols.LeafOpenings.HVal[0], cols.Interm[2][0], cols.LeafHashes[i], nil) + + // Global: IsActive[i] * (1 - IsEmptyLeaf[i]) * (Leaves[i] - LeafHashes[i]) + expr1 := symbolic.Sub(cols.Leaves[i], cols.LeafHashes[i]) + expr2 := symbolic.Sub(symbolic.NewConstant(1), cols.IsEmptyLeaf) + expr3 := symbolic.Mul(cols.IsActiveAccumulator, expr1, expr2) + am.comp.InsertGlobal(am.Round, am.qname("LEAF_HASH_EQUALITY_%d", i), expr3) + } + // Booleaninty of IsEmptyLeaf: IsActive[i] * (IsEmptyLeaf^2[i] - IsEmptyLeaf[i]) + expr4 := symbolic.Sub(symbolic.Square(cols.IsEmptyLeaf), cols.IsEmptyLeaf) + expr4 = symbolic.Mul(expr4, cols.IsActiveAccumulator) + am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_BOOLEANITY"), expr4) + + // IsEmptyLeaf is set to true if and only if it is the third row for INSERT, or fourth row for DELETE + // i.e. IsActiveAccumulator[i] * (IsEmptyLeaf[i] - IsFirst[i-2] * IsInsert[i-2] - IsFirst[i-3] * IsDelete[i-3]) + expr5 := symbolic.Mul(cols.IsActiveAccumulator, + symbolic.Sub(cols.IsEmptyLeaf, + symbolic.Mul(column.Shift(cols.IsFirst, -2), column.Shift(cols.IsInsert, -2)), + symbolic.Mul(column.Shift(cols.IsFirst, -3), column.Shift(cols.IsDelete, -3)))) + am.comp.InsertGlobal(am.Round, am.qname("IS_EMPTY_LEAF_ONE_FOR_INSERT_THIRD_ROW_AND_DELETE_FOURTH_ROW"), expr5) } func (am *Module) checkNextFreeNode() { @@ -803,8 +803,8 @@ func (am *Module) checkTopRootHash() { //cols := am.Cols // //for i := 0; i < common.NbElemPerHash; i++ { - // am.comp.InsertMiMC(am.Round, am.qname("MIMC_INTERM_TOP_ROOT_%d", i), cols.NextFreeNode, cols.Zero, cols.IntermTopRoot[i], nil) - // am.comp.InsertMiMC(am.Round, am.qname("MIMC_TOP_ROOT_%d", i), cols.Roots, cols.IntermTopRoot[i], cols.TopRoot[i], nil) + // am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_INTERM_TOP_ROOT_%d", i), cols.NextFreeNode, cols.Zero, cols.IntermTopRoot[i], nil) + // am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_TOP_ROOT_%d", i), cols.Roots, cols.IntermTopRoot[i], cols.TopRoot[i], nil) //} } @@ -849,7 +849,7 @@ func (am *Module) checkZeroInInactive() { am.colZeroAtInactive(cols.IsReadNonZero) // Skipping Interm, Zero, and LeafHashes as two of them contain zero hashes and // Zero is a verifier column. The padding area of Interm and LeafHashes - // are already constrained by the MiMC query + // are already constrained by the Poseidon2 query am.colZeroAtInactive(cols.IsEmptyLeaf) am.colZeroAtInactive(cols.IsInsertRow3) // Again skipping IntermTopRoot and TopRoot as they contain zero hashes From 4e8504eb89c2e35ae629045a96bf2096cc803433 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Wed, 26 Nov 2025 13:29:42 +0530 Subject: [PATCH 20/22] fix(define accumulator): added poseidon2 queries for leaf hashes --- .../prover/statemanager/accumulator/define.go | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index 7cf6326a10..634c73b8a0 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -176,7 +176,7 @@ type Module struct { // Interm contains the three intermediate states corresponding to the Poseidon2 block computation divided into limbs Interm [common.NbElemPerHash][]ifaces.Column // Zero contains the column with zero value, used in the Poseidon2 query - Zero ifaces.Column + Zero [common.NbElemPerHash]ifaces.Column // LeafHash contains the leafHashes (the final Poseidon2 block), equals with Leaves, except when it is empty leaf LeafHashes [common.NbElemPerHash]ifaces.Column // IsEmptyLeaf is one when Leaves contains empty leaf and does not match with LeafHash @@ -269,6 +269,9 @@ func (am *Module) define(comp *wizard.CompiledIOP, s Settings) { am.Cols.IsReadZero = comp.InsertCommit(am.Round, ACCUMULATOR_IS_READ_ZERO_NAME, am.NumRows(), true) am.Cols.IsReadNonZero = comp.InsertCommit(am.Round, ACCUMULATOR_IS_READ_NON_ZERO_NAME, am.NumRows(), true) + // define the zero column for leaf hashing check + am.defineZero() + // Leaf hashing columns commitments am.commitLeafHashingCols() @@ -347,6 +350,13 @@ func (am *Module) define(comp *wizard.CompiledIOP, s Settings) { am.MerkleProofVerification.AddProofReuseConstraint(comp, am.Cols.UseNextMerkleProof) } +// defineZero defines the precomputed column ZERO (always zero) +func (am *Module) defineZero() { + for i := 0; i < common.NbElemPerHash; i++ { + am.Cols.Zero[i] = verifiercol.NewConstantCol(field.Zero(), am.NumRows(), "") + } +} + func (am *Module) commitLeafHashingCols() { ACCUMULATOR_INTERM := make([]ifaces.ColID, 5) ACCUMULATOR_LEAF_OPENING_PREV := "ACCUMULATOR_LEAF_OPENING_PREV" @@ -358,7 +368,6 @@ func (am *Module) commitLeafHashingCols() { ACCUMULATOR_INTERM[2] = "ACCUMULATOR_INTERM_NEXT_FIRST" ACCUMULATOR_INTERM[3] = "ACCUMULATOR_INTERM_NEXT_SECOND" ACCUMULATOR_INTERM[4] = "ACCUMULATOR_INTERM_HKEY" - am.Cols.Zero = verifiercol.NewConstantCol(field.Zero(), am.NumRows(), "merkle-tree-accumulator") for i := range am.Cols.LeafOpenings.Prev { am.Cols.LeafOpenings.Prev[i] = am.comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_LEAF_OPENING_PREV, i), am.NumRows(), true) @@ -679,23 +688,33 @@ func (am *Module) checkPointer() { func (am *Module) checkLeafHashes() { cols := am.Cols - + // we assume prev and next length = 2 * common.NbElemPerHash + prevFirst := cols.LeafOpenings.Prev[0:common.NbElemPerHash] + nextFirst := cols.LeafOpenings.Next[0:common.NbElemPerHash] + prevLast := cols.LeafOpenings.Prev[common.NbElemPerHash : 2*common.NbElemPerHash] + nextLast := cols.LeafOpenings.Next[common.NbElemPerHash : 2*common.NbElemPerHash] + + // Interm[0] = Poseidon2(Zero, PrevFirst), old = Zero, Block = PrevFirst + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_PREV_FIRST"), [8]ifaces.Column(prevFirst), cols.Zero, [8]ifaces.Column(cols.Interm[0]), cols.IsActiveAccumulator) + // Interm[1] = Poseidon2(Interm[0], PrevLast), old = Interm[0], Block = PrevLast + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_PREV_LAST"), [8]ifaces.Column(prevLast), [8]ifaces.Column(cols.Interm[0]), [8]ifaces.Column(cols.Interm[1]), cols.IsActiveAccumulator) + // Interm[2] = Poseidon2(Interm[1], NextFirst), old = Interm[1], Block = NextFirst + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_NEXT_FIRST"), [8]ifaces.Column(nextFirst), [8]ifaces.Column(cols.Interm[1]), [8]ifaces.Column(cols.Interm[2]), cols.IsActiveAccumulator) + // Interm[3] = Poseidon2(Interm[2], NextLast), old = Interm[2], Block = NextLast + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_NEXT_LAST"), [8]ifaces.Column(nextLast), [8]ifaces.Column(cols.Interm[2]), [8]ifaces.Column(cols.Interm[3]), cols.IsActiveAccumulator) + // Interm[4] = Poseidon2(Interm[3], HKey), old = Interm[3], Block = HKey + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_HKEY"), [8]ifaces.Column(cols.LeafOpenings.HKey), [8]ifaces.Column(cols.Interm[3]), [8]ifaces.Column(cols.Interm[4]), cols.IsActiveAccumulator) + // LeafHashes = Poseidon2(Interm[4], HVal), old = Interm[4], Block = HVal + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_HVAL_LEAF"), [8]ifaces.Column(cols.LeafOpenings.HVal), [8]ifaces.Column(cols.Interm[4]), [8]ifaces.Column(cols.LeafHashes), cols.IsActiveAccumulator) + + // Global: IsActive[i] * (1 - IsEmptyLeaf[i]) * (Leaves[i] - LeafHashes[i]) for i := 0; i < common.NbElemPerHash; i++ { - - // TODO: fix Poseidon2 query - am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_PREV_%d", i), cols.LeafOpenings.Prev[0], cols.Zero, cols.Interm[i][0], nil) - am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_NEXT_%d", i), cols.LeafOpenings.Next[0], cols.Interm[i][0], cols.Interm[i][1], nil) - - // TODO: fix Poseidon2 query - am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_HKEY"), cols.LeafOpenings.HKey[0], cols.Interm[1][0], cols.Interm[2][0], nil) - am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_HVAL_LEAF_%d", i), cols.LeafOpenings.HVal[0], cols.Interm[2][0], cols.LeafHashes[i], nil) - - // Global: IsActive[i] * (1 - IsEmptyLeaf[i]) * (Leaves[i] - LeafHashes[i]) expr1 := symbolic.Sub(cols.Leaves[i], cols.LeafHashes[i]) expr2 := symbolic.Sub(symbolic.NewConstant(1), cols.IsEmptyLeaf) expr3 := symbolic.Mul(cols.IsActiveAccumulator, expr1, expr2) - am.comp.InsertGlobal(am.Round, am.qname("LEAF_HASH_EQUALITY_%d", i), expr3) + am.comp.InsertGlobal(am.Round, am.qnamef("LEAF_HASH_EQUALITY_%d", i), expr3) } + // Booleaninty of IsEmptyLeaf: IsActive[i] * (IsEmptyLeaf^2[i] - IsEmptyLeaf[i]) expr4 := symbolic.Sub(symbolic.Square(cols.IsEmptyLeaf), cols.IsEmptyLeaf) expr4 = symbolic.Mul(expr4, cols.IsActiveAccumulator) From aebbbc86a3dc1c984c670d4c988956cebf810687 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Wed, 26 Nov 2025 16:54:25 +0530 Subject: [PATCH 21/22] fix(accumulator): poseidon2 query for top root is added --- .../prover/statemanager/accumulator/assign.go | 41 ++++++++++++------- .../prover/statemanager/accumulator/define.go | 30 +++++++------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/prover/zkevm/prover/statemanager/accumulator/assign.go b/prover/zkevm/prover/statemanager/accumulator/assign.go index eeb7c55081..2960ecc661 100644 --- a/prover/zkevm/prover/statemanager/accumulator/assign.go +++ b/prover/zkevm/prover/statemanager/accumulator/assign.go @@ -118,8 +118,10 @@ type assignmentBuilder struct { insertionPath [common.NbElemForHasingU64][]field.Element // isInsertRow3 is one for row 3 of INSERT operation isInsertRow3 []field.Element - // intermTopRoot contains the intermediate Poseidon2 state hash - intermTopRoot [common.NbElemPerHash][]field.Element + // intermZeroTopRoot contains the the first intermediate Poseidon2 state hash + intermZeroTopRoot [common.NbElemPerHash][]field.Element + // intermOneTopRoot contains the second intermediate Poseidon2 state hash + intermOneTopRoot [common.NbElemPerHash][]field.Element // topRoot contains the Poseidon2 hash of SubTreeRoot and NextFreeNode topRoot [common.NbElemPerHash][]field.Element } @@ -173,7 +175,7 @@ func newAssignmentBuilder(s Settings) *assignmentBuilder { amb.leafOpening.hKey[i] = make([]field.Element, 0, amb.NumRows()) amb.leafOpening.hVal[i] = make([]field.Element, 0, amb.NumRows()) - amb.intermTopRoot[i] = make([]field.Element, 0, amb.NumRows()) + amb.intermZeroTopRoot[i] = make([]field.Element, 0, amb.NumRows()) amb.topRoot[i] = make([]field.Element, 0, amb.NumRows()) amb.interm[i] = make([][]field.Element, 5) @@ -354,13 +356,14 @@ func (am *Module) assignTopRootCols( paddedSize := am.NumRows() // compute the padding values for intermTopRoot and topRoot - var zeroBlock field.Octuplet - intermTopRootPadLimbs := vortex.CompressPoseidon2(zeroBlock, zeroBlock) - topRootPadLimbs := vortex.CompressPoseidon2(intermTopRootPadLimbs, zeroBlock) - - for i := range cols.IntermTopRoot { - run.AssignColumn(cols.IntermTopRoot[i].GetColID(), smartvectors.RightPadded(builder.intermTopRoot[i], intermTopRootPadLimbs[i], paddedSize)) - run.AssignColumn(cols.TopRoot[i].GetColID(), smartvectors.RightPadded(builder.topRoot[i], topRootPadLimbs[i], paddedSize)) + // var zeroBlock field.Octuplet + // intermTopRootPadLimbs := vortex.CompressPoseidon2(zeroBlock, zeroBlock) + // topRootPadLimbs := vortex.CompressPoseidon2(intermTopRootPadLimbs, zeroBlock) + + for i := range cols.IntermZeroTopRoot { + run.AssignColumn(cols.IntermZeroTopRoot[i].GetColID(), smartvectors.RightPadded(builder.intermZeroTopRoot[i], field.Zero(), paddedSize)) + run.AssignColumn(cols.IntermOneTopRoot[i].GetColID(), smartvectors.RightPadded(builder.intermOneTopRoot[i], field.Zero(), paddedSize)) + run.AssignColumn(cols.TopRoot[i].GetColID(), smartvectors.RightPadded(builder.topRoot[i], field.Zero(), paddedSize)) } } @@ -424,11 +427,19 @@ func (a *assignmentBuilder) pushRow( a.proofs = append(a.proofs, proof) - // We assign intermTopRoot = Poseidon2(zero, root), and topRoot = Poseidon2(interm, nextFreeNode) - intermTopRootFrLimbs := common.BlockCompression([]field.Element{field.Zero()}, nextFreeNodeFrLimbs) - topRootFrLimbs := common.BlockCompression(intermTopRootFrLimbs, rootFrLimbs) - for i := range a.intermTopRoot { - a.intermTopRoot[i] = append(a.intermTopRoot[i], intermTopRootFrLimbs[i]) + // We assign intermZeroTopRoot = Poseidon2(zero, root), intermOneTopRoot = Poseidon2(intermZeroTopRoot, nextFreeNodeFirst) + // and topRoot = Poseidon2(intermOneTopRoot, nextFreeNodeSecond). + // We also assume nextFreeNodeFrLimbs is of length 2*common.NbElemPerHash + nextFreeNodeFirst := nextFreeNodeFrLimbs[0:common.NbElemPerHash] + nextFreeNodeSecond := nextFreeNodeFrLimbs[common.NbElemPerHash : 2*common.NbElemPerHash] + zeroBlock := field.Octuplet{} + + intermZeroTopRootFrLimbs := common.BlockCompression(zeroBlock[:], rootFrLimbs) + intermOneTopRootFrLimbs := common.BlockCompression(intermZeroTopRootFrLimbs, nextFreeNodeFirst) + topRootFrLimbs := common.BlockCompression(intermOneTopRootFrLimbs, nextFreeNodeSecond) + for i := range a.intermZeroTopRoot { + a.intermZeroTopRoot[i] = append(a.intermZeroTopRoot[i], intermZeroTopRootFrLimbs[i]) + a.intermOneTopRoot[i] = append(a.intermOneTopRoot[i], intermOneTopRootFrLimbs[i]) a.topRoot[i] = append(a.topRoot[i], topRootFrLimbs[i]) } diff --git a/prover/zkevm/prover/statemanager/accumulator/define.go b/prover/zkevm/prover/statemanager/accumulator/define.go index 634c73b8a0..bf52267b10 100644 --- a/prover/zkevm/prover/statemanager/accumulator/define.go +++ b/prover/zkevm/prover/statemanager/accumulator/define.go @@ -99,7 +99,8 @@ const ( ACCUMULATOR_IS_INSERT_ROW3_NAME ifaces.ColID = "ACCUMULATOR_IS_INSERT_ROW3" ACCUMULATOR_NEXT_FREE_NODE_SHIFT_NAME ifaces.ColID = "ACCUMULATOR_NEXT_FREE_NODE_SHIFT" // Columns for hashing the top root - ACCUMULATOR_INTERM_TOP_ROOT_NAME ifaces.ColID = "ACCUMULATOR_INTERM_TOP_ROOT" + ACCUMULATOR_INTERM_ZERO_TOP_ROOT_NAME ifaces.ColID = "ACCUMULATOR_INTERM_ZERO_TOP_ROOT" + ACCUMULATOR_INTERM_ONE_TOP_ROOT_NAME ifaces.ColID = "ACCUMULATOR_INTERM_ONE_TOP_ROOT" ACCUMULATOR_TOP_ROOT_NAME ifaces.ColID = "ACCUMULATOR_TOP_ROOT" ) @@ -194,8 +195,10 @@ type Module struct { IsInsertRow3 ifaces.Column // Columns for hashing the top root - // IntermTopRoot contains the intermediate Poseidon2 state hash - IntermTopRoot [common.NbElemPerHash]ifaces.Column + // IntermZeroTopRoot contains the the first intermediate Poseidon2 state hash + IntermZeroTopRoot [common.NbElemPerHash]ifaces.Column + // IntermOneTopRoot contains the second intermediate Poseidon2 state hash + IntermOneTopRoot [common.NbElemPerHash]ifaces.Column // TopRoot contains the Poseidon2 hash of Roots and NextFreeNode TopRoot [common.NbElemPerHash]ifaces.Column } @@ -239,7 +242,8 @@ func (am *Module) define(comp *wizard.CompiledIOP, s Settings) { am.Cols.HKeyPlus[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_HKEY_PLUS_NAME, i), am.NumRows(), true) // TopRoot hash check columns commitments - am.Cols.IntermTopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INTERM_TOP_ROOT_NAME, i), am.NumRows(), true) + am.Cols.IntermZeroTopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INTERM_ZERO_TOP_ROOT_NAME, i), am.NumRows(), true) + am.Cols.IntermOneTopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_INTERM_ONE_TOP_ROOT_NAME, i), am.NumRows(), true) am.Cols.TopRoot[i] = comp.InsertCommit(am.Round, ifaces.ColIDf("%s_%d", ACCUMULATOR_TOP_ROOT_NAME, i), am.NumRows(), true) } @@ -714,7 +718,7 @@ func (am *Module) checkLeafHashes() { expr3 := symbolic.Mul(cols.IsActiveAccumulator, expr1, expr2) am.comp.InsertGlobal(am.Round, am.qnamef("LEAF_HASH_EQUALITY_%d", i), expr3) } - + // Booleaninty of IsEmptyLeaf: IsActive[i] * (IsEmptyLeaf^2[i] - IsEmptyLeaf[i]) expr4 := symbolic.Sub(symbolic.Square(cols.IsEmptyLeaf), cols.IsEmptyLeaf) expr4 = symbolic.Mul(expr4, cols.IsActiveAccumulator) @@ -816,15 +820,13 @@ func (am *Module) checkNextFreeNode() { } func (am *Module) checkTopRootHash() { - - panic("add Poseidon query here") - - //cols := am.Cols - // - //for i := 0; i < common.NbElemPerHash; i++ { - // am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_INTERM_TOP_ROOT_%d", i), cols.NextFreeNode, cols.Zero, cols.IntermTopRoot[i], nil) - // am.comp.InsertPoseidon2(am.Round, am.qname("Poseidon2_TOP_ROOT_%d", i), cols.Roots, cols.IntermTopRoot[i], cols.TopRoot[i], nil) - //} + cols := am.Cols + // we assume the length of NextFreeNode is 2 * common.NbElemPerHash + nextFreeNodeFirst := cols.NextFreeNode[0:common.NbElemPerHash] + nextFreeNodeSecond := cols.NextFreeNode[common.NbElemPerHash : 2*common.NbElemPerHash] + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_INTERM_ZERO_TOP_ROOT"), cols.Roots, cols.Zero, cols.IntermZeroTopRoot, cols.IsActiveAccumulator) + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_INTERM_ONE_TOP_ROOT"), cols.IntermZeroTopRoot, [8]ifaces.Column(nextFreeNodeFirst), cols.IntermOneTopRoot, cols.IsActiveAccumulator) + am.comp.InsertPoseidon2(am.Round, am.qname("POSEIDON2_TOP_ROOT"), [8]ifaces.Column(nextFreeNodeSecond), cols.IntermOneTopRoot, cols.TopRoot, cols.IsActiveAccumulator) } func (am *Module) checkZeroInInactive() { From ac37e7f696b8d0cc9f894d9d01d9144ef533e6c5 Mon Sep 17 00:00:00 2001 From: arijitdutta67 Date: Thu, 27 Nov 2025 17:48:55 +0530 Subject: [PATCH 22/22] fix(mock): change mimc to poseidon2 --- .../statemanager/mock/arithmetization.go | 4 +-- .../prover/statemanager/mock/basic_state.go | 28 +++++++++---------- .../zkevm/prover/statemanager/mock/shomei.go | 4 +-- .../statemanager/mock/state_access_log.go | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/prover/zkevm/prover/statemanager/mock/arithmetization.go b/prover/zkevm/prover/statemanager/mock/arithmetization.go index 687db3d28a..f6b474657c 100644 --- a/prover/zkevm/prover/statemanager/mock/arithmetization.go +++ b/prover/zkevm/prover/statemanager/mock/arithmetization.go @@ -300,9 +300,9 @@ func (accHistory *AccountHistory) InitializeNewRow(currentBlock int, initialStat } // hashes - stateMimcHash := initialState.GetMimcCodeHash(address) + statePoseidon2Hash := initialState.GetPoseidon2CodeHash(address) - limbBytes := common.SplitBytes(stateMimcHash[:]) + limbBytes := common.SplitBytes(statePoseidon2Hash[:]) for i := range common.NbLimbU256 { prevMimcCodeHash[i].SetBytes(limbBytes[i]) } diff --git a/prover/zkevm/prover/statemanager/mock/basic_state.go b/prover/zkevm/prover/statemanager/mock/basic_state.go index 0bad61cbd6..67d54ac9af 100644 --- a/prover/zkevm/prover/statemanager/mock/basic_state.go +++ b/prover/zkevm/prover/statemanager/mock/basic_state.go @@ -17,13 +17,13 @@ type State map[types.EthAddress]*AccountState // it is meant to be used by the StateAccessFrame builder internally to // initialize the state and keep track of the state. type AccountState struct { - Nonce int64 - Balance *big.Int - KeccakCodeHash types.FullBytes32 - MimcCodeHash types.Bytes32 - CodeSize int64 - Storage map[types.FullBytes32]types.FullBytes32 - DeploymentNumber int64 + Nonce int64 + Balance *big.Int + KeccakCodeHash types.FullBytes32 + Poseidon2CodeHash types.Bytes32 + CodeSize int64 + Storage map[types.FullBytes32]types.FullBytes32 + DeploymentNumber int64 } // deepCopyState makes a hard copy of the state so that modifications of the @@ -50,7 +50,7 @@ func (s State) InsertEOA(a types.EthAddress, nonce int64, balance *big.Int) { s[a] = &AccountState{ Nonce: nonce, Balance: balance, - MimcCodeHash: statemanager.EmptyCodeHash(statemanager.POSEIDON2_CONFIG), + Poseidon2CodeHash: statemanager.EmptyCodeHash(statemanager.POSEIDON2_CONFIG), KeccakCodeHash: types.AsFullBytes32(statemanager.LEGACY_KECCAK_EMPTY_CODEHASH), CodeSize: 0, } @@ -66,7 +66,7 @@ func (s State) InsertContract(a types.EthAddress, mimcCodeHash types.Bytes32, ke s[a] = &AccountState{ Nonce: 0, Balance: &big.Int{}, - MimcCodeHash: mimcCodeHash, + Poseidon2CodeHash: mimcCodeHash, KeccakCodeHash: keccakCodeHash, CodeSize: codeSize, Storage: map[types.FullBytes32]types.FullBytes32{}, @@ -94,11 +94,11 @@ func (s State) SetCodeHash(a types.EthAddress, codeHash types.FullBytes32) { s[a].KeccakCodeHash = codeHash } -// SetMimcCodeHash initializes the mimc code hash of an account and initializes +// SetPoseidon2CodeHash initializes the Poseidon2 code hash of an account and initializes // an empty account with the value. If the account does not already exist. -func (s State) SetMimcCodeHash(a types.EthAddress, codeHash types.Bytes32) { +func (s State) SetPoseidon2CodeHash(a types.EthAddress, codeHash types.Bytes32) { s.initAccountIfNil(a) - s[a].MimcCodeHash = codeHash + s[a].Poseidon2CodeHash = codeHash } // SetCodeSize initializes the code size of an account and initializes the @@ -138,9 +138,9 @@ func (s State) GetCodeHash(a types.EthAddress) types.FullBytes32 { // GetMimcCodeHash returns the Mimc code hash of an account and zero if the account does // not exist. -func (s State) GetMimcCodeHash(a types.EthAddress) types.Bytes32 { +func (s State) GetPoseidon2CodeHash(a types.EthAddress) types.Bytes32 { s.initAccountIfNil(a) - return s[a].MimcCodeHash + return s[a].Poseidon2CodeHash } // SetCodeSize returns the code size of an account and initializes the diff --git a/prover/zkevm/prover/statemanager/mock/shomei.go b/prover/zkevm/prover/statemanager/mock/shomei.go index 53cd7eb679..b877dc6bea 100644 --- a/prover/zkevm/prover/statemanager/mock/shomei.go +++ b/prover/zkevm/prover/statemanager/mock/shomei.go @@ -75,7 +75,7 @@ func InitShomeiState(state State) *statemanager.WorldState { Nonce: acc.Nonce, Balance: acc.Balance, StorageRoot: storageTrie.TopRoot(), - MimcCodeHash: acc.MimcCodeHash, + Poseidon2CodeHash: acc.Poseidon2CodeHash, KeccakCodeHash: acc.KeccakCodeHash, CodeSize: acc.CodeSize, } @@ -488,7 +488,7 @@ func squashSubSegmentForShomei(initialAccountValue types.Account, logs []StateAc vals := log.Value.([]any) currAccountValue.CodeSize = vals[0].(int64) currAccountValue.KeccakCodeHash = vals[1].(types.FullBytes32) - currAccountValue.MimcCodeHash = vals[2].(types.Bytes32) + currAccountValue.Poseidon2CodeHash = vals[2].(types.Bytes32) if currAccountValue.Balance == nil { // we give it a non-nil value because this is used to infer // the existence of the account in the `statesummary` module diff --git a/prover/zkevm/prover/statemanager/mock/state_access_log.go b/prover/zkevm/prover/statemanager/mock/state_access_log.go index 8e596122aa..340d9cfaf7 100644 --- a/prover/zkevm/prover/statemanager/mock/state_access_log.go +++ b/prover/zkevm/prover/statemanager/mock/state_access_log.go @@ -282,7 +282,7 @@ func (b *StateLogBuilder) InitContract(codeSize int64, keccakCodeHash types.Full address := b.currAddress state.SetCodeSize(address, codeSize) state.SetCodeHash(address, keccakCodeHash) - state.SetMimcCodeHash(address, mimcCodeHash) + state.SetPoseidon2CodeHash(address, mimcCodeHash) b.pushFrame( StateAccessLog{ Block: b.currBlock,