go-waku/waku/node.go

156 lines
4.0 KiB
Go

package waku
import (
"context"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"net"
"os"
"os/signal"
"syscall"
"github.com/ethereum/go-ethereum/crypto"
dssql "github.com/ipfs/go-ds-sql"
logging "github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-peerstore/pstoreds"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/status-im/go-waku/waku/persistence"
"github.com/status-im/go-waku/waku/persistence/sqlite"
"github.com/status-im/go-waku/waku/v2/node"
)
var log = logging.Logger("wakunode")
func randomHex(n int) (string, error) {
bytes := make([]byte, n)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
func checkError(err error, msg string) {
if err != nil {
if msg != "" {
msg = msg + ": "
}
log.Fatal(msg, err)
}
}
var rootCmd = &cobra.Command{
Use: "waku",
Short: "Start a waku node",
Long: `Start a waku node...`,
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
port, _ := cmd.Flags().GetInt("port")
relay, _ := cmd.Flags().GetBool("relay")
key, _ := cmd.Flags().GetString("nodekey")
store, _ := cmd.Flags().GetBool("store")
dbPath, _ := cmd.Flags().GetString("dbpath")
storenode, _ := cmd.Flags().GetString("storenode")
staticnodes, _ := cmd.Flags().GetStringSlice("staticnodes")
hostAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprint("0.0.0.0:", port))
var err error
if key == "" {
key, err = randomHex(32)
checkError(err, "Could not generate random key")
}
prvKey, err := crypto.HexToECDSA(key)
if dbPath == "" {
checkError(errors.New("dbpath can't be null"), "")
}
db, err := sqlite.NewDB(dbPath)
checkError(err, "Could not connect to DB")
ctx := context.Background()
// Create persistent peerstore
queries, err := sqlite.NewQueries("peerstore", db)
checkError(err, "Peerstore")
datastore := dssql.NewDatastore(db, queries)
opts := pstoreds.DefaultOpts()
peerStore, err := pstoreds.NewPeerstore(ctx, datastore, opts)
checkError(err, "Peerstore")
wakuNode, err := node.New(ctx, prvKey, []net.Addr{hostAddr}, libp2p.Peerstore(peerStore))
checkError(err, "Wakunode")
if relay {
wakuNode.MountRelay()
}
if store {
dbStore, err := persistence.NewDBStore(persistence.WithDB(db))
checkError(err, "DBStore")
err = wakuNode.MountStore(dbStore)
checkError(err, "Error mounting store")
wakuNode.StartStore()
}
if storenode != "" && !store {
checkError(errors.New("Store protocol was not started"), "")
} else {
if storenode != "" {
wakuNode.AddStorePeer(storenode)
}
}
if len(staticnodes) > 0 {
for _, n := range staticnodes {
go wakuNode.DialPeer(n)
}
}
// Wait for a SIGINT or SIGTERM signal
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
<-ch
fmt.Println("\n\n\nReceived signal, shutting down...")
// shut the node down
wakuNode.Stop()
err = db.Close()
checkError(err, "DBClose")
},
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
cobra.CheckErr(rootCmd.Execute())
}
func init() {
cobra.OnInitialize(initConfig)
rootCmd.Flags().Int("port", 9000, "Libp2p TCP listening port (0 for random)")
rootCmd.Flags().String("nodekey", "", "P2P node private key as hex (default random)")
rootCmd.Flags().StringSlice("staticnodes", []string{}, "Multiaddr of peer to directly connect with. Argument may be repeated")
rootCmd.Flags().Bool("store", false, "Enable store protocol")
rootCmd.Flags().String("dbpath", "./store.db", "Path to DB file")
rootCmd.Flags().String("storenode", "", "Multiaddr of peer to connect with for waku store protocol")
rootCmd.Flags().Bool("relay", true, "Enable relay protocol")
}
func initConfig() {
viper.AutomaticEnv() // read in environment variables that match
}