github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/cmd/devp2p/keycmd.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "fmt" 21 "net" 22 23 "github.com/tirogen/go-ethereum/crypto" 24 "github.com/tirogen/go-ethereum/p2p/enode" 25 "github.com/tirogen/go-ethereum/p2p/enr" 26 "github.com/urfave/cli/v2" 27 ) 28 29 var ( 30 keyCommand = &cli.Command{ 31 Name: "key", 32 Usage: "Operations on node keys", 33 Subcommands: []*cli.Command{ 34 keyGenerateCommand, 35 keyToIDCommand, 36 keyToNodeCommand, 37 keyToRecordCommand, 38 }, 39 } 40 keyGenerateCommand = &cli.Command{ 41 Name: "generate", 42 Usage: "Generates node key files", 43 ArgsUsage: "keyfile", 44 Action: genkey, 45 } 46 keyToIDCommand = &cli.Command{ 47 Name: "to-id", 48 Usage: "Creates a node ID from a node key file", 49 ArgsUsage: "keyfile", 50 Action: keyToID, 51 Flags: []cli.Flag{}, 52 } 53 keyToNodeCommand = &cli.Command{ 54 Name: "to-enode", 55 Usage: "Creates an enode URL from a node key file", 56 ArgsUsage: "keyfile", 57 Action: keyToURL, 58 Flags: []cli.Flag{hostFlag, tcpPortFlag, udpPortFlag}, 59 } 60 keyToRecordCommand = &cli.Command{ 61 Name: "to-enr", 62 Usage: "Creates an ENR from a node key file", 63 ArgsUsage: "keyfile", 64 Action: keyToRecord, 65 Flags: []cli.Flag{hostFlag, tcpPortFlag, udpPortFlag}, 66 } 67 ) 68 69 var ( 70 hostFlag = &cli.StringFlag{ 71 Name: "ip", 72 Usage: "IP address of the node", 73 Value: "127.0.0.1", 74 } 75 tcpPortFlag = &cli.IntFlag{ 76 Name: "tcp", 77 Usage: "TCP port of the node", 78 Value: 30303, 79 } 80 udpPortFlag = &cli.IntFlag{ 81 Name: "udp", 82 Usage: "UDP port of the node", 83 Value: 30303, 84 } 85 ) 86 87 func genkey(ctx *cli.Context) error { 88 if ctx.NArg() != 1 { 89 return fmt.Errorf("need key file as argument") 90 } 91 file := ctx.Args().Get(0) 92 93 key, err := crypto.GenerateKey() 94 if err != nil { 95 return fmt.Errorf("could not generate key: %v", err) 96 } 97 return crypto.SaveECDSA(file, key) 98 } 99 100 func keyToID(ctx *cli.Context) error { 101 n, err := makeRecord(ctx) 102 if err != nil { 103 return err 104 } 105 fmt.Println(n.ID()) 106 return nil 107 } 108 109 func keyToURL(ctx *cli.Context) error { 110 n, err := makeRecord(ctx) 111 if err != nil { 112 return err 113 } 114 fmt.Println(n.URLv4()) 115 return nil 116 } 117 118 func keyToRecord(ctx *cli.Context) error { 119 n, err := makeRecord(ctx) 120 if err != nil { 121 return err 122 } 123 fmt.Println(n.String()) 124 return nil 125 } 126 127 func makeRecord(ctx *cli.Context) (*enode.Node, error) { 128 if ctx.NArg() != 1 { 129 return nil, fmt.Errorf("need key file as argument") 130 } 131 132 var ( 133 file = ctx.Args().Get(0) 134 host = ctx.String(hostFlag.Name) 135 tcp = ctx.Int(tcpPortFlag.Name) 136 udp = ctx.Int(udpPortFlag.Name) 137 ) 138 key, err := crypto.LoadECDSA(file) 139 if err != nil { 140 return nil, err 141 } 142 143 var r enr.Record 144 if host != "" { 145 ip := net.ParseIP(host) 146 if ip == nil { 147 return nil, fmt.Errorf("invalid IP address %q", host) 148 } 149 r.Set(enr.IP(ip)) 150 } 151 if udp != 0 { 152 r.Set(enr.UDP(udp)) 153 } 154 if tcp != 0 { 155 r.Set(enr.TCP(tcp)) 156 } 157 158 if err := enode.SignV4(&r, key); err != nil { 159 return nil, err 160 } 161 return enode.New(enode.ValidSchemes, &r) 162 }