github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/crypto/hd/algorithm.go (about)

     1  package hd
     2  
     3  import (
     4  	"github.com/pkg/errors"
     5  
     6  	"github.com/btcsuite/btcd/chaincfg"
     7  	"github.com/btcsuite/btcutil/hdkeychain"
     8  	"github.com/tyler-smith/go-bip39"
     9  
    10  	ethaccounts "github.com/ethereum/go-ethereum/accounts"
    11  	ethcrypto "github.com/ethereum/go-ethereum/crypto"
    12  
    13  	tmcrypto "github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
    14  
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys"
    16  
    17  	"github.com/fibonacci-chain/fbc/app/crypto/ethsecp256k1"
    18  )
    19  
    20  const (
    21  	// EthSecp256k1 defines the ECDSA secp256k1 used on Ethereum
    22  	EthSecp256k1 = keys.SigningAlgo(ethsecp256k1.KeyType)
    23  )
    24  
    25  // SupportedAlgorithms defines the list of signing algorithms used on Ethermint:
    26  //   - eth_secp256k1 (Ethereum)
    27  //   - secp256k1 (Tendermint)
    28  var SupportedAlgorithms = []keys.SigningAlgo{EthSecp256k1, keys.Secp256k1}
    29  
    30  // EthSecp256k1Options defines a keys options for the ethereum Secp256k1 curve.
    31  func EthSecp256k1Options() []keys.KeybaseOption {
    32  	return []keys.KeybaseOption{
    33  		keys.WithKeygenFunc(EthermintKeygenFunc),
    34  		keys.WithDeriveFunc(DeriveKey),
    35  		keys.WithSupportedAlgos(SupportedAlgorithms),
    36  		keys.WithSupportedAlgosLedger(SupportedAlgorithms),
    37  	}
    38  }
    39  
    40  func DeriveKey(mnemonic, bip39Passphrase, hdPath string, algo keys.SigningAlgo) ([]byte, error) {
    41  	switch algo {
    42  	case keys.Secp256k1:
    43  		return keys.StdDeriveKey(mnemonic, bip39Passphrase, hdPath, algo)
    44  	case EthSecp256k1:
    45  		return DeriveSecp256k1(mnemonic, bip39Passphrase, hdPath)
    46  	default:
    47  		return nil, errors.Wrap(keys.ErrUnsupportedSigningAlgo, string(algo))
    48  	}
    49  }
    50  
    51  // EthermintKeygenFunc is the key generation function to generate secp256k1.
    52  func EthermintKeygenFunc(bz []byte, algo keys.SigningAlgo) (tmcrypto.PrivKey, error) {
    53  	switch algo {
    54  	case keys.Secp256k1:
    55  		return keys.StdPrivKeyGen(bz, algo)
    56  	case EthSecp256k1:
    57  		return ethsecp256k1.PrivKey(bz), nil
    58  	default:
    59  		return nil, errors.Wrap(keys.ErrUnsupportedSigningAlgo, string(algo))
    60  	}
    61  }
    62  
    63  // DeriveSecp256k1 derives and returns the eth_secp256k1 private key for the given mnemonic and HD path.
    64  func DeriveSecp256k1(mnemonic, bip39Passphrase, path string) ([]byte, error) {
    65  	hdpath, err := ethaccounts.ParseDerivationPath(path)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	key := masterKey
    81  	for _, n := range hdpath {
    82  		key, err = key.Derive(n)
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  	}
    87  
    88  	privateKey, err := key.ECPrivKey()
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	privateKeyECDSA := privateKey.ToECDSA()
    94  	derivedKey := ethsecp256k1.PrivKey(ethcrypto.FromECDSA(privateKeyECDSA))
    95  	return derivedKey, nil
    96  }