|
|
@ -54,7 +54,10 @@ const ( |
|
|
|
MaxTxStatus = 256 // Amount of transactions to queried per request
|
|
|
|
MaxTxStatus = 256 // Amount of transactions to queried per request
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
var errTooManyInvalidRequest = errors.New("too many invalid requests made") |
|
|
|
var ( |
|
|
|
|
|
|
|
errTooManyInvalidRequest = errors.New("too many invalid requests made") |
|
|
|
|
|
|
|
errFullClientPool = errors.New("client pool is full") |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// serverHandler is responsible for serving light client and process
|
|
|
|
// serverHandler is responsible for serving light client and process
|
|
|
|
// all incoming light requests.
|
|
|
|
// all incoming light requests.
|
|
|
@ -124,23 +127,26 @@ func (h *serverHandler) handle(p *peer) error { |
|
|
|
} |
|
|
|
} |
|
|
|
defer p.fcClient.Disconnect() |
|
|
|
defer p.fcClient.Disconnect() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Disconnect the inbound peer if it's rejected by clientPool
|
|
|
|
|
|
|
|
if !h.server.clientPool.connect(p, 0) { |
|
|
|
|
|
|
|
p.Log().Debug("Light Ethereum peer registration failed", "err", errFullClientPool) |
|
|
|
|
|
|
|
return errFullClientPool |
|
|
|
|
|
|
|
} |
|
|
|
// Register the peer locally
|
|
|
|
// Register the peer locally
|
|
|
|
if err := h.server.peers.Register(p); err != nil { |
|
|
|
if err := h.server.peers.Register(p); err != nil { |
|
|
|
|
|
|
|
h.server.clientPool.disconnect(p) |
|
|
|
p.Log().Error("Light Ethereum peer registration failed", "err", err) |
|
|
|
p.Log().Error("Light Ethereum peer registration failed", "err", err) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len())) |
|
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len())) |
|
|
|
|
|
|
|
|
|
|
|
// add dummy balance tracker for tests
|
|
|
|
var wg sync.WaitGroup // Wait group used to track all in-flight task routines.
|
|
|
|
if p.balanceTracker == nil { |
|
|
|
|
|
|
|
p.balanceTracker = &balanceTracker{} |
|
|
|
|
|
|
|
p.balanceTracker.init(&mclock.System{}, 1) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
connectedAt := mclock.Now() |
|
|
|
connectedAt := mclock.Now() |
|
|
|
defer func() { |
|
|
|
defer func() { |
|
|
|
p.balanceTracker = nil |
|
|
|
wg.Wait() // Ensure all background task routines have exited.
|
|
|
|
h.server.peers.Unregister(p.id) |
|
|
|
h.server.peers.Unregister(p.id) |
|
|
|
|
|
|
|
h.server.clientPool.disconnect(p) |
|
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len())) |
|
|
|
clientConnectionGauge.Update(int64(h.server.peers.Len())) |
|
|
|
connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) |
|
|
|
connectionTimer.Update(time.Duration(mclock.Now() - connectedAt)) |
|
|
|
}() |
|
|
|
}() |
|
|
@ -153,7 +159,7 @@ func (h *serverHandler) handle(p *peer) error { |
|
|
|
return err |
|
|
|
return err |
|
|
|
default: |
|
|
|
default: |
|
|
|
} |
|
|
|
} |
|
|
|
if err := h.handleMsg(p); err != nil { |
|
|
|
if err := h.handleMsg(p, &wg); err != nil { |
|
|
|
p.Log().Debug("Light Ethereum message handling failed", "err", err) |
|
|
|
p.Log().Debug("Light Ethereum message handling failed", "err", err) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
@ -162,7 +168,7 @@ func (h *serverHandler) handle(p *peer) error { |
|
|
|
|
|
|
|
|
|
|
|
// handleMsg is invoked whenever an inbound message is received from a remote
|
|
|
|
// handleMsg is invoked whenever an inbound message is received from a remote
|
|
|
|
// peer. The remote connection is torn down upon returning any error.
|
|
|
|
// peer. The remote connection is torn down upon returning any error.
|
|
|
|
func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
func (h *serverHandler) handleMsg(p *peer, wg *sync.WaitGroup) error { |
|
|
|
// Read the next message from the remote peer, and ensure it's fully consumed
|
|
|
|
// Read the next message from the remote peer, and ensure it's fully consumed
|
|
|
|
msg, err := p.rw.ReadMsg() |
|
|
|
msg, err := p.rw.ReadMsg() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -243,7 +249,7 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
// Feed cost tracker request serving statistic.
|
|
|
|
// Feed cost tracker request serving statistic.
|
|
|
|
h.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost) |
|
|
|
h.server.costTracker.updateStats(msg.Code, amount, servingTime, realCost) |
|
|
|
// Reduce priority "balance" for the specific peer.
|
|
|
|
// Reduce priority "balance" for the specific peer.
|
|
|
|
p.balanceTracker.requestCost(realCost) |
|
|
|
h.server.clientPool.requestCost(p, realCost) |
|
|
|
} |
|
|
|
} |
|
|
|
if reply != nil { |
|
|
|
if reply != nil { |
|
|
|
p.queueSend(func() { |
|
|
|
p.queueSend(func() { |
|
|
@ -273,7 +279,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
} |
|
|
|
} |
|
|
|
query := req.Query |
|
|
|
query := req.Query |
|
|
|
if accept(req.ReqID, query.Amount, MaxHeaderFetch) { |
|
|
|
if accept(req.ReqID, query.Amount, MaxHeaderFetch) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
hashMode := query.Origin.Hash != (common.Hash{}) |
|
|
|
hashMode := query.Origin.Hash != (common.Hash{}) |
|
|
|
first := true |
|
|
|
first := true |
|
|
|
maxNonCanonical := uint64(100) |
|
|
|
maxNonCanonical := uint64(100) |
|
|
@ -387,7 +395,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
) |
|
|
|
) |
|
|
|
reqCnt := len(req.Hashes) |
|
|
|
reqCnt := len(req.Hashes) |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) { |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxBodyFetch) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
for i, hash := range req.Hashes { |
|
|
|
for i, hash := range req.Hashes { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime) |
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime) |
|
|
@ -433,7 +443,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
) |
|
|
|
) |
|
|
|
reqCnt := len(req.Reqs) |
|
|
|
reqCnt := len(req.Reqs) |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) { |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxCodeFetch) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
for i, request := range req.Reqs { |
|
|
|
for i, request := range req.Reqs { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime) |
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime) |
|
|
@ -502,7 +514,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
) |
|
|
|
) |
|
|
|
reqCnt := len(req.Hashes) |
|
|
|
reqCnt := len(req.Hashes) |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) { |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxReceiptFetch) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
for i, hash := range req.Hashes { |
|
|
|
for i, hash := range req.Hashes { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime) |
|
|
|
sendResponse(req.ReqID, 0, nil, task.servingTime) |
|
|
@ -557,7 +571,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
) |
|
|
|
) |
|
|
|
reqCnt := len(req.Reqs) |
|
|
|
reqCnt := len(req.Reqs) |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) { |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxProofsFetch) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
nodes := light.NewNodeSet() |
|
|
|
nodes := light.NewNodeSet() |
|
|
|
|
|
|
|
|
|
|
|
for i, request := range req.Reqs { |
|
|
|
for i, request := range req.Reqs { |
|
|
@ -658,7 +674,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
) |
|
|
|
) |
|
|
|
reqCnt := len(req.Reqs) |
|
|
|
reqCnt := len(req.Reqs) |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) { |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxHelperTrieProofsFetch) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
var ( |
|
|
|
var ( |
|
|
|
lastIdx uint64 |
|
|
|
lastIdx uint64 |
|
|
|
lastType uint |
|
|
|
lastType uint |
|
|
@ -725,7 +743,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
} |
|
|
|
} |
|
|
|
reqCnt := len(req.Txs) |
|
|
|
reqCnt := len(req.Txs) |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxSend) { |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxSend) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
stats := make([]light.TxStatus, len(req.Txs)) |
|
|
|
stats := make([]light.TxStatus, len(req.Txs)) |
|
|
|
for i, tx := range req.Txs { |
|
|
|
for i, tx := range req.Txs { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
@ -771,7 +791,9 @@ func (h *serverHandler) handleMsg(p *peer) error { |
|
|
|
} |
|
|
|
} |
|
|
|
reqCnt := len(req.Hashes) |
|
|
|
reqCnt := len(req.Hashes) |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) { |
|
|
|
if accept(req.ReqID, uint64(reqCnt), MaxTxStatus) { |
|
|
|
|
|
|
|
wg.Add(1) |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
|
|
|
|
defer wg.Done() |
|
|
|
stats := make([]light.TxStatus, len(req.Hashes)) |
|
|
|
stats := make([]light.TxStatus, len(req.Hashes)) |
|
|
|
for i, hash := range req.Hashes { |
|
|
|
for i, hash := range req.Hashes { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|
if i != 0 && !task.waitOrStop() { |
|
|
|