github.com/onflow/flow-go@v0.33.17/cmd/utils.go (about) 1 package cmd 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "fmt" 7 "path/filepath" 8 "strings" 9 10 "github.com/libp2p/go-libp2p/core/peer" 11 "github.com/rs/zerolog" 12 13 "github.com/onflow/flow-go/crypto" 14 "github.com/onflow/flow-go/model/bootstrap" 15 "github.com/onflow/flow-go/model/flow" 16 "github.com/onflow/flow-go/module" 17 "github.com/onflow/flow-go/module/id" 18 "github.com/onflow/flow-go/network/p2p" 19 "github.com/onflow/flow-go/network/p2p/cache" 20 p2plogging "github.com/onflow/flow-go/network/p2p/logging" 21 "github.com/onflow/flow-go/network/p2p/translator" 22 "github.com/onflow/flow-go/network/p2p/unicast/protocols" 23 "github.com/onflow/flow-go/state/protocol/inmem" 24 "github.com/onflow/flow-go/utils/io" 25 ) 26 27 // loadRootProtocolSnapshot loads the root protocol snapshot from disk 28 func loadRootProtocolSnapshot(dir string) (*inmem.Snapshot, error) { 29 path := filepath.Join(dir, bootstrap.PathRootProtocolStateSnapshot) 30 data, err := io.ReadFile(path) 31 if err != nil { 32 return nil, fmt.Errorf("could not read root snapshot (path=%s): %w", path, err) 33 } 34 35 var snapshot inmem.EncodableSnapshot 36 err = json.Unmarshal(data, &snapshot) 37 if err != nil { 38 return nil, err 39 } 40 41 return inmem.SnapshotFromEncodable(snapshot), nil 42 } 43 44 // LoadPrivateNodeInfo the private info for this node from disk (e.g., private staking/network keys). 45 func LoadPrivateNodeInfo(dir string, myID flow.Identifier) (*bootstrap.NodeInfoPriv, error) { 46 path := filepath.Join(dir, fmt.Sprintf(bootstrap.PathNodeInfoPriv, myID)) 47 data, err := io.ReadFile(path) 48 if err != nil { 49 return nil, fmt.Errorf("could not read private node info (path=%s): %w", path, err) 50 } 51 var info bootstrap.NodeInfoPriv 52 err = json.Unmarshal(data, &info) 53 return &info, err 54 } 55 56 func LoadNetworkPrivateKey(dir string, myID flow.Identifier) (crypto.PrivateKey, error) { 57 path := filepath.Join(dir, fmt.Sprintf(filepath.Join(bootstrap.DirPrivateRoot, 58 "private-node-info_%v/network_private_key"), myID)) 59 data, err := io.ReadFile(path) 60 if err != nil { 61 return nil, fmt.Errorf("could not read private node info (path=%s): %w", path, err) 62 } 63 64 keyBytes, err := hex.DecodeString(strings.Trim(string(data), "\n ")) 65 if err != nil { 66 return nil, fmt.Errorf("could not hex decode networking key (path=%s): %w", path, err) 67 } 68 69 networkingKey, err := crypto.DecodePrivateKey(crypto.ECDSASecp256k1, keyBytes) 70 if err != nil { 71 return nil, fmt.Errorf("could not decode networking key (path=%s): %w", path, err) 72 } 73 return networkingKey, nil 74 } 75 76 // loadSecretsEncryptionKey loads the encryption key for the secrets database. 77 // If the file does not exist, returns os.ErrNotExist. 78 func loadSecretsEncryptionKey(dir string, myID flow.Identifier) ([]byte, error) { 79 path := filepath.Join(dir, fmt.Sprintf(bootstrap.PathSecretsEncryptionKey, myID)) 80 data, err := io.ReadFile(path) 81 if err != nil { 82 return nil, fmt.Errorf("could not read secrets db encryption key (path=%s): %w", path, err) 83 } 84 return data, nil 85 } 86 87 func rateLimiterPeerFilter(rateLimiter p2p.RateLimiter) p2p.PeerFilter { 88 return func(p peer.ID) error { 89 if rateLimiter.IsRateLimited(p) { 90 return fmt.Errorf("peer is rate limited") 91 } 92 93 return nil 94 } 95 } 96 97 // BootstrapIdentities converts the bootstrap node addresses and keys to a Flow Identity list where 98 // each Flow Identity is initialized with the passed address, the networking key 99 // and the Node ID set to ZeroID, role set to Access, 0 stake and no staking key. 100 func BootstrapIdentities(addresses []string, keys []string) (flow.IdentityList, error) { 101 if len(addresses) != len(keys) { 102 return nil, fmt.Errorf("number of addresses and keys provided for the boostrap nodes don't match") 103 } 104 105 ids := make(flow.IdentityList, len(addresses)) 106 for i, address := range addresses { 107 bytes, err := hex.DecodeString(keys[i]) 108 if err != nil { 109 return nil, fmt.Errorf("failed to decode secured GRPC server public key hex %w", err) 110 } 111 112 publicFlowNetworkingKey, err := crypto.DecodePublicKey(crypto.ECDSAP256, bytes) 113 if err != nil { 114 return nil, fmt.Errorf("failed to get public flow networking key could not decode public key bytes %w", err) 115 } 116 117 // create the identity of the peer by setting only the relevant fields 118 ids[i] = &flow.Identity{ 119 NodeID: flow.ZeroID, // the NodeID is the hash of the staking key and for the public network it does not apply 120 Address: address, 121 Role: flow.RoleAccess, // the upstream node has to be an access node 122 NetworkPubKey: publicFlowNetworkingKey, 123 } 124 } 125 return ids, nil 126 } 127 128 func CreatePublicIDTranslatorAndIdentifierProvider( 129 logger zerolog.Logger, 130 networkKey crypto.PrivateKey, 131 sporkID flow.Identifier, 132 getLibp2pNode func() p2p.LibP2PNode, 133 idCache *cache.ProtocolStateIDCache, 134 ) ( 135 p2p.IDTranslator, 136 func() module.IdentifierProvider, 137 error, 138 ) { 139 idTranslator := translator.NewHierarchicalIDTranslator(idCache, translator.NewPublicNetworkIDTranslator()) 140 141 peerID, err := peerIDFromNetworkKey(networkKey) 142 if err != nil { 143 return nil, nil, fmt.Errorf("could not get peer ID from network key: %w", err) 144 } 145 // use the default identifier provider 146 factory := func() module.IdentifierProvider { 147 return id.NewCustomIdentifierProvider(func() flow.IdentifierList { 148 pids := getLibp2pNode().GetPeersForProtocol(protocols.FlowProtocolID(sporkID)) 149 result := make(flow.IdentifierList, 0, len(pids)) 150 151 for _, pid := range pids { 152 // exclude own Identifier 153 if pid == peerID { 154 continue 155 } 156 157 if flowID, err := idTranslator.GetFlowID(pid); err != nil { 158 // TODO: this is an instance of "log error and continue with best effort" anti-pattern 159 logger.Fatal().Err(err).Str("peer", p2plogging.PeerId(pid)).Msg("failed to translate to Flow ID") 160 } else { 161 result = append(result, flowID) 162 } 163 } 164 165 if len(result) == 0 { 166 logger.Error().Msgf("empty identifier list, pids: %v", pids) 167 } 168 169 return result 170 }) 171 } 172 173 return idTranslator, factory, nil 174 }