github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/cmd/bootnode/main.go (about) 1 // bootnode runs a bootstrap node for the Quickchain Discovery Protocol. 2 package main 3 4 import ( 5 "crypto/ecdsa" 6 "flag" 7 "fmt" 8 "net" 9 "os" 10 11 "github.com/quickchainproject/quickchain/cmd/utils" 12 "github.com/quickchainproject/quickchain/crypto" 13 "github.com/quickchainproject/quickchain/log" 14 "github.com/quickchainproject/quickchain/p2p/discover" 15 "github.com/quickchainproject/quickchain/p2p/discv5" 16 "github.com/quickchainproject/quickchain/p2p/nat" 17 "github.com/quickchainproject/quickchain/p2p/netutil" 18 ) 19 20 func main() { 21 var ( 22 //listenAddr = flag.String("addr", ":30301", "listen address") 23 listenAddr = flag.String("addr", ":36661", "listen address") 24 genKey = flag.String("genkey", "", "generate a node key") 25 writeAddr = flag.Bool("writeaddress", false, "write out the node's pubkey hash and quit") 26 nodeKeyFile = flag.String("nodekey", "", "private key filename") 27 nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)") 28 natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)") 29 netrestrict = flag.String("netrestrict", "", "restrict network communication to the given IP networks (CIDR masks)") 30 runv5 = flag.Bool("v5", false, "run a v5 topic discovery bootnode") 31 verbosity = flag.Int("verbosity", int(log.LvlInfo), "log verbosity (0-9)") 32 vmodule = flag.String("vmodule", "", "log verbosity pattern") 33 34 nodeKey *ecdsa.PrivateKey 35 err error 36 ) 37 flag.Parse() 38 39 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 40 glogger.Verbosity(log.Lvl(*verbosity)) 41 glogger.Vmodule(*vmodule) 42 log.Root().SetHandler(glogger) 43 44 natm, err := nat.Parse(*natdesc) 45 if err != nil { 46 utils.Fatalf("-nat: %v", err) 47 } 48 switch { 49 case *genKey != "": 50 nodeKey, err = crypto.GenerateKey() 51 if err != nil { 52 utils.Fatalf("could not generate key: %v", err) 53 } 54 if err = crypto.SaveECDSA(*genKey, nodeKey); err != nil { 55 utils.Fatalf("%v", err) 56 } 57 return 58 case *nodeKeyFile == "" && *nodeKeyHex == "": 59 utils.Fatalf("Use -nodekey or -nodekeyhex to specify a private key") 60 case *nodeKeyFile != "" && *nodeKeyHex != "": 61 utils.Fatalf("Options -nodekey and -nodekeyhex are mutually exclusive") 62 case *nodeKeyFile != "": 63 if nodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil { 64 utils.Fatalf("-nodekey: %v", err) 65 } 66 case *nodeKeyHex != "": 67 if nodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil { 68 utils.Fatalf("-nodekeyhex: %v", err) 69 } 70 } 71 72 if *writeAddr { 73 fmt.Printf("%v\n", discover.PubkeyID(&nodeKey.PublicKey)) 74 os.Exit(0) 75 } 76 77 var restrictList *netutil.Netlist 78 if *netrestrict != "" { 79 restrictList, err = netutil.ParseNetlist(*netrestrict) 80 if err != nil { 81 utils.Fatalf("-netrestrict: %v", err) 82 } 83 } 84 85 addr, err := net.ResolveUDPAddr("udp", *listenAddr) 86 if err != nil { 87 utils.Fatalf("-ResolveUDPAddr: %v", err) 88 } 89 conn, err := net.ListenUDP("udp", addr) 90 if err != nil { 91 utils.Fatalf("-ListenUDP: %v", err) 92 } 93 94 realaddr := conn.LocalAddr().(*net.UDPAddr) 95 if natm != nil { 96 if !realaddr.IP.IsLoopback() { 97 go nat.Map(natm, nil, "udp", realaddr.Port, realaddr.Port, "quickchain discovery") 98 } 99 // TODO: react to external IP changes over time. 100 if ext, err := natm.ExternalIP(); err == nil { 101 realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port} 102 } 103 } 104 105 if *runv5 { 106 if _, err := discv5.ListenUDP(nodeKey, conn, realaddr, "", restrictList); err != nil { 107 utils.Fatalf("%v", err) 108 } 109 } else { 110 cfg := discover.Config{ 111 PrivateKey: nodeKey, 112 AnnounceAddr: realaddr, 113 NetRestrict: restrictList, 114 } 115 if _, err := discover.ListenUDP(conn, cfg); err != nil { 116 utils.Fatalf("%v", err) 117 } 118 } 119 120 select {} 121 }