Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unreachable peers #949

Merged
merged 7 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ RUN --mount=type=cache,target=/go go build -o /app/iota-core -tags="$BUILD_TAGS"
RUN cp ./config_defaults.json /app/config.json
RUN cp ./peering.json /app/peering.json

RUN mkdir -p /app/data/peerdb
RUN mkdir -p /app/data/p2p

############################
# Runtime Image
Expand Down
100 changes: 12 additions & 88 deletions components/p2p/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package p2p

import (
"context"
"path/filepath"

"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
Expand All @@ -16,9 +15,7 @@ import (
"github.com/iotaledger/hive.go/app"
"github.com/iotaledger/hive.go/app/configuration"
hivep2p "github.com/iotaledger/hive.go/crypto/p2p"
"github.com/iotaledger/hive.go/db"
"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/kvstore"
"github.com/iotaledger/iota-core/pkg/daemon"
"github.com/iotaledger/iota-core/pkg/network"
"github.com/iotaledger/iota-core/pkg/network/p2p"
Expand All @@ -27,13 +24,12 @@ import (

func init() {
Component = &app.Component{
Name: "P2P",
DepsFunc: func(cDeps dependencies) { deps = cDeps },
Params: params,
InitConfigParams: initConfigParams,
Provide: provide,
Configure: configure,
Run: run,
Name: "P2P",
DepsFunc: func(cDeps dependencies) { deps = cDeps },
Params: params,
Provide: provide,
Configure: configure,
Run: run,
}
}

Expand All @@ -47,52 +43,10 @@ type dependencies struct {
PeeringConfig *configuration.Configuration `name:"peeringConfig"`
PeeringConfigManager *p2p.ConfigManager
NetworkManager network.Manager
PeerDB *network.DB
Protocol *protocol.Protocol
PeerDBKVSTore kvstore.KVStore `name:"peerDBKVStore"`
}

func initConfigParams(c *dig.Container) error {
type cfgResult struct {
dig.Out
P2PDatabasePath string `name:"p2pDatabasePath"`
P2PBindMultiAddresses []string `name:"p2pBindMultiAddresses"`
}

if err := c.Provide(func() cfgResult {
return cfgResult{
P2PDatabasePath: ParamsP2P.Database.Path,
P2PBindMultiAddresses: ParamsP2P.BindMultiAddresses,
}
}); err != nil {
Component.LogPanic(err.Error())
}

return nil
}

func provide(c *dig.Container) error {
type peerDatabaseResult struct {
dig.Out

PeerDB *network.DB
PeerDBKVSTore kvstore.KVStore `name:"peerDBKVStore"`
}

if err := c.Provide(func() peerDatabaseResult {
peerDB, peerDBKVStore, err := initPeerDB()
if err != nil {
Component.LogFatal(err.Error())
}

return peerDatabaseResult{
PeerDB: peerDB,
PeerDBKVSTore: peerDBKVStore,
}
}); err != nil {
return err
}

type configManagerDeps struct {
dig.In
PeeringConfig *configuration.Configuration `name:"peeringConfig"`
Expand Down Expand Up @@ -164,38 +118,29 @@ func provide(c *dig.Container) error {
Component.LogPanic(err.Error())
}

type p2pDeps struct {
dig.In
DatabaseEngine db.Engine `name:"databaseEngine"`
P2PDatabasePath string `name:"p2pDatabasePath"`
P2PBindMultiAddresses []string `name:"p2pBindMultiAddresses"`
}

type p2pResult struct {
dig.Out
NodePrivateKey crypto.PrivKey `name:"nodePrivateKey"`
Host host.Host
}

if err := c.Provide(func(deps p2pDeps) p2pResult {
if err := c.Provide(func() p2pResult {
res := p2pResult{}

privKeyFilePath := filepath.Join(deps.P2PDatabasePath, IdentityPrivateKeyFileName)

// make sure nobody copies around the peer store since it contains the private key of the node
Component.LogInfof(`WARNING: never share your "%s" folder as it contains your node's private key!`, deps.P2PDatabasePath)
Component.LogInfof(`WARNING: never share the file "%s" as it contains your node's private key!`, ParamsP2P.IdentityPrivateKeyFilePath)

// load up the previously generated identity or create a new one
nodePrivateKey, newlyCreated, err := hivep2p.LoadOrCreateIdentityPrivateKey(privKeyFilePath, ParamsP2P.IdentityPrivateKey)
nodePrivateKey, newlyCreated, err := hivep2p.LoadOrCreateIdentityPrivateKey(ParamsP2P.IdentityPrivateKeyFilePath, ParamsP2P.IdentityPrivateKey)
if err != nil {
Component.LogPanic(err.Error())
}
res.NodePrivateKey = nodePrivateKey

if newlyCreated {
Component.LogInfof(`stored new private key for peer identity under "%s"`, privKeyFilePath)
Component.LogInfof(`stored new private key for peer identity under "%s"`, ParamsP2P.IdentityPrivateKeyFilePath)
} else {
Component.LogInfof(`loaded existing private key for peer identity from "%s"`, privKeyFilePath)
Component.LogInfof(`loaded existing private key for peer identity from "%s"`, ParamsP2P.IdentityPrivateKeyFilePath)
}

connManager, err := connmgr.NewConnManager(
Expand Down Expand Up @@ -238,7 +183,6 @@ func provide(c *dig.Container) error {
type p2pManagerDeps struct {
dig.In
Host host.Host
PeerDB *network.DB
P2PMetrics *p2p.Metrics
}

Expand All @@ -247,31 +191,11 @@ func provide(c *dig.Container) error {
inDeps.P2PMetrics.OutgoingBlocks.Add(1)
}

return p2p.NewManager(Component.Logger, inDeps.Host, inDeps.PeerDB, ParamsP2P.Autopeering.MaxPeers, ParamsP2P.Autopeering.AllowLocalIPs, onBlockSentCallback)
return p2p.NewManager(Component.Logger, inDeps.Host, ParamsP2P.Autopeering.MaxPeers, ParamsP2P.Autopeering.AllowLocalIPs, onBlockSentCallback)
})
}

func configure() error {
if err := Component.Daemon().BackgroundWorker("Close p2p peer database", func(ctx context.Context) {
<-ctx.Done()

closeDatabases := func() error {
if err := deps.PeerDBKVSTore.Flush(); err != nil {
return err
}

return deps.PeerDBKVSTore.Close()
}

Component.LogInfo("Syncing p2p peer database to disk ...")
if err := closeDatabases(); err != nil {
Component.LogPanicf("Syncing p2p peer database to disk ... failed: %s", err)
}
Component.LogInfo("Syncing p2p peer database to disk ... done")
}, daemon.PriorityCloseDatabase); err != nil {
Component.LogPanicf("failed to start worker: %s", err)
}

// log the p2p events
deps.NetworkManager.OnNeighborAdded(func(neighbor network.Neighbor) {
Component.LogInfof("neighbor added: %s / %s", neighbor.Peer().PeerAddresses, neighbor.Peer().ID)
Expand Down
11 changes: 4 additions & 7 deletions components/p2p/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (

const (
// CfgPeers defines the static peers this node should retain a connection to (CLI).
CfgPeers = "peers"
IdentityPrivateKeyFileName = "identity.key"
CfgPeers = "peers"
)

// ParametersP2P contains the definition of configuration parameters used by the p2p plugin.
Expand All @@ -25,6 +24,9 @@ type ParametersP2P struct {
// Defines the private key used to derive the node identity (optional).
IdentityPrivateKey string `default:"" usage:"private key used to derive the node identity (optional)"`

// Defines the file path to the private key used to derive the node identity.
IdentityPrivateKeyFilePath string `default:"testnet/p2p/identity.key" usage:"the file path to the private key used to derive the node identity"`

Autopeering struct {
// MaxPeers defines the max number of auto-peer connections. Set to 0 to disable auto-peering.
MaxPeers int `default:"5" usage:"the max number of auto-peer connections. Set to 0 to disable auto-peering."`
Expand All @@ -38,11 +40,6 @@ type ParametersP2P struct {
// ExternalMultiAddress defines additional p2p multiaddresses to be advertised via DHT.
ExternalMultiAddresses []string `default:"" usage:"external reacheable multi addresses advertised to the network"`
}

Database struct {
// Defines the path to the p2p database.
Path string `default:"testnet/p2pstore" usage:"the path to the p2p database"`
} `name:"db"`
}

// ParametersPeers contains the definition of the parameters used by peers.
Expand Down
37 changes: 0 additions & 37 deletions components/p2p/utils.go

This file was deleted.

4 changes: 1 addition & 3 deletions config_defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,12 @@
"lowWatermark": 5
},
"identityPrivateKey": "",
"identityPrivateKeyFilePath": "testnet/p2p/identity.key",
"autopeering": {
"maxPeers": 5,
"bootstrapPeers": [],
"allowLocalIPs": false,
"externalMultiAddresses": []
},
"db": {
"path": "testnet/p2pstore"
}
},
"profiling": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ services:
--p2p.peers=/dns/node-01.feature/tcp/15600/p2p/12D3KooWCrjmh4dUCWfGVQT6ivzArieJB9Z3eKdy2mdEEN95NDPS
--p2p.externalMultiAddresses={{ ips | join(',') }}
--p2p.identityPrivateKey={{p2pIdentityPrvKey}}
--p2p.db.path=/app/data/peerdb
--p2p.identityPrivateKeyFilePath=/app/data/p2p/identity.key",
--profiling.enabled=true
--profiling.bindAddress=0.0.0.0:6061
--restAPI.bindAddress=0.0.0.0:14265
Expand Down
24 changes: 8 additions & 16 deletions documentation/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ Example:

## <a id="p2p"></a> 3. Peer to Peer

| Name | Description | Type | Default value |
| ------------------------------------------- | ------------------------------------------------------- | ------ | -------------------------------------------- |
| bindMultiAddresses | The bind multi addresses for p2p connections | array | /ip4/0.0.0.0/tcp/15600<br/>/ip6/::/tcp/15600 |
| [connectionManager](#p2p_connectionmanager) | Configuration for connectionManager | object | |
| identityPrivateKey | Private key used to derive the node identity (optional) | string | "" |
| [autopeering](#p2p_autopeering) | Configuration for autopeering | object | |
| [db](#p2p_db) | Configuration for Database | object | |
| Name | Description | Type | Default value |
| ------------------------------------------- | ----------------------------------------------------------------- | ------ | -------------------------------------------- |
| bindMultiAddresses | The bind multi addresses for p2p connections | array | /ip4/0.0.0.0/tcp/15600<br/>/ip6/::/tcp/15600 |
| [connectionManager](#p2p_connectionmanager) | Configuration for connectionManager | object | |
| identityPrivateKey | Private key used to derive the node identity (optional) | string | "" |
| identityPrivateKeyFilePath | The file path to the private key used to derive the node identity | string | "testnet/p2p/identity.key" |
| [autopeering](#p2p_autopeering) | Configuration for autopeering | object | |

### <a id="p2p_connectionmanager"></a> ConnectionManager

Expand All @@ -117,12 +117,6 @@ Example:
| allowLocalIPs | Allow local IPs to be used for autopeering | boolean | false |
| externalMultiAddresses | External reacheable multi addresses advertised to the network | array | |

### <a id="p2p_db"></a> Database

| Name | Description | Type | Default value |
| ---- | ---------------------------- | ------ | ------------------ |
| path | The path to the p2p database | string | "testnet/p2pstore" |

Example:

```json
Expand All @@ -137,14 +131,12 @@ Example:
"lowWatermark": 5
},
"identityPrivateKey": "",
"identityPrivateKeyFilePath": "testnet/p2p/identity.key",
"autopeering": {
"maxPeers": 5,
"bootstrapPeers": [],
"allowLocalIPs": false,
"externalMultiAddresses": []
},
"db": {
"path": "testnet/p2pstore"
}
}
}
Expand Down
24 changes: 4 additions & 20 deletions pkg/network/p2p/autopeering/autopeering.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ type Manager struct {
networkManager network.Manager
logger log.Logger
host host.Host
peerDB *network.DB
startOnce sync.Once
isStarted atomic.Bool
stopOnce sync.Once
Expand All @@ -42,12 +41,11 @@ type Manager struct {
}

// NewManager creates a new autopeering manager.
func NewManager(maxPeers int, networkManager network.Manager, host host.Host, peerDB *network.DB, addressFilter network.AddressFilter, logger log.Logger) *Manager {
func NewManager(maxPeers int, networkManager network.Manager, host host.Host, addressFilter network.AddressFilter, logger log.Logger) *Manager {
return &Manager{
maxPeers: maxPeers,
networkManager: networkManager,
host: host,
peerDB: peerDB,
logger: logger.NewChildLogger("Autopeering"),
addrFilter: addressFilter,
}
Expand Down Expand Up @@ -75,6 +73,7 @@ func (m *Manager) Start(ctx context.Context, networkID string, bootstrapPeers []
dht.ProtocolExtension(extension),
dht.AddressFilter(m.addrFilter),
dht.BootstrapPeers(bootstrapPeers...),
dht.MaxRecordAge(10*time.Minute),
)
if innerErr != nil {
err = innerErr
Expand All @@ -94,21 +93,6 @@ func (m *Manager) Start(ctx context.Context, networkID string, bootstrapPeers []

m.ctx = dhtCtx

for _, seedPeer := range m.peerDB.SeedPeers() {
addrInfo := seedPeer.ToAddrInfo()
if innerErr := m.host.Connect(ctx, *addrInfo); innerErr != nil {
m.logger.LogInfof("Failed to connect to bootstrap node, peer: %s, error: %s", seedPeer, innerErr)
continue
}

if _, innerErr := kademliaDHT.RoutingTable().TryAddPeer(addrInfo.ID, true, true); innerErr != nil {
m.logger.LogWarnf("Failed to add bootstrap node to routing table, error: %s", innerErr)
continue
}

m.logger.LogDebugf("Connected to bootstrap node, peer: %s", seedPeer)
}

m.routingDiscovery = routing.NewRoutingDiscovery(kademliaDHT)
m.startAdvertisingIfNeeded()
go m.discoveryLoop()
Expand All @@ -118,7 +102,7 @@ func (m *Manager) Start(ctx context.Context, networkID string, bootstrapPeers []
})
onGossipNeighborAddedHook := m.networkManager.OnNeighborAdded(func(neighbor network.Neighbor) {
m.logger.LogInfof("Gossip layer successfully connected with the peer %s", neighbor.Peer())
m.stopAdvertisingItNotNeeded()
m.stopAdvertisingIfNotNeeded()
})

m.stopFunc = func() {
Expand Down Expand Up @@ -162,7 +146,7 @@ func (m *Manager) startAdvertisingIfNeeded() {
}
}

func (m *Manager) stopAdvertisingItNotNeeded() {
func (m *Manager) stopAdvertisingIfNotNeeded() {
if len(m.networkManager.AutopeeringNeighbors()) >= m.maxPeers {
m.stopAdvertising()
}
Expand Down
Loading
Loading