diff --git a/cli/yarn.lock b/cli/yarn.lock index 94aad86a71..be683a9990 100644 --- a/cli/yarn.lock +++ b/cli/yarn.lock @@ -329,19 +329,6 @@ axios "^0.21.1" fast-deep-equal "^3.1.3" -"@cosmjs/ledger-amino@^0.26.5": - version "0.26.6" - resolved "https://registry.yarnpkg.com/@cosmjs/ledger-amino/-/ledger-amino-0.26.6.tgz#4fd342229f3de3059e193f8db3f88877074aabe0" - integrity sha512-L5KDfEq7EswV4ku2SbWlozfKVv9WJWtap4/7SMXKH0XrYWOIz0AYeBfM0OGtJQjuHAiD/1QJ8pam/kjUL3+quQ== - dependencies: - "@cosmjs/amino" "0.26.6" - "@cosmjs/crypto" "0.26.6" - "@cosmjs/encoding" "0.26.6" - "@cosmjs/math" "0.26.6" - "@cosmjs/utils" "0.26.6" - ledger-cosmos-js "^2.1.8" - semver "^7.3.2" - "@cosmjs/math@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.23.1.tgz#706f38742a9a1f6561cf2c4510f8e5ab001fc5e6" @@ -1062,7 +1049,7 @@ "@ledgerhq/errors" "^6.10.0" events "^3.3.0" -"@ledgerhq/hw-transport@^5.11.0", "@ledgerhq/hw-transport@^5.19.1", "@ledgerhq/hw-transport@^5.25.0", "@ledgerhq/hw-transport@^5.51.1": +"@ledgerhq/hw-transport@^5.11.0", "@ledgerhq/hw-transport@^5.19.1", "@ledgerhq/hw-transport@^5.51.1": version "5.51.1" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz#8dd14a8e58cbee4df0c29eaeef983a79f5f22578" integrity sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw== @@ -1095,16 +1082,13 @@ bignumber.js "^9.0.1" json-rpc-2.0 "^0.2.16" -"@ledgerhq/live-common@22.0.0": +"@ledgerhq/live-common@file:.yalc/@ledgerhq/live-common": version "22.0.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-22.0.0.tgz#2717701fc8ba63b4befdd3cb1400527c2922335f" - integrity sha512-BUMgPMWmavlFip0LwMVzr+TABG1o77nLZepGSmxZWIcyLUvsmRRDtCEasVJCW60g0Cd0BhvbtUOo8l0NdDZ+/A== dependencies: "@celo/contractkit" "^1.5.2" "@celo/wallet-base" "^1.5.2" "@celo/wallet-ledger" "^1.5.2" "@cosmjs/crypto" "^0.26.5" - "@cosmjs/ledger-amino" "^0.26.5" "@cosmjs/proto-signing" "^0.26.5" "@cosmjs/stargate" "^0.26.5" "@crypto-com/chain-jslib" "0.0.19" @@ -4855,16 +4839,6 @@ leb128@^0.0.5: bn.js "^5.0.0" buffer-pipe "0.0.3" -ledger-cosmos-js@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/ledger-cosmos-js/-/ledger-cosmos-js-2.1.8.tgz#b409ecd1e77f630e6fb212a9f602fe5c6e8f054b" - integrity sha512-Gl7SWMq+3R9OTkF1hLlg5+1geGOmcHX9OdS+INDsGNxSiKRWlsWCvQipGoDnRIQ6CPo2i/Ze58Dw0Mt/l3UYyA== - dependencies: - "@babel/runtime" "^7.11.2" - "@ledgerhq/hw-transport" "^5.25.0" - bech32 "^1.1.4" - ripemd160 "^2.0.2" - libsodium-wrappers@^0.7.6: version "0.7.9" resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.9.tgz#4ffc2b69b8f7c7c7c5594a93a4803f80f6d0f346" diff --git a/package.json b/package.json index ed30cd6f6b..43516f7775 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "@celo/wallet-base": "^1.5.2", "@celo/wallet-ledger": "^1.5.2", "@cosmjs/crypto": "^0.26.5", - "@cosmjs/ledger-amino": "^0.26.5", "@cosmjs/proto-signing": "^0.26.5", "@cosmjs/stargate": "^0.26.5", "@crypto-com/chain-jslib": "0.0.19", diff --git a/src/families/cosmos/js-prepareTransaction.ts b/src/families/cosmos/js-prepareTransaction.ts index 95657d5013..f7310eb413 100644 --- a/src/families/cosmos/js-prepareTransaction.ts +++ b/src/families/cosmos/js-prepareTransaction.ts @@ -2,7 +2,6 @@ import { Account } from "../../types"; import { Transaction } from "./types"; import BigNumber from "bignumber.js"; import { simulate } from "./api/Cosmos"; -import { encodePubkey } from "@cosmjs/proto-signing"; import { getEnv } from "../../env"; import { buildTransaction, postBuildTransaction } from "./js-buildTransaction"; import { getMaxEstimatedBalance } from "./logic"; @@ -50,10 +49,13 @@ const getEstimatedFees = async ( // be sure payload is complete if (unsignedPayload) { - const pubkey = encodePubkey({ - type: "tendermint/PubKeySecp256k1", - value: Buffer.from(account.seedIdentifier, "hex").toString("base64"), - }); + const pubkey = { + typeUrl: "/cosmos.crypto.secp256k1.PubKey", + value: new Uint8Array([ + ...new Uint8Array([10, 33]), + ...new Uint8Array(Buffer.from(account.seedIdentifier, "hex")), + ]), + }; const tx_bytes = await postBuildTransaction( account, diff --git a/src/families/cosmos/js-signOperation.ts b/src/families/cosmos/js-signOperation.ts index dba1960f55..ab0cf93d6b 100644 --- a/src/families/cosmos/js-signOperation.ts +++ b/src/families/cosmos/js-signOperation.ts @@ -8,13 +8,12 @@ import type { Transaction } from "./types"; import { getAccount, getChainId } from "./api/Cosmos"; import { Observable } from "rxjs"; import { withDevice } from "../../hw/deviceAccess"; -import { encodePubkey } from "@cosmjs/proto-signing"; import { encodeOperationId } from "../../operation"; -import { LedgerSigner } from "@cosmjs/ledger-amino"; +import Cosmos from "@ledgerhq/hw-app-cosmos"; import { AminoTypes } from "@cosmjs/stargate"; -import { stringToPath } from "@cosmjs/crypto"; import { buildTransaction, postBuildTransaction } from "./js-buildTransaction"; import BigNumber from "bignumber.js"; +import { Secp256k1Signature } from "@cosmjs/crypto"; const aminoTypes = new AminoTypes({ prefix: "cosmos" }); @@ -32,52 +31,39 @@ const signOperation = ({ let cancelled; async function main() { + const hwApp = new Cosmos(transport); + const { accountNumber, sequence } = await getAccount( account.freshAddress ); const chainId = await getChainId(); - const hdPaths: any = stringToPath("m/" + account.freshAddressPath); - - const ledgerSigner = new LedgerSigner(transport, { - hdPaths: [hdPaths], - }); - o.next({ type: "device-signature-requested" }); - const accounts = await ledgerSigner.getAccounts(); - - let pubkey; + const { publicKey } = await hwApp.getAddress( + account.freshAddressPath, + "cosmos", + false + ); - accounts.forEach((a) => { - if (a.address == account.freshAddress) { - pubkey = encodePubkey({ - type: "tendermint/PubKeySecp256k1", - value: Buffer.from(a.pubkey).toString("base64"), - }); - } - }); + const pubkey = { + typeUrl: "/cosmos.crypto.secp256k1.PubKey", + value: new Uint8Array([ + ...new Uint8Array([10, 33]), + ...new Uint8Array(Buffer.from(publicKey, "hex")), + ]), + }; const unsignedPayload = await buildTransaction(account, transaction); const msgs = unsignedPayload.map((msg) => aminoTypes.toAmino(msg)); // Note: - // We don't use Cosmos App, - // Cosmos App support legacy StdTx and required to be ordered in a strict way, - // Cosmos API expects a different sorting, resulting in a separate signature. - // https://github.com/LedgerHQ/app-cosmos/blob/6c194daa28936e273f9548eabca9e72ba04bb632/app/src/tx_parser.c#L52 - - // Cosmos App sign data in Amino way only, not Protobuf. + // Cosmos Nano App sign data in Amino way only, not Protobuf. // This is a legacy outdated standard and a long-term blocking point. - // @ledgerhq/hw-app-cosmos don't allow to push message to device message converted - // by the AminoConverter from @cosmjs/stargate. There's two things who don't work: - // 1st, the way who message is sorted. - // 2nd, cast of numeric value (integer/numeric versus string). - - const signed = await ledgerSigner.signAmino(account.freshAddress, { + const message = { chain_id: chainId, account_number: accountNumber.toString(), sequence: sequence.toString(), @@ -92,17 +78,30 @@ const signOperation = ({ }, msgs: msgs, memo: transaction.memo || "", - }); + }; + + const { signature } = await hwApp.sign( + account.freshAddressPath, + JSON.stringify(sortedObject(message)) + ); + + if (!signature) { + throw new Error("Cosmos: no Signature Found"); + } + + const secp256k1Signature = Secp256k1Signature.fromDer( + new Uint8Array(signature) + ).toFixedLength(); const tx_bytes = await postBuildTransaction( account, transaction, pubkey, unsignedPayload, - new Uint8Array(Buffer.from(signed.signature.signature, "base64")) + secp256k1Signature ); - const signature = Buffer.from(tx_bytes).toString("hex"); + const signed = Buffer.from(tx_bytes).toString("hex"); if (cancelled) { return; @@ -169,7 +168,7 @@ const signOperation = ({ type: "signed", signedOperation: { operation, - signature, + signature: signed, expirationDate: null, }, }); @@ -186,4 +185,23 @@ const signOperation = ({ }) ); +const sortedObject = (obj) => { + if (typeof obj !== "object" || obj === null) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map(sortedObject); + } + + const sortedKeys = Object.keys(obj).sort(); + const result = {}; + + sortedKeys.forEach((key) => { + result[key] = sortedObject(obj[key]); + }); + + return result; +}; + export default signOperation; diff --git a/yarn.lock b/yarn.lock index 513a128fc5..8f3e5f065b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -614,19 +614,6 @@ axios "^0.21.1" fast-deep-equal "^3.1.3" -"@cosmjs/ledger-amino@^0.26.5": - version "0.26.6" - resolved "https://registry.yarnpkg.com/@cosmjs/ledger-amino/-/ledger-amino-0.26.6.tgz#4fd342229f3de3059e193f8db3f88877074aabe0" - integrity sha512-L5KDfEq7EswV4ku2SbWlozfKVv9WJWtap4/7SMXKH0XrYWOIz0AYeBfM0OGtJQjuHAiD/1QJ8pam/kjUL3+quQ== - dependencies: - "@cosmjs/amino" "0.26.6" - "@cosmjs/crypto" "0.26.6" - "@cosmjs/encoding" "0.26.6" - "@cosmjs/math" "0.26.6" - "@cosmjs/utils" "0.26.6" - ledger-cosmos-js "^2.1.8" - semver "^7.3.2" - "@cosmjs/math@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.23.1.tgz#706f38742a9a1f6561cf2c4510f8e5ab001fc5e6"