mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
beacon/light: use explicit request/response types where possible
This commit is contained in:
parent
245d166d45
commit
084f23cfa0
3 changed files with 55 additions and 66 deletions
|
|
@ -360,11 +360,7 @@ func (s *Scheduler) filterEvents() map[Module][]Event {
|
||||||
|
|
||||||
filteredEvents := make(map[Module][]Event)
|
filteredEvents := make(map[Module][]Event)
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
server, ok := event.Server.(server)
|
server := event.Server.(server)
|
||||||
if !ok {
|
|
||||||
log.Error("Server interface type unknown for Scheduler")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, ok := s.servers[server]; !ok && event.Type != EvRegistered {
|
if _, ok := s.servers[server]; !ok && event.Type != EvRegistered {
|
||||||
continue // before EvRegister or after EvUnregister, discard
|
continue // before EvRegister or after EvUnregister, discard
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ func (s *CheckpointInit) Process(events []request.Event) {
|
||||||
s.locked = request.ServerAndID{}
|
s.locked = request.ServerAndID{}
|
||||||
}
|
}
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
if checkpoint, ok := resp.(*types.BootstrapData); ok && checkpoint.Header.Hash() == common.Hash(req.(ReqCheckpointData)) {
|
if checkpoint := resp.(*types.BootstrapData); checkpoint.Header.Hash() == common.Hash(req.(ReqCheckpointData)) {
|
||||||
s.chain.CheckpointInit(*checkpoint)
|
s.chain.CheckpointInit(*checkpoint)
|
||||||
s.initialized = true
|
s.initialized = true
|
||||||
return
|
return
|
||||||
|
|
@ -93,7 +93,7 @@ type ForwardUpdateSync struct {
|
||||||
chain committeeChain
|
chain committeeChain
|
||||||
rangeLock rangeLock
|
rangeLock rangeLock
|
||||||
lockedIDs map[request.ServerAndID]struct{}
|
lockedIDs map[request.ServerAndID]struct{}
|
||||||
processQueue []request.Event
|
processQueue []updateResponse
|
||||||
nextSyncPeriod map[request.Server]uint64
|
nextSyncPeriod map[request.Server]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,37 +147,27 @@ func (r rangeLock) firstUnlocked(start, maxCount uint64) (first, count uint64) {
|
||||||
|
|
||||||
// lockRange locks the range belonging to the given update request, unless the
|
// lockRange locks the range belonging to the given update request, unless the
|
||||||
// same request has already been locked
|
// same request has already been locked
|
||||||
func (s *ForwardUpdateSync) lockRange(sid request.ServerAndID, req request.Request) {
|
func (s *ForwardUpdateSync) lockRange(sid request.ServerAndID, req ReqUpdates) {
|
||||||
if _, ok := s.lockedIDs[sid]; ok {
|
if _, ok := s.lockedIDs[sid]; ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.lockedIDs[sid] = struct{}{}
|
s.lockedIDs[sid] = struct{}{}
|
||||||
r := req.(ReqUpdates)
|
s.rangeLock.lock(req.FirstPeriod, req.Count, 1)
|
||||||
s.rangeLock.lock(r.FirstPeriod, r.Count, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlockRange unlocks the range belonging to the given update request, unless
|
// unlockRange unlocks the range belonging to the given update request, unless
|
||||||
// same request has already been unlocked
|
// same request has already been unlocked
|
||||||
func (s *ForwardUpdateSync) unlockRange(sid request.ServerAndID, req request.Request) {
|
func (s *ForwardUpdateSync) unlockRange(sid request.ServerAndID, req ReqUpdates) {
|
||||||
if _, ok := s.lockedIDs[sid]; !ok {
|
if _, ok := s.lockedIDs[sid]; !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
delete(s.lockedIDs, sid)
|
delete(s.lockedIDs, sid)
|
||||||
r := req.(ReqUpdates)
|
s.rangeLock.lock(req.FirstPeriod, req.Count, -1)
|
||||||
s.rangeLock.lock(r.FirstPeriod, r.Count, -1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyRange returns true if the number of updates and the individual update
|
// verifyRange returns true if the number of updates and the individual update
|
||||||
// periods in the response match the requested section.
|
// periods in the response match the requested section.
|
||||||
func (s *ForwardUpdateSync) verifyRange(req request.Request, resp request.Response) bool {
|
func (s *ForwardUpdateSync) verifyRange(request ReqUpdates, response RespUpdates) bool {
|
||||||
request, ok := req.(ReqUpdates)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
response, ok := resp.(RespUpdates)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if uint64(len(response.Updates)) != request.Count || uint64(len(response.Committees)) != request.Count {
|
if uint64(len(response.Updates)) != request.Count || uint64(len(response.Committees)) != request.Count {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -189,41 +179,19 @@ func (s *ForwardUpdateSync) verifyRange(req request.Request, resp request.Respon
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// processResponse adds the fetched updates and committees to the committee chain.
|
type updateResponse struct {
|
||||||
// Returns true in case of full or partial success.
|
sid request.ServerAndID
|
||||||
func (s *ForwardUpdateSync) processResponse(event request.Event) (success bool) {
|
request ReqUpdates
|
||||||
_, _, resp := event.RequestInfo()
|
response RespUpdates
|
||||||
response, ok := resp.(RespUpdates)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, update := range response.Updates {
|
|
||||||
if err := s.chain.InsertUpdate(update, response.Committees[i]); err != nil {
|
|
||||||
if err == light.ErrInvalidPeriod {
|
|
||||||
// there is a gap in the update periods; stop processing without
|
|
||||||
// failing and try again next time
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err == light.ErrInvalidUpdate || err == light.ErrWrongCommitteeRoot || err == light.ErrCannotReorg {
|
|
||||||
event.Server.Fail("invalid update received")
|
|
||||||
} else {
|
|
||||||
log.Error("Unexpected InsertUpdate error", "error", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
success = true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateResponseList implements sort.Sort and sorts update request/response events by FirstPeriod.
|
// updateResponseList implements sort.Sort and sorts update request/response events by FirstPeriod.
|
||||||
type updateResponseList []request.Event
|
type updateResponseList []updateResponse
|
||||||
|
|
||||||
func (u updateResponseList) Len() int { return len(u) }
|
func (u updateResponseList) Len() int { return len(u) }
|
||||||
func (u updateResponseList) Swap(i, j int) { u[i], u[j] = u[j], u[i] }
|
func (u updateResponseList) Swap(i, j int) { u[i], u[j] = u[j], u[i] }
|
||||||
func (u updateResponseList) Less(i, j int) bool {
|
func (u updateResponseList) Less(i, j int) bool {
|
||||||
return u[i].Data.(request.RequestResponse).Request.(ReqUpdates).FirstPeriod <
|
return u[i].request.FirstPeriod < u[j].request.FirstPeriod
|
||||||
u[j].Data.(request.RequestResponse).Request.(ReqUpdates).FirstPeriod
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ForwardUpdateSync) Process(events []request.Event) {
|
func (s *ForwardUpdateSync) Process(events []request.Event) {
|
||||||
|
|
@ -231,18 +199,23 @@ func (s *ForwardUpdateSync) Process(events []request.Event) {
|
||||||
switch event.Type {
|
switch event.Type {
|
||||||
case request.EvRequest:
|
case request.EvRequest:
|
||||||
sid, req, _ := event.RequestInfo()
|
sid, req, _ := event.RequestInfo()
|
||||||
s.lockRange(sid, req)
|
s.lockRange(sid, req.(ReqUpdates))
|
||||||
case request.EvResponse, request.EvFail, request.EvTimeout:
|
case request.EvResponse, request.EvFail, request.EvTimeout:
|
||||||
sid, req, resp := event.RequestInfo()
|
sid, rq, rs := event.RequestInfo()
|
||||||
if event.Type == request.EvResponse && !s.verifyRange(req, resp) {
|
req := rq.(ReqUpdates)
|
||||||
event.Server.Fail("invalid update range")
|
var queued bool
|
||||||
resp = nil
|
if event.Type == request.EvResponse {
|
||||||
|
resp := rs.(RespUpdates)
|
||||||
|
if s.verifyRange(req, resp) {
|
||||||
|
// there is a response with a valid format; put it in the process queue
|
||||||
|
s.processQueue = append(s.processQueue, updateResponse{sid: sid, request: req, response: resp})
|
||||||
|
s.lockRange(sid, req)
|
||||||
|
queued = true
|
||||||
|
} else {
|
||||||
|
event.Server.Fail("invalid update range")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if resp != nil {
|
if !queued {
|
||||||
// there is a response with a valid format; put it in the process queue
|
|
||||||
s.processQueue = append(s.processQueue, event)
|
|
||||||
s.lockRange(sid, req)
|
|
||||||
} else {
|
|
||||||
s.unlockRange(sid, req)
|
s.unlockRange(sid, req)
|
||||||
}
|
}
|
||||||
case EvNewSignedHead:
|
case EvNewSignedHead:
|
||||||
|
|
@ -256,12 +229,11 @@ func (s *ForwardUpdateSync) Process(events []request.Event) {
|
||||||
// try processing ordered list of available responses
|
// try processing ordered list of available responses
|
||||||
sort.Sort(updateResponseList(s.processQueue))
|
sort.Sort(updateResponseList(s.processQueue))
|
||||||
for s.processQueue != nil {
|
for s.processQueue != nil {
|
||||||
event := s.processQueue[0]
|
u := s.processQueue[0]
|
||||||
if !s.processResponse(event) {
|
if !s.processResponse(u) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sid, req, _ := event.RequestInfo()
|
s.unlockRange(u.sid, u.request)
|
||||||
s.unlockRange(sid, req)
|
|
||||||
s.processQueue = s.processQueue[1:]
|
s.processQueue = s.processQueue[1:]
|
||||||
if len(s.processQueue) == 0 {
|
if len(s.processQueue) == 0 {
|
||||||
s.processQueue = nil
|
s.processQueue = nil
|
||||||
|
|
@ -269,6 +241,28 @@ func (s *ForwardUpdateSync) Process(events []request.Event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processResponse adds the fetched updates and committees to the committee chain.
|
||||||
|
// Returns true in case of full or partial success.
|
||||||
|
func (s *ForwardUpdateSync) processResponse(u updateResponse) (success bool) {
|
||||||
|
for i, update := range u.response.Updates {
|
||||||
|
if err := s.chain.InsertUpdate(update, u.response.Committees[i]); err != nil {
|
||||||
|
if err == light.ErrInvalidPeriod {
|
||||||
|
// there is a gap in the update periods; stop processing without
|
||||||
|
// failing and try again next time
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err == light.ErrInvalidUpdate || err == light.ErrWrongCommitteeRoot || err == light.ErrCannotReorg {
|
||||||
|
u.sid.Server.Fail("invalid update received")
|
||||||
|
} else {
|
||||||
|
log.Error("Unexpected InsertUpdate error", "error", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
success = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ForwardUpdateSync) MakeRequest(server request.Server) (request.Request, float32) {
|
func (s *ForwardUpdateSync) MakeRequest(server request.Server) (request.Request, float32) {
|
||||||
startPeriod, chainInit := s.chain.NextSyncPeriod()
|
startPeriod, chainInit := s.chain.NextSyncPeriod()
|
||||||
if !chainInit {
|
if !chainInit {
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,7 @@ func (s *beaconBlockSync) Process(events []request.Event) {
|
||||||
_, req, resp := event.RequestInfo()
|
_, req, resp := event.RequestInfo()
|
||||||
blockRoot := common.Hash(req.(sync.ReqBeaconBlock))
|
blockRoot := common.Hash(req.(sync.ReqBeaconBlock))
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
block := resp.(*capella.BeaconBlock)
|
s.recentBlocks.Add(blockRoot, resp.(*capella.BeaconBlock))
|
||||||
s.recentBlocks.Add(blockRoot, block)
|
|
||||||
}
|
}
|
||||||
delete(s.locked, blockRoot)
|
delete(s.locked, blockRoot)
|
||||||
case sync.EvNewHead:
|
case sync.EvNewHead:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue