cosmwasm-stargate: Remove legacy Amino signing support
This commit is contained in:
parent
5358e9c4f8
commit
fc08e4dadd
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user