Skip to content

Commit

Permalink
feat: update cosmos-sdk code for ledger-cosmos-go
Browse files Browse the repository at this point in the history
Inspired by cosmos#14661
  • Loading branch information
rootulp committed Oct 12, 2023
1 parent 3273d71 commit f21fce9
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
2 changes: 1 addition & 1 deletion crypto/keyring/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ func SignWithLedger(k *Record, msg []byte) (sig []byte, pub types.PubKey, err er
return
}

sig, err = priv.Sign(msg)
sig, err = priv.SignLedgerAminoJSON(msg)
if err != nil {
return nil, nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion crypto/ledger/ledger_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (mock LedgerSECP256K1Mock) GetAddressPubKeySECP256K1(derivationPath []uint3
return pk, addr, err
}

func (mock LedgerSECP256K1Mock) SignSECP256K1(derivationPath []uint32, message []byte) ([]byte, error) {
func (mock LedgerSECP256K1Mock) SignSECP256K1(derivationPath []uint32, message []byte, p2 byte) ([]byte, error) {
path := hd.NewParams(derivationPath[0], derivationPath[1], derivationPath[2], derivationPath[3] != 0, derivationPath[4])
seed, err := bip39.NewSeedWithErrorChecking(testdata.TestMnemonic, "")
if err != nil {
Expand Down
30 changes: 24 additions & 6 deletions crypto/ledger/ledger_secp256k1.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ type (
// Returns a compressed pubkey and bech32 address (requires user confirmation)
GetAddressPubKeySECP256K1([]uint32, string) ([]byte, string, error)
// Signs a message (requires user confirmation)
SignSECP256K1([]uint32, []byte) ([]byte, error)
// The last byte denotes the SIGN_MODE to be used by Ledger: 0 for
// LEGACY_AMINO_JSON, 1 for TEXTUAL. It corresponds to the P2 value
// in https://github.com/cosmos/ledger-cosmos/blob/main/docs/APDUSPEC.md
SignSECP256K1([]uint32, []byte, byte) ([]byte, error)
}

// PrivKeyLedgerSecp256k1 implements PrivKey, calling the ledger nano we
Expand All @@ -51,7 +54,7 @@ type (
// This function is marked as unsafe as it will retrieve a pubkey without user verification.
// It can only be used to verify a pubkey but never to create new accounts/keys. In that case,
// please refer to NewPrivKeySecp256k1
func NewPrivKeySecp256k1Unsafe(path hd.BIP44Params) (types.LedgerPrivKey, error) {
func NewPrivKeySecp256k1Unsafe(path hd.BIP44Params) (types.LedgerPrivKeyAminoJSON, error) {
device, err := getDevice()
if err != nil {
return nil, err
Expand Down Expand Up @@ -88,15 +91,28 @@ func (pkl PrivKeyLedgerSecp256k1) PubKey() types.PubKey {
return pkl.CachedPubKey
}

// Sign returns a secp256k1 signature for the corresponding message
// Sign returns a secp256k1 signature for the corresponding message using
// SIGN_MODE_TEXTUAL.
func (pkl PrivKeyLedgerSecp256k1) Sign(message []byte) ([]byte, error) {
device, err := getDevice()
if err != nil {
return nil, err
}
defer warnIfErrors(device.Close)

return sign(device, pkl, message)
return sign(device, pkl, message, 1)
}

// SignLedgerAminoJSON returns a secp256k1 signature for the corresponding message using
// SIGN_MODE_LEGACY_AMINO_JSON.
func (pkl PrivKeyLedgerSecp256k1) SignLedgerAminoJSON(message []byte) ([]byte, error) {
device, err := getDevice()
if err != nil {
return nil, err
}
defer warnIfErrors(device.Close)

return sign(device, pkl, message, 0)
}

// ShowAddress triggers a ledger device to show the corresponding address.
Expand Down Expand Up @@ -228,13 +244,15 @@ func validateKey(device SECP256K1, pkl PrivKeyLedgerSecp256k1) error {
// Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, returning
// an error, so this should only trigger if the private key is held in memory
// for a while before use.
func sign(device SECP256K1, pkl PrivKeyLedgerSecp256k1, msg []byte) ([]byte, error) {
//
// Last byte P2 is 0 for LEGACY_AMINO_JSON, and 1 for TEXTUAL.
func sign(device SECP256K1, pkl PrivKeyLedgerSecp256k1, msg []byte, p2 byte) ([]byte, error) {
err := validateKey(device, pkl)
if err != nil {
return nil, err
}

sig, err := device.SignSECP256K1(pkl.Path.DerivationPath(), msg)
sig, err := device.SignSECP256K1(pkl.Path.DerivationPath(), msg, p2)
if err != nil {
return nil, err
}
Expand Down
11 changes: 11 additions & 0 deletions crypto/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ type LedgerPrivKey interface {
Type() string
}

// LedgerPrivKeyAminoJSON is a Ledger PrivKey type that supports signing with
// SIGN_MODE_LEGACY_AMINO_JSON. It is added as a non-breaking change, instead of directly
// on the LedgerPrivKey interface (whose Sign method will sign with TEXTUAL),
// and will be deprecated/removed once LEGACY_AMINO_JSON is removed.
type LedgerPrivKeyAminoJSON interface {
LedgerPrivKey
// SignLedgerAminoJSON signs a messages on the Ledger device using
// SIGN_MODE_LEGACY_AMINO_JSON.
SignLedgerAminoJSON(msg []byte) ([]byte, error)
}

// PrivKey defines a private key and extends proto.Message. For now, it extends
// LedgerPrivKey (see godoc for LedgerPrivKey). Ultimately, we should remove
// LedgerPrivKey and add its methods here directly.
Expand Down

0 comments on commit f21fce9

Please sign in to comment.