88 "net/http"
99 "strconv"
1010 "sync"
11+ "time"
1112
1213 "github.com/ethereum/go-ethereum/common"
1314 "github.com/ethereum/go-ethereum/common/hexutil"
@@ -29,21 +30,28 @@ func (b *testBeaconClient) onForkchoiceUpdate() (uint64, error) {
2930 return b .slot , nil
3031}
3132
33+ func (b * testBeaconClient ) updateValidatorsMap () error {
34+ return nil
35+ }
36+
3237type BeaconClient struct {
3338 endpoint string
3439 slotsInEpoch uint64
40+ secondsInSlot uint64
3541
3642 mu sync.Mutex
3743 currentEpoch uint64
3844 currentSlot uint64
3945 nextSlotProposer PubkeyHex
4046 slotProposerMap map [uint64 ]PubkeyHex
47+ slotRequestedCh chan uint64
4148}
4249
43- func NewBeaconClient (endpoint string , slotsInEpoch uint64 ) * BeaconClient {
50+ func NewBeaconClient (endpoint string , slotsInEpoch uint64 , secondsInSlot uint64 ) * BeaconClient {
4451 return & BeaconClient {
4552 endpoint : endpoint ,
4653 slotsInEpoch : slotsInEpoch ,
54+ secondsInSlot : secondsInSlot ,
4755 slotProposerMap : make (map [uint64 ]PubkeyHex ),
4856 }
4957}
@@ -56,8 +64,6 @@ func (b *BeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex,
5664 b .mu .Lock ()
5765 defer b .mu .Unlock ()
5866
59- go b .updateValidatorsMap (requestedSlot )
60-
6167 nextSlotProposer , found := b .slotProposerMap [requestedSlot ]
6268 if ! found {
6369 log .Error ("inconsistent proposer mapping" , "currentSlot" , b .currentSlot , "slotProposerMap" , b .slotProposerMap )
@@ -66,20 +72,42 @@ func (b *BeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex,
6672 return nextSlotProposer , nil
6773}
6874
69- func (b * BeaconClient ) updateValidatorsMap (nextSlot uint64 ) error {
70- b .currentSlot = nextSlot
71- nextSlotEpoch := nextSlot / b .slotsInEpoch
72- // if slot at half epoch, fetch next epoch's proposers
73- if nextSlotEpoch != b .currentEpoch || nextSlot % b .slotsInEpoch == b .slotsInEpoch / 2 {
74- slotProposerMap , err := fetchEpochProposersMap (b .endpoint , nextSlotEpoch )
75- if err != nil {
76- return err
75+ func (b * BeaconClient ) updateValidatorsMap () error {
76+ // Start regular slot updates
77+ slotsPerEpoch := b .slotsInEpoch
78+ durationPerSlot := time .Duration (b .secondsInSlot ) * time .Second
79+ durationPerEpoch := durationPerSlot * time .Duration (slotsPerEpoch )
80+ b .slotRequestedCh = make (chan uint64 )
81+ // Every half epoch request validators map
82+ timer := time .NewTicker (durationPerEpoch / 2 )
83+ for {
84+ select {
85+ case slot := <- b .slotRequestedCh :
86+ b .currentSlot = slot
87+ nextSlotEpoch := slot / b .slotsInEpoch
88+ // if slot at half epoch, fetch next epoch's proposers
89+ if nextSlotEpoch > b .currentEpoch {
90+ slotProposerMap , err := fetchEpochProposersMap (b .endpoint , nextSlotEpoch )
91+ if err != nil {
92+ log .Error ("could not fetch validators map" , "err" , err )
93+ continue
94+ }
95+
96+ b .slotProposerMap = slotProposerMap
97+ b .currentEpoch = nextSlotEpoch
98+ b .slotProposerMap = slotProposerMap
99+ timer .Reset (durationPerEpoch / 2 )
100+ }
101+ case <- timer .C :
102+ slotProposerMap , err := fetchEpochProposersMap (b .endpoint , b .currentEpoch + 1 )
103+ if err != nil {
104+ log .Error ("could not fetch validators map" , "err" , err )
105+ continue
106+ }
107+ b .slotProposerMap = slotProposerMap
108+ timer .Reset (durationPerEpoch / 2 )
77109 }
78-
79- b .currentEpoch = nextSlotEpoch
80- b .slotProposerMap = slotProposerMap
81110 }
82-
83111 return nil
84112}
85113
0 commit comments