Skip to content

Commit

Permalink
Merge pull request #949 from iotaledger/fix/unreachable-peers
Browse files Browse the repository at this point in the history
Fix unreachable peers
  • Loading branch information
muXxer authored Apr 30, 2024
2 parents 719f890 + 756e3f7 commit c83d415
Show file tree
Hide file tree
Showing 17 changed files with 72 additions and 534 deletions.
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

0 comments on commit c83d415

Please sign in to comment.