github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/rpc/config.go (about) 1 package rpc 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/ethereum/go-ethereum/rpc" 10 "github.com/fibonacci-chain/fbc/app/crypto/ethsecp256k1" 11 "github.com/fibonacci-chain/fbc/app/crypto/hd" 12 "github.com/fibonacci-chain/fbc/app/rpc/nacos" 13 "github.com/fibonacci-chain/fbc/app/rpc/pendingtx" 14 "github.com/fibonacci-chain/fbc/app/rpc/websockets" 15 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags" 16 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/input" 17 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/lcd" 18 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys" 19 cmserver "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/server" 20 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 21 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 22 23 "github.com/spf13/viper" 24 ) 25 26 const ( 27 flagUnlockKey = "unlock-key" 28 FlagWebsocket = "wsport" 29 FlagPersonalAPI = "personal-api" 30 FlagDebugAPI = "debug-api" 31 FlagRateLimitAPI = "rpc.rate-limit-api" 32 FlagRateLimitCount = "rpc.rate-limit-count" 33 FlagRateLimitBurst = "rpc.rate-limit-burst" 34 FlagDisableAPI = "rpc.disable-api" 35 FlagKafkaAddr = "pendingtx.kafka-addr" 36 FlagKafkaTopic = "pendingtx.kafka-topic" 37 FlagNacosTmrpcUrls = "rpc.tmrpc_nacos_urls" 38 FlagNacosTmrpcNamespaceID = "rpc.tmrpc_nacos_namespace_id" 39 FlagNacosTmrpcAppName = "rpc.tmrpc_application_name" 40 FlagRpcExternalAddr = "rpc.external_laddr" 41 FlagRestApplicationName = "rest.application_name" 42 FlagRestNacosUrls = "rest.nacos_urls" 43 FlagRestNacosNamespaceId = "rest.nacos_namespace_id" 44 FlagExternalListenAddr = "rest.external_laddr" 45 ) 46 47 // RegisterRoutes creates a new server and registers the `/rpc` endpoint. 48 // Rpc calls are enabled based on their associated module (eg. "eth"). 49 func RegisterRoutes(rs *lcd.RestServer) { 50 // register nacos first 51 registerNacos(rs.Logger()) 52 53 server := rpc.NewServer() 54 accountName := viper.GetString(cmserver.FlagUlockKey) 55 accountNames := strings.Split(accountName, ",") 56 57 var privkeys []ethsecp256k1.PrivKey 58 if len(accountName) > 0 { 59 var err error 60 inBuf := bufio.NewReader(os.Stdin) 61 62 keyringBackend := viper.GetString(flags.FlagKeyringBackend) 63 passphrase := "" 64 switch keyringBackend { 65 case keys.BackendOS: 66 break 67 case keys.BackendFile: 68 passphrase, err = input.GetPassword( 69 "Enter password to unlock key for RPC API: ", 70 inBuf) 71 if err != nil { 72 panic(err) 73 } 74 } 75 76 privkeys, err = unlockKeyFromNameAndPassphrase(accountNames, passphrase) 77 if err != nil { 78 panic(err) 79 } 80 } 81 82 apis := GetAPIs(rs.CliCtx, rs.Logger(), privkeys...) 83 84 // Register all the APIs exposed by the namespace services 85 // TODO: handle allowlist and private APIs 86 for _, api := range apis { 87 if err := server.RegisterName(api.Namespace, api.Service); err != nil { 88 panic(err) 89 } 90 } 91 92 // Web3 RPC API route 93 rs.Mux.HandleFunc("/", server.ServeHTTP).Methods("POST", "OPTIONS") 94 95 // start websockets server 96 websocketAddr := viper.GetString(FlagWebsocket) 97 ws := websockets.NewServer(rs.CliCtx, rs.Logger(), websocketAddr) 98 ws.Start() 99 100 // pending tx watcher 101 kafkaAddrs := viper.GetString(FlagKafkaAddr) 102 kafkaTopic := viper.GetString(FlagKafkaTopic) 103 if kafkaAddrs != "" && kafkaTopic != "" { 104 kafkaClient := pendingtx.NewKafkaClient(strings.Split(kafkaAddrs, ","), kafkaTopic) 105 ptw := pendingtx.NewWatcher(rs.CliCtx, rs.Logger(), kafkaClient) 106 ptw.Start() 107 } 108 } 109 110 func unlockKeyFromNameAndPassphrase(accountNames []string, passphrase string) ([]ethsecp256k1.PrivKey, error) { 111 keybase, err := keys.NewKeyring( 112 sdk.KeyringServiceName(), 113 viper.GetString(flags.FlagKeyringBackend), 114 viper.GetString(cmserver.FlagUlockKeyHome), 115 os.Stdin, 116 hd.EthSecp256k1Options()..., 117 ) 118 if err != nil { 119 return []ethsecp256k1.PrivKey{}, err 120 } 121 122 // try the for loop with array []string accountNames 123 // run through the bottom code inside the for loop 124 125 keys := make([]ethsecp256k1.PrivKey, len(accountNames)) 126 for i, acc := range accountNames { 127 // With keyring keybase, password is not required as it is pulled from the OS prompt 128 privKey, err := keybase.ExportPrivateKeyObject(acc, passphrase) 129 if err != nil { 130 return []ethsecp256k1.PrivKey{}, err 131 } 132 133 var ok bool 134 keys[i], ok = privKey.(ethsecp256k1.PrivKey) 135 if !ok { 136 panic(fmt.Sprintf("invalid private key type %T at index %d", privKey, i)) 137 } 138 } 139 140 return keys, nil 141 } 142 143 func registerNacos(logger log.Logger) { 144 nacosUrls := viper.GetString(FlagRestNacosUrls) 145 nacosNamespaceId := viper.GetString(FlagRestNacosNamespaceId) 146 applicationName := viper.GetString(FlagRestApplicationName) 147 externalAddr := viper.GetString(FlagExternalListenAddr) 148 149 // start nacos client for registering restful service 150 if nacosUrls != "" { 151 nacos.StartNacosClient(logger, nacosUrls, nacosNamespaceId, applicationName, externalAddr) 152 } 153 154 nacosTmRpcUrls := viper.GetString(FlagNacosTmrpcUrls) 155 nacosTmRpcNamespaceID := viper.GetString(FlagNacosTmrpcNamespaceID) 156 nacosTmRpcAppName := viper.GetString(FlagNacosTmrpcAppName) 157 rpcExternalAddr := viper.GetString(FlagRpcExternalAddr) 158 // start nacos client for tmrpc service 159 if nacosTmRpcUrls != "" { 160 nacos.StartNacosClient(logger, nacosTmRpcUrls, nacosTmRpcNamespaceID, nacosTmRpcAppName, rpcExternalAddr) 161 } 162 }