Skip to content

Commit

Permalink
improving backwards compatibility support
Browse files Browse the repository at this point in the history
  • Loading branch information
jleni committed Nov 17, 2019
1 parent 824116c commit 007384f
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const APP_KEY = "CSM";

export const INS = {
GET_VERSION: 0x00,
INS_PUBLIC_KEY_SECP256K1: 0x01, // Obsolete
SIGN_SECP256K1: 0x02,
GET_ADDR_SECP256K1: 0x04,
};
Expand Down
25 changes: 25 additions & 0 deletions src/helperV1.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,28 @@ export async function signSendChunkv1(app, chunkIdx, chunkNum, chunk) {
};
}, processErrorResponse);
}

function compressPublicKey(publicKey) {
if (publicKey.length !== 65) {
throw new Error("decompressed public key length should be 65 bytes");
}
const y = publicKey.slice(33, 65);
// eslint-disable-next-line no-bitwise
const z = Buffer.from([2 + (y[y.length - 1] & 1)]);
return Buffer.concat([z, publicKey.slice(1, 33)]);
}

export async function publicKeyv1(app, data) {
return app.transport.send(CLA, INS.INS_PUBLIC_KEY_SECP256K1, 0, 0, data, [0x9000]).then(response => {
const errorCodeData = response.slice(-2);
const returnCode = errorCodeData[0] * 256 + errorCodeData[1];
const pk = Buffer.from(response.slice(0, 65));

return {
pk,
compressed_pk: compressPublicKey(pk),
return_code: returnCode,
error_message: errorCodeToString(returnCode),
};
}, processErrorResponse);
}
17 changes: 16 additions & 1 deletion src/helperV2.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { signSendChunkv1 } from "./helperV1";
import { PAYLOAD_TYPE } from "./common";
import { CLA, errorCodeToString, INS, PAYLOAD_TYPE, processErrorResponse } from "./common";

export function serializePathv2(path) {
if (!path || path.length !== 5) {
Expand Down Expand Up @@ -27,3 +27,18 @@ export async function signSendChunkv2(app, chunkIdx, chunkNum, chunk) {

return signSendChunkv1(app, payloadType, 0, chunk);
}

export async function publicKeyv2(app, data) {
return this.transport.send(CLA, INS.GET_ADDR_SECP256K1, 0, 0, data, [0x9000]).then(response => {
const errorCodeData = response.slice(-2);
const returnCode = errorCodeData[0] * 256 + errorCodeData[1];
const compressedPk = Buffer.from(response.slice(0, 33));

return {
pk: "OBSOLETE PROPERTY",
compressed_pk: compressedPk,
return_code: returnCode,
error_message: errorCodeToString(returnCode),
};
}, processErrorResponse);
}
29 changes: 15 additions & 14 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import crypto from "crypto";
import Ripemd160 from "ripemd160";
import bech32 from "bech32";
import { serializePathv1, signSendChunkv1 } from "./helperV1";
import { serializePathv2, signSendChunkv2 } from "./helperV2";
import { publicKeyv1, serializePathv1, signSendChunkv1 } from "./helperV1";
import { publicKeyv2, serializePathv2, signSendChunkv2 } from "./helperV2";
import { APP_KEY, CHUNK_SIZE, CLA, INS, errorCodeToString, getVersion, processErrorResponse } from "./common";

export default class CosmosApp {
Expand Down Expand Up @@ -194,19 +194,20 @@ export default class CosmosApp {

async publicKey(path) {
const serializedPath = await this.serializePath(path);
const data = Buffer.concat([CosmosApp.serializeHRP("cosmos"), serializedPath]);
return this.transport.send(CLA, INS.GET_ADDR_SECP256K1, 0, 0, data, [0x9000]).then(response => {
const errorCodeData = response.slice(-2);
const returnCode = errorCodeData[0] * 256 + errorCodeData[1];
const compressedPk = Buffer.from(response.slice(0, 33));

return {
pk: "OBSOLETE PROPERTY",
compressed_pk: compressedPk,
return_code: returnCode,
error_message: errorCodeToString(returnCode),
};
}, processErrorResponse);
switch (this.versionResponse.major) {
case 1:
return publicKeyv1(this, serializedPath);
case 2: {
const data = Buffer.concat([CosmosApp.serializeHRP("cosmos"), serializedPath]);
return publicKeyv2(this, data);
}
default:
return {
return_code: 0x6400,
error_message: "App Version is not supported",
};
}
}

async getAddressAndPubKey(path, hrp) {
Expand Down
29 changes: 26 additions & 3 deletions tests/basic.ispec.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,19 @@ test("sign_big_tx", async () => {
expect(responsePk.return_code).toEqual(0x9000);
expect(responsePk.error_message).toEqual("No errors");
expect(responseSign.return_code).toEqual(0x6a80);
expect(responseSign.error_message).toEqual("NOMEM: JSON string contains too many tokens");

switch (app.versionResponse.major) {
case 1:
expect(responseSign.error_message).toEqual(
"Bad key handle : NOMEM: JSON string contains too many tokens",
);
break;
case 2:
expect(responseSign.error_message).toEqual("NOMEM: JSON string contains too many tokens");
break;
default:
expect.fail("Version not supported");
}
});

test("sign_invalid", async () => {
Expand All @@ -234,6 +246,17 @@ test("sign_invalid", async () => {
const responseSign = await app.sign(path, invalidMessage);

console.log(responseSign);
expect(responseSign.return_code).toEqual(0x6984);
expect(responseSign.error_message).toEqual("Data is invalid : JSON Missing account number");

switch (app.versionResponse.major) {
case 1:
expect(responseSign.return_code).toEqual(0x6a80);
expect(responseSign.error_message).toEqual("Bad key handle : JSON Missing account_number");
break;
case 2:
expect(responseSign.return_code).toEqual(0x6984);
expect(responseSign.error_message).toEqual("Data is invalid : JSON Missing account number");
break;
default:
expect.fail("Version not supported");
}
});

0 comments on commit 007384f

Please sign in to comment.