github.com/InjectiveLabs/sdk-go@v1.53.0/chain/crypto/hd/algorithm.go (about)

     1  package hd
     2  
     3  import (
     4  	"github.com/btcsuite/btcd/btcutil/hdkeychain"
     5  	"github.com/btcsuite/btcd/chaincfg"
     6  	"github.com/cosmos/cosmos-sdk/crypto/hd"
     7  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
     8  	ethaccounts "github.com/ethereum/go-ethereum/accounts"
     9  	ethcrypto "github.com/ethereum/go-ethereum/crypto"
    10  	"github.com/tyler-smith/go-bip39"
    11  
    12  	"github.com/cosmos/cosmos-sdk/crypto/keyring"
    13  
    14  	"github.com/InjectiveLabs/sdk-go/chain/crypto/ethsecp256k1"
    15  )
    16  
    17  const (
    18  	// EthSecp256k1Type defines the ECDSA secp256k1 used on Ethereum
    19  	EthSecp256k1Type = hd.PubKeyType(ethsecp256k1.KeyType)
    20  )
    21  
    22  var (
    23  	// SupportedAlgorithms defines the list of signing algorithms used on Ethermint:
    24  	//  - eth_secp256k1 (Ethereum)
    25  	//  - secp256k1 (Tendermint)
    26  	SupportedAlgorithms = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
    27  	// SupportedAlgorithmsLedger defines the list of signing algorithms used on Ethermint for the Ledger device:
    28  	//  - eth_secp256k1 (Ethereum)
    29  	//  - secp256k1 (Tendermint)
    30  	SupportedAlgorithmsLedger = keyring.SigningAlgoList{EthSecp256k1, hd.Secp256k1}
    31  )
    32  
    33  // EthSecp256k1Option defines a function keys options for the ethereum Secp256k1 curve.
    34  func EthSecp256k1Option() keyring.Option {
    35  	return func(options *keyring.Options) {
    36  		options.SupportedAlgos = SupportedAlgorithms
    37  		options.SupportedAlgosLedger = SupportedAlgorithmsLedger
    38  	}
    39  }
    40  
    41  var (
    42  	_ keyring.SignatureAlgo = EthSecp256k1
    43  
    44  	// EthSecp256k1 uses the Bitcoin secp256k1 ECDSA parameters.
    45  	EthSecp256k1 = ethSecp256k1Algo{}
    46  )
    47  
    48  type ethSecp256k1Algo struct {
    49  }
    50  
    51  // Name returns eth_secp256k1
    52  func (s ethSecp256k1Algo) Name() hd.PubKeyType {
    53  	return EthSecp256k1Type
    54  }
    55  
    56  // Derive derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
    57  func (s ethSecp256k1Algo) Derive() hd.DeriveFn {
    58  	return func(mnemonic string, bip39Passphrase, path string) ([]byte, error) {
    59  		hdpath, err := ethaccounts.ParseDerivationPath(path)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  
    64  		seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  
    69  		masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  
    74  		key := masterKey
    75  		// todo: Child method incompatible, see
    76  		// https://pkg.go.dev/github.com/btcsuite/btcd/btcutil/hdkeychain@v1.1.2#ExtendedKey.Derive:~:text=the%20given%20index.-,IMPORTANT,-%3A%20if%20you%20were
    77  		for _, n := range hdpath {
    78  			key, err = key.Derive(n)
    79  			if err != nil {
    80  				return nil, err
    81  			}
    82  		}
    83  
    84  		privateKey, err := key.ECPrivKey()
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  
    89  		privateKeyECDSA := privateKey.ToECDSA()
    90  		derivedKey := ethcrypto.FromECDSA(privateKeyECDSA)
    91  
    92  		return derivedKey, nil
    93  	}
    94  }
    95  
    96  // Generate generates a secp256k1 private key from the given bytes.
    97  func (s ethSecp256k1Algo) Generate() hd.GenerateFn {
    98  	return func(bz []byte) cryptotypes.PrivKey {
    99  		var bzArr = make([]byte, ethsecp256k1.PrivKeySize)
   100  		copy(bzArr, bz)
   101  
   102  		return &ethsecp256k1.PrivKey{Key: bzArr}
   103  	}
   104  }