2019-07-15 14:13:59 +00:00
|
|
|
package rpc
|
|
|
|
|
|
|
|
import (
|
2019-12-13 19:50:19 +00:00
|
|
|
"bufio"
|
2019-09-18 18:45:21 +00:00
|
|
|
"fmt"
|
2019-12-13 19:50:19 +00:00
|
|
|
"os"
|
2020-07-06 17:03:34 +00:00
|
|
|
"strings"
|
2019-09-18 18:45:21 +00:00
|
|
|
|
2019-12-20 09:47:02 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
2019-09-18 20:14:39 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
2019-12-13 19:50:19 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/client/input"
|
2019-07-15 14:13:59 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/client/lcd"
|
2020-08-23 21:41:54 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
2020-04-22 19:26:01 +00:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-12-20 09:47:02 +00:00
|
|
|
"github.com/cosmos/ethermint/app"
|
2020-10-06 18:57:55 +00:00
|
|
|
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
|
|
|
"github.com/cosmos/ethermint/crypto/hd"
|
2020-10-22 20:39:51 +00:00
|
|
|
"github.com/cosmos/ethermint/rpc/websockets"
|
2021-01-11 13:31:30 +00:00
|
|
|
evmrest "github.com/cosmos/ethermint/x/evm/client/rest"
|
2019-07-15 14:13:59 +00:00
|
|
|
"github.com/ethereum/go-ethereum/rpc"
|
2021-01-11 13:31:30 +00:00
|
|
|
"github.com/spf13/viper"
|
2019-07-15 14:13:59 +00:00
|
|
|
)
|
|
|
|
|
2019-09-18 18:45:21 +00:00
|
|
|
const (
|
|
|
|
flagUnlockKey = "unlock-key"
|
2020-07-06 17:23:35 +00:00
|
|
|
flagWebsocket = "wsport"
|
2019-09-18 18:45:21 +00:00
|
|
|
)
|
2019-07-15 14:13:59 +00:00
|
|
|
|
2020-10-22 20:39:51 +00:00
|
|
|
// RegisterRoutes creates a new server and registers the `/rpc` endpoint.
|
2019-07-15 14:13:59 +00:00
|
|
|
// Rpc calls are enabled based on their associated module (eg. "eth").
|
2020-10-22 20:39:51 +00:00
|
|
|
func RegisterRoutes(rs *lcd.RestServer) {
|
|
|
|
server := rpc.NewServer()
|
2019-09-18 18:45:21 +00:00
|
|
|
accountName := viper.GetString(flagUnlockKey)
|
2020-07-06 17:03:34 +00:00
|
|
|
accountNames := strings.Split(accountName, ",")
|
2019-09-18 18:45:21 +00:00
|
|
|
|
2020-10-06 18:57:55 +00:00
|
|
|
var privkeys []ethsecp256k1.PrivKey
|
2019-09-18 18:45:21 +00:00
|
|
|
if len(accountName) > 0 {
|
2019-12-13 19:50:19 +00:00
|
|
|
var err error
|
2020-04-22 19:26:01 +00:00
|
|
|
inBuf := bufio.NewReader(os.Stdin)
|
|
|
|
|
2019-12-13 19:50:19 +00:00
|
|
|
keyringBackend := viper.GetString(flags.FlagKeyringBackend)
|
|
|
|
passphrase := ""
|
|
|
|
switch keyringBackend {
|
2020-08-23 21:41:54 +00:00
|
|
|
case keys.BackendOS:
|
2019-12-13 19:50:19 +00:00
|
|
|
break
|
2020-08-23 21:41:54 +00:00
|
|
|
case keys.BackendFile:
|
2020-04-22 19:26:01 +00:00
|
|
|
passphrase, err = input.GetPassword(
|
|
|
|
"Enter password to unlock key for RPC API: ",
|
|
|
|
inBuf)
|
2019-12-13 19:50:19 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2019-09-18 18:45:21 +00:00
|
|
|
}
|
|
|
|
|
2020-08-23 21:41:54 +00:00
|
|
|
privkeys, err = unlockKeyFromNameAndPassphrase(accountNames, passphrase)
|
2019-09-18 18:45:21 +00:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-22 20:39:51 +00:00
|
|
|
apis := GetAPIs(rs.CliCtx, privkeys...)
|
2019-07-15 14:13:59 +00:00
|
|
|
|
2020-10-22 20:39:51 +00:00
|
|
|
// Register all the APIs exposed by the namespace services
|
|
|
|
// TODO: handle allowlist and private APIs
|
2019-07-15 14:13:59 +00:00
|
|
|
for _, api := range apis {
|
2020-10-22 20:39:51 +00:00
|
|
|
if err := server.RegisterName(api.Namespace, api.Service); err != nil {
|
|
|
|
panic(err)
|
2019-07-15 14:13:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-20 09:47:02 +00:00
|
|
|
// Web3 RPC API route
|
2020-10-22 20:39:51 +00:00
|
|
|
rs.Mux.HandleFunc("/", server.ServeHTTP).Methods("POST", "OPTIONS")
|
2019-12-20 09:47:02 +00:00
|
|
|
|
|
|
|
// Register all other Cosmos routes
|
|
|
|
client.RegisterRoutes(rs.CliCtx, rs.Mux)
|
2021-01-11 13:31:30 +00:00
|
|
|
evmrest.RegisterRoutes(rs.CliCtx, rs.Mux)
|
2019-12-20 09:47:02 +00:00
|
|
|
app.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux)
|
2020-07-06 17:23:35 +00:00
|
|
|
|
|
|
|
// start websockets server
|
|
|
|
websocketAddr := viper.GetString(flagWebsocket)
|
2020-10-22 20:39:51 +00:00
|
|
|
ws := websockets.NewServer(rs.CliCtx, websocketAddr)
|
|
|
|
ws.Start()
|
2019-07-15 14:13:59 +00:00
|
|
|
}
|
2019-09-18 18:45:21 +00:00
|
|
|
|
2020-10-06 18:57:55 +00:00
|
|
|
func unlockKeyFromNameAndPassphrase(accountNames []string, passphrase string) ([]ethsecp256k1.PrivKey, error) {
|
2020-08-23 21:41:54 +00:00
|
|
|
keybase, err := keys.NewKeyring(
|
2020-04-22 19:26:01 +00:00
|
|
|
sdk.KeyringServiceName(),
|
|
|
|
viper.GetString(flags.FlagKeyringBackend),
|
|
|
|
viper.GetString(flags.FlagHome),
|
|
|
|
os.Stdin,
|
2020-10-06 18:57:55 +00:00
|
|
|
hd.EthSecp256k1Options()...,
|
2020-04-22 19:26:01 +00:00
|
|
|
)
|
2019-09-18 18:45:21 +00:00
|
|
|
if err != nil {
|
2020-10-06 18:57:55 +00:00
|
|
|
return []ethsecp256k1.PrivKey{}, err
|
2019-09-18 18:45:21 +00:00
|
|
|
}
|
|
|
|
|
2020-07-06 17:03:34 +00:00
|
|
|
// try the for loop with array []string accountNames
|
|
|
|
// run through the bottom code inside the for loop
|
2020-08-11 15:01:15 +00:00
|
|
|
|
2020-10-06 18:57:55 +00:00
|
|
|
keys := make([]ethsecp256k1.PrivKey, len(accountNames))
|
2020-08-11 15:01:15 +00:00
|
|
|
for i, acc := range accountNames {
|
2020-07-06 17:03:34 +00:00
|
|
|
// With keyring keybase, password is not required as it is pulled from the OS prompt
|
|
|
|
privKey, err := keybase.ExportPrivateKeyObject(acc, passphrase)
|
|
|
|
if err != nil {
|
2020-10-06 18:57:55 +00:00
|
|
|
return []ethsecp256k1.PrivKey{}, err
|
2020-07-06 17:03:34 +00:00
|
|
|
}
|
2019-09-18 18:45:21 +00:00
|
|
|
|
2020-07-06 17:03:34 +00:00
|
|
|
var ok bool
|
2020-10-06 18:57:55 +00:00
|
|
|
keys[i], ok = privKey.(ethsecp256k1.PrivKey)
|
2020-07-06 17:03:34 +00:00
|
|
|
if !ok {
|
2020-08-11 15:01:15 +00:00
|
|
|
panic(fmt.Sprintf("invalid private key type %T at index %d", privKey, i))
|
2020-07-06 17:03:34 +00:00
|
|
|
}
|
2019-09-18 18:45:21 +00:00
|
|
|
}
|
|
|
|
|
2020-08-11 15:01:15 +00:00
|
|
|
return keys, nil
|
2019-09-18 18:45:21 +00:00
|
|
|
}
|