Extract encodeSecp256k1Signature

This commit is contained in:
Simon Warta 2020-02-04 12:43:25 +01:00
parent a9189262e5
commit cd66935dce
8 changed files with 93 additions and 28 deletions

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/camelcase */
import { types } from "@cosmwasm/sdk";
import { encodeSecp256k1Signature, types } from "@cosmwasm/sdk";
import {
Algorithm,
Amount,
@ -10,7 +10,6 @@ import {
SignedTransaction,
UnsignedTransaction,
} from "@iov/bcp";
import { Secp256k1 } from "@iov/crypto";
import { Decimal, Encoding } from "@iov/encoding";
import { TokenInfos } from "./types";
@ -72,14 +71,12 @@ export function encodeFee(fee: Fee, tokens: TokenInfos): types.StdFee {
}
export function encodeFullSignature(fullSignature: FullSignature): types.StdSignature {
return {
pub_key: {
type: "tendermint/PubKeySecp256k1",
value: toBase64(Secp256k1.compressPubkey(fullSignature.pubkey.data)),
},
// Recovery seems to be unused
signature: toBase64(Secp256k1.trimRecoveryByte(fullSignature.signature)),
};
switch (fullSignature.pubkey.algo) {
case Algorithm.Secp256k1:
return encodeSecp256k1Signature(fullSignature.pubkey.data, fullSignature.signature);
default:
throw new Error("Unsupported signing algorithm");
}
}
export function buildUnsignedTx(tx: UnsignedTransaction, tokens: TokenInfos): types.AminoTx {

View File

@ -38,6 +38,7 @@
"pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js"
},
"dependencies": {
"@iov/crypto": "^2.0.0-alpha.7",
"@iov/encoding": "^2.0.0-alpha.7",
"axios": "^0.19.0"
},

View File

@ -0,0 +1,59 @@
import { Encoding } from "@iov/encoding";
import { encodeSecp256k1Signature } from "./encoding";
const { fromBase64 } = Encoding;
describe("encoding", () => {
describe("encodeSecp256k1Signature", () => {
it("encodes a full signature", () => {
const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP");
const signature = fromBase64(
"1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==",
);
expect(encodeSecp256k1Signature(pubkey, signature)).toEqual({
// eslint-disable-next-line @typescript-eslint/camelcase
pub_key: {
type: "tendermint/PubKeySecp256k1",
value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP",
},
signature: "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==",
});
});
it("compresses uncompressed public keys", () => {
const pubkey = fromBase64(
"BE8EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQE7WHpoHoNswYeoFkuYpYSKK4mzFzMV/dB0DVAy4lnNU=",
);
const signature = fromBase64(
"1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==",
);
expect(encodeSecp256k1Signature(pubkey, signature)).toEqual({
// eslint-disable-next-line @typescript-eslint/camelcase
pub_key: {
type: "tendermint/PubKeySecp256k1",
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
},
signature: "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==",
});
});
it("removes recovery values from signature data", () => {
const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP");
const signature = Uint8Array.from([
...fromBase64(
"1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==",
),
99,
]);
expect(encodeSecp256k1Signature(pubkey, signature)).toEqual({
// eslint-disable-next-line @typescript-eslint/camelcase
pub_key: {
type: "tendermint/PubKeySecp256k1",
value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP",
},
signature: "1nUcIH0CLT0/nQ0mBTDrT6kMG20NY/PsH7P2gc4bpYNGLEYjBmdWevXUJouSE/9A/60QG9cYeqyTe5kFDeIPxQ==",
});
});
});
});

View File

@ -1,6 +1,9 @@
import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import { StdTx } from "./types";
import { StdSignature, StdTx } from "./types";
const { toBase64 } = Encoding;
export function sortJson(json: any): any {
if (typeof json !== "object" || json === null) {
@ -24,3 +27,15 @@ export function marshalTx(tx: StdTx): Uint8Array {
const json = JSON.stringify(tx);
return Encoding.toUtf8(json);
}
export function encodeSecp256k1Signature(pubkey: Uint8Array, signature: Uint8Array): StdSignature {
return {
// eslint-disable-next-line @typescript-eslint/camelcase
pub_key: {
type: "tendermint/PubKeySecp256k1",
value: toBase64(Secp256k1.compressPubkey(pubkey)),
},
// Recovery seems to be unused
signature: toBase64(Secp256k1.trimRecoveryByte(signature)),
};
}

View File

@ -1,6 +1,6 @@
import * as types from "./types";
export { unmarshalTx } from "./decoding";
export { marshalTx, sortJson } from "./encoding";
export { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding";
export { RestClient, TxsResponse } from "./restclient";
export { types };

View File

@ -1,16 +1,15 @@
/* eslint-disable @typescript-eslint/camelcase */
import { ChainId, PrehashType, SignableBytes } from "@iov/bcp";
import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import { HdPaths, Secp256k1HdWallet } from "@iov/keycontrol";
import { marshalTx, sortJson } from "./encoding";
import { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding";
import { RestClient } from "./restclient";
import contract from "./testdata/contract.json";
import data from "./testdata/cosmoshub.json";
import { MsgStoreCodeWrapped, StdSignature, StdTx } from "./types";
import { MsgStoreCodeWrapped, StdTx } from "./types";
const { fromBase64, toBase64, toUtf8 } = Encoding;
const { fromBase64, toUtf8 } = Encoding;
const httpUrl = "http://localhost:1317";
const defaultNetworkId = "testing";
@ -105,21 +104,14 @@ describe("RestClient", () => {
});
const signBytes = toUtf8(JSON.stringify(signMsg)) as SignableBytes;
const signature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256);
const fullSignature: StdSignature = {
pub_key: {
type: "tendermint/PubKeySecp256k1",
value: toBase64(Secp256k1.compressPubkey(signer.pubkey.data)),
},
// Recovery seems to be unused
signature: toBase64(Secp256k1.trimRecoveryByte(signature)),
};
const rawSignature = await wallet.createTransactionSignature(signer, signBytes, PrehashType.Sha256);
const signature = encodeSecp256k1Signature(signer.pubkey.data, rawSignature);
const tx: StdTx = {
msg: unsigned.msg,
fee: unsigned.fee,
memo: memo,
signatures: [fullSignature],
signatures: [signature],
};
const postableBytes = marshalTx(tx);

View File

@ -1,3 +1,4 @@
import { StdTx } from "./types";
import { StdSignature, StdTx } from "./types";
export declare function sortJson(json: any): any;
export declare function marshalTx(tx: StdTx): Uint8Array;
export declare function encodeSecp256k1Signature(pubkey: Uint8Array, signature: Uint8Array): StdSignature;

View File

@ -1,5 +1,5 @@
import * as types from "./types";
export { unmarshalTx } from "./decoding";
export { marshalTx, sortJson } from "./encoding";
export { encodeSecp256k1Signature, marshalTx, sortJson } from "./encoding";
export { RestClient, TxsResponse } from "./restclient";
export { types };