Skip to content

Commit

Permalink
feat: notify epoch is a percentage of epoch
Browse files Browse the repository at this point in the history
  • Loading branch information
joanestebanr committed Nov 12, 2024
1 parent 06c121a commit 41378a7
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 39 deletions.
4 changes: 2 additions & 2 deletions aggsender/aggsender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}

Expand All @@ -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())
Expand Down
8 changes: 5 additions & 3 deletions aggsender/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check failure on line 27 in aggsender/config.go

View workflow job for this annotation

GitHub Actions / lint

`Begining` is a misspelling of `Beginning` (misspell)
// 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"`
}
Expand All @@ -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"
}
46 changes: 29 additions & 17 deletions aggsender/epoch_notifier_per_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check failure on line 24 in aggsender/epoch_notifier_per_block.go

View workflow job for this annotation

GitHub Actions / lint

`begining` is a misspelling of `beginning` (misspell)
// 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")
}
Expand All @@ -34,18 +37,18 @@ 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
}

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 {

Check failure on line 50 in aggsender/epoch_notifier_per_block.go

View workflow job for this annotation

GitHub Actions / lint

Magic number: 100, in <condition> detected (mnd)
return fmt.Errorf("epochNotificationPercentage: must be between 0 and 99")
}
return nil
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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

Check failure on line 172 in aggsender/epoch_notifier_per_block.go

View workflow job for this annotation

GitHub Actions / lint

Magic number: 100.0, in <operation> detected (mnd)
if percentEpoch < thresholdPercent {
e.logger.Debugf("Block %d is at %f%% of the epoch no notify", currentBlock, percentEpoch*100)

Check failure on line 174 in aggsender/epoch_notifier_per_block.go

View workflow job for this annotation

GitHub Actions / lint

Magic number: 100, in <argument> detected (mnd)
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
Expand Down
30 changes: 15 additions & 15 deletions aggsender/epoch_notifier_per_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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))
Expand All @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,6 @@ BlockGetInterval = "2s"
URLRPCL2="{{L2URL}}"
CheckSettledInterval = "2s"
BlockFinality = "LatestBlock"
BlocksBeforeEpochEnding = 2
EpochNotificationPercentage = 50
SaveCertificatesToFiles = false
`
1 change: 1 addition & 0 deletions test/helpers/lxly-bridge-test.bash
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 41378a7

Please sign in to comment.