github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/p2p/key.go (about) 1 package p2p 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 8 "github.com/gnolang/gno/tm2/pkg/amino" 9 "github.com/gnolang/gno/tm2/pkg/crypto" 10 "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" 11 osm "github.com/gnolang/gno/tm2/pkg/os" 12 ) 13 14 // ------------------------------------------------------------------------------ 15 // Persistent peer ID 16 // TODO: encrypt on disk 17 18 // NodeKey is the persistent peer key. 19 // It contains the nodes private key for authentication. 20 type NodeKey struct { 21 crypto.PrivKey `json:"priv_key"` // our priv key 22 } 23 24 func (nk NodeKey) ID() ID { 25 return nk.PubKey().Address().ID() 26 } 27 28 // LoadOrGenNodeKey attempts to load the NodeKey from the given filePath. 29 // If the file does not exist, it generates and saves a new NodeKey. 30 func LoadOrGenNodeKey(filePath string) (*NodeKey, error) { 31 if osm.FileExists(filePath) { 32 nodeKey, err := LoadNodeKey(filePath) 33 if err != nil { 34 return nil, err 35 } 36 return nodeKey, nil 37 } 38 return genNodeKey(filePath) 39 } 40 41 func LoadNodeKey(filePath string) (*NodeKey, error) { 42 jsonBytes, err := os.ReadFile(filePath) 43 if err != nil { 44 return nil, err 45 } 46 nodeKey := new(NodeKey) 47 err = amino.UnmarshalJSON(jsonBytes, nodeKey) 48 if err != nil { 49 return nil, fmt.Errorf("Error reading NodeKey from %v: %w", filePath, err) 50 } 51 return nodeKey, nil 52 } 53 54 func genNodeKey(filePath string) (*NodeKey, error) { 55 privKey := ed25519.GenPrivKey() 56 nodeKey := &NodeKey{ 57 PrivKey: privKey, 58 } 59 60 jsonBytes, err := amino.MarshalJSON(nodeKey) 61 if err != nil { 62 return nil, err 63 } 64 err = os.WriteFile(filePath, jsonBytes, 0o600) 65 if err != nil { 66 return nil, err 67 } 68 return nodeKey, nil 69 } 70 71 // ------------------------------------------------------------------------------ 72 73 // MakePoWTarget returns the big-endian encoding of 2^(targetBits - difficulty) - 1. 74 // It can be used as a Proof of Work target. 75 // NOTE: targetBits must be a multiple of 8 and difficulty must be less than targetBits. 76 func MakePoWTarget(difficulty, targetBits uint) []byte { 77 if targetBits%8 != 0 { 78 panic(fmt.Sprintf("targetBits (%d) not a multiple of 8", targetBits)) 79 } 80 if difficulty >= targetBits { 81 panic(fmt.Sprintf("difficulty (%d) >= targetBits (%d)", difficulty, targetBits)) 82 } 83 targetBytes := targetBits / 8 84 zeroPrefixLen := (int(difficulty) / 8) 85 prefix := bytes.Repeat([]byte{0}, zeroPrefixLen) 86 mod := (difficulty % 8) 87 if mod > 0 { 88 nonZeroPrefix := byte(1<<(8-mod) - 1) 89 prefix = append(prefix, nonZeroPrefix) 90 } 91 tailLen := int(targetBytes) - len(prefix) 92 return append(prefix, bytes.Repeat([]byte{0xFF}, tailLen)...) 93 }