github.com/cosmos/cosmos-sdk@v0.50.10/crypto/ledger/ledger_mock.go (about)

     1  //go:build ledger && test_ledger_mock
     2  // +build ledger,test_ledger_mock
     3  
     4  package ledger
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  
    10  	"github.com/cometbft/cometbft/crypto"
    11  	"github.com/cosmos/go-bip39"
    12  	secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
    13  	"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
    14  
    15  	"github.com/cosmos/cosmos-sdk/crypto/hd"
    16  	csecp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
    17  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    18  	sdk "github.com/cosmos/cosmos-sdk/types"
    19  )
    20  
    21  // If ledger support (build tag) has been enabled, which implies a CGO dependency,
    22  // set the discoverLedger function which is responsible for loading the Ledger
    23  // device at runtime or returning an error.
    24  func init() {
    25  	options.discoverLedger = func() (SECP256K1, error) {
    26  		return LedgerSECP256K1Mock{}, nil
    27  	}
    28  
    29  	initOptionsDefault()
    30  }
    31  
    32  type LedgerSECP256K1Mock struct{}
    33  
    34  func (mock LedgerSECP256K1Mock) Close() error {
    35  	return nil
    36  }
    37  
    38  // GetPublicKeySECP256K1 mocks a ledger device
    39  // as per the original API, it returns an uncompressed key
    40  func (mock LedgerSECP256K1Mock) GetPublicKeySECP256K1(derivationPath []uint32) ([]byte, error) {
    41  	if derivationPath[0] != 44 {
    42  		return nil, errors.New("invalid derivation path")
    43  	}
    44  
    45  	if derivationPath[1] != sdk.GetConfig().GetCoinType() {
    46  		return nil, errors.New("invalid derivation path")
    47  	}
    48  
    49  	seed, err := bip39.NewSeedWithErrorChecking(testdata.TestMnemonic, "")
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	path := hd.NewParams(derivationPath[0], derivationPath[1], derivationPath[2], derivationPath[3] != 0, derivationPath[4])
    55  	masterPriv, ch := hd.ComputeMastersFromSeed(seed)
    56  	derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, path.String())
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	pubkeyObject := secp.PrivKeyFromBytes(derivedPriv).PubKey()
    62  
    63  	return pubkeyObject.SerializeUncompressed(), nil
    64  }
    65  
    66  // GetAddressPubKeySECP256K1 mocks a ledger device
    67  // as per the original API, it returns a compressed key and a bech32 address
    68  func (mock LedgerSECP256K1Mock) GetAddressPubKeySECP256K1(derivationPath []uint32, hrp string) ([]byte, string, error) {
    69  	pk, err := mock.GetPublicKeySECP256K1(derivationPath)
    70  	if err != nil {
    71  		return nil, "", err
    72  	}
    73  
    74  	// re-serialize in the 33-byte compressed format
    75  	cmp, err := secp.ParsePubKey(pk)
    76  	if err != nil {
    77  		return nil, "", fmt.Errorf("error parsing public key: %v", err)
    78  	}
    79  
    80  	compressedPublicKey := make([]byte, csecp256k1.PubKeySize)
    81  	copy(compressedPublicKey, cmp.SerializeCompressed())
    82  
    83  	// Generate the bech32 addr using existing cmtcrypto/etc.
    84  	pub := &csecp256k1.PubKey{Key: compressedPublicKey}
    85  	addr := sdk.AccAddress(pub.Address()).String()
    86  	return pk, addr, err
    87  }
    88  
    89  func (mock LedgerSECP256K1Mock) SignSECP256K1(derivationPath []uint32, message []byte, p2 byte) ([]byte, error) {
    90  	path := hd.NewParams(derivationPath[0], derivationPath[1], derivationPath[2], derivationPath[3] != 0, derivationPath[4])
    91  	seed, err := bip39.NewSeedWithErrorChecking(testdata.TestMnemonic, "")
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  
    96  	masterPriv, ch := hd.ComputeMastersFromSeed(seed)
    97  	derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, path.String())
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	priv := secp.PrivKeyFromBytes(derivedPriv)
   103  	sig := ecdsa.Sign(priv, crypto.Sha256(message))
   104  
   105  	return sig.Serialize(), nil
   106  }
   107  
   108  // ShowAddressSECP256K1 shows the address for the corresponding bip32 derivation path
   109  func (mock LedgerSECP256K1Mock) ShowAddressSECP256K1(bip32Path []uint32, hrp string) error {
   110  	fmt.Printf("Request to show address for %v at %v", hrp, bip32Path)
   111  	return nil
   112  }