Skip to content

Commit

Permalink
Merge pull request #6361 from multiversx/light-client-network
Browse files Browse the repository at this point in the history
New p2p network messenger for the light clients and suppliers.
  • Loading branch information
AdoAdoAdo authored Sep 3, 2024
2 parents a369185 + 4c4aae8 commit e3ebbf0
Show file tree
Hide file tree
Showing 19 changed files with 381 additions and 43 deletions.
3 changes: 3 additions & 0 deletions cmd/node/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ GLOBAL OPTIONS:
--config-external [path] The [path] for the external configuration file. This TOML file contains external configurations such as ElasticSearch's URL and login information (default: "./config/external.toml")
--p2p-config [path] The [path] for the p2p configuration file. This TOML file contains peer-to-peer configurations such as port, target peer count or KadDHT settings (default: "./config/p2p.toml")
--full-archive-p2p-config [path] The [path] for the p2p configuration file for the full archive network. This TOML file contains peer-to-peer configurations such as port, target peer count or KadDHT settings (default: "./config/fullArchiveP2P.toml")
--light-client-p2p-config [path] The [path] for the p2p configuration file for the light client network. This TOML file contains peer-to-peer configurations such as port, target peer count or KadDHT settings (default: "./config/lightClientP2P.toml")
--epoch-config [path] The [path] for the epoch configuration file. This TOML file contains activation epochs configurations (default: "./config/enableEpochs.toml")
--round-config [path] The [path] for the round configuration file. This TOML file contains activation round configurations (default: "./config/enableRounds.toml")
--gas-costs-config [path] The [path] for the gas costs configuration directory. (default: "./config/gasSchedules")
Expand Down Expand Up @@ -60,6 +61,8 @@ GLOBAL OPTIONS:
--import-db-save-epoch-root-hash This flag, if set, will export the trie snapshots at every new epoch
--redundancy-level value This flag specifies the level of redundancy used by the current instance for the node (-1 = disabled, 0 = main instance (default), 1 = first backup, 2 = second backup, etc.) (default: 0)
--full-archive Boolean option for settings an observer as full archive, which will sync the entire database of its shard
--light-client Boolean option for setting an observer as light client
--light-client-supplier Boolean option for setting an observer as light client supplier
--mem-ballast value Flag that specifies the number of MegaBytes to be used as a memory ballast for Garbage Collector optimization. If set to 0 (or not set at all), the feature will be disabled. This flag should be used only for well-monitored nodes and by advanced users, as a too high memory ballast could lead to Out Of Memory panics. The memory ballast should not be higher than 20-25% of the machine's available RAM (default: 0)
--memory-usage-to-create-profiles value Integer value to be used to set the memory usage thresholds (in bytes) (default: 2415919104)
--force-start-from-network Flag that will force the start from network bootstrap process
Expand Down
89 changes: 89 additions & 0 deletions cmd/node/config/lightClientP2P.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# LightClientP2P config file

# NodeConfig holds the P2P settings
[Node]
# Port is the port that will be opened by the node on all interfaces so other peers can connect to it
# If the port = 0, the node will search for a free port on the machine and use it
Port = "37373-38383"

# ThresholdMinConnectedPeers represents the minimum number of connections a node should have before it can start
# the sync and consensus mechanisms
ThresholdMinConnectedPeers = 3

# MinNumPeersToWaitForOnBootstrap is the minimum number of peers to wait on bootstrap or the node will wait the default
# time which is now set to ~20 seconds (the const defined in the common package named TimeToWaitForP2PBootstrap)
MinNumPeersToWaitForOnBootstrap = 10

# available transports. All defined addresses contains a single '%d' markup that is mandatory and will
# be replaced at runtime with the actual port value
[Node.Transports]
QUICAddress = "" # optional QUIC address. If this transport should be activated, should be in this format: /ip4/0.0.0.0/udp/%d/quic-v1
WebSocketAddress = "" # optional WebSocket address. If this transport should be activated, should be in this format: /ip4/0.0.0.0/tcp/%d/ws
WebTransportAddress = "" # optional WebTransport address. If this transport should be activated, should be in this format: /ip4/0.0.0.0/udp/%d/quic-v1/webtransport
[Node.Transports.TCP]
ListenAddress = "/ip4/0.0.0.0/tcp/%d" # TCP listen address
PreventPortReuse = false

