Skip to content
This repository has been archived by the owner on Jul 15, 2022. It is now read-only.

LIVE-1839 Use @ledgerhq/hw-app-cosmos instead of @cosmjs/LedgerSigner #1913

Merged
3 commits merged into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 2 additions & 28 deletions cli/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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==
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 7 additions & 5 deletions src/families/cosmos/js-prepareTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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,
Expand Down
90 changes: 54 additions & 36 deletions src/families/cosmos/js-signOperation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" });

Expand All @@ -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(),
Expand All @@ -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;
Expand Down Expand Up @@ -169,7 +168,7 @@ const signOperation = ({
type: "signed",
signedOperation: {
operation,
signature,
signature: signed,
expirationDate: null,
},
});
Expand All @@ -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;
13 changes: 0 additions & 13 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down