les, tests: fix les clientpool (#22756)

* les, tests: fix les clientpool

* tests: disable debug mode

* les: polish code
pull/22761/head
gary rong 4 years ago committed by GitHub
parent 9e5bb84c0e
commit 6d7c9566df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      les/vflux/server/clientpool.go
  2. 76
      tests/fuzzers/vflux/clientpool-fuzzer.go
  3. 3
      tests/fuzzers/vflux/debug/main.go

@ -239,12 +239,11 @@ func (cp *ClientPool) SetCapacity(node *enode.Node, reqCap uint64, bias time.Dur
maxTarget = curve.maxCapacity(func(capacity uint64) int64 { maxTarget = curve.maxCapacity(func(capacity uint64) int64 {
return balance.estimatePriority(capacity, 0, 0, bias, false) return balance.estimatePriority(capacity, 0, 0, bias, false)
}) })
if maxTarget <= capacity { if maxTarget < reqCap {
return return
} }
if maxTarget > reqCap { maxTarget = reqCap
maxTarget = reqCap
}
// Specify a narrow target range that allows a limited number of fine step // Specify a narrow target range that allows a limited number of fine step
// iterations // iterations
minTarget = maxTarget - maxTarget/20 minTarget = maxTarget - maxTarget/20

@ -28,11 +28,22 @@ import (
"github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/les/vflux" "github.com/ethereum/go-ethereum/les/vflux"
vfs "github.com/ethereum/go-ethereum/les/vflux/server" vfs "github.com/ethereum/go-ethereum/les/vflux/server"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
var (
debugMode = false
doLog = func(msg string, ctx ...interface{}) {
if !debugMode {
return
}
log.Info(msg, ctx...)
}
)
type fuzzer struct { type fuzzer struct {
peers [256]*clientPeer peers [256]*clientPeer
disconnectList []*clientPeer disconnectList []*clientPeer
@ -65,6 +76,7 @@ func (p *clientPeer) InactiveAllowance() time.Duration {
} }
func (p *clientPeer) UpdateCapacity(newCap uint64, requested bool) { func (p *clientPeer) UpdateCapacity(newCap uint64, requested bool) {
origin, originTotal := p.capacity, p.fuzzer.activeCap
p.fuzzer.activeCap -= p.capacity p.fuzzer.activeCap -= p.capacity
if p.capacity != 0 { if p.capacity != 0 {
p.fuzzer.activeCount-- p.fuzzer.activeCount--
@ -74,9 +86,11 @@ func (p *clientPeer) UpdateCapacity(newCap uint64, requested bool) {
if p.capacity != 0 { if p.capacity != 0 {
p.fuzzer.activeCount++ p.fuzzer.activeCount++
} }
doLog("Update capacity", "peer", p.node.ID(), "origin", origin, "cap", newCap, "origintotal", originTotal, "total", p.fuzzer.activeCap, "requested", requested)
} }
func (p *clientPeer) Disconnect() { func (p *clientPeer) Disconnect() {
origin, originTotal := p.capacity, p.fuzzer.activeCap
p.fuzzer.disconnectList = append(p.fuzzer.disconnectList, p) p.fuzzer.disconnectList = append(p.fuzzer.disconnectList, p)
p.fuzzer.activeCap -= p.capacity p.fuzzer.activeCap -= p.capacity
if p.capacity != 0 { if p.capacity != 0 {
@ -84,6 +98,7 @@ func (p *clientPeer) Disconnect() {
} }
p.capacity = 0 p.capacity = 0
p.balance = nil p.balance = nil
doLog("Disconnect", "peer", p.node.ID(), "origin", origin, "origintotal", originTotal, "total", p.fuzzer.activeCap)
} }
func newFuzzer(input []byte) *fuzzer { func newFuzzer(input []byte) *fuzzer {
@ -165,12 +180,16 @@ func (f *fuzzer) randomFactors() vfs.PriceFactors {
} }
} }
func (f *fuzzer) connectedBalanceOp(balance vfs.ConnectedBalance) { func (f *fuzzer) connectedBalanceOp(balance vfs.ConnectedBalance, id enode.ID) {
switch f.randomInt(3) { switch f.randomInt(3) {
case 0: case 0:
balance.RequestServed(uint64(f.randomTokenAmount(false))) cost := uint64(f.randomTokenAmount(false))
balance.RequestServed(cost)
doLog("Serve request cost", "id", id, "amount", cost)
case 1: case 1:
balance.SetPriceFactors(f.randomFactors(), f.randomFactors()) posFactor, negFactor := f.randomFactors(), f.randomFactors()
balance.SetPriceFactors(posFactor, negFactor)
doLog("Set price factor", "pos", posFactor, "neg", negFactor)
case 2: case 2:
balance.GetBalance() balance.GetBalance()
balance.GetRawBalance() balance.GetRawBalance()
@ -178,12 +197,16 @@ func (f *fuzzer) connectedBalanceOp(balance vfs.ConnectedBalance) {
} }
} }
func (f *fuzzer) atomicBalanceOp(balance vfs.AtomicBalanceOperator) { func (f *fuzzer) atomicBalanceOp(balance vfs.AtomicBalanceOperator, id enode.ID) {
switch f.randomInt(3) { switch f.randomInt(3) {
case 0: case 0:
balance.AddBalance(f.randomTokenAmount(true)) amount := f.randomTokenAmount(true)
balance.AddBalance(amount)
doLog("Add balance", "id", id, "amount", amount)
case 1: case 1:
balance.SetBalance(uint64(f.randomTokenAmount(false)), uint64(f.randomTokenAmount(false))) pos, neg := uint64(f.randomTokenAmount(false)), uint64(f.randomTokenAmount(false))
balance.SetBalance(pos, neg)
doLog("Set balance", "id", id, "pos", pos, "neg", neg)
case 2: case 2:
balance.GetBalance() balance.GetBalance()
balance.GetRawBalance() balance.GetRawBalance()
@ -212,33 +235,53 @@ func FuzzClientPool(input []byte) int {
case 0: case 0:
i := int(f.randomByte()) i := int(f.randomByte())
f.peers[i].balance = pool.Register(f.peers[i]) f.peers[i].balance = pool.Register(f.peers[i])
doLog("Register peer", "id", f.peers[i].node.ID())
case 1: case 1:
i := int(f.randomByte()) i := int(f.randomByte())
f.peers[i].Disconnect() f.peers[i].Disconnect()
doLog("Disconnect peer", "id", f.peers[i].node.ID())
case 2: case 2:
f.maxCount = uint64(f.randomByte()) f.maxCount = uint64(f.randomByte())
f.maxCap = uint64(f.randomByte()) f.maxCap = uint64(f.randomByte())
f.maxCap *= f.maxCap f.maxCap *= f.maxCap
count, cap := pool.Limits()
pool.SetLimits(f.maxCount, f.maxCap) pool.SetLimits(f.maxCount, f.maxCap)
doLog("Set limits", "maxcount", f.maxCount, "maxcap", f.maxCap, "origincount", count, "oricap", cap)
case 3: case 3:
bias := f.randomDelay()
pool.SetConnectedBias(f.randomDelay()) pool.SetConnectedBias(f.randomDelay())
doLog("Set connection bias", "bias", bias)
case 4: case 4:
pool.SetDefaultFactors(f.randomFactors(), f.randomFactors()) pos, neg := f.randomFactors(), f.randomFactors()
pool.SetDefaultFactors(pos, neg)
doLog("Set default factors", "pos", pos, "neg", neg)
case 5: case 5:
pool.SetExpirationTCs(uint64(f.randomInt(50000)), uint64(f.randomInt(50000))) pos, neg := uint64(f.randomInt(50000)), uint64(f.randomInt(50000))
pool.SetExpirationTCs(pos, neg)
doLog("Set expiration constants", "pos", pos, "neg", neg)
case 6: case 6:
if _, err := pool.SetCapacity(f.peers[f.randomByte()].node, uint64(f.randomByte()), f.randomDelay(), f.randomBool()); err == vfs.ErrCantFindMaximum { var (
index = f.randomByte()
reqCap = uint64(f.randomByte())
bias = f.randomDelay()
requested = f.randomBool()
)
if _, err := pool.SetCapacity(f.peers[index].node, reqCap, bias, requested); err == vfs.ErrCantFindMaximum {
panic(nil) panic(nil)
} }
doLog("Set capacity", "id", f.peers[index].node.ID(), "reqcap", reqCap, "bias", bias, "requested", requested)
case 7: case 7:
if balance := f.peers[f.randomByte()].balance; balance != nil { index := f.randomByte()
f.connectedBalanceOp(balance) if balance := f.peers[index].balance; balance != nil {
f.connectedBalanceOp(balance, f.peers[index].node.ID())
} }
case 8: case 8:
pool.BalanceOperation(f.peers[f.randomByte()].node.ID(), f.peers[f.randomByte()].freeID, func(balance vfs.AtomicBalanceOperator) { index := f.randomByte()
pool.BalanceOperation(f.peers[index].node.ID(), f.peers[index].freeID, func(balance vfs.AtomicBalanceOperator) {
count := f.randomInt(4) count := f.randomInt(4)
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
f.atomicBalanceOp(balance) f.atomicBalanceOp(balance, f.peers[index].node.ID())
} }
}) })
case 9: case 9:
@ -272,13 +315,16 @@ func FuzzClientPool(input []byte) int {
for _, peer := range f.disconnectList { for _, peer := range f.disconnectList {
pool.Unregister(peer) pool.Unregister(peer)
doLog("Unregister peer", "id", peer.node.ID())
} }
f.disconnectList = nil f.disconnectList = nil
if d := f.randomDelay(); d > 0 { if d := f.randomDelay(); d > 0 {
clock.Run(d) clock.Run(d)
} }
//fmt.Println(f.activeCount, f.maxCount, f.activeCap, f.maxCap) doLog("Clientpool stats in fuzzer", "count", f.activeCap, "maxcount", f.maxCount, "cap", f.activeCap, "maxcap", f.maxCap)
if activeCount, activeCap := pool.Active(); activeCount != f.activeCount || activeCap != f.activeCap { activeCount, activeCap := pool.Active()
doLog("Clientpool stats in pool", "count", activeCount, "cap", activeCap)
if activeCount != f.activeCount || activeCap != f.activeCap {
panic(nil) panic(nil)
} }
if f.activeCount > f.maxCount || f.activeCap > f.maxCap { if f.activeCount > f.maxCount || f.activeCap > f.maxCap {

@ -21,10 +21,13 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/tests/fuzzers/vflux" "github.com/ethereum/go-ethereum/tests/fuzzers/vflux"
) )
func main() { func main() {
log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
if len(os.Args) != 2 { if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: debug <file>\n") fmt.Fprintf(os.Stderr, "Usage: debug <file>\n")
fmt.Fprintf(os.Stderr, "Example\n") fmt.Fprintf(os.Stderr, "Example\n")

Loading…
Cancel
Save