mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
feat:migrate and remove portal wire in p2p package
Signed-off-by: Chen Kai <281165273grape@gmail.com>
This commit is contained in:
parent
bce048fb1a
commit
ee11806dd7
38 changed files with 852 additions and 5307 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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))
|
|
||||||
}
|
|
||||||
|
|
@ -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("")
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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{
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
443
portalnetwork/history/new_storage.go
Normal file
443
portalnetwork/history/new_storage.go
Normal 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
|
||||||
|
//}
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
@ -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))
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package discover
|
package portalwire
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
@ -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"
|
||||||
|
|
@ -143,7 +142,6 @@ 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],
|
||||||
217
portalnetwork/portalwire/portal_protocol_metrics.go
Normal file
217
portalnetwork/portalwire/portal_protocol_metrics.go
Normal 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
|
||||||
|
}
|
||||||
|
|
@ -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"),
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue