github.com/Finschia/finschia-sdk@v0.48.1/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 "fmt" 8 9 "github.com/btcsuite/btcd/btcec" 10 "github.com/pkg/errors" 11 12 "github.com/cosmos/go-bip39" 13 secp256k1 "github.com/tendermint/btcd/btcec" 14 15 "github.com/Finschia/ostracon/crypto" 16 17 "github.com/Finschia/finschia-sdk/crypto/hd" 18 csecp256k1 "github.com/Finschia/finschia-sdk/crypto/keys/secp256k1" 19 "github.com/Finschia/finschia-sdk/testutil/testdata" 20 sdk "github.com/Finschia/finschia-sdk/types" 21 ) 22 23 // If ledger support (build tag) has been enabled, which implies a CGO dependency, 24 // set the discoverLedger function which is responsible for loading the Ledger 25 // device at runtime or returning an error. 26 func init() { 27 discoverLedger = func() (SECP256K1, error) { 28 return LedgerSECP256K1Mock{}, nil 29 } 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 := secp256k1.PrivKeyFromBytes(secp256k1.S256(), derivedPriv[:]) 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 := btcec.ParsePubKey(pk[:], btcec.S256()) 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 occrypto/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, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), derivedPriv[:]) 103 104 sig, err := priv.Sign(crypto.Sha256(message)) 105 if err != nil { 106 return nil, err 107 } 108 109 // Need to return DER as the ledger does 110 sig2 := btcec.Signature{R: sig.R, S: sig.S} 111 return sig2.Serialize(), nil 112 } 113 114 // ShowAddressSECP256K1 shows the address for the corresponding bip32 derivation path 115 func (mock LedgerSECP256K1Mock) ShowAddressSECP256K1(bip32Path []uint32, hrp string) error { 116 fmt.Printf("Request to show address for %v at %v", hrp, bip32Path) 117 return nil 118 }