You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
2.9 KiB
123 lines
2.9 KiB
6 years ago
|
// bootnode provides peer discovery service to new node to connect to the p2p network
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"flag"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"path"
|
||
|
|
||
|
"github.com/ethereum/go-ethereum/log"
|
||
|
"github.com/harmony-one/harmony/internal/utils"
|
||
|
libp2p "github.com/libp2p/go-libp2p"
|
||
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
||
|
ma "github.com/multiformats/go-multiaddr"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
version string
|
||
|
builtBy string
|
||
|
builtAt string
|
||
|
commit string
|
||
|
)
|
||
|
|
||
|
type privKey struct {
|
||
|
Key string `json:"key"`
|
||
|
}
|
||
|
|
||
|
func printVersion(me string) {
|
||
|
fmt.Fprintf(os.Stderr, "Harmony (C) 2019. %v, version %v-%v (%v %v)\n", path.Base(me), version, commit, builtBy, builtAt)
|
||
|
os.Exit(0)
|
||
|
}
|
||
|
|
||
|
func loggingInit(logFolder, ip, port string) {
|
||
|
// Setup a logger to stdout and log file.
|
||
|
if err := os.MkdirAll(logFolder, 0755); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
logFileName := fmt.Sprintf("./%v/bootnode-%v-%v.log", logFolder, ip, port)
|
||
|
h := log.MultiHandler(
|
||
|
log.StreamHandler(os.Stdout, log.TerminalFormat(false)),
|
||
|
log.Must.FileHandler(logFileName, log.JSONFormat()), // Log to file
|
||
|
)
|
||
|
log.Root().SetHandler(h)
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
ip := flag.String("ip", "127.0.0.1", "IP of the node")
|
||
|
port := flag.String("port", "9876", "port of the node.")
|
||
|
logFolder := flag.String("log_folder", "latest", "the folder collecting the logs of this execution")
|
||
|
keyFile := flag.String("key", "./.bnkey", "the private key file of the bootnode")
|
||
|
versionFlag := flag.Bool("version", false, "Output version info")
|
||
|
|
||
|
flag.Parse()
|
||
|
|
||
|
if *versionFlag {
|
||
|
printVersion(os.Args[0])
|
||
|
}
|
||
|
|
||
|
// Logging setup
|
||
|
utils.SetPortAndIP(*port, *ip)
|
||
|
|
||
|
// Init logging.
|
||
|
loggingInit(*logFolder, *ip, *port)
|
||
|
|
||
|
listen, err := ma.NewMultiaddr(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", *port))
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
opts := []libp2p.Option{
|
||
|
libp2p.ListenAddrs(listen),
|
||
|
}
|
||
|
privKey, err := loadKey(*keyFile)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
opts = append(opts, libp2p.Identity(privKey))
|
||
|
|
||
|
host, err := libp2p.New(context.Background(), opts...)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
log.Info("bootnode", "BN_MA", fmt.Sprintf("/ipv/%s/tcp/%s/p2p/%s", *ip, *port, host.ID().Pretty()))
|
||
|
}
|
||
|
|
||
|
// saveKey save private key to keyfile
|
||
|
func saveKey(keyfile string, key crypto.PrivKey) (err error) {
|
||
|
str, err := utils.SavePrivateKey(key)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
keyStruct := privKey{Key: str}
|
||
|
|
||
|
err = utils.Save(keyfile, &keyStruct)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// loadKey load private key from keyfile
|
||
|
func loadKey(keyfile string) (key crypto.PrivKey, err error) {
|
||
|
var keyStruct privKey
|
||
|
err = utils.Load(keyfile, &keyStruct)
|
||
|
if err != nil {
|
||
|
log.Warn("No priviate key can be loaded from file", "keyfile", keyfile)
|
||
|
log.Warn("Using random private key")
|
||
|
key, _, err = utils.GenKeyP2PRand()
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
err = saveKey(keyfile, key)
|
||
|
if err != nil {
|
||
|
log.Warn("bootnode", "failed to save key to keyfile", err)
|
||
|
}
|
||
|
return key, nil
|
||
|
}
|
||
|
key, err = utils.LoadPrivateKey(keyStruct.Key)
|
||
|
return key, err
|
||
|
}
|