allow multikey unlock (#356)
* allow multikey unlock * fix lint * Update rpc/apis.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
parent
5768706917
commit
b76c36fcdb
@ -3,10 +3,8 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
|
||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
@ -21,7 +19,7 @@ const (
|
||||
)
|
||||
|
||||
// GetRPCAPIs returns the list of all APIs
|
||||
func GetRPCAPIs(cliCtx context.CLIContext, key emintcrypto.PrivKeySecp256k1) []rpc.API {
|
||||
func GetRPCAPIs(cliCtx context.CLIContext, keys []emintcrypto.PrivKeySecp256k1) []rpc.API {
|
||||
nonceLock := new(AddrLocker)
|
||||
backend := NewEthermintBackend(cliCtx)
|
||||
return []rpc.API{
|
||||
@ -34,7 +32,7 @@ func GetRPCAPIs(cliCtx context.CLIContext, key emintcrypto.PrivKeySecp256k1) []r
|
||||
{
|
||||
Namespace: EthNamespace,
|
||||
Version: apiVersion,
|
||||
Service: NewPublicEthAPI(cliCtx, backend, nonceLock, key),
|
||||
Service: NewPublicEthAPI(cliCtx, backend, nonceLock, keys),
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
@ -16,7 +17,6 @@ import (
|
||||
|
||||
"github.com/cosmos/ethermint/app"
|
||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@ -56,8 +56,9 @@ func EmintServeCmd(cdc *codec.Codec) *cobra.Command {
|
||||
func registerRoutes(rs *lcd.RestServer) {
|
||||
s := rpc.NewServer()
|
||||
accountName := viper.GetString(flagUnlockKey)
|
||||
accountNames := strings.Split(accountName, ",")
|
||||
|
||||
var emintKey emintcrypto.PrivKeySecp256k1
|
||||
var emintKeys []emintcrypto.PrivKeySecp256k1
|
||||
if len(accountName) > 0 {
|
||||
var err error
|
||||
inBuf := bufio.NewReader(os.Stdin)
|
||||
@ -76,13 +77,13 @@ func registerRoutes(rs *lcd.RestServer) {
|
||||
}
|
||||
}
|
||||
|
||||
emintKey, err = unlockKeyFromNameAndPassphrase(accountName, passphrase)
|
||||
emintKeys, err = unlockKeyFromNameAndPassphrase(accountNames, passphrase)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
apis := GetRPCAPIs(rs.CliCtx, emintKey)
|
||||
apis := GetRPCAPIs(rs.CliCtx, emintKeys)
|
||||
|
||||
// TODO: Allow cli to configure modules https://github.com/ChainSafe/ethermint/issues/74
|
||||
whitelist := make(map[string]bool)
|
||||
@ -105,7 +106,7 @@ func registerRoutes(rs *lcd.RestServer) {
|
||||
app.ModuleBasics.RegisterRESTRoutes(rs.CliCtx, rs.Mux)
|
||||
}
|
||||
|
||||
func unlockKeyFromNameAndPassphrase(accountName, passphrase string) (emintKey emintcrypto.PrivKeySecp256k1, err error) {
|
||||
func unlockKeyFromNameAndPassphrase(accountNames []string, passphrase string) (emintKeys []emintcrypto.PrivKeySecp256k1, err error) {
|
||||
keybase, err := keyring.NewKeyring(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
@ -116,17 +117,22 @@ func unlockKeyFromNameAndPassphrase(accountName, passphrase string) (emintKey em
|
||||
return
|
||||
}
|
||||
|
||||
// try the for loop with array []string accountNames
|
||||
// run through the bottom code inside the for loop
|
||||
for _, acc := range accountNames {
|
||||
// With keyring keybase, password is not required as it is pulled from the OS prompt
|
||||
privKey, err := keybase.ExportPrivateKeyObject(accountName, passphrase)
|
||||
privKey, err := keybase.ExportPrivateKeyObject(acc, passphrase)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
emintKey, ok = privKey.(emintcrypto.PrivKeySecp256k1)
|
||||
emintKey, ok := privKey.(emintcrypto.PrivKeySecp256k1)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("invalid private key type: %T", privKey))
|
||||
}
|
||||
emintKeys = append(emintKeys, emintKey)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -45,19 +45,19 @@ import (
|
||||
type PublicEthAPI struct {
|
||||
cliCtx context.CLIContext
|
||||
backend Backend
|
||||
key emintcrypto.PrivKeySecp256k1
|
||||
keys []emintcrypto.PrivKeySecp256k1
|
||||
nonceLock *AddrLocker
|
||||
keybaseLock sync.Mutex
|
||||
}
|
||||
|
||||
// NewPublicEthAPI creates an instance of the public ETH Web3 API.
|
||||
func NewPublicEthAPI(cliCtx context.CLIContext, backend Backend, nonceLock *AddrLocker,
|
||||
key emintcrypto.PrivKeySecp256k1) *PublicEthAPI {
|
||||
key []emintcrypto.PrivKeySecp256k1) *PublicEthAPI {
|
||||
|
||||
return &PublicEthAPI{
|
||||
cliCtx: cliCtx,
|
||||
backend: backend,
|
||||
key: key,
|
||||
keys: key,
|
||||
nonceLock: nonceLock,
|
||||
}
|
||||
}
|
||||
@ -282,15 +282,28 @@ func (e *PublicEthAPI) ExportAccount(address common.Address, blockNumber BlockNu
|
||||
return string(res), nil
|
||||
}
|
||||
|
||||
func checkKeyInKeyring(keys []emintcrypto.PrivKeySecp256k1, address common.Address) (key emintcrypto.PrivKeySecp256k1, exist bool) {
|
||||
if len(keys) > 0 {
|
||||
for _, key := range keys {
|
||||
if bytes.Equal(key.PubKey().Address().Bytes(), address.Bytes()) {
|
||||
return key, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Sign signs the provided data using the private key of address via Geth's signature standard.
|
||||
func (e *PublicEthAPI) Sign(address common.Address, data hexutil.Bytes) (hexutil.Bytes, error) {
|
||||
// TODO: Change this functionality to find an unlocked account by address
|
||||
if e.key == nil || !bytes.Equal(e.key.PubKey().Address().Bytes(), address.Bytes()) {
|
||||
|
||||
key, exist := checkKeyInKeyring(e.keys, address)
|
||||
if !exist {
|
||||
return nil, keystore.ErrLocked
|
||||
}
|
||||
|
||||
// Sign the requested hash with the wallet
|
||||
signature, err := e.key.Sign(data)
|
||||
signature, err := key.Sign(data)
|
||||
if err == nil {
|
||||
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
|
||||
}
|
||||
@ -301,7 +314,9 @@ func (e *PublicEthAPI) Sign(address common.Address, data hexutil.Bytes) (hexutil
|
||||
// SendTransaction sends an Ethereum transaction.
|
||||
func (e *PublicEthAPI) SendTransaction(args params.SendTxArgs) (common.Hash, error) {
|
||||
// TODO: Change this functionality to find an unlocked account by address
|
||||
if e.key == nil || !bytes.Equal(e.key.PubKey().Address().Bytes(), args.From.Bytes()) {
|
||||
|
||||
key, exist := checkKeyInKeyring(e.keys, args.From)
|
||||
if !exist {
|
||||
return common.Hash{}, keystore.ErrLocked
|
||||
}
|
||||
|
||||
@ -326,7 +341,7 @@ func (e *PublicEthAPI) SendTransaction(args params.SendTxArgs) (common.Hash, err
|
||||
}
|
||||
|
||||
// Sign transaction
|
||||
if err := tx.Sign(intChainID, e.key.ToECDSA()); err != nil {
|
||||
if err := tx.Sign(intChainID, key.ToECDSA()); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
|
||||
@ -429,9 +444,11 @@ func (e *PublicEthAPI) doCall(
|
||||
|
||||
// Set sender address or use a default if none specified
|
||||
var addr common.Address
|
||||
|
||||
if args.From == nil {
|
||||
if e.key != nil {
|
||||
addr = common.BytesToAddress(e.key.PubKey().Address().Bytes())
|
||||
key, exist := checkKeyInKeyring(e.keys, *args.From)
|
||||
if exist {
|
||||
addr = common.BytesToAddress(key.PubKey().Address().Bytes())
|
||||
}
|
||||
// No error handled here intentionally to match geth behaviour
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user