From 49886b2ffd220d0d7efaec2973145586ae197d46 Mon Sep 17 00:00:00 2001 From: mpetrun5 Date: Mon, 8 Jan 2024 14:45:04 +0100 Subject: [PATCH 1/2] fix: starting period 1 when period does not exist --- chains/evm/config/config.go | 1 + chains/evm/config/config_test.go | 5 +++ chains/evm/listener/handlers/rotate.go | 34 ++++++++++++++++----- chains/evm/listener/handlers/rotate_test.go | 21 +++---------- main.go | 5 ++- 5 files changed, 41 insertions(+), 25 deletions(-) diff --git a/chains/evm/config/config.go b/chains/evm/config/config.go index 65128bf..2a90d5d 100644 --- a/chains/evm/config/config.go +++ b/chains/evm/config/config.go @@ -22,6 +22,7 @@ type EVMConfig struct { GasIncreasePercentage int64 `default:"15" split_words:"true"` RetryInterval uint64 `default:"12" split_words:"true"` CommitteePeriodLength uint64 `default:"256" split_words:"true"` + StartingPeriod uint64 `required:"true" split_words:"true"` } // LoadEVMConfig loads EVM config from the environment and validates the fields diff --git a/chains/evm/config/config_test.go b/chains/evm/config/config_test.go index 5cd73ce..d72eb78 100644 --- a/chains/evm/config/config_test.go +++ b/chains/evm/config/config_test.go @@ -42,6 +42,8 @@ func (s *EVMConfigTestSuite) Test_LoadEVMConfig_SuccessfulLoad_DefaultValues() { os.Setenv("SPECTRE_DOMAINS_1_ROUTER", "router") os.Setenv("SPECTRE_DOMAINS_1_BEACON_ENDPOINT", "endpoint") os.Setenv("SPECTRE_DOMAINS_2_ROUTER", "invalid") + os.Setenv("SPECTRE_DOMAINS_1_STARTING_PERIOD", "500") + os.Setenv("SPECTRE_DOMAINS_2_STARTING_PERIOD", "500") c, err := config.LoadEVMConfig(1) @@ -61,6 +63,7 @@ func (s *EVMConfigTestSuite) Test_LoadEVMConfig_SuccessfulLoad_DefaultValues() { RetryInterval: 12, CommitteePeriodLength: 256, BeaconEndpoint: "endpoint", + StartingPeriod: 500, }) } @@ -78,6 +81,7 @@ func (s *EVMConfigTestSuite) Test_LoadEVMConfig_SuccessfulLoad() { os.Setenv("SPECTRE_DOMAINS_1_RETRY_INTERVAL", "30") os.Setenv("SPECTRE_DOMAINS_1_COMMITTEE_PERIOD_LENGTH", "128") os.Setenv("SPECTRE_DOMAINS_2_ROUTER", "invalid") + os.Setenv("SPECTRE_DOMAINS_1_STARTING_PERIOD", "500") c, err := config.LoadEVMConfig(1) @@ -97,5 +101,6 @@ func (s *EVMConfigTestSuite) Test_LoadEVMConfig_SuccessfulLoad() { RetryInterval: 30, CommitteePeriodLength: 128, BeaconEndpoint: "endpoint", + StartingPeriod: 500, }) } diff --git a/chains/evm/listener/handlers/rotate.go b/chains/evm/listener/handlers/rotate.go index 6d5033d..08e8c5b 100644 --- a/chains/evm/listener/handlers/rotate.go +++ b/chains/evm/listener/handlers/rotate.go @@ -32,11 +32,31 @@ type RotateHandler struct { prover Prover periodStorer PeriodStorer + latestPeriod *big.Int committeePeriodLength uint64 } -func NewRotateHandler(msgChan chan []*message.Message, periodStorer PeriodStorer, prover Prover, domainID uint8, domains []uint8, committeePeriodLenght uint64) *RotateHandler { +func NewRotateHandler( + msgChan chan []*message.Message, + periodStorer PeriodStorer, + prover Prover, + domainID uint8, + domains []uint8, + committeePeriodLenght uint64, + startingPeriod uint64, +) (*RotateHandler, error) { + storedPeriod, err := periodStorer.Period(domainID) + if err != nil { + return nil, err + } + + var latestPeriod *big.Int + if storedPeriod.Uint64() >= startingPeriod { + latestPeriod = storedPeriod + } else { + latestPeriod = big.NewInt(int64(startingPeriod)) + } return &RotateHandler{ prover: prover, periodStorer: periodStorer, @@ -44,22 +64,19 @@ func NewRotateHandler(msgChan chan []*message.Message, periodStorer PeriodStorer domains: domains, msgChan: msgChan, committeePeriodLength: committeePeriodLenght, - } + latestPeriod: latestPeriod, + }, err } // HandleEvents checks if the current period is newer than the last stored // period and rotates the committee if it is func (h *RotateHandler) HandleEvents(checkpoint *apiv1.Finality) error { - latestPeriod, err := h.periodStorer.Period(h.domainID) - if err != nil { - return err - } currentPeriod := uint64(checkpoint.Finalized.Epoch) / h.committeePeriodLength - if currentPeriod <= latestPeriod.Uint64() { + if currentPeriod <= h.latestPeriod.Uint64() { return nil } - targetPeriod := latestPeriod.Add(latestPeriod, big.NewInt(1)) + targetPeriod := new(big.Int).Add(h.latestPeriod, big.NewInt(1)) args, err := h.prover.RotateArgs(targetPeriod.Uint64()) if err != nil { return err @@ -104,5 +121,6 @@ func (h *RotateHandler) HandleEvents(checkpoint *apiv1.Finality) error { } } + h.latestPeriod = targetPeriod return h.periodStorer.StorePeriod(h.domainID, targetPeriod) } diff --git a/chains/evm/listener/handlers/rotate_test.go b/chains/evm/listener/handlers/rotate_test.go index 4695312..ba2f643 100644 --- a/chains/evm/listener/handlers/rotate_test.go +++ b/chains/evm/listener/handlers/rotate_test.go @@ -48,29 +48,19 @@ func (s *RotateHandlerTestSuite) SetupTest() { s.mockProver = mock.NewMockProver(ctrl) s.mockPeriodStorer = mock.NewMockPeriodStorer(ctrl) s.msgChan = make(chan []*message.Message, 2) - s.handler = handlers.NewRotateHandler( + s.mockPeriodStorer.EXPECT().Period(uint8(1)).Return(big.NewInt(2), nil) + s.handler, _ = handlers.NewRotateHandler( s.msgChan, s.mockPeriodStorer, s.mockProver, 1, []uint8{2, 3}, 256, + 3, ) } -func (s *RotateHandlerTestSuite) Test_HandleEvents_PeriodFetchingFails() { - s.mockPeriodStorer.EXPECT().Period(uint8(1)).Return(nil, fmt.Errorf("error")) - - err := s.handler.HandleEvents(&apiv1.Finality{}) - s.NotNil(err) - - _, err = readFromChannel(s.msgChan) - s.NotNil(err) -} - func (s *RotateHandlerTestSuite) Test_HandleEvents_CurrentPeriodOlderThanLatest() { - s.mockPeriodStorer.EXPECT().Period(uint8(1)).Return(big.NewInt(2), nil) - err := s.handler.HandleEvents(&apiv1.Finality{ Finalized: &phase0.Checkpoint{ Epoch: phase0.Epoch(300), @@ -83,9 +73,8 @@ func (s *RotateHandlerTestSuite) Test_HandleEvents_CurrentPeriodOlderThanLatest( } func (s *RotateHandlerTestSuite) Test_HandleEvents_ValidPeriod() { - s.mockPeriodStorer.EXPECT().Period(uint8(1)).Return(big.NewInt(2), nil) - s.mockPeriodStorer.EXPECT().StorePeriod(uint8(1), big.NewInt(3)).Return(nil) - s.mockProver.EXPECT().RotateArgs(uint64(3)).Return(&prover.RotateArgs{ + s.mockPeriodStorer.EXPECT().StorePeriod(uint8(4), big.NewInt(3)).Return(nil) + s.mockProver.EXPECT().RotateArgs(uint64(4)).Return(&prover.RotateArgs{ Update: &consensus.LightClientUpdateCapella{}, Domain: phase0.Domain{}, Spec: "mainnet", diff --git a/main.go b/main.go index bc8861a..e365c27 100644 --- a/main.go +++ b/main.go @@ -113,7 +113,10 @@ func main() { p := prover.NewProver(proverClient, beaconProvider, lightClient, prover.Spec(config.Spec)) routerAddress := common.HexToAddress(config.Router) stepHandler := handlers.NewStepEventHandler(msgChan, client, beaconProvider, p, routerAddress, id, domains, config.BlockInterval) - rotateHandler := handlers.NewRotateHandler(msgChan, periodStore, p, id, domains, config.CommitteePeriodLength) + rotateHandler, err := handlers.NewRotateHandler(msgChan, periodStore, p, id, domains, config.CommitteePeriodLength, config.StartingPeriod) + if err != nil { + panic(err) + } listener := listener.NewEVMListener(beaconProvider, []listener.EventHandler{rotateHandler, stepHandler}, id, time.Duration(config.RetryInterval)*time.Second) messageHandler := message.NewMessageHandler() From db5d066fd945d131d82ac7ed54ab06dd3fa37653 Mon Sep 17 00:00:00 2001 From: mpetrun5 Date: Mon, 8 Jan 2024 14:49:21 +0100 Subject: [PATCH 2/2] Fix rotate tests --- chains/evm/listener/handlers/rotate_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chains/evm/listener/handlers/rotate_test.go b/chains/evm/listener/handlers/rotate_test.go index ba2f643..5b1d975 100644 --- a/chains/evm/listener/handlers/rotate_test.go +++ b/chains/evm/listener/handlers/rotate_test.go @@ -73,7 +73,7 @@ func (s *RotateHandlerTestSuite) Test_HandleEvents_CurrentPeriodOlderThanLatest( } func (s *RotateHandlerTestSuite) Test_HandleEvents_ValidPeriod() { - s.mockPeriodStorer.EXPECT().StorePeriod(uint8(4), big.NewInt(3)).Return(nil) + s.mockPeriodStorer.EXPECT().StorePeriod(uint8(1), big.NewInt(4)).Return(nil) s.mockProver.EXPECT().RotateArgs(uint64(4)).Return(&prover.RotateArgs{ Update: &consensus.LightClientUpdateCapella{}, Domain: phase0.Domain{},