Let makeAuthInfoBytes support different sequences for signers

This commit is contained in:
Simon Warta 2021-07-26 14:49:07 +02:00
parent b3af6be16f
commit 343f775099
12 changed files with 41 additions and 30 deletions

View File

@ -46,6 +46,8 @@ and this project adheres to
- @cosmjs/tendermint-rpc: Make `tendermint34.Header.lastBlockId` and
`tendermint34.Block.lastCommit` optional to better handle the case of height 1
where there is no previous block.
- @cosmjs/proto-signing: `makeAuthInfoBytes` now takes an array of pubkey
sequence pairs in order to support different sequences for different signers.
### Removed

View File

@ -79,7 +79,7 @@ async function sendTokens(
},
];
const gasLimit = 200000;
const authInfoBytes = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence);
const authInfoBytes = makeAuthInfoBytes([{ pubkey, sequence }], feeAmount, gasLimit);
const chainId = await client.getChainId();
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);

View File

@ -193,7 +193,7 @@ describe("CosmWasmClient", () => {
const sequenceResponse = await client.getSequence(alice.address0);
assert(sequenceResponse);
const { accountNumber, sequence } = sequenceResponse;
const pubkeyAny = encodePubkey(alice.pubkey0);
const pubkey = encodePubkey(alice.pubkey0);
const txBody: TxBodyEncodeObject = {
typeUrl: "/cosmos.tx.v1beta1.TxBody",
value: {
@ -203,7 +203,7 @@ describe("CosmWasmClient", () => {
};
const txBodyBytes = registry.encode(txBody);
const gasLimit = Int53.fromString(fee.gas).toNumber();
const authInfoBytes = makeAuthInfoBytes([pubkeyAny], fee.amount, gasLimit, sequence);
const authInfoBytes = makeAuthInfoBytes([{ pubkey, sequence }], fee.amount, gasLimit);
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);
const { signed, signature } = await wallet.signDirect(alice.address0, signDoc);
const txRaw = TxRaw.fromPartial({

View File

@ -527,10 +527,9 @@ export class SigningCosmWasmClient extends CosmWasmClient {
const signedGasLimit = Int53.fromString(signed.fee.gas).toNumber();
const signedSequence = Int53.fromString(signed.sequence).toNumber();
const signedAuthInfoBytes = makeAuthInfoBytes(
[pubkey],
[{ pubkey, sequence: signedSequence }],
signed.fee.amount,
signedGasLimit,
signedSequence,
signMode,
);
return TxRaw.fromPartial({
@ -564,7 +563,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
};
const txBodyBytes = this.registry.encode(txBody);
const gasLimit = Int53.fromString(fee.gas).toNumber();
const authInfoBytes = makeAuthInfoBytes([pubkey], fee.amount, gasLimit, sequence);
const authInfoBytes = makeAuthInfoBytes([{ pubkey, sequence }], fee.amount, gasLimit);
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);
const { signature, signed } = await this.signer.signDirect(signerAddress, signDoc);
return TxRaw.fromPartial({

View File

@ -252,18 +252,19 @@ export class ModifyingDirectSecp256k1HdWallet extends DirectSecp256k1HdWallet {
memo: "This was modified",
});
const authInfo = AuthInfo.decode(signDoc.authInfoBytes);
const pubkeys = authInfo.signerInfos.map((signerInfo) => signerInfo.publicKey!);
const sequence = authInfo.signerInfos[0].sequence.toNumber();
const signers = authInfo.signerInfos.map((signerInfo) => ({
pubkey: signerInfo.publicKey!,
sequence: signerInfo.sequence.toNumber(),
}));
const modifiedFeeAmount = coins(3000, "ucosm");
const modifiedGasLimit = 333333;
const modifiedSignDoc = {
...signDoc,
bodyBytes: Uint8Array.from(TxBody.encode(modifiedTxBody).finish()),
authInfoBytes: makeAuthInfoBytes(
pubkeys,
signers,
modifiedFeeAmount,
modifiedGasLimit,
sequence,
SignMode.SIGN_MODE_DIRECT,
),
};

View File

@ -264,7 +264,7 @@ describe("DirectSecp256k1HdWallet", () => {
const chainId = "simd-testing";
const signDoc = makeSignDoc(
fromHex(bodyBytes),
makeAuthInfoBytes([pubkey], fee, gasLimit, sequence),
makeAuthInfoBytes([{ pubkey, sequence }], fee, gasLimit),
chainId,
accountNumber,
);

View File

@ -46,7 +46,7 @@ describe("DirectSecp256k1Wallet", () => {
const chainId = "simd-testing";
const signDoc = makeSignDoc(
fromHex(bodyBytes),
makeAuthInfoBytes([pubkey], fee, gasLimit, sequence),
makeAuthInfoBytes([{ pubkey, sequence }], fee, gasLimit),
chainId,
accountNumber,
);

View File

@ -5,9 +5,17 @@ import { AuthInfo, SignDoc, SignerInfo } from "cosmjs-types/cosmos/tx/v1beta1/tx
import { Any } from "cosmjs-types/google/protobuf/any";
import Long from "long";
function makeSignerInfos(pubkeys: readonly Any[], sequence: number, signMode: SignMode): SignerInfo[] {
return pubkeys.map(
(pubkey): SignerInfo => ({
/**
* Create signer infos from the provided signers.
*
* This implementation does not support different signing modes for the different signers.
*/
function makeSignerInfos(
signers: ReadonlyArray<{ readonly pubkey: Any; readonly sequence: number }>,
signMode: SignMode,
): SignerInfo[] {
return signers.map(
({ pubkey, sequence }): SignerInfo => ({
publicKey: pubkey,
modeInfo: {
single: { mode: signMode },
@ -19,16 +27,17 @@ function makeSignerInfos(pubkeys: readonly Any[], sequence: number, signMode: Si
/**
* Creates and serializes an AuthInfo document.
*
* This implementation does not support different signing modes for the different signers.
*/
export function makeAuthInfoBytes(
pubkeys: readonly Any[],
signers: ReadonlyArray<{ readonly pubkey: Any; readonly sequence: number }>,
feeAmount: readonly Coin[],
gasLimit: number,
sequence: number,
signMode = SignMode.SIGN_MODE_DIRECT,
): Uint8Array {
const authInfo = {
signerInfos: makeSignerInfos(pubkeys, sequence, signMode),
signerInfos: makeSignerInfos(signers, signMode),
fee: {
amount: [...feeAmount],
gasLimit: Long.fromNumber(gasLimit),

View File

@ -354,10 +354,9 @@ export class SigningStargateClient extends StargateClient {
const signedGasLimit = Int53.fromString(signed.fee.gas).toNumber();
const signedSequence = Int53.fromString(signed.sequence).toNumber();
const signedAuthInfoBytes = makeAuthInfoBytes(
[pubkey],
[{ pubkey, sequence: signedSequence }],
signed.fee.amount,
signedGasLimit,
signedSequence,
signMode,
);
return TxRaw.fromPartial({
@ -391,7 +390,7 @@ export class SigningStargateClient extends StargateClient {
};
const txBodyBytes = this.registry.encode(txBodyEncodeObject);
const gasLimit = Int53.fromString(fee.gas).toNumber();
const authInfoBytes = makeAuthInfoBytes([pubkey], fee.amount, gasLimit, sequence);
const authInfoBytes = makeAuthInfoBytes([{ pubkey, sequence }], fee.amount, gasLimit);
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);
const { signature, signed } = await this.signer.signDirect(signerAddress, signDoc);
return TxRaw.fromPartial({

View File

@ -78,7 +78,7 @@ async function sendTokens(
},
];
const gasLimit = 200000;
const authInfoBytes = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence);
const authInfoBytes = makeAuthInfoBytes([{ pubkey, sequence }], feeAmount, gasLimit);
const chainId = await client.getChainId();
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);

View File

@ -315,7 +315,7 @@ describe("StargateClient", () => {
const { accountNumber, sequence } = (await client.getSequence(address))!;
const feeAmount = coins(2000, "ucosm");
const gasLimit = 200000;
const authInfoBytes = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence);
const authInfoBytes = makeAuthInfoBytes([{ pubkey, sequence }], feeAmount, gasLimit);
const chainId = await client.getChainId();
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);
@ -372,7 +372,7 @@ describe("StargateClient", () => {
const { accountNumber, sequence } = (await client.getSequence(address))!;
const feeAmount = coins(2000, "ucosm");
const gasLimit = 200000;
const authInfoBytes = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence);
const authInfoBytes = makeAuthInfoBytes([{ pubkey, sequence }], feeAmount, gasLimit, sequence);
const chainId = await client.getChainId();
const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, chainId, accountNumber);
@ -425,7 +425,7 @@ describe("StargateClient", () => {
const gasLimit = 200000;
const { accountNumber: accountNumber1, sequence: sequence1 } = (await client.getSequence(address))!;
const authInfoBytes1 = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence1);
const authInfoBytes1 = makeAuthInfoBytes([{ pubkey, sequence: sequence1 }], feeAmount, gasLimit);
const signDoc1 = makeSignDoc(txBodyBytes, authInfoBytes1, chainId, accountNumber1);
const { signature: signature1 } = await wallet.signDirect(address, signDoc1);
const txRaw1 = TxRaw.fromPartial({
@ -439,7 +439,7 @@ describe("StargateClient", () => {
assertIsBroadcastTxSuccess(txResult);
const { accountNumber: accountNumber2, sequence: sequence2 } = (await client.getSequence(address))!;
const authInfoBytes2 = makeAuthInfoBytes([pubkey], feeAmount, gasLimit, sequence2);
const authInfoBytes2 = makeAuthInfoBytes([{ pubkey, sequence: sequence2 }], feeAmount, gasLimit);
const signDoc2 = makeSignDoc(txBodyBytes, authInfoBytes2, chainId, accountNumber2);
const { signature: signature2 } = await wallet.signDirect(address, signDoc2);
const txRaw2 = TxRaw.fromPartial({

View File

@ -199,18 +199,19 @@ export class ModifyingDirectSecp256k1HdWallet extends DirectSecp256k1HdWallet {
memo: "This was modified",
});
const authInfo = AuthInfo.decode(signDoc.authInfoBytes);
const pubkeys = authInfo.signerInfos.map((signerInfo) => signerInfo.publicKey!);
const sequence = authInfo.signerInfos[0].sequence.toNumber();
const signers = authInfo.signerInfos.map((signerInfo) => ({
pubkey: signerInfo.publicKey!,
sequence: signerInfo.sequence.toNumber(),
}));
const modifiedFeeAmount = coins(3000, "ucosm");
const modifiedGasLimit = 333333;
const modifiedSignDoc = {
...signDoc,
bodyBytes: Uint8Array.from(TxBody.encode(modifiedTxBody).finish()),
authInfoBytes: makeAuthInfoBytes(
pubkeys,
signers,
modifiedFeeAmount,
modifiedGasLimit,
sequence,
SignMode.SIGN_MODE_DIRECT,
),
};