Skip to content

Commit

Permalink
feat: geth bootnode binary (#1)
Browse files Browse the repository at this point in the history
* feat: add dockerfile for bootnode build

* test: remove pong bond verify

* feat: add static peers on bootnode
  • Loading branch information
krish-nr committed Mar 27, 2024
1 parent c18478a commit d2be1de
Show file tree
Hide file tree
Showing 11 changed files with 411 additions and 16 deletions.
35 changes: 34 additions & 1 deletion .github/workflows/docker-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,37 @@ jobs:
provenance: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}


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 }}

36 changes: 36 additions & 0 deletions cmd/bootnode/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"
38 changes: 38 additions & 0 deletions cmd/bootnode/Makefile
Original file line number Diff line number Diff line change
@@ -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'
16 changes: 14 additions & 2 deletions cmd/bootnode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down
110 changes: 110 additions & 0 deletions cmd/bootnode/static_nodes.go
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 4 additions & 0 deletions p2p/discover/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
63 changes: 63 additions & 0 deletions p2p/discover/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

}
}

Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
Loading

0 comments on commit d2be1de

Please sign in to comment.