[Node.ResourceLimiter]
Type = "default autoscale" #available options "default autoscale", "infinite", "default with manual scale".
ManualSystemMemoryInMB = 0 # not taken into account if the type is not "default with manual scale"
ManualMaximumFD = 0 # not taken into account if the type is not "default with manual scale"

# P2P peer discovery section

# The following sections correspond to the way new peers will be discovered
# If all config types are disabled then the peer will run in single mode (will not try to find other peers)
# If more than one peer discovery mechanism is enabled, the application will output an error and will not start

[KadDhtPeerDiscovery]
# Enabled: true/false to enable/disable this discovery mechanism
Enabled = true

# Type represents the kad-dht glue code implementation.
# "legacy" will define the first implementation.
# "optimized" represents the new variant able to connect to multiple seeders at once. This implementation also has
# a built-in timer that will try to automatically reconnect to the seeders (in case the seeders recover after a
# premature shutdown)
Type = "optimized"

# RefreshIntervalInSec represents the time in seconds between querying for new peers
RefreshIntervalInSec = 10

# ProtocolIDs represents the protocols that this node will advertise to other peers
# To connect to other nodes, those nodes should have at least one common protocol string
ProtocolIDs = [
"/mvx/light/1.0.0",
]

# InitialPeerList represents the list of strings of some known nodes that will bootstrap this node
# The address will be in a self-describing addressing format.
# More can be found here: https://github.com/libp2p/specs/blob/master/3-requirements.md#34-transport-agnostic
# Example:
# /ip6/fe80::8823:6dff:fee7:f172/tcp/4001/p2p/QmYJyUMAcXEw1b5bFfbBbzYu5wyyjLMRHXGUkCXpag74Fu
# /ip4/162.246.145.218/udp/4001/utp/ipfs/QmYJyUMAcXEw1b5bFfbBbzYu5wyyjLMRHXGUkCXpag74Fu
#
# If the initial peers list is left empty, the node will not try to connect to other peers during initial bootstrap
# phase but will accept connections and will do the network discovery if another peer connects to it
InitialPeerList = ["/ip4/127.0.0.1/tcp/9999/p2p/16Uiu2HAkw5SNNtSvH1zJiQ6Gc3WoGNSxiyNueRKe6fuAuh57G3Bk"]

# kademlia's routing table bucket size
BucketSize = 100

# RoutingTableRefreshIntervalInSec defines how many seconds should pass between 2 kad routing table auto refresh calls
RoutingTableRefreshIntervalInSec = 300

[Sharding]
# The targeted number of peer connections
TargetPeerCount = 41
MaxIntraShardValidators = 7
MaxCrossShardValidators = 15
MaxIntraShardObservers = 7
MaxCrossShardObservers = 3
MaxSeeders = 2

# available options:
# `ListsSharder` will split the peers based on the shard membership (intra, cross or unknown)
# `OneListSharder` will do just the connection triming (upto TargetPeerCount value) not taking into account
# the shard membership of the connected peers
# `NilListSharder` will disable conection trimming (sharder is off)
Type = "ListsSharder"
8 changes: 8 additions & 0 deletions cmd/node/config/prefs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
# It is highly recommended to enable this flag on an observer (not on a validator node)
FullArchive = false

# LightClient, if enabled, will make the node able to connect on the light client network.
# It is highly recommended to enable this flag on an observer (not on a validator node)
LightClient = false

# LightClientSupplier, if enabled, will make the node able to connect on the light client network as a supplier.
# It is highly recommended to enable this flag on an observer (not on a validator node)
LightClientSupplier = false

# PreferredConnections holds an array containing valid ips or peer ids from nodes to connect with (in top of other connections)
# Example:
# PreferredConnections = [
Expand Down
37 changes: 35 additions & 2 deletions cmd/node/flags.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package main

import (
"errors"
"fmt"
"math"
"os"
"runtime"

logger "github.com/multiversx/mx-chain-logger-go"
"github.com/urfave/cli"

"github.com/multiversx/mx-chain-go/common"
"github.com/multiversx/mx-chain-go/common/operationmodes"
"github.com/multiversx/mx-chain-go/config"
"github.com/multiversx/mx-chain-go/facade"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/urfave/cli"
)

var (
Expand Down Expand Up @@ -98,6 +100,12 @@ var (
"configurations such as port, target peer count or KadDHT settings",
Value: "./config/fullArchiveP2P.toml",
}
lightClientP2PConfigurationFile = cli.StringFlag{
Name: "light-client-p2p-config",
Usage: "The `" + filePathPlaceholder + "` for the p2p configuration file for the light client network. This TOML file contains peer-to-peer " +
"configurations such as port, target peer count or KadDHT settings",
Value: "./config/lightClientP2P.toml",
}
// epochConfigurationFile defines a flag for the path to the toml file containing the epoch configuration
epochConfigurationFile = cli.StringFlag{
Name: "epoch-config",
Expand Down Expand Up @@ -342,6 +350,16 @@ var (
Name: "full-archive",
Usage: "Boolean option for settings an observer as full archive, which will sync the entire database of its shard",
}
// lightClient defines a flag that, if set, will make the node act like a light client
lightClient = cli.BoolFlag{
Name: "light-client",
Usage: "Boolean option for setting an observer as light client",
}
// lightClientSupplier defines a flag that, if set, will make the node act like a light client supplier
lightClientSupplier = cli.BoolFlag{
Name: "light-client-supplier",
Usage: "Boolean option for setting an observer as light client supplier",
}
// memBallast defines a flag that specifies the number of MegaBytes to be used as a memory ballast for Garbage Collector optimization
// if set to 0, the memory ballast won't be used
memBallast = cli.Uint64Flag{
Expand Down Expand Up @@ -424,6 +442,7 @@ func getFlags() []cli.Flag {
externalConfigFile,
p2pConfigurationFile,
fullArchiveP2PConfigurationFile,
lightClientP2PConfigurationFile,
epochConfigurationFile,
roundConfigurationFile,
gasScheduleConfigurationDirectory,
Expand Down Expand Up @@ -457,6 +476,8 @@ func getFlags() []cli.Flag {
importDbSaveEpochRootHash,
redundancyLevel,
fullArchive,
lightClient,
lightClientSupplier,
memBallast,
memoryUsageToCreateProfiles,
forceStartFromNetwork,
Expand Down Expand Up @@ -535,6 +556,12 @@ func applyFlags(ctx *cli.Context, cfgs *config.Configs, flagsConfig *config.Cont
if ctx.IsSet(fullArchive.Name) {
cfgs.PreferencesConfig.Preferences.FullArchive = ctx.GlobalBool(fullArchive.Name)
}
if ctx.IsSet(lightClient.Name) {
cfgs.PreferencesConfig.Preferences.LightClient = ctx.GlobalBool(lightClient.Name)
}
if ctx.IsSet(lightClientSupplier.Name) {
cfgs.PreferencesConfig.Preferences.LightClientSupplier = ctx.GlobalBool(lightClientSupplier.Name)
}
if ctx.IsSet(memoryUsageToCreateProfiles.Name) {
cfgs.GeneralConfig.Health.MemoryUsageToCreateProfiles = int(ctx.GlobalUint64(memoryUsageToCreateProfiles.Name))
log.Info("setting a new value for the memoryUsageToCreateProfiles option",
Expand Down Expand Up @@ -647,6 +674,12 @@ func applyCompatibleConfigs(log logger.Logger, configs *config.Configs) error {
processSnapshotLessObserverMode(log, configs)
}

isBothLightClientConsumerAndSupplier := configs.PreferencesConfig.Preferences.LightClientSupplier &&
configs.PreferencesConfig.Preferences.LightClient
if isBothLightClientConsumerAndSupplier {
return errors.New("cannot have node running in both light client consumer and supplier mode")
}

return nil
}

Expand Down
15 changes: 12 additions & 3 deletions cmd/node/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import (
"github.com/klauspost/cpuid/v2"
"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-core-go/core/check"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/multiversx/mx-chain-logger-go/file"
"github.com/urfave/cli"

"github.com/multiversx/mx-chain-go/cmd/node/factory"
"github.com/multiversx/mx-chain-go/common"
"github.com/multiversx/mx-chain-go/config"
"github.com/multiversx/mx-chain-go/config/overridableConfig"
"github.com/multiversx/mx-chain-go/node"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/multiversx/mx-chain-logger-go/file"
"github.com/urfave/cli"
// test point 1 for custom profiler
)

Expand Down Expand Up @@ -224,6 +225,13 @@ func readConfigs(ctx *cli.Context, log logger.Logger) (*config.Configs, error) {
}
log.Debug("config", "file", configurationPaths.FullArchiveP2p)

configurationPaths.LightClientP2p = ctx.GlobalString(lightClientP2PConfigurationFile.Name)
lightClientP2PConfig, err := common.LoadP2PConfig(configurationPaths.LightClientP2p)
if err != nil {
return nil, err
}
log.Debug("config", "file", configurationPaths.LightClientP2p)

configurationPaths.Epoch = ctx.GlobalString(epochConfigurationFile.Name)
epochConfig, err := common.LoadEpochConfig(configurationPaths.Epoch)
if err != nil {
Expand Down Expand Up @@ -264,6 +272,7 @@ func readConfigs(ctx *cli.Context, log logger.Logger) (*config.Configs, error) {
ExternalConfig: externalConfig,
MainP2pConfig: mainP2PConfig,
FullArchiveP2pConfig: fullArchiveP2PConfig,
LightClientP2pConfig: lightClientP2PConfig,
ConfigurationPathsHolder: configurationPaths,
EpochConfig: epochConfig,
RoundConfig: roundConfig,
Expand Down
6 changes: 6 additions & 0 deletions common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ const NormalOperation NodeOperation = "normal operation"
// FullArchiveMode defines the node operation as a full archive mode
const FullArchiveMode NodeOperation = "full archive mode"

// LightClientMode defines the node operation as a light client
const LightClientMode NodeOperation = "light client mode"

// LightClientSupplierMode defines the node operation light client supplier
const LightClientSupplierMode NodeOperation = "light client supplier mode"

// PeerType represents the type of peer
type PeerType string

Expand Down
13 changes: 13 additions & 0 deletions common/generics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package common

// Contains returns true if the specified value is contained in a slice.
func Contains[T comparable](s []T, e ...T) bool {
for _, v := range s {
for _, v2 := range e {
if v == v2 {
return true
}
}
}
return false
}
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ type Configs struct {
ExternalConfig *ExternalConfig
MainP2pConfig *p2pConfig.P2PConfig
FullArchiveP2pConfig *p2pConfig.P2PConfig
LightClientP2pConfig *p2pConfig.P2PConfig
FlagsConfig *ContextFlagsConfig
ImportDbConfig *ImportDbConfig
ConfigurationPathsHolder *ConfigurationPathsHolder
Expand All @@ -606,6 +607,7 @@ type ConfigurationPathsHolder struct {
External string
MainP2p string
FullArchiveP2p string
LightClientP2p string
GasScheduleDirectoryName string
Nodes string
Genesis string
Expand Down
2 changes: 2 additions & 0 deletions config/prefsConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ type PreferencesConfig struct {
ConnectionWatcherType string
OverridableConfigTomlValues []OverridableConfig
FullArchive bool
LightClient bool
LightClientSupplier bool
}

// OverridableConfig holds the path and the new value to be updated in the configuration
Expand Down
10 changes: 8 additions & 2 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,14 @@ var ErrNilBLSPublicKey = errors.New("bls public key is nil")
// ErrEmptyAddress defines the error when trying to work with an empty address
var ErrEmptyAddress = errors.New("empty Address")

// ErrInvalidNodeOperationMode signals that an invalid node operation mode has been provided
var ErrInvalidNodeOperationMode = errors.New("invalid node operation mode")
// ErrInvalidOperationMode signals that the operation mode is invalid
var ErrInvalidOperationMode = errors.New("invalid operation mode")

// ErrInvalidMainNodeOperationMode signals that an invalid node operation mode has been provided
var ErrInvalidMainNodeOperationMode = errors.New("node operation modes does not contain Normal or FullArchive")

// ErrInvalidNodeOperationModeCombo signals that an invalid node operation mode combination has been provided
var ErrInvalidNodeOperationModeCombo = errors.New("invalid node operation mode combo")

// ErrNilSentSignatureTracker defines the error for setting a nil SentSignatureTracker
var ErrNilSentSignatureTracker = errors.New("nil sent signature tracker")
Expand Down
Loading

0 comments on commit e3ebbf0

Please sign in to comment.