Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix fail amino sign verify with special chars #1373

Merged
merged 1 commit into from
Mar 9, 2023
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
14 changes: 12 additions & 2 deletions packages/amino/src/signdoc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Random } from "@cosmjs/crypto";
import { toBech32 } from "@cosmjs/encoding";
import { fromUtf8, toBech32, toUtf8 } from "@cosmjs/encoding";

import { AminoMsg, makeSignDoc, sortedJsonStringify } from "./signdoc";
import { AminoMsg, escapeCharacters, makeSignDoc, sortedJsonStringify } from "./signdoc";

function makeRandomAddress(): string {
return toBech32("cosmos", Random.getBytes(20));
Expand Down Expand Up @@ -132,4 +132,14 @@ describe("encoding", () => {
});
});
});

describe("escape characters after utf8 encoding", () => {
it("works", () => {
const test = JSON.stringify({ memo: "ampersand:&,lt:<,gt:>" });
const utf8Encoding = toUtf8(test);
const escapedEncoding = escapeCharacters(utf8Encoding);

expect(JSON.parse(fromUtf8(utf8Encoding))).toEqual(JSON.parse(fromUtf8(escapedEncoding)));
});
});
});
31 changes: 30 additions & 1 deletion packages/amino/src/signdoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,35 @@ export function makeSignDoc(
};
}

export function escapeCharacters(encodedArray: Uint8Array): Uint8Array {
const AmpersandUnicode = new Uint8Array([92, 117, 48, 48, 50, 54]);
const LtSignUnicode = new Uint8Array([92, 117, 48, 48, 51, 99]);
const GtSignUnicode = new Uint8Array([92, 117, 48, 48, 51, 101]);

const AmpersandAscii = 38;
const LtSign = 60; // <
const GtSign = 62; // >

const filteredIndex: number[] = [];
encodedArray.forEach((value, index) => {
if (value === AmpersandAscii || value === LtSign || value === GtSign) filteredIndex.push(index);
});

let result = new Uint8Array([...encodedArray]);
const reversedFilteredIndex = filteredIndex.reverse();
reversedFilteredIndex.forEach((value) => {
let unicode = AmpersandUnicode;
if (result[value] === LtSign) {
unicode = LtSignUnicode;
} else if (result[value] === GtSign) {
unicode = GtSignUnicode;
}
result = new Uint8Array([...result.slice(0, value), ...unicode, ...result.slice(value + 1)]);
});

return result;
}

export function serializeSignDoc(signDoc: StdSignDoc): Uint8Array {
return toUtf8(sortedJsonStringify(signDoc));
return escapeCharacters(toUtf8(sortedJsonStringify(signDoc)));
}
27 changes: 27 additions & 0 deletions packages/stargate/src/signingstargateclient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,33 @@ describe("SigningStargateClient", () => {
});

describe("legacy Amino mode", () => {
it("works with special characters in memo", async () => {
pendingWithoutSimapp();
const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const client = await SigningStargateClient.connectWithSigner(
simapp.tendermintUrl,
wallet,
defaultSigningClientOptions,
);

const msgSend: MsgSend = {
fromAddress: faucet.address0,
toAddress: makeRandomAddress(),
amount: coins(1234, "ucosm"),
};
const msgAny: MsgSendEncodeObject = {
typeUrl: "/cosmos.bank.v1beta1.MsgSend",
value: msgSend,
};
const fee = {
amount: coins(2000, "ucosm"),
gas: "200000",
};
const memo = "ampersand:&,lt:<,gt:>";
const result = await client.signAndBroadcast(faucet.address0, [msgAny], fee, memo);
assertIsDeliverTxSuccess(result);
});

it("works with bank MsgSend", async () => {
pendingWithoutSimapp();
const wallet = await Secp256k1HdWallet.fromMnemonic(faucet.mnemonic);
Expand Down