Skip to content
Open
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
28 changes: 28 additions & 0 deletions packages/amino/src/encoding.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
encodeAminoPubkey,
encodeBech32Pubkey,
encodeEd25519Pubkey,
encodeEthSecp256k1Pubkey,
encodeSecp256k1Pubkey,
} from "./encoding";
import { Pubkey } from "./pubkeys";
Expand Down Expand Up @@ -171,6 +172,23 @@ describe("encoding", () => {
});
});

describe("encodeEthSecp256k1Pubkey", () => {
it("encodes a compressed pubkey", () => {
const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP");
expect(encodeEthSecp256k1Pubkey(pubkey)).toEqual({
type: "os/PubKeyEthSecp256k1",
value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP",
});
});

it("throws for uncompressed public keys", () => {
const pubkey = fromBase64(
"BE8EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQE7WHpoHoNswYeoFkuYpYSKK4mzFzMV/dB0DVAy4lnNU=",
);
expect(() => encodeEthSecp256k1Pubkey(pubkey)).toThrowError(/must be compressed secp256k1/i);
});
});

describe("encodeAminoPubkey", () => {
it("works for secp256k1", () => {
const pubkey: Pubkey = {
Expand All @@ -195,6 +213,16 @@ describe("encoding", () => {
).data;
expect(encodeAminoPubkey(pubkey)).toEqual(expected);
});

it("works for ethsecp256k1", () => {
const pubkey: Pubkey = {
type: "os/PubKeyEthSecp256k1",
value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP",
};
// 5D7423DF21 amino prefix followed by the 33-byte compressed pubkey
const expected = new Uint8Array([...fromHex("5D7423DF21"), ...fromBase64(pubkey.value)]);
expect(encodeAminoPubkey(pubkey)).toEqual(expected);
});
});

describe("encodeBech32Pubkey", () => {
Expand Down
4 changes: 4 additions & 0 deletions packages/cosmwasm/src/signingcosmwasmclient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@ import {
expect(result.height).toBeGreaterThan(0);
expect(result.gasWanted).toBeGreaterThan(0);
expect(result.gasUsed).toBeGreaterThan(0);
// One MsgExecuteContractResponse (and thus one `data` entry) per instruction.
expect(result.data.length).toEqual(1);
const wasmEvent = result.events.find((e) => e.type === "wasm");
assert(wasmEvent, "Event of type wasm expected");
expect(wasmEvent.attributes).toContain({ key: "action", value: "release" });
Expand Down Expand Up @@ -794,6 +796,8 @@ import {
const { events } = result;
const wasmEvents = events.filter((e) => e.type == "wasm");
expect(wasmEvents.length).toEqual(2);
// One `data` entry per instruction, in order.
expect(result.data.length).toEqual(2);
const [wasmEvent1, wasmEvent2] = wasmEvents;
expect(wasmEvent1.type).toEqual("wasm");
expect(wasmEvent1.attributes).toContain({ key: "action", value: "release" });
Expand Down
12 changes: 12 additions & 0 deletions packages/cosmwasm/src/signingcosmwasmclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
import {
MsgClearAdmin,
MsgExecuteContract,
MsgExecuteContractResponse,
MsgInstantiateContract,
MsgInstantiateContract2,
MsgMigrateContract,
Expand Down Expand Up @@ -163,6 +164,12 @@ export interface ExecuteResult {
/** Transaction hash (might be used as transaction ID). Guaranteed to be non-empty upper-case hex */
readonly transactionHash: string;
readonly events: readonly Event[];
/**
* The `data` bytes each executed contract returned via `Response::set_data`,
* one entry per instruction in the same order. Empty for chains running
* Cosmos SDK < 0.46, which do not expose message responses.
*/
readonly data: readonly Uint8Array[];
readonly gasWanted: bigint;
readonly gasUsed: bigint;
}
Expand Down Expand Up @@ -540,6 +547,11 @@ export class SigningCosmWasmClient extends CosmWasmClient {
height: result.height,
transactionHash: result.transactionHash,
events: result.events,
// Each MsgExecuteContract produces a MsgExecuteContractResponse whose
// `data` field carries what the contract set via `Response::set_data`.
data: result.msgResponses.map(
(msgResponse) => MsgExecuteContractResponse.decode(msgResponse.value).data,
),
gasWanted: result.gasWanted,
gasUsed: result.gasUsed,
};
Expand Down
19 changes: 19 additions & 0 deletions packages/proto-signing/src/pubkey.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,25 @@ describe("pubkey", () => {
});
});

it("works for multisig threshold pubkeys", () => {
// Build a 2-of-2 multisig over the secp256k1 and ed25519 keys above,
// encode it to protobuf, then check decodePubkey reconstructs it. This
// covers the LegacyAminoPubKey branch on both encode and decode.
const multisigPubkey = {
type: "tendermint/PubKeyMultisigThreshold",
value: {
threshold: "2",
pubkeys: [
{ type: "tendermint/PubKeySecp256k1", value: defaultPubkeyBase64 },
{ type: "tendermint/PubKeyEd25519", value: ed25519PubkeyBase64 },
],
},
};
const encoded = encodePubkey(multisigPubkey);
expect(encoded.typeUrl).toEqual("/cosmos.crypto.multisig.LegacyAminoPubKey");
expect(decodePubkey(encoded)).toEqual(multisigPubkey);
});

it("throws for unsupported pubkey types", () => {
const pubkey = {
typeUrl: "/cosmos.crypto.unknown.PubKey",
Expand Down