From 4e5ac3c716515f82d306587ee5ff13f7268ca6f6 Mon Sep 17 00:00:00 2001 From: Alejo Acosta Date: Tue, 17 Oct 2023 00:13:11 -0300 Subject: [PATCH] add support for node info persistence on file --- .gitignore | 3 ++- p2p/node/api.go | 3 ++- p2p/node/cid.go | 38 ++++++++++++++++++++++++++++++++++++++ p2p/node/node.go | 25 +++++++++++++++++++------ 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index a5013fb8c8..afafe5f6e5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ # git config --global core.excludesfile ~/.gitignore_global *.key -nodelogs \ No newline at end of file +nodelogs +node.info \ No newline at end of file diff --git a/p2p/node/api.go b/p2p/node/api.go index e1e5ee5795..778acfd52d 100644 --- a/p2p/node/api.go +++ b/p2p/node/api.go @@ -104,8 +104,9 @@ func (p *P2PNode) ListenForEvents() { case evt := <-subAddrUpdated.Out(): if e, ok := evt.(event.EvtLocalAddressesUpdated); ok { for _, addr := range e.Current { - fullAddr := fmt.Sprintf("%+v/p2p/%s", addr, p.ID().Pretty()) + fullAddr := fmt.Sprintf("%+v/p2p/%s", addr.Address.String(), p.ID().Pretty()) log.Debugf("Advertised Address changed: %s", fullAddr) + saveNodeInfo("Advertised address: " + fullAddr) } } case evt := <-subPeerConnected.Out(): diff --git a/p2p/node/cid.go b/p2p/node/cid.go index 0915041745..38940e4228 100644 --- a/p2p/node/cid.go +++ b/p2p/node/cid.go @@ -1,6 +1,7 @@ package node import ( + "bufio" "crypto/rand" "os" @@ -9,6 +10,11 @@ import ( "github.com/libp2p/go-libp2p/core/crypto" ) +const ( + // file to store node's CID and listening address + nodeInfoFile = "node.info" +) + // Returns the private key stored in the file to be used to generate // the node's identity (CID) func getPrivKey(privKeyFile string) (crypto.PrivKey, error) { @@ -52,3 +58,35 @@ func getPrivKey(privKeyFile string) (crypto.PrivKey, error) { return privateKey, nil } + +// Utility function that synchronously writes the provided "info" string to the node.info file. +// If the file doesn't exist, it creates it. Otherwise, it appends the new "info" as a new line. +func saveNodeInfo(info string) { + go func() { + // Open file with O_APPEND flag to append data to the file or create the file if it doesn't exist. + f, err := os.OpenFile(nodeInfoFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Errorf("error opening node info file: %s", err) + return + } + defer f.Close() + + // Use bufio for efficient writing + writer := bufio.NewWriter(f) + defer writer.Flush() + + // Append new line and write to file + writer.WriteString(info + "\n") + }() +} + +// utility function used to delete any existing node info file +func deleteNodeInfoFile() error { + if _, err := os.Stat(nodeInfoFile); !os.IsNotExist(err) { + err := os.Remove(nodeInfoFile) + if err != nil { + return err + } + } + return nil +} diff --git a/p2p/node/node.go b/p2p/node/node.go index 90d9f098bd..a41c9da039 100644 --- a/p2p/node/node.go +++ b/p2p/node/node.go @@ -10,7 +10,6 @@ import ( routedhost "github.com/libp2p/go-libp2p/p2p/host/routed" "github.com/libp2p/go-libp2p" - dht "github.com/libp2p/go-libp2p-kad-dht" kadht "github.com/libp2p/go-libp2p-kad-dht" "github.com/libp2p/go-libp2p/core/host" @@ -51,12 +50,11 @@ func NewNode(ctx context.Context) (*P2PNode, error) { // list of options to instantiate the libp2p node nodeOptions := []libp2p.Option{} - + // use a private key for persistent identity nodeOptions = append(nodeOptions, libp2p.Identity(privateKey)) - + // pass the ip address and port to listen on sourceMultiAddr, _ := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%s", ipAddr, port)) nodeOptions = append(nodeOptions, libp2p.ListenAddrs(sourceMultiAddr)) - // check if there is a host IP we can use to replace Docker's internal IP hostIP, err := readHostIPFromFile(hostIPFile) if err != nil || hostIP == "" { @@ -87,7 +85,7 @@ func NewNode(ctx context.Context) (*P2PNode, error) { return nil, err } - // wrap the node with the routed host + // wrap the node with the routed host to improve network performance rnode := routedhost.Wrap(node, p2pNode.dht) p2pNode.Host = rnode log.Debugf("Routed node created") @@ -101,11 +99,26 @@ func NewNode(ctx context.Context) (*P2PNode, error) { return nil, err } + err = deleteNodeInfoFile() + if err != nil { + log.Errorf("error deleting node info file: %s", err) + return nil, err + } + + // log the p2p node's ID + log.Infof("node created: %s", p2pNode.ID().Pretty()) + saveNodeInfo("Node ID: " + p2pNode.ID().Pretty()) + + // log the p2p node's listening addresses + for _, addr := range p2pNode.Addrs() { + log.Infof("listening on: %s", addr.String()) + } + return p2pNode, nil } // Initializes the DHT for the libp2p node in server mode. -func (p *P2PNode) initializeDHT(opts ...dht.Option) error { +func (p *P2PNode) initializeDHT(opts ...kadht.Option) error { serverModeOpt := kadht.Mode(kadht.ModeServer) opts = append(opts, serverModeOpt) p.dht = &discovery.KadDHT{}