github.com/okex/exchain@v1.8.0/libs/tendermint/p2p/key.go (about) 1 package p2p 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "fmt" 7 "io/ioutil" 8 9 "github.com/okex/exchain/libs/tendermint/crypto" 10 "github.com/okex/exchain/libs/tendermint/crypto/ed25519" 11 tmos "github.com/okex/exchain/libs/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 // BytesToPubKey returns the PubKey corresponding to the given ID. 48 func BytesToPubKey(b []byte) crypto.PubKey { 49 var pub crypto.PubKey 50 if err := cdc.UnmarshalBinaryBare(b, &pub); err != nil { 51 return nil 52 } 53 return pub 54 } 55 56 // LoadOrGenNodeKey attempts to load the NodeKey from the given filePath. 57 // If the file does not exist, it generates and saves a new NodeKey. 58 func LoadOrGenNodeKey(filePath string) (*NodeKey, error) { 59 if tmos.FileExists(filePath) { 60 nodeKey, err := LoadNodeKey(filePath) 61 if err != nil { 62 return nil, err 63 } 64 return nodeKey, nil 65 } 66 return genNodeKey(filePath) 67 } 68 69 func LoadOrGenNodeKeyByIndex(filePath string, index int) (*NodeKey, error) { 70 if tmos.FileExists(filePath) { 71 nodeKey, err := LoadNodeKey(filePath) 72 if err != nil { 73 return nil, err 74 } 75 return nodeKey, nil 76 } 77 return genNodeKeyByIndex(filePath, index) 78 } 79 80 func LoadNodeKey(filePath string) (*NodeKey, error) { 81 jsonBytes, err := ioutil.ReadFile(filePath) 82 if err != nil { 83 return nil, err 84 } 85 nodeKey := new(NodeKey) 86 err = cdc.UnmarshalJSON(jsonBytes, nodeKey) 87 if err != nil { 88 return nil, fmt.Errorf("error reading NodeKey from %v: %v", filePath, err) 89 } 90 return nodeKey, nil 91 } 92 93 func genNodeKey(filePath string) (*NodeKey, error) { 94 privKey := ed25519.GenPrivKey() 95 nodeKey := &NodeKey{ 96 PrivKey: privKey, 97 } 98 99 jsonBytes, err := cdc.MarshalJSON(nodeKey) 100 if err != nil { 101 return nil, err 102 } 103 err = ioutil.WriteFile(filePath, jsonBytes, 0600) 104 if err != nil { 105 return nil, err 106 } 107 return nodeKey, nil 108 } 109 110 func genNodeKeyByIndex(filePath string, index int) (*NodeKey, error) { 111 if index < 0 { 112 return genNodeKey(filePath) 113 } 114 115 privKey := ed25519.GenPrivKeyFromSecret([]byte(fmt.Sprintf("secret%d", index))) 116 nodeKey := &NodeKey{ 117 PrivKey: privKey, 118 } 119 120 jsonBytes, err := cdc.MarshalJSON(nodeKey) 121 if err != nil { 122 return nil, err 123 } 124 err = ioutil.WriteFile(filePath, jsonBytes, 0600) 125 if err != nil { 126 return nil, err 127 } 128 return nodeKey, nil 129 } 130 131 //------------------------------------------------------------------------------ 132 133 // MakePoWTarget returns the big-endian encoding of 2^(targetBits - difficulty) - 1. 134 // It can be used as a Proof of Work target. 135 // NOTE: targetBits must be a multiple of 8 and difficulty must be less than targetBits. 136 func MakePoWTarget(difficulty, targetBits uint) []byte { 137 if targetBits%8 != 0 { 138 panic(fmt.Sprintf("targetBits (%d) not a multiple of 8", targetBits)) 139 } 140 if difficulty >= targetBits { 141 panic(fmt.Sprintf("difficulty (%d) >= targetBits (%d)", difficulty, targetBits)) 142 } 143 targetBytes := targetBits / 8 144 zeroPrefixLen := (int(difficulty) / 8) 145 prefix := bytes.Repeat([]byte{0}, zeroPrefixLen) 146 mod := (difficulty % 8) 147 if mod > 0 { 148 nonZeroPrefix := byte(1<<(8-mod) - 1) 149 prefix = append(prefix, nonZeroPrefix) 150 } 151 tailLen := int(targetBytes) - len(prefix) 152 return append(prefix, bytes.Repeat([]byte{0xFF}, tailLen)...) 153 }