diff --git a/.github/workflows/docker-release.yaml b/.github/workflows/docker-release.yaml index 8411bf07d3..391112820f 100644 --- a/.github/workflows/docker-release.yaml +++ b/.github/workflows/docker-release.yaml @@ -43,4 +43,37 @@ jobs: provenance: false tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - \ No newline at end of file + + push-op-geth-bootnode: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login to GHCR + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: image meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/${{ github.repository_owner }}/op-geth-bootnode + tags: | + type=ref,event=branch + type=ref,event=tag + type=semver,pattern={{version}} + type=sha + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./cmd/bootnode/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + diff --git a/cmd/bootnode/Dockerfile b/cmd/bootnode/Dockerfile new file mode 100644 index 0000000000..f1d1272d53 --- /dev/null +++ b/cmd/bootnode/Dockerfile @@ -0,0 +1,36 @@ +# Support setting various labels on the final image +ARG COMMIT="" +ARG VERSION="" +ARG BUILDNUM="" + +# Build Geth in a stock Go builder container +FROM golang:1.20-alpine as builder + +RUN apk add --no-cache build-base libc-dev +RUN apk add --no-cache gcc musl-dev linux-headers git + +# Get dependencies - will also be cached if we won't change go.mod/go.sum +COPY go.mod /go-ethereum/ +COPY go.sum /go-ethereum/ +RUN cd /go-ethereum && go mod download + +ADD . /go-ethereum +ENV CGO_CFLAGS="-O -D__BLST_PORTABLE__" +ENV CGO_CFLAGS_ALLOW="-O -D__BLST_PORTABLE__" +RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/bootnode + +# Pull Geth into a second stage deploy alpine container +FROM alpine:latest + +RUN apk add --no-cache ca-certificates +COPY --from=builder /go-ethereum/build/bin/bootnode /usr/local/bin/ + +EXPOSE 8545 8546 30303 30303/udp +ENTRYPOINT ["bootnode"] + +# Add some metadata labels to help programatic image consumption +ARG COMMIT="" +ARG VERSION="" +ARG BUILDNUM="" + +LABEL commit="$COMMIT" version="$VERSION" buildnum="$BUILDNUM" diff --git a/cmd/bootnode/Makefile b/cmd/bootnode/Makefile new file mode 100644 index 0000000000..e6286da7fb --- /dev/null +++ b/cmd/bootnode/Makefile @@ -0,0 +1,38 @@ +# This Makefile is meant to be used by people that do not usually work +# with Go source code. If you know what GOPATH is then you probably +# don't need to bother with make. + +.PHONY: geth android ios evm all test clean + +GOBIN = ./build/bin +GO ?= latest +GORUN = env GO111MODULE=on go run + +geth: + $(GORUN) build/ci.go install ./cmd/geth + @echo "Done building." + @echo "Run \"$(GOBIN)/geth\" to launch geth." + +all: + $(GORUN) build/ci.go install + +test: all + $(GORUN) build/ci.go test + +lint: ## Run linters. + $(GORUN) build/ci.go lint + +clean: + env GO111MODULE=on go clean -cache + rm -fr build/_workspace/pkg/ $(GOBIN)/* + +# The devtools target installs tools required for 'go generate'. +# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'. + +devtools: + env GOBIN= go install golang.org/x/tools/cmd/stringer@latest + env GOBIN= go install github.com/fjl/gencodec@latest + env GOBIN= go install github.com/golang/protobuf/protoc-gen-go@latest + env GOBIN= go install ./cmd/abigen + @type "solc" 2> /dev/null || echo 'Please install solc' + @type "protoc" 2> /dev/null || echo 'Please install protoc' diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index 5c1635de39..c8322aea45 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/discover/v4wire" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/netutil" @@ -46,10 +47,14 @@ func main() { runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode") verbosity = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-5)") vmodule = flag.String("vmodule", "", "log verbosity pattern") + network = flag.String("network", "", "testnet/mainnet") nodeKey *ecdsa.PrivateKey err error ) + + var staticV4Nodes []v4wire.Node + flag.Parse() glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) @@ -87,6 +92,12 @@ func main() { } } + if *network == "testnet" { + staticV4Nodes = staticV4NodesTestnet + } else { + staticV4Nodes = staticV4NodesMainnet + } + if *writeAddr { fmt.Printf("%x\n", crypto.FromECDSAPub(&nodeKey.PublicKey)[1:]) os.Exit(0) @@ -123,8 +134,9 @@ func main() { printNotice(&nodeKey.PublicKey, *listenerAddr) cfg := discover.Config{ - PrivateKey: nodeKey, - NetRestrict: restrictList, + PrivateKey: nodeKey, + NetRestrict: restrictList, + StaticV4Nodes: staticV4Nodes, } if *runv5 { if _, err := discover.ListenV5(conn, ln, cfg); err != nil { diff --git a/cmd/bootnode/static_nodes.go b/cmd/bootnode/static_nodes.go new file mode 100644 index 0000000000..f90a9cb796 --- /dev/null +++ b/cmd/bootnode/static_nodes.go @@ -0,0 +1,110 @@ +package main + +import ( + "encoding/hex" + "net" + + "github.com/ethereum/go-ethereum/p2p/discover/v4wire" +) + +var staticV4NodesTestnet = []v4wire.Node{ + //p2p-0 + + { + IP: net.ParseIP("18.177.245.157").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("223488870e492f49873b621c21f3e1302f00993aaa5214a077a1c4eb62dfe96675cc7a3360525c3409480d1ec13cc72f432b4d50f5e70f98e60385dc25d4be6b"), + }, + + //p2p-1 + { + IP: net.ParseIP("18.176.219.164").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("f6a082e7861762da7e5d65ebf92b06e72b9fde81787a1a71ec8ab407345f3a7787e2617c5b9565ea3a1be46f794eeb791aef3059818b23588f2352b1d7973dfd"), + }, +} + +var staticV4NodesMainnet = []v4wire.Node{ + //ap-p2p-0 + + { + IP: net.ParseIP("52.193.218.151").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("db109c6cac5c8b6225edd3176fc3764c58e0720950fe94c122c80978e706a9c9e976629b718e48b6306ea0f9126e5394d3424c9716c5703549e2e7eba216353b"), + }, + + //ap-p2p-1 + { + IP: net.ParseIP("52.195.105.192").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("afe18782053bb31fb7ea41e1acf659ab9bd1eec181fb97331f0a6b61871a469b4f75138f903c977796be1cc2a3c985d33150a396e878d3cd6e4723b6040ff9c0"), + }, + //ap-p2p-2 + { + IP: net.ParseIP("18.182.161.116").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("0cbbf05d39193127e373038f41cdfb520644453dc764bac49f8403b774f2aab7e679b72ac1ee692f19f55cf07cdf07ef99195c841cbe30d263955149de9213cb"), + }, + //us-p2p-2 + { + IP: net.ParseIP("34.205.6.198").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("ad16edbb25953c36026636427d637fd874f65d1895a589c987009cb820a675cb0f0e1a1dffe34b826a8ef4cc9a0da398cc921ce612de7e6167dd3fdf3db9a1d9"), + }, + //us-p2p-1 + { + IP: net.ParseIP("34.194.74.36").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("852a9d69b385ccf858227ab741d73821704b7fc4abf6510840e8769a44c0d360d269a6ff6b0c42d7335e1caa494a16e45e24ad8aaa9830509f1d8ff49ebb1288"), + }, + //us-p2p-0 + { + IP: net.ParseIP("54.211.157.22").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("23538322b4fa60a936395012b37d5b4407717eec54c64232bd4e985b24ad941c3e4dd36d634e053286d926ceed66c725f8f2a72003f59901b963dee9d9983080"), + }, + //eu-p2p-0 + { + IP: net.ParseIP("34.246.100.156").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("752038ca7a0359e967d5096453935a5c3d5a13864c3551bd60c5d7d8e6547b2d68b1ceb484d872116ac6977b78d1d39fab8ebd92d22e68b032ffc196fa6cecd7"), + }, + //eu-p2p-1 + { + IP: net.ParseIP("99.81.30.183").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("6c24f4531d755d647ee3d8082f7945f051032c7bc1fc6c90ae6c328092efa2cf1ce429db01e7c4efe26f198eecf996979c2958745ac1f4d831f88231abd0096e"), + }, + //eu-p2p-2 + { + IP: net.ParseIP("34.243.159.16").To4(), + UDP: 30303, + TCP: 30303, + ID: decodePubkeyV4("f39da1c3b027b5683387c724363e0e132c287a6094564a05b43e8f22508e973098b3c7234df09beabcc19827f1d8998bd1e1d960fb5949bac0317bbe7fcb20a4"), + }, +} + +// decodePubkeyV4 +func decodePubkeyV4(hexPubkey string) v4wire.Pubkey { + pubkeyBytes, err := hex.DecodeString(hexPubkey) + if err != nil { + return v4wire.Pubkey{} + } + if len(pubkeyBytes) != 64 { + return v4wire.Pubkey{} + } + + var pubkey v4wire.Pubkey + copy(pubkey[:], pubkeyBytes) + return pubkey +} diff --git a/p2p/discover/common.go b/p2p/discover/common.go index c9f0477def..9ccf889428 100644 --- a/p2p/discover/common.go +++ b/p2p/discover/common.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover/v4wire" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/netutil" @@ -57,6 +58,9 @@ type Config struct { Log log.Logger // if set, log messages go here ValidSchemes enr.IdentityScheme // allowed identity schemes Clock mclock.Clock + + //static v4 nodes + StaticV4Nodes []v4wire.Node } func (cfg Config) withDefaults() Config { diff --git a/p2p/discover/table.go b/p2p/discover/table.go index f476d2079f..6cc7d60fd0 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -443,10 +443,13 @@ func (tab *Table) findnodeByID(target enode.ID, nresults int, preferLive bool) * liveNodes := &nodesByDistance{target: target} for _, b := range &tab.buckets { for _, n := range b.entries { + distance := xorDistance(target, n.ID()) nodes.push(n, nresults) if preferLive && n.livenessChecks > 0 { liveNodes.push(n, nresults) } + log.Trace("Distance", "Node ID", n.ID(), "Target ID", target, "XOR Distance", distance) + } } @@ -456,6 +459,56 @@ func (tab *Table) findnodeByID(target enode.ID, nresults int, preferLive bool) * return nodes } +func xorDistance(a, b enode.ID) (distance enode.ID) { + for i := range a { + distance[i] = a[i] ^ b[i] + } + return distance +} + +// get all nodes ids +func (tab *Table) getAllNodeIDs() []enode.ID { + tab.mutex.Lock() + defer tab.mutex.Unlock() + + var ids []enode.ID + for _, b := range tab.buckets { + for _, n := range b.entries { + ids = append(ids, n.ID()) + } + } + return ids +} + +// get node by given id +func (tab *Table) getNodeByID(id enode.ID) enode.Node { + tab.mutex.Lock() + defer tab.mutex.Unlock() + + for _, b := range tab.buckets { + for _, n := range b.entries { + if n.ID().String() == id.String() { + return n.Node + } + } + } + return enode.Node{} +} + +// get all nodes ids +func (tab *Table) getAllNodes() []enode.Node { + tab.mutex.Lock() + defer tab.mutex.Unlock() + + var nodes []enode.Node + for _, b := range tab.buckets { + for _, n := range b.entries { + nodes = append(nodes, n.Node) + } + } + return nodes +} + // len returns the number of nodes in the table. func (tab *Table) len() (n int) { tab.mutex.Lock() @@ -535,12 +588,22 @@ func (tab *Table) addSeenNode(n *node) { // // The caller must not hold tab.mutex. func (tab *Table) addVerifiedNode(n *node) { + log.Trace("addVerifiedNode", "nodeIP", n.IP().String(), "nodeId", n.ID().String()) if !tab.isInitDone() { return } if n.ID() == tab.self().ID() { return } + nodes := tab.getAllNodes() + + for i, nodeIndex := range nodes { + log.Trace("current tab content", "index", i, "nodeId", nodeIndex.ID(), "nodeIP", nodeIndex.IP().String()) + for j, pair := range nodeIndex.Record().GetPairs() { + log.Trace("current node content", "node index", i, "pair index", j, "pairKey", pair.GetPairKey(), "pairValue", pair.GetPairValue()) + + } + } tab.mutex.Lock() defer tab.mutex.Unlock() diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index 988f16b01d..a2b332ee4e 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -25,6 +25,7 @@ import ( "errors" "fmt" "io" + "math/rand" "net" "sync" "time" @@ -47,6 +48,24 @@ var ( errLowPort = errors.New("low port") ) +/* +// decodePubkeyV4 +func decodePubkeyV4(hexPubkey string) (v4wire.Pubkey, error) { + pubkeyBytes, err := hex.DecodeString(hexPubkey) + if err != nil { + return v4wire.Pubkey{}, err + } + if len(pubkeyBytes) != 64 { + return v4wire.Pubkey{}, fmt.Errorf("public key is not 64 bytes long") + } + + var pubkey v4wire.Pubkey + copy(pubkey[:], pubkeyBytes) + return pubkey, nil +} + +*/ + const ( respTimeout = 500 * time.Millisecond expiration = 20 * time.Second @@ -79,6 +98,9 @@ type UDPv4 struct { gotreply chan reply closeCtx context.Context cancelCloseCtx context.CancelFunc + + //static peers + staticNodes []v4wire.Node } // replyMatcher represents a pending reply. @@ -140,6 +162,7 @@ func ListenV4(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) { closeCtx: closeCtx, cancelCloseCtx: cancel, log: cfg.Log, + staticNodes: cfg.StaticV4Nodes, } tab, err := newMeteredTable(t, ln.Database(), cfg) @@ -208,6 +231,7 @@ func (t *UDPv4) ourEndpoint() v4wire.Endpoint { // Ping sends a ping message to the given node. func (t *UDPv4) Ping(n *enode.Node) error { + log.Info("send ping from ping-ping") _, err := t.ping(n) return err } @@ -223,8 +247,10 @@ func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) { // sendPing sends a ping message to the given node and invokes the callback // when the reply arrives. +// 在这里发生的变化,只要给Bootndoe发过就会更替 func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *replyMatcher { req := t.makePing(toaddr) + log.Trace("SendPing", "toID", toid, "fromIP", req.From.IP.String(), "fromPortTCP", req.From.TCP, "fromPortUDP", req.From.UDP) packet, hash, err := v4wire.Encode(t.priv, req) if err != nil { errc := make(chan error, 1) @@ -298,6 +324,7 @@ func (t *UDPv4) newLookup(ctx context.Context, targetKey encPubkey) *lookup { // findnode sends a findnode request to the given node and waits until // the node has sent up to k neighbors. +// 处理neighbors逻辑的地方 func (t *UDPv4) findnode(toid enode.ID, toaddr *net.UDPAddr, target v4wire.Pubkey) ([]*node, error) { t.ensureBond(toid, toaddr) @@ -496,6 +523,7 @@ func (t *UDPv4) loop() { } } +// 通用send? send func (t *UDPv4) send(toaddr *net.UDPAddr, toid enode.ID, req v4wire.Packet) ([]byte, error) { packet, hash, err := v4wire.Encode(t.priv, req) if err != nil { @@ -507,6 +535,11 @@ 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 { _, err := t.conn.WriteToUDP(packet, toaddr) t.log.Trace(">> "+what, "id", toid, "addr", toaddr, "err", err) + /* + if what == "FINDNODE/v4" { + log.Info("FINDNODE msg") + } + */ return err } @@ -568,6 +601,7 @@ func (t *UDPv4) checkBond(id enode.ID, ip net.IP) bool { func (t *UDPv4) ensureBond(toid enode.ID, toaddr *net.UDPAddr) { tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.IP)) > bondExpiration if tooOld || t.db.FindFails(toid, toaddr.IP) > maxFindnodeFailures { + log.Trace("sendPing from ensureBond") rm := t.sendPing(toid, toaddr, nil) <-rm.errc // Wait for them to ping back and process our pong. @@ -664,10 +698,13 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I Expiration: uint64(time.Now().Add(expiration).Unix()), ENRSeq: t.localNode.Node().Seq(), }) + log.Trace("handlePing,sendPong", "nodeId", fromID, "targetIP", from.IP.String(), "targetPort", from.Port) // Ping back if our last pong on file is too far in the past. + // TODO 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 { + log.Trace("sendPing from bondExpiration") t.sendPing(fromID, from, func() { t.tab.addVerifiedNode(n) }) @@ -704,15 +741,20 @@ func (t *UDPv4) verifyFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno if v4wire.Expired(req.Expiration) { return errExpired } - if !t.checkBond(fromID, from.IP) { - // 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 - // DDOS attack. A malicious actor would send a findnode request with the IP address - // and UDP port of the target as the source address. The recipient of the findnode - // packet would then send a neighbors packet (which is a much bigger packet than - // findnode) to the victim. - return errUnknownNode - } + + /* + if !t.checkBond(fromID, from.IP) { + // No endpoint proof poudpng exists, we don't process the packet. This prevents an + // 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 + // and UDP port of the target as the source address. The recipient of the findnode + // packet would then send a neighbors packet (which is a much bigger packet than + // findnode) to the victim. + return errUnknownNode + } + + */ + return nil } @@ -726,6 +768,13 @@ func (t *UDPv4) handleFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno // Send neighbors in chunks with at most maxNeighbors per packet // to stay below the packet size limit. p := v4wire.Neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())} + + // Add static peers + for i, staticNode := range t.staticNodes { + log.Debug("static nodes", "index", i, "node ID", staticNode.ID.ID().String(), "IP", staticNode.IP.String()) + p.Nodes = append(p.Nodes, staticNode) + } + var sent bool for _, n := range closest { if netutil.CheckRelayIP(from.IP, n.IP()) == nil { @@ -742,10 +791,22 @@ func (t *UDPv4) handleFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno } } +// shuffleNodes takes a slice of nodes and shuffles them in place. +func shuffleNodes(nodes []v4wire.Node) { + rand.Seed(time.Now().UnixNano()) // Ensure a different sequence each time + rand.Shuffle(len(nodes), func(i, j int) { + nodes[i], nodes[j] = nodes[j], nodes[i] + }) +} + // NEIGHBORS/v4 func (t *UDPv4) verifyNeighbors(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error { + log.Debug("verifyNeighbors", "fromIp", from.IP.String(), "fromPort", from.Port) req := h.Packet.(*v4wire.Neighbors) + for i, neighbor := range req.Nodes { + log.Debug("received neighbors", "index", i, "IP", neighbor.IP.String(), "UDP_PORT", neighbor.UDP, "TCP_PORT", neighbor.TCP, "NodeId", neighbor.ID.ID()) + } if v4wire.Expired(req.Expiration) { return errExpired @@ -764,13 +825,21 @@ func (t *UDPv4) verifyENRRequest(h *packetHandlerV4, from *net.UDPAddr, fromID e if v4wire.Expired(req.Expiration) { return errExpired } - if !t.checkBond(fromID, from.IP) { - return errUnknownNode - } + /* + if !t.checkBond(fromID, from.IP) { + return errUnknownNode + } + + */ return nil } func (t *UDPv4) handleENRRequest(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, mac []byte) { + log.Info("handle ENR reqeust", "from", from, "fromID", fromID) + record := t.localNode.Node().Record() + for i, p := range record.GetPairs() { + log.Info("ENR pairs", "index", i, "key", p.GetPairKey(), "value", p.GetPairValue()) + } t.send(from, fromID, &v4wire.ENRResponse{ ReplyTok: mac, Record: *t.localNode.Node().Record(), diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go index 5add9cefa1..c01798fe7e 100644 --- a/p2p/discover/v4_udp_test.go +++ b/p2p/discover/v4_udp_test.go @@ -21,6 +21,7 @@ import ( "crypto/ecdsa" crand "crypto/rand" "encoding/binary" + "encoding/hex" "errors" "fmt" "io" @@ -664,3 +665,20 @@ func (c *dgramPipe) receive() (dgram, error) { c.queue = c.queue[:len(c.queue)-1] return p, nil } + +func TestPubkeyToID(t *testing.T) { + hexPubkey := "223488870e492f49873b621c21f3e1302f00993aaa5214a077a1c4eb62dfe96675cc7a3360525c3409480d1ec13cc72f432b4d50f5e70f98e60385dc25d4be6b" + + pubkeyBytes, err := hex.DecodeString(hexPubkey) + if err != nil { + t.Fatalf("Error decoding public key: %v", err) + } + + var pubkey v4wire.Pubkey + copy(pubkey[:], pubkeyBytes) + + nodeID := pubkey.ID() + + fmt.Printf("Node ID: %s\n", nodeID.String()) + +} diff --git a/p2p/discover/v4wire/v4wire.go b/p2p/discover/v4wire/v4wire.go index 9c59359fb2..295116c7ef 100644 --- a/p2p/discover/v4wire/v4wire.go +++ b/p2p/discover/v4wire/v4wire.go @@ -103,7 +103,7 @@ type ( ) // MaxNeighbors is the maximum number of neighbor nodes in a Neighbors packet. -const MaxNeighbors = 12 +const MaxNeighbors = 20 // This code computes the MaxNeighbors constant value. diff --git a/p2p/enr/enr.go b/p2p/enr/enr.go index 2b093b2f1a..697e942639 100644 --- a/p2p/enr/enr.go +++ b/p2p/enr/enr.go @@ -90,12 +90,24 @@ type Record struct { pairs []pair // sorted list of all key/value pairs } +func (r *Record) GetPairs() []pair { + return r.pairs +} + // pair is a key/value pair in a record. type pair struct { k string v rlp.RawValue } +func (r *pair) GetPairKey() string { + return r.k +} + +func (r *pair) GetPairValue() rlp.RawValue { + return r.v +} + // Size returns the encoded size of the record. func (r *Record) Size() uint64 { if r.raw != nil {