github.com/status-im/status-go@v1.1.0/cmd/bootnode/main.go (about)

     1  // bootnode runs a bootstrap node for the Ethereum Discovery Protocol.
     2  package main
     3  
     4  import (
     5  	"crypto/ecdsa"
     6  	"encoding/hex"
     7  	"flag"
     8  	"fmt"
     9  	"net"
    10  	"os"
    11  
    12  	"github.com/ethereum/go-ethereum/crypto"
    13  	"github.com/ethereum/go-ethereum/log"
    14  	"github.com/ethereum/go-ethereum/p2p/discv5"
    15  )
    16  
    17  var (
    18  	writeAddr   = flag.Bool("writeaddress", false, "write out the node's public key and quit")
    19  	listenAddr  = flag.String("addr", ":30301", "listen address")
    20  	genKeyFile  = flag.String("genkey", "", "generate a node key")
    21  	nodeKeyFile = flag.String("nodekey", "", "private key filename")
    22  	keydata     = flag.String("keydata", "", "hex encoded private key")
    23  	verbosity   = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-9)")
    24  	vmodule     = flag.String("vmodule", "", "log verbosity pattern")
    25  	nursery     = bootnodes{}
    26  	nodeKey     *ecdsa.PrivateKey
    27  	err         error
    28  )
    29  
    30  type bootnodes []*discv5.Node
    31  
    32  func (f *bootnodes) String() string {
    33  	return "discv5 nodes"
    34  }
    35  
    36  // Set unmarshals enode into discv5.Node.
    37  func (f *bootnodes) Set(value string) error {
    38  	n, err := discv5.ParseNode(value)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	*f = append(*f, n)
    43  	return nil
    44  }
    45  
    46  func main() {
    47  	flag.Var(&nursery, "n", "These nodes are used to connect to the network if the table is empty and there are no known nodes in the database.")
    48  	flag.Parse()
    49  
    50  	glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
    51  	glogger.Verbosity(log.Lvl(*verbosity))
    52  	if err = glogger.Vmodule(*vmodule); err != nil {
    53  		log.Crit("Failed to set glog verbosity", "value", *vmodule, "err", err)
    54  	}
    55  	log.Root().SetHandler(glogger)
    56  
    57  	if len(*genKeyFile) != 0 {
    58  		log.Info("Generating key file", "path", *genKeyFile)
    59  		key, err := crypto.GenerateKey()
    60  		if err != nil {
    61  			log.Crit("unable to generate key", "error", err)
    62  		}
    63  		if err := crypto.SaveECDSA(*genKeyFile, key); err != nil {
    64  			log.Crit("unable to save key", "error", err)
    65  		}
    66  		os.Exit(0)
    67  	}
    68  	if len(*nodeKeyFile) == 0 && len(*keydata) == 0 {
    69  		log.Crit("either `nodekey` or `keydata` must be provided")
    70  	}
    71  	if len(*nodeKeyFile) != 0 {
    72  		nodeKey, err = crypto.LoadECDSA(*nodeKeyFile)
    73  		if err != nil {
    74  			log.Crit("Failed to load ecdsa key from", "file", *nodeKeyFile, "error", err)
    75  		}
    76  	} else if len(*keydata) != 0 {
    77  		log.Warn("key will be visible in process list. should be used only for tests")
    78  		key, err := hex.DecodeString(*keydata)
    79  		if err != nil {
    80  			log.Crit("unable to decode hex", "data", keydata, "error", err)
    81  		}
    82  		nodeKey, err = crypto.ToECDSA(key)
    83  		if err != nil {
    84  			log.Crit("unable to convert decoded hex into ecdsa.PrivateKey", "data", key, "error", err)
    85  		}
    86  	}
    87  	if *writeAddr {
    88  		// we remove the first uncompressed byte since it's not used in an enode address
    89  		fmt.Printf("%x\n", crypto.FromECDSAPub(&nodeKey.PublicKey)[1:])
    90  		os.Exit(0)
    91  	}
    92  
    93  	addr, err := net.ResolveUDPAddr("udp", *listenAddr)
    94  	if err != nil {
    95  		log.Crit("Unable to resolve UDP", "address", *listenAddr, "error", err)
    96  	}
    97  	conn, err := net.ListenUDP("udp", addr)
    98  	if err != nil {
    99  		log.Crit("Unable to listen on udp", "address", addr, "error", err)
   100  	}
   101  
   102  	tab, err := discv5.ListenUDP(nodeKey, conn, "", nil)
   103  	if err != nil {
   104  		log.Crit("Failed to create discovery v5 table:", "error", err)
   105  	}
   106  	defer tab.Close()
   107  	if err := tab.SetFallbackNodes(nursery); err != nil {
   108  		log.Crit("Failed to set fallback", "nodes", nursery, "error", err)
   109  	}
   110  
   111  	select {}
   112  }