Skip to content

Commit

Permalink
allow rpc to access the ForkID directly from DB (0xPolygonHermez#3197)
Browse files Browse the repository at this point in the history
* allow rpc to access the ForkID directly from DB

* update docs

* fix migration down; check for greater forkIDs instead of the next +1 (0xPolygonHermez#3182)

* fix state storage config initialization

* add tests and fix get forkID by block number

* fix test TestGetForkIDByBlockNumber

---------

Co-authored-by: agnusmor <[email protected]>
  • Loading branch information
tclemos and agnusmor authored Feb 3, 2024
1 parent 284dda3 commit 95465ca
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 10 deletions.
4 changes: 2 additions & 2 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,6 @@ func waitSignal(cancelFuncs []context.CancelFunc) {
}

func newState(ctx context.Context, c *config.Config, etherman *etherman.Client, l2ChainID uint64, sqlDB *pgxpool.Pool, eventLog *event.EventLog, needsExecutor, needsStateTree, avoidForkIDInMemory bool) (*state.State, uint64) {
stateDb := pgstatestorage.NewPostgresStorage(c.State, sqlDB)

// Executor
var executorClient executor.ExecutorServiceClient
if needsExecutor {
Expand All @@ -482,6 +480,8 @@ func newState(ctx context.Context, c *config.Config, etherman *etherman.Client,
MaxNativeBlockHashBlockRange: c.RPC.MaxNativeBlockHashBlockRange,
AvoidForkIDInMemory: avoidForkIDInMemory,
}
stateDb := pgstatestorage.NewPostgresStorage(stateCfg, sqlDB)

allLeaves, err := stateDb.GetAllL1InfoRootEntries(ctx, nil)
if err != nil {
log.Fatal("error getting all leaves. Error: ", err)
Expand Down
6 changes: 4 additions & 2 deletions db/migrations/state/0009.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
ALTER TABLE IF EXISTS state.fork_id DROP CONSTRAINT IF EXISTS fork_id_block_num_fkey;

-- +migrate Down
DELETE FROM state.fork_id f
WHERE NOT EXISTS(SELECT 1 FROM state.block b WHERE b.block_num = f.block_num);

ALTER TABLE IF EXISTS state.fork_id ADD CONSTRAINT fork_id_block_num_fkey
FOREIGN KEY(block_num)
REFERENCES state.block (block_num) ON DELETE CASCADE;
FOREIGN KEY(block_num) REFERENCES state.block (block_num) ON DELETE CASCADE;
12 changes: 7 additions & 5 deletions state/pgstatestorage/forkid.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ func (p *PostgresStorage) AddForkIDInterval(ctx context.Context, newForkID state
var forkIDs []state.ForkIDInterval
forkIDs = oldForkIDs
// Check to detect forkID inconsistencies
if forkIDs[len(forkIDs)-1].ForkId+1 != newForkID.ForkId {
log.Errorf("error checking forkID sequence. Last ForkID stored: %d. New ForkID received: %d", forkIDs[len(forkIDs)-1].ForkId, newForkID.ForkId)
return fmt.Errorf("error checking forkID sequence. Last ForkID stored: %d. New ForkID received: %d", forkIDs[len(forkIDs)-1].ForkId, newForkID.ForkId)
if forkIDs[len(forkIDs)-1].ForkId >= newForkID.ForkId {
errMsg := "error checking forkID sequence. Last ForkID stored: %d. New ForkID received: %d"
err := fmt.Errorf(errMsg, forkIDs[len(forkIDs)-1].ForkId, newForkID.ForkId)
log.Errorf(err.Error())
return err
}
forkIDs[len(forkIDs)-1].ToBatchNumber = newForkID.FromBatchNumber - 1
err := p.UpdateForkID(ctx, forkIDs[len(forkIDs)-1], dbTx)
Expand All @@ -109,7 +111,7 @@ func (p *PostgresStorage) GetForkIDByBlockNumber(blockNumber uint64) uint64 {
const query = `
SELECT fork_id
FROM state.fork_id
WHERE block_num < $1
WHERE block_num <= $1
ORDER BY fork_id DESC
LIMIT 1`
q := p.getExecQuerier(nil)
Expand All @@ -134,7 +136,7 @@ func (p *PostgresStorage) GetForkIDByBlockNumberInMemory(blockNumber uint64) uin
for _, index := range sortIndexForForkdIDSortedByBlockNumber(p.cfg.ForkIDIntervals) {
// reverse travesal
interval := p.cfg.ForkIDIntervals[len(p.cfg.ForkIDIntervals)-1-index]
if blockNumber > interval.BlockNumber {
if blockNumber >= interval.BlockNumber {
return interval.ForkId
}
}
Expand Down
133 changes: 133 additions & 0 deletions state/pgstatestorage/forkid_external_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package pgstatestorage_test

import (
"context"
"fmt"
"testing"

"github.com/0xPolygonHermez/zkevm-node/state"
"github.com/0xPolygonHermez/zkevm-node/state/pgstatestorage"
"github.com/0xPolygonHermez/zkevm-node/test/dbutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAddForkIDInterval(t *testing.T) {
if err := dbutils.InitOrResetState(stateDBCfg); err != nil {
panic(err)
}
pgStateStorage = pgstatestorage.NewPostgresStorage(state.Config{}, stateDb)
testState = state.NewState(stateCfg, pgStateStorage, executorClient, stateTree, nil, nil)

for i := 1; i <= 6; i++ {
err = testState.AddForkID(ctx, state.ForkIDInterval{ForkId: uint64(i), BlockNumber: uint64(i * 100), FromBatchNumber: uint64(i * 10), ToBatchNumber: uint64(i*10) + 9}, nil)
require.NoError(t, err)
}

testCases := []struct {
name string
forkIDToAdd state.ForkIDInterval
expectedError error
}{
{
name: "fails to add because forkID already exists",
forkIDToAdd: state.ForkIDInterval{ForkId: 3},
expectedError: fmt.Errorf("error checking forkID sequence. Last ForkID stored: 6. New ForkID received: 3"),
},
{
name: "fails to add because forkID is smaller than the latest forkID",
forkIDToAdd: state.ForkIDInterval{ForkId: 5},
expectedError: fmt.Errorf("error checking forkID sequence. Last ForkID stored: 6. New ForkID received: 5"),
},
{
name: "fails to add because forkID is equal to the latest forkID",
forkIDToAdd: state.ForkIDInterval{ForkId: 6},
expectedError: fmt.Errorf("error checking forkID sequence. Last ForkID stored: 6. New ForkID received: 6"),
},
{
name: "adds successfully",
forkIDToAdd: state.ForkIDInterval{ForkId: 7},
expectedError: nil,
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
ctx := context.Background()
dbTx, err := testState.BeginStateTransaction(ctx)
require.NoError(t, err)

err = testState.AddForkIDInterval(ctx, tc.forkIDToAdd, dbTx)

if tc.expectedError == nil {
assert.Nil(t, err)
} else {
assert.Equal(t, tc.expectedError.Error(), err.Error())
}

require.NoError(t, dbTx.Commit(ctx))
})
}
}

func TestGetForkID(t *testing.T) {
if err := dbutils.InitOrResetState(stateDBCfg); err != nil {
panic(err)
}
pgStateStorage = pgstatestorage.NewPostgresStorage(stateCfg, stateDb)
testState = state.NewState(stateCfg, pgStateStorage, executorClient, stateTree, nil, nil)
st := state.NewState(stateCfg, pgstatestorage.NewPostgresStorage(stateCfg, stateDb), executorClient, stateTree, nil, nil)

avoidMemoryStateCfg := stateCfg
avoidMemoryStateCfg.AvoidForkIDInMemory = true
pgStateStorageAvoidMemory := pgstatestorage.NewPostgresStorage(avoidMemoryStateCfg, stateDb)
stAvoidMemory := state.NewState(avoidMemoryStateCfg, pgStateStorageAvoidMemory, executorClient, stateTree, nil, nil)

// persist forkID intervals
forkIdIntervals := []state.ForkIDInterval{}
for i := 1; i <= 6; i++ {
forkIDInterval := state.ForkIDInterval{ForkId: uint64(i), BlockNumber: uint64(i * 100), FromBatchNumber: uint64(i * 10), ToBatchNumber: uint64(i*10) + 9}
forkIdIntervals = append(forkIdIntervals, forkIDInterval)
err = testState.AddForkID(ctx, forkIDInterval, nil)
require.NoError(t, err)
}

// updates the memory with some of the forkIDs
forkIdIntervalsToAddInMemory := forkIdIntervals[0:3]
st.UpdateForkIDIntervalsInMemory(forkIdIntervalsToAddInMemory)
stAvoidMemory.UpdateForkIDIntervalsInMemory(forkIdIntervalsToAddInMemory)

// get forkID by blockNumber
forkIDFromMemory := st.GetForkIDByBlockNumber(500)
assert.Equal(t, uint64(3), forkIDFromMemory)

forkIDFromDB := stAvoidMemory.GetForkIDByBlockNumber(500)
assert.Equal(t, uint64(5), forkIDFromDB)

// get forkID by batchNumber
forkIDFromMemory = st.GetForkIDByBatchNumber(45)
assert.Equal(t, uint64(3), forkIDFromMemory)

forkIDFromDB = stAvoidMemory.GetForkIDByBatchNumber(45)
assert.Equal(t, uint64(4), forkIDFromDB)

// updates the memory with some of the forkIDs
forkIdIntervalsToAddInMemory = forkIdIntervals[0:6]
st.UpdateForkIDIntervalsInMemory(forkIdIntervalsToAddInMemory)
stAvoidMemory.UpdateForkIDIntervalsInMemory(forkIdIntervalsToAddInMemory)

// get forkID by blockNumber
forkIDFromMemory = st.GetForkIDByBlockNumber(500)
assert.Equal(t, uint64(5), forkIDFromMemory)

forkIDFromDB = stAvoidMemory.GetForkIDByBlockNumber(500)
assert.Equal(t, uint64(5), forkIDFromDB)

// get forkID by batchNumber
forkIDFromMemory = st.GetForkIDByBatchNumber(45)
assert.Equal(t, uint64(4), forkIDFromMemory)

forkIDFromDB = stAvoidMemory.GetForkIDByBatchNumber(45)
assert.Equal(t, uint64(4), forkIDFromDB)
}
2 changes: 1 addition & 1 deletion state/pgstatestorage/forkid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestGetForkIDByBlockNumber(t *testing.T) {
{
name: "Block number is equal to an interval",
blockNumber: 200,
expected: 1,
expected: 2,
},
{
name: "Block number is greater to an interval",
Expand Down

0 comments on commit 95465ca

Please sign in to comment.