diff --git a/command/genesis/genesis.go b/command/genesis/genesis.go index 8ddb22021a..c07456df1b 100644 --- a/command/genesis/genesis.go +++ b/command/genesis/genesis.go @@ -263,6 +263,13 @@ func setFlags(cmd *cobra.Command) { command.DefaultGenesisBaseFeeChangeDenom, "default base fee change denominator the value to bound the amount the base fee can change between blocks.", ) + + cmd.Flags().DurationVar( + ¶ms.blockTrackerPollInterval, + blockTrackerPollIntervalFlag, + defaultBlockTrackerPollInterval, + "interval (number of seconds) at which block tracker polls for latest block at rootchain", + ) } // Governance diff --git a/command/genesis/params.go b/command/genesis/params.go index 179fb20338..27ac19d513 100644 --- a/command/genesis/params.go +++ b/command/genesis/params.go @@ -26,29 +26,30 @@ import ( ) const ( - dirFlag = "dir" - nameFlag = "name" - premineFlag = "premine" - chainIDFlag = "chain-id" - epochSizeFlag = "epoch-size" - epochRewardFlag = "epoch-reward" - blockGasLimitFlag = "block-gas-limit" - burnContractFlag = "burn-contract" - posFlag = "pos" - minValidatorCount = "min-validator-count" - maxValidatorCount = "max-validator-count" - nativeTokenConfigFlag = "native-token-config" - rewardTokenCodeFlag = "reward-token-code" - rewardWalletFlag = "reward-wallet" - checkpointIntervalFlag = "checkpoint-interval" - withdrawalWaitPeriodFlag = "withdrawal-wait-period" - baseFeeChangeDenomFlag = "base-fee-change-denom" - voteDelayFlag = "vote-delay" - votePeriodFlag = "vote-period" - voteProposalThresholdFlag = "vote-proposal-threshold" - governorAdminFlag = "governor-admin" - proposalQuorumFlag = "proposal-quorum" - proxyContractsAdminFlag = "proxy-contracts-admin" + dirFlag = "dir" + nameFlag = "name" + premineFlag = "premine" + chainIDFlag = "chain-id" + epochSizeFlag = "epoch-size" + epochRewardFlag = "epoch-reward" + blockGasLimitFlag = "block-gas-limit" + burnContractFlag = "burn-contract" + posFlag = "pos" + minValidatorCount = "min-validator-count" + maxValidatorCount = "max-validator-count" + nativeTokenConfigFlag = "native-token-config" + rewardTokenCodeFlag = "reward-token-code" + rewardWalletFlag = "reward-wallet" + checkpointIntervalFlag = "checkpoint-interval" + withdrawalWaitPeriodFlag = "withdrawal-wait-period" + baseFeeChangeDenomFlag = "base-fee-change-denom" + voteDelayFlag = "vote-delay" + votePeriodFlag = "vote-period" + voteProposalThresholdFlag = "vote-proposal-threshold" + governorAdminFlag = "governor-admin" + proposalQuorumFlag = "proposal-quorum" + proxyContractsAdminFlag = "proxy-contracts-admin" + blockTrackerPollIntervalFlag = "block-tracker-poll-interval" defaultNativeTokenName = "Polygon" defaultNativeTokenSymbol = "MATIC" @@ -76,6 +77,7 @@ var ( errInvalidVotingPeriod = errors.New("voting period can not be zero") errInvalidGovernorAdmin = errors.New("governor admin address must be defined") errBaseFeeChangeDenomZero = errors.New("base fee change denominator must be greater than 0") + errBlockTrackerPollInterval = errors.New("block tracker poll interval must be greater than 0") ) type genesisParams struct { @@ -156,7 +158,8 @@ type genesisParams struct { proposalQuorum uint64 governorAdmin string - proxyContractsAdmin string + proxyContractsAdmin string + blockTrackerPollInterval time.Duration } func (p *genesisParams) validateFlags() error { @@ -204,6 +207,10 @@ func (p *genesisParams) validateFlags() error { if err := p.validateProxyContractsAdmin(); err != nil { return err } + + if err := p.validateBlockTrackerPollInterval(); err != nil { + return err + } } // Check if the genesis file already exists @@ -560,6 +567,16 @@ func (p *genesisParams) validateGovernorAdminAddr() error { return nil } +// validateBlockTrackerPollInterval validates block tracker block interval +// which can not be 0 +func (p *genesisParams) validateBlockTrackerPollInterval() error { + if p.blockTrackerPollInterval == 0 { + return helper.ErrBlockTrackerPollInterval + } + + return nil +} + // validateBurnContract validates burn contract. If native token is mintable, // burn contract flag must not be set. If native token is non mintable only one burn contract // can be set and the specified address will be used to predeploy default EIP1559 burn contract. diff --git a/command/genesis/polybft_params.go b/command/genesis/polybft_params.go index 265962940b..2184d44ee5 100644 --- a/command/genesis/polybft_params.go +++ b/command/genesis/polybft_params.go @@ -50,6 +50,7 @@ const ( defaultVotingPeriod = "10000" // in blocks defaultVoteProposalThreshold = "1000" // in blocks defaultProposalQuorumPercentage = uint64(67) // percentage + defaultBlockTrackerPollInterval = time.Second accessListsOwnerFlag = "access-lists-owner" // #nosec G101 contractDeployerAllowListAdminFlag = "contract-deployer-allow-list-admin" @@ -214,6 +215,7 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er NetworkParamsAddr: contracts.NetworkParamsContract, ForkParamsAddr: contracts.ForkParamsContract, }, + BlockTrackerPollInterval: common.Duration{Duration: p.blockTrackerPollInterval}, } // Disable london hardfork if burn contract address is not provided diff --git a/command/helper/helper.go b/command/helper/helper.go index 8e847f7d7c..2fe0647421 100644 --- a/command/helper/helper.go +++ b/command/helper/helper.go @@ -23,6 +23,8 @@ import ( "google.golang.org/grpc/credentials/insecure" ) +var ErrBlockTrackerPollInterval = errors.New("block tracker poll interval must be greater than 0") + type ClientCloseResult struct { Message string `json:"message"` } diff --git a/command/server/config/config.go b/command/server/config/config.go index 115bf8b858..1b26e8cd1b 100644 --- a/command/server/config/config.go +++ b/command/server/config/config.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "strings" + "time" "github.com/0xPolygon/polygon-edge/network" "github.com/hashicorp/hcl" @@ -32,8 +33,9 @@ type Config struct { JSONLogFormat bool `json:"json_log_format" yaml:"json_log_format"` CorsAllowedOrigins []string `json:"cors_allowed_origins" yaml:"cors_allowed_origins"` - Relayer bool `json:"relayer" yaml:"relayer"` - NumBlockConfirmations uint64 `json:"num_block_confirmations" yaml:"num_block_confirmations"` + Relayer bool `json:"relayer" yaml:"relayer"` + NumBlockConfirmations uint64 `json:"num_block_confirmations" yaml:"num_block_confirmations"` + RelayerTrackerPollInterval time.Duration `json:"relayer_tracker_poll_interval" yaml:"relayer_tracker_poll_interval"` ConcurrentRequestsDebug uint64 `json:"concurrent_requests_debug" yaml:"concurrent_requests_debug"` WebSocketReadLimit uint64 `json:"web_socket_read_limit" yaml:"web_socket_read_limit"` @@ -90,6 +92,10 @@ const ( // If a message exceeds the limit, // the connection sends a close message to the peer and returns ErrReadLimit to the application. DefaultWebSocketReadLimit uint64 = 8192 + + // DefaultRelayerTrackerPollInterval specifies time interval after which relayer node's event tracker + // polls child chain to get the latest block + DefaultRelayerTrackerPollInterval time.Duration = time.Second ) // DefaultConfig returns the default server configuration @@ -122,13 +128,14 @@ func DefaultConfig() *Config { Headers: &Headers{ AccessControlAllowOrigins: []string{"*"}, }, - LogFilePath: "", - JSONRPCBatchRequestLimit: DefaultJSONRPCBatchRequestLimit, - JSONRPCBlockRangeLimit: DefaultJSONRPCBlockRangeLimit, - Relayer: false, - NumBlockConfirmations: DefaultNumBlockConfirmations, - ConcurrentRequestsDebug: DefaultConcurrentRequestsDebug, - WebSocketReadLimit: DefaultWebSocketReadLimit, + LogFilePath: "", + JSONRPCBatchRequestLimit: DefaultJSONRPCBatchRequestLimit, + JSONRPCBlockRangeLimit: DefaultJSONRPCBlockRangeLimit, + Relayer: false, + NumBlockConfirmations: DefaultNumBlockConfirmations, + ConcurrentRequestsDebug: DefaultConcurrentRequestsDebug, + WebSocketReadLimit: DefaultWebSocketReadLimit, + RelayerTrackerPollInterval: DefaultRelayerTrackerPollInterval, } } diff --git a/command/server/init.go b/command/server/init.go index 216c4e28c1..996a664477 100644 --- a/command/server/init.go +++ b/command/server/init.go @@ -58,6 +58,10 @@ func (p *serverParams) initRawParams() error { p.relayer = p.rawConfig.Relayer + if p.relayer && p.rawConfig.RelayerTrackerPollInterval == 0 { + return helper.ErrBlockTrackerPollInterval + } + return p.initAddresses() } diff --git a/command/server/params.go b/command/server/params.go index db592b0fcf..c7752c41f2 100644 --- a/command/server/params.go +++ b/command/server/params.go @@ -43,6 +43,8 @@ const ( concurrentRequestsDebugFlag = "concurrent-requests-debug" webSocketReadLimitFlag = "websocket-read-limit" + + relayerTrackerPollIntervalFlag = "relayer-poll-interval" ) // Flags that are deprecated, but need to be preserved for @@ -185,7 +187,8 @@ func (p *serverParams) generateConfig() *server.Config { JSONLogFormat: p.rawConfig.JSONLogFormat, LogFilePath: p.logFileLocation, - Relayer: p.relayer, - NumBlockConfirmations: p.rawConfig.NumBlockConfirmations, + Relayer: p.relayer, + NumBlockConfirmations: p.rawConfig.NumBlockConfirmations, + RelayerTrackerPollInterval: p.rawConfig.RelayerTrackerPollInterval, } } diff --git a/command/server/server.go b/command/server/server.go index 74c44d5d8d..135f2ce0ce 100644 --- a/command/server/server.go +++ b/command/server/server.go @@ -242,6 +242,13 @@ func setFlags(cmd *cobra.Command) { "maximum size in bytes for a message read from the peer by websocket", ) + cmd.Flags().DurationVar( + ¶ms.rawConfig.RelayerTrackerPollInterval, + relayerTrackerPollIntervalFlag, + defaultConfig.RelayerTrackerPollInterval, + "interval (number of seconds) at which relayer's tracker polls for latest block at childchain", + ) + setLegacyFlags(cmd) setDevFlags(cmd) diff --git a/consensus/polybft/common/polybft_config.go b/consensus/polybft/common/polybft_config.go index 7c02af98d6..8e82f1e962 100644 --- a/consensus/polybft/common/polybft_config.go +++ b/consensus/polybft/common/polybft_config.go @@ -68,6 +68,10 @@ type PolyBFTConfig struct { // ProxyContractsAdmin is the address that will have the privilege to change both the proxy // implementation address and the admin ProxyContractsAdmin types.Address `json:"proxyContractsAdmin,omitempty"` + + // BlockTrackerPollInterval specifies interval + // at which block tracker polls for blocks on a rootchain + BlockTrackerPollInterval common.Duration `json:"blockTrackerPollInterval,omitempty"` } // LoadPolyBFTConfig loads chain config from provided path and unmarshals PolyBFTConfig diff --git a/consensus/polybft/consensus_runtime.go b/consensus/polybft/consensus_runtime.go index 97709de313..70d3ae5821 100644 --- a/consensus/polybft/consensus_runtime.go +++ b/consensus/polybft/consensus_runtime.go @@ -195,14 +195,15 @@ func (c *consensusRuntime) initStateSyncManager(logger hcf.Logger) error { logger.Named("state-sync-manager"), c.config.State, &stateSyncConfig{ - key: c.config.Key, - stateSenderAddr: stateSenderAddr, - stateSenderStartBlock: c.config.GenesisConfig.Bridge.EventTrackerStartBlocks[stateSenderAddr], - jsonrpcAddr: c.config.GenesisConfig.Bridge.JSONRPCEndpoint, - dataDir: c.config.DataDir, - topic: c.config.bridgeTopic, - maxCommitmentSize: maxCommitmentSize, - numBlockConfirmations: c.config.numBlockConfirmations, + key: c.config.Key, + stateSenderAddr: stateSenderAddr, + stateSenderStartBlock: c.config.GenesisConfig.Bridge.EventTrackerStartBlocks[stateSenderAddr], + jsonrpcAddr: c.config.GenesisConfig.Bridge.JSONRPCEndpoint, + dataDir: c.config.DataDir, + topic: c.config.bridgeTopic, + maxCommitmentSize: maxCommitmentSize, + numBlockConfirmations: c.config.numBlockConfirmations, + blockTrackerPollInterval: c.config.GenesisConfig.BlockTrackerPollInterval.Duration, }, c, ) diff --git a/consensus/polybft/state_sync_manager.go b/consensus/polybft/state_sync_manager.go index 5e3b4337c0..c62a66621a 100644 --- a/consensus/polybft/state_sync_manager.go +++ b/consensus/polybft/state_sync_manager.go @@ -8,9 +8,10 @@ import ( "fmt" "path" "sync" + "time" "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" - "github.com/0xPolygon/polygon-edge/consensus/polybft/common" + polybftCommon "github.com/0xPolygon/polygon-edge/consensus/polybft/common" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" polybftProto "github.com/0xPolygon/polygon-edge/consensus/polybft/proto" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" @@ -39,8 +40,8 @@ type StateSyncManager interface { Close() Commitment(blockNumber uint64) (*CommitmentMessageSigned, error) GetStateSyncProof(stateSyncID uint64) (types.Proof, error) - PostBlock(req *common.PostBlockRequest) error - PostEpoch(req *common.PostEpochRequest) error + PostBlock(req *polybftCommon.PostBlockRequest) error + PostEpoch(req *polybftCommon.PostEpochRequest) error } var _ StateSyncManager = (*dummyStateSyncManager)(nil) @@ -53,22 +54,23 @@ func (n *dummyStateSyncManager) Close() {} func (n *dummyStateSyncManager) Commitment(blockNumber uint64) (*CommitmentMessageSigned, error) { return nil, nil } -func (n *dummyStateSyncManager) PostBlock(req *common.PostBlockRequest) error { return nil } -func (n *dummyStateSyncManager) PostEpoch(req *common.PostEpochRequest) error { return nil } +func (n *dummyStateSyncManager) PostBlock(req *polybftCommon.PostBlockRequest) error { return nil } +func (n *dummyStateSyncManager) PostEpoch(req *polybftCommon.PostEpochRequest) error { return nil } func (n *dummyStateSyncManager) GetStateSyncProof(stateSyncID uint64) (types.Proof, error) { return types.Proof{}, nil } // stateSyncConfig holds the configuration data of state sync manager type stateSyncConfig struct { - stateSenderAddr types.Address - stateSenderStartBlock uint64 - jsonrpcAddr string - dataDir string - topic topic - key *wallet.Key - maxCommitmentSize uint64 - numBlockConfirmations uint64 + stateSenderAddr types.Address + stateSenderStartBlock uint64 + jsonrpcAddr string + dataDir string + topic topic + key *wallet.Key + maxCommitmentSize uint64 + numBlockConfirmations uint64 + blockTrackerPollInterval time.Duration } var _ StateSyncManager = (*stateSyncManager)(nil) @@ -138,7 +140,8 @@ func (s *stateSyncManager) initTracker() error { s, s.config.numBlockConfirmations, s.config.stateSenderStartBlock, - s.logger) + s.logger, + s.config.blockTrackerPollInterval) go func() { <-s.closeCh @@ -374,7 +377,7 @@ func (s *stateSyncManager) getAggSignatureForCommitmentMessage(blockNumber uint6 // PostEpoch notifies the state sync manager that an epoch has changed, // so that it can discard any previous epoch commitments, and build a new one (since validator set changed) -func (s *stateSyncManager) PostEpoch(req *common.PostEpochRequest) error { +func (s *stateSyncManager) PostEpoch(req *polybftCommon.PostEpochRequest) error { s.lock.Lock() s.pendingCommitments = nil @@ -398,7 +401,7 @@ func (s *stateSyncManager) PostEpoch(req *common.PostEpochRequest) error { // PostBlock notifies state sync manager that a block was finalized, // so that it can build state sync proofs if a block has a commitment submission transaction -func (s *stateSyncManager) PostBlock(req *common.PostBlockRequest) error { +func (s *stateSyncManager) PostBlock(req *polybftCommon.PostBlockRequest) error { commitment, err := getCommitmentMessageSignedTx(req.FullBlock.Block.Transactions) if err != nil { return err diff --git a/consensus/polybft/statesyncrelayer/state_sync_relayer.go b/consensus/polybft/statesyncrelayer/state_sync_relayer.go index 33232387ea..62c901b376 100644 --- a/consensus/polybft/statesyncrelayer/state_sync_relayer.go +++ b/consensus/polybft/statesyncrelayer/state_sync_relayer.go @@ -8,6 +8,7 @@ import ( "net" "path" "strings" + "time" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/contracts" @@ -30,6 +31,7 @@ type StateSyncRelayer struct { txRelayer txrelayer.TxRelayer key ethgo.Key closeCh chan struct{} + pollInterval time.Duration } func sanitizeRPCEndpoint(rpcEndpoint string) string { @@ -52,6 +54,7 @@ func NewRelayer( stateReceiverTrackerStartBlock uint64, logger hcf.Logger, key ethgo.Key, + pollInterval time.Duration, ) *StateSyncRelayer { endpoint := sanitizeRPCEndpoint(rpcEndpoint) @@ -78,6 +81,7 @@ func NewRelayer( key: key, closeCh: make(chan struct{}), eventTrackerStartBlock: stateReceiverTrackerStartBlock, + pollInterval: pollInterval, } } @@ -90,6 +94,7 @@ func (r *StateSyncRelayer) Start() error { 0, // sidechain (Polygon POS) is instant finality, so no need to wait r.eventTrackerStartBlock, r.logger, + r.pollInterval, ) ctx, cancelFn := context.WithCancel(context.Background()) diff --git a/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go b/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go index e523bb0b40..65341dcc91 100644 --- a/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go +++ b/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go @@ -3,6 +3,7 @@ package statesyncrelayer import ( "math/big" "testing" + "time" "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/txrelayer" @@ -123,7 +124,8 @@ func TestStateSyncRelayer_Stop(t *testing.T) { key, err := wallet.GenerateKey() require.NoError(t, err) - r := NewRelayer("test-chain-1", txrelayer.DefaultRPCAddress, ethgo.Address(contracts.StateReceiverContract), 0, hclog.NewNullLogger(), key) + r := NewRelayer("test-chain-1", txrelayer.DefaultRPCAddress, ethgo.Address(contracts.StateReceiverContract), + 0, hclog.NewNullLogger(), key, time.Second) require.NotPanics(t, func() { r.Stop() }) } diff --git a/e2e-polybft/e2e/bridge_test.go b/e2e-polybft/e2e/bridge_test.go index 9432091bad..eb69d38aff 100644 --- a/e2e-polybft/e2e/bridge_test.go +++ b/e2e-polybft/e2e/bridge_test.go @@ -1621,3 +1621,67 @@ func TestE2E_DoubleSign_Slashing(t *testing.T) { t, cluster.Servers[0].JSONRPCAddr(), blockWithSlashTx.Number) require.ErrorContains(t, err, fmt.Sprintf("no slashing exit event proof found for block number %v", blockWithSlashTx.Number)) } + +func TestE2E_Bridge_Transfers_WithBlockTrackerPollInterval(t *testing.T) { + var ( + // amount = ethgo.Gwei(10) + numBlockConfirmations = uint64(2) + epochSize = 30 + sprintSize = uint64(5) + rootPollInterval = 5 * time.Second + relayerPollInterval = 5 * time.Second + ) + + cluster := framework.NewTestCluster(t, 5, + framework.WithEpochSize(epochSize), + framework.WithNumBlockConfirmations(numBlockConfirmations), + framework.WithRootTrackerPollInterval(rootPollInterval), + framework.WithRelayerTrackerPollInterval(relayerPollInterval), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + polybftCfg, err := polyCommon.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) + require.NoError(t, err) + + validatorSrv := cluster.Servers[0] + senderAccount, err := sidechain.GetAccountFromDir(validatorSrv.DataDir()) + require.NoError(t, err) + + childEthEndpoint := validatorSrv.JSONRPC().Eth() + + // bridge some tokens for first validator to child chain + tokensToDeposit := ethgo.Ether(10) + + require.NoError(t, cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + rootHelper.TestAccountPrivKey, + senderAccount.Address().String(), + tokensToDeposit.String(), + "", + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) + + // wait for a couple of sprints + finalBlockNum := 5 * sprintSize + require.NoError(t, cluster.WaitForBlock(finalBlockNum, 2*time.Minute)) + + // the transaction is processed and there should be a success event + var stateSyncedResult contractsapi.StateSyncResultEvent + + logs, err := getFilteredLogs(stateSyncedResult.Sig(), 0, finalBlockNum, childEthEndpoint) + require.NoError(t, err) + + // assert that all deposits are executed successfully + checkStateSyncResultLogs(t, logs, 1) + + // check validator balance got increased by deposited amount + balance, err := childEthEndpoint.GetBalance(ethgo.Address(senderAccount.Address()), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, tokensToDeposit, balance) +} diff --git a/e2e-polybft/framework/test-cluster.go b/e2e-polybft/framework/test-cluster.go index 15b8041181..1831284c36 100644 --- a/e2e-polybft/framework/test-cluster.go +++ b/e2e-polybft/framework/test-cluster.go @@ -130,7 +130,9 @@ type TestClusterConfig struct { VotingPeriod uint64 VotingDelay uint64 - ProxyContractsAdmin string + ProxyContractsAdmin string + RootTrackerPollInterval time.Duration + RelayerTrackerPollInterval time.Duration logsDirOnce sync.Once } @@ -414,6 +416,18 @@ func WithProxyContractsAdmin(address string) ClusterOption { } } +func WithRootTrackerPollInterval(pollInterval time.Duration) ClusterOption { + return func(h *TestClusterConfig) { + h.RootTrackerPollInterval = pollInterval + } +} + +func WithRelayerTrackerPollInterval(pollInterval time.Duration) ClusterOption { + return func(h *TestClusterConfig) { + h.RelayerTrackerPollInterval = pollInterval + } +} + func isTrueEnv(e string) bool { return strings.ToLower(os.Getenv(e)) == "true" } @@ -515,6 +529,11 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T "--vote-delay", fmt.Sprint(cluster.Config.VotingDelay), } + if cluster.Config.RelayerTrackerPollInterval != 0 { + args = append(args, "--block-tracker-poll-interval", + cluster.Config.RelayerTrackerPollInterval.String()) + } + if cluster.Config.VotingPeriod > 0 { args = append(args, "--vote-period", fmt.Sprint(cluster.Config.VotingPeriod)) } @@ -713,6 +732,7 @@ func (c *TestCluster) InitTestServer(t *testing.T, config.NumBlockConfirmations = c.Config.NumBlockConfirmations config.BridgeJSONRPC = bridgeJSONRPC config.Byzantine = byzantine + config.RelayerTrackerPollInterval = c.Config.RelayerTrackerPollInterval }) // watch the server for stop signals. It is important to fix the specific diff --git a/e2e-polybft/framework/test-server.go b/e2e-polybft/framework/test-server.go index 64066adfef..5f9e8d6791 100644 --- a/e2e-polybft/framework/test-server.go +++ b/e2e-polybft/framework/test-server.go @@ -28,18 +28,19 @@ import ( ) type TestServerConfig struct { - Name string - JSONRPCPort int64 - GRPCPort int64 - P2PPort int64 - Seal bool - DataDir string - Chain string - LogLevel string - Relayer bool - NumBlockConfirmations uint64 - BridgeJSONRPC string - Byzantine bool + Name string + JSONRPCPort int64 + GRPCPort int64 + P2PPort int64 + Seal bool + DataDir string + Chain string + LogLevel string + Relayer bool + NumBlockConfirmations uint64 + BridgeJSONRPC string + Byzantine bool + RelayerTrackerPollInterval time.Duration } type TestServerConfigCallback func(*TestServerConfig) @@ -184,6 +185,11 @@ func (t *TestServer) Start() { if config.Relayer { args = append(args, "--relayer") + + if config.RelayerTrackerPollInterval != 0 { + // only relayer node should have this setup if + args = append(args, "--relayer-poll-interval", config.RelayerTrackerPollInterval.String()) + } } // Start the server diff --git a/server/config.go b/server/config.go index 8a76cc1db7..edfb2980ae 100644 --- a/server/config.go +++ b/server/config.go @@ -2,6 +2,7 @@ package server import ( "net" + "time" "github.com/hashicorp/go-hclog" @@ -43,7 +44,8 @@ type Config struct { Relayer bool - NumBlockConfirmations uint64 + NumBlockConfirmations uint64 + RelayerTrackerPollInterval time.Duration } // Telemetry holds the config details for metric services diff --git a/server/server.go b/server/server.go index 54c02e8ce7..32aebe669a 100644 --- a/server/server.go +++ b/server/server.go @@ -635,6 +635,7 @@ func (s *Server) setupRelayer() error { trackerStartBlockConfig[contracts.StateReceiverContract], s.logger.Named("relayer"), wallet.NewEcdsaSigner(wallet.NewKey(account)), + s.config.RelayerTrackerPollInterval, ) // start relayer diff --git a/tracker/event_tracker.go b/tracker/event_tracker.go index c2ae154172..14e1d18553 100644 --- a/tracker/event_tracker.go +++ b/tracker/event_tracker.go @@ -26,6 +26,7 @@ type EventTracker struct { subscriber eventSubscription logger hcf.Logger numBlockConfirmations uint64 // minimal number of child blocks required for the parent block to be considered final + pollInterval time.Duration } func NewEventTracker( @@ -36,6 +37,7 @@ func NewEventTracker( numBlockConfirmations uint64, startBlock uint64, logger hcf.Logger, + pollInterval time.Duration, ) *EventTracker { return &EventTracker{ dbPath: dbPath, @@ -45,6 +47,7 @@ func NewEventTracker( numBlockConfirmations: numBlockConfirmations, startBlock: startBlock, logger: logger.Named("event_tracker"), + pollInterval: pollInterval, } } @@ -53,7 +56,8 @@ func (e *EventTracker) Start(ctx context.Context) error { "contract", e.contractAddr, "JSON RPC address", e.rpcEndpoint, "num block confirmations", e.numBlockConfirmations, - "start block", e.startBlock) + "start block", e.startBlock, + "poll interval", e.pollInterval) provider, err := jsonrpc.NewClient(e.rpcEndpoint) if err != nil { @@ -70,7 +74,13 @@ func (e *EventTracker) Start(ctx context.Context) error { blockMaxBacklog = minBlockMaxBacklog } - blockTracker := blocktracker.NewBlockTracker(provider.Eth(), blocktracker.WithBlockMaxBacklog(blockMaxBacklog)) + jsonBlockTracker := blocktracker.NewJSONBlockTracker(provider.Eth()) + jsonBlockTracker.PollInterval = e.pollInterval + blockTracker := blocktracker.NewBlockTracker( + provider.Eth(), + blocktracker.WithBlockMaxBacklog(blockMaxBacklog), + blocktracker.WithTracker(jsonBlockTracker), + ) go func() { <-ctx.Done() diff --git a/tracker/event_tracker_test.go b/tracker/event_tracker_test.go index bfc1c00e0a..bc247c3a69 100644 --- a/tracker/event_tracker_test.go +++ b/tracker/event_tracker_test.go @@ -84,6 +84,7 @@ func TestEventTracker_TrackSyncEvents(t *testing.T) { rpcEndpoint: server.HTTPAddr(), contractAddr: addr, numBlockConfirmations: numBlockConfirmations, + pollInterval: time.Second, } err = tracker.Start(context.Background())