github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/p2p/key.go (about) 1 package p2p 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "fmt" 7 "io/ioutil" 8 9 "github.com/tendermint/tendermint/crypto" 10 "github.com/tendermint/tendermint/crypto/ed25519" 11 tmos "github.com/tendermint/tendermint/libs/os" 12 ) 13 14 // ID is a hex-encoded crypto.Address 15 type ID string 16 17 // IDByteLength is the length of a crypto.Address. Currently only 20. 18 // TODO: support other length addresses ? 19 const IDByteLength = crypto.AddressSize 20 21 //------------------------------------------------------------------------------ 22 // Persistent peer ID 23 // TODO: encrypt on disk 24 25 // NodeKey is the persistent peer key. 26 // It contains the nodes private key for authentication. 27 type NodeKey struct { 28 PrivKey crypto.PrivKey `json:"priv_key"` // our priv key 29 } 30 31 // ID returns the peer's canonical ID - the hash of its public key. 32 func (nodeKey *NodeKey) ID() ID { 33 return PubKeyToID(nodeKey.PubKey()) 34 } 35 36 // PubKey returns the peer's PubKey 37 func (nodeKey *NodeKey) PubKey() crypto.PubKey { 38 return nodeKey.PrivKey.PubKey() 39 } 40 41 // PubKeyToID returns the ID corresponding to the given PubKey. 42 // It's the hex-encoding of the pubKey.Address(). 43 func PubKeyToID(pubKey crypto.PubKey) ID { 44 return ID(hex.EncodeToString(pubKey.Address())) 45 } 46 47 // LoadOrGenNodeKey attempts to load the NodeKey from the given filePath. 48 // If the file does not exist, it generates and saves a new NodeKey. 49 func LoadOrGenNodeKey(filePath string) (*NodeKey, error) { 50 if tmos.FileExists(filePath) { 51 nodeKey, err := LoadNodeKey(filePath) 52 if err != nil { 53 return nil, err 54 } 55 return nodeKey, nil 56 } 57 return genNodeKey(filePath) 58 } 59 60 func LoadNodeKey(filePath string) (*NodeKey, error) { 61 jsonBytes, err := ioutil.ReadFile(filePath) 62 if err != nil { 63 return nil, err 64 } 65 nodeKey := new(NodeKey) 66 err = cdc.UnmarshalJSON(jsonBytes, nodeKey) 67 if err != nil { 68 return nil, fmt.Errorf("error reading NodeKey from %v: %v", filePath, err) 69 } 70 return nodeKey, nil 71 } 72 73 func genNodeKey(filePath string) (*NodeKey, error) { 74 privKey := ed25519.GenPrivKey() 75 nodeKey := &NodeKey{ 76 PrivKey: privKey, 77 } 78 79 jsonBytes, err := cdc.MarshalJSON(nodeKey) 80 if err != nil { 81 return nil, err 82 } 83 err = ioutil.WriteFile(filePath, jsonBytes, 0600) 84 if err != nil { 85 return nil, err 86 } 87 return nodeKey, nil 88 } 89 90 //------------------------------------------------------------------------------ 91 92 // MakePoWTarget returns the big-endian encoding of 2^(targetBits - difficulty) - 1. 93 // It can be used as a Proof of Work target. 94 // NOTE: targetBits must be a multiple of 8 and difficulty must be less than targetBits. 95 func MakePoWTarget(difficulty, targetBits uint) []byte { 96 if targetBits%8 != 0 { 97 panic(fmt.Sprintf("targetBits (%d) not a multiple of 8", targetBits)) 98 } 99 if difficulty >= targetBits { 100 panic(fmt.Sprintf("difficulty (%d) >= targetBits (%d)", difficulty, targetBits)) 101 } 102 targetBytes := targetBits / 8 103 zeroPrefixLen := (int(difficulty) / 8) 104 prefix := bytes.Repeat([]byte{0}, zeroPrefixLen) 105 mod := (difficulty % 8) 106 if mod > 0 { 107 nonZeroPrefix := byte(1<<(8-mod) - 1) 108 prefix = append(prefix, nonZeroPrefix) 109 } 110 tailLen := int(targetBytes) - len(prefix) 111 return append(prefix, bytes.Repeat([]byte{0xFF}, tailLen)...) 112 }