diff --git a/CHANGELOG.md b/CHANGELOG.md index a892d23..05b7e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,8 +38,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## Unreleased ### Bug Fixes + * [#138](https://github.com/babylonlabs-io/vigilante/pull/138) fix: panic in SendCheckpointToBTC +### Improvements + +* [#136](https://github.com/babylonlabs-io/vigilante/pull/136) rate limit activations + ## v0.18.0 ### Improvements diff --git a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go index 613a4ab..d16b694 100644 --- a/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go +++ b/btcstaking-tracker/stakingeventwatcher/stakingeventwatcher.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "golang.org/x/sync/semaphore" "sync" "sync/atomic" "time" @@ -26,8 +27,9 @@ import ( ) var ( - fixedDelyTypeWithJitter = retry.DelayType(retry.CombineDelay(retry.FixedDelay, retry.RandomDelay)) - retryForever = retry.Attempts(0) + fixedDelyTypeWithJitter = retry.DelayType(retry.CombineDelay(retry.FixedDelay, retry.RandomDelay)) + retryForever = retry.Attempts(0) + maxConcurrentActivations = int64(1000) ) func (sew *StakingEventWatcher) quitContext() (context.Context, func()) { @@ -83,6 +85,7 @@ type StakingEventWatcher struct { unbondingDelegationChan chan *newDelegation unbondingRemovalChan chan *delegationInactive currentBestBlockHeight atomic.Uint32 + activationLimiter *semaphore.Weighted } func NewStakingEventWatcher( @@ -106,6 +109,7 @@ func NewStakingEventWatcher( inProgressTracker: NewTrackedDelegations(), unbondingDelegationChan: make(chan *newDelegation), unbondingRemovalChan: make(chan *delegationInactive), + activationLimiter: semaphore.NewWeighted(maxConcurrentActivations), // todo(lazar): this should be in config } } @@ -613,6 +617,11 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { continue } + if err := sew.activationLimiter.Acquire(context.Background(), 1); err != nil { + sew.logger.Warnf("error acquiring a activation semaphore %s", err) + continue + } + if _, err = sew.inProgressTracker.AddDelegation( del.StakingTx, del.StakingOutputIdx, @@ -624,7 +633,10 @@ func (sew *StakingEventWatcher) checkBtcForStakingTx() { continue } - go sew.activateBtcDelegation(txHash, proof, details.Block.BlockHash(), params.ConfirmationTimeBlocks) + go func() { + defer sew.activationLimiter.Release(1) + sew.activateBtcDelegation(txHash, proof, details.Block.BlockHash(), params.ConfirmationTimeBlocks) + }() } }