cosmwasm-stargate: Remove legacy Amino signing support

This commit is contained in:
willclarktech 2021-01-06 16:01:28 +00:00
parent 5358e9c4f8
commit fc08e4dadd
No known key found for this signature in database
GPG Key ID: 551A86E2E398ADF7
4 changed files with 13 additions and 177 deletions

View File

@ -3,11 +3,10 @@ import { UploadMeta } from "@cosmjs/cosmwasm-launchpad";
import { sha256 } from "@cosmjs/crypto";
import { toHex } from "@cosmjs/encoding";
import { coin, coins, GasPrice } from "@cosmjs/launchpad";
import { Coin, cosmosField, DirectSecp256k1HdWallet, registered, Registry } from "@cosmjs/proto-signing";
import { DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-signing";
import { assertIsBroadcastTxSuccess, codec } from "@cosmjs/stargate";
import { assert, sleep } from "@cosmjs/utils";
import Long from "long";
import { Message } from "protobufjs";
import { PrivateSigningCosmWasmClient, SigningCosmWasmClient } from "./signingcosmwasmclient";
import {
@ -16,7 +15,6 @@ import {
makeRandomAddress,
makeWasmClient,
ModifyingDirectSecp256k1HdWallet,
ModifyingSecp256k1HdWallet,
pendingWithoutWasmd,
unused,
validator,
@ -504,82 +502,5 @@ describe("SigningCosmWasmClient", () => {
expect(tx.authInfo!.fee!.gasLimit!.toNumber()).toEqual(333333);
});
});
describe("legacy Amino mode", () => {
// NOTE: One registry shared between tests
// See https://github.com/protobufjs/protobuf.js#using-decorators
// > Decorated types reside in protobuf.roots["decorated"] using a flat structure, so no duplicate names.
const registry = new Registry();
const msgDelegateTypeUrl = "/cosmos.staking.v1beta1.MsgDelegate";
@registered(registry, msgDelegateTypeUrl)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class CustomMsgDelegate extends Message {
@cosmosField.string(1)
public readonly delegator_address?: string;
@cosmosField.string(2)
public readonly validator_address?: string;
@cosmosField.message(3, Coin)
public readonly amount?: Coin;
}
it("works", async () => {
pendingWithoutWasmd();
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(alice.mnemonic, undefined, wasmd.prefix);
const options = { registry: registry };
const client = await SigningCosmWasmClient.connectWithWallet(wasmd.endpoint, wallet, options);
const msg = {
delegator_address: alice.address0,
validator_address: validator.validatorAddress,
amount: coin(1234, "ustake"),
};
const msgAny = {
typeUrl: msgDelegateTypeUrl,
value: msg,
};
const fee = {
amount: coins(2000, "ucosm"),
gas: "200000",
};
const memo = "Use your power wisely";
const result = await client.signAndBroadcast(alice.address0, [msgAny], fee, memo);
assertIsBroadcastTxSuccess(result);
});
it("works with a modifying signer", async () => {
pendingWithoutWasmd();
const wallet = await ModifyingSecp256k1HdWallet.fromMnemonic(alice.mnemonic, undefined, wasmd.prefix);
const options = { registry: registry };
const client = await SigningCosmWasmClient.connectWithWallet(wasmd.endpoint, wallet, options);
const msg = {
delegator_address: alice.address0,
validator_address: validator.validatorAddress,
amount: coin(1234, "ustake"),
};
const msgAny = {
typeUrl: msgDelegateTypeUrl,
value: msg,
};
const fee = {
amount: coins(2000, "ucosm"),
gas: "200000",
};
const memo = "Use your power wisely";
const result = await client.signAndBroadcast(alice.address0, [msgAny], fee, memo);
assertIsBroadcastTxSuccess(result);
await sleep(1000);
const searchResult = await client.getTx(result.transactionHash);
assert(searchResult, "Must find transaction");
const tx = Tx.decode(searchResult.tx);
// From ModifyingSecp256k1HdWallet
expect(tx.body!.memo).toEqual("This was modified");
expect({ ...tx.authInfo!.fee!.amount![0] }).toEqual(coin(3000, "ucosm"));
expect(tx.authInfo!.fee!.gasLimit!.toNumber()).toEqual(333333);
});
});
});
});

View File

