Skip to content

Commit

Permalink
Acceptance/1.2.5.4 (#963)
Browse files Browse the repository at this point in the history
* Fix Exit Roots & Startup L1 Contract Address Check (#943)

* fix bug affecting gas prices and batchL2Data output (#962)

---------

Co-authored-by: Max Revitt <max.revitt@gmail.com>
  • Loading branch information
hexoscott and revitteth authored Aug 14, 2024
1 parent 01158ec commit de3d03f
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 59 deletions.
2 changes: 1 addition & 1 deletion cmd/rpcdaemon/commands/eth_receipts_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ func (api *APIImpl) addEffectiveGasPercentage(fields map[string]interface{}, tx
if err != nil {
return nil, err
}
fields["effectiveGasPrice"] = core.CalculateEffectiveGas(txn.GetPrice(), effectiveGasPricePercentage)
fields["effectiveGasPrice"] = core.CalculateEffectiveGas(txn.GetPrice().Clone(), effectiveGasPricePercentage)
return fields, nil
}
41 changes: 15 additions & 26 deletions cmd/rpcdaemon/commands/zkevm_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/ledgerwatch/erigon/zk/witness"
"github.com/ledgerwatch/erigon/zkevm/hex"
"github.com/ledgerwatch/erigon/zkevm/jsonrpc/client"
"github.com/ledgerwatch/log/v3"
)

var sha3UncleHash = common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
Expand Down Expand Up @@ -309,7 +310,6 @@ func (api *ZkEvmAPIImpl) GetBatchDataByNumbers(ctx context.Context, batchNumbers
return nil, err
}

// todo: max - take out shared logic with getBatchByNumber
// collect blocks in batch
var batchBlocks []*eritypes.Block
var batchTxs []eritypes.Transaction
Expand Down Expand Up @@ -405,7 +405,7 @@ func (api *ZkEvmAPIImpl) GetBatchByNumber(ctx context.Context, batchNumber rpc.B
hermezDb := hermez_db.NewHermezDbReader(tx)

// use inbuilt rpc.BlockNumber type to implement the 'latest' behaviour
// highest block/batch tied to last block synced
// the highest block/batch is tied to last block synced
// unless the node is still syncing - in which case 'current block' is used
// this is the batch number of stage progress of the Finish stage

Expand All @@ -420,12 +420,12 @@ func (api *ZkEvmAPIImpl) GetBatchByNumber(ctx context.Context, batchNumber rpc.B
}

// check sync status of node
syncing, err := api.ethApi.Syncing(ctx)
syncStatus, err := api.ethApi.Syncing(ctx)
if err != nil {
return nil, err
}
if syncing != nil && syncing != false {
bn := syncing.(map[string]interface{})["currentBlock"]
if _, ok := syncStatus.(bool); !ok {
bn := syncStatus.(map[string]interface{})["currentBlock"]
highestBatchNo, err = hermezDb.GetBatchNoByL2Block(uint64(bn.(hexutil.Uint64)))
}
if batchNumber > rpc.BlockNumber(highestBatchNo) {
Expand Down Expand Up @@ -605,27 +605,15 @@ func (api *ZkEvmAPIImpl) GetBatchByNumber(ctx context.Context, batchNumber rpc.B
}
if ver != nil {
batch.VerifyBatchTxHash = &ver.L1TxHash
}

verificationBatch := ver.BatchNo
verifiedBatchHighestBlock, err := hermezDb.GetHighestBlockInBatch(verificationBatch)
if err != nil {
return nil, err
}

verifiedBatchGer, err := hermezDb.GetBlockGlobalExitRoot(verifiedBatchHighestBlock)
if err != nil {
return nil, err
}

// exit roots (MainnetExitRoot, RollupExitRoot)
infoTreeUpdate, err := hermezDb.GetL1InfoTreeUpdateByGer(verifiedBatchGer)
if err != nil {
return nil, err
}
if infoTreeUpdate != nil {
batch.MainnetExitRoot = infoTreeUpdate.MainnetExitRoot
batch.RollupExitRoot = infoTreeUpdate.RollupExitRoot
}
itu, err := hermezDb.GetL1InfoTreeUpdateByGer(batchGer)
if err != nil {
return nil, err
}
if itu != nil {
batch.MainnetExitRoot = itu.MainnetExitRoot
batch.RollupExitRoot = itu.RollupExitRoot
}

// local exit root
Expand All @@ -649,7 +637,8 @@ func (api *ZkEvmAPIImpl) GetBatchByNumber(ctx context.Context, batchNumber rpc.B

oldAccInputHash, err := api.l1Syncer.GetOldAccInputHash(ctx, &api.config.AddressRollup, ApiRollupId, batchNo)
if err != nil {
return nil, err
log.Warn("Failed to get old acc input hash", "err", err)
batch.AccInputHash = common.Hash{}
}
batch.AccInputHash = oldAccInputHash

Expand Down
47 changes: 47 additions & 0 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,14 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
cfg.L1HighestBlockType,
)

// check contract addresses in config against L1
success, err := l1ContractAddressCheck(ctx, cfg.Zk, backend.l1Syncer)
if !success || err != nil {
//log.Warn("Contract address check failed", "success", success, "err", err)
panic("Contract address check failed")
}
log.Info("Contract address check passed")

l1InfoTreeSyncer := syncer.NewL1Syncer(
ctx,
ethermanClients,
Expand Down Expand Up @@ -1514,3 +1522,42 @@ func checkPortIsFree(addr string) (free bool) {
c.Close()
return false
}

func l1ContractAddressCheck(ctx context.Context, cfg *ethconfig.Zk, l1BlockSyncer *syncer.L1Syncer) (bool, error) {
l1AddrRollup, err := l1BlockSyncer.CallRollupManager(ctx, &cfg.AddressZkevm)
if err != nil {
return false, err
}
if l1AddrRollup != cfg.AddressRollup {
log.Warn("L1 contract address check failed (AddressRollup)", "expected", cfg.AddressRollup, "actual", l1AddrRollup)
return false, nil
}

l1AddrAdmin, err := l1BlockSyncer.CallAdmin(ctx, &cfg.AddressZkevm)
if err != nil {
return false, err
}
if l1AddrAdmin != cfg.AddressAdmin {
log.Warn("L1 contract address check failed (AddressAdmin)", "expected", cfg.AddressAdmin, "actual", l1AddrAdmin)
return false, nil
}

l1AddrGerManager, err := l1BlockSyncer.CallGlobalExitRootManager(ctx, &cfg.AddressZkevm)
if err != nil {
return false, err
}
if l1AddrGerManager != cfg.AddressGerManager {
log.Warn("L1 contract address check failed (AddressGerManager)", "expected", cfg.AddressGerManager, "actual", l1AddrGerManager)
return false, nil
}

l1AddrSequencer, err := l1BlockSyncer.CallTrustedSequencer(ctx, &cfg.AddressZkevm)
if err != nil {
return false, err
}
if l1AddrSequencer != cfg.AddressSequencer {
log.Warn("L1 contract address check failed (AddressSequencer)", "expected", cfg.AddressSequencer, "actual", l1AddrSequencer)
return false, nil
}
return true, nil
}
4 changes: 0 additions & 4 deletions zk/debug_tools/rpc-batch-compare/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@ func compareBatches(erigonURL, legacyURL string, batchNumber *big.Int) (string,
// ignore list
il := []string{
"timestamp",
"accInputHash",
"transactions",
"rollupExitRoot",
"mainnetExitRoot",
}
for _, i := range il {
delete(batch1, i)
Expand Down
13 changes: 10 additions & 3 deletions zk/stages/stage_l1syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func SpawnStageL1Syncer(

newVerificationsCount := 0
newSequencesCount := 0
highestWrittenL1BlockNo := uint64(0)
Loop:
for {
select {
Expand All @@ -142,6 +143,9 @@ Loop:
if err := hermezDb.WriteSequence(info.L1BlockNo, info.BatchNo, info.L1TxHash, info.StateRoot); err != nil {
return fmt.Errorf("failed to write batch info, %w", err)
}
if info.L1BlockNo > highestWrittenL1BlockNo {
highestWrittenL1BlockNo = info.L1BlockNo
}
newSequencesCount++
case logVerify:
if info.BatchNo > highestVerification.BatchNo {
Expand All @@ -150,6 +154,9 @@ Loop:
if err := hermezDb.WriteVerification(info.L1BlockNo, info.BatchNo, info.L1TxHash, info.StateRoot); err != nil {
return fmt.Errorf("failed to write verification for block %d, %w", info.L1BlockNo, err)
}
if info.L1BlockNo > highestWrittenL1BlockNo {
highestWrittenL1BlockNo = info.L1BlockNo
}
newVerificationsCount++
case logIncompatible:
continue
Expand All @@ -168,10 +175,10 @@ Loop:
}

latestCheckedBlock := cfg.syncer.GetLastCheckedL1Block()
if latestCheckedBlock > l1BlockProgress {
log.Info(fmt.Sprintf("[%s] Saving L1 syncer progress", logPrefix), "latestCheckedBlock", latestCheckedBlock, "newVerificationsCount", newVerificationsCount, "newSequencesCount", newSequencesCount)
if highestWrittenL1BlockNo > l1BlockProgress {
log.Info(fmt.Sprintf("[%s] Saving L1 syncer progress", logPrefix), "latestCheckedBlock", latestCheckedBlock, "newVerificationsCount", newVerificationsCount, "newSequencesCount", newSequencesCount, "highestWrittenL1BlockNo", highestWrittenL1BlockNo)

if err := stages.SaveStageProgress(tx, stages.L1Syncer, latestCheckedBlock); err != nil {
if err := stages.SaveStageProgress(tx, stages.L1Syncer, highestWrittenL1BlockNo); err != nil {
return fmt.Errorf("failed to save stage progress, %w", err)
}
if highestVerification.BatchNo > 0 {
Expand Down
38 changes: 38 additions & 0 deletions zk/syncer/l1_syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ var errorShortResponseLT32 = fmt.Errorf("response too short to contain hash data
var errorShortResponseLT96 = fmt.Errorf("response too short to contain last batch number data")

const rollupSequencedBatchesSignature = "0x25280169" // hardcoded abi signature
const globalExitRootManager = "0xd02103ca"
const rollupManager = "0x49b7b802"
const admin = "0xf851a440"
const trustedSequencer = "0xcfa8ed47"

type IEtherman interface {
HeaderByNumber(ctx context.Context, blockNumber *big.Int) (*ethTypes.Header, error)
Expand Down Expand Up @@ -455,3 +459,37 @@ func (s *L1Syncer) callGetRollupSequencedBatches(ctx context.Context, addr *comm

return h, lastBatchNumber, nil
}

func (s *L1Syncer) CallAdmin(ctx context.Context, addr *common.Address) (common.Address, error) {
return s.callGetAddress(ctx, addr, admin)
}

func (s *L1Syncer) CallRollupManager(ctx context.Context, addr *common.Address) (common.Address, error) {
return s.callGetAddress(ctx, addr, rollupManager)
}

func (s *L1Syncer) CallGlobalExitRootManager(ctx context.Context, addr *common.Address) (common.Address, error) {
return s.callGetAddress(ctx, addr, globalExitRootManager)
}

func (s *L1Syncer) CallTrustedSequencer(ctx context.Context, addr *common.Address) (common.Address, error) {
return s.callGetAddress(ctx, addr, trustedSequencer)
}

func (s *L1Syncer) callGetAddress(ctx context.Context, addr *common.Address, data string) (common.Address, error) {
em := s.getNextEtherman()
resp, err := em.CallContract(ctx, ethereum.CallMsg{
To: addr,
Data: common.FromHex(data),
}, nil)

if err != nil {
return common.Address{}, err
}

if len(resp) < 20 {
return common.Address{}, errorShortResponseLT32
}

return common.BytesToAddress(resp[len(resp)-20:]), nil
}
36 changes: 11 additions & 25 deletions zk/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package utils

import (
"fmt"

libcommon "github.com/gateway-fm/cdk-erigon-lib/common"
"github.com/gateway-fm/cdk-erigon-lib/kv"
"github.com/ledgerwatch/erigon/chain"
"github.com/ledgerwatch/erigon/core/state"
"github.com/ledgerwatch/erigon/core/systemcontracts"
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
"github.com/ledgerwatch/erigon/zk/constants"
"github.com/ledgerwatch/erigon/zk/hermez_db"
Expand Down Expand Up @@ -146,33 +146,19 @@ func GetBatchLocalExitRoot(batchNo uint64, db DbReader, tx kv.Tx) (libcommon.Has
}

func GetBatchLocalExitRootFromSCStorage(batchNo uint64, db DbReader, tx kv.Tx) (libcommon.Hash, error) {
var localExitRoot libcommon.Hash

if batchNo > 0 {
checkBatch := batchNo

stateReader := state.NewPlainStateReadAccountStorage(tx, 0)
defer stateReader.Close()

for ; checkBatch > 0; checkBatch-- {
blockNo, err := db.GetHighestBlockInBatch(checkBatch)
if err != nil {
return libcommon.Hash{}, err
}
blockNo, err := db.GetHighestBlockInBatch(batchNo)
if err != nil {
return libcommon.Hash{}, err
}

// stateReader := state.NewPlainStateReadAccountStorage(tx, blockNo)
// defer stateReader.Close()
stateReader.SetBlockNr(blockNo)
rawLer, err := stateReader.ReadAccountStorage(state.GER_MANAGER_ADDRESS, 1, &state.GLOBAL_EXIT_ROOT_POS_1)
if err != nil {
return libcommon.Hash{}, err
}
localExitRoot = libcommon.BytesToHash(rawLer)
if localExitRoot != (libcommon.Hash{}) {
break
}
stateReader := state.NewPlainState(tx, blockNo+1, systemcontracts.SystemContractCodeLookup["hermez"])
rawLer, err := stateReader.ReadAccountStorage(state.GER_MANAGER_ADDRESS, 1, &state.GLOBAL_EXIT_ROOT_POS_1)
if err != nil {
return libcommon.Hash{}, err
}
return libcommon.BytesToHash(rawLer), nil
}

return localExitRoot, nil
return libcommon.Hash{}, nil
}

0 comments on commit de3d03f

Please sign in to comment.