diff --git a/aggsender/aggsender_test.go b/aggsender/aggsender_test.go index 1ea46f5ce..8f1aea36c 100644 --- a/aggsender/aggsender_test.go +++ b/aggsender/aggsender_test.go @@ -50,7 +50,7 @@ func TestConfigString(t *testing.T) { AggsenderPrivateKey: types.KeystoreFileConfig{Path: "/path/to/key", Password: "password"}, URLRPCL2: "http://l2.rpc.url", BlockFinality: "latestBlock", - BlocksBeforeEpochEnding: 10, + EpochNotificationPercentage: 50, SaveCertificatesToFilesPath: "/path/to/certificates", } @@ -62,7 +62,7 @@ func TestConfigString(t *testing.T) { "AggsenderPrivateKeyPassword: password\n" + "URLRPCL2: http://l2.rpc.url\n" + "BlockFinality: latestBlock\n" + - "BlocksBeforeEpochEnding: 10\n" + + "EpochNotificationPercentage: 50\n" + "SaveCertificatesToFilesPath: /path/to/certificates\n" require.Equal(t, expected, config.String()) diff --git a/aggsender/config.go b/aggsender/config.go index 686945897..a7efdd378 100644 --- a/aggsender/config.go +++ b/aggsender/config.go @@ -22,9 +22,11 @@ type Config struct { URLRPCL2 string `mapstructure:"URLRPCL2"` // BlockFinality indicates which finality follows AggLayer BlockFinality string `jsonschema:"enum=LatestBlock, enum=SafeBlock, enum=PendingBlock, enum=FinalizedBlock, enum=EarliestBlock" mapstructure:"BlockFinality"` //nolint:lll - // BlocksBeforeEpochEnding indicates how many blocks before the epoch ending + // EpochNotificationPercentage indicates the percentage of the epoch // the AggSender should send the certificate - BlocksBeforeEpochEnding uint `mapstructure:"BlocksBeforeEpochEnding"` + // 0 -> Begining + // 50 -> Middle + EpochNotificationPercentage uint `mapstructure:"EpochNotificationPercentage"` // SaveCertificatesToFilesPath if != "" tells the AggSender to save the certificates to a file in this path SaveCertificatesToFilesPath string `mapstructure:"SaveCertificatesToFilesPath"` } @@ -39,6 +41,6 @@ func (c Config) String() string { "AggsenderPrivateKeyPassword: " + c.AggsenderPrivateKey.Password + "\n" + "URLRPCL2: " + c.URLRPCL2 + "\n" + "BlockFinality: " + c.BlockFinality + "\n" + - "BlocksBeforeEpochEnding: " + fmt.Sprintf("%d", c.BlocksBeforeEpochEnding) + "\n" + + "EpochNotificationPercentage: " + fmt.Sprintf("%d", c.EpochNotificationPercentage) + "\n" + "SaveCertificatesToFilesPath: " + c.SaveCertificatesToFilesPath + "\n" } diff --git a/aggsender/epoch_notifier_per_block.go b/aggsender/epoch_notifier_per_block.go index d1309a226..5fc4bcec9 100644 --- a/aggsender/epoch_notifier_per_block.go +++ b/aggsender/epoch_notifier_per_block.go @@ -20,12 +20,15 @@ type ConfigEpochNotifierPerBlock struct { StartingEpochBlock uint64 NumBlockPerEpoch uint - // Num blocks before the end of the epoch to notify it - NotifyPendingBlocksBeforeEndEpoch uint + // EpochNotificationPercentage + // 0 -> begining new Epoch + // 50 -> middle of epoch + // 100 -> end of epoch (same as 0) + EpochNotificationPercentage uint } func NewConfigEpochNotifierPerBlock(aggLayer agglayer.AggLayerClientGetEpochConfiguration, - notifyPendingBlocksBeforeEndEpoch uint) (*ConfigEpochNotifierPerBlock, error) { + epochNotificationPercentage uint) (*ConfigEpochNotifierPerBlock, error) { if aggLayer == nil { return nil, fmt.Errorf("newConfigEpochNotifierPerBlock: aggLayerClient is required") } @@ -34,9 +37,9 @@ func NewConfigEpochNotifierPerBlock(aggLayer agglayer.AggLayerClientGetEpochConf return nil, fmt.Errorf("newConfigEpochNotifierPerBlock: error getting clock configuration from AggLayer: %w", err) } return &ConfigEpochNotifierPerBlock{ - StartingEpochBlock: clockConfig.GenesisBlock, - NumBlockPerEpoch: uint(clockConfig.EpochDuration), - NotifyPendingBlocksBeforeEndEpoch: notifyPendingBlocksBeforeEndEpoch, + StartingEpochBlock: clockConfig.GenesisBlock, + NumBlockPerEpoch: uint(clockConfig.EpochDuration), + EpochNotificationPercentage: epochNotificationPercentage, }, nil } @@ -44,8 +47,8 @@ func (c *ConfigEpochNotifierPerBlock) Validate() error { if c.NumBlockPerEpoch == 0 { return fmt.Errorf("numBlockPerEpoch: num block per epoch is required > 0 ") } - if c.NumBlockPerEpoch-c.NotifyPendingBlocksBeforeEndEpoch == 0 { - return fmt.Errorf("notifyPendingBlocksBeforeEndEpoch: Notify before num blocks end of epoch is required > 0") + if c.EpochNotificationPercentage >= 100 { + return fmt.Errorf("epochNotificationPercentage: must be between 0 and 99") } return nil } @@ -83,8 +86,8 @@ func NewEpochNotifierPerBlock(blockNotifier types.BlockNotifier, func (e *EpochNotifierPerBlock) String() string { return fmt.Sprintf("EpochNotifierPerBlock: startingEpochBlock=%d, numBlockPerEpoch=%d,"+ - " notifyPendingBlocksBeforeEndEpoch=%d", - e.Config.StartingEpochBlock, e.Config.NumBlockPerEpoch, e.Config.NotifyPendingBlocksBeforeEndEpoch) + " EpochNotificationPercentage=%d", + e.Config.StartingEpochBlock, e.Config.NumBlockPerEpoch, e.Config.EpochNotificationPercentage) } // StartAsync starts the notifier in a goroutine @@ -139,14 +142,10 @@ func (e *EpochNotifierPerBlock) step(status internalStatus, } status.lastBlockSeen = currentBlock - needNotify, closingEpoch := e.isClosingEpochBlock(currentBlock, status.waitingForEpoch) + needNotify, closingEpoch := e.isNotificationRequired(currentBlock, status.waitingForEpoch) if needNotify { // Notify the epoch has started info := e.infoEpoch(currentBlock, closingEpoch) - if status.waitingForEpoch == 0 && info.PendingBlocks > int(e.Config.NotifyPendingBlocksBeforeEndEpoch) { - // We are in the first epoch, but we are not near the end of the epoch - return status, nil - } status.waitingForEpoch = closingEpoch + 1 return status, &types.EpochEvent{ Epoch: closingEpoch, @@ -162,10 +161,23 @@ func (e *EpochNotifierPerBlock) infoEpoch(currentBlock, newEpochNotified uint64) PendingBlocks: int(nextBlockStartingEpoch - currentBlock), } } -func (e *EpochNotifierPerBlock) isClosingEpochBlock(currentBlock, lastEpochNotified uint64) (bool, uint64) { - nextEpoch := e.epochNumber(currentBlock + uint64(e.Config.NotifyPendingBlocksBeforeEndEpoch)) +func (e *EpochNotifierPerBlock) percentEpoch(currentBlock uint64) float64 { + epoch := e.epochNumber(currentBlock) + startingBlock := e.startingBlockEpoch(epoch) + elapsedBlocks := currentBlock - startingBlock + return float64(elapsedBlocks) / float64(e.Config.NumBlockPerEpoch) +} +func (e *EpochNotifierPerBlock) isNotificationRequired(currentBlock, lastEpochNotified uint64) (bool, uint64) { + percentEpoch := e.percentEpoch(currentBlock) + thresholdPercent := float64(e.Config.EpochNotificationPercentage) / 100.0 + if percentEpoch < thresholdPercent { + e.logger.Debugf("Block %d is at %f%% of the epoch no notify", currentBlock, percentEpoch*100) + return false, e.epochNumber(currentBlock) + } + nextEpoch := e.epochNumber(currentBlock) + 1 return nextEpoch > lastEpochNotified, e.epochNumber(currentBlock) } + func (e *EpochNotifierPerBlock) startingBlockEpoch(epoch uint64) uint64 { if epoch == 0 { return e.Config.StartingEpochBlock - 1 diff --git a/aggsender/epoch_notifier_per_block_test.go b/aggsender/epoch_notifier_per_block_test.go index 9e84fb6a4..99119f5eb 100644 --- a/aggsender/epoch_notifier_per_block_test.go +++ b/aggsender/epoch_notifier_per_block_test.go @@ -16,9 +16,9 @@ import ( func TestStartingBlockEpoch(t *testing.T) { testData := newNotifierPerBlockTestData(t, &ConfigEpochNotifierPerBlock{ - StartingEpochBlock: 9, - NumBlockPerEpoch: 10, - NotifyPendingBlocksBeforeEndEpoch: 1, + StartingEpochBlock: 9, + NumBlockPerEpoch: 10, + EpochNotificationPercentage: 80, }) // EPOCH: ---0 ----+----1 -----+----2 ----+----3 ----+----4 ----+----5 ----+---- // BLOCK: 9 19 29 39 49 @@ -29,9 +29,9 @@ func TestStartingBlockEpoch(t *testing.T) { func TestEpochStep(t *testing.T) { testData := newNotifierPerBlockTestData(t, &ConfigEpochNotifierPerBlock{ - StartingEpochBlock: 9, - NumBlockPerEpoch: 10, - NotifyPendingBlocksBeforeEndEpoch: 1, + StartingEpochBlock: 9, + NumBlockPerEpoch: 10, + EpochNotificationPercentage: 50, }) // EPOCH: ---0 ----+----1 -----+----2 ----+----3 ----+----4 ----+----5 ----+---- // BLOCK: 9 19 29 39 49 @@ -138,9 +138,9 @@ func TestStepNotifyEpoch(t *testing.T) { func TestBlockEpochNumber(t *testing.T) { testData := newNotifierPerBlockTestData(t, &ConfigEpochNotifierPerBlock{ - StartingEpochBlock: 105, - NumBlockPerEpoch: 10, - NotifyPendingBlocksBeforeEndEpoch: 1, + StartingEpochBlock: 105, + NumBlockPerEpoch: 10, + EpochNotificationPercentage: 1, }) require.Equal(t, uint64(0), testData.sut.epochNumber(0)) require.Equal(t, uint64(0), testData.sut.epochNumber(104)) @@ -154,9 +154,9 @@ func TestBlockEpochNumber(t *testing.T) { func TestBlockBeforeEpoch(t *testing.T) { testData := newNotifierPerBlockTestData(t, &ConfigEpochNotifierPerBlock{ - StartingEpochBlock: 105, - NumBlockPerEpoch: 10, - NotifyPendingBlocksBeforeEndEpoch: 1, + StartingEpochBlock: 105, + NumBlockPerEpoch: 10, + EpochNotificationPercentage: 1, }) status := internalStatus{ lastBlockSeen: 104, @@ -184,9 +184,9 @@ func newNotifierPerBlockTestData(t *testing.T, config *ConfigEpochNotifierPerBlo t.Helper() if config == nil { config = &ConfigEpochNotifierPerBlock{ - StartingEpochBlock: 0, - NumBlockPerEpoch: 10, - NotifyPendingBlocksBeforeEndEpoch: 1, + StartingEpochBlock: 0, + NumBlockPerEpoch: 10, + EpochNotificationPercentage: 50, } } blockNotifierMock := mocks.NewBlockNotifier(t) diff --git a/cmd/run.go b/cmd/run.go index 070ff4622..6042e935a 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -158,7 +158,7 @@ func createAggSender( return nil, err } - notifierCfg, err := aggsender.NewConfigEpochNotifierPerBlock(agglayerClient, cfg.BlocksBeforeEpochEnding) + notifierCfg, err := aggsender.NewConfigEpochNotifierPerBlock(agglayerClient, cfg.EpochNotificationPercentage) if err != nil { return nil, fmt.Errorf("cant generate config for Epoch Notifier because: %w", err) } diff --git a/config/default.go b/config/default.go index f54aa82e9..d7188e433 100644 --- a/config/default.go +++ b/config/default.go @@ -342,6 +342,6 @@ BlockGetInterval = "2s" URLRPCL2="{{L2URL}}" CheckSettledInterval = "2s" BlockFinality = "LatestBlock" -BlocksBeforeEpochEnding = 2 +EpochNotificationPercentage = 50 SaveCertificatesToFiles = false ` diff --git a/test/helpers/lxly-bridge-test.bash b/test/helpers/lxly-bridge-test.bash index 7b3cb0086..ad5ab9430 100644 --- a/test/helpers/lxly-bridge-test.bash +++ b/test/helpers/lxly-bridge-test.bash @@ -36,6 +36,7 @@ function claim() { readonly bridge_deposit_file=$(mktemp) readonly claimable_deposit_file=$(mktemp) echo "Getting full list of deposits" >&3 + echo " curl -s \"$bridge_api_url/bridges/$destination_addr?limit=100&offset=0\"" >&3 curl -s "$bridge_api_url/bridges/$destination_addr?limit=100&offset=0" | jq '.' | tee $bridge_deposit_file echo "Looking for claimable deposits" >&3