error: latest Synced BlockNumber (7089137) is higher than the latest Proposed block (1008) in the network
问题
cdk 跨链桥启动后,发起一笔跨链复现networkID数据错乱,重启后报错
2024-11-16T14:36:29.512Z INFO cmd/run.go:59 main network id: 0 {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.512Z INFO cmd/run.go:64 l2 network id: 0 {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.542Z DEBUG cmd/run.go:102 trusted sequencer URL http://172.18.39.103:8123 {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.542Z INFO server/server.go:93 gRPC Server is serving at 9090 {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.542Z INFO server/server.go:166 Restful Server is serving at 8080 {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.548Z INFO synchronizer/synchronizer.go:104 NetworkID: 0, Synchronization started {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.549Z DEBUG synchronizer/synchronizer.go:119 NetworkID: 0, initial lastBlockSynced: &{ID:3 BlockNumber:7089137 BlockHash:0xbcb0638af2a8014b561ee72c2f568bda819039ca93f16c7de22896fc1037c1a3 ParentHash:0x919c0185dfa6dbc92fb9e13f535c09130d04d1f980749b952b057ffed68f77b6 NetworkID:0 GlobalExitRoots:[] Deposits:[] Claims:[] Tokens:[] VerifiedBatches:[] ActivateEtrog:[] ReceivedAt:2024-11-16 13:48:00 +0000 UTC} {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.549Z DEBUG synchronizer/synchronizer.go:126 NetworkID: 0, syncing... {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.550Z INFO synchronizer/synchronizer.go:543 NetworkID: 0, [checkReorg function] Checking Block 7089137 in L1 {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:36:29.553Z ERROR synchronizer/synchronizer.go:546 networkID: 0, error getting latest block synced from blockchain. Block: 7089137, error: Not found%!(EXTRA string=
/src/log/log.go:142 github.com/0xPolygonHermez/zkevm-bridge-service/log.appendStackTraceMaybeArgs()
/src/log/log.go:251 github.com/0xPolygonHermez/zkevm-bridge-service/log.Errorf()
/src/synchronizer/synchronizer.go:546 github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).checkReorg()
/src/synchronizer/synchronizer.go:239 github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).syncBlocks()
/src/synchronizer/synchronizer.go:128 github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).Sync()
/src/cmd/run.go:245 main.runSynchronizer()
) {"pid": 1, "version": "v0.6.0-RC1"}
github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).checkReorg
/src/synchronizer/synchronizer.go:546
github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).syncBlocks
/src/synchronizer/synchronizer.go:239
github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).Sync
/src/synchronizer/synchronizer.go:128
main.runSynchronizer
/src/cmd/run.go:245
2024-11-16T14:36:29.553Z ERROR synchronizer/synchronizer.go:241 networkID: 0, error checking reorgs. Retrying... Err: Not found {"pid": 1, "version": "v0.6.0-RC1"}
github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).syncBlocks
/src/synchronizer/synchronizer.go:241
github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).Sync
/src/synchronizer/synchronizer.go:128
main.runSynchronizer
/src/cmd/run.go:245
2024-11-16T14:36:29.553Z WARN synchronizer/synchronizer.go:129 networkID: 0, error syncing blocks: networkID: 0, error checking reorgs {"pid": 1, "version": "v0.6.0-RC1"}
github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).Sync
/src/synchronizer/synchronizer.go:129
main.runSynchronizer
/src/cmd/run.go:245
2024-11-16T14:36:29.554Z FATAL synchronizer/synchronizer.go:161 networkID: 0, error: latest Synced BlockNumber (7089137) is higher than the latest Proposed block (1008) in the network {"pid": 1, "version": "v0.6.0-RC1"}
github.com/0xPolygonHermez/zkevm-bridge-service/synchronizer.(*ClientSynchronizer).Sync
/src/synchronizer/synchronizer.go:161
main.runSynchronizer
/src/cmd/run.go:245
2024-11-16T14:37:29.896Z INFO cmd/run.go:26 Starting application {"pid": 1, "version": "v0.6.0-RC1", "gitRevision": "002f436", "gitBranch": "HEAD", "goVersion": "go1.21.13", "built": "Thu, 26 Sep 2024 10:05:53 +0000", "os/arch": "linux/amd64"}
2024-11-16T14:37:29.915Z INFO pgstorage/utils.go:63 successfully ran 0 migrations {"pid": 1, "version": "v0.6.0-RC1"}
2024-11-16T14:37:29.923Z WARN etherman/etherman.go:187 Claim compressor Address not configured {"pid": 1, "version": "v0.6.0-RC1"}
github.com/0xPolygonHermez/zkevm-bridge-service/etherman.NewL2Client
/src/etherman/etherman.go:187
main.newEthermans
/src/cmd/run.go:230
main.start
/src/cmd/run.go:52
github.com/urfave/cli/v2.(*Command).Run
/go/pkg/mod/github.com/urfave/cli/v2@v2.27.4/command.go:276
github.com/urfave/cli/v2.(*Command).Run
/go/pkg/mod/github.com/urfave/cli/v2@v2.27.4/command.go:269
github.com/urfave/cli/v2.(*App).RunContext
/go/pkg/mod/github.com/urfave/cli/v2@v2.27.4/app.go:333
github.com/urfave/cli/v2.(*App).Run
/go/pkg/mod/github.com/urfave/cli/v2@v2.27.4/app.go:307
main.main
/src/cmd/main.go:56
runtime.main
/usr/local/go/src/runtime/proc.go:267
func (s *ClientSynchronizer) Sync() error {
lastBlockSynced, err := s.storage.GetLastBlock(s.ctx, s.networkID, nil)
....
if !s.synced {
// Check latest Block
header, err := s.etherMan.HeaderByNumber(s.ctx, nil)
if err != nil {
log.Warnf("networkID: %d, error getting latest block from. Error: %s", s.networkID, err.Error())
continue
}
lastKnownBlock := header.Number.Uint64()
if lastBlockSynced.BlockNumber == lastKnownBlock && !s.synced {
log.Infof("NetworkID %d Synced!", s.networkID)
waitDuration = s.cfg.SyncInterval.Duration
s.synced = true
s.chSynced <- s.networkID
}
if lastBlockSynced.BlockNumber > lastKnownBlock {
if s.networkID == 0 {
log.Fatalf("networkID: %d, error: latest Synced BlockNumber (%d) is higher than the latest Proposed block (%d) in the network", s.networkID, lastBlockSynced.BlockNumber, lastKnownBlock)
}
lastBlockSynced = 7089137
lastKnownBlock = 1008
lastBlockSynced为L1数据,lastKnownBlock为L2数据,说明s.etherMan应使用L1 RPC,目前使用了L2RPC导致出错
s.storage.GetLastBlock查询时有networkID区分,所以被对比数据是正确的
s.networkID等于0, s.etherMan使用的L2 RPC, 也就是networkID与etherMan对应关系乱了
func runSynchronizer(ctx context.Context, genBlockNumber uint64, brdigeCtrl *bridgectrl.BridgeController, etherman *etherman.Client, cfg synchronizer.Config, storage db.Storage, zkEVMClient *client.Client, chExitRootEventL2 chan *etherman.GlobalExitRoot, chsExitRootEvent []chan *etherman.GlobalExitRoot, chSynced chan uint, allNetworkIDs []uint) {
sy, err := synchronizer.NewSynchronizer(ctx, storage, brdigeCtrl, etherman, zkEVMClient, genBlockNumber, chExitRootEventL2, chsExitRootEvent, chSynced, cfg, allNetworkIDs)
if err != nil {
log.Fatal(err)
}
if err := sy.Sync(); err != nil {
log.Fatal(err)
}
}
for i, l2EthermanClient := range l2Ethermans {
log.Debug("trusted sequencer URL ", c.Etherman.L2URLs[i])
zkEVMClient := client.NewClient(c.Etherman.L2URLs[i])
chExitRootEventL2 := make(chan *etherman.GlobalExitRoot)
chSyncedL2 := make(chan uint)
chsExitRootEvent = append(chsExitRootEvent, chExitRootEventL2)
chsSyncedL2 = append(chsSyncedL2, chSyncedL2)
go runSynchronizer(ctx.Context, 0, bridgeController, l2EthermanClient, c.Synchronizer, storage, zkEVMClient, chExitRootEventL2, nil, chSyncedL2, []uint{})
}
chSynced := make(chan uint)
go runSynchronizer(ctx.Context, c.NetworkConfig.GenBlockNumber, bridgeController, l1Etherman, c.Synchronizer, storage, nil, nil, chsExitRootEvent, chSynced, networkIDs)
func newEthermans(c *config.Config) (*etherman.Client, []*etherman.Client, error) {
l1Etherman, err := etherman.NewClient(c.Etherman,
c.NetworkConfig.PolygonBridgeAddress,
c.NetworkConfig.PolygonZkEVMGlobalExitRootAddress,
c.NetworkConfig.PolygonRollupManagerAddress)
if err != nil {
log.Error("L1 etherman error: ", err)
return nil, nil, err
}
if len(c.L2PolygonBridgeAddresses) != len(c.Etherman.L2URLs) {
log.Fatal("environment configuration error. zkevm bridge addresses and zkevm node urls mismatch")
}
var l2Ethermans []*etherman.Client
for i, addr := range c.L2PolygonBridgeAddresses {
l2Etherman, err := etherman.NewL2Client(c.Etherman.L2URLs[i], addr, c.NetworkConfig.L2ClaimCompressorAddress)
if err != nil {
log.Error("L2 etherman ", i, c.Etherman.L2URLs[i], ", error: ", err)
return l1Etherman, nil, err
}
l2Ethermans = append(l2Ethermans, l2Etherman)
}
return l1Etherman, l2Ethermans, nil
}
对于l1Etherman networkID直接没有赋值,所以等于0
func NewClient(cfg Config, polygonBridgeAddr, polygonZkEVMGlobalExitRootAddress, polygonRollupManagerAddress common.Address) (*Client, error) {
logger := log.WithFields("networkID", 0)
// Connect to ethereum node
ethClient, err := ethclient.Dial(cfg.L1URL)
对于l2Etherman,经过NewL2Client
func NewL2Client(url string, polygonBridgeAddr, claimCompressorAddress common.Address) (*Client, error) {
// Connect to ethereum node
ethClient, err := ethclient.Dial(url)
if err != nil {
log.Errorf("error connecting to %s: %+v", url, err)
return nil, err
}
// Create smc clients
bridge, err := polygonzkevmbridge.NewPolygonzkevmbridge(polygonBridgeAddr, ethClient)
if err != nil {
return nil, err
}
oldpolygonBridge, err := oldpolygonzkevmbridge.NewOldpolygonzkevmbridge(polygonBridgeAddr, ethClient)
if err != nil {
return nil, err
}
var claimCompressor *claimcompressor.Claimcompressor
if claimCompressorAddress == (common.Address{}) {
log.Warn("Claim compressor Address not configured")
} else {
log.Infof("Grouping claims allowed, claimCompressor=%s", claimCompressorAddress.String())
claimCompressor, err = claimcompressor.NewClaimcompressor(claimCompressorAddress, ethClient)
if err != nil {
log.Errorf("error creating claimCompressor: %+v", err)
return nil, err
}
}
networkID, err := bridge.NetworkID(&bind.CallOpts{Pending: false}) // 从合约读取
if err != nil {
return nil, err
}
scAddresses := []common.Address{polygonBridgeAddr}
logger := log.WithFields("networkID", networkID)
return &Client{
logger: logger,
EtherClient: ethClient,
PolygonBridge: bridge,
OldPolygonBridge: oldpolygonBridge,
SCAddresses: scAddresses,
ClaimCompressor: claimCompressor,
NetworkID: networkID,
}, nil
}
对于L2 会使用对应的L2 RPC从二层桥合约读取对应的NetworkID
// Solidity: function networkID() view returns(uint32)
func (_Polygonzkevmbridge *PolygonzkevmbridgeCaller) NetworkID(opts *bind.CallOpts) (uint32, error) {
var out []interface{}
err := _Polygonzkevmbridge.contract.Call(opts, &out, "networkID")
if err != nil {
return *new(uint32), err
}
out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32)
return out0, err
}
查询二层networkID,确实是0
目前的问题就是因为二层桥合约错误的设置了networkID,导致逻辑错乱,进一步分析下,二层networkID什么时候设置的,如何导致的错误
经过确认,PolygonZkEVMBridgeV2合约没有初始化
结论
经过确认和重置对比测试,该错误是因为当时部署时RPC不稳定造成的交易丢失,所以部署时尽量选择稳定的RPC以及对应链相对空闲时段部署,并且部署完成后检查一下L2的networkID是否为1