mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
beacon/light: added and updated descriptions
This commit is contained in:
parent
c249d129b6
commit
7c51f57ded
7 changed files with 54 additions and 36 deletions
|
|
@ -63,10 +63,6 @@ func (s *ApiServer) SendRequest(id request.ID, req request.Request) {
|
||||||
if updates, committees, err := s.api.GetBestUpdatesAndCommittees(data.FirstPeriod, data.Count); err == nil {
|
if updates, committees, err := s.api.GetBestUpdatesAndCommittees(data.FirstPeriod, data.Count); err == nil {
|
||||||
resp = sync.RespUpdates{Updates: updates, Committees: committees}
|
resp = sync.RespUpdates{Updates: updates, Committees: committees}
|
||||||
}
|
}
|
||||||
/*case sync.ReqOptimisticHead:
|
|
||||||
if signedHead, err := s.api.GetOptimisticHeadUpdate(); err == nil {
|
|
||||||
resp = signedHead
|
|
||||||
}*/ //TODO ???
|
|
||||||
case sync.ReqHeader:
|
case sync.ReqHeader:
|
||||||
if header, err := s.api.GetHeader(common.Hash(data)); err == nil {
|
if header, err := s.api.GetHeader(common.Hash(data)); err == nil {
|
||||||
resp = header
|
resp = header
|
||||||
|
|
|
||||||
|
|
@ -24,20 +24,21 @@ import (
|
||||||
|
|
||||||
// Module represents a mechanism which is typically responsible for downloading
|
// Module represents a mechanism which is typically responsible for downloading
|
||||||
// and updating a passive data structure. It does not directly interact with the
|
// and updating a passive data structure. It does not directly interact with the
|
||||||
// servers (except for reporting server side failures). It receives and processes
|
// servers. It can start requests using the Requester interface, maintain its
|
||||||
// events, maintains its internal state and generates request candidates. It is
|
// internal state by receiving and processing Events and update its target data
|
||||||
// the Scheduler's responsibility to feed events to the modules, call Process as
|
// structure based on the obtained data.
|
||||||
// long as there might be something to process and then generate request
|
// It is the Scheduler's responsibility to feed events to the modules, call
|
||||||
|
// Process as long as there might be something to process and then generate request
|
||||||
// candidates using MakeRequest and start the best possible requests.
|
// candidates using MakeRequest and start the best possible requests.
|
||||||
// Modules are called by Scheduler whenever a global trigger is fired. All events
|
// Modules are called by Scheduler whenever a global trigger is fired. All events
|
||||||
// fire the trigger. Changing a target data structure also triggers a next
|
// fire the trigger. Changing a target data structure also triggers a next
|
||||||
// processing round as it could make further actions possible either by the same
|
// processing round as it could make further actions possible either by the same
|
||||||
// or another Module.
|
// or another Module.
|
||||||
type Module interface {
|
type Module interface {
|
||||||
// Process is a non-blocking function responsible for maintaining the target
|
// Process is a non-blocking function responsible for starting requests,
|
||||||
// data structures(s) and the internal state of the module. This state
|
// processing events and updating the target data structures(s) and the
|
||||||
// typically consists of information about pending requests and registered
|
// internal state of the module. Module state typically consists of information
|
||||||
// servers and it is updated based on the received events.
|
// about pending requests and registered servers.
|
||||||
// Process is always called after an event is received or after a target data
|
// Process is always called after an event is received or after a target data
|
||||||
// structure has been changed.
|
// structure has been changed.
|
||||||
//
|
//
|
||||||
|
|
@ -47,6 +48,10 @@ type Module interface {
|
||||||
Process(Requester, []Event)
|
Process(Requester, []Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Requester allows Modules to obtain the list of momentarily available servers,
|
||||||
|
// start new requests and report server failure when a response has been proven
|
||||||
|
// to be invalid in the processing phase.
|
||||||
|
// Note that all Requester functions should be safe to call from Module.Process.
|
||||||
type Requester interface {
|
type Requester interface {
|
||||||
CanSendTo() []Server
|
CanSendTo() []Server
|
||||||
Send(Server, Request) ID
|
Send(Server, Request) ID
|
||||||
|
|
@ -340,11 +345,18 @@ func (s *Scheduler) closePending(server Server, filteredEvents map[Module][]Even
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// requester implements Requester. Note that while requester basically wraps
|
||||||
|
// Scheduler (with the added information of the currently processed Module), all
|
||||||
|
// functions are safe to call from Module.Process which is running while
|
||||||
|
// the Scheduler.lock mutex is held.
|
||||||
type requester struct {
|
type requester struct {
|
||||||
*Scheduler
|
*Scheduler
|
||||||
module Module
|
module Module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanSendTo returns the list of currently available servers. It also returns
|
||||||
|
// them in an order of least to most recently used, ensuring a round-robin usage
|
||||||
|
// of suitable servers if the module always chooses the first suitable one.
|
||||||
func (s requester) CanSendTo() []Server {
|
func (s requester) CanSendTo() []Server {
|
||||||
s.requesterLock.RLock()
|
s.requesterLock.RLock()
|
||||||
defer s.requesterLock.RUnlock()
|
defer s.requesterLock.RUnlock()
|
||||||
|
|
@ -358,6 +370,8 @@ func (s requester) CanSendTo() []Server {
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send sends a request and adds an entry to Scheduler.pending map, ensuring that
|
||||||
|
// related request events will be delivered to the sender Module.
|
||||||
func (s requester) Send(srv Server, req Request) ID {
|
func (s requester) Send(srv Server, req Request) ID {
|
||||||
s.requesterLock.Lock()
|
s.requesterLock.Lock()
|
||||||
defer s.requesterLock.Unlock()
|
defer s.requesterLock.Unlock()
|
||||||
|
|
@ -377,6 +391,11 @@ func (s requester) Send(srv Server, req Request) ID {
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fail should be called when a server delivers invalid or useless information.
|
||||||
|
// Calling Fail disables the given server for a period that is initially short
|
||||||
|
// but is exponentially growing if it happens frequently. This results in a
|
||||||
|
// somewhat fault tolerant operation that avoids hammering servers with requests
|
||||||
|
// that they cannot serve but still gives them a chance periodically.
|
||||||
func (s requester) Fail(srv Server, desc string) {
|
func (s requester) Fail(srv Server, desc string) {
|
||||||
srv.(server).fail(desc)
|
srv.(server).fail(desc)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,12 +119,11 @@ type RequestResponse struct {
|
||||||
Response Response
|
Response Response
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO serverWithTimeout wraps a requestServer and introduces two new request event
|
// serverWithTimeout wraps a requestServer and introduces timeouts.
|
||||||
// types: EvRequest and EvTimeout. Whenever a request is successfully sent, an
|
// The request's lifecycle is concluded if EvResponse or EvFail emitted by the
|
||||||
// EvRequest event is emitted first. The request's lifecycle is concluded if
|
// parent requestServer. If this does not happen until softRequestTimeout then
|
||||||
// EvResponse or EvFail emitted by the parent requestServer. If this does not
|
// EvTimeout is emitted, after which the final EvResponse or EvFail is still
|
||||||
// happen until softRequestTimeout then EvTimeout is emitted, after which the
|
// guaranteed to follow.
|
||||||
// final EvResponse or EvFail is still guaranteed to follow.
|
|
||||||
// If the parent fails to send this final event for hardRequestTimeout then
|
// If the parent fails to send this final event for hardRequestTimeout then
|
||||||
// serverWithTimeout emits EvFail and discards any further events from the
|
// serverWithTimeout emits EvFail and discards any further events from the
|
||||||
// parent related to the given request.
|
// parent related to the given request.
|
||||||
|
|
@ -340,9 +339,6 @@ func (s *serverWithLimits) canRequest() bool {
|
||||||
// canRequestNow checks whether a new request can be started, according to the
|
// canRequestNow checks whether a new request can be started, according to the
|
||||||
// current in-flight request count and parallelLimit, and also the failure delay
|
// current in-flight request count and parallelLimit, and also the failure delay
|
||||||
// timer.
|
// timer.
|
||||||
// If a new request is allowed then it also returns a priority value that can be
|
|
||||||
// used to select the least overloaded server from an otherwise equally suitable
|
|
||||||
// set of servers.
|
|
||||||
// If it returns false then it is guaranteed that an EvCanRequestAgain will be
|
// If it returns false then it is guaranteed that an EvCanRequestAgain will be
|
||||||
// sent whenever the server becomes available for requesting again.
|
// sent whenever the server becomes available for requesting again.
|
||||||
func (s *serverWithLimits) canRequestNow() bool {
|
func (s *serverWithLimits) canRequestNow() bool {
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ func NewHeadSync(headTracker headTracker, chain committeeChain) *HeadSync {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process implements request.Module.
|
||||||
func (s *HeadSync) Process(requester request.Requester, events []request.Event) {
|
func (s *HeadSync) Process(requester request.Requester, events []request.Event) {
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
switch event.Type {
|
switch event.Type {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ func NewCheckpointInit(chain committeeChain, checkpointHash common.Hash) *Checkp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process implements request.Module.
|
||||||
func (s *CheckpointInit) Process(requester request.Requester, events []request.Event) {
|
func (s *CheckpointInit) Process(requester request.Requester, events []request.Event) {
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
if !event.IsRequestEvent() {
|
if !event.IsRequestEvent() {
|
||||||
|
|
@ -180,6 +181,9 @@ func (s *ForwardUpdateSync) verifyRange(request ReqUpdates, response RespUpdates
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateResponse is a response that has passed initial verification and has been
|
||||||
|
// queued for processing. Note that an update response cannot be processed until
|
||||||
|
// the previous updates have also been added to the chain.
|
||||||
type updateResponse struct {
|
type updateResponse struct {
|
||||||
sid request.ServerAndID
|
sid request.ServerAndID
|
||||||
request ReqUpdates
|
request ReqUpdates
|
||||||
|
|
@ -195,6 +199,7 @@ func (u updateResponseList) Less(i, j int) bool {
|
||||||
return u[i].request.FirstPeriod < u[j].request.FirstPeriod
|
return u[i].request.FirstPeriod < u[j].request.FirstPeriod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process implements request.Module.
|
||||||
func (s *ForwardUpdateSync) Process(requester request.Requester, events []request.Event) {
|
func (s *ForwardUpdateSync) Process(requester request.Requester, events []request.Event) {
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
switch event.Type {
|
switch event.Type {
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ func TestUpdateSyncParallel(t *testing.T) {
|
||||||
// valid response to request 1; expect 8 periods synced and a new request started
|
// valid response to request 1; expect 8 periods synced and a new request started
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(1, 1), testRespUpdate(ts.Request(1, 1)))
|
ts.RequestEvent(request.EvResponse, ts.Request(1, 1), testRespUpdate(ts.Request(1, 1)))
|
||||||
ts.AddAllowance(testServer1, 1)
|
ts.AddAllowance(testServer1, 1)
|
||||||
ts.Run(7, testServer1, ReqUpdates{FirstPeriod: 48, Count: 8})
|
ts.Run(2, testServer1, ReqUpdates{FirstPeriod: 48, Count: 8})
|
||||||
chain.ExpNextSyncPeriod(t, 8)
|
chain.ExpNextSyncPeriod(t, 8)
|
||||||
|
|
||||||
// valid response to requests 4 and 5
|
// valid response to requests 4 and 5
|
||||||
|
|
@ -92,7 +92,7 @@ func TestUpdateSyncParallel(t *testing.T) {
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(1, 5), testRespUpdate(ts.Request(1, 5)))
|
ts.RequestEvent(request.EvResponse, ts.Request(1, 5), testRespUpdate(ts.Request(1, 5)))
|
||||||
ts.AddAllowance(testServer2, 2)
|
ts.AddAllowance(testServer2, 2)
|
||||||
// expect 2 more requests but no sync progress (responses 4 and 5 cannot be added before 2 and 3)
|
// expect 2 more requests but no sync progress (responses 4 and 5 cannot be added before 2 and 3)
|
||||||
ts.Run(8,
|
ts.Run(3,
|
||||||
testServer2, ReqUpdates{FirstPeriod: 56, Count: 8},
|
testServer2, ReqUpdates{FirstPeriod: 56, Count: 8},
|
||||||
testServer2, ReqUpdates{FirstPeriod: 64, Count: 8})
|
testServer2, ReqUpdates{FirstPeriod: 64, Count: 8})
|
||||||
chain.ExpNextSyncPeriod(t, 8)
|
chain.ExpNextSyncPeriod(t, 8)
|
||||||
|
|
@ -101,15 +101,15 @@ func TestUpdateSyncParallel(t *testing.T) {
|
||||||
ts.RequestEvent(request.EvTimeout, ts.Request(1, 2), nil)
|
ts.RequestEvent(request.EvTimeout, ts.Request(1, 2), nil)
|
||||||
ts.RequestEvent(request.EvTimeout, ts.Request(1, 3), nil)
|
ts.RequestEvent(request.EvTimeout, ts.Request(1, 3), nil)
|
||||||
// no allowance, no more requests
|
// no allowance, no more requests
|
||||||
ts.Run(10)
|
ts.Run(4)
|
||||||
|
|
||||||
// valid response to requests 6 and 8 and 9
|
// valid response to requests 6 and 8 and 9
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(1, 6), testRespUpdate(ts.Request(1, 6)))
|
ts.RequestEvent(request.EvResponse, ts.Request(1, 6), testRespUpdate(ts.Request(1, 6)))
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(8, 1), testRespUpdate(ts.Request(8, 1)))
|
ts.RequestEvent(request.EvResponse, ts.Request(3, 1), testRespUpdate(ts.Request(3, 1)))
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(8, 2), testRespUpdate(ts.Request(8, 2)))
|
ts.RequestEvent(request.EvResponse, ts.Request(3, 2), testRespUpdate(ts.Request(3, 2)))
|
||||||
ts.AddAllowance(testServer2, 3)
|
ts.AddAllowance(testServer2, 3)
|
||||||
// server 2 can now resend requests 2 and 3 (timed out by server 1) and also send a new one
|
// server 2 can now resend requests 2 and 3 (timed out by server 1) and also send a new one
|
||||||
ts.Run(11,
|
ts.Run(5,
|
||||||
testServer2, ReqUpdates{FirstPeriod: 8, Count: 8},
|
testServer2, ReqUpdates{FirstPeriod: 8, Count: 8},
|
||||||
testServer2, ReqUpdates{FirstPeriod: 16, Count: 8},
|
testServer2, ReqUpdates{FirstPeriod: 16, Count: 8},
|
||||||
testServer2, ReqUpdates{FirstPeriod: 72, Count: 8})
|
testServer2, ReqUpdates{FirstPeriod: 72, Count: 8})
|
||||||
|
|
@ -118,14 +118,14 @@ func TestUpdateSyncParallel(t *testing.T) {
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(1, 2), testRespUpdate(ts.Request(1, 2)))
|
ts.RequestEvent(request.EvResponse, ts.Request(1, 2), testRespUpdate(ts.Request(1, 2)))
|
||||||
ts.AddAllowance(testServer1, 1)
|
ts.AddAllowance(testServer1, 1)
|
||||||
// expect sync progress and one new request
|
// expect sync progress and one new request
|
||||||
ts.Run(14, testServer1, ReqUpdates{FirstPeriod: 80, Count: 8})
|
ts.Run(6, testServer1, ReqUpdates{FirstPeriod: 80, Count: 8})
|
||||||
chain.ExpNextSyncPeriod(t, 16)
|
chain.ExpNextSyncPeriod(t, 16)
|
||||||
|
|
||||||
// server 2 answers requests 11 and 12 (resends of requests 2 and 3)
|
// server 2 answers requests 11 and 12 (resends of requests 2 and 3)
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(11, 1), testRespUpdate(ts.Request(11, 1)))
|
ts.RequestEvent(request.EvResponse, ts.Request(5, 1), testRespUpdate(ts.Request(5, 1)))
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(11, 2), testRespUpdate(ts.Request(11, 2)))
|
ts.RequestEvent(request.EvResponse, ts.Request(5, 2), testRespUpdate(ts.Request(5, 2)))
|
||||||
ts.AddAllowance(testServer2, 2)
|
ts.AddAllowance(testServer2, 2)
|
||||||
ts.Run(15,
|
ts.Run(7,
|
||||||
testServer2, ReqUpdates{FirstPeriod: 88, Count: 8},
|
testServer2, ReqUpdates{FirstPeriod: 88, Count: 8},
|
||||||
testServer2, ReqUpdates{FirstPeriod: 96, Count: 4})
|
testServer2, ReqUpdates{FirstPeriod: 96, Count: 4})
|
||||||
// finally the gap is filled, update can process responses up to req6
|
// finally the gap is filled, update can process responses up to req6
|
||||||
|
|
@ -133,12 +133,12 @@ func TestUpdateSyncParallel(t *testing.T) {
|
||||||
|
|
||||||
// all remaining requests are answered
|
// all remaining requests are answered
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(1, 3), testRespUpdate(ts.Request(1, 3)))
|
ts.RequestEvent(request.EvResponse, ts.Request(1, 3), testRespUpdate(ts.Request(1, 3)))
|
||||||
|
ts.RequestEvent(request.EvResponse, ts.Request(2, 1), testRespUpdate(ts.Request(2, 1)))
|
||||||
|
ts.RequestEvent(request.EvResponse, ts.Request(5, 3), testRespUpdate(ts.Request(5, 3)))
|
||||||
|
ts.RequestEvent(request.EvResponse, ts.Request(6, 1), testRespUpdate(ts.Request(6, 1)))
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(7, 1), testRespUpdate(ts.Request(7, 1)))
|
ts.RequestEvent(request.EvResponse, ts.Request(7, 1), testRespUpdate(ts.Request(7, 1)))
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(11, 3), testRespUpdate(ts.Request(11, 3)))
|
ts.RequestEvent(request.EvResponse, ts.Request(7, 2), testRespUpdate(ts.Request(7, 2)))
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(14, 1), testRespUpdate(ts.Request(14, 1)))
|
ts.Run(8)
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(15, 1), testRespUpdate(ts.Request(15, 1)))
|
|
||||||
ts.RequestEvent(request.EvResponse, ts.Request(15, 2), testRespUpdate(ts.Request(15, 2)))
|
|
||||||
ts.Run(17)
|
|
||||||
// expect chain to be fully synced
|
// expect chain to be fully synced
|
||||||
chain.ExpNextSyncPeriod(t, 100)
|
chain.ExpNextSyncPeriod(t, 100)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ func newBeaconBlockSync(headTracker headTracker) *beaconBlockSync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process implements request.Module.
|
||||||
func (s *beaconBlockSync) Process(requester request.Requester, events []request.Event) {
|
func (s *beaconBlockSync) Process(requester request.Requester, events []request.Event) {
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
switch event.Type {
|
switch event.Type {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue