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 }