Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 30 additions & 23 deletions relayer/chains/avalanche/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import (
"fmt"
"os"

"github.com/cometbft/cometbft/libs/bytes"
ckeys "github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/go-bip39"
"github.com/ethereum/go-ethereum/crypto"

Expand Down Expand Up @@ -41,7 +39,14 @@ func KeyringAlgoOptions() keyring.Option {

// CreateKeystore initializes a new instance of a keyring at the specified path in the local filesystem.
func (a *AvalancheProvider) CreateKeystore(_ string) error {
keybase, err := keyring.New(a.PCfg.ChainID, a.PCfg.KeyringBackend, a.PCfg.KeyDirectory, a.Input, a.Codec.Marshaler, KeyringAlgoOptions())
keybase, err := keyring.New(
a.PCfg.ChainID,
a.PCfg.KeyringBackend,
a.PCfg.KeyDirectory,
a.Input,
a.Codec.Marshaler,
a.KeyringOptions...,
)
if err != nil {
return err
}
Expand Down Expand Up @@ -110,33 +115,28 @@ func (a *AvalancheProvider) KeyAddOrRestore(keyName string, coinType uint32, mne
algo = keyring.SignatureAlgo(ethermint.EthSecp256k1)
}

info, err := a.Keybase.NewAccount(keyName, mnemonicStr, "", hd.CreateHDPath(coinType, 0, 0).String(), algo)
_, err = a.Keybase.NewAccount(
keyName,
mnemonicStr,
"",
hd.CreateHDPath(coinType, 0, 0).String(),
algo,
)
if err != nil {
return nil, err
}

acc, err := info.GetAddress()
out, err := a.EncodeAccAddr(keyName)
if err != nil {
return nil, err
}
out := a.EncodeAccAddr(acc)

return &provider.KeyOutput{Mnemonic: mnemonicStr, Address: out}, nil
}

// ShowAddress retrieves a key by name from the keystore and returns the bech32 encoded string representation of that key.
func (a *AvalancheProvider) ShowAddress(name string) (address string, err error) {
info, err := a.Keybase.Key(name)
if err != nil {
return "", err
}
acc, err := info.GetAddress()
if err != nil {
return "", nil
}
out := a.EncodeAccAddr(acc)

return out, nil
return a.EncodeAccAddr(name)
}

// ListAddresses returns a map of bech32 encoded strings representing all keys currently in the keystore.
Expand All @@ -147,12 +147,10 @@ func (a *AvalancheProvider) ListAddresses() (map[string]string, error) {
return nil, err
}
for _, k := range info {
acc, err := k.GetAddress()
addr, err := a.EncodeAccAddr(k.Name)
if err != nil {
return nil, err
}
addr := a.EncodeAccAddr(acc)

out[k.Name] = addr
}
return out, nil
Expand Down Expand Up @@ -198,8 +196,17 @@ func CreateMnemonic() (string, error) {
return mnemonic, nil
}

func (a *AvalancheProvider) EncodeAccAddr(addr sdk.AccAddress) string {
var data bytes.HexBytes = addr.Bytes()
// EncodeAccAddr returns the encoded string representation of the account address for the specified key.
func (a *AvalancheProvider) EncodeAccAddr(name string) (string, error) {
old := a.PCfg.Key // save the old key

a.PCfg.Key = name // set the key to the name of the key we want to get the address of
address, err := a.Address()
if err != nil {
return "", err
}

a.PCfg.Key = old // reset the key to the old key

return fmt.Sprintf("0x%s", data.String())
return fmt.Sprintf("%s", address), nil
}
12 changes: 6 additions & 6 deletions relayer/chains/avalanche/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/cosmos/relayer/v2/relayer/provider"
)

func testProviderWithKeystore(t *testing.T, extraCodecs []string) provider.ChainProvider {
func testProviderWithKeystore(t *testing.T) provider.ChainProvider {
homePath := t.TempDir()
cfg := avalanche.AvalancheProviderConfig{
ChainID: "test",
Expand All @@ -36,11 +36,11 @@ func TestKeyRestore(t *testing.T) {
keyName = "test_key"
signatureAlgorithm = "secp256k1"
mnemonic = "three elevator silk family street child flip also leaf inmate call frame shock little legal october vivid enable fetch siege sell burger dolphin green"
expectedAddress = "0x6E7BE67F3619731AB38875999873E8FACE935735"
coinType = uint32(60)
expectedAddress = "0x836E7e82deDE708Ba83ADe38216F5e30AC0fFB03"
coinType = uint32(118)
)

p := testProviderWithKeystore(t, []string{"ethermint"})
p := testProviderWithKeystore(t)

address, err := p.RestoreKey(keyName, mnemonic, coinType, signatureAlgorithm)
require.NoError(t, err)
Expand All @@ -54,10 +54,10 @@ func TestKeyRestorePrivateKey(t *testing.T) {
signatureAlgorithm = "secp256k1"
mnemonic = "56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027"
expectedAddress = "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
coinType = uint32(60)
coinType = uint32(118)
)

p := testProviderWithKeystore(t, []string{"ethermint"})
p := testProviderWithKeystore(t)

address, err := p.RestoreKey(keyName, mnemonic, coinType, signatureAlgorithm)
require.NoError(t, err)
Expand Down
71 changes: 56 additions & 15 deletions relayer/chains/avalanche/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package avalanche

import (
"context"
"crypto/ecdsa"
_ "embed"
"fmt"
"io"
Expand All @@ -18,6 +19,7 @@ import (
"github.com/ava-labs/subnet-evm/rpc"
"github.com/avast/retry-go/v4"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/gogoproto/proto"
ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported"
avalanche "github.com/cosmos/ibc-go/v8/modules/light-clients/14-avalanche"
Expand Down Expand Up @@ -69,7 +71,7 @@ func (h AvalancheIBCHeader) ConsensusState() ibcexported.ConsensusState {
Timestamp: time.Unix(int64(h.EthHeader.Time), 0),
StorageRoot: h.EthHeader.Root.Bytes(),
SignedStorageRoot: h.SignedStorageRoot[:],
//ValidatorSet: h.ValidatorSet,
// ValidatorSet: h.ValidatorSet,
SignedValidatorSet: h.SignedValidatorSet[:],
Vdrs: h.Vdrs,
SignersInput: h.SignersInput,
Expand Down Expand Up @@ -109,25 +111,35 @@ func (a *AvalancheProvider) Init(ctx context.Context) error {
a.ethClient = ethclient.NewClient(rpcClient)
a.subnetClient = subnetevmclient.New(rpcClient)
a.pClient = platformvm.NewClient(a.PCfg.BaseRPCAddr)
ibcClient, err := NewIbcClient(a.PCfg.RPCAddr)
a.ibcClient = ibcClient
a.ibcClient, err = NewIbcClient(a.PCfg.RPCAddr)
a.Keybase, err = keyring.New(
a.PCfg.ChainID,
a.PCfg.KeyringBackend,
a.PCfg.KeyDirectory,
a.Input,
a.Codec.Marshaler,
a.KeyringOptions...,
)
if err != nil {
return err
}

ethPrivKey, err := a.GetPrivKey(a.Key())
if err != nil {
ethPrivKey = tempKey
}

chainId, ok := new(big.Int).SetString(a.PCfg.ChainID, 10)
if !ok {
return fmt.Errorf("invalid chain id %s", a.PCfg.ChainID)
}

a.txAuth, err = bind.NewKeyedTransactorWithChainID(tempKey, chainId)
a.txAuth, err = bind.NewKeyedTransactorWithChainID(ethPrivKey, chainId)
a.txAuth.GasLimit = 1000000
if err != nil {
return err
}

keybase, err := keyring.New(a.PCfg.ChainID, a.PCfg.KeyringBackend, a.PCfg.KeyDirectory, a.Input, a.Codec.Marshaler, a.KeyringOptions...)
if err != nil {
return err
}

contractAbi, err := abi.JSON(strings.NewReader(ibccontract.IBCABI))
if err != nil {
return err
Expand All @@ -148,7 +160,6 @@ func (a *AvalancheProvider) Init(ctx context.Context) error {
return err
}

a.Keybase = keybase
a.abi = contractAbi
a.subnetID = subnetID
a.blockchainID = blockchainID
Expand All @@ -157,6 +168,35 @@ func (a *AvalancheProvider) Init(ctx context.Context) error {
return nil
}

// GetPrivKey extracts a private key from a keyring record
func (a AvalancheProvider) GetPrivKey(name string) (*ecdsa.PrivateKey, error) {
info, err := a.Keybase.Key(name)
if err != nil {
return nil, err
}

local := info.GetLocal()
if local == nil {
return nil, fmt.Errorf("key is not a local key")
}

if local.PrivKey == nil {
return nil, fmt.Errorf("private key not available in record")
}

priv, ok := local.PrivKey.GetCachedValue().(cryptotypes.PrivKey)
if !ok {
return nil, fmt.Errorf("failed to cast private key to cryptotypes.PrivKey")
}

ethPrivKey, err := crypto.ToECDSA(priv.Bytes())
if err != nil {
return nil, fmt.Errorf("failed to convert private key to ECDSA: %w", err)
}

return ethPrivKey, nil
}

func (a AvalancheProvider) SetRpcAddr(rpcAddr string) error {
// TODO implement me
panic("implement me")
Expand Down Expand Up @@ -188,16 +228,17 @@ func (a AvalancheProvider) Key() string {
}

func (a AvalancheProvider) Address() (string, error) {
info, err := a.Keybase.Key(a.PCfg.Key)
ethPrivKey, err := a.GetPrivKey(a.Key())
if err != nil {
return "", err
}

acc, err := info.GetAddress()
if err != nil {
return "", err
publicKeyECDSA, ok := ethPrivKey.Public().(*ecdsa.PublicKey)
if !ok {
return "", fmt.Errorf("error casting public key to ECDSA")
}
out := a.EncodeAccAddr(acc)

out := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()

return out, nil
}
Expand Down
Loading