88 "path/filepath"
99 "strconv"
1010 "strings"
11- "sync"
1211 "time"
1312
1413 "github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -24,52 +23,43 @@ import (
2423 rprewards "github.com/rocket-pool/smartnode/v2/rocketpool-daemon/common/rewards"
2524 "github.com/rocket-pool/smartnode/v2/rocketpool-daemon/common/services"
2625 "github.com/rocket-pool/smartnode/v2/rocketpool-daemon/common/state"
26+ "github.com/rocket-pool/smartnode/v2/rocketpool-daemon/task"
2727 "github.com/rocket-pool/smartnode/v2/shared/config"
2828 "github.com/rocket-pool/smartnode/v2/shared/keys"
2929 sharedtypes "github.com/rocket-pool/smartnode/v2/shared/types"
3030)
3131
3232// Generate rewards Merkle Tree task
3333type GenerateRewardsTree struct {
34- ctx context.Context
35- sp * services.ServiceProvider
36- logger * slog.Logger
37- cfg * config.SmartNodeConfig
38- rp * rocketpool.RocketPool
39- ec eth.IExecutionClient
40- bc beacon.IBeaconClient
41- lock * sync.Mutex
42- isRunning bool
34+ * task.LockingBackgroundTask
35+ sp * services.ServiceProvider
36+ logger * slog.Logger
37+ cfg * config.SmartNodeConfig
38+ rp * rocketpool.RocketPool
39+ ec eth.IExecutionClient
40+ bc beacon.IBeaconClient
4341}
4442
4543// Create generate rewards Merkle Tree task
4644func NewGenerateRewardsTree (ctx context.Context , sp * services.ServiceProvider , logger * log.Logger ) * GenerateRewardsTree {
47- lock := & sync.Mutex {}
48- return & GenerateRewardsTree {
49- ctx : ctx ,
50- sp : sp ,
51- logger : logger .With (slog .String (keys .RoutineKey , "Generate Rewards Tree" )),
52- cfg : sp .GetConfig (),
53- rp : sp .GetRocketPool (),
54- ec : sp .GetEthClient (),
55- bc : sp .GetBeaconClient (),
56- lock : lock ,
57- isRunning : false ,
45+ out := & GenerateRewardsTree {
46+ sp : sp ,
47+ logger : logger .With (slog .String (keys .RoutineKey , "Generate Rewards Tree" )),
48+ cfg : sp .GetConfig (),
49+ rp : sp .GetRocketPool (),
50+ ec : sp .GetEthClient (),
51+ bc : sp .GetBeaconClient (),
5852 }
53+ out .LockingBackgroundTask = task .NewLockingBackgroundTask (
54+ logger .With (slog .String (keys .RoutineKey , "Generate Rewards Tree" )),
55+ "manual rewards tree generation request check" ,
56+ out .Run ,
57+ )
58+ return out
5959}
6060
6161// Check for generation requests
62- func (t * GenerateRewardsTree ) Run () error {
63- t .logger .Info ("Starting manual rewards tree generation request check." )
64-
65- // Check if rewards generation is already running
66- t .lock .Lock ()
67- if t .isRunning {
68- t .logger .Info ("Tree generation is already running." )
69- t .lock .Unlock ()
70- return nil
71- }
72- t .lock .Unlock ()
62+ func (t * GenerateRewardsTree ) Run (taskCtx * task.BackgroundTaskContext ) error {
7363
7464 // Check for requests
7565 requestDir := t .cfg .GetWatchtowerFolder ()
@@ -102,10 +92,7 @@ func (t *GenerateRewardsTree) Run() error {
10292 }
10393
10494 // Generate the rewards tree
105- t .lock .Lock ()
106- t .isRunning = true
107- t .lock .Unlock ()
108- go t .generateRewardsTree (index )
95+ go t .generateRewardsTree (taskCtx .Ctx , index )
10996
11097 // Return after the first request, do others at other intervals
11198 return nil
@@ -115,7 +102,10 @@ func (t *GenerateRewardsTree) Run() error {
115102 return nil
116103}
117104
118- func (t * GenerateRewardsTree ) generateRewardsTree (index uint64 ) {
105+ func (t * GenerateRewardsTree ) generateRewardsTree (ctx context.Context , index uint64 ) {
106+ // This function is the async portion of the task, so make sure to signal completion
107+ defer t .LockingBackgroundTask .Done ()
108+
119109 // Begin generation of the tree
120110 logger := t .logger .With (slog .Uint64 (keys .IntervalKey , index ))
121111 logger .Info ("Starting generation of Merkle rewards tree." )
@@ -150,7 +140,7 @@ func (t *GenerateRewardsTree) generateRewardsTree(index uint64) {
150140 }, opts )
151141 if err == nil {
152142 // Create the state manager with using the primary or fallback (not necessarily archive) EC
153- stateManager , err = state .NewNetworkStateManager (t . ctx , client , t .cfg , t .rp .Client , t .bc , logger )
143+ stateManager , err = state .NewNetworkStateManager (ctx , client , t .cfg , t .rp .Client , t .bc , logger )
154144 if err != nil {
155145 t .handleError (fmt .Errorf ("error creating new NetworkStateManager with Archive EC: %w" , err ), logger )
156146 return
@@ -189,7 +179,7 @@ func (t *GenerateRewardsTree) generateRewardsTree(index uint64) {
189179 return
190180 }
191181 // Create the state manager with the archive EC
192- stateManager , err = state .NewNetworkStateManager (t . ctx , client , t .cfg , ec , t .bc , logger )
182+ stateManager , err = state .NewNetworkStateManager (ctx , client , t .cfg , ec , t .bc , logger )
193183 if err != nil {
194184 t .handleError (fmt .Errorf ("error creating new NetworkStateManager with Archive EC: %w" , err ), logger )
195185 return
@@ -210,26 +200,26 @@ func (t *GenerateRewardsTree) generateRewardsTree(index uint64) {
210200 }
211201
212202 // Get the state for the target slot
213- state , err := stateManager .GetStateForSlot (t . ctx , rewardsEvent .ConsensusBlock .Uint64 ())
203+ state , err := stateManager .GetStateForSlot (ctx , rewardsEvent .ConsensusBlock .Uint64 ())
214204 if err != nil {
215205 t .handleError (fmt .Errorf ("error getting state for beacon slot %d: %w" , rewardsEvent .ConsensusBlock .Uint64 (), err ), logger )
216206 return
217207 }
218208
219209 // Generate the tree
220- t .generateRewardsTreeImpl (logger , client , index , rewardsEvent , elBlockHeader , state )
210+ t .generateRewardsTreeImpl (ctx , logger , client , index , rewardsEvent , elBlockHeader , state )
221211}
222212
223213// Implementation for rewards tree generation using a viable EC
224- func (t * GenerateRewardsTree ) generateRewardsTreeImpl (logger * slog.Logger , rp * rocketpool.RocketPool , index uint64 , rewardsEvent rewards.RewardsEvent , elBlockHeader * types.Header , state * state.NetworkState ) {
214+ func (t * GenerateRewardsTree ) generateRewardsTreeImpl (ctx context. Context , logger * slog.Logger , rp * rocketpool.RocketPool , index uint64 , rewardsEvent rewards.RewardsEvent , elBlockHeader * types.Header , state * state.NetworkState ) {
225215 // Generate the rewards file
226216 start := time .Now ()
227217 treegen , err := rprewards .NewTreeGenerator (t .logger , rp , t .cfg , t .bc , index , rewardsEvent .IntervalStartTime , rewardsEvent .IntervalEndTime , rewardsEvent .ConsensusBlock .Uint64 (), elBlockHeader , rewardsEvent .IntervalsPassed .Uint64 (), state , nil )
228218 if err != nil {
229219 t .handleError (fmt .Errorf ("Error creating Merkle tree generator: %w" , err ), logger )
230220 return
231221 }
232- rewardsFile , err := treegen .GenerateTree (t . ctx )
222+ rewardsFile , err := treegen .GenerateTree (ctx )
233223 if err != nil {
234224 t .handleError (fmt .Errorf ("%s Error generating Merkle tree: %w" , err ), logger )
235225 return
@@ -273,14 +263,8 @@ func (t *GenerateRewardsTree) generateRewardsTreeImpl(logger *slog.Logger, rp *r
273263 }
274264
275265 t .logger .Info ("Merkle tree generation complete!" )
276- t .lock .Lock ()
277- t .isRunning = false
278- t .lock .Unlock ()
279266}
280267
281268func (t * GenerateRewardsTree ) handleError (err error , logger * slog.Logger ) {
282269 logger .Error ("*** Rewards tree generation failed. ***" , log .Err (err ))
283- t .lock .Lock ()
284- t .isRunning = false
285- t .lock .Unlock ()
286270}
0 commit comments