feat:migrate and remove portal wire in p2p package

Signed-off-by: Chen Kai <281165273grape@gmail.com>
This commit is contained in:
Chen Kai 2024-11-25 14:18:17 +08:00
parent bce048fb1a
commit ee11806dd7
38 changed files with 852 additions and 5307 deletions

View file

@ -27,13 +27,13 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/portalnetwork/beacon" "github.com/ethereum/go-ethereum/portalnetwork/beacon"
"github.com/ethereum/go-ethereum/portalnetwork/ethapi" "github.com/ethereum/go-ethereum/portalnetwork/ethapi"
"github.com/ethereum/go-ethereum/portalnetwork/history" "github.com/ethereum/go-ethereum/portalnetwork/history"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/state" "github.com/ethereum/go-ethereum/portalnetwork/state"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/ethereum/go-ethereum/portalnetwork/web3" "github.com/ethereum/go-ethereum/portalnetwork/web3"
@ -53,7 +53,7 @@ const (
) )
type Config struct { type Config struct {
Protocol *discover.PortalProtocolConfig Protocol *portalwire.PortalProtocolConfig
PrivateKey *ecdsa.PrivateKey PrivateKey *ecdsa.PrivateKey
RpcAddr string RpcAddr string
DataDir string DataDir string
@ -63,8 +63,8 @@ type Config struct {
} }
type Client struct { type Client struct {
DiscV5API *discover.DiscV5API DiscV5API *portalwire.DiscV5API
HistoryNetwork *history.HistoryNetwork HistoryNetwork *history.Network
BeaconNetwork *beacon.BeaconNetwork BeaconNetwork *beacon.BeaconNetwork
StateNetwork *state.StateNetwork StateNetwork *state.StateNetwork
Server *http.Server Server *http.Server
@ -129,7 +129,7 @@ func shisui(ctx *cli.Context) error {
// Start system runtime metrics collection // Start system runtime metrics collection
go metrics.CollectProcessMetrics(3 * time.Second) go metrics.CollectProcessMetrics(3 * time.Second)
go metrics.CollectPortalMetrics(5*time.Second, ctx.StringSlice(utils.PortalNetworksFlag.Name), ctx.String(utils.PortalDataDirFlag.Name)) go portalwire.CollectPortalMetrics(5*time.Second, ctx.StringSlice(utils.PortalNetworksFlag.Name), ctx.String(utils.PortalDataDirFlag.Name))
if metrics.Enabled { if metrics.Enabled {
storageCapacity = metrics.NewRegisteredGauge("portal/storage_capacity", nil) storageCapacity = metrics.NewRegisteredGauge("portal/storage_capacity", nil)
@ -229,7 +229,7 @@ func startPortalRpcServer(config Config, conn discover.UDPConn, addr string, cli
} }
server := rpc.NewServer() server := rpc.NewServer()
discV5API := discover.NewDiscV5API(discV5) discV5API := portalwire.NewDiscV5API(discV5)
err = server.RegisterName("discv5", discV5API) err = server.RegisterName("discv5", discV5API)
if err != nil { if err != nil {
return err return err
@ -241,9 +241,9 @@ func startPortalRpcServer(config Config, conn discover.UDPConn, addr string, cli
if err != nil { if err != nil {
return err return err
} }
utp := discover.NewPortalUtp(context.Background(), config.Protocol, discV5, conn) utp := portalwire.NewPortalUtp(context.Background(), config.Protocol, discV5, conn)
var historyNetwork *history.HistoryNetwork var historyNetwork *history.Network
if slices.Contains(config.Networks, portalwire.History.Name()) { if slices.Contains(config.Networks, portalwire.History.Name()) {
historyNetwork, err = initHistory(config, server, conn, localNode, discV5, utp) historyNetwork, err = initHistory(config, server, conn, localNode, discV5, utp)
if err != nil { if err != nil {
@ -305,7 +305,7 @@ func initDiscV5(config Config, conn discover.UDPConn) (*discover.UDPv5, *enode.L
localNode := enode.NewLocalNode(nodeDB, config.PrivateKey) localNode := enode.NewLocalNode(nodeDB, config.PrivateKey)
localNode.Set(discover.Tag) localNode.Set(portalwire.Tag)
listenerAddr := conn.LocalAddr().(*net.UDPAddr) listenerAddr := conn.LocalAddr().(*net.UDPAddr)
nat := config.Protocol.NAT nat := config.Protocol.NAT
if nat != nil && !listenerAddr.IP.IsLoopback() { if nat != nil && !listenerAddr.IP.IsLoopback() {
@ -370,7 +370,7 @@ func doPortMapping(natm nat.Interface, ln *enode.LocalNode, addr *net.UDPAddr) {
}() }()
} }
func initHistory(config Config, server *rpc.Server, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *discover.PortalUtp) (*history.HistoryNetwork, error) { func initHistory(config Config, server *rpc.Server, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *portalwire.PortalUtp) (*history.Network, error) {
networkName := portalwire.History.Name() networkName := portalwire.History.Name()
db, err := history.NewDB(config.DataDir, networkName) db, err := history.NewDB(config.DataDir, networkName)
if err != nil { if err != nil {
@ -385,9 +385,9 @@ func initHistory(config Config, server *rpc.Server, conn discover.UDPConn, local
if err != nil { if err != nil {
return nil, err return nil, err
} }
contentQueue := make(chan *discover.ContentElement, 50) contentQueue := make(chan *portalwire.ContentElement, 50)
protocol, err := discover.NewPortalProtocol( protocol, err := portalwire.NewPortalProtocol(
config.Protocol, config.Protocol,
portalwire.History, portalwire.History,
config.PrivateKey, config.PrivateKey,
@ -401,7 +401,7 @@ func initHistory(config Config, server *rpc.Server, conn discover.UDPConn, local
if err != nil { if err != nil {
return nil, err return nil, err
} }
historyAPI := discover.NewPortalAPI(protocol) historyAPI := portalwire.NewPortalAPI(protocol)
historyNetworkAPI := history.NewHistoryNetworkAPI(historyAPI) historyNetworkAPI := history.NewHistoryNetworkAPI(historyAPI)
err = server.RegisterName("portal", historyNetworkAPI) err = server.RegisterName("portal", historyNetworkAPI)
if err != nil { if err != nil {
@ -415,7 +415,7 @@ func initHistory(config Config, server *rpc.Server, conn discover.UDPConn, local
return historyNetwork, historyNetwork.Start() return historyNetwork, historyNetwork.Start()
} }
func initBeacon(config Config, server *rpc.Server, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *discover.PortalUtp) (*beacon.BeaconNetwork, error) { func initBeacon(config Config, server *rpc.Server, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *portalwire.PortalUtp) (*beacon.BeaconNetwork, error) {
dbPath := path.Join(config.DataDir, "beacon") dbPath := path.Join(config.DataDir, "beacon")
err := os.MkdirAll(dbPath, 0755) err := os.MkdirAll(dbPath, 0755)
if err != nil { if err != nil {
@ -436,9 +436,9 @@ func initBeacon(config Config, server *rpc.Server, conn discover.UDPConn, localN
if err != nil { if err != nil {
return nil, err return nil, err
} }
contentQueue := make(chan *discover.ContentElement, 50) contentQueue := make(chan *portalwire.ContentElement, 50)
protocol, err := discover.NewPortalProtocol( protocol, err := portalwire.NewPortalProtocol(
config.Protocol, config.Protocol,
portalwire.Beacon, portalwire.Beacon,
config.PrivateKey, config.PrivateKey,
@ -452,7 +452,7 @@ func initBeacon(config Config, server *rpc.Server, conn discover.UDPConn, localN
if err != nil { if err != nil {
return nil, err return nil, err
} }
portalApi := discover.NewPortalAPI(protocol) portalApi := portalwire.NewPortalAPI(protocol)
beaconAPI := beacon.NewBeaconNetworkAPI(portalApi) beaconAPI := beacon.NewBeaconNetworkAPI(portalApi)
err = server.RegisterName("portal", beaconAPI) err = server.RegisterName("portal", beaconAPI)
@ -464,7 +464,7 @@ func initBeacon(config Config, server *rpc.Server, conn discover.UDPConn, localN
return beaconNetwork, beaconNetwork.Start() return beaconNetwork, beaconNetwork.Start()
} }
func initState(config Config, server *rpc.Server, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *discover.PortalUtp) (*state.StateNetwork, error) { func initState(config Config, server *rpc.Server, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *portalwire.PortalUtp) (*state.StateNetwork, error) {
networkName := portalwire.State.Name() networkName := portalwire.State.Name()
db, err := history.NewDB(config.DataDir, networkName) db, err := history.NewDB(config.DataDir, networkName)
if err != nil { if err != nil {
@ -480,9 +480,9 @@ func initState(config Config, server *rpc.Server, conn discover.UDPConn, localNo
return nil, err return nil, err
} }
stateStore := state.NewStateStorage(contentStorage, db) stateStore := state.NewStateStorage(contentStorage, db)
contentQueue := make(chan *discover.ContentElement, 50) contentQueue := make(chan *portalwire.ContentElement, 50)
protocol, err := discover.NewPortalProtocol( protocol, err := portalwire.NewPortalProtocol(
config.Protocol, config.Protocol,
portalwire.State, portalwire.State,
config.PrivateKey, config.PrivateKey,
@ -496,7 +496,7 @@ func initState(config Config, server *rpc.Server, conn discover.UDPConn, localNo
if err != nil { if err != nil {
return nil, err return nil, err
} }
api := discover.NewPortalAPI(protocol) api := portalwire.NewPortalAPI(protocol)
stateNetworkAPI := state.NewStateNetworkAPI(api) stateNetworkAPI := state.NewStateNetworkAPI(api)
err = server.RegisterName("portal", stateNetworkAPI) err = server.RegisterName("portal", stateNetworkAPI)
if err != nil { if err != nil {
@ -509,7 +509,7 @@ func initState(config Config, server *rpc.Server, conn discover.UDPConn, localNo
func getPortalConfig(ctx *cli.Context) (*Config, error) { func getPortalConfig(ctx *cli.Context) (*Config, error) {
config := &Config{ config := &Config{
Protocol: discover.DefaultPortalProtocolConfig(), Protocol: portalwire.DefaultPortalProtocolConfig(),
} }
httpAddr := ctx.String(utils.PortalRPCListenAddrFlag.Name) httpAddr := ctx.String(utils.PortalRPCListenAddrFlag.Name)

View file

@ -68,11 +68,11 @@ import (
"github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
"github.com/ethereum/go-ethereum/triedb/hashdb" "github.com/ethereum/go-ethereum/triedb/hashdb"

View file

@ -1,153 +0,0 @@
package metrics
import (
"database/sql"
"errors"
"os"
"path"
"slices"
"strings"
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
)
type networkFileMetric struct {
filename string
metric Gauge
file *os.File
network string
}
type PortalStorageMetrics struct {
RadiusRatio GaugeFloat64
EntriesCount Gauge
ContentStorageUsage Gauge
}
const (
countEntrySql = "SELECT COUNT(1) FROM kvstore;"
contentStorageUsageSql = "SELECT SUM( length(value) ) FROM kvstore;"
)
// CollectPortalMetrics periodically collects various metrics about system entities.
func CollectPortalMetrics(refresh time.Duration, networks []string, dataDir string) {
// Short circuit if the metrics system is disabled
if !Enabled {
return
}
// Define the various metrics to collect
var (
historyTotalStorage = GetOrRegisterGauge("portal/history/total_storage", nil)
beaconTotalStorage = GetOrRegisterGauge("portal/beacon/total_storage", nil)
stateTotalStorage = GetOrRegisterGauge("portal/state/total_storage", nil)
)
var metricsArr []*networkFileMetric
if slices.Contains(networks, portalwire.History.Name()) {
dbPath := path.Join(dataDir, portalwire.History.Name())
metricsArr = append(metricsArr, &networkFileMetric{
filename: path.Join(dbPath, portalwire.History.Name()+".sqlite"),
metric: historyTotalStorage,
network: portalwire.History.Name(),
})
}
if slices.Contains(networks, portalwire.Beacon.Name()) {
dbPath := path.Join(dataDir, portalwire.Beacon.Name())
metricsArr = append(metricsArr, &networkFileMetric{
filename: path.Join(dbPath, portalwire.Beacon.Name()+".sqlite"),
metric: beaconTotalStorage,
network: portalwire.Beacon.Name(),
})
}
if slices.Contains(networks, portalwire.State.Name()) {
dbPath := path.Join(dataDir, portalwire.State.Name())
metricsArr = append(metricsArr, &networkFileMetric{
filename: path.Join(dbPath, portalwire.State.Name()+".sqlite"),
metric: stateTotalStorage,
network: portalwire.State.Name(),
})
}
for {
for _, m := range metricsArr {
var err error = nil
if m.file == nil {
m.file, err = os.OpenFile(m.filename, os.O_RDONLY, 0600)
if err != nil {
log.Debug("Could not open file", "network", m.network, "file", m.filename, "metric", "total_storage", "err", err)
}
}
if m.file != nil && err == nil {
stat, err := m.file.Stat()
if err != nil {
log.Warn("Could not get file stat", "network", m.network, "file", m.filename, "metric", "total_storage", "err", err)
}
if err == nil {
m.metric.Update(stat.Size())
}
}
}
time.Sleep(refresh)
}
}
func NewPortalStorageMetrics(network string, db *sql.DB) (*PortalStorageMetrics, error) {
if !Enabled {
return nil, nil
}
if network != portalwire.History.Name() && network != portalwire.Beacon.Name() && network != portalwire.State.Name() {
log.Debug("Unknow network for metrics", "network", network)
return nil, errors.New("unknow network for metrics")
}
var countSql string
var contentSql string
if network == portalwire.Beacon.Name() {
countSql = strings.Replace(countEntrySql, "kvstore", "beacon", 1)
contentSql = strings.Replace(contentStorageUsageSql, "kvstore", "beacon", 1)
contentSql = strings.Replace(contentSql, "value", "content_value", 1)
} else {
countSql = countEntrySql
contentSql = contentStorageUsageSql
}
storageMetrics := &PortalStorageMetrics{}
storageMetrics.RadiusRatio = NewRegisteredGaugeFloat64("portal/"+network+"/radius_ratio", nil)
storageMetrics.RadiusRatio.Update(1)
storageMetrics.EntriesCount = NewRegisteredGauge("portal/"+network+"/entry_count", nil)
log.Debug("Counting entities in " + network + " storage for metrics")
var res *int64 = new(int64)
q := db.QueryRow(countSql)
if q.Err() == sql.ErrNoRows {
storageMetrics.EntriesCount.Update(0)
} else if q.Err() != nil {
log.Error("Querry execution error", "network", network, "metric", "entry_count", "err", q.Err())
return nil, q.Err()
} else {
q.Scan(res)
storageMetrics.EntriesCount.Update(*res)
}
storageMetrics.ContentStorageUsage = NewRegisteredGauge("portal/"+network+"/content_storage", nil)
log.Debug("Counting storage usage (bytes) in " + network + " for metrics")
var res2 *int64 = new(int64)
q2 := db.QueryRow(contentSql)
if q2.Err() == sql.ErrNoRows {
storageMetrics.ContentStorageUsage.Update(0)
} else if q2.Err() != nil {
log.Error("Querry execution error", "network", network, "metric", "entry_count", "err", q2.Err())
return nil, q2.Err()
} else {
q2.Scan(res2)
storageMetrics.ContentStorageUsage.Update(*res2)
}
return storageMetrics, nil
}

View file

@ -1,550 +0,0 @@
package discover
import (
"errors"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/holiman/uint256"
)
// DiscV5API json-rpc spec
// https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/ethereum/portal-network-specs/assembled-spec/jsonrpc/openrpc.json&uiSchema%5BappBar%5D%5Bui:splitView%5D=false&uiSchema%5BappBar%5D%5Bui:input%5D=false&uiSchema%5BappBar%5D%5Bui:examplesDropdown%5D=false
type DiscV5API struct {
DiscV5 *UDPv5
}
func NewDiscV5API(discV5 *UDPv5) *DiscV5API {
return &DiscV5API{discV5}
}
type NodeInfo struct {
NodeId string `json:"nodeId"`
Enr string `json:"enr"`
Ip string `json:"ip"`
}
type RoutingTableInfo struct {
Buckets [][]string `json:"buckets"`
LocalNodeId string `json:"localNodeId"`
}
type DiscV5PongResp struct {
EnrSeq uint64 `json:"enrSeq"`
RecipientIP string `json:"recipientIP"`
RecipientPort uint16 `json:"recipientPort"`
}
type PortalPongResp struct {
EnrSeq uint32 `json:"enrSeq"`
DataRadius string `json:"dataRadius"`
}
type ContentInfo struct {
Content string `json:"content"`
UtpTransfer bool `json:"utpTransfer"`
}
type TraceContentResult struct {
Content string `json:"content"`
UtpTransfer bool `json:"utpTransfer"`
Trace Trace `json:"trace"`
}
type Trace struct {
Origin string `json:"origin"` // local node id
TargetId string `json:"targetId"` // target content id
ReceivedFrom string `json:"receivedFrom"` // the node id of which content from
Responses map[string]RespByNode `json:"responses"` // the node id and there response nodeIds
Metadata map[string]*NodeMetadata `json:"metadata"` // node id and there metadata object
StartedAtMs int `json:"startedAtMs"` // timestamp of the beginning of this request in milliseconds
Cancelled []string `json:"cancelled"` // the node ids which are send but cancelled
}
type NodeMetadata struct {
Enr string `json:"enr"`
Distance string `json:"distance"`
}
type RespByNode struct {
DurationMs int32 `json:"durationMs"`
RespondedWith []string `json:"respondedWith"`
}
type Enrs struct {
Enrs []string `json:"enrs"`
}
func (d *DiscV5API) NodeInfo() *NodeInfo {
n := d.DiscV5.LocalNode().Node()
return &NodeInfo{
NodeId: "0x" + n.ID().String(),
Enr: n.String(),
Ip: n.IP().String(),
}
}
func (d *DiscV5API) RoutingTableInfo() *RoutingTableInfo {
n := d.DiscV5.LocalNode().Node()
bucketNodes := d.DiscV5.RoutingTableInfo()
return &RoutingTableInfo{
Buckets: bucketNodes,
LocalNodeId: "0x" + n.ID().String(),
}
}
func (d *DiscV5API) AddEnr(enr string) (bool, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return false, err
}
// immediately add the node to the routing table
d.DiscV5.tab.mutex.Lock()
defer d.DiscV5.tab.mutex.Unlock()
d.DiscV5.tab.handleAddNode(addNodeOp{node: n, isInbound: true, forceSetLive: true})
return true, nil
}
func (d *DiscV5API) GetEnr(nodeId string) (bool, error) {
id, err := enode.ParseID(nodeId)
if err != nil {
return false, err
}
n := d.DiscV5.tab.GetNode(id)
if n == nil {
return false, errors.New("record not in local routing table")
}
return true, nil
}
func (d *DiscV5API) DeleteEnr(nodeId string) (bool, error) {
id, err := enode.ParseID(nodeId)
if err != nil {
return false, err
}
n := d.DiscV5.tab.GetNode(id)
if n == nil {
return false, errors.New("record not in local routing table")
}
d.DiscV5.tab.mutex.Lock()
defer d.DiscV5.tab.mutex.Unlock()
b := d.DiscV5.tab.bucket(n.ID())
d.DiscV5.tab.deleteInBucket(b, n.ID())
return true, nil
}
func (d *DiscV5API) LookupEnr(nodeId string) (string, error) {
id, err := enode.ParseID(nodeId)
if err != nil {
return "", err
}
enr := d.DiscV5.ResolveNodeId(id)
if enr == nil {
return "", errors.New("record not found in DHT lookup")
}
return enr.String(), nil
}
func (d *DiscV5API) Ping(enr string) (*DiscV5PongResp, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return nil, err
}
pong, err := d.DiscV5.PingWithResp(n)
if err != nil {
return nil, err
}
return &DiscV5PongResp{
EnrSeq: pong.ENRSeq,
RecipientIP: pong.ToIP.String(),
RecipientPort: pong.ToPort,
}, nil
}
func (d *DiscV5API) FindNodes(enr string, distances []uint) ([]string, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return nil, err
}
findNodes, err := d.DiscV5.Findnode(n, distances)
if err != nil {
return nil, err
}
enrs := make([]string, 0, len(findNodes))
for _, r := range findNodes {
enrs = append(enrs, r.String())
}
return enrs, nil
}
func (d *DiscV5API) TalkReq(enr string, protocol string, payload string) (string, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return "", err
}
req, err := hexutil.Decode(payload)
if err != nil {
return "", err
}
talkResp, err := d.DiscV5.TalkRequest(n, protocol, req)
if err != nil {
return "", err
}
return hexutil.Encode(talkResp), nil
}
func (d *DiscV5API) RecursiveFindNodes(nodeId string) ([]string, error) {
findNodes := d.DiscV5.Lookup(enode.HexID(nodeId))
enrs := make([]string, 0, len(findNodes))
for _, r := range findNodes {
enrs = append(enrs, r.String())
}
return enrs, nil
}
type PortalProtocolAPI struct {
portalProtocol *PortalProtocol
}
func NewPortalAPI(portalProtocol *PortalProtocol) *PortalProtocolAPI {
return &PortalProtocolAPI{
portalProtocol: portalProtocol,
}
}
func (p *PortalProtocolAPI) NodeInfo() *NodeInfo {
n := p.portalProtocol.localNode.Node()
return &NodeInfo{
NodeId: n.ID().String(),
Enr: n.String(),
Ip: n.IP().String(),
}
}
func (p *PortalProtocolAPI) RoutingTableInfo() *RoutingTableInfo {
n := p.portalProtocol.localNode.Node()
bucketNodes := p.portalProtocol.RoutingTableInfo()
return &RoutingTableInfo{
Buckets: bucketNodes,
LocalNodeId: "0x" + n.ID().String(),
}
}
func (p *PortalProtocolAPI) AddEnr(enr string) (bool, error) {
p.portalProtocol.Log.Debug("serving AddEnr", "enr", enr)
n, err := enode.ParseForAddEnr(enode.ValidSchemes, enr)
if err != nil {
return false, err
}
p.portalProtocol.AddEnr(n)
return true, nil
}
func (p *PortalProtocolAPI) AddEnrs(enrs []string) bool {
// Note: unspecified RPC, but useful for our local testnet test
for _, enr := range enrs {
n, err := enode.ParseForAddEnr(enode.ValidSchemes, enr)
if err != nil {
continue
}
p.portalProtocol.AddEnr(n)
}
return true
}
func (p *PortalProtocolAPI) GetEnr(nodeId string) (string, error) {
id, err := enode.ParseID(nodeId)
if err != nil {
return "", err
}
if id == p.portalProtocol.localNode.Node().ID() {
return p.portalProtocol.localNode.Node().String(), nil
}
n := p.portalProtocol.table.GetNode(id)
if n == nil {
return "", errors.New("record not in local routing table")
}
return n.String(), nil
}
func (p *PortalProtocolAPI) DeleteEnr(nodeId string) (bool, error) {
id, err := enode.ParseID(nodeId)
if err != nil {
return false, err
}
n := p.portalProtocol.table.GetNode(id)
if n == nil {
return false, nil
}
p.portalProtocol.table.mutex.Lock()
defer p.portalProtocol.table.mutex.Unlock()
b := p.portalProtocol.table.bucket(n.ID())
p.portalProtocol.table.deleteInBucket(b, n.ID())
return true, nil
}
func (p *PortalProtocolAPI) LookupEnr(nodeId string) (string, error) {
id, err := enode.ParseID(nodeId)
if err != nil {
return "", err
}
enr := p.portalProtocol.ResolveNodeId(id)
if enr == nil {
return "", errors.New("record not found in DHT lookup")
}
return enr.String(), nil
}
func (p *PortalProtocolAPI) Ping(enr string) (*PortalPongResp, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return nil, err
}
pong, err := p.portalProtocol.pingInner(n)
if err != nil {
return nil, err
}
customPayload := &portalwire.PingPongCustomData{}
err = customPayload.UnmarshalSSZ(pong.CustomPayload)
if err != nil {
return nil, err
}
nodeRadius := new(uint256.Int)
err = nodeRadius.UnmarshalSSZ(customPayload.Radius)
if err != nil {
return nil, err
}
return &PortalPongResp{
EnrSeq: uint32(pong.EnrSeq),
DataRadius: nodeRadius.Hex(),
}, nil
}
func (p *PortalProtocolAPI) FindNodes(enr string, distances []uint) ([]string, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return nil, err
}
findNodes, err := p.portalProtocol.findNodes(n, distances)
if err != nil {
return nil, err
}
enrs := make([]string, 0, len(findNodes))
for _, r := range findNodes {
enrs = append(enrs, r.String())
}
return enrs, nil
}
func (p *PortalProtocolAPI) FindContent(enr string, contentKey string) (interface{}, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return nil, err
}
contentKeyBytes, err := hexutil.Decode(contentKey)
if err != nil {
return nil, err
}
flag, findContent, err := p.portalProtocol.findContent(n, contentKeyBytes)
if err != nil {
return nil, err
}
switch flag {
case portalwire.ContentRawSelector:
contentInfo := &ContentInfo{
Content: hexutil.Encode(findContent.([]byte)),
UtpTransfer: false,
}
p.portalProtocol.Log.Trace("FindContent", "contentInfo", contentInfo)
return contentInfo, nil
case portalwire.ContentConnIdSelector:
contentInfo := &ContentInfo{
Content: hexutil.Encode(findContent.([]byte)),
UtpTransfer: true,
}
p.portalProtocol.Log.Trace("FindContent", "contentInfo", contentInfo)
return contentInfo, nil
default:
enrs := make([]string, 0)
for _, r := range findContent.([]*enode.Node) {
enrs = append(enrs, r.String())
}
p.portalProtocol.Log.Trace("FindContent", "enrs", enrs)
return &Enrs{
Enrs: enrs,
}, nil
}
}
func (p *PortalProtocolAPI) Offer(enr string, contentItems [][2]string) (string, error) {
n, err := enode.Parse(enode.ValidSchemes, enr)
if err != nil {
return "", err
}
entries := make([]*ContentEntry, 0, len(contentItems))
for _, contentItem := range contentItems {
contentKey, err := hexutil.Decode(contentItem[0])
if err != nil {
return "", err
}
contentValue, err := hexutil.Decode(contentItem[1])
if err != nil {
return "", err
}
contentEntry := &ContentEntry{
ContentKey: contentKey,
Content: contentValue,
}
entries = append(entries, contentEntry)
}
transientOfferRequest := &TransientOfferRequest{
Contents: entries,
}
offerReq := &OfferRequest{
Kind: TransientOfferRequestKind,
Request: transientOfferRequest,
}
accept, err := p.portalProtocol.offer(n, offerReq)
if err != nil {
return "", err
}
return hexutil.Encode(accept), nil
}
func (p *PortalProtocolAPI) RecursiveFindNodes(nodeId string) ([]string, error) {
findNodes := p.portalProtocol.Lookup(enode.HexID(nodeId))
enrs := make([]string, 0, len(findNodes))
for _, r := range findNodes {
enrs = append(enrs, r.String())
}
return enrs, nil
}
func (p *PortalProtocolAPI) RecursiveFindContent(contentKeyHex string) (*ContentInfo, error) {
contentKey, err := hexutil.Decode(contentKeyHex)
if err != nil {
return nil, err
}
contentId := p.portalProtocol.toContentId(contentKey)
data, err := p.portalProtocol.Get(contentKey, contentId)
if err == nil {
return &ContentInfo{
Content: hexutil.Encode(data),
UtpTransfer: false,
}, err
}
p.portalProtocol.Log.Warn("find content err", "contextKey", hexutil.Encode(contentKey), "err", err)
content, utpTransfer, err := p.portalProtocol.ContentLookup(contentKey, contentId)
if err != nil {
return nil, err
}
return &ContentInfo{
Content: hexutil.Encode(content),
UtpTransfer: utpTransfer,
}, err
}
func (p *PortalProtocolAPI) LocalContent(contentKeyHex string) (string, error) {
contentKey, err := hexutil.Decode(contentKeyHex)
if err != nil {
return "", err
}
contentId := p.portalProtocol.ToContentId(contentKey)
content, err := p.portalProtocol.Get(contentKey, contentId)
if err != nil {
return "", err
}
return hexutil.Encode(content), nil
}
func (p *PortalProtocolAPI) Store(contentKeyHex string, contextHex string) (bool, error) {
contentKey, err := hexutil.Decode(contentKeyHex)
if err != nil {
return false, err
}
contentId := p.portalProtocol.ToContentId(contentKey)
if !p.portalProtocol.InRange(contentId) {
return false, nil
}
content, err := hexutil.Decode(contextHex)
if err != nil {
return false, err
}
err = p.portalProtocol.Put(contentKey, contentId, content)
if err != nil {
return false, err
}
return true, nil
}
func (p *PortalProtocolAPI) Gossip(contentKeyHex, contentHex string) (int, error) {
contentKey, err := hexutil.Decode(contentKeyHex)
if err != nil {
return 0, err
}
content, err := hexutil.Decode(contentHex)
if err != nil {
return 0, err
}
id := p.portalProtocol.Self().ID()
return p.portalProtocol.Gossip(&id, [][]byte{contentKey}, [][]byte{content})
}
func (p *PortalProtocolAPI) TraceRecursiveFindContent(contentKeyHex string) (*TraceContentResult, error) {
contentKey, err := hexutil.Decode(contentKeyHex)
if err != nil {
return nil, err
}
contentId := p.portalProtocol.toContentId(contentKey)
return p.portalProtocol.TraceContentLookup(contentKey, contentId)
}

File diff suppressed because it is too large Load diff

View file

@ -1,67 +0,0 @@
package discover
import "github.com/ethereum/go-ethereum/metrics"
type portalMetrics struct {
messagesReceivedAccept metrics.Meter
messagesReceivedNodes metrics.Meter
messagesReceivedFindNodes metrics.Meter
messagesReceivedFindContent metrics.Meter
messagesReceivedContent metrics.Meter
messagesReceivedOffer metrics.Meter
messagesReceivedPing metrics.Meter
messagesReceivedPong metrics.Meter
messagesSentAccept metrics.Meter
messagesSentNodes metrics.Meter
messagesSentFindNodes metrics.Meter
messagesSentFindContent metrics.Meter
messagesSentContent metrics.Meter
messagesSentOffer metrics.Meter
messagesSentPing metrics.Meter
messagesSentPong metrics.Meter
utpInFailConn metrics.Counter
utpInFailRead metrics.Counter
utpInFailDeadline metrics.Counter
utpInSuccess metrics.Counter
utpOutFailConn metrics.Counter
utpOutFailWrite metrics.Counter
utpOutFailDeadline metrics.Counter
utpOutSuccess metrics.Counter
contentDecodedTrue metrics.Counter
contentDecodedFalse metrics.Counter
}
func newPortalMetrics(protocolName string) *portalMetrics {
return &portalMetrics{
messagesReceivedAccept: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/accept", nil),
messagesReceivedNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/nodes", nil),
messagesReceivedFindNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/find_nodes", nil),
messagesReceivedFindContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/find_content", nil),
messagesReceivedContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/content", nil),
messagesReceivedOffer: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/offer", nil),
messagesReceivedPing: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/ping", nil),
messagesReceivedPong: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/pong", nil),
messagesSentAccept: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/accept", nil),
messagesSentNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/nodes", nil),
messagesSentFindNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/find_nodes", nil),
messagesSentFindContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/find_content", nil),
messagesSentContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/content", nil),
messagesSentOffer: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/offer", nil),
messagesSentPing: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/ping", nil),
messagesSentPong: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/pong", nil),
utpInFailConn: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_conn", nil),
utpInFailRead: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_read", nil),
utpInFailDeadline: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_deadline", nil),
utpInSuccess: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/success", nil),
utpOutFailConn: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_conn", nil),
utpOutFailWrite: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_write", nil),
utpOutFailDeadline: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_deadline", nil),
utpOutSuccess: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/success", nil),
contentDecodedTrue: metrics.NewRegisteredCounter("portal/"+protocolName+"/content/decoded/true", nil),
contentDecodedFalse: metrics.NewRegisteredCounter("portal/"+protocolName+"/content/decoded/false", nil),
}
}

View file

@ -1,503 +0,0 @@
package discover
import (
"context"
"crypto/rand"
"errors"
"fmt"
"io"
"net"
"sync"
"testing"
"time"
"github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/optimism-java/utp-go"
"github.com/optimism-java/utp-go/libutp"
"github.com/prysmaticlabs/go-bitfield"
"golang.org/x/exp/slices"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/internal/testlog"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
"github.com/ethereum/go-ethereum/p2p/enode"
assert "github.com/stretchr/testify/require"
)
func setupLocalPortalNode(addr string, bootNodes []*enode.Node) (*PortalProtocol, error) {
conf := DefaultPortalProtocolConfig()
conf.NAT = nil
if addr != "" {
conf.ListenAddr = addr
}
if bootNodes != nil {
conf.BootstrapNodes = bootNodes
}
addr1, err := net.ResolveUDPAddr("udp", conf.ListenAddr)
if err != nil {
return nil, err
}
conn, err := net.ListenUDP("udp", addr1)
if err != nil {
return nil, err
}
privKey := newkey()
discCfg := Config{
PrivateKey: privKey,
NetRestrict: conf.NetRestrict,
Bootnodes: conf.BootstrapNodes,
}
nodeDB, err := enode.OpenDB(conf.NodeDBPath)
if err != nil {
return nil, err
}
localNode := enode.NewLocalNode(nodeDB, privKey)
localNode.SetFallbackIP(net.IP{127, 0, 0, 1})
localNode.Set(Tag)
if conf.NAT == nil {
var addrs []net.Addr
addrs, err = net.InterfaceAddrs()
if err != nil {
return nil, err
}
for _, address := range addrs {
// check ip addr is loopback addr
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
localNode.SetStaticIP(ipnet.IP)
break
}
}
}
}
discV5, err := ListenV5(conn, localNode, discCfg)
if err != nil {
return nil, err
}
utpSocket := NewPortalUtp(context.Background(), conf, discV5, conn)
contentQueue := make(chan *ContentElement, 50)
portalProtocol, err := NewPortalProtocol(
conf,
portalwire.History,
privKey,
conn,
localNode,
discV5,
utpSocket,
&storage.MockStorage{Db: make(map[string][]byte)},
contentQueue)
if err != nil {
return nil, err
}
return portalProtocol, nil
}
func TestPortalWireProtocolUdp(t *testing.T) {
node1, err := setupLocalPortalNode(":8777", nil)
assert.NoError(t, err)
node1.Log = testlog.Logger(t, log.LvlTrace)
err = node1.Start()
assert.NoError(t, err)
node2, err := setupLocalPortalNode(":8778", []*enode.Node{node1.localNode.Node()})
assert.NoError(t, err)
node2.Log = testlog.Logger(t, log.LvlTrace)
err = node2.Start()
assert.NoError(t, err)
time.Sleep(12 * time.Second)
node3, err := setupLocalPortalNode(":8779", []*enode.Node{node1.localNode.Node()})
assert.NoError(t, err)
node3.Log = testlog.Logger(t, log.LvlTrace)
err = node3.Start()
assert.NoError(t, err)
time.Sleep(12 * time.Second)
cid1 := libutp.ReceConnId(12)
cid2 := libutp.ReceConnId(116)
cliSendMsgWithCid1 := "there are connection id : 12!"
cliSendMsgWithCid2 := "there are connection id: 116!"
serverEchoWithCid := "accept connection sends back msg: echo"
largeTestContent := make([]byte, 1199)
_, err = rand.Read(largeTestContent)
assert.NoError(t, err)
var workGroup sync.WaitGroup
var acceptGroup sync.WaitGroup
workGroup.Add(4)
acceptGroup.Add(1)
go func() {
var acceptConn *utp.Conn
defer func() {
workGroup.Done()
_ = acceptConn.Close()
}()
acceptConn, err := node1.Utp.AcceptWithCid(context.Background(), node2.localNode.ID(), cid1)
if err != nil {
panic(err)
}
acceptGroup.Done()
buf := make([]byte, 100)
n, err := acceptConn.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
assert.Equal(t, cliSendMsgWithCid1, string(buf[:n]))
_, err = acceptConn.Write([]byte(serverEchoWithCid))
if err != nil {
panic(err)
}
}()
go func() {
var connId2Conn net.Conn
defer func() {
workGroup.Done()
_ = connId2Conn.Close()
}()
connId2Conn, err := node1.Utp.AcceptWithCid(context.Background(), node2.localNode.ID(), cid2)
if err != nil {
panic(err)
}
buf := make([]byte, 100)
n, err := connId2Conn.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
assert.Equal(t, cliSendMsgWithCid2, string(buf[:n]))
_, err = connId2Conn.Write(largeTestContent)
if err != nil {
panic(err)
}
}()
go func() {
var connWithConnId net.Conn
defer func() {
workGroup.Done()
if connWithConnId != nil {
_ = connWithConnId.Close()
}
}()
connWithConnId, err = node2.Utp.DialWithCid(context.Background(), node1.localNode.Node(), cid1.SendId())
if err != nil {
panic(err)
}
_, err = connWithConnId.Write([]byte(cliSendMsgWithCid1))
if err != nil && err != io.EOF {
panic(err)
}
buf := make([]byte, 100)
n, err := connWithConnId.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
assert.Equal(t, serverEchoWithCid, string(buf[:n]))
}()
go func() {
var ConnId2Conn net.Conn
defer func() {
workGroup.Done()
if ConnId2Conn != nil {
_ = ConnId2Conn.Close()
}
}()
ConnId2Conn, err = node2.Utp.DialWithCid(context.Background(), node1.localNode.Node(), cid2.SendId())
if err != nil && err != io.EOF {
panic(err)
}
_, err = ConnId2Conn.Write([]byte(cliSendMsgWithCid2))
if err != nil {
panic(err)
}
data := make([]byte, 0)
buf := make([]byte, 1024)
for {
var n int
n, err = ConnId2Conn.Read(buf)
if err != nil {
if errors.Is(err, io.EOF) {
break
}
}
data = append(data, buf[:n]...)
}
assert.Equal(t, largeTestContent, data)
}()
workGroup.Wait()
node1.Stop()
node2.Stop()
node3.Stop()
}
func TestPortalWireProtocol(t *testing.T) {
node1, err := setupLocalPortalNode(":7777", nil)
assert.NoError(t, err)
node1.Log = testlog.Logger(t, log.LevelDebug)
err = node1.Start()
assert.NoError(t, err)
node2, err := setupLocalPortalNode(":7778", []*enode.Node{node1.localNode.Node()})
assert.NoError(t, err)
node2.Log = testlog.Logger(t, log.LevelDebug)
err = node2.Start()
assert.NoError(t, err)
time.Sleep(12 * time.Second)
node3, err := setupLocalPortalNode(":7779", []*enode.Node{node1.localNode.Node()})
assert.NoError(t, err)
node3.Log = testlog.Logger(t, log.LevelDebug)
err = node3.Start()
assert.NoError(t, err)
time.Sleep(12 * time.Second)
slices.ContainsFunc(node1.table.NodeList(), func(n *enode.Node) bool {
return n.ID() == node2.localNode.Node().ID()
})
slices.ContainsFunc(node1.table.NodeList(), func(n *enode.Node) bool {
return n.ID() == node3.localNode.Node().ID()
})
slices.ContainsFunc(node2.table.NodeList(), func(n *enode.Node) bool {
return n.ID() == node1.localNode.Node().ID()
})
slices.ContainsFunc(node2.table.NodeList(), func(n *enode.Node) bool {
return n.ID() == node3.localNode.Node().ID()
})
slices.ContainsFunc(node3.table.NodeList(), func(n *enode.Node) bool {
return n.ID() == node1.localNode.Node().ID()
})
slices.ContainsFunc(node3.table.NodeList(), func(n *enode.Node) bool {
return n.ID() == node2.localNode.Node().ID()
})
err = node1.storage.Put(nil, node1.toContentId([]byte("test_key")), []byte("test_value"))
assert.NoError(t, err)
flag, content, err := node2.findContent(node1.localNode.Node(), []byte("test_key"))
assert.NoError(t, err)
assert.Equal(t, portalwire.ContentRawSelector, flag)
assert.Equal(t, []byte("test_value"), content)
flag, content, err = node2.findContent(node3.localNode.Node(), []byte("test_key"))
assert.NoError(t, err)
assert.Equal(t, portalwire.ContentEnrsSelector, flag)
assert.Equal(t, 1, len(content.([]*enode.Node)))
assert.Equal(t, node1.localNode.Node().ID(), content.([]*enode.Node)[0].ID())
// create a byte slice of length 1199 and fill it with random data
// this will be used as a test content
largeTestContent := make([]byte, 2000)
_, err = rand.Read(largeTestContent)
assert.NoError(t, err)
err = node1.storage.Put(nil, node1.toContentId([]byte("large_test_key")), largeTestContent)
assert.NoError(t, err)
flag, content, err = node2.findContent(node1.localNode.Node(), []byte("large_test_key"))
assert.NoError(t, err)
assert.Equal(t, largeTestContent, content)
assert.Equal(t, portalwire.ContentConnIdSelector, flag)
testEntry1 := &ContentEntry{
ContentKey: []byte("test_entry1"),
Content: []byte("test_entry1_content"),
}
testEntry2 := &ContentEntry{
ContentKey: []byte("test_entry2"),
Content: []byte("test_entry2_content"),
}
testTransientOfferRequest := &TransientOfferRequest{
Contents: []*ContentEntry{testEntry1, testEntry2},
}
offerRequest := &OfferRequest{
Kind: TransientOfferRequestKind,
Request: testTransientOfferRequest,
}
contentKeys, err := node1.offer(node3.localNode.Node(), offerRequest)
assert.Equal(t, uint64(2), bitfield.Bitlist(contentKeys).Count())
assert.NoError(t, err)
contentElement := <-node3.contentQueue
assert.Equal(t, node1.localNode.Node().ID(), contentElement.Node)
assert.Equal(t, testEntry1.ContentKey, contentElement.ContentKeys[0])
assert.Equal(t, testEntry1.Content, contentElement.Contents[0])
assert.Equal(t, testEntry2.ContentKey, contentElement.ContentKeys[1])
assert.Equal(t, testEntry2.Content, contentElement.Contents[1])
testGossipContentKeys := [][]byte{[]byte("test_gossip_content_keys"), []byte("test_gossip_content_keys2")}
testGossipContent := [][]byte{[]byte("test_gossip_content"), []byte("test_gossip_content2")}
id := node1.Self().ID()
gossip, err := node1.Gossip(&id, testGossipContentKeys, testGossipContent)
assert.NoError(t, err)
assert.Equal(t, 2, gossip)
contentElement = <-node2.contentQueue
assert.Equal(t, node1.localNode.Node().ID(), contentElement.Node)
assert.Equal(t, testGossipContentKeys[0], contentElement.ContentKeys[0])
assert.Equal(t, testGossipContent[0], contentElement.Contents[0])
assert.Equal(t, testGossipContentKeys[1], contentElement.ContentKeys[1])
assert.Equal(t, testGossipContent[1], contentElement.Contents[1])
contentElement = <-node3.contentQueue
assert.Equal(t, node1.localNode.Node().ID(), contentElement.Node)
assert.Equal(t, testGossipContentKeys[0], contentElement.ContentKeys[0])
assert.Equal(t, testGossipContent[0], contentElement.Contents[0])
assert.Equal(t, testGossipContentKeys[1], contentElement.ContentKeys[1])
assert.Equal(t, testGossipContent[1], contentElement.Contents[1])
node1.Stop()
node2.Stop()
node3.Stop()
}
func TestCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) {
defer func() {
t.Log("goroutine cancel")
}()
time.Sleep(time.Second * 5)
}(ctx)
cancel()
t.Log("after main cancel")
time.Sleep(time.Second * 3)
}
func TestContentLookup(t *testing.T) {
node1, err := setupLocalPortalNode(":17777", nil)
assert.NoError(t, err)
node1.Log = testlog.Logger(t, log.LvlTrace)
err = node1.Start()
assert.NoError(t, err)
node2, err := setupLocalPortalNode(":17778", []*enode.Node{node1.localNode.Node()})
assert.NoError(t, err)
node2.Log = testlog.Logger(t, log.LvlTrace)
err = node2.Start()
assert.NoError(t, err)
fmt.Println(node2.localNode.Node().String())
node3, err := setupLocalPortalNode(":17779", []*enode.Node{node1.localNode.Node()})
assert.NoError(t, err)
node3.Log = testlog.Logger(t, log.LvlTrace)
err = node3.Start()
assert.NoError(t, err)
defer func() {
node1.Stop()
node2.Stop()
node3.Stop()
}()
contentKey := []byte{0x3, 0x4}
content := []byte{0x1, 0x2}
contentId := node1.toContentId(contentKey)
err = node3.storage.Put(nil, contentId, content)
assert.NoError(t, err)
res, _, err := node1.ContentLookup(contentKey, contentId)
assert.NoError(t, err)
assert.Equal(t, res, content)
nonExist := []byte{0x2, 0x4}
res, _, err = node1.ContentLookup(nonExist, node1.toContentId(nonExist))
assert.Equal(t, ContentNotFound, err)
assert.Nil(t, res)
}
func TestTraceContentLookup(t *testing.T) {
node1, err := setupLocalPortalNode(":17787", nil)
assert.NoError(t, err)
node1.Log = testlog.Logger(t, log.LvlTrace)
err = node1.Start()
assert.NoError(t, err)
node2, err := setupLocalPortalNode(":17788", []*enode.Node{node1.localNode.Node()})
assert.NoError(t, err)
node2.Log = testlog.Logger(t, log.LvlTrace)
err = node2.Start()
assert.NoError(t, err)
node3, err := setupLocalPortalNode(":17789", []*enode.Node{node2.localNode.Node()})
assert.NoError(t, err)
node3.Log = testlog.Logger(t, log.LvlTrace)
err = node3.Start()
assert.NoError(t, err)
defer node1.Stop()
defer node2.Stop()
defer node3.Stop()
contentKey := []byte{0x3, 0x4}
content := []byte{0x1, 0x2}
contentId := node1.toContentId(contentKey)
err = node1.storage.Put(nil, contentId, content)
assert.NoError(t, err)
node1Id := hexutil.Encode(node1.Self().ID().Bytes())
node2Id := hexutil.Encode(node2.Self().ID().Bytes())
node3Id := hexutil.Encode(node3.Self().ID().Bytes())
res, err := node3.TraceContentLookup(contentKey, contentId)
assert.NoError(t, err)
assert.Equal(t, res.Content, hexutil.Encode(content))
assert.Equal(t, res.UtpTransfer, false)
assert.Equal(t, res.Trace.Origin, node3Id)
assert.Equal(t, res.Trace.TargetId, hexutil.Encode(contentId))
assert.Equal(t, res.Trace.ReceivedFrom, node1Id)
// check nodeMeta
node1Meta := res.Trace.Metadata[node1Id]
assert.Equal(t, node1Meta.Enr, node1.Self().String())
dis := node1.Distance(node1.Self().ID(), enode.ID(contentId))
assert.Equal(t, node1Meta.Distance, hexutil.Encode(dis[:]))
node2Meta := res.Trace.Metadata[node2Id]
assert.Equal(t, node2Meta.Enr, node2.Self().String())
dis = node2.Distance(node2.Self().ID(), enode.ID(contentId))
assert.Equal(t, node2Meta.Distance, hexutil.Encode(dis[:]))
node3Meta := res.Trace.Metadata[node3Id]
assert.Equal(t, node3Meta.Enr, node3.Self().String())
dis = node3.Distance(node3.Self().ID(), enode.ID(contentId))
assert.Equal(t, node3Meta.Distance, hexutil.Encode(dis[:]))
// check response
node3Response := res.Trace.Responses[node3Id]
assert.Equal(t, node3Response.RespondedWith, []string{node2Id})
node2Response := res.Trace.Responses[node2Id]
assert.Equal(t, node2Response.RespondedWith, []string{node1Id})
node1Response := res.Trace.Responses[node1Id]
assert.Equal(t, node1Response.RespondedWith, ([]string)(nil))
}

View file

@ -1,138 +0,0 @@
package discover
import (
"context"
"fmt"
"net"
"net/netip"
"sync"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
"github.com/ethereum/go-ethereum/p2p/discover/v5wire"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/optimism-java/utp-go"
"github.com/optimism-java/utp-go/libutp"
"go.uber.org/zap"
)
type PortalUtp struct {
ctx context.Context
log log.Logger
discV5 *UDPv5
conn UDPConn
ListenAddr string
listener *utp.Listener
utpSm *utp.SocketManager
packetRouter *utp.PacketRouter
lAddr *utp.Addr
startOnce sync.Once
}
func NewPortalUtp(ctx context.Context, config *PortalProtocolConfig, discV5 *UDPv5, conn UDPConn) *PortalUtp {
return &PortalUtp{
ctx: ctx,
log: log.New("protocol", "utp", "local", conn.LocalAddr().String()),
discV5: discV5,
conn: conn,
ListenAddr: config.ListenAddr,
}
}
func (p *PortalUtp) Start() error {
var err error
go p.startOnce.Do(func() {
var logger *zap.Logger
if p.log.Enabled(p.ctx, log.LevelDebug) || p.log.Enabled(p.ctx, log.LevelTrace) {
logger, err = zap.NewDevelopmentConfig().Build()
} else {
logger, err = zap.NewProductionConfig().Build()
}
if err != nil {
return
}
laddr := p.getLocalAddr()
p.packetRouter = utp.NewPacketRouter(p.packetRouterFunc)
p.utpSm, err = utp.NewSocketManagerWithOptions(
"utp",
laddr,
utp.WithContext(p.ctx),
utp.WithLogger(logger.Named(p.ListenAddr)),
utp.WithPacketRouter(p.packetRouter),
utp.WithMaxPacketSize(1145))
if err != nil {
return
}
p.listener, err = utp.ListenUTPOptions("utp", (*utp.Addr)(laddr), utp.WithSocketManager(p.utpSm))
if err != nil {
return
}
p.lAddr = p.listener.Addr().(*utp.Addr)
// register discv5 listener
p.discV5.RegisterTalkHandler(string(portalwire.Utp), p.handleUtpTalkRequest)
})
return err
}
func (p *PortalUtp) Stop() {
err := p.listener.Close()
if err != nil {
p.log.Error("close utp listener has error", "error", err)
}
p.discV5.Close()
}
func (p *PortalUtp) DialWithCid(ctx context.Context, dest *enode.Node, connId uint16) (net.Conn, error) {
raddr := &utp.Addr{IP: dest.IP(), Port: dest.UDP()}
p.log.Debug("will connect to: ", "nodeId", dest.ID().String(), "connId", connId)
conn, err := utp.DialUTPOptions("utp", p.lAddr, raddr, utp.WithContext(ctx), utp.WithSocketManager(p.utpSm), utp.WithConnId(connId))
return conn, err
}
func (p *PortalUtp) Dial(ctx context.Context, dest *enode.Node) (net.Conn, error) {
raddr := &utp.Addr{IP: dest.IP(), Port: dest.UDP()}
p.log.Info("will connect to: ", "addr", raddr.String())
conn, err := utp.DialUTPOptions("utp", p.lAddr, raddr, utp.WithContext(ctx), utp.WithSocketManager(p.utpSm))
return conn, err
}
func (p *PortalUtp) AcceptWithCid(ctx context.Context, nodeId enode.ID, cid *libutp.ConnId) (*utp.Conn, error) {
p.log.Debug("will accept from: ", "nodeId", nodeId.String(), "sendId", cid.SendId(), "recvId", cid.RecvId())
return p.listener.AcceptUTPContext(ctx, nodeId, cid)
}
func (p *PortalUtp) Accept(ctx context.Context) (*utp.Conn, error) {
return p.listener.AcceptUTPContext(ctx, enode.ID{}, nil)
}
func (p *PortalUtp) getLocalAddr() *net.UDPAddr {
laddr := p.conn.LocalAddr().(*net.UDPAddr)
p.log.Debug("UDP listener up", "addr", laddr)
return laddr
}
func (p *PortalUtp) packetRouterFunc(buf []byte, id enode.ID, addr *net.UDPAddr) (int, error) {
p.log.Info("will send to target data", "nodeId", id.String(), "ip", addr.IP.To4().String(), "port", addr.Port, "bufLength", len(buf))
if n, ok := p.discV5.GetCachedNode(addr.String()); ok {
//_, err := p.DiscV5.TalkRequestToID(id, addr, string(portalwire.UTPNetwork), buf)
req := &v5wire.TalkRequest{Protocol: string(portalwire.Utp), Message: buf}
p.discV5.SendFromAnotherThreadWithNode(n, netip.AddrPortFrom(netutil.IPToAddr(addr.IP), uint16(addr.Port)), req)
return len(buf), nil
} else {
p.log.Warn("not found target node info", "ip", addr.IP.To4().String(), "port", addr.Port, "bufLength", len(buf))
return 0, fmt.Errorf("not found target node id")
}
}
func (p *PortalUtp) handleUtpTalkRequest(id enode.ID, addr *net.UDPAddr, msg []byte) []byte {
p.log.Trace("receive utp data", "nodeId", id.String(), "addr", addr, "msg-length", len(msg))
p.packetRouter.ReceiveMessage(msg, &utp.NodeInfo{Id: id, Addr: addr})
return []byte("")
}

View file

@ -1,14 +1,14 @@
package beacon package beacon
import ( import (
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/portalnetwork/portalwire"
) )
type API struct { type API struct {
*discover.PortalProtocolAPI *portalwire.PortalProtocolAPI
} }
func (p *API) BeaconRoutingTableInfo() *discover.RoutingTableInfo { func (p *API) BeaconRoutingTableInfo() *portalwire.RoutingTableInfo {
return p.RoutingTableInfo() return p.RoutingTableInfo()
} }
@ -28,7 +28,7 @@ func (p *API) BeaconLookupEnr(nodeId string) (string, error) {
return p.LookupEnr(nodeId) return p.LookupEnr(nodeId)
} }
func (p *API) BeaconPing(enr string) (*discover.PortalPongResp, error) { func (p *API) BeaconPing(enr string) (*portalwire.PortalPongResp, error) {
return p.Ping(enr) return p.Ping(enr)
} }
@ -48,7 +48,7 @@ func (p *API) BeaconRecursiveFindNodes(nodeId string) ([]string, error) {
return p.RecursiveFindNodes(nodeId) return p.RecursiveFindNodes(nodeId)
} }
func (p *API) BeaconGetContent(contentKeyHex string) (*discover.ContentInfo, error) { func (p *API) BeaconGetContent(contentKeyHex string) (*portalwire.ContentInfo, error) {
return p.RecursiveFindContent(contentKeyHex) return p.RecursiveFindContent(contentKeyHex)
} }
@ -64,11 +64,11 @@ func (p *API) BeaconGossip(contentKeyHex, contentHex string) (int, error) {
return p.Gossip(contentKeyHex, contentHex) return p.Gossip(contentKeyHex, contentHex)
} }
func (p *API) BeaconTraceGetContent(contentKeyHex string) (*discover.TraceContentResult, error) { func (p *API) BeaconTraceGetContent(contentKeyHex string) (*portalwire.TraceContentResult, error) {
return p.TraceRecursiveFindContent(contentKeyHex) return p.TraceRecursiveFindContent(contentKeyHex)
} }
func NewBeaconNetworkAPI(BeaconAPI *discover.PortalProtocolAPI) *API { func NewBeaconNetworkAPI(BeaconAPI *portalwire.PortalProtocolAPI) *API {
return &API{ return &API{
BeaconAPI, BeaconAPI,
} }

View file

@ -9,7 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
ssz "github.com/ferranbt/fastssz" ssz "github.com/ferranbt/fastssz"
"github.com/protolambda/zrnt/eth2/beacon/common" "github.com/protolambda/zrnt/eth2/beacon/common"
@ -28,7 +28,7 @@ const (
) )
type BeaconNetwork struct { type BeaconNetwork struct {
portalProtocol *discover.PortalProtocol portalProtocol *portalwire.PortalProtocol
spec *common.Spec spec *common.Spec
log log.Logger log log.Logger
closeCtx context.Context closeCtx context.Context
@ -36,7 +36,7 @@ type BeaconNetwork struct {
lightClient *ConsensusLightClient lightClient *ConsensusLightClient
} }
func NewBeaconNetwork(portalProtocol *discover.PortalProtocol) *BeaconNetwork { func NewBeaconNetwork(portalProtocol *portalwire.PortalProtocol) *BeaconNetwork {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
return &BeaconNetwork{ return &BeaconNetwork{

View file

@ -8,11 +8,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
type Entry struct {
ContentKey string `yaml:"content_key"`
ContentValue string `yaml:"content_value"`
}
func TestLightClientBootstrapValidation(t *testing.T) { func TestLightClientBootstrapValidation(t *testing.T) {
bootstrap, err := GetLightClientBootstrap(0) bootstrap, err := GetLightClientBootstrap(0)
require.NoError(t, err) require.NoError(t, err)

View file

@ -5,7 +5,7 @@ import (
"errors" "errors"
"time" "time"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/protolambda/zrnt/eth2/beacon/common" "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/ztyp/codec" "github.com/protolambda/ztyp/codec"
@ -17,7 +17,7 @@ const BeaconGenesisTime uint64 = 1606824023
var _ ConsensusAPI = &PortalLightApi{} var _ ConsensusAPI = &PortalLightApi{}
type PortalLightApi struct { type PortalLightApi struct {
portalProtocol *discover.PortalProtocol portalProtocol *portalwire.PortalProtocol
spec *common.Spec spec *common.Spec
} }

View file

@ -4,9 +4,11 @@ import (
"bytes" "bytes"
"context" "context"
"database/sql" "database/sql"
"errors"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/holiman/uint256" "github.com/holiman/uint256"
"github.com/protolambda/zrnt/eth2/beacon/common" "github.com/protolambda/zrnt/eth2/beacon/common"
"github.com/protolambda/ztyp/codec" "github.com/protolambda/ztyp/codec"
@ -16,7 +18,7 @@ import (
const BytesInMB uint64 = 1000 * 1000 const BytesInMB uint64 = 1000 * 1000
type BeaconStorage struct { type Storage struct {
storageCapacityInBytes uint64 storageCapacityInBytes uint64
db *sql.DB db *sql.DB
log log.Logger log log.Logger
@ -24,17 +26,17 @@ type BeaconStorage struct {
cache *beaconStorageCache cache *beaconStorageCache
} }
var portalStorageMetrics *metrics.PortalStorageMetrics var portalStorageMetrics *portalwire.PortalStorageMetrics
type beaconStorageCache struct { type beaconStorageCache struct {
OptimisticUpdate []byte OptimisticUpdate []byte
FinalityUpdate []byte FinalityUpdate []byte
} }
var _ storage.ContentStorage = &BeaconStorage{} var _ storage.ContentStorage = &Storage{}
func NewBeaconStorage(config storage.PortalStorageConfig) (storage.ContentStorage, error) { func NewBeaconStorage(config storage.PortalStorageConfig) (storage.ContentStorage, error) {
bs := &BeaconStorage{ bs := &Storage{
storageCapacityInBytes: config.StorageCapacityMB * BytesInMB, storageCapacityInBytes: config.StorageCapacityMB * BytesInMB,
db: config.DB, db: config.DB,
log: log.New("beacon_storage"), log: log.New("beacon_storage"),
@ -46,7 +48,7 @@ func NewBeaconStorage(config storage.PortalStorageConfig) (storage.ContentStorag
} }
var err error var err error
portalStorageMetrics, err = metrics.NewPortalStorageMetrics(config.NetworkName, config.DB) portalStorageMetrics, err = portalwire.NewPortalStorageMetrics(config.NetworkName, config.DB)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -54,7 +56,7 @@ func NewBeaconStorage(config storage.PortalStorageConfig) (storage.ContentStorag
return bs, nil return bs, nil
} }
func (bs *BeaconStorage) setup() error { func (bs *Storage) setup() error {
if _, err := bs.db.Exec(CreateQueryDBBeacon); err != nil { if _, err := bs.db.Exec(CreateQueryDBBeacon); err != nil {
return err return err
} }
@ -64,7 +66,7 @@ func (bs *BeaconStorage) setup() error {
return nil return nil
} }
func (bs *BeaconStorage) Get(contentKey []byte, contentId []byte) ([]byte, error) { func (bs *Storage) Get(contentKey []byte, contentId []byte) ([]byte, error) {
switch storage.ContentType(contentKey[0]) { switch storage.ContentType(contentKey[0]) {
case LightClientBootstrap: case LightClientBootstrap:
return bs.getContentValue(contentId) return bs.getContentValue(contentId)
@ -89,7 +91,7 @@ func (bs *BeaconStorage) Get(contentKey []byte, contentId []byte) ([]byte, error
return nil, nil return nil, nil
} }
func (bs *BeaconStorage) Put(contentKey []byte, contentId []byte, content []byte) error { func (bs *Storage) Put(contentKey []byte, contentId []byte, content []byte) error {
switch storage.ContentType(contentKey[0]) { switch storage.ContentType(contentKey[0]) {
case LightClientBootstrap: case LightClientBootstrap:
return bs.putContentValue(contentId, contentKey, content) return bs.putContentValue(contentId, contentKey, content)
@ -129,20 +131,20 @@ func (bs *BeaconStorage) Put(contentKey []byte, contentId []byte, content []byte
return nil return nil
} }
func (bs *BeaconStorage) Radius() *uint256.Int { func (bs *Storage) Radius() *uint256.Int {
return storage.MaxDistance return storage.MaxDistance
} }
func (bs *BeaconStorage) getContentValue(contentId []byte) ([]byte, error) { func (bs *Storage) getContentValue(contentId []byte) ([]byte, error) {
res := make([]byte, 0) res := make([]byte, 0)
err := bs.db.QueryRowContext(context.Background(), ContentValueLookupQueryBeacon, contentId).Scan(&res) err := bs.db.QueryRowContext(context.Background(), ContentValueLookupQueryBeacon, contentId).Scan(&res)
if err == sql.ErrNoRows { if errors.Is(err, sql.ErrNoRows) {
return nil, storage.ErrContentNotFound return nil, storage.ErrContentNotFound
} }
return res, err return res, err
} }
func (bs *BeaconStorage) getLcUpdateValueByRange(start, end uint64) ([]byte, error) { func (bs *Storage) getLcUpdateValueByRange(start, end uint64) ([]byte, error) {
// LightClientUpdateRange := make([]ForkedLightClientUpdate, 0) // LightClientUpdateRange := make([]ForkedLightClientUpdate, 0)
var lightClientUpdateRange LightClientUpdateRange var lightClientUpdateRange LightClientUpdateRange
rows, err := bs.db.QueryContext(context.Background(), LCUpdateLookupQueryByRange, start, end) rows, err := bs.db.QueryContext(context.Background(), LCUpdateLookupQueryByRange, start, end)
@ -182,7 +184,7 @@ func (bs *BeaconStorage) getLcUpdateValueByRange(start, end uint64) ([]byte, err
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func (bs *BeaconStorage) putContentValue(contentId, contentKey, value []byte) error { func (bs *Storage) putContentValue(contentId, contentKey, value []byte) error {
length := 32 + len(contentKey) + len(value) length := 32 + len(contentKey) + len(value)
_, err := bs.db.ExecContext(context.Background(), InsertQueryBeacon, contentId, contentKey, value, length) _, err := bs.db.ExecContext(context.Background(), InsertQueryBeacon, contentId, contentKey, value, length)
if metrics.Enabled && err == nil { if metrics.Enabled && err == nil {
@ -192,7 +194,7 @@ func (bs *BeaconStorage) putContentValue(contentId, contentKey, value []byte) er
return err return err
} }
func (bs *BeaconStorage) putLcUpdate(period uint64, value []byte) error { func (bs *Storage) putLcUpdate(period uint64, value []byte) error {
_, err := bs.db.ExecContext(context.Background(), InsertLCUpdateQuery, period, value, 0, len(value)) _, err := bs.db.ExecContext(context.Background(), InsertLCUpdateQuery, period, value, 0, len(value))
if metrics.Enabled && err == nil { if metrics.Enabled && err == nil {
portalStorageMetrics.EntriesCount.Inc(1) portalStorageMetrics.EntriesCount.Inc(1)

View file

@ -9,8 +9,8 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
ssz "github.com/ferranbt/fastssz" ssz "github.com/ferranbt/fastssz"
"github.com/golang/snappy" "github.com/golang/snappy"
@ -22,7 +22,7 @@ import (
) )
func SetupBeaconNetwork(addr string, bootNodes []*enode.Node) (*BeaconNetwork, error) { func SetupBeaconNetwork(addr string, bootNodes []*enode.Node) (*BeaconNetwork, error) {
conf := discover.DefaultPortalProtocolConfig() conf := portalwire.DefaultPortalProtocolConfig()
if addr != "" { if addr != "" {
conf.ListenAddr = addr conf.ListenAddr = addr
} }
@ -57,17 +57,17 @@ func SetupBeaconNetwork(addr string, bootNodes []*enode.Node) (*BeaconNetwork, e
localNode := enode.NewLocalNode(nodeDB, privKey) localNode := enode.NewLocalNode(nodeDB, privKey)
localNode.SetFallbackIP(net.IP{127, 0, 0, 1}) localNode.SetFallbackIP(net.IP{127, 0, 0, 1})
localNode.Set(discover.Tag) localNode.Set(portalwire.Tag)
discV5, err := discover.ListenV5(conn, localNode, discCfg) discV5, err := discover.ListenV5(conn, localNode, discCfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
contentQueue := make(chan *discover.ContentElement, 50) contentQueue := make(chan *portalwire.ContentElement, 50)
utpSocket := discover.NewPortalUtp(context.Background(), conf, discV5, conn) utpSocket := portalwire.NewPortalUtp(context.Background(), conf, discV5, conn)
portalProtocol, err := discover.NewPortalProtocol(conf, portalwire.Beacon, privKey, conn, localNode, discV5, utpSocket, &storage.MockStorage{Db: make(map[string][]byte)}, contentQueue) portalProtocol, err := portalwire.NewPortalProtocol(conf, portalwire.Beacon, privKey, conn, localNode, discV5, utpSocket, &storage.MockStorage{Db: make(map[string][]byte)}, contentQueue)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -232,11 +232,11 @@ func BuildHistoricalSummariesProof(beaconState deneb.BeaconState) ([][]byte, err
leavesBytes = append(leavesBytes, dest) leavesBytes = append(leavesBytes, dest)
} }
tree, err := ssz.TreeFromChunks(leavesBytes) chunks, err := ssz.TreeFromChunks(leavesBytes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
proof, err := tree.Prove(59) proof, err := chunks.Prove(59)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -60,7 +60,7 @@ func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber u
} }
type API struct { type API struct {
History *history.HistoryNetwork History *history.Network
ChainID *big.Int ChainID *big.Int
} }

View file

@ -1,14 +1,14 @@
package history package history
import ( import (
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/portalnetwork/portalwire"
) )
type API struct { type API struct {
*discover.PortalProtocolAPI *portalwire.PortalProtocolAPI
} }
func (p *API) HistoryRoutingTableInfo() *discover.RoutingTableInfo { func (p *API) HistoryRoutingTableInfo() *portalwire.RoutingTableInfo {
return p.RoutingTableInfo() return p.RoutingTableInfo()
} }
@ -28,7 +28,7 @@ func (p *API) HistoryLookupEnr(nodeId string) (string, error) {
return p.LookupEnr(nodeId) return p.LookupEnr(nodeId)
} }
func (p *API) HistoryPing(enr string) (*discover.PortalPongResp, error) { func (p *API) HistoryPing(enr string) (*portalwire.PortalPongResp, error) {
return p.Ping(enr) return p.Ping(enr)
} }
@ -48,7 +48,7 @@ func (p *API) HistoryRecursiveFindNodes(nodeId string) ([]string, error) {
return p.RecursiveFindNodes(nodeId) return p.RecursiveFindNodes(nodeId)
} }
func (p *API) HistoryGetContent(contentKeyHex string) (*discover.ContentInfo, error) { func (p *API) HistoryGetContent(contentKeyHex string) (*portalwire.ContentInfo, error) {
return p.RecursiveFindContent(contentKeyHex) return p.RecursiveFindContent(contentKeyHex)
} }
@ -64,11 +64,11 @@ func (p *API) HistoryGossip(contentKeyHex, contentHex string) (int, error) {
return p.Gossip(contentKeyHex, contentHex) return p.Gossip(contentKeyHex, contentHex)
} }
func (p *API) HistoryTraceGetContent(contentKeyHex string) (*discover.TraceContentResult, error) { func (p *API) HistoryTraceGetContent(contentKeyHex string) (*portalwire.TraceContentResult, error) {
return p.TraceRecursiveFindContent(contentKeyHex) return p.TraceRecursiveFindContent(contentKeyHex)
} }
func NewHistoryNetworkAPI(historyAPI *discover.PortalProtocolAPI) *API { func NewHistoryNetworkAPI(historyAPI *portalwire.PortalProtocolAPI) *API {
return &API{ return &API{
historyAPI, historyAPI,
} }

View file

@ -13,7 +13,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
@ -61,18 +61,18 @@ func (c *ContentKey) encode() []byte {
return res return res
} }
type HistoryNetwork struct { type Network struct {
portalProtocol *discover.PortalProtocol portalProtocol *portalwire.PortalProtocol
masterAccumulator *MasterAccumulator masterAccumulator *MasterAccumulator
closeCtx context.Context closeCtx context.Context
closeFunc context.CancelFunc closeFunc context.CancelFunc
log log.Logger log log.Logger
} }
func NewHistoryNetwork(portalProtocol *discover.PortalProtocol, accu *MasterAccumulator) *HistoryNetwork { func NewHistoryNetwork(portalProtocol *portalwire.PortalProtocol, accu *MasterAccumulator) *Network {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
return &HistoryNetwork{ return &Network{
portalProtocol: portalProtocol, portalProtocol: portalProtocol,
masterAccumulator: accu, masterAccumulator: accu,
closeCtx: ctx, closeCtx: ctx,
@ -81,7 +81,7 @@ func NewHistoryNetwork(portalProtocol *discover.PortalProtocol, accu *MasterAccu
} }
} }
func (h *HistoryNetwork) Start() error { func (h *Network) Start() error {
err := h.portalProtocol.Start() err := h.portalProtocol.Start()
if err != nil { if err != nil {
return err return err
@ -91,7 +91,7 @@ func (h *HistoryNetwork) Start() error {
return nil return nil
} }
func (h *HistoryNetwork) Stop() { func (h *Network) Stop() {
h.closeFunc() h.closeFunc()
h.portalProtocol.Stop() h.portalProtocol.Stop()
} }
@ -99,7 +99,7 @@ func (h *HistoryNetwork) Stop() {
// Currently doing 4 retries on lookups but only when the validation fails. // Currently doing 4 retries on lookups but only when the validation fails.
const requestRetries = 4 const requestRetries = 4
func (h *HistoryNetwork) GetBlockHeader(blockHash []byte) (*types.Header, error) { func (h *Network) GetBlockHeader(blockHash []byte) (*types.Header, error) {
contentKey := newContentKey(BlockHeaderType, blockHash).encode() contentKey := newContentKey(BlockHeaderType, blockHash).encode()
contentId := h.portalProtocol.ToContentId(contentKey) contentId := h.portalProtocol.ToContentId(contentKey)
h.log.Trace("contentKey convert to contentId", "contentKey", hexutil.Encode(contentKey), "contentId", hexutil.Encode(contentId)) h.log.Trace("contentKey convert to contentId", "contentKey", hexutil.Encode(contentKey), "contentId", hexutil.Encode(contentId))
@ -155,7 +155,7 @@ func (h *HistoryNetwork) GetBlockHeader(blockHash []byte) (*types.Header, error)
return nil, storage.ErrContentNotFound return nil, storage.ErrContentNotFound
} }
func (h *HistoryNetwork) GetBlockBody(blockHash []byte) (*types.Body, error) { func (h *Network) GetBlockBody(blockHash []byte) (*types.Body, error) {
header, err := h.GetBlockHeader(blockHash) header, err := h.GetBlockHeader(blockHash)
if err != nil { if err != nil {
return nil, err return nil, err
@ -206,7 +206,7 @@ func (h *HistoryNetwork) GetBlockBody(blockHash []byte) (*types.Body, error) {
return nil, storage.ErrContentNotFound return nil, storage.ErrContentNotFound
} }
func (h *HistoryNetwork) GetReceipts(blockHash []byte) ([]*types.Receipt, error) { func (h *Network) GetReceipts(blockHash []byte) ([]*types.Receipt, error) {
header, err := h.GetBlockHeader(blockHash) header, err := h.GetBlockHeader(blockHash)
if err != nil { if err != nil {
return nil, err return nil, err
@ -255,7 +255,7 @@ func (h *HistoryNetwork) GetReceipts(blockHash []byte) ([]*types.Receipt, error)
return nil, storage.ErrContentNotFound return nil, storage.ErrContentNotFound
} }
func (h *HistoryNetwork) verifyHeader(header *types.Header, proof BlockHeaderProof) (bool, error) { func (h *Network) verifyHeader(header *types.Header, proof BlockHeaderProof) (bool, error) {
return h.masterAccumulator.VerifyHeader(*header, proof) return h.masterAccumulator.VerifyHeader(*header, proof)
} }
@ -457,7 +457,7 @@ func ToPortalReceipts(receipts []*types.Receipt) (*PortalReceipts, error) {
return &PortalReceipts{Receipts: res}, nil return &PortalReceipts{Receipts: res}, nil
} }
func (h *HistoryNetwork) processContentLoop(ctx context.Context) { func (h *Network) processContentLoop(ctx context.Context) {
contentChan := h.portalProtocol.GetContent() contentChan := h.portalProtocol.GetContent()
for { for {
select { select {
@ -488,7 +488,7 @@ func (h *HistoryNetwork) processContentLoop(ctx context.Context) {
} }
} }
func (h *HistoryNetwork) validateContent(contentKey []byte, content []byte) error { func (h *Network) validateContent(contentKey []byte, content []byte) error {
switch ContentType(contentKey[0]) { switch ContentType(contentKey[0]) {
case BlockHeaderType: case BlockHeaderType:
headerWithProof, err := DecodeBlockHeaderWithProof(content) headerWithProof, err := DecodeBlockHeaderWithProof(content)
@ -559,7 +559,7 @@ func (h *HistoryNetwork) validateContent(contentKey []byte, content []byte) erro
return errors.New("unknown content type") return errors.New("unknown content type")
} }
func (h *HistoryNetwork) validateContents(contentKeys [][]byte, contents [][]byte) error { func (h *Network) validateContents(contentKeys [][]byte, contents [][]byte) error {
for i, content := range contents { for i, content := range contents {
contentKey := contentKeys[i] contentKey := contentKeys[i]
err := h.validateContent(contentKey, content) err := h.validateContent(contentKey, content)

View file

@ -16,8 +16,8 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/discover/portalwire"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@ -241,7 +241,7 @@ func TestValidateContents(t *testing.T) {
func TestValidateContentForCancun(t *testing.T) { func TestValidateContentForCancun(t *testing.T) {
master, err := NewMasterAccumulator() master, err := NewMasterAccumulator()
require.NoError(t, err) require.NoError(t, err)
historyNetwork := &HistoryNetwork{ historyNetwork := &Network{
masterAccumulator: &master, masterAccumulator: &master,
} }
@ -287,12 +287,12 @@ func parseBlockHeaderKeyContent() ([]contentEntry, error) {
return res, nil return res, nil
} }
func genHistoryNetwork(addr string, bootNodes []*enode.Node) (*HistoryNetwork, error) { func genHistoryNetwork(addr string, bootNodes []*enode.Node) (*Network, error) {
glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, true)) glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, true))
slogVerbosity := log.FromLegacyLevel(5) slogVerbosity := log.FromLegacyLevel(5)
glogger.Verbosity(slogVerbosity) glogger.Verbosity(slogVerbosity)
log.SetDefault(log.NewLogger(glogger)) log.SetDefault(log.NewLogger(glogger))
conf := discover.DefaultPortalProtocolConfig() conf := portalwire.DefaultPortalProtocolConfig()
if addr != "" { if addr != "" {
conf.ListenAddr = addr conf.ListenAddr = addr
} }
@ -327,16 +327,16 @@ func genHistoryNetwork(addr string, bootNodes []*enode.Node) (*HistoryNetwork, e
localNode := enode.NewLocalNode(nodeDB, privKey) localNode := enode.NewLocalNode(nodeDB, privKey)
localNode.SetFallbackIP(net.IP{127, 0, 0, 1}) localNode.SetFallbackIP(net.IP{127, 0, 0, 1})
localNode.Set(discover.Tag) localNode.Set(portalwire.Tag)
discV5, err := discover.ListenV5(conn, localNode, discCfg) discV5, err := discover.ListenV5(conn, localNode, discCfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
contentQueue := make(chan *discover.ContentElement, 50) contentQueue := make(chan *portalwire.ContentElement, 50)
utpSocket := discover.NewPortalUtp(context.Background(), conf, discV5, conn) utpSocket := portalwire.NewPortalUtp(context.Background(), conf, discV5, conn)
portalProtocol, err := discover.NewPortalProtocol(conf, portalwire.History, privKey, conn, localNode, discV5, utpSocket, &storage.MockStorage{Db: make(map[string][]byte)}, contentQueue) portalProtocol, err := portalwire.NewPortalProtocol(conf, portalwire.History, privKey, conn, localNode, discV5, utpSocket, &storage.MockStorage{Db: make(map[string][]byte)}, contentQueue)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -0,0 +1,443 @@
package history
//
//import (
// "encoding/binary"
// "errors"
// "fmt"
// "path"
// "sync/atomic"
//
// "github.com/cockroachdb/pebble"
// "github.com/ethereum/go-ethereum/log"
// "github.com/ethereum/go-ethereum/metrics"
// "github.com/ethereum/go-ethereum/p2p/enode"
// "github.com/ethereum/go-ethereum/portalnetwork/storage"
// "github.com/holiman/uint256"
//)
//
//const (
// contentDeletionFraction = 0.05
// prefixContent = byte(0x01) // prefixContent + distance + contentId -> content
// prefixDistanceSize = byte(0x02) // prefixDistanceSize + distance -> total size
//)
//
//type ContentStorage struct {
// nodeId enode.ID
// storageCapacityInBytes uint64
// radius atomic.Value
// db *pebble.DB
// log log.Logger
//}
//
//func NewHistoryStorage(config storage.PortalStorageConfig) (storage.ContentStorage, error) {
// dbPath := path.Join(config.DataDir, config.NetworkName)
//
// opts := &pebble.Options{
// MaxOpenFiles: 1000,
// }
//
// db, err := pebble.Open(dbPath, opts)
// if err != nil {
// return nil, err
// }
//
// cs := &ContentStorage{
// nodeId: config.NodeId,
// db: db,
// storageCapacityInBytes: config.StorageCapacityMB * 1000000,
// log: log.New("storage", config.NetworkName),
// }
// cs.radius.Store(storage.MaxDistance)
// cs.setRadiusToFarthestDistance()
//
// return cs, nil
//}
//
//func makeKey(prefix byte, distance []byte, contentId []byte) []byte {
// if contentId == nil {
// key := make([]byte, 1+len(distance))
// key[0] = prefix
// copy(key[1:], distance)
// return key
// }
// key := make([]byte, 1+len(distance)+len(contentId))
// key[0] = prefix
// copy(key[1:], distance)
// copy(key[1+len(distance):], contentId)
// return key
//}
//
//func (p *ContentStorage) Put(contentKey []byte, contentId []byte, content []byte) error {
// distance := xor(contentId, p.nodeId[:])
// key := makeKey(prefixContent, distance, contentId)
//
// batch := p.db.NewBatch()
// defer batch.Close()
//
// // Update content
// if err := batch.Set(key, content, pebble.Sync); err != nil {
// return err
// }
//
// // Update distance size index
// sizeKey := makeKey(prefixDistanceSize, distance, nil)
// var currentSize uint64
// if value, closer, err := p.db.Get(sizeKey); err == nil {
// currentSize = binary.BigEndian.Uint64(value)
// closer.Close()
// }
//
// newSize := currentSize + uint64(len(content))
// sizeBytes := make([]byte, 8)
// binary.BigEndian.PutUint64(sizeBytes, newSize)
//
// if err := batch.Set(sizeKey, sizeBytes, pebble.Sync); err != nil {
// return err
// }
//
// if err := batch.Commit(pebble.Sync); err != nil {
// return err
// }
//
// if size, _ := p.UsedSize(); size > p.storageCapacityInBytes {
// if _, err := p.deleteContentFraction(contentDeletionFraction); err != nil {
// p.log.Warn("failed to delete oversize content", "err", err)
// }
// }
//
// if metrics.Enabled {
// portalStorageMetrics.EntriesCount.Inc(1)
// portalStorageMetrics.ContentStorageUsage.Inc(int64(len(content)))
// }
//
// return nil
//}
//
//func (p *ContentStorage) Get(contentKey []byte, contentId []byte) ([]byte, error) {
// distance := xor(contentId, p.nodeId[:])
// key := makeKey(prefixContent, distance, contentId)
//
// value, closer, err := p.db.Get(key)
// if err == pebble.ErrNotFound {
// return nil, storage.ErrContentNotFound
// }
// if err != nil {
// return nil, err
// }
// defer closer.Close()
//
// return value, nil
//}
//
//func (p *ContentStorage) deleteContentFraction(fraction float64) (deleteCount int, err error) {
// if fraction <= 0 || fraction >= 1 {
// return 0, errors.New("fraction should be between 0 and 1")
// }
//
// totalSize, err := p.ContentSize()
// if err != nil {
// return 0, err
// }
//
// targetSize := uint64(float64(totalSize) * fraction)
// deletedSize := uint64(0)
// count := 0
//
// iter := p.db.NewIter(&pebble.IterOptions{
// LowerBound: []byte{prefixContent},
// UpperBound: []byte{prefixContent + 1},
// })
// defer iter.Close()
//
// batch := p.db.NewBatch()
// defer batch.Close()
//
// for iter.Last(); iter.Valid() && deletedSize < targetSize; iter.Prev() {
// key := iter.Key()
// value := iter.Value()
// distance := key[1:33]
//
// // Delete content
// if err := batch.Delete(key, nil); err != nil {
// return count, err
// }
//
// // Update distance size index
// sizeKey := makeKey(prefixDistanceSize, distance, nil)
// var currentSize uint64
// sizeValue, closer, err := p.db.Get(sizeKey)
// if err == nil {
// currentSize = binary.BigEndian.Uint64(sizeValue)
// closer.Close()
// }
//
// newSize := currentSize - uint64(len(value))
// if newSize == 0 {
// if err := batch.Delete(sizeKey, nil); err != nil {
// return count, err
// }
// } else {
// sizeBytes := make([]byte, 8)
// binary.BigEndian.PutUint64(sizeBytes, newSize)
// if err := batch.Set(sizeKey, sizeBytes, nil); err != nil {
// return count, err
// }
// }
//
// deletedSize += uint64(len(value))
// count++
//
// if batch.Len() >= 1000 {
// if err := batch.Commit(pebble.Sync); err != nil {
// return count, err
// }
// batch = p.db.NewBatch()
// }
// }
// if batch.Len() > 0 {
// if err := batch.Commit(pebble.Sync); err != nil {
// return count, err
// }
// }
//
// if iter.Valid() {
// key := iter.Key()
// distance := key[1:33]
// dis := uint256.NewInt(0)
// if err := dis.UnmarshalSSZ(distance); err != nil {
// return count, err
// }
// p.radius.Store(dis)
// }
//
// return count, nil
//}
//
//func (p *ContentStorage) UsedSize() (uint64, error) {
// var totalSize uint64
// iter := p.db.NewIter(&pebble.IterOptions{
// LowerBound: []byte{prefixDistanceSize},
// UpperBound: []byte{prefixDistanceSize + 1},
// })
// defer iter.Close()
//
// for iter.First(); iter.Valid(); iter.Next() {
// size := binary.BigEndian.Uint64(iter.Value())
// totalSize += size
// }
//
// return totalSize, nil
//}
//
//func (p *ContentStorage) ContentSize() (uint64, error) {
// return p.UsedSize()
//}
//
//func (p *ContentStorage) ContentCount() (uint64, error) {
// var count uint64
// iter, _ := p.db.NewIter(&pebble.IterOptions{
// LowerBound: []byte{prefixContent},
// UpperBound: []byte{prefixContent + 1},
// })
// defer iter.Close()
//
// for iter.First(); iter.Valid(); iter.Next() {
// count++
// }
//
// return count, nil
//}
//
//func (p *ContentStorage) Radius() *uint256.Int {
// radius := p.radius.Load()
// val := radius.(*uint256.Int)
// return val
//}
//func (p *ContentStorage) GetLargestDistance() (*uint256.Int, error) {
// iter := p.db.NewIter(&pebble.IterOptions{
// LowerBound: []byte{prefixContent},
// UpperBound: []byte{prefixContent + 1},
// })
// defer iter.Close()
//
// if !iter.Last() {
// return nil, fmt.Errorf("no content found")
// }
//
// key := iter.Key()
// distance := key[1:33]
//
// res := uint256.NewInt(0)
// err := res.UnmarshalSSZ(distance)
// return res, err
//}
//
//func (p *ContentStorage) EstimateNewRadius(currentRadius *uint256.Int) (*uint256.Int, error) {
// currrentSize, err := p.UsedSize()
// if err != nil {
// return nil, err
// }
//
// sizeRatio := currrentSize / p.storageCapacityInBytes
// if sizeRatio > 0 {
// newRadius := new(uint256.Int).Div(currentRadius, uint256.NewInt(sizeRatio))
//
// if metrics.Enabled {
// ratio := new(uint256.Int).Mul(newRadius, uint256.NewInt(100))
// ratio.Mod(ratio, storage.MaxDistance)
// portalStorageMetrics.RadiusRatio.Update(ratio.Float64() / 100)
// }
//
// return newRadius, nil
// }
// return currentRadius, nil
//}
//
//func (p *ContentStorage) setRadiusToFarthestDistance() {
// largestDistance, err := p.GetLargestDistance()
// if err != nil {
// p.log.Error("failed to get farthest distance", "err", err)
// return
// }
// p.radius.Store(largestDistance)
//}
//func (p *ContentStorage) ForcePrune(radius *uint256.Int) error {
// batch := p.db.NewBatch()
// defer batch.Close()
//
// iter := p.db.NewIter(&pebble.IterOptions{
// LowerBound: []byte{prefixContent},
// UpperBound: []byte{prefixContent + 1},
// })
// defer iter.Close()
//
// var deletedSize int64
// deleteCount := 0
//
// for iter.First(); iter.Valid(); iter.Next() {
// key := iter.Key()
// value := iter.Value()
// distance := key[1:33]
//
// dis := uint256.NewInt(0)
// if err := dis.UnmarshalSSZ(distance); err != nil {
// return err
// }
//
// if dis.Cmp(radius) > 0 {
// // Delete content
// if err := batch.Delete(key, nil); err != nil {
// return err
// }
//
// // Update distance size index
// sizeKey := makeKey(prefixDistanceSize, distance, nil)
// var currentSize uint64
// if sizeValue, closer, err := p.db.Get(sizeKey); err == nil {
// currentSize = binary.BigEndian.Uint64(sizeValue)
// closer.Close()
// }
//
// newSize := currentSize - uint64(len(value))
// if newSize == 0 {
// if err := batch.Delete(sizeKey, nil); err != nil {
// return err
// }
// } else {
// sizeBytes := make([]byte, 8)
// binary.BigEndian.PutUint64(sizeBytes, newSize)
// if err := batch.Set(sizeKey, sizeBytes, nil); err != nil {
// return err
// }
// }
//
// deletedSize += int64(len(value))
// deleteCount++
// }
//
// if batch.Len() >= 1000 {
// if err := batch.Commit(pebble.Sync); err != nil {
// return err
// }
// batch = p.db.NewBatch()
// }
// }
// if batch.Len() > 0 {
// if err := batch.Commit(pebble.Sync); err != nil {
// return err
// }
// }
//
// if metrics.Enabled {
// portalStorageMetrics.EntriesCount.Dec(int64(deleteCount))
// portalStorageMetrics.ContentStorageUsage.Dec(deletedSize)
// }
//
// return nil
//}
//
//func (p *ContentStorage) ReclaimSpace() error {
// return p.db.Compact([]byte{prefixContent}, []byte{prefixContent + 1}, true)
//}
//
//func (p *ContentStorage) Close() error {
// return p.db.Close()
//}
//
//func (p *ContentStorage) SizeByKey(contentId []byte) (uint64, error) {
// distance := xor(contentId, p.nodeId[:])
// key := makeKey(prefixContent, distance, contentId)
//
// value, closer, err := p.db.Get(key)
// if err == pebble.ErrNotFound {
// return 0, nil
// }
// if err != nil {
// return 0, err
// }
// defer closer.Close()
//
// return uint64(len(value)), nil
//}
//
//func (p *ContentStorage) SizeByKeys(ids [][]byte) (uint64, error) {
// var totalSize uint64
//
// for _, id := range ids {
// size, err := p.SizeByKey(id)
// if err != nil {
// return 0, err
// }
// totalSize += size
// }
//
// return totalSize, nil
//}
//
//func (p *ContentStorage) SizeOutRadius(radius *uint256.Int) (uint64, error) {
// var totalSize uint64
//
// iter := p.db.NewIter(&pebble.IterOptions{
// LowerBound: []byte{prefixDistanceSize},
// UpperBound: []byte{prefixDistanceSize + 1},
// })
// defer iter.Close()
//
// for iter.First(); iter.Valid(); iter.Next() {
// key := iter.Key()
// distance := key[1:33]
//
// dis := uint256.NewInt(0)
// if err := dis.UnmarshalSSZ(distance); err != nil {
// return 0, err
// }
//
// if dis.Cmp(radius) > 0 {
// size := binary.BigEndian.Uint64(iter.Value())
// totalSize += size
// }
// }
//
// return totalSize, nil
//}

View file

@ -16,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/holiman/uint256" "github.com/holiman/uint256"
"github.com/mattn/go-sqlite3" "github.com/mattn/go-sqlite3"
@ -57,7 +58,7 @@ type ContentStorage struct {
log log.Logger log log.Logger
} }
var portalStorageMetrics *metrics.PortalStorageMetrics var portalStorageMetrics *portalwire.PortalStorageMetrics
func xor(contentId, nodeId []byte) []byte { func xor(contentId, nodeId []byte) []byte {
// length of contentId maybe not 32bytes // length of contentId maybe not 32bytes
@ -123,7 +124,7 @@ func NewHistoryStorage(config storage.PortalStorageConfig) (storage.ContentStora
// necessary to test NetworkName==history because state also initialize HistoryStorage // necessary to test NetworkName==history because state also initialize HistoryStorage
if strings.ToLower(config.NetworkName) == "history" { if strings.ToLower(config.NetworkName) == "history" {
portalStorageMetrics, err = metrics.NewPortalStorageMetrics(config.NetworkName, config.DB) portalStorageMetrics, err = portalwire.NewPortalStorageMetrics(config.NetworkName, config.DB)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1,172 +0,0 @@
package portalnetwork
import (
"net"
"time"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/p2p/nat"
)
const (
portMapDuration = 10 * time.Minute
portMapRefreshInterval = 8 * time.Minute
portMapRetryInterval = 5 * time.Minute
extipRetryInterval = 2 * time.Minute
)
type portMapping struct {
protocol string
name string
port int
// for use by the portMappingLoop goroutine:
extPort int // the mapped port returned by the NAT interface
nextTime mclock.AbsTime
}
// setupPortMapping starts the port mapping loop if necessary.
// Note: this needs to be called after the LocalNode instance has been set on the server.
func (p *PortalProtocol) setupPortMapping() {
// portMappingRegister will receive up to two values: one for the TCP port if
// listening is enabled, and one more for enabling UDP port mapping if discovery is
// enabled. We make it buffered to avoid blocking setup while a mapping request is in
// progress.
p.portMappingRegister = make(chan *portMapping, 2)
switch p.NAT.(type) {
case nil:
// No NAT interface configured.
go p.consumePortMappingRequests()
case nat.ExtIP:
// ExtIP doesn't block, set the IP right away.
ip, _ := p.NAT.ExternalIP()
p.localNode.SetStaticIP(ip)
go p.consumePortMappingRequests()
case nat.STUN:
// STUN doesn't block, set the IP right away.
ip, _ := p.NAT.ExternalIP()
p.localNode.SetStaticIP(ip)
go p.consumePortMappingRequests()
default:
go p.portMappingLoop()
}
}
func (p *PortalProtocol) consumePortMappingRequests() {
for {
select {
case <-p.closeCtx.Done():
return
case <-p.portMappingRegister:
}
}
}
// portMappingLoop manages port mappings for UDP and TCP.
func (p *PortalProtocol) portMappingLoop() {
newLogger := func(proto string, e int, i int) log.Logger {
return log.New("proto", proto, "extport", e, "intport", i, "interface", p.NAT)
}
var (
mappings = make(map[string]*portMapping, 2)
refresh = mclock.NewAlarm(p.clock)
extip = mclock.NewAlarm(p.clock)
lastExtIP net.IP
)
extip.Schedule(p.clock.Now())
defer func() {
refresh.Stop()
extip.Stop()
for _, m := range mappings {
if m.extPort != 0 {
log := newLogger(m.protocol, m.extPort, m.port)
log.Debug("Deleting port mapping")
p.NAT.DeleteMapping(m.protocol, m.extPort, m.port)
}
}
}()
for {
// Schedule refresh of existing mappings.
for _, m := range mappings {
refresh.Schedule(m.nextTime)
}
select {
case <-p.closeCtx.Done():
return
case <-extip.C():
extip.Schedule(p.clock.Now().Add(extipRetryInterval))
ip, err := p.NAT.ExternalIP()
if err != nil {
log.Debug("Couldn't get external IP", "err", err, "interface", p.NAT)
} else if !ip.Equal(lastExtIP) {
log.Debug("External IP changed", "ip", extip, "interface", p.NAT)
} else {
continue
}
// Here, we either failed to get the external IP, or it has changed.
lastExtIP = ip
p.localNode.SetStaticIP(ip)
p.Log.Debug("set static ip in nat", "ip", p.localNode.Node().IP().String())
// Ensure port mappings are refreshed in case we have moved to a new network.
for _, m := range mappings {
m.nextTime = p.clock.Now()
}
case m := <-p.portMappingRegister:
if m.protocol != "TCP" && m.protocol != "UDP" {
panic("unknown NAT protocol name: " + m.protocol)
}
mappings[m.protocol] = m
m.nextTime = p.clock.Now()
case <-refresh.C():
for _, m := range mappings {
if p.clock.Now() < m.nextTime {
continue
}
external := m.port
if m.extPort != 0 {
external = m.extPort
}
log := newLogger(m.protocol, external, m.port)
log.Trace("Attempting port mapping")
port, err := p.NAT.AddMapping(m.protocol, external, m.port, m.name, portMapDuration)
if err != nil {
log.Debug("Couldn't add port mapping", "err", err)
m.extPort = 0
m.nextTime = p.clock.Now().Add(portMapRetryInterval)
continue
}
// It was mapped!
m.extPort = int(port)
m.nextTime = p.clock.Now().Add(portMapRefreshInterval)
if external != m.extPort {
log = newLogger(m.protocol, m.extPort, m.port)
log.Info("NAT mapped alternative port")
} else {
log.Info("NAT mapped port")
}
// Update port in local ENR.
switch m.protocol {
case "TCP":
p.localNode.Set(enr.TCP(m.extPort))
case "UDP":
p.localNode.SetFallbackUDP(m.extPort)
}
}
}
}
}

View file

@ -1,67 +0,0 @@
package portalnetwork
import "github.com/ethereum/go-ethereum/metrics"
type portalMetrics struct {
messagesReceivedAccept metrics.Meter
messagesReceivedNodes metrics.Meter
messagesReceivedFindNodes metrics.Meter
messagesReceivedFindContent metrics.Meter
messagesReceivedContent metrics.Meter
messagesReceivedOffer metrics.Meter
messagesReceivedPing metrics.Meter
messagesReceivedPong metrics.Meter
messagesSentAccept metrics.Meter
messagesSentNodes metrics.Meter
messagesSentFindNodes metrics.Meter
messagesSentFindContent metrics.Meter
messagesSentContent metrics.Meter
messagesSentOffer metrics.Meter
messagesSentPing metrics.Meter
messagesSentPong metrics.Meter
utpInFailConn metrics.Counter
utpInFailRead metrics.Counter
utpInFailDeadline metrics.Counter
utpInSuccess metrics.Counter
utpOutFailConn metrics.Counter
utpOutFailWrite metrics.Counter
utpOutFailDeadline metrics.Counter
utpOutSuccess metrics.Counter
contentDecodedTrue metrics.Counter
contentDecodedFalse metrics.Counter
}
func newPortalMetrics(protocolName string) *portalMetrics {
return &portalMetrics{
messagesReceivedAccept: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/accept", nil),
messagesReceivedNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/nodes", nil),
messagesReceivedFindNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/find_nodes", nil),
messagesReceivedFindContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/find_content", nil),
messagesReceivedContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/content", nil),
messagesReceivedOffer: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/offer", nil),
messagesReceivedPing: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/ping", nil),
messagesReceivedPong: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/pong", nil),
messagesSentAccept: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/accept", nil),
messagesSentNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/nodes", nil),
messagesSentFindNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/find_nodes", nil),
messagesSentFindContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/find_content", nil),
messagesSentContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/content", nil),
messagesSentOffer: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/offer", nil),
messagesSentPing: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/ping", nil),
messagesSentPong: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/pong", nil),
utpInFailConn: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_conn", nil),
utpInFailRead: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_read", nil),
utpInFailDeadline: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_deadline", nil),
utpInSuccess: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/success", nil),
utpOutFailConn: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_conn", nil),
utpOutFailWrite: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_write", nil),
utpOutFailDeadline: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_deadline", nil),
utpOutSuccess: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/success", nil),
contentDecodedTrue: metrics.NewRegisteredCounter("portal/"+protocolName+"/content/decoded/true", nil),
contentDecodedFalse: metrics.NewRegisteredCounter("portal/"+protocolName+"/content/decoded/false", nil),
}
}

View file

@ -1,4 +1,4 @@
package portalnetwork package portalwire
import ( import (
"errors" "errors"
@ -6,7 +6,6 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
@ -73,7 +72,7 @@ type RespByNode struct {
RespondedWith []string `json:"respondedWith"` RespondedWith []string `json:"respondedWith"`
} }
type Enrs struct { type EnrsResp struct {
Enrs []string `json:"enrs"` Enrs []string `json:"enrs"`
} }
@ -328,7 +327,7 @@ func (p *PortalProtocolAPI) Ping(enr string) (*PortalPongResp, error) {
return nil, err return nil, err
} }
customPayload := &portalwire.PingPongCustomData{} customPayload := &PingPongCustomData{}
err = customPayload.UnmarshalSSZ(pong.CustomPayload) err = customPayload.UnmarshalSSZ(pong.CustomPayload)
if err != nil { if err != nil {
return nil, err return nil, err
@ -381,14 +380,14 @@ func (p *PortalProtocolAPI) FindContent(enr string, contentKey string) (interfac
} }
switch flag { switch flag {
case portalwire.ContentRawSelector: case ContentRawSelector:
contentInfo := &ContentInfo{ contentInfo := &ContentInfo{
Content: hexutil.Encode(findContent.([]byte)), Content: hexutil.Encode(findContent.([]byte)),
UtpTransfer: false, UtpTransfer: false,
} }
p.portalProtocol.Log.Trace("FindContent", "contentInfo", contentInfo) p.portalProtocol.Log.Trace("FindContent", "contentInfo", contentInfo)
return contentInfo, nil return contentInfo, nil
case portalwire.ContentConnIdSelector: case ContentConnIdSelector:
contentInfo := &ContentInfo{ contentInfo := &ContentInfo{
Content: hexutil.Encode(findContent.([]byte)), Content: hexutil.Encode(findContent.([]byte)),
UtpTransfer: true, UtpTransfer: true,
@ -402,7 +401,7 @@ func (p *PortalProtocolAPI) FindContent(enr string, contentKey string) (interfac
} }
p.portalProtocol.Log.Trace("FindContent", "enrs", enrs) p.portalProtocol.Log.Trace("FindContent", "enrs", enrs)
return &Enrs{ return &EnrsResp{
Enrs: enrs, Enrs: enrs,
}, nil }, nil
} }

View file

@ -1,336 +0,0 @@
package portalwire
import (
ssz "github.com/ferranbt/fastssz"
)
// note: We changed the generated file since fastssz issues which can't be passed by the CI, so we commented the go:generate line
///go:generate sszgen --path messages.go --exclude-objs Content,Enrs,ContentKV
// Message codes for the portal protocol.
const (
PING byte = 0x00
PONG byte = 0x01
FINDNODES byte = 0x02
NODES byte = 0x03
FINDCONTENT byte = 0x04
CONTENT byte = 0x05
OFFER byte = 0x06
ACCEPT byte = 0x07
)
// Content selectors for the portal protocol.
const (
ContentConnIdSelector byte = 0x00
ContentRawSelector byte = 0x01
ContentEnrsSelector byte = 0x02
)
const (
ContentKeysLimit = 64
// OfferMessageOverhead overhead of content message is a result of 1byte for kind enum, and
// 4 bytes for offset in ssz serialization
OfferMessageOverhead = 5
// PerContentKeyOverhead each key in ContentKeysList has uint32 offset which results in 4 bytes per
// key overhead when serialized
PerContentKeyOverhead = 4
)
// Protocol IDs for the portal protocol.
// var (
// StateNetwork = []byte{0x50, 0x0a}
// HistoryNetwork = []byte{0x50, 0x0b}
// TxGossipNetwork = []byte{0x50, 0x0c}
// HeaderGossipNetwork = []byte{0x50, 0x0d}
// CanonicalIndicesNetwork = []byte{0x50, 0x0e}
// BeaconLightClientNetwork = []byte{0x50, 0x1a}
// UTPNetwork = []byte{0x75, 0x74, 0x70}
// Rendezvous = []byte{0x72, 0x65, 0x6e}
// )
type ProtocolId []byte
var (
State ProtocolId = []byte{0x50, 0x0A}
History ProtocolId = []byte{0x50, 0x0B}
Beacon ProtocolId = []byte{0x50, 0x0C}
CanonicalIndices ProtocolId = []byte{0x50, 0x0D}
VerkleState ProtocolId = []byte{0x50, 0x0E}
TransactionGossip ProtocolId = []byte{0x50, 0x0F}
Utp ProtocolId = []byte{0x75, 0x74, 0x70}
)
var protocalName = map[string]string{
string(State): "state",
string(History): "history",
string(Beacon): "beacon",
string(CanonicalIndices): "canonical indices",
string(VerkleState): "verkle state",
string(TransactionGossip): "transaction gossip",
}
func (p ProtocolId) Name() string {
return protocalName[string(p)]
}
// const (
// HistoryNetworkName = "history"
// BeaconNetworkName = "beacon"
// StateNetworkName = "state"
// )
// var NetworkNameMap = map[string]string{
// string(StateNetwork): StateNetworkName,
// string(HistoryNetwork): HistoryNetworkName,
// string(BeaconLightClientNetwork): BeaconNetworkName,
// }
type ContentKV struct {
ContentKey []byte
Content []byte
}
// Request messages for the portal protocol.
type (
PingPongCustomData struct {
Radius []byte `ssz-size:"32"`
}
Ping struct {
EnrSeq uint64
CustomPayload []byte `ssz-max:"2048"`
}
FindNodes struct {
Distances [][2]byte `ssz-max:"256,2" ssz-size:"?,2"`
}
FindContent struct {
ContentKey []byte `ssz-max:"2048"`
}
Offer struct {
ContentKeys [][]byte `ssz-max:"64,2048"`
}
)
// Response messages for the portal protocol.
type (
Pong struct {
EnrSeq uint64
CustomPayload []byte `ssz-max:"2048"`
}
Nodes struct {
Total uint8
Enrs [][]byte `ssz-max:"32,2048"`
}
ConnectionId struct {
Id []byte `ssz-size:"2"`
}
Content struct {
Content []byte `ssz-max:"2048"`
}
Enrs struct {
Enrs [][]byte `ssz-max:"32,2048"`
}
Accept struct {
ConnectionId []byte `ssz-size:"2"`
ContentKeys []byte `ssz:"bitlist" ssz-max:"64"`
}
)
// MarshalSSZ ssz marshals the Content object
func (c *Content) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(c)
}
// MarshalSSZTo ssz marshals the Content object to a target array
func (c *Content) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
// Field (0) 'Content'
if size := len(c.Content); size > 2048 {
err = ssz.ErrBytesLengthFn("Content.Content", size, 2048)
return
}
dst = append(dst, c.Content...)
return
}
// UnmarshalSSZ ssz unmarshals the Content object
func (c *Content) UnmarshalSSZ(buf []byte) error {
var err error
tail := buf
// Field (0) 'Content'
{
buf = tail[:]
if len(buf) > 2048 {
return ssz.ErrBytesLength
}
if cap(c.Content) == 0 {
c.Content = make([]byte, 0, len(buf))
}
c.Content = append(c.Content, buf...)
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Content object
func (c *Content) SizeSSZ() (size int) {
// Field (0) 'Content'
return len(c.Content)
}
// HashTreeRoot ssz hashes the Content object
func (c *Content) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(c)
}
// HashTreeRootWith ssz hashes the Content object with a hasher
func (c *Content) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'Content'
{
elemIndx := hh.Index()
byteLen := uint64(len(c.Content))
if byteLen > 2048 {
err = ssz.ErrIncorrectListSize
return
}
hh.Append(c.Content)
hh.MerkleizeWithMixin(elemIndx, byteLen, (2048+31)/32)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the Content object
func (c *Content) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(c)
}
// MarshalSSZ ssz marshals the Enrs object
func (e *Enrs) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(e)
}
// MarshalSSZTo ssz marshals the Enrs object to a target array
func (e *Enrs) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(0)
// Field (0) 'Enrs'
if size := len(e.Enrs); size > 32 {
err = ssz.ErrListTooBigFn("Enrs.Enrs", size, 32)
return
}
{
offset = 4 * len(e.Enrs)
for ii := 0; ii < len(e.Enrs); ii++ {
dst = ssz.WriteOffset(dst, offset)
offset += len(e.Enrs[ii])
}
}
for ii := 0; ii < len(e.Enrs); ii++ {
if size := len(e.Enrs[ii]); size > 2048 {
err = ssz.ErrBytesLengthFn("Enrs.Enrs[ii]", size, 2048)
return
}
dst = append(dst, e.Enrs[ii]...)
}
return
}
// UnmarshalSSZ ssz unmarshals the Enrs object
func (e *Enrs) UnmarshalSSZ(buf []byte) error {
var err error
tail := buf
// Field (0) 'Enrs'
{
buf = tail[:]
num, err := ssz.DecodeDynamicLength(buf, 32)
if err != nil {
return err
}
e.Enrs = make([][]byte, num)
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
if len(buf) > 2048 {
return ssz.ErrBytesLength
}
if cap(e.Enrs[indx]) == 0 {
e.Enrs[indx] = make([]byte, 0, len(buf))
}
e.Enrs[indx] = append(e.Enrs[indx], buf...)
return nil
})
if err != nil {
return err
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Enrs object
func (e *Enrs) SizeSSZ() (size int) {
size = 0
// Field (0) 'Enrs'
for ii := 0; ii < len(e.Enrs); ii++ {
size += 4
size += len(e.Enrs[ii])
}
return
}
// HashTreeRoot ssz hashes the Enrs object
func (e *Enrs) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(e)
}
// HashTreeRootWith ssz hashes the Enrs object with a hasher
func (e *Enrs) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'Enrs'
{
subIndx := hh.Index()
num := uint64(len(e.Enrs))
if num > 32 {
err = ssz.ErrIncorrectListSize
return
}
for _, elem := range e.Enrs {
{
elemIndx := hh.Index()
byteLen := uint64(len(elem))
if byteLen > 2048 {
err = ssz.ErrIncorrectListSize
return
}
hh.AppendBytes32(elem)
hh.MerkleizeWithMixin(elemIndx, byteLen, (2048+31)/32)
}
}
hh.MerkleizeWithMixin(subIndx, num, 32)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the Enrs object
func (e *Enrs) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(e)
}

View file

@ -1,957 +0,0 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 26a61b12807ff78c64a029acdd5bcb580dfe35b7bfbf8bf04ceebae1a3d5cac1
// Version: 0.1.3
package portalwire
import (
ssz "github.com/ferranbt/fastssz"
)
// MarshalSSZ ssz marshals the PingPongCustomData object
func (p *PingPongCustomData) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(p)
}
// MarshalSSZTo ssz marshals the PingPongCustomData object to a target array
func (p *PingPongCustomData) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
// Field (0) 'Radius'
if size := len(p.Radius); size != 32 {
err = ssz.ErrBytesLengthFn("PingPongCustomData.Radius", size, 32)
return
}
dst = append(dst, p.Radius...)
return
}
// UnmarshalSSZ ssz unmarshals the PingPongCustomData object
func (p *PingPongCustomData) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size != 32 {
return ssz.ErrSize
}
// Field (0) 'Radius'
if cap(p.Radius) == 0 {
p.Radius = make([]byte, 0, len(buf[0:32]))
}
p.Radius = append(p.Radius, buf[0:32]...)
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the PingPongCustomData object
func (p *PingPongCustomData) SizeSSZ() (size int) {
size = 32
return
}
// HashTreeRoot ssz hashes the PingPongCustomData object
func (p *PingPongCustomData) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(p)
}
// HashTreeRootWith ssz hashes the PingPongCustomData object with a hasher
func (p *PingPongCustomData) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'Radius'
if size := len(p.Radius); size != 32 {
err = ssz.ErrBytesLengthFn("PingPongCustomData.Radius", size, 32)
return
}
hh.PutBytes(p.Radius)
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the PingPongCustomData object
func (p *PingPongCustomData) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(p)
}
// MarshalSSZ ssz marshals the Ping object
func (p *Ping) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(p)
}
// MarshalSSZTo ssz marshals the Ping object to a target array
func (p *Ping) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(12)
// Field (0) 'EnrSeq'
dst = ssz.MarshalUint64(dst, p.EnrSeq)
// Offset (1) 'CustomPayload'
dst = ssz.WriteOffset(dst, offset)
offset += len(p.CustomPayload)
// Field (1) 'CustomPayload'
if size := len(p.CustomPayload); size > 2048 {
err = ssz.ErrBytesLengthFn("Ping.CustomPayload", size, 2048)
return
}
dst = append(dst, p.CustomPayload...)
return
}
// UnmarshalSSZ ssz unmarshals the Ping object
func (p *Ping) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 12 {
return ssz.ErrSize
}
tail := buf
var o1 uint64
// Field (0) 'EnrSeq'
p.EnrSeq = ssz.UnmarshallUint64(buf[0:8])
// Offset (1) 'CustomPayload'
if o1 = ssz.ReadOffset(buf[8:12]); o1 > size {
return ssz.ErrOffset
}
if o1 < 12 {
return ssz.ErrInvalidVariableOffset
}
// Field (1) 'CustomPayload'
{
buf = tail[o1:]
if len(buf) > 2048 {
return ssz.ErrBytesLength
}
if cap(p.CustomPayload) == 0 {
p.CustomPayload = make([]byte, 0, len(buf))
}
p.CustomPayload = append(p.CustomPayload, buf...)
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Ping object
func (p *Ping) SizeSSZ() (size int) {
size = 12
// Field (1) 'CustomPayload'
size += len(p.CustomPayload)
return
}
// HashTreeRoot ssz hashes the Ping object
func (p *Ping) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(p)
}
// HashTreeRootWith ssz hashes the Ping object with a hasher
func (p *Ping) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'EnrSeq'
hh.PutUint64(p.EnrSeq)
// Field (1) 'CustomPayload'
{
elemIndx := hh.Index()
byteLen := uint64(len(p.CustomPayload))
if byteLen > 2048 {
err = ssz.ErrIncorrectListSize
return
}
hh.Append(p.CustomPayload)
hh.MerkleizeWithMixin(elemIndx, byteLen, (2048+31)/32)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the Ping object
func (p *Ping) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(p)
}
// MarshalSSZ ssz marshals the FindNodes object
func (f *FindNodes) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(f)
}
// MarshalSSZTo ssz marshals the FindNodes object to a target array
func (f *FindNodes) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(4)
// Offset (0) 'Distances'
dst = ssz.WriteOffset(dst, offset)
offset += len(f.Distances) * 2
// Field (0) 'Distances'
if size := len(f.Distances); size > 256 {
err = ssz.ErrListTooBigFn("FindNodes.Distances", size, 256)
return
}
for ii := 0; ii < len(f.Distances); ii++ {
dst = append(dst, f.Distances[ii][:]...)
}
return
}
// UnmarshalSSZ ssz unmarshals the FindNodes object
func (f *FindNodes) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 4 {
return ssz.ErrSize
}
tail := buf
var o0 uint64
// Offset (0) 'Distances'
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
return ssz.ErrOffset
}
if o0 < 4 {
return ssz.ErrInvalidVariableOffset
}
// Field (0) 'Distances'
{
buf = tail[o0:]
num, err := ssz.DivideInt2(len(buf), 2, 256)
if err != nil {
return err
}
f.Distances = make([][2]byte, num)
for ii := 0; ii < num; ii++ {
copy(f.Distances[ii][:], buf[ii*2:(ii+1)*2])
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the FindNodes object
func (f *FindNodes) SizeSSZ() (size int) {
size = 4
// Field (0) 'Distances'
size += len(f.Distances) * 2
return
}
// HashTreeRoot ssz hashes the FindNodes object
func (f *FindNodes) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(f)
}
// HashTreeRootWith ssz hashes the FindNodes object with a hasher
func (f *FindNodes) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'Distances'
{
if size := len(f.Distances); size > 256 {
err = ssz.ErrListTooBigFn("FindNodes.Distances", size, 256)
return
}
subIndx := hh.Index()
for _, i := range f.Distances {
hh.PutBytes(i[:])
}
numItems := uint64(len(f.Distances))
hh.MerkleizeWithMixin(subIndx, numItems, 256)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the FindNodes object
func (f *FindNodes) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(f)
}
// MarshalSSZ ssz marshals the FindContent object
func (f *FindContent) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(f)
}
// MarshalSSZTo ssz marshals the FindContent object to a target array
func (f *FindContent) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(4)
// Offset (0) 'ContentKey'
dst = ssz.WriteOffset(dst, offset)
offset += len(f.ContentKey)
// Field (0) 'ContentKey'
if size := len(f.ContentKey); size > 2048 {
err = ssz.ErrBytesLengthFn("FindContent.ContentKey", size, 2048)
return
}
dst = append(dst, f.ContentKey...)
return
}
// UnmarshalSSZ ssz unmarshals the FindContent object
func (f *FindContent) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 4 {
return ssz.ErrSize
}
tail := buf
var o0 uint64
// Offset (0) 'ContentKey'
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
return ssz.ErrOffset
}
if o0 < 4 {
return ssz.ErrInvalidVariableOffset
}
// Field (0) 'ContentKey'
{
buf = tail[o0:]
if len(buf) > 2048 {
return ssz.ErrBytesLength
}
if cap(f.ContentKey) == 0 {
f.ContentKey = make([]byte, 0, len(buf))
}
f.ContentKey = append(f.ContentKey, buf...)
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the FindContent object
func (f *FindContent) SizeSSZ() (size int) {
size = 4
// Field (0) 'ContentKey'
size += len(f.ContentKey)
return
}
// HashTreeRoot ssz hashes the FindContent object
func (f *FindContent) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(f)
}
// HashTreeRootWith ssz hashes the FindContent object with a hasher
func (f *FindContent) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'ContentKey'
{
elemIndx := hh.Index()
byteLen := uint64(len(f.ContentKey))
if byteLen > 2048 {
err = ssz.ErrIncorrectListSize
return
}
hh.Append(f.ContentKey)
hh.MerkleizeWithMixin(elemIndx, byteLen, (2048+31)/32)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the FindContent object
func (f *FindContent) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(f)
}
// MarshalSSZ ssz marshals the Offer object
func (o *Offer) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(o)
}
// MarshalSSZTo ssz marshals the Offer object to a target array
func (o *Offer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(4)
// Offset (0) 'ContentKeys'
dst = ssz.WriteOffset(dst, offset)
for ii := 0; ii < len(o.ContentKeys); ii++ {
offset += 4
offset += len(o.ContentKeys[ii])
}
// Field (0) 'ContentKeys'
if size := len(o.ContentKeys); size > 64 {
err = ssz.ErrListTooBigFn("Offer.ContentKeys", size, 64)
return
}
{
offset = 4 * len(o.ContentKeys)
for ii := 0; ii < len(o.ContentKeys); ii++ {
dst = ssz.WriteOffset(dst, offset)
offset += len(o.ContentKeys[ii])
}
}
for ii := 0; ii < len(o.ContentKeys); ii++ {
if size := len(o.ContentKeys[ii]); size > 2048 {
err = ssz.ErrBytesLengthFn("Offer.ContentKeys[ii]", size, 2048)
return
}
dst = append(dst, o.ContentKeys[ii]...)
}
return
}
// UnmarshalSSZ ssz unmarshals the Offer object
func (o *Offer) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 4 {
return ssz.ErrSize
}
tail := buf
var o0 uint64
// Offset (0) 'ContentKeys'
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
return ssz.ErrOffset
}
if o0 < 4 {
return ssz.ErrInvalidVariableOffset
}
// Field (0) 'ContentKeys'
{
buf = tail[o0:]
num, err := ssz.DecodeDynamicLength(buf, 64)
if err != nil {
return err
}
o.ContentKeys = make([][]byte, num)
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
if len(buf) > 2048 {
return ssz.ErrBytesLength
}
if cap(o.ContentKeys[indx]) == 0 {
o.ContentKeys[indx] = make([]byte, 0, len(buf))
}
o.ContentKeys[indx] = append(o.ContentKeys[indx], buf...)
return nil
})
if err != nil {
return err
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Offer object
func (o *Offer) SizeSSZ() (size int) {
size = 4
// Field (0) 'ContentKeys'
for ii := 0; ii < len(o.ContentKeys); ii++ {
size += 4
size += len(o.ContentKeys[ii])
}
return
}
// HashTreeRoot ssz hashes the Offer object
func (o *Offer) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(o)
}
// HashTreeRootWith ssz hashes the Offer object with a hasher
func (o *Offer) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'ContentKeys'
{
subIndx := hh.Index()
num := uint64(len(o.ContentKeys))
if num > 64 {
err = ssz.ErrIncorrectListSize
return
}
for _, elem := range o.ContentKeys {
{
elemIndx := hh.Index()
byteLen := uint64(len(elem))
if byteLen > 2048 {
err = ssz.ErrIncorrectListSize
return
}
hh.AppendBytes32(elem)
hh.MerkleizeWithMixin(elemIndx, byteLen, (2048+31)/32)
}
}
hh.MerkleizeWithMixin(subIndx, num, 64)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the Offer object
func (o *Offer) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(o)
}
// MarshalSSZ ssz marshals the Pong object
func (p *Pong) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(p)
}
// MarshalSSZTo ssz marshals the Pong object to a target array
func (p *Pong) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(12)
// Field (0) 'EnrSeq'
dst = ssz.MarshalUint64(dst, p.EnrSeq)
// Offset (1) 'CustomPayload'
dst = ssz.WriteOffset(dst, offset)
offset += len(p.CustomPayload)
// Field (1) 'CustomPayload'
if size := len(p.CustomPayload); size > 2048 {
err = ssz.ErrBytesLengthFn("Pong.CustomPayload", size, 2048)
return
}
dst = append(dst, p.CustomPayload...)
return
}
// UnmarshalSSZ ssz unmarshals the Pong object
func (p *Pong) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 12 {
return ssz.ErrSize
}
tail := buf
var o1 uint64
// Field (0) 'EnrSeq'
p.EnrSeq = ssz.UnmarshallUint64(buf[0:8])
// Offset (1) 'CustomPayload'
if o1 = ssz.ReadOffset(buf[8:12]); o1 > size {
return ssz.ErrOffset
}
if o1 < 12 {
return ssz.ErrInvalidVariableOffset
}
// Field (1) 'CustomPayload'
{
buf = tail[o1:]
if len(buf) > 2048 {
return ssz.ErrBytesLength
}
if cap(p.CustomPayload) == 0 {
p.CustomPayload = make([]byte, 0, len(buf))
}
p.CustomPayload = append(p.CustomPayload, buf...)
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Pong object
func (p *Pong) SizeSSZ() (size int) {
size = 12
// Field (1) 'CustomPayload'
size += len(p.CustomPayload)
return
}
// HashTreeRoot ssz hashes the Pong object
func (p *Pong) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(p)
}
// HashTreeRootWith ssz hashes the Pong object with a hasher
func (p *Pong) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'EnrSeq'
hh.PutUint64(p.EnrSeq)
// Field (1) 'CustomPayload'
{
elemIndx := hh.Index()
byteLen := uint64(len(p.CustomPayload))
if byteLen > 2048 {
err = ssz.ErrIncorrectListSize
return
}
hh.Append(p.CustomPayload)
hh.MerkleizeWithMixin(elemIndx, byteLen, (2048+31)/32)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the Pong object
func (p *Pong) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(p)
}
// MarshalSSZ ssz marshals the Nodes object
func (n *Nodes) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(n)
}
// MarshalSSZTo ssz marshals the Nodes object to a target array
func (n *Nodes) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(5)
// Field (0) 'Total'
dst = ssz.MarshalUint8(dst, n.Total)
// Offset (1) 'Enrs'
dst = ssz.WriteOffset(dst, offset)
for ii := 0; ii < len(n.Enrs); ii++ {
offset += 4
offset += len(n.Enrs[ii])
}
// Field (1) 'Enrs'
if size := len(n.Enrs); size > 32 {
err = ssz.ErrListTooBigFn("Nodes.Enrs", size, 32)
return
}
{
offset = 4 * len(n.Enrs)
for ii := 0; ii < len(n.Enrs); ii++ {
dst = ssz.WriteOffset(dst, offset)
offset += len(n.Enrs[ii])
}
}
for ii := 0; ii < len(n.Enrs); ii++ {
if size := len(n.Enrs[ii]); size > 2048 {
err = ssz.ErrBytesLengthFn("Nodes.Enrs[ii]", size, 2048)
return
}
dst = append(dst, n.Enrs[ii]...)
}
return
}
// UnmarshalSSZ ssz unmarshals the Nodes object
func (n *Nodes) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 5 {
return ssz.ErrSize
}
tail := buf
var o1 uint64
// Field (0) 'Total'
n.Total = ssz.UnmarshallUint8(buf[0:1])
// Offset (1) 'Enrs'
if o1 = ssz.ReadOffset(buf[1:5]); o1 > size {
return ssz.ErrOffset
}
if o1 < 5 {
return ssz.ErrInvalidVariableOffset
}
// Field (1) 'Enrs'
{
buf = tail[o1:]
num, err := ssz.DecodeDynamicLength(buf, 32)
if err != nil {
return err
}
n.Enrs = make([][]byte, num)
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
if len(buf) > 2048 {
return ssz.ErrBytesLength
}
if cap(n.Enrs[indx]) == 0 {
n.Enrs[indx] = make([]byte, 0, len(buf))
}
n.Enrs[indx] = append(n.Enrs[indx], buf...)
return nil
})
if err != nil {
return err
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Nodes object
func (n *Nodes) SizeSSZ() (size int) {
size = 5
// Field (1) 'Enrs'
for ii := 0; ii < len(n.Enrs); ii++ {
size += 4
size += len(n.Enrs[ii])
}
return
}
// HashTreeRoot ssz hashes the Nodes object
func (n *Nodes) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(n)
}
// HashTreeRootWith ssz hashes the Nodes object with a hasher
func (n *Nodes) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'Total'
hh.PutUint8(n.Total)
// Field (1) 'Enrs'
{
subIndx := hh.Index()
num := uint64(len(n.Enrs))
if num > 32 {
err = ssz.ErrIncorrectListSize
return
}
for _, elem := range n.Enrs {
{
elemIndx := hh.Index()
byteLen := uint64(len(elem))
if byteLen > 2048 {
err = ssz.ErrIncorrectListSize
return
}
hh.AppendBytes32(elem)
hh.MerkleizeWithMixin(elemIndx, byteLen, (2048+31)/32)
}
}
hh.MerkleizeWithMixin(subIndx, num, 32)
}
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the Nodes object
func (n *Nodes) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(n)
}
// MarshalSSZ ssz marshals the ConnectionId object
func (c *ConnectionId) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(c)
}
// MarshalSSZTo ssz marshals the ConnectionId object to a target array
func (c *ConnectionId) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
// Field (0) 'Id'
if size := len(c.Id); size != 2 {
err = ssz.ErrBytesLengthFn("ConnectionId.Id", size, 2)
return
}
dst = append(dst, c.Id...)
return
}
// UnmarshalSSZ ssz unmarshals the ConnectionId object
func (c *ConnectionId) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size != 2 {
return ssz.ErrSize
}
// Field (0) 'Id'
if cap(c.Id) == 0 {
c.Id = make([]byte, 0, len(buf[0:2]))
}
c.Id = append(c.Id, buf[0:2]...)
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the ConnectionId object
func (c *ConnectionId) SizeSSZ() (size int) {
size = 2
return
}
// HashTreeRoot ssz hashes the ConnectionId object
func (c *ConnectionId) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(c)
}
// HashTreeRootWith ssz hashes the ConnectionId object with a hasher
func (c *ConnectionId) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'Id'
if size := len(c.Id); size != 2 {
err = ssz.ErrBytesLengthFn("ConnectionId.Id", size, 2)
return
}
hh.PutBytes(c.Id)
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the ConnectionId object
func (c *ConnectionId) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(c)
}
// MarshalSSZ ssz marshals the Accept object
func (a *Accept) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(a)
}
// MarshalSSZTo ssz marshals the Accept object to a target array
func (a *Accept) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(6)
// Field (0) 'ConnectionId'
if size := len(a.ConnectionId); size != 2 {
err = ssz.ErrBytesLengthFn("Accept.ConnectionId", size, 2)
return
}
dst = append(dst, a.ConnectionId...)
// Offset (1) 'ContentKeys'
dst = ssz.WriteOffset(dst, offset)
offset += len(a.ContentKeys)
// Field (1) 'ContentKeys'
if size := len(a.ContentKeys); size > 64 {
err = ssz.ErrBytesLengthFn("Accept.ContentKeys", size, 64)
return
}
dst = append(dst, a.ContentKeys...)
return
}
// UnmarshalSSZ ssz unmarshals the Accept object
func (a *Accept) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 6 {
return ssz.ErrSize
}
tail := buf
var o1 uint64
// Field (0) 'ConnectionId'
if cap(a.ConnectionId) == 0 {
a.ConnectionId = make([]byte, 0, len(buf[0:2]))
}
a.ConnectionId = append(a.ConnectionId, buf[0:2]...)
// Offset (1) 'ContentKeys'
if o1 = ssz.ReadOffset(buf[2:6]); o1 > size {
return ssz.ErrOffset
}
if o1 < 6 {
return ssz.ErrInvalidVariableOffset
}
// Field (1) 'ContentKeys'
{
buf = tail[o1:]
if err = ssz.ValidateBitlist(buf, 64); err != nil {
return err
}
if cap(a.ContentKeys) == 0 {
a.ContentKeys = make([]byte, 0, len(buf))
}
a.ContentKeys = append(a.ContentKeys, buf...)
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Accept object
func (a *Accept) SizeSSZ() (size int) {
size = 6
// Field (1) 'ContentKeys'
size += len(a.ContentKeys)
return
}
// HashTreeRoot ssz hashes the Accept object
func (a *Accept) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(a)
}
// HashTreeRootWith ssz hashes the Accept object with a hasher
func (a *Accept) HashTreeRootWith(hh ssz.HashWalker) (err error) {
indx := hh.Index()
// Field (0) 'ConnectionId'
if size := len(a.ConnectionId); size != 2 {
err = ssz.ErrBytesLengthFn("Accept.ConnectionId", size, 2)
return
}
hh.PutBytes(a.ConnectionId)
// Field (1) 'ContentKeys'
if len(a.ContentKeys) == 0 {
err = ssz.ErrEmptyBitlist
return
}
hh.PutBitlist(a.ContentKeys, 64)
hh.Merkleize(indx)
return
}
// GetTree ssz hashes the Accept object
func (a *Accept) GetTree() (*ssz.Node, error) {
return ssz.ProofTree(a)
}

View file

@ -1,212 +0,0 @@
package portalwire
import (
"fmt"
"testing"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rlp"
ssz "github.com/ferranbt/fastssz"
"github.com/holiman/uint256"
"github.com/prysmaticlabs/go-bitfield"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var maxUint256 = uint256.MustFromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
// https://github.com/ethereum/portal-network-specs/blob/master/portal-wire-test-vectors.md
// we remove the message type here
func TestPingMessage(t *testing.T) {
dataRadius := maxUint256.Sub(maxUint256, uint256.NewInt(1))
reverseBytes, err := dataRadius.MarshalSSZ()
require.NoError(t, err)
customData := &PingPongCustomData{
Radius: reverseBytes,
}
dataBytes, err := customData.MarshalSSZ()
assert.NoError(t, err)
ping := &Ping{
EnrSeq: 1,
CustomPayload: dataBytes,
}
expected := "0x01000000000000000c000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
data, err := ping.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
}
func TestPongMessage(t *testing.T) {
dataRadius := maxUint256.Div(maxUint256, uint256.NewInt(2))
reverseBytes, err := dataRadius.MarshalSSZ()
require.NoError(t, err)
customData := &PingPongCustomData{
Radius: reverseBytes,
}
dataBytes, err := customData.MarshalSSZ()
assert.NoError(t, err)
pong := &Pong{
EnrSeq: 1,
CustomPayload: dataBytes,
}
expected := "0x01000000000000000c000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"
data, err := pong.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
}
func TestFindNodesMessage(t *testing.T) {
distances := []uint16{256, 255}
distancesBytes := make([][2]byte, len(distances))
for i, distance := range distances {
copy(distancesBytes[i][:], ssz.MarshalUint16(make([]byte, 0), distance))
}
findNode := &FindNodes{
Distances: distancesBytes,
}
data, err := findNode.MarshalSSZ()
expected := "0x040000000001ff00"
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
}
func TestNodes(t *testing.T) {
enrs := []string{
"enr:-HW4QBzimRxkmT18hMKaAL3IcZF1UcfTMPyi3Q1pxwZZbcZVRI8DC5infUAB_UauARLOJtYTxaagKoGmIjzQxO2qUygBgmlkgnY0iXNlY3AyNTZrMaEDymNMrg1JrLQB2KTGtv6MVbcNEVv0AHacwUAPMljNMTg",
"enr:-HW4QNfxw543Ypf4HXKXdYxkyzfcxcO-6p9X986WldfVpnVTQX1xlTnWrktEWUbeTZnmgOuAY_KUhbVV1Ft98WoYUBMBgmlkgnY0iXNlY3AyNTZrMaEDDiy3QkHAxPyOgWbxp5oF1bDdlYE6dLCUUp8xfVw50jU",
}
enrsBytes := make([][]byte, 0)
for _, enr := range enrs {
n, err := enode.Parse(enode.ValidSchemes, enr)
assert.NoError(t, err)
enrBytes, err := rlp.EncodeToBytes(n.Record())
assert.NoError(t, err)
enrsBytes = append(enrsBytes, enrBytes)
}
testCases := []struct {
name string
input [][]byte
expected string
}{
{
name: "empty nodes",
input: make([][]byte, 0),
expected: "0x0105000000",
},
{
name: "two nodes",
input: enrsBytes,
expected: "0x0105000000080000007f000000f875b8401ce2991c64993d7c84c29a00bdc871917551c7d330fca2dd0d69c706596dc655448f030b98a77d4001fd46ae0112ce26d613c5a6a02a81a6223cd0c4edaa53280182696482763489736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138f875b840d7f1c39e376297f81d7297758c64cb37dcc5c3beea9f57f7ce9695d7d5a67553417d719539d6ae4b445946de4d99e680eb8063f29485b555d45b7df16a1850130182696482763489736563703235366b31a1030e2cb74241c0c4fc8e8166f1a79a05d5b0dd95813a74b094529f317d5c39d235",
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
nodes := &Nodes{
Total: 1,
Enrs: test.input,
}
data, err := nodes.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, test.expected, fmt.Sprintf("0x%x", data))
})
}
}
func TestContent(t *testing.T) {
contentKey := "0x706f7274616c"
content := &FindContent{
ContentKey: hexutil.MustDecode(contentKey),
}
expected := "0x04000000706f7274616c"
data, err := content.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
expected = "0x7468652063616b652069732061206c6965"
contentRes := &Content{
Content: hexutil.MustDecode("0x7468652063616b652069732061206c6965"),
}
data, err = contentRes.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
expectData := &Content{}
err = expectData.UnmarshalSSZ(data)
assert.NoError(t, err)
assert.Equal(t, contentRes.Content, expectData.Content)
enrs := []string{
"enr:-HW4QBzimRxkmT18hMKaAL3IcZF1UcfTMPyi3Q1pxwZZbcZVRI8DC5infUAB_UauARLOJtYTxaagKoGmIjzQxO2qUygBgmlkgnY0iXNlY3AyNTZrMaEDymNMrg1JrLQB2KTGtv6MVbcNEVv0AHacwUAPMljNMTg",
"enr:-HW4QNfxw543Ypf4HXKXdYxkyzfcxcO-6p9X986WldfVpnVTQX1xlTnWrktEWUbeTZnmgOuAY_KUhbVV1Ft98WoYUBMBgmlkgnY0iXNlY3AyNTZrMaEDDiy3QkHAxPyOgWbxp5oF1bDdlYE6dLCUUp8xfVw50jU",
}
enrsBytes := make([][]byte, 0)
for _, enr := range enrs {
n, err := enode.Parse(enode.ValidSchemes, enr)
assert.NoError(t, err)
enrBytes, err := rlp.EncodeToBytes(n.Record())
assert.NoError(t, err)
enrsBytes = append(enrsBytes, enrBytes)
}
enrsRes := &Enrs{
Enrs: enrsBytes,
}
expected = "0x080000007f000000f875b8401ce2991c64993d7c84c29a00bdc871917551c7d330fca2dd0d69c706596dc655448f030b98a77d4001fd46ae0112ce26d613c5a6a02a81a6223cd0c4edaa53280182696482763489736563703235366b31a103ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138f875b840d7f1c39e376297f81d7297758c64cb37dcc5c3beea9f57f7ce9695d7d5a67553417d719539d6ae4b445946de4d99e680eb8063f29485b555d45b7df16a1850130182696482763489736563703235366b31a1030e2cb74241c0c4fc8e8166f1a79a05d5b0dd95813a74b094529f317d5c39d235"
data, err = enrsRes.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
expectEnrs := &Enrs{}
err = expectEnrs.UnmarshalSSZ(data)
assert.NoError(t, err)
assert.Equal(t, expectEnrs.Enrs, enrsRes.Enrs)
}
func TestOfferAndAcceptMessage(t *testing.T) {
contentKey := "0x010203"
contentBytes := hexutil.MustDecode(contentKey)
contentKeys := [][]byte{contentBytes}
offer := &Offer{
ContentKeys: contentKeys,
}
expected := "0x0400000004000000010203"
data, err := offer.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
contentKeyBitlist := bitfield.NewBitlist(8)
contentKeyBitlist.SetBitAt(0, true)
accept := &Accept{
ConnectionId: []byte{0x01, 0x02},
ContentKeys: contentKeyBitlist,
}
expected = "0x0102060000000101"
data, err = accept.MarshalSSZ()
assert.NoError(t, err)
assert.Equal(t, expected, fmt.Sprintf("0x%x", data))
}

View file

@ -1,4 +1,4 @@
package discover package portalwire
import ( import (
"net" "net"

View file

@ -1,4 +1,4 @@
package portalnetwork package portalwire
import ( import (
"bytes" "bytes"
@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
ssz "github.com/ferranbt/fastssz" ssz "github.com/ferranbt/fastssz"
@ -142,8 +141,7 @@ type traceContentInfoResp struct {
type PortalProtocolOption func(p *PortalProtocol) type PortalProtocolOption func(p *PortalProtocol)
type PortalProtocolConfig struct { type PortalProtocolConfig struct {
BootstrapNodes []*enode.Node BootstrapNodes []*enode.Node
// NodeIP net.IP
ListenAddr string ListenAddr string
NetRestrict *netutil.Netlist NetRestrict *netutil.Netlist
NodeRadius *uint256.Int NodeRadius *uint256.Int
@ -203,7 +201,7 @@ func defaultContentIdFunc(contentKey []byte) []byte {
return digest[:] return digest[:]
} }
func NewPortalProtocol(config *PortalProtocolConfig, protocolId portalwire.ProtocolId, privateKey *ecdsa.PrivateKey, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *PortalUtp, storage storage.ContentStorage, contentQueue chan *ContentElement, opts ...PortalProtocolOption) (*PortalProtocol, error) { func NewPortalProtocol(config *PortalProtocolConfig, protocolId ProtocolId, privateKey *ecdsa.PrivateKey, conn discover.UDPConn, localNode *enode.LocalNode, discV5 *discover.UDPv5, utp *PortalUtp, storage storage.ContentStorage, contentQueue chan *ContentElement, opts ...PortalProtocolOption) (*PortalProtocol, error) {
closeCtx, cancelCloseCtx := context.WithCancel(context.Background()) closeCtx, cancelCloseCtx := context.WithCancel(context.Background())
protocol := &PortalProtocol{ protocol := &PortalProtocol{
@ -340,13 +338,13 @@ func (p *PortalProtocol) Ping(node *enode.Node) (uint64, error) {
return pong.EnrSeq, nil return pong.EnrSeq, nil
} }
func (p *PortalProtocol) pingInner(node *enode.Node) (*portalwire.Pong, error) { func (p *PortalProtocol) pingInner(node *enode.Node) (*Pong, error) {
enrSeq := p.Self().Seq() enrSeq := p.Self().Seq()
radiusBytes, err := p.Radius().MarshalSSZ() radiusBytes, err := p.Radius().MarshalSSZ()
if err != nil { if err != nil {
return nil, err return nil, err
} }
customPayload := &portalwire.PingPongCustomData{ customPayload := &PingPongCustomData{
Radius: radiusBytes, Radius: radiusBytes,
} }
@ -355,7 +353,7 @@ func (p *PortalProtocol) pingInner(node *enode.Node) (*portalwire.Pong, error) {
return nil, err return nil, err
} }
pingRequest := &portalwire.Ping{ pingRequest := &Ping{
EnrSeq: enrSeq, EnrSeq: enrSeq,
CustomPayload: customPayloadBytes, CustomPayload: customPayloadBytes,
} }
@ -370,7 +368,7 @@ func (p *PortalProtocol) pingInner(node *enode.Node) (*portalwire.Pong, error) {
} }
talkRequestBytes := make([]byte, 0, len(pingRequestBytes)+1) talkRequestBytes := make([]byte, 0, len(pingRequestBytes)+1)
talkRequestBytes = append(talkRequestBytes, portalwire.PING) talkRequestBytes = append(talkRequestBytes, PING)
talkRequestBytes = append(talkRequestBytes, pingRequestBytes...) talkRequestBytes = append(talkRequestBytes, pingRequestBytes...)
talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes) talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes)
@ -397,7 +395,7 @@ func (p *PortalProtocol) findNodes(node *enode.Node, distances []uint) ([]*enode
copy(distancesBytes[i][:], ssz.MarshalUint16(make([]byte, 0), uint16(distance))) copy(distancesBytes[i][:], ssz.MarshalUint16(make([]byte, 0), uint16(distance)))
} }
findNodes := &portalwire.FindNodes{ findNodes := &FindNodes{
Distances: distancesBytes, Distances: distancesBytes,
} }
@ -412,7 +410,7 @@ func (p *PortalProtocol) findNodes(node *enode.Node, distances []uint) ([]*enode
} }
talkRequestBytes := make([]byte, 0, len(findNodesBytes)+1) talkRequestBytes := make([]byte, 0, len(findNodesBytes)+1)
talkRequestBytes = append(talkRequestBytes, portalwire.FINDNODES) talkRequestBytes = append(talkRequestBytes, FINDNODES)
talkRequestBytes = append(talkRequestBytes, findNodesBytes...) talkRequestBytes = append(talkRequestBytes, findNodesBytes...)
talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes) talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes)
@ -425,7 +423,7 @@ func (p *PortalProtocol) findNodes(node *enode.Node, distances []uint) ([]*enode
} }
func (p *PortalProtocol) findContent(node *enode.Node, contentKey []byte) (byte, interface{}, error) { func (p *PortalProtocol) findContent(node *enode.Node, contentKey []byte) (byte, interface{}, error) {
findContent := &portalwire.FindContent{ findContent := &FindContent{
ContentKey: contentKey, ContentKey: contentKey,
} }
@ -440,7 +438,7 @@ func (p *PortalProtocol) findContent(node *enode.Node, contentKey []byte) (byte,
} }
talkRequestBytes := make([]byte, 0, len(findContentBytes)+1) talkRequestBytes := make([]byte, 0, len(findContentBytes)+1)
talkRequestBytes = append(talkRequestBytes, portalwire.FINDCONTENT) talkRequestBytes = append(talkRequestBytes, FINDCONTENT)
talkRequestBytes = append(talkRequestBytes, findContentBytes...) talkRequestBytes = append(talkRequestBytes, findContentBytes...)
talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes) talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes)
@ -455,7 +453,7 @@ func (p *PortalProtocol) findContent(node *enode.Node, contentKey []byte) (byte,
func (p *PortalProtocol) offer(node *enode.Node, offerRequest *OfferRequest) ([]byte, error) { func (p *PortalProtocol) offer(node *enode.Node, offerRequest *OfferRequest) ([]byte, error) {
contentKeys := getContentKeys(offerRequest) contentKeys := getContentKeys(offerRequest)
offer := &portalwire.Offer{ offer := &Offer{
ContentKeys: contentKeys, ContentKeys: contentKeys,
} }
@ -470,7 +468,7 @@ func (p *PortalProtocol) offer(node *enode.Node, offerRequest *OfferRequest) ([]
} }
talkRequestBytes := make([]byte, 0, len(offerBytes)+1) talkRequestBytes := make([]byte, 0, len(offerBytes)+1)
talkRequestBytes = append(talkRequestBytes, portalwire.OFFER) talkRequestBytes = append(talkRequestBytes, OFFER)
talkRequestBytes = append(talkRequestBytes, offerBytes...) talkRequestBytes = append(talkRequestBytes, offerBytes...)
talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes) talkResp, err := p.DiscV5.TalkRequest(node, p.protocolId, talkRequestBytes)
@ -487,13 +485,13 @@ func (p *PortalProtocol) processOffer(target *enode.Node, resp []byte, request *
if len(resp) == 0 { if len(resp) == 0 {
return nil, ErrEmptyResp return nil, ErrEmptyResp
} }
if resp[0] != portalwire.ACCEPT { if resp[0] != ACCEPT {
return nil, fmt.Errorf("invalid accept response") return nil, fmt.Errorf("invalid accept response")
} }
p.Log.Info("will process Offer", "id", target.ID(), "ip", target.IP().To4().String(), "port", target.UDP()) p.Log.Info("will process Offer", "id", target.ID(), "ip", target.IP().To4().String(), "port", target.UDP())
accept := &portalwire.Accept{} accept := &Accept{}
err = accept.UnmarshalSSZ(resp[1:]) err = accept.UnmarshalSSZ(resp[1:])
if err != nil { if err != nil {
return nil, err return nil, err
@ -621,15 +619,15 @@ func (p *PortalProtocol) processContent(target *enode.Node, resp []byte) (byte,
return 0x00, nil, ErrEmptyResp return 0x00, nil, ErrEmptyResp
} }
if resp[0] != portalwire.CONTENT { if resp[0] != CONTENT {
return 0xff, nil, fmt.Errorf("invalid content response") return 0xff, nil, fmt.Errorf("invalid content response")
} }
p.Log.Info("will process content", "id", target.ID(), "ip", target.IP().To4().String(), "port", target.UDP()) p.Log.Info("will process content", "id", target.ID(), "ip", target.IP().To4().String(), "port", target.UDP())
switch resp[1] { switch resp[1] {
case portalwire.ContentRawSelector: case ContentRawSelector:
content := &portalwire.Content{} content := &Content{}
err := content.UnmarshalSSZ(resp[2:]) err := content.UnmarshalSSZ(resp[2:])
if err != nil { if err != nil {
return 0xff, nil, err return 0xff, nil, err
@ -646,8 +644,8 @@ func (p *PortalProtocol) processContent(target *enode.Node, resp []byte) (byte,
log.Debug("Node added to replacements list", "protocol", p.protocolName, "node", target.IP(), "port", target.UDP()) log.Debug("Node added to replacements list", "protocol", p.protocolName, "node", target.IP(), "port", target.UDP())
} }
return resp[1], content.Content, nil return resp[1], content.Content, nil
case portalwire.ContentConnIdSelector: case ContentConnIdSelector:
connIdMsg := &portalwire.ConnectionId{} connIdMsg := &ConnectionId{}
err := connIdMsg.UnmarshalSSZ(resp[2:]) err := connIdMsg.UnmarshalSSZ(resp[2:])
if err != nil { if err != nil {
return 0xff, nil, err return 0xff, nil, err
@ -705,8 +703,8 @@ func (p *PortalProtocol) processContent(target *enode.Node, resp []byte) (byte,
p.portalMetrics.utpInSuccess.Inc(1) p.portalMetrics.utpInSuccess.Inc(1)
} }
return resp[1], data, nil return resp[1], data, nil
case portalwire.ContentEnrsSelector: case ContentEnrsSelector:
enrs := &portalwire.Enrs{} enrs := &Enrs{}
err := enrs.UnmarshalSSZ(resp[2:]) err := enrs.UnmarshalSSZ(resp[2:])
if err != nil { if err != nil {
@ -735,11 +733,11 @@ func (p *PortalProtocol) processNodes(target *enode.Node, resp []byte, distances
return nil, ErrEmptyResp return nil, ErrEmptyResp
} }
if resp[0] != portalwire.NODES { if resp[0] != NODES {
return nil, fmt.Errorf("invalid nodes response") return nil, fmt.Errorf("invalid nodes response")
} }
nodesResp := &portalwire.Nodes{} nodesResp := &Nodes{}
err := nodesResp.UnmarshalSSZ(resp[1:]) err := nodesResp.UnmarshalSSZ(resp[1:])
if err != nil { if err != nil {
return nil, err return nil, err
@ -788,14 +786,14 @@ func (p *PortalProtocol) filterNodes(target *enode.Node, enrs [][]byte, distance
return nodes return nodes
} }
func (p *PortalProtocol) processPong(target *enode.Node, resp []byte) (*portalwire.Pong, error) { func (p *PortalProtocol) processPong(target *enode.Node, resp []byte) (*Pong, error) {
if len(resp) == 0 { if len(resp) == 0 {
return nil, ErrEmptyResp return nil, ErrEmptyResp
} }
if resp[0] != portalwire.PONG { if resp[0] != PONG {
return nil, fmt.Errorf("invalid pong response") return nil, fmt.Errorf("invalid pong response")
} }
pong := &portalwire.Pong{} pong := &Pong{}
err := pong.UnmarshalSSZ(resp[1:]) err := pong.UnmarshalSSZ(resp[1:])
if err != nil { if err != nil {
return nil, err return nil, err
@ -806,7 +804,7 @@ func (p *PortalProtocol) processPong(target *enode.Node, resp []byte) (*portalwi
p.portalMetrics.messagesReceivedPong.Mark(1) p.portalMetrics.messagesReceivedPong.Mark(1)
} }
customPayload := &portalwire.PingPongCustomData{} customPayload := &PingPongCustomData{}
err = customPayload.UnmarshalSSZ(pong.CustomPayload) err = customPayload.UnmarshalSSZ(pong.CustomPayload)
if err != nil { if err != nil {
return nil, err return nil, err
@ -835,8 +833,8 @@ func (p *PortalProtocol) handleTalkRequest(id enode.ID, addr *net.UDPAddr, msg [
msgCode := msg[0] msgCode := msg[0]
switch msgCode { switch msgCode {
case portalwire.PING: case PING:
pingRequest := &portalwire.Ping{} pingRequest := &Ping{}
err := pingRequest.UnmarshalSSZ(msg[1:]) err := pingRequest.UnmarshalSSZ(msg[1:])
if err != nil { if err != nil {
p.Log.Error("failed to unmarshal ping request", "err", err) p.Log.Error("failed to unmarshal ping request", "err", err)
@ -854,8 +852,8 @@ func (p *PortalProtocol) handleTalkRequest(id enode.ID, addr *net.UDPAddr, msg [
} }
return resp return resp
case portalwire.FINDNODES: case FINDNODES:
findNodesRequest := &portalwire.FindNodes{} findNodesRequest := &FindNodes{}
err := findNodesRequest.UnmarshalSSZ(msg[1:]) err := findNodesRequest.UnmarshalSSZ(msg[1:])
if err != nil { if err != nil {
p.Log.Error("failed to unmarshal find nodes request", "err", err) p.Log.Error("failed to unmarshal find nodes request", "err", err)
@ -873,8 +871,8 @@ func (p *PortalProtocol) handleTalkRequest(id enode.ID, addr *net.UDPAddr, msg [
} }
return resp return resp
case portalwire.FINDCONTENT: case FINDCONTENT:
findContentRequest := &portalwire.FindContent{} findContentRequest := &FindContent{}
err := findContentRequest.UnmarshalSSZ(msg[1:]) err := findContentRequest.UnmarshalSSZ(msg[1:])
if err != nil { if err != nil {
p.Log.Error("failed to unmarshal find content request", "err", err) p.Log.Error("failed to unmarshal find content request", "err", err)
@ -892,8 +890,8 @@ func (p *PortalProtocol) handleTalkRequest(id enode.ID, addr *net.UDPAddr, msg [
} }
return resp return resp
case portalwire.OFFER: case OFFER:
offerRequest := &portalwire.Offer{} offerRequest := &Offer{}
err := offerRequest.UnmarshalSSZ(msg[1:]) err := offerRequest.UnmarshalSSZ(msg[1:])
if err != nil { if err != nil {
p.Log.Error("failed to unmarshal offer request", "err", err) p.Log.Error("failed to unmarshal offer request", "err", err)
@ -916,8 +914,8 @@ func (p *PortalProtocol) handleTalkRequest(id enode.ID, addr *net.UDPAddr, msg [
return nil return nil
} }
func (p *PortalProtocol) handlePing(id enode.ID, ping *portalwire.Ping) ([]byte, error) { func (p *PortalProtocol) handlePing(id enode.ID, ping *Ping) ([]byte, error) {
pingCustomPayload := &portalwire.PingPongCustomData{} pingCustomPayload := &PingPongCustomData{}
err := pingCustomPayload.UnmarshalSSZ(ping.CustomPayload) err := pingCustomPayload.UnmarshalSSZ(ping.CustomPayload)
if err != nil { if err != nil {
return nil, err return nil, err
@ -930,7 +928,7 @@ func (p *PortalProtocol) handlePing(id enode.ID, ping *portalwire.Ping) ([]byte,
if err != nil { if err != nil {
return nil, err return nil, err
} }
pongCustomPayload := &portalwire.PingPongCustomData{ pongCustomPayload := &PingPongCustomData{
Radius: radiusBytes, Radius: radiusBytes,
} }
@ -939,7 +937,7 @@ func (p *PortalProtocol) handlePing(id enode.ID, ping *portalwire.Ping) ([]byte,
return nil, err return nil, err
} }
pong := &portalwire.Pong{ pong := &Pong{
EnrSeq: enrSeq, EnrSeq: enrSeq,
CustomPayload: pongCustomPayloadBytes, CustomPayload: pongCustomPayloadBytes,
} }
@ -955,13 +953,13 @@ func (p *PortalProtocol) handlePing(id enode.ID, ping *portalwire.Ping) ([]byte,
} }
talkRespBytes := make([]byte, 0, len(pongBytes)+1) talkRespBytes := make([]byte, 0, len(pongBytes)+1)
talkRespBytes = append(talkRespBytes, portalwire.PONG) talkRespBytes = append(talkRespBytes, PONG)
talkRespBytes = append(talkRespBytes, pongBytes...) talkRespBytes = append(talkRespBytes, pongBytes...)
return talkRespBytes, nil return talkRespBytes, nil
} }
func (p *PortalProtocol) handleFindNodes(fromAddr *net.UDPAddr, request *portalwire.FindNodes) ([]byte, error) { func (p *PortalProtocol) handleFindNodes(fromAddr *net.UDPAddr, request *FindNodes) ([]byte, error) {
distances := make([]uint, len(request.Distances)) distances := make([]uint, len(request.Distances))
for i, distance := range request.Distances { for i, distance := range request.Distances {
distances[i] = uint(ssz.UnmarshallUint16(distance[:])) distances[i] = uint(ssz.UnmarshallUint16(distance[:]))
@ -975,7 +973,7 @@ func (p *PortalProtocol) handleFindNodes(fromAddr *net.UDPAddr, request *portalw
enrs := p.truncateNodes(nodes, maxPayloadSize, enrOverhead) enrs := p.truncateNodes(nodes, maxPayloadSize, enrOverhead)
nodesMsg := &portalwire.Nodes{ nodesMsg := &Nodes{
Total: 1, Total: 1,
Enrs: enrs, Enrs: enrs,
} }
@ -990,13 +988,13 @@ func (p *PortalProtocol) handleFindNodes(fromAddr *net.UDPAddr, request *portalw
} }
talkRespBytes := make([]byte, 0, len(nodesMsgBytes)+1) talkRespBytes := make([]byte, 0, len(nodesMsgBytes)+1)
talkRespBytes = append(talkRespBytes, portalwire.NODES) talkRespBytes = append(talkRespBytes, NODES)
talkRespBytes = append(talkRespBytes, nodesMsgBytes...) talkRespBytes = append(talkRespBytes, nodesMsgBytes...)
return talkRespBytes, nil return talkRespBytes, nil
} }
func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, request *portalwire.FindContent) ([]byte, error) { func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, request *FindContent) ([]byte, error) {
contentOverhead := 1 + 1 // msg id + SSZ Union selector contentOverhead := 1 + 1 // msg id + SSZ Union selector
maxPayloadSize := v5wire.MaxPacketSize - talkRespOverhead - contentOverhead maxPayloadSize := v5wire.MaxPacketSize - talkRespOverhead - contentOverhead
enrOverhead := 4 //per added ENR, 4 bytes offset overhead enrOverhead := 4 //per added ENR, 4 bytes offset overhead
@ -1028,7 +1026,7 @@ func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, reque
enrs = nil enrs = nil
} }
enrsMsg := &portalwire.Enrs{ enrsMsg := &Enrs{
Enrs: enrs, Enrs: enrs,
} }
@ -1043,16 +1041,16 @@ func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, reque
} }
contentMsgBytes := make([]byte, 0, len(enrsMsgBytes)+1) contentMsgBytes := make([]byte, 0, len(enrsMsgBytes)+1)
contentMsgBytes = append(contentMsgBytes, portalwire.ContentEnrsSelector) contentMsgBytes = append(contentMsgBytes, ContentEnrsSelector)
contentMsgBytes = append(contentMsgBytes, enrsMsgBytes...) contentMsgBytes = append(contentMsgBytes, enrsMsgBytes...)
talkRespBytes := make([]byte, 0, len(contentMsgBytes)+1) talkRespBytes := make([]byte, 0, len(contentMsgBytes)+1)
talkRespBytes = append(talkRespBytes, portalwire.CONTENT) talkRespBytes = append(talkRespBytes, CONTENT)
talkRespBytes = append(talkRespBytes, contentMsgBytes...) talkRespBytes = append(talkRespBytes, contentMsgBytes...)
return talkRespBytes, nil return talkRespBytes, nil
} else if len(content) <= maxPayloadSize { } else if len(content) <= maxPayloadSize {
rawContentMsg := &portalwire.Content{ rawContentMsg := &Content{
Content: content, Content: content,
} }
@ -1068,11 +1066,11 @@ func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, reque
} }
contentMsgBytes := make([]byte, 0, len(rawContentMsgBytes)+1) contentMsgBytes := make([]byte, 0, len(rawContentMsgBytes)+1)
contentMsgBytes = append(contentMsgBytes, portalwire.ContentRawSelector) contentMsgBytes = append(contentMsgBytes, ContentRawSelector)
contentMsgBytes = append(contentMsgBytes, rawContentMsgBytes...) contentMsgBytes = append(contentMsgBytes, rawContentMsgBytes...)
talkRespBytes := make([]byte, 0, len(contentMsgBytes)+1) talkRespBytes := make([]byte, 0, len(contentMsgBytes)+1)
talkRespBytes = append(talkRespBytes, portalwire.CONTENT) talkRespBytes = append(talkRespBytes, CONTENT)
talkRespBytes = append(talkRespBytes, contentMsgBytes...) talkRespBytes = append(talkRespBytes, contentMsgBytes...)
return talkRespBytes, nil return talkRespBytes, nil
@ -1140,7 +1138,7 @@ func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, reque
idBuffer := make([]byte, 2) idBuffer := make([]byte, 2)
binary.BigEndian.PutUint16(idBuffer, connectionId.SendId()) binary.BigEndian.PutUint16(idBuffer, connectionId.SendId())
connIdMsg := &portalwire.ConnectionId{ connIdMsg := &ConnectionId{
Id: idBuffer, Id: idBuffer,
} }
@ -1155,22 +1153,22 @@ func (p *PortalProtocol) handleFindContent(id enode.ID, addr *net.UDPAddr, reque
} }
contentMsgBytes := make([]byte, 0, len(connIdMsgBytes)+1) contentMsgBytes := make([]byte, 0, len(connIdMsgBytes)+1)
contentMsgBytes = append(contentMsgBytes, portalwire.ContentConnIdSelector) contentMsgBytes = append(contentMsgBytes, ContentConnIdSelector)
contentMsgBytes = append(contentMsgBytes, connIdMsgBytes...) contentMsgBytes = append(contentMsgBytes, connIdMsgBytes...)
talkRespBytes := make([]byte, 0, len(contentMsgBytes)+1) talkRespBytes := make([]byte, 0, len(contentMsgBytes)+1)
talkRespBytes = append(talkRespBytes, portalwire.CONTENT) talkRespBytes = append(talkRespBytes, CONTENT)
talkRespBytes = append(talkRespBytes, contentMsgBytes...) talkRespBytes = append(talkRespBytes, contentMsgBytes...)
return talkRespBytes, nil return talkRespBytes, nil
} }
} }
func (p *PortalProtocol) handleOffer(id enode.ID, addr *net.UDPAddr, request *portalwire.Offer) ([]byte, error) { func (p *PortalProtocol) handleOffer(id enode.ID, addr *net.UDPAddr, request *Offer) ([]byte, error) {
var err error var err error
contentKeyBitlist := bitfield.NewBitlist(uint64(len(request.ContentKeys))) contentKeyBitlist := bitfield.NewBitlist(uint64(len(request.ContentKeys)))
if len(p.contentQueue) >= cap(p.contentQueue) { if len(p.contentQueue) >= cap(p.contentQueue) {
acceptMsg := &portalwire.Accept{ acceptMsg := &Accept{
ConnectionId: []byte{0, 0}, ConnectionId: []byte{0, 0},
ContentKeys: contentKeyBitlist, ContentKeys: contentKeyBitlist,
} }
@ -1186,7 +1184,7 @@ func (p *PortalProtocol) handleOffer(id enode.ID, addr *net.UDPAddr, request *po
} }
talkRespBytes := make([]byte, 0, len(acceptMsgBytes)+1) talkRespBytes := make([]byte, 0, len(acceptMsgBytes)+1)
talkRespBytes = append(talkRespBytes, portalwire.ACCEPT) talkRespBytes = append(talkRespBytes, ACCEPT)
talkRespBytes = append(talkRespBytes, acceptMsgBytes...) talkRespBytes = append(talkRespBytes, acceptMsgBytes...)
return talkRespBytes, nil return talkRespBytes, nil
@ -1284,7 +1282,7 @@ func (p *PortalProtocol) handleOffer(id enode.ID, addr *net.UDPAddr, request *po
binary.BigEndian.PutUint16(idBuffer, uint16(0)) binary.BigEndian.PutUint16(idBuffer, uint16(0))
} }
acceptMsg := &portalwire.Accept{ acceptMsg := &Accept{
ConnectionId: idBuffer, ConnectionId: idBuffer,
ContentKeys: []byte(contentKeyBitlist), ContentKeys: []byte(contentKeyBitlist),
} }
@ -1300,7 +1298,7 @@ func (p *PortalProtocol) handleOffer(id enode.ID, addr *net.UDPAddr, request *po
} }
talkRespBytes := make([]byte, 0, len(acceptMsgBytes)+1) talkRespBytes := make([]byte, 0, len(acceptMsgBytes)+1)
talkRespBytes = append(talkRespBytes, portalwire.ACCEPT) talkRespBytes = append(talkRespBytes, ACCEPT)
talkRespBytes = append(talkRespBytes, acceptMsgBytes...) talkRespBytes = append(talkRespBytes, acceptMsgBytes...)
return talkRespBytes, nil return talkRespBytes, nil
@ -1581,7 +1579,7 @@ func (p *PortalProtocol) ContentLookup(contentKey, contentId []byte) ([]byte, bo
go func() { go func() {
defer wg.Done() defer wg.Done()
for res := range resChan { for res := range resChan {
if res.Flag != portalwire.ContentEnrsSelector { if res.Flag != ContentEnrsSelector {
result.Content = res.Content.([]byte) result.Content = res.Content.([]byte)
result.UtpTransfer = res.UtpTransfer result.UtpTransfer = res.UtpTransfer
} }
@ -1656,7 +1654,7 @@ func (p *PortalProtocol) TraceContentLookup(contentKey, contentId []byte) (*Trac
} }
// no content return // no content return
if traceContentRes.Content == "" { if traceContentRes.Content == "" {
if res.Flag == portalwire.ContentRawSelector || res.Flag == portalwire.ContentConnIdSelector { if res.Flag == ContentRawSelector || res.Flag == ContentConnIdSelector {
trace.ReceivedFrom = hexId trace.ReceivedFrom = hexId
content := res.Content.([]byte) content := res.Content.([]byte)
traceContentRes.Content = hexutil.Encode(content) traceContentRes.Content = hexutil.Encode(content)
@ -1710,7 +1708,7 @@ func (p *PortalProtocol) contentLookupWorker(n *enode.Node, contentKey []byte, r
p.Log.Debug("traceContentLookupWorker reveice response", "ip", n.IP().String(), "flag", flag) p.Log.Debug("traceContentLookupWorker reveice response", "ip", n.IP().String(), "flag", flag)
switch flag { switch flag {
case portalwire.ContentRawSelector, portalwire.ContentConnIdSelector: case ContentRawSelector, ContentConnIdSelector:
content, ok := content.([]byte) content, ok := content.([]byte)
if !ok { if !ok {
return wrapedNode, fmt.Errorf("failed to assert to raw content, value is: %v", content) return wrapedNode, fmt.Errorf("failed to assert to raw content, value is: %v", content)
@ -1721,7 +1719,7 @@ func (p *PortalProtocol) contentLookupWorker(n *enode.Node, contentKey []byte, r
Content: content, Content: content,
UtpTransfer: false, UtpTransfer: false,
} }
if flag == portalwire.ContentConnIdSelector { if flag == ContentConnIdSelector {
res.UtpTransfer = true res.UtpTransfer = true
} }
if atomic.CompareAndSwapInt32(done, 0, 1) { if atomic.CompareAndSwapInt32(done, 0, 1) {
@ -1730,7 +1728,7 @@ func (p *PortalProtocol) contentLookupWorker(n *enode.Node, contentKey []byte, r
cancel() cancel()
} }
return wrapedNode, err return wrapedNode, err
case portalwire.ContentEnrsSelector: case ContentEnrsSelector:
nodes, ok := content.([]*enode.Node) nodes, ok := content.([]*enode.Node)
if !ok { if !ok {
return wrapedNode, fmt.Errorf("failed to assert to enrs content, value is: %v", content) return wrapedNode, fmt.Errorf("failed to assert to enrs content, value is: %v", content)
@ -1775,7 +1773,7 @@ func (p *PortalProtocol) Gossip(srcNodeId *enode.ID, contentKeys [][]byte, conte
return 0, errors.New("empty content") return 0, errors.New("empty content")
} }
contentList := make([]*ContentEntry, 0, portalwire.ContentKeysLimit) contentList := make([]*ContentEntry, 0, ContentKeysLimit)
for i := 0; i < len(content); i++ { for i := 0; i < len(content); i++ {
contentEntry := &ContentEntry{ contentEntry := &ContentEntry{
ContentKey: contentKeys[i], ContentKey: contentKeys[i],

View file

@ -0,0 +1,217 @@
package portalwire
import (
"database/sql"
"errors"
"os"
"path"
"slices"
"strings"
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
)
type portalMetrics struct {
messagesReceivedAccept metrics.Meter
messagesReceivedNodes metrics.Meter
messagesReceivedFindNodes metrics.Meter
messagesReceivedFindContent metrics.Meter
messagesReceivedContent metrics.Meter
messagesReceivedOffer metrics.Meter
messagesReceivedPing metrics.Meter
messagesReceivedPong metrics.Meter
messagesSentAccept metrics.Meter
messagesSentNodes metrics.Meter
messagesSentFindNodes metrics.Meter
messagesSentFindContent metrics.Meter
messagesSentContent metrics.Meter
messagesSentOffer metrics.Meter
messagesSentPing metrics.Meter
messagesSentPong metrics.Meter
utpInFailConn metrics.Counter
utpInFailRead metrics.Counter
utpInFailDeadline metrics.Counter
utpInSuccess metrics.Counter
utpOutFailConn metrics.Counter
utpOutFailWrite metrics.Counter
utpOutFailDeadline metrics.Counter
utpOutSuccess metrics.Counter
contentDecodedTrue metrics.Counter
contentDecodedFalse metrics.Counter
}
func newPortalMetrics(protocolName string) *portalMetrics {
return &portalMetrics{
messagesReceivedAccept: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/accept", nil),
messagesReceivedNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/nodes", nil),
messagesReceivedFindNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/find_nodes", nil),
messagesReceivedFindContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/find_content", nil),
messagesReceivedContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/content", nil),
messagesReceivedOffer: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/offer", nil),
messagesReceivedPing: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/ping", nil),
messagesReceivedPong: metrics.NewRegisteredMeter("portal/"+protocolName+"/received/pong", nil),
messagesSentAccept: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/accept", nil),
messagesSentNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/nodes", nil),
messagesSentFindNodes: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/find_nodes", nil),
messagesSentFindContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/find_content", nil),
messagesSentContent: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/content", nil),
messagesSentOffer: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/offer", nil),
messagesSentPing: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/ping", nil),
messagesSentPong: metrics.NewRegisteredMeter("portal/"+protocolName+"/sent/pong", nil),
utpInFailConn: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_conn", nil),
utpInFailRead: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_read", nil),
utpInFailDeadline: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/fail_deadline", nil),
utpInSuccess: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/inbound/success", nil),
utpOutFailConn: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_conn", nil),
utpOutFailWrite: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_write", nil),
utpOutFailDeadline: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/fail_deadline", nil),
utpOutSuccess: metrics.NewRegisteredCounter("portal/"+protocolName+"/utp/outbound/success", nil),
contentDecodedTrue: metrics.NewRegisteredCounter("portal/"+protocolName+"/content/decoded/true", nil),
contentDecodedFalse: metrics.NewRegisteredCounter("portal/"+protocolName+"/content/decoded/false", nil),
}
}
type networkFileMetric struct {
filename string
metric metrics.Gauge
file *os.File
network string
}
type PortalStorageMetrics struct {
RadiusRatio metrics.GaugeFloat64
EntriesCount metrics.Gauge
ContentStorageUsage metrics.Gauge
}
const (
countEntrySql = "SELECT COUNT(1) FROM kvstore;"
contentStorageUsageSql = "SELECT SUM( length(value) ) FROM kvstore;"
)
// CollectPortalMetrics periodically collects various metrics about system entities.
func CollectPortalMetrics(refresh time.Duration, networks []string, dataDir string) {
// Short circuit if the metrics system is disabled
if !metrics.Enabled {
return
}
// Define the various metrics to collect
var (
historyTotalStorage = metrics.GetOrRegisterGauge("portal/history/total_storage", nil)
beaconTotalStorage = metrics.GetOrRegisterGauge("portal/beacon/total_storage", nil)
stateTotalStorage = metrics.GetOrRegisterGauge("portal/state/total_storage", nil)
)
var metricsArr []*networkFileMetric
if slices.Contains(networks, History.Name()) {
dbPath := path.Join(dataDir, History.Name())
metricsArr = append(metricsArr, &networkFileMetric{
filename: path.Join(dbPath, History.Name()+".sqlite"),
metric: historyTotalStorage,
network: History.Name(),
})
}
if slices.Contains(networks, Beacon.Name()) {
dbPath := path.Join(dataDir, Beacon.Name())
metricsArr = append(metricsArr, &networkFileMetric{
filename: path.Join(dbPath, Beacon.Name()+".sqlite"),
metric: beaconTotalStorage,
network: Beacon.Name(),
})
}
if slices.Contains(networks, State.Name()) {
dbPath := path.Join(dataDir, State.Name())
metricsArr = append(metricsArr, &networkFileMetric{
filename: path.Join(dbPath, State.Name()+".sqlite"),
metric: stateTotalStorage,
network: State.Name(),
})
}
for {
for _, m := range metricsArr {
var err error = nil
if m.file == nil {
m.file, err = os.OpenFile(m.filename, os.O_RDONLY, 0600)
if err != nil {
log.Debug("Could not open file", "network", m.network, "file", m.filename, "metric", "total_storage", "err", err)
}
}
if m.file != nil && err == nil {
stat, err := m.file.Stat()
if err != nil {
log.Warn("Could not get file stat", "network", m.network, "file", m.filename, "metric", "total_storage", "err", err)
}
if err == nil {
m.metric.Update(stat.Size())
}
}
}
time.Sleep(refresh)
}
}
func NewPortalStorageMetrics(network string, db *sql.DB) (*PortalStorageMetrics, error) {
if !metrics.Enabled {
return nil, nil
}
if network != History.Name() && network != Beacon.Name() && network != State.Name() {
log.Debug("Unknow network for metrics", "network", network)
return nil, errors.New("unknow network for metrics")
}
var countSql string
var contentSql string
if network == Beacon.Name() {
countSql = strings.Replace(countEntrySql, "kvstore", "beacon", 1)
contentSql = strings.Replace(contentStorageUsageSql, "kvstore", "beacon", 1)
contentSql = strings.Replace(contentSql, "value", "content_value", 1)
} else {
countSql = countEntrySql
contentSql = contentStorageUsageSql
}
storageMetrics := &PortalStorageMetrics{}
storageMetrics.RadiusRatio = metrics.NewRegisteredGaugeFloat64("portal/"+network+"/radius_ratio", nil)
storageMetrics.RadiusRatio.Update(1)
storageMetrics.EntriesCount = metrics.NewRegisteredGauge("portal/"+network+"/entry_count", nil)
log.Debug("Counting entities in " + network + " storage for metrics")
var res = new(int64)
q := db.QueryRow(countSql)
if errors.Is(q.Err(), sql.ErrNoRows) {
storageMetrics.EntriesCount.Update(0)
} else if q.Err() != nil {
log.Error("Querry execution error", "network", network, "metric", "entry_count", "err", q.Err())
return nil, q.Err()
} else {
q.Scan(res)
storageMetrics.EntriesCount.Update(*res)
}
storageMetrics.ContentStorageUsage = metrics.NewRegisteredGauge("portal/"+network+"/content_storage", nil)
log.Debug("Counting storage usage (bytes) in " + network + " for metrics")
var res2 = new(int64)
q2 := db.QueryRow(contentSql)
if errors.Is(q2.Err(), sql.ErrNoRows) {
storageMetrics.ContentStorageUsage.Update(0)
} else if q2.Err() != nil {
log.Error("Querry execution error", "network", network, "metric", "entry_count", "err", q2.Err())
return nil, q2.Err()
} else {
q2.Scan(res2)
storageMetrics.ContentStorageUsage.Update(*res2)
}
return storageMetrics, nil
}

View file

@ -1,4 +1,4 @@
package portalnetwork package portalwire
import ( import (
"context" "context"
@ -14,7 +14,6 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/optimism-java/utp-go" "github.com/optimism-java/utp-go"
"github.com/optimism-java/utp-go/libutp" "github.com/optimism-java/utp-go/libutp"
@ -92,7 +91,7 @@ func setupLocalPortalNode(addr string, bootNodes []*enode.Node) (*PortalProtocol
contentQueue := make(chan *ContentElement, 50) contentQueue := make(chan *ContentElement, 50)
portalProtocol, err := NewPortalProtocol( portalProtocol, err := NewPortalProtocol(
conf, conf,
portalwire.History, History,
privKey, privKey,
conn, conn,
localNode, localNode,
@ -297,12 +296,12 @@ func TestPortalWireProtocol(t *testing.T) {
flag, content, err := node2.findContent(node1.localNode.Node(), []byte("test_key")) flag, content, err := node2.findContent(node1.localNode.Node(), []byte("test_key"))
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, portalwire.ContentRawSelector, flag) assert.Equal(t, ContentRawSelector, flag)
assert.Equal(t, []byte("test_value"), content) assert.Equal(t, []byte("test_value"), content)
flag, content, err = node2.findContent(node3.localNode.Node(), []byte("test_key")) flag, content, err = node2.findContent(node3.localNode.Node(), []byte("test_key"))
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, portalwire.ContentEnrsSelector, flag) assert.Equal(t, ContentEnrsSelector, flag)
assert.Equal(t, 1, len(content.([]*enode.Node))) assert.Equal(t, 1, len(content.([]*enode.Node)))
assert.Equal(t, node1.localNode.Node().ID(), content.([]*enode.Node)[0].ID()) assert.Equal(t, node1.localNode.Node().ID(), content.([]*enode.Node)[0].ID())
@ -318,7 +317,7 @@ func TestPortalWireProtocol(t *testing.T) {
flag, content, err = node2.findContent(node1.localNode.Node(), []byte("large_test_key")) flag, content, err = node2.findContent(node1.localNode.Node(), []byte("large_test_key"))
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, largeTestContent, content) assert.Equal(t, largeTestContent, content)
assert.Equal(t, portalwire.ContentConnIdSelector, flag) assert.Equal(t, ContentConnIdSelector, flag)
testEntry1 := &ContentEntry{ testEntry1 := &ContentEntry{
ContentKey: []byte("test_entry1"), ContentKey: []byte("test_entry1"),

View file

@ -1,4 +1,4 @@
package portalnetwork package portalwire
import ( import (
"context" "context"
@ -12,7 +12,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/discover/v5wire" "github.com/ethereum/go-ethereum/p2p/discover/v5wire"
"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/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/optimism-java/utp-go" "github.com/optimism-java/utp-go"
"github.com/optimism-java/utp-go/libutp" "github.com/optimism-java/utp-go/libutp"
"go.uber.org/zap" "go.uber.org/zap"
@ -74,7 +73,7 @@ func (p *PortalUtp) Start() error {
p.lAddr = p.listener.Addr().(*utp.Addr) p.lAddr = p.listener.Addr().(*utp.Addr)
// register discv5 listener // register discv5 listener
p.discV5.RegisterTalkHandler(string(portalwire.Utp), p.handleUtpTalkRequest) p.discV5.RegisterTalkHandler(string(Utp), p.handleUtpTalkRequest)
}) })
return err return err
@ -122,7 +121,7 @@ func (p *PortalUtp) packetRouterFunc(buf []byte, id enode.ID, addr *net.UDPAddr)
if n, ok := p.discV5.GetCachedNode(addr.String()); ok { if n, ok := p.discV5.GetCachedNode(addr.String()); ok {
//_, err := p.DiscV5.TalkRequestToID(id, addr, string(portalwire.UTPNetwork), buf) //_, err := p.DiscV5.TalkRequestToID(id, addr, string(portalwire.UTPNetwork), buf)
req := &v5wire.TalkRequest{Protocol: string(portalwire.Utp), Message: buf} req := &v5wire.TalkRequest{Protocol: string(Utp), Message: buf}
p.discV5.SendFromAnotherThreadWithNode(n, netip.AddrPortFrom(netutil.IPToAddr(addr.IP), uint16(addr.Port)), req) p.discV5.SendFromAnotherThreadWithNode(n, netip.AddrPortFrom(netutil.IPToAddr(addr.IP), uint16(addr.Port)), req)
return len(buf), nil return len(buf), nil

View file

@ -5,7 +5,7 @@ import (
) )
// note: We changed the generated file since fastssz issues which can't be passed by the CI, so we commented the go:generate line // note: We changed the generated file since fastssz issues which can't be passed by the CI, so we commented the go:generate line
///go:generate sszgen --path messages.go --exclude-objs Content,Enrs,ContentKV ///go:generate sszgen --path types.go --exclude-objs Content,Enrs,ContentKV
// Message codes for the portal protocol. // Message codes for the portal protocol.
const ( const (
@ -37,18 +37,6 @@ const (
PerContentKeyOverhead = 4 PerContentKeyOverhead = 4
) )
// Protocol IDs for the portal protocol.
// var (
// StateNetwork = []byte{0x50, 0x0a}
// HistoryNetwork = []byte{0x50, 0x0b}
// TxGossipNetwork = []byte{0x50, 0x0c}
// HeaderGossipNetwork = []byte{0x50, 0x0d}
// CanonicalIndicesNetwork = []byte{0x50, 0x0e}
// BeaconLightClientNetwork = []byte{0x50, 0x1a}
// UTPNetwork = []byte{0x75, 0x74, 0x70}
// Rendezvous = []byte{0x72, 0x65, 0x6e}
// )
type ProtocolId []byte type ProtocolId []byte
var ( var (
@ -61,7 +49,7 @@ var (
Utp ProtocolId = []byte{0x75, 0x74, 0x70} Utp ProtocolId = []byte{0x75, 0x74, 0x70}
) )
var protocalName = map[string]string{ var protocolName = map[string]string{
string(State): "state", string(State): "state",
string(History): "history", string(History): "history",
string(Beacon): "beacon", string(Beacon): "beacon",
@ -71,21 +59,9 @@ var protocalName = map[string]string{
} }
func (p ProtocolId) Name() string { func (p ProtocolId) Name() string {
return protocalName[string(p)] return protocolName[string(p)]
} }
// const (
// HistoryNetworkName = "history"
// BeaconNetworkName = "beacon"
// StateNetworkName = "state"
// )
// var NetworkNameMap = map[string]string{
// string(StateNetwork): StateNetworkName,
// string(HistoryNetwork): HistoryNetworkName,
// string(BeaconLightClientNetwork): BeaconNetworkName,
// }
type ContentKV struct { type ContentKV struct {
ContentKey []byte ContentKey []byte
Content []byte Content []byte

View file

@ -1,14 +1,14 @@
package state package state
import ( import (
"github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/portalnetwork/portalwire"
) )
type API struct { type API struct {
*discover.PortalProtocolAPI *portalwire.PortalProtocolAPI
} }
func (p *API) StateRoutingTableInfo() *discover.RoutingTableInfo { func (p *API) StateRoutingTableInfo() *portalwire.RoutingTableInfo {
return p.RoutingTableInfo() return p.RoutingTableInfo()
} }
@ -28,7 +28,7 @@ func (p *API) StateLookupEnr(nodeId string) (string, error) {
return p.LookupEnr(nodeId) return p.LookupEnr(nodeId)
} }
func (p *API) StatePing(enr string) (*discover.PortalPongResp, error) { func (p *API) StatePing(enr string) (*portalwire.PortalPongResp, error) {
return p.Ping(enr) return p.Ping(enr)
} }
@ -48,7 +48,7 @@ func (p *API) StateRecursiveFindNodes(nodeId string) ([]string, error) {
return p.RecursiveFindNodes(nodeId) return p.RecursiveFindNodes(nodeId)
} }
func (p *API) StateGetContent(contentKeyHex string) (*discover.ContentInfo, error) { func (p *API) StateGetContent(contentKeyHex string) (*portalwire.ContentInfo, error) {
return p.RecursiveFindContent(contentKeyHex) return p.RecursiveFindContent(contentKeyHex)
} }
@ -64,11 +64,11 @@ func (p *API) StateGossip(contentKeyHex, contentHex string) (int, error) {
return p.Gossip(contentKeyHex, contentHex) return p.Gossip(contentKeyHex, contentHex)
} }
func (p *API) StateTraceGetContent(contentKeyHex string) (*discover.TraceContentResult, error) { func (p *API) StateTraceGetContent(contentKeyHex string) (*portalwire.TraceContentResult, error) {
return p.TraceRecursiveFindContent(contentKeyHex) return p.TraceRecursiveFindContent(contentKeyHex)
} }
func NewStateNetworkAPI(portalProtocolAPI *discover.PortalProtocolAPI) *API { func NewStateNetworkAPI(portalProtocolAPI *portalwire.PortalProtocolAPI) *API {
return &API{ return &API{
portalProtocolAPI, portalProtocolAPI,
} }

View file

@ -10,8 +10,8 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/portalnetwork/history" "github.com/ethereum/go-ethereum/portalnetwork/history"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
@ -21,7 +21,7 @@ import (
) )
type StateNetwork struct { type StateNetwork struct {
portalProtocol *discover.PortalProtocol portalProtocol *portalwire.PortalProtocol
closeCtx context.Context closeCtx context.Context
closeFunc context.CancelFunc closeFunc context.CancelFunc
log log.Logger log log.Logger
@ -29,7 +29,7 @@ type StateNetwork struct {
client *rpc.Client client *rpc.Client
} }
func NewStateNetwork(portalProtocol *discover.PortalProtocol, client *rpc.Client) *StateNetwork { func NewStateNetwork(portalProtocol *portalwire.PortalProtocol, client *rpc.Client) *StateNetwork {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
return &StateNetwork{ return &StateNetwork{
portalProtocol: portalProtocol, portalProtocol: portalProtocol,
@ -196,7 +196,7 @@ func (h *StateNetwork) getStateRoot(blockHash common.Bytes32) (common.Bytes32, e
contentKey = append(contentKey, blockHash[:]...) contentKey = append(contentKey, blockHash[:]...)
arg := hexutil.Encode(contentKey) arg := hexutil.Encode(contentKey)
res := &discover.ContentInfo{} res := &portalwire.ContentInfo{}
err := h.client.CallContext(ctx, res, "portal_historyGetContent", arg) err := h.client.CallContext(ctx, res, "portal_historyGetContent", arg)
if err != nil { if err != nil {
return common.Bytes32{}, err return common.Bytes32{}, err

View file

@ -6,8 +6,8 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/portalnetwork/history" "github.com/ethereum/go-ethereum/portalnetwork/history"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
@ -37,7 +37,7 @@ type MockAPI struct {
header string header string
} }
func (p *MockAPI) HistoryGetContent(contentKeyHex string) (*discover.ContentInfo, error) { func (p *MockAPI) HistoryGetContent(contentKeyHex string) (*portalwire.ContentInfo, error) {
headerWithProof := &history.BlockHeaderWithProof{ headerWithProof := &history.BlockHeaderWithProof{
Header: hexutil.MustDecode(p.header), Header: hexutil.MustDecode(p.header),
Proof: &history.BlockHeaderProof{ Proof: &history.BlockHeaderProof{
@ -49,7 +49,7 @@ func (p *MockAPI) HistoryGetContent(contentKeyHex string) (*discover.ContentInfo
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &discover.ContentInfo{ return &portalwire.ContentInfo{
Content: hexutil.Encode(data), Content: hexutil.Encode(data),
UtpTransfer: false, UtpTransfer: false,
}, nil }, nil

View file

@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/portalnetwork/portalwire"
"github.com/ethereum/go-ethereum/portalnetwork/storage" "github.com/ethereum/go-ethereum/portalnetwork/storage"
"github.com/holiman/uint256" "github.com/holiman/uint256"
"github.com/protolambda/ztyp/codec" "github.com/protolambda/ztyp/codec"
@ -27,7 +28,7 @@ type StateStorage struct {
log log.Logger log log.Logger
} }
var portalStorageMetrics *metrics.PortalStorageMetrics var portalStorageMetrics *portalwire.PortalStorageMetrics
func NewStateStorage(store storage.ContentStorage, db *sql.DB) *StateStorage { func NewStateStorage(store storage.ContentStorage, db *sql.DB) *StateStorage {
storage := &StateStorage{ storage := &StateStorage{
@ -37,7 +38,7 @@ func NewStateStorage(store storage.ContentStorage, db *sql.DB) *StateStorage {
} }
var err error var err error
portalStorageMetrics, err = metrics.NewPortalStorageMetrics("state", db) portalStorageMetrics, err = portalwire.NewPortalStorageMetrics("state", db)
if err != nil { if err != nil {
return nil return nil
} }