feat: upgrade go-ethereum (#9)

* feat: use zap logger

* chore: upgrade go-ethereum

* chore: use stdlib min

* fix: IP, Addr, AddrPort changes

* fix: more logging replace
This commit is contained in:
Igor Sirotin 2025-10-03 00:01:39 +01:00 committed by GitHub
parent fe708039d5
commit b9b5a06121
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 173 additions and 297 deletions

View File

@ -20,8 +20,9 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"net" "net"
"go.uber.org/zap"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"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/p2p/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
@ -48,7 +49,7 @@ type Config struct {
NetRestrict *netutil.Netlist // list of allowed IP networks NetRestrict *netutil.Netlist // list of allowed IP networks
Bootnodes []*enode.Node // list of bootstrap nodes Bootnodes []*enode.Node // list of bootstrap nodes
Unhandled chan<- ReadPacket // unhandled packets are sent on this channel Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
Log log.Logger // if set, log messages go here Log *zap.Logger // if set, log messages go here
// V5ProtocolID configures the discv5 protocol identifier. // V5ProtocolID configures the discv5 protocol identifier.
V5ProtocolID *[6]byte V5ProtocolID *[6]byte
@ -59,7 +60,7 @@ type Config struct {
func (cfg Config) withDefaults() Config { func (cfg Config) withDefaults() Config {
if cfg.Log == nil { if cfg.Log == nil {
cfg.Log = log.Root() cfg.Log = zap.NewNop()
} }
if cfg.ValidSchemes == nil { if cfg.ValidSchemes == nil {
cfg.ValidSchemes = enode.ValidSchemes cfg.ValidSchemes = enode.ValidSchemes
@ -81,10 +82,3 @@ type ReadPacket struct {
Data []byte Data []byte
Addr *net.UDPAddr Addr *net.UDPAddr
} }
func min(x, y int) int {
if x > y {
return y
}
return x
}

View File

@ -140,7 +140,7 @@ func (it *lookup) slowdown() {
} }
func (it *lookup) query(n *node, reply chan<- []*node) { func (it *lookup) query(n *node, reply chan<- []*node) {
fails := it.tab.db.FindFails(n.ID(), n.IP()) fails := it.tab.db.FindFails(n.ID(), n.IPAddr())
r, err := it.queryfunc(n) r, err := it.queryfunc(n)
if errors.Is(err, errClosed) { if errors.Is(err, errClosed) {
// Avoid recording failures on shutdown. // Avoid recording failures on shutdown.
@ -148,18 +148,15 @@ func (it *lookup) query(n *node, reply chan<- []*node) {
return return
} else if len(r) == 0 { } else if len(r) == 0 {
fails++ fails++
it.tab.db.UpdateFindFails(n.ID(), n.IP(), fails) it.tab.db.UpdateFindFails(n.ID(), n.IPAddr(), fails)
// Remove the node from the local table if it fails to return anything useful too // Remove the node from the local table if it fails to return anything useful too
// many times, but only if there are enough other nodes in the bucket. // many times, but only if there are enough other nodes in the bucket.
dropped := false
if fails >= maxFindnodeFailures && it.tab.bucketLen(n.ID()) >= bucketSize/2 { if fails >= maxFindnodeFailures && it.tab.bucketLen(n.ID()) >= bucketSize/2 {
dropped = true
it.tab.delete(n) it.tab.delete(n)
} }
it.tab.log.Trace("FINDNODE failed", "id", n.ID(), "failcount", fails, "dropped", dropped, "err", err)
} else if fails > 0 { } else if fails > 0 {
// Reset failure counter because it counts _consecutive_ failures. // Reset failure counter because it counts _consecutive_ failures.
it.tab.db.UpdateFindFails(n.ID(), n.IP(), 0) it.tab.db.UpdateFindFails(n.ID(), n.IPAddr(), 0)
} }
// Grab as many nodes as possible. Some of them might not be alive anymore, but we'll // Grab as many nodes as possible. Some of them might not be alive anymore, but we'll

View File

@ -44,7 +44,7 @@ type meteredUdpConn struct {
func newMeteredConn(conn UDPConn) UDPConn { func newMeteredConn(conn UDPConn) UDPConn {
// Short circuit if metrics are disabled // Short circuit if metrics are disabled
if !metrics.Enabled { if !metrics.Enabled() {
return conn return conn
} }
return &meteredUdpConn{UDPConn: conn} return &meteredUdpConn{UDPConn: conn}

View File

@ -20,12 +20,11 @@
package discover package discover
import ( import (
"fmt"
"net" "net"
"sort" "sort"
"time" "time"
"github.com/ethereum/go-ethereum/log" "go.uber.org/zap"
) )
const ( const (
@ -49,10 +48,10 @@ func checkClockDrift() {
return return
} }
if drift < -driftThreshold || drift > driftThreshold { if drift < -driftThreshold || drift > driftThreshold {
log.Warn(fmt.Sprintf("System clock seems off by %v, which can prevent network connectivity", drift)) zap.L().Warn("System clock seems off", zap.Duration("drift", drift))
log.Warn("Please enable network time synchronisation in system settings.") zap.L().Warn("Please enable network time synchronisation in system settings.")
} else { } else {
log.Debug("NTP sanity check done", "drift", drift) zap.L().Debug("NTP sanity check done", zap.Duration("drift", drift))
} }
} }

View File

@ -32,8 +32,9 @@ import (
"sync" "sync"
"time" "time"
"go.uber.org/zap"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"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/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
) )
@ -71,7 +72,7 @@ type Table struct {
rand *mrand.Rand // source of randomness, periodically reseeded rand *mrand.Rand // source of randomness, periodically reseeded
ips netutil.DistinctNetSet ips netutil.DistinctNetSet
log log.Logger log *zap.Logger
db *enode.DB // database of known nodes db *enode.DB // database of known nodes
net transport net transport
refreshReq chan chan struct{} refreshReq chan chan struct{}
@ -99,26 +100,32 @@ type bucket struct {
ips netutil.DistinctNetSet ips netutil.DistinctNetSet
} }
func newTable(t transport, db *enode.DB, bootnodes []*enode.Node, log log.Logger) (*Table, error) { func newTable(t transport, db *enode.DB, bootnodes []*enode.Node, logger *zap.Logger) (*Table, error) {
buckets := [nBuckets]*bucket{}
for i := range buckets {
buckets[i] = &bucket{
ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
}
}
nursery := wrapNodes(bootnodes)
tab := &Table{ tab := &Table{
net: t, mutex: sync.Mutex{},
buckets: buckets,
nursery: nursery,
rand: mrand.New(mrand.NewSource(time.Now().UnixNano())),
ips: netutil.DistinctNetSet{},
log: logger,
db: db, db: db,
net: t,
refreshReq: make(chan chan struct{}), refreshReq: make(chan chan struct{}),
initDone: make(chan struct{}), initDone: make(chan struct{}),
closeReq: make(chan struct{}), closeReq: make(chan struct{}),
closed: make(chan struct{}), closed: make(chan struct{}),
rand: mrand.New(mrand.NewSource(0)),
ips: netutil.DistinctNetSet{Subnet: tableSubnet, Limit: tableIPLimit},
log: log,
} }
if err := tab.setFallbackNodes(bootnodes); err != nil { if err := tab.setFallbackNodes(bootnodes); err != nil {
return nil, err return nil, err
} }
for i := range tab.buckets {
tab.buckets[i] = &bucket{
ips: netutil.DistinctNetSet{Subnet: bucketSubnet, Limit: bucketIPLimit},
}
}
tab.seedRand() tab.seedRand()
tab.loadSeedNodes() tab.loadSeedNodes()
@ -309,8 +316,6 @@ func (tab *Table) loadSeedNodes() {
tab.mutex.Unlock() tab.mutex.Unlock()
for i := range seeds { for i := range seeds {
seed := seeds[i] seed := seeds[i]
age := log.Lazy{Fn: func() interface{} { return time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP())) }}
tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", seed.addr(), "age", age)
tab.addSeenNode(seed) tab.addSeenNode(seed)
} }
} }
@ -329,32 +334,41 @@ func (tab *Table) doRevalidate(done chan<- struct{}) {
// Ping the selected node and wait for a pong. // Ping the selected node and wait for a pong.
remoteSeq, err := tab.net.ping(unwrapNode(last)) remoteSeq, err := tab.net.ping(unwrapNode(last))
logger := tab.log.With(zap.Stringer("id", last.ID()), zap.Stringer("addr", last.addr()))
// Also fetch record if the node replied and returned a higher sequence number. // Also fetch record if the node replied and returned a higher sequence number.
if last.Seq() < remoteSeq { if last.Seq() < remoteSeq {
n, err := tab.net.RequestENR(unwrapNode(last)) n, err := tab.net.RequestENR(unwrapNode(last))
if err != nil { if err != nil {
tab.log.Debug("ENR request failed", "id", last.ID(), "addr", last.addr(), "err", err) logger.Debug("ENR request failed", zap.Error(err))
} else { } else {
last = &node{Node: *n, addedAt: last.addedAt, livenessChecks: last.livenessChecks} last = &node{Node: *n, addedAt: last.addedAt, livenessChecks: last.livenessChecks}
} }
} }
logger = logger.With(zap.Int("b", bi))
tab.mutex.Lock() tab.mutex.Lock()
defer tab.mutex.Unlock() defer tab.mutex.Unlock()
b := tab.buckets[bi] b := tab.buckets[bi]
if err == nil { if err == nil {
// The node responded, move it to the front. // The node responded, move it to the front.
last.livenessChecks++ last.livenessChecks++
tab.log.Debug("Revalidated node", "b", bi, "id", last.ID(), "checks", last.livenessChecks) logger.Debug("Revalidated node", zap.Uint("checks", last.livenessChecks))
tab.bumpInBucket(b, last) tab.bumpInBucket(b, last)
return return
} }
// No reply received, pick a replacement or delete the node if there aren't // No reply received, pick a replacement or delete the node if there aren't
// any replacements. // any replacements.
if r := tab.replace(b, last); r != nil { if r := tab.replace(b, last); r != nil {
tab.log.Debug("Replaced dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks, "r", r.ID(), "rip", r.IP()) tab.log.Debug("Replaced dead node",
zap.Uint("checks", last.livenessChecks),
zap.Stringer("r", r.ID()),
zap.Stringer("rip", r.IP()))
} else { } else {
tab.log.Debug("Removed dead node", "b", bi, "id", last.ID(), "ip", last.IP(), "checks", last.livenessChecks) tab.log.Debug("Removed dead node",
zap.Uint("checks", last.livenessChecks))
} }
} }
@ -552,11 +566,11 @@ func (tab *Table) addIP(b *bucket, ip net.IP) bool {
return true return true
} }
if !tab.ips.Add(ip) { if !tab.ips.Add(ip) {
tab.log.Debug("IP exceeds table limit", "ip", ip) tab.log.Debug("IP exceeds table limit", zap.Stringer("ip", ip))
return false return false
} }
if !b.ips.Add(ip) { if !b.ips.Add(ip) {
tab.log.Debug("IP exceeds bucket limit", "ip", ip) tab.log.Debug("IP exceeds bucket limit", zap.Stringer("ip", ip))
tab.ips.Remove(ip) tab.ips.Remove(ip)
return false return false
} }

View File

@ -27,8 +27,9 @@ import (
"sort" "sort"
"sync" "sync"
"go.uber.org/zap"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"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"
) )
@ -43,7 +44,11 @@ func init() {
func newTestTable(t transport) (*Table, *enode.DB) { func newTestTable(t transport) (*Table, *enode.DB) {
db, _ := enode.OpenDB("") db, _ := enode.OpenDB("")
tab, _ := newTable(t, db, nil, log.Root()) logger, err := zap.NewDevelopment()
if err != nil {
panic(err)
}
tab, _ := newTable(t, db, nil, logger)
go tab.loop() go tab.loop()
return tab, db return tab, db
} }

View File

@ -26,13 +26,16 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"net/netip"
"sync" "sync"
"time" "time"
"go.uber.org/zap"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"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/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/waku-org/go-discover/discover/v4wire" "github.com/waku-org/go-discover/discover/v4wire"
) )
@ -66,7 +69,7 @@ const (
// UDPv4 implements the v4 wire protocol. // UDPv4 implements the v4 wire protocol.
type UDPv4 struct { type UDPv4 struct {
conn UDPConn conn UDPConn
log log.Logger log *zap.Logger
netrestrict *netutil.Netlist netrestrict *netutil.Netlist
priv *ecdsa.PrivateKey priv *ecdsa.PrivateKey
localNode *enode.LocalNode localNode *enode.LocalNode
@ -241,7 +244,7 @@ func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *r
return matched, matched return matched, matched
}) })
// Send the packet. // Send the packet.
t.localNode.UDPContact(toaddr) t.localNode.UDPContact(toaddr.AddrPort())
t.write(toaddr, toid, req.Name(), packet) t.write(toaddr, toid, req.Name(), packet)
return rm return rm
} }
@ -311,7 +314,6 @@ func (t *UDPv4) findnode(toid enode.ID, toaddr *net.UDPAddr, target v4wire.Pubke
nreceived++ nreceived++
n, err := t.nodeFromRPC(toaddr, rn) n, err := t.nodeFromRPC(toaddr, rn)
if err != nil { if err != nil {
t.log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toaddr, "err", err)
continue continue
} }
nodes = append(nodes, n) nodes = append(nodes, n)
@ -506,7 +508,6 @@ func (t *UDPv4) send(toaddr *net.UDPAddr, toid enode.ID, req v4wire.Packet) ([]b
func (t *UDPv4) write(toaddr *net.UDPAddr, toid enode.ID, what string, packet []byte) error { func (t *UDPv4) write(toaddr *net.UDPAddr, toid enode.ID, what string, packet []byte) error {
_, err := t.conn.WriteToUDP(packet, toaddr) _, err := t.conn.WriteToUDP(packet, toaddr)
t.log.Trace(">> "+what, "id", toid, "addr", toaddr, "err", err)
return err return err
} }
@ -522,12 +523,12 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) {
nbytes, from, err := t.conn.ReadFromUDP(buf) nbytes, from, err := t.conn.ReadFromUDP(buf)
if netutil.IsTemporaryError(err) { if netutil.IsTemporaryError(err) {
// Ignore temporary read errors. // Ignore temporary read errors.
t.log.Debug("Temporary UDP read error", "err", err) t.log.Debug("Temporary UDP read error", zap.Error(err))
continue continue
} else if err != nil { } else if err != nil {
// Shut down the loop for permanent errors. // Shut down the loop for permanent errors.
if !errors.Is(err, io.EOF) { if !errors.Is(err, io.EOF) {
t.log.Debug("UDP read error", "err", err) t.log.Debug("UDP read error", zap.Error(err))
} }
return return
} }
@ -543,7 +544,10 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) {
func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error { func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error {
rawpacket, fromKey, hash, err := v4wire.Decode(buf) rawpacket, fromKey, hash, err := v4wire.Decode(buf)
if err != nil { if err != nil {
t.log.Debug("Bad discv4 packet", "addr", from, "err", err) t.log.Debug("bad discv4 packet",
zap.Stringer("addr", from),
zap.Error(err),
)
return err return err
} }
packet := t.wrapPacket(rawpacket) packet := t.wrapPacket(rawpacket)
@ -551,7 +555,6 @@ func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error {
if err == nil && packet.preverify != nil { if err == nil && packet.preverify != nil {
err = packet.preverify(packet, from, fromID, fromKey) err = packet.preverify(packet, from, fromID, fromKey)
} }
t.log.Trace("<< "+packet.Name(), "id", fromID, "addr", from, "err", err)
if err == nil && packet.handle != nil { if err == nil && packet.handle != nil {
packet.handle(packet, from, fromID, hash) packet.handle(packet, from, fromID, hash)
} }
@ -559,15 +562,15 @@ func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error {
} }
// checkBond checks if the given node has a recent enough endpoint proof. // checkBond checks if the given node has a recent enough endpoint proof.
func (t *UDPv4) checkBond(id enode.ID, ip net.IP) bool { func (t *UDPv4) checkBond(id enode.ID, addr netip.Addr) bool {
return time.Since(t.db.LastPongReceived(id, ip)) < bondExpiration return time.Since(t.db.LastPongReceived(id, addr)) < bondExpiration
} }
// ensureBond solicits a ping from a node if we haven't seen a ping from it for a while. // ensureBond solicits a ping from a node if we haven't seen a ping from it for a while.
// This ensures there is a valid endpoint proof on the remote end. // This ensures there is a valid endpoint proof on the remote end.
func (t *UDPv4) ensureBond(toid enode.ID, toaddr *net.UDPAddr) { func (t *UDPv4) ensureBond(toid enode.ID, toaddr *net.UDPAddr) {
tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.IP)) > bondExpiration tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.AddrPort().Addr())) > bondExpiration
if tooOld || t.db.FindFails(toid, toaddr.IP) > maxFindnodeFailures { if tooOld || t.db.FindFails(toid, toaddr.AddrPort().Addr()) > maxFindnodeFailures {
rm := t.sendPing(toid, toaddr, nil) rm := t.sendPing(toid, toaddr, nil)
<-rm.errc <-rm.errc
// Wait for them to ping back and process our pong. // Wait for them to ping back and process our pong.
@ -667,7 +670,7 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
// Ping back if our last pong on file is too far in the past. // Ping back if our last pong on file is too far in the past.
n := wrapNode(enode.NewV4(h.senderKey, from.IP, int(req.From.TCP), from.Port)) n := wrapNode(enode.NewV4(h.senderKey, from.IP, int(req.From.TCP), from.Port))
if time.Since(t.db.LastPongReceived(n.ID(), from.IP)) > bondExpiration { if time.Since(t.db.LastPongReceived(n.ID(), from.AddrPort().Addr())) > bondExpiration {
t.sendPing(fromID, from, func() { t.sendPing(fromID, from, func() {
t.tab.addVerifiedNode(n) t.tab.addVerifiedNode(n)
}) })
@ -676,8 +679,8 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
} }
// Update node database and endpoint predictor. // Update node database and endpoint predictor.
t.db.UpdateLastPingReceived(n.ID(), from.IP, time.Now()) t.db.UpdateLastPingReceived(n.ID(), from.AddrPort().Addr(), time.Now())
t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}) t.localNode.UDPEndpointStatement(from.AddrPort(), req.To.UDPAddrPort())
} }
// PONG/v4 // PONG/v4
@ -691,8 +694,8 @@ func (t *UDPv4) verifyPong(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
if !t.handleReply(fromID, from.IP, req) { if !t.handleReply(fromID, from.IP, req) {
return errUnsolicitedReply return errUnsolicitedReply
} }
t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}) t.localNode.UDPEndpointStatement(from.AddrPort(), req.To.UDPAddrPort())
t.db.UpdateLastPongReceived(fromID, from.IP, time.Now()) t.db.UpdateLastPongReceived(fromID, from.AddrPort().Addr(), time.Now())
return nil return nil
} }
@ -704,7 +707,7 @@ func (t *UDPv4) verifyFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno
if v4wire.Expired(req.Expiration) { if v4wire.Expired(req.Expiration) {
return errExpired return errExpired
} }
if !t.checkBond(fromID, from.IP) { if !t.checkBond(fromID, from.AddrPort().Addr()) {
// No endpoint proof pong exists, we don't process the packet. This prevents an // No endpoint proof pong exists, we don't process the packet. This prevents an
// attack vector where the discovery protocol could be used to amplify traffic in a // attack vector where the discovery protocol could be used to amplify traffic in a
// DDOS attack. A malicious actor would send a findnode request with the IP address // DDOS attack. A malicious actor would send a findnode request with the IP address
@ -764,7 +767,7 @@ func (t *UDPv4) verifyENRRequest(h *packetHandlerV4, from *net.UDPAddr, fromID e
if v4wire.Expired(req.Expiration) { if v4wire.Expired(req.Expiration) {
return errExpired return errExpired
} }
if !t.checkBond(fromID, from.IP) { if !t.checkBond(fromID, from.AddrPort().Addr()) {
return errUnknownNode return errUnknownNode
} }
return nil return nil

View File

@ -31,11 +31,11 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum/go-ethereum/log" "go.uber.org/zap"
"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/waku-org/go-discover/discover/v4wire" "github.com/waku-org/go-discover/discover/v4wire"
"github.com/waku-org/go-discover/internal/testlog"
) )
// shared test variables // shared test variables
@ -71,7 +71,7 @@ func newUDPTest(t *testing.T) *udpTest {
ln := enode.NewLocalNode(test.db, test.localkey) ln := enode.NewLocalNode(test.db, test.localkey)
test.udp, _ = ListenV4(test.pipe, ln, Config{ test.udp, _ = ListenV4(test.pipe, ln, Config{
PrivateKey: test.localkey, PrivateKey: test.localkey,
Log: testlog.Logger(t, log.LvlTrace), Log: zap.NewNop(),
}) })
test.table = test.udp.tab test.table = test.udp.tab
// Wait for initial refresh so the table doesn't send unexpected findnode. // Wait for initial refresh so the table doesn't send unexpected findnode.
@ -555,15 +555,6 @@ func startLocalhostV4(t *testing.T, cfg Config) *UDPv4 {
db, _ := enode.OpenDB("") db, _ := enode.OpenDB("")
ln := enode.NewLocalNode(db, cfg.PrivateKey) ln := enode.NewLocalNode(db, cfg.PrivateKey)
// Prefix logs with node ID.
lprefix := fmt.Sprintf("(%s)", ln.ID().TerminalString())
lfmt := log.TerminalFormat(false)
cfg.Log = testlog.Logger(t, log.LvlTrace)
cfg.Log.SetHandler(log.FuncHandler(func(r *log.Record) error {
t.Logf("%s %s", lprefix, lfmt.Format(r))
return nil
}))
// Listen. // Listen.
socket, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IP{127, 0, 0, 1}}) socket, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IP{127, 0, 0, 1}})
if err != nil { if err != nil {

View File

@ -25,6 +25,7 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"net" "net"
"net/netip"
"time" "time"
"github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common/math"
@ -151,13 +152,16 @@ type Endpoint struct {
// NewEndpoint creates an endpoint. // NewEndpoint creates an endpoint.
func NewEndpoint(addr *net.UDPAddr, tcpPort uint16) Endpoint { func NewEndpoint(addr *net.UDPAddr, tcpPort uint16) Endpoint {
ip := net.IP{} return Endpoint{
if ip4 := addr.IP.To4(); ip4 != nil { IP: addr.IP,
ip = ip4 UDP: uint16(addr.Port),
} else if ip6 := addr.IP.To16(); ip6 != nil { TCP: tcpPort,
ip = ip6
} }
return Endpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} }
func (ep *Endpoint) UDPAddrPort() netip.AddrPort {
addr, _ := netip.AddrFromSlice(ep.IP)
return netip.AddrPortFrom(addr, ep.UDP)
} }
type Packet interface { type Packet interface {

View File

@ -21,7 +21,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/ethereum/go-ethereum/log" "go.uber.org/zap"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/waku-org/go-discover/discover/v5wire" "github.com/waku-org/go-discover/discover/v5wire"
) )
@ -95,7 +96,7 @@ func (t *talkSystem) handleRequest(id enode.ID, addr *net.UDPAddr, req *v5wire.T
case <-timeout.C: case <-timeout.C:
// Couldn't get it in time, drop the request. // Couldn't get it in time, drop the request.
if time.Since(t.lastLog) > 5*time.Second { if time.Since(t.lastLog) > 5*time.Second {
log.Warn("Dropping TALKREQ due to overload", "ndrop", t.dropCount) t.transport.log.Warn("Dropping TALKREQ due to overload", zap.Int("ndrop", t.dropCount))
t.lastLog = time.Now() t.lastLog = time.Now()
t.dropCount++ t.dropCount++
} }

View File

@ -25,14 +25,17 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"net/netip"
"sync" "sync"
"time" "time"
"go.uber.org/zap"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"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/p2p/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/waku-org/go-discover/discover/v5wire" "github.com/waku-org/go-discover/discover/v5wire"
) )
@ -66,7 +69,7 @@ type UDPv5 struct {
priv *ecdsa.PrivateKey priv *ecdsa.PrivateKey
localNode *enode.LocalNode localNode *enode.LocalNode
db *enode.DB db *enode.DB
log log.Logger log *zap.Logger
clock mclock.Clock clock mclock.Clock
validSchemes enr.IdentityScheme validSchemes enr.IdentityScheme
@ -403,7 +406,10 @@ func (t *UDPv5) waitForNodes(c *callV5, distances []uint) ([]*enode.Node, error)
for _, record := range response.Nodes { for _, record := range response.Nodes {
node, err := t.verifyResponseNode(c, record, distances, seen) node, err := t.verifyResponseNode(c, record, distances, seen)
if err != nil { if err != nil {
t.log.Debug("Invalid record in "+response.Name(), "id", c.node.ID(), "err", err) t.log.Debug("Invalid record in "+response.Name(),
zap.Stringer("id", c.node.ID()),
zap.Error(err),
)
continue continue
} }
nodes = append(nodes, node) nodes = append(nodes, node)
@ -648,12 +654,11 @@ func (t *UDPv5) send(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet, c
enc, nonce, err := t.codec.Encode(toID, addr, packet, c) enc, nonce, err := t.codec.Encode(toID, addr, packet, c)
if err != nil { if err != nil {
t.logcontext = append(t.logcontext, "err", err) t.logcontext = append(t.logcontext, "err", err)
t.log.Warn(">> "+packet.Name(), t.logcontext...) t.log.Warn(">> "+packet.Name(), zap.Any("context", t.logcontext))
return nonce, err return nonce, err
} }
_, err = t.conn.WriteToUDP(enc, toAddr) _, err = t.conn.WriteToUDP(enc, toAddr)
t.log.Trace(">> "+packet.Name(), t.logcontext...)
return nonce, err return nonce, err
} }
@ -666,12 +671,12 @@ func (t *UDPv5) readLoop() {
nbytes, from, err := t.conn.ReadFromUDP(buf) nbytes, from, err := t.conn.ReadFromUDP(buf)
if netutil.IsTemporaryError(err) { if netutil.IsTemporaryError(err) {
// Ignore temporary read errors. // Ignore temporary read errors.
t.log.Debug("Temporary UDP read error", "err", err) t.log.Debug("Temporary UDP read error", zap.Error(err))
continue continue
} else if err != nil { } else if err != nil {
// Shut down the loop for permanent errors. // Shut down the loop for permanent errors.
if !errors.Is(err, io.EOF) { if !errors.Is(err, io.EOF) {
t.log.Debug("UDP read error", "err", err) t.log.Debug("UDP read error", zap.Error(err))
} }
return return
} }
@ -696,13 +701,12 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error {
if err != nil { if err != nil {
if t.unhandled != nil && v5wire.IsInvalidHeader(err) { if t.unhandled != nil && v5wire.IsInvalidHeader(err) {
// The packet seems unrelated to discv5, send it to the next protocol. // The packet seems unrelated to discv5, send it to the next protocol.
// t.log.Trace("Unhandled discv5 packet", "id", fromID, "addr", addr, "err", err)
up := ReadPacket{Data: make([]byte, len(rawpacket)), Addr: fromAddr} up := ReadPacket{Data: make([]byte, len(rawpacket)), Addr: fromAddr}
copy(up.Data, rawpacket) copy(up.Data, rawpacket)
t.unhandled <- up t.unhandled <- up
return nil return nil
} }
t.log.Debug("Bad discv5 packet", "id", fromID, "addr", addr, "err", err) t.log.Debug("Bad discv5 packet", zap.Stringer("id", fromID), zap.Stringer("addr", fromAddr), zap.Error(err))
return err return err
} }
if fromNode != nil { if fromNode != nil {
@ -713,7 +717,6 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error {
// WHOAREYOU logged separately to report errors. // WHOAREYOU logged separately to report errors.
t.logcontext = append(t.logcontext[:0], "id", fromID, "addr", addr) t.logcontext = append(t.logcontext[:0], "id", fromID, "addr", addr)
t.logcontext = packet.AppendLogInfo(t.logcontext) t.logcontext = packet.AppendLogInfo(t.logcontext)
t.log.Trace("<< "+packet.Name(), t.logcontext...)
} }
t.handle(packet, fromID, fromAddr) t.handle(packet, fromID, fromAddr)
return nil return nil
@ -723,15 +726,15 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error {
func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr *net.UDPAddr, p v5wire.Packet) bool { func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr *net.UDPAddr, p v5wire.Packet) bool {
ac := t.activeCallByNode[fromID] ac := t.activeCallByNode[fromID]
if ac == nil || !bytes.Equal(p.RequestID(), ac.reqid) { if ac == nil || !bytes.Equal(p.RequestID(), ac.reqid) {
t.log.Debug(fmt.Sprintf("Unsolicited/late %s response", p.Name()), "id", fromID, "addr", fromAddr) t.log.Debug(fmt.Sprintf("Unsolicited/late %s response", p.Name()), zap.Stringer("id", fromID), zap.Stringer("addr", fromAddr))
return false return false
} }
if !fromAddr.IP.Equal(ac.addr.IP) || fromAddr.Port != ac.addr.Port { if !fromAddr.IP.Equal(ac.addr.IP) || fromAddr.Port != ac.addr.Port {
t.log.Debug(fmt.Sprintf("%s from wrong endpoint", p.Name()), "id", fromID, "addr", fromAddr) t.log.Debug(fmt.Sprintf("%s from wrong endpoint", p.Name()), zap.Stringer("id", fromID), zap.Stringer("addr", fromAddr))
return false return false
} }
if p.Kind() != ac.responseType { if p.Kind() != ac.responseType {
t.log.Debug(fmt.Sprintf("Wrong discv5 response type %s", p.Name()), "id", fromID, "addr", fromAddr) t.log.Debug(fmt.Sprintf("Wrong discv5 response type %s", p.Name()), zap.Stringer("id", fromID), zap.Stringer("addr", fromAddr))
return false return false
} }
t.startResponseTimeout(ac) t.startResponseTimeout(ac)
@ -761,7 +764,8 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr *net.UDPAddr)
t.handlePing(p, fromID, fromAddr) t.handlePing(p, fromID, fromAddr)
case *v5wire.Pong: case *v5wire.Pong:
if t.handleCallResponse(fromID, fromAddr, p) { if t.handleCallResponse(fromID, fromAddr, p) {
t.localNode.UDPEndpointStatement(fromAddr, &net.UDPAddr{IP: p.ToIP, Port: int(p.ToPort)}) toAddr, _ := netip.AddrFromSlice(p.ToIP)
t.localNode.UDPEndpointStatement(fromAddr.AddrPort(), netip.AddrPortFrom(toAddr, p.ToPort))
} }
case *v5wire.Findnode: case *v5wire.Findnode:
t.handleFindnode(p, fromID, fromAddr) t.handleFindnode(p, fromID, fromAddr)
@ -794,18 +798,17 @@ var (
func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr *net.UDPAddr) { func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr *net.UDPAddr) {
c, err := t.matchWithCall(fromID, p.Nonce) c, err := t.matchWithCall(fromID, p.Nonce)
if err != nil { if err != nil {
t.log.Debug("Invalid "+p.Name(), "addr", fromAddr, "err", err) t.log.Debug("Invalid "+p.Name(), zap.String("addr", fromAddr.String()), zap.Error(err))
return return
} }
if c.node == nil { if c.node == nil {
// Can't perform handshake because we don't have the ENR. // Can't perform handshake because we don't have the ENR.
t.log.Debug("Can't handle "+p.Name(), "addr", fromAddr, "err", "call has no ENR") t.log.Debug("Can't handle "+p.Name(), zap.String("addr", fromAddr.String()), zap.Error(errors.New("call has no ENR")))
c.err <- errors.New("remote wants handshake, but call has no ENR") c.err <- errors.New("remote wants handshake, but call has no ENR")
return return
} }
// Resend the call that was answered by WHOAREYOU. // Resend the call that was answered by WHOAREYOU.
t.log.Trace("<< "+p.Name(), "id", c.node.ID(), "addr", fromAddr)
c.handshakeCount++ c.handshakeCount++
c.challenge = p c.challenge = p
p.Node = c.node p.Node = c.node

View File

@ -29,13 +29,13 @@ import (
"testing" "testing"
"time" "time"
"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"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.uber.org/zap"
"github.com/waku-org/go-discover/discover/v5wire" "github.com/waku-org/go-discover/discover/v5wire"
"github.com/waku-org/go-discover/internal/testlog"
) )
// Real sockets, real crypto: this test checks end-to-end connectivity for UDPv5. // Real sockets, real crypto: this test checks end-to-end connectivity for UDPv5.
@ -79,13 +79,11 @@ func startLocalhostV5(t *testing.T, cfg Config) *UDPv5 {
ln := enode.NewLocalNode(db, cfg.PrivateKey) ln := enode.NewLocalNode(db, cfg.PrivateKey)
// Prefix logs with node ID. // Prefix logs with node ID.
lprefix := fmt.Sprintf("(%s)", ln.ID().TerminalString()) logger, err := zap.NewDevelopment()
lfmt := log.TerminalFormat(false) if err != nil {
cfg.Log = testlog.Logger(t, log.LvlTrace) t.Fatal(err)
cfg.Log.SetHandler(log.FuncHandler(func(r *log.Record) error { }
t.Logf("%s %s", lprefix, lfmt.Format(r)) cfg.Log = logger.With(zap.String("nodeId", ln.ID().TerminalString()))
return nil
}))
// Listen. // Listen.
socket, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IP{127, 0, 0, 1}}) socket, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IP{127, 0, 0, 1}})
@ -751,6 +749,11 @@ func (c *testCodec) decodeFrame(input []byte) (frame testCodecFrame, p v5wire.Pa
} }
func newUDPV5Test(t *testing.T) *udpV5Test { func newUDPV5Test(t *testing.T) *udpV5Test {
logger, err := zap.NewDevelopment()
if err != nil {
t.Fatal(err)
}
test := &udpV5Test{ test := &udpV5Test{
t: t, t: t,
pipe: newpipe(), pipe: newpipe(),
@ -766,7 +769,7 @@ func newUDPV5Test(t *testing.T) *udpV5Test {
ln.Set(enr.UDP(30303)) ln.Set(enr.UDP(30303))
test.udp, _ = ListenV5(context.Background(), test.pipe, ln, Config{ test.udp, _ = ListenV5(context.Background(), test.pipe, ln, Config{
PrivateKey: test.localkey, PrivateKey: test.localkey,
Log: testlog.Logger(t, log.LvlTrace), Log: logger,
ValidSchemes: enode.ValidSchemesForTesting, ValidSchemes: enode.ValidSchemesForTesting,
}) })
test.udp.codec = &testCodec{test: test, id: ln.ID()} test.udp.codec = &testCodec{test: test, id: ln.ID()}

24
go.mod
View File

@ -1,27 +1,27 @@
module github.com/waku-org/go-discover module github.com/waku-org/go-discover
go 1.19 go 1.23.0
require ( require (
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/ethereum/go-ethereum v1.11.6 github.com/ethereum/go-ethereum v1.16.3
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.1.0 go.uber.org/zap v1.27.0
golang.org/x/crypto v0.36.0
) )
require ( require (
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/StackExchange/wmi v1.2.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/holiman/uint256 v1.3.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect github.com/tklauser/numcpus v0.6.1 // indirect
golang.org/x/sys v0.6.0 // indirect go.uber.org/multierr v1.10.0 // indirect
golang.org/x/sys v0.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

68
go.sum
View File

@ -1,24 +1,20 @@
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/ethereum/go-ethereum v1.11.6 h1:2VF8Mf7XiSUfmoNOy3D+ocfl9Qu8baQBrCNbo2CXQ8E= github.com/ethereum/go-ethereum v1.16.3 h1:nDoBSrmsrPbrDIVLTkDQCy1U9KdHN+F2PzvMbDoS42Q=
github.com/ethereum/go-ethereum v1.11.6/go.mod h1:+a8pUj1tOyJ2RinsNQD4326YS+leSoKGiG/uVVb0x6Y= github.com/ethereum/go-ethereum v1.16.3/go.mod h1:Lrsc6bt9Gm9RyvhfFK53vboCia8kpF9nv+2Ukntnl+8=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@ -32,8 +28,8 @@ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@ -48,47 +44,55 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -103,6 +107,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,142 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package testlog provides a log handler for unit tests.
package testlog
import (
"sync"
"testing"
"github.com/ethereum/go-ethereum/log"
)
// Handler returns a log handler which logs to the unit test log of t.
func Handler(t *testing.T, level log.Lvl) log.Handler {
return log.LvlFilterHandler(level, &handler{t, log.TerminalFormat(false)})
}
type handler struct {
t *testing.T
fmt log.Format
}
func (h *handler) Log(r *log.Record) error {
h.t.Logf("%s", h.fmt.Format(r))
return nil
}
// logger implements log.Logger such that all output goes to the unit test log via
// t.Logf(). All methods in between logger.Trace, logger.Debug, etc. are marked as test
// helpers, so the file and line number in unit test output correspond to the call site
// which emitted the log message.
type logger struct {
t *testing.T
l log.Logger
mu *sync.Mutex
h *bufHandler
}
type bufHandler struct {
buf []*log.Record
fmt log.Format
}
func (h *bufHandler) Log(r *log.Record) error {
h.buf = append(h.buf, r)
return nil
}
// Logger returns a logger which logs to the unit test log of t.
func Logger(t *testing.T, level log.Lvl) log.Logger {
l := &logger{
t: t,
l: log.New(),
mu: new(sync.Mutex),
h: &bufHandler{fmt: log.TerminalFormat(false)},
}
l.l.SetHandler(log.LvlFilterHandler(level, l.h))
return l
}
func (l *logger) Trace(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Trace(msg, ctx...)
l.flush()
}
func (l *logger) Debug(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Debug(msg, ctx...)
l.flush()
}
func (l *logger) Info(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Info(msg, ctx...)
l.flush()
}
func (l *logger) Warn(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Warn(msg, ctx...)
l.flush()
}
func (l *logger) Error(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Error(msg, ctx...)
l.flush()
}
func (l *logger) Crit(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Crit(msg, ctx...)
l.flush()
}
func (l *logger) New(ctx ...interface{}) log.Logger {
return &logger{l.t, l.l.New(ctx...), l.mu, l.h}
}
func (l *logger) GetHandler() log.Handler {
return l.l.GetHandler()
}
func (l *logger) SetHandler(h log.Handler) {
l.l.SetHandler(h)
}
// flush writes all buffered messages and clears the buffer.
func (l *logger) flush() {
l.t.Helper()
for _, r := range l.h.buf {
l.t.Logf("%s", l.h.fmt.Format(r))
}
l.h.buf = nil
}