Skip to content

Commit

Permalink
Fix/3164 eth syncing dont return expected values (0xPolygonHermez#3165)…
Browse files Browse the repository at this point in the history
  • Loading branch information
joanestebanr authored Feb 6, 2024
1 parent d6d4b96 commit 1dfa467
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 65 deletions.
36 changes: 33 additions & 3 deletions jsonrpc/endpoints_eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,23 @@ func (e *EthEndpoints) getPriceFromSequencerNode() (interface{}, types.Error) {
return gasPrice, nil
}

func (e *EthEndpoints) getHighestL2BlockFromTrustedNode() (interface{}, types.Error) {
res, err := client.JSONRPCCall(e.cfg.SequencerNodeURI, "eth_blockNumber")
if err != nil {
return RPCErrorResponse(types.DefaultErrorCode, "failed to get gas price from sequencer node", err, true)
}

if res.Error != nil {
return RPCErrorResponse(res.Error.Code, res.Error.Message, nil, false)
}
var highestBlockNum types.ArgUint64
err = json.Unmarshal(res.Result, &highestBlockNum)
if err != nil {
return RPCErrorResponse(types.DefaultErrorCode, "failed to read eth_blockNumber from sequencer node", err, true)
}
return uint64(highestBlockNum), nil
}

// GetBalance returns the account's balance at the referenced block
func (e *EthEndpoints) GetBalance(address types.ArgAddress, blockArg *types.BlockNumberOrHash) (interface{}, types.Error) {
return e.txMan.NewDbTxScope(e.state, func(ctx context.Context, dbTx pgx.Tx) (interface{}, types.Error) {
Expand Down Expand Up @@ -992,18 +1009,31 @@ func (e *EthEndpoints) Syncing() (interface{}, types.Error) {
return RPCErrorResponse(types.DefaultErrorCode, "failed to get syncing info from state", err, true)
}

if syncInfo.CurrentBlockNumber >= syncInfo.LastBlockNumberSeen {
if !syncInfo.IsSynchronizing {
return false, nil
}

if e.cfg.SequencerNodeURI != "" {
// If we have a trusted node we ask it for the highest l2 block
res, err := e.getHighestL2BlockFromTrustedNode()
if err != nil {
log.Warnf("failed to get highest l2 block from trusted node: %v", err)
} else {
highestL2BlockInTrusted := res.(uint64)
if highestL2BlockInTrusted > syncInfo.CurrentBlockNumber {
syncInfo.EstimatedHighestBlock = highestL2BlockInTrusted
} else {
log.Warnf("highest l2 block in trusted node (%d) is lower than the current block number in the state (%d)", highestL2BlockInTrusted, syncInfo.CurrentBlockNumber)
}
}
}
return struct {
S types.ArgUint64 `json:"startingBlock"`
C types.ArgUint64 `json:"currentBlock"`
H types.ArgUint64 `json:"highestBlock"`
}{
S: types.ArgUint64(syncInfo.InitialSyncingBlock),
C: types.ArgUint64(syncInfo.CurrentBlockNumber),
H: types.ArgUint64(syncInfo.LastBlockNumberSeen),
H: types.ArgUint64(syncInfo.EstimatedHighestBlock),
}, nil
})
}
Expand Down
6 changes: 3 additions & 3 deletions jsonrpc/endpoints_eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2083,7 +2083,7 @@ func TestSyncing(t *testing.T) {

m.State.
On("GetSyncingInfo", context.Background(), m.DbTx).
Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 2, LastBlockNumberSeen: 3, LastBlockNumberConsolidated: 3}, nil).
Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 2, EstimatedHighestBlock: 3, IsSynchronizing: true}, nil).
Once()
},
},
Expand All @@ -2109,7 +2109,7 @@ func TestSyncing(t *testing.T) {

m.State.
On("GetSyncingInfo", context.Background(), m.DbTx).
Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 1, LastBlockNumberSeen: 1, LastBlockNumberConsolidated: 1}, nil).
Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 1, EstimatedHighestBlock: 3, IsSynchronizing: false}, nil).
Once()
},
},
Expand All @@ -2135,7 +2135,7 @@ func TestSyncing(t *testing.T) {

m.State.
On("GetSyncingInfo", context.Background(), m.DbTx).
Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 2, LastBlockNumberSeen: 1, LastBlockNumberConsolidated: 1}, nil).
Return(state.SyncingInfo{InitialSyncingBlock: 1, CurrentBlockNumber: 2, EstimatedHighestBlock: 3, IsSynchronizing: false}, nil).
Once()
},
},
Expand Down
3 changes: 2 additions & 1 deletion state/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ type storage interface {
IsL2BlockConsolidated(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error)
IsL2BlockVirtualized(ctx context.Context, blockNumber uint64, dbTx pgx.Tx) (bool, error)
GetLogs(ctx context.Context, fromBlock uint64, toBlock uint64, addresses []common.Address, topics [][]common.Hash, blockHash *common.Hash, since *time.Time, dbTx pgx.Tx) ([]*types.Log, error)
GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (SyncingInfo, error)
AddReceipt(ctx context.Context, receipt *types.Receipt, dbTx pgx.Tx) error
AddLog(ctx context.Context, l *types.Log, dbTx pgx.Tx) error
GetExitRootByGlobalExitRoot(ctx context.Context, ger common.Hash, dbTx pgx.Tx) (*GlobalExitRoot, error)
Expand Down Expand Up @@ -151,5 +150,7 @@ type storage interface {
GetForcedBatchParentHash(ctx context.Context, forcedBatchNumber uint64, dbTx pgx.Tx) (common.Hash, error)
GetLatestBatchGlobalExitRoot(ctx context.Context, dbTx pgx.Tx) (common.Hash, error)
GetL2TxHashByTxHash(ctx context.Context, hash common.Hash, dbTx pgx.Tx) (common.Hash, error)
GetSyncInfoData(ctx context.Context, dbTx pgx.Tx) (SyncInfoDataOnStorage, error)
GetFirstL2BlockNumberForBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (uint64, error)
GetForkIDInMemory(forkId uint64) *ForkIDInterval
}
88 changes: 73 additions & 15 deletions state/mocks/mock_storage.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions state/pgstatestorage/l2block.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,3 +517,23 @@ func buildBlock(header *state.L2Header, transactions []*types.Transaction, uncle

return l2Block
}

func (p *PostgresStorage) GetFirstL2BlockNumberForBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (uint64, error) {
const getL2BlockNumSQL = `
select MIN(block_num)
FROM state.l2block
WHERE batch_num = $1;
`

q := p.getExecQuerier(dbTx)
row := q.QueryRow(ctx, getL2BlockNumSQL, batchNumber)
var l2BlockNumber uint64
err := row.Scan(&l2BlockNumber)
if errors.Is(err, pgx.ErrNoRows) {
return 0, state.ErrNotFound
} else if err != nil {
return 0, err
}

return l2BlockNumber, nil
}
48 changes: 12 additions & 36 deletions state/pgstatestorage/syncinginfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,24 @@ package pgstatestorage

import (
"context"
"errors"

"github.com/0xPolygonHermez/zkevm-node/state"
"github.com/jackc/pgx/v4"
)

// GetSyncingInfo returns information regarding the syncing status of the node
func (p *PostgresStorage) GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (state.SyncingInfo, error) {
var info state.SyncingInfo
const getSyncingInfoSQL = `
SELECT coalesce(MIN(initial_blocks.block_num), 0) as init_sync_block
, coalesce(MAX(virtual_blocks.block_num), 0) as last_block_num_seen
, coalesce(MAX(consolidated_blocks.block_num), 0) as last_block_num_consolidated
, coalesce(MIN(sy.init_sync_batch), 0) as init_sync_batch
, coalesce(MIN(sy.last_batch_num_seen), 0) as last_batch_num_seen
, coalesce(MIN(sy.last_batch_num_consolidated), 0) as last_batch_num_consolidated
FROM state.sync_info sy
INNER JOIN state.l2block initial_blocks
ON initial_blocks.batch_num = sy.init_sync_batch
INNER JOIN state.l2block virtual_blocks
ON virtual_blocks.batch_num = sy.last_batch_num_seen
INNER JOIN state.l2block consolidated_blocks
ON consolidated_blocks.batch_num = sy.last_batch_num_consolidated;
func (p *PostgresStorage) GetSyncInfoData(ctx context.Context, dbTx pgx.Tx) (state.SyncInfoDataOnStorage, error) {
var info state.SyncInfoDataOnStorage
const getSyncTableSQL = `
select last_batch_num_seen, last_batch_num_consolidated, init_sync_batch from state.sync_info;
`
q := p.getExecQuerier(dbTx)
err := q.QueryRow(ctx, getSyncingInfoSQL).
Scan(&info.InitialSyncingBlock, &info.LastBlockNumberSeen, &info.LastBlockNumberConsolidated,
&info.InitialSyncingBatch, &info.LastBatchNumberSeen, &info.LastBatchNumberConsolidated)
if err != nil {
return state.SyncingInfo{}, nil
row := q.QueryRow(ctx, getSyncTableSQL)
err := row.Scan(&info.LastBatchNumberSeen, &info.LastBatchNumberConsolidated, &info.InitialSyncingBatch)
if errors.Is(err, pgx.ErrNoRows) {
return state.SyncInfoDataOnStorage{}, state.ErrNotFound
} else if err != nil {
return state.SyncInfoDataOnStorage{}, err
}

lastBlockNumber, err := p.GetLastL2BlockNumber(ctx, dbTx)
if err != nil {
return state.SyncingInfo{}, nil
}
info.CurrentBlockNumber = lastBlockNumber

lastBatchNumber, err := p.GetLastBatchNumber(ctx, dbTx)
if err != nil {
return state.SyncingInfo{}, nil
}
info.CurrentBatchNumber = lastBatchNumber

return info, err
return info, nil
}
64 changes: 57 additions & 7 deletions state/syncinginfo.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,64 @@
package state

// SyncingInfo stores information regarding the syncing status of the node
type SyncingInfo struct {
InitialSyncingBlock uint64
LastBlockNumberSeen uint64
LastBlockNumberConsolidated uint64
CurrentBlockNumber uint64
import (
"context"
"errors"

"github.com/jackc/pgx/v4"
)

// SyncInfoDataOnStorage stores information regarding the syncing status of the node in the database
type SyncInfoDataOnStorage struct {
InitialSyncingBatch uint64
LastBatchNumberSeen uint64
LastBatchNumberConsolidated uint64
CurrentBatchNumber uint64
}

// SyncingInfo stores information regarding the syncing status of the node
type SyncingInfo struct {
InitialSyncingBlock uint64 // L2Block corresponding to InitialSyncingBatch
CurrentBlockNumber uint64 // last L2Block in state
EstimatedHighestBlock uint64 // estimated highest L2Block in state

// IsSynchronizing indicates if the node is syncing (true -> syncing, false -> fully synced)
IsSynchronizing bool
}

// GetSyncingInfo returns information regarding the syncing status of the node
func (p *State) GetSyncingInfo(ctx context.Context, dbTx pgx.Tx) (SyncingInfo, error) {
var info SyncingInfo

syncData, err := p.GetSyncInfoData(ctx, dbTx)
if errors.Is(err, ErrNotFound) {
return SyncingInfo{}, ErrStateNotSynchronized
} else if err != nil {
return SyncingInfo{}, err
}

info.InitialSyncingBlock, err = p.GetFirstL2BlockNumberForBatchNumber(ctx, syncData.InitialSyncingBatch, dbTx)
if errors.Is(err, ErrNotFound) {
return SyncingInfo{}, ErrStateNotSynchronized
} else if err != nil {
return SyncingInfo{}, err
}

lastBlockNumber, err := p.GetLastL2BlockNumber(ctx, dbTx)
if errors.Is(err, ErrNotFound) {
return SyncingInfo{}, ErrStateNotSynchronized
} else if err != nil {
return SyncingInfo{}, err
}
info.CurrentBlockNumber = lastBlockNumber

lastBatchNumber, err := p.GetLastBatchNumber(ctx, dbTx)
if errors.Is(err, ErrNotFound) {
return SyncingInfo{}, ErrStateNotSynchronized
} else if err != nil {
return SyncingInfo{}, err
}

info.EstimatedHighestBlock = ^uint64(0)
info.IsSynchronizing = syncData.LastBatchNumberSeen > lastBatchNumber

return info, nil
}
Loading

0 comments on commit 1dfa467

Please sign in to comment.