@ -21,21 +21,18 @@ import {
GasLimits,
GasPrice,
logs,
makeSignDoc as makeSignDocAmino,
StdFee,
} from "@cosmjs/launchpad";
import { Int53, Uint53 } from "@cosmjs/math";
import {
EncodeObject,
encodePubkey,
isOfflineDirectSigner,
makeAuthInfoBytes,
makeSignDoc,
OfflineSigner,
OfflineDirectSigner,
Registry,
} from "@cosmjs/proto-signing";
import {
AminoTypes,
BroadcastTxFailure,
BroadcastTxResponse,
codec,
@ -50,7 +47,6 @@ import { cosmwasm } from "./codec";
import { CosmWasmClient } from "./cosmwasmclient";
const { TxRaw } = codec.cosmos.tx.v1beta1;
const { SignMode } = codec.cosmos.tx.signing.v1beta1;
const {
MsgClearAdmin,
MsgExecuteContract,
@ -108,12 +104,11 @@ export interface PrivateSigningCosmWasmClient {
export class SigningCosmWasmClient extends CosmWasmClient {
private readonly fees: CosmosFeeTable;
private readonly registry: Registry;
private readonly signer: OfflineSigner;
private readonly aminoTypes = new AminoTypes();
private readonly signer: OfflineDirectSigner;
public static async connectWithWallet(
endpoint: string,
signer: OfflineSigner,
signer: OfflineDirectSigner,
options: SigningCosmWasmClientOptions = {},
): Promise<SigningCosmWasmClient> {
const tmClient = await TendermintClient.connect(endpoint, adaptor34);
@ -122,7 +117,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
private constructor(
tmClient: TendermintClient,
signer: OfflineSigner,
signer: OfflineDirectSigner,
options: SigningCosmWasmClientOptions,
) {
super(tmClient);
@ -352,50 +347,12 @@ export class SigningCosmWasmClient extends CosmWasmClient {
});
const gasLimit = Int53.fromString(fee.gas).toNumber();
if (isOfflineDirectSigner(this.signer)) {
const authInfoBytes = makeAuthInfoBytes([pubkeyAny], fee.amount, gasLimit, sequence);
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);
const { signature, signed } = await this.signer.signDirect(address, signDoc);
const txRaw = TxRaw.create({
bodyBytes: signed.bodyBytes,
authInfoBytes: signed.authInfoBytes,
signatures: [fromBase64(signature.signature)],
});
const signedTx = Uint8Array.from(TxRaw.encode(txRaw).finish());
return this.broadcastTx(signedTx);
}
// Amino signer
const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON;
const msgs = messages.map((msg) => ({
type: this.aminoTypes.toAmino(msg.typeUrl),
value: msg.value,
}));
const signDoc = makeSignDocAmino(msgs, fee, chainId, memo, accountNumber, sequence);
const { signature, signed } = await this.signer.signAmino(address, signDoc);
const signedTxBody = {
messages: signed.msgs.map((msg) => ({
typeUrl: this.aminoTypes.fromAmino(msg.type),
value: msg.value,
})),
memo: signed.memo,
};
const signedTxBodyBytes = this.registry.encode({
typeUrl: "/cosmos.tx.v1beta1.TxBody",
value: signedTxBody,
});
const signedGasLimit = Int53.fromString(signed.fee.gas).toNumber();
const signedSequence = Int53.fromString(signed.sequence).toNumber();
const signedAuthInfoBytes = makeAuthInfoBytes(
[pubkeyAny],
signed.fee.amount,
signedGasLimit,
signedSequence,
signMode,
);
const authInfoBytes = makeAuthInfoBytes([pubkeyAny], fee.amount, gasLimit, sequence);
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);
const { signature, signed } = await this.signer.signDirect(address, signDoc);
const txRaw = TxRaw.create({
bodyBytes: signedTxBodyBytes,
authInfoBytes: signedAuthInfoBytes,
bodyBytes: signed.bodyBytes,
authInfoBytes: signed.authInfoBytes,
signatures: [fromBase64(signature.signature)],
});
const signedTx = Uint8Array.from(TxRaw.encode(txRaw).finish());

View File

@ -1,13 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Bip39, EnglishMnemonic, Random, Secp256k1, Slip10, Slip10Curve } from "@cosmjs/crypto";
import { Bech32, fromBase64 } from "@cosmjs/encoding";
import {
AminoSignResponse,
coins,
makeCosmoshubPath,
Secp256k1HdWallet,
StdSignDoc,
} from "@cosmjs/launchpad";
import { coins, makeCosmoshubPath } from "@cosmjs/launchpad";
import { DirectSecp256k1HdWallet, DirectSignResponse, makeAuthInfoBytes } from "@cosmjs/proto-signing";
import {
AuthExtension,
@ -211,41 +205,6 @@ export async function makeWasmClient(
return QueryClient.withExtensions(tmClient, setupAuthExtension, setupBankExtension, setupWasmExtension);
}
/**
* A class for testing clients using an Amino signer which modifies the transaction it receives before signing
*/
export class ModifyingSecp256k1HdWallet extends Secp256k1HdWallet {
public static async fromMnemonic(
mnemonic: string,
hdPath = makeCosmoshubPath(0),
prefix = "cosmos",
): Promise<ModifyingSecp256k1HdWallet> {
const mnemonicChecked = new EnglishMnemonic(mnemonic);
const seed = await Bip39.mnemonicToSeed(mnemonicChecked);
const { privkey } = Slip10.derivePath(Slip10Curve.Secp256k1, seed, hdPath);
const uncompressed = (await Secp256k1.makeKeypair(privkey)).pubkey;
return new ModifyingSecp256k1HdWallet(
mnemonicChecked,
hdPath,
privkey,
Secp256k1.compressPubkey(uncompressed),
prefix,
);
}
public async signAmino(signerAddress: string, signDoc: StdSignDoc): Promise<AminoSignResponse> {
const modifiedSignDoc = {
...signDoc,
fee: {
amount: coins(3000, "ucosm"),
gas: "333333",
},
memo: "This was modified",
};
return super.signAmino(signerAddress, modifiedSignDoc);
}
}
/**
* A class for testing clients using a direct signer which modifies the transaction it receives before signing
*/

View File

@ -9,7 +9,7 @@ import {
UploadResult,
} from "@cosmjs/cosmwasm-launchpad";
import { Coin, CosmosFeeTable, GasLimits, GasPrice, StdFee } from "@cosmjs/launchpad";
import { EncodeObject, OfflineSigner, Registry } from "@cosmjs/proto-signing";
import { EncodeObject, OfflineDirectSigner, Registry } from "@cosmjs/proto-signing";
import { BroadcastTxResponse } from "@cosmjs/stargate";
import { CosmWasmClient } from "./cosmwasmclient";
export interface SigningCosmWasmClientOptions {
@ -25,10 +25,9 @@ export declare class SigningCosmWasmClient extends CosmWasmClient {
private readonly fees;
private readonly registry;
private readonly signer;
private readonly aminoTypes;
static connectWithWallet(
endpoint: string,
signer: OfflineSigner,
signer: OfflineDirectSigner,
options?: SigningCosmWasmClientOptions,
): Promise<SigningCosmWasmClient>;
private constructor();