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