Post tx tests work until invalid signature

This commit is contained in:
Ethan Frey 2020-01-22 23:33:00 +01:00
parent 344d980b5f
commit f1ad81a05a
6 changed files with 55 additions and 43 deletions

View File

@ -56,7 +56,7 @@ export class CosmosCodec implements TxCodec {
public bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob {
const accountNumber = 0;
const memo = (unsigned as any).memo;
const built = buildUnsignedTx(unsigned);
const built = buildUnsignedTx(unsigned, this.tokens);
const signMsg = sortJson({
account_number: accountNumber.toString(),
@ -75,7 +75,7 @@ export class CosmosCodec implements TxCodec {
}
public bytesToPost(signed: SignedTransaction): PostableBytes {
const built = buildSignedTx(signed);
const built = buildSignedTx(signed, this.tokens);
const bytes = marshalTx(built, true);
return bytes as PostableBytes;
}

View File

@ -14,7 +14,7 @@ import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol";
import { cosmosCodec } from "./cosmoscodec";
import { cosmosCodec, CosmosCodec } from "./cosmoscodec";
import { CosmosConnection } from "./cosmosconnection";
import { CosmosBech32Prefix } from "./address";
import { TokenInfos } from "./types";
@ -28,7 +28,7 @@ function pendingWithoutCosmos(): void {
}
describe("CosmosConnection", () => {
const atom = "ATOM" as TokenTicker;
const cosm = "COSM" as TokenTicker;
const httpUrl = "http://localhost:1317";
const defaultChainId = "cosmos:testing" as ChainId;
const defaultEmptyAddress = "cosmos1h806c7khnvmjlywdrkdgk2vrayy2mmvf9rxk2r" as Address;
@ -191,13 +191,17 @@ describe("CosmosConnection", () => {
amount: {
quantity: "75000",
fractionalDigits: 6,
tokenTicker: atom,
tokenTicker: cosm,
},
});
const nonce = await connection.getNonce({ address: faucetAddress });
const signed = await profile.signTransaction(faucet, unsigned, cosmosCodec, nonce);
const postableBytes = cosmosCodec.bytesToPost(signed);
// TODO: we need to use custom codecs everywhere
const codec = new CosmosCodec(defaultPrefix, defaultTokens);
console.log("nonce:", nonce);
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
const postableBytes = codec.bytesToPost(signed);
const response = await connection.postTx(postableBytes);
console.log(response);
const { transactionId } = response;
const blockInfo = await response.blockInfo.waitFor(info => !isBlockInfoPending(info));
expect(blockInfo.state).toEqual(TransactionState.Succeeded);
@ -250,13 +254,16 @@ describe("CosmosConnection", () => {
amount: {
quantity: "75000",
fractionalDigits: 6,
tokenTicker: atom,
tokenTicker: cosm,
},
});
const nonce = await connection.getNonce({ address: faucetAddress });
const signed = await profile.signTransaction(faucet, unsigned, cosmosCodec, nonce);
const postableBytes = cosmosCodec.bytesToPost(signed);
// TODO: we need to use custom codecs everywhere
const codec = new CosmosCodec(defaultPrefix, defaultTokens);
const signed = await profile.signTransaction(faucet, unsigned, codec, nonce);
const postableBytes = codec.bytesToPost(signed);
const response = await connection.postTx(postableBytes);
console.log(response);
const { transactionId } = response;
const blockInfo = await response.blockInfo.waitFor(info => !isBlockInfoPending(info));
expect(blockInfo.state).toEqual(TransactionState.Succeeded);

View File

@ -214,6 +214,7 @@ export class CosmosConnection implements BlockchainConnection {
}
public async postTx(tx: PostableBytes): Promise<PostTxResponse> {
// TODO: we need to check errors here... bad chain-id breaks this
const { txhash, raw_log } = await this.restClient.postTx(tx);
const transactionId = txhash as TransactionId;
const firstEvent: BlockInfo = { state: TransactionState.Pending };

View File

@ -19,15 +19,6 @@ import { TokenInfos } from "./types";
const { fromBase64 } = Encoding;
const defaultTokens: TokenInfos = [
{
fractionalDigits: 6,
tokenName: "Atom (Cosmos Hub)",
tokenTicker: "ATOM" as TokenTicker,
denom: "uatom",
},
];
describe("decode", () => {
const defaultPubkey = {
algo: Algorithm.Secp256k1,
@ -61,6 +52,14 @@ describe("decode", () => {
},
gasLimit: "200000",
};
const defaultTokens: TokenInfos = [
{
fractionalDigits: 6,
tokenName: "Atom (Cosmos Hub)",
tokenTicker: "ATOM" as TokenTicker,
denom: "uatom",
},
];
describe("decodePubkey", () => {
it("works", () => {

View File

@ -21,6 +21,7 @@ import {
encodeFullSignature,
encodePubkey,
} from "./encode";
import { TokenInfos } from "./types";
const { fromBase64 } = Encoding;
@ -40,6 +41,14 @@ describe("encode", () => {
tokenTicker: atom,
};
const defaultMemo = "hello cosmos hub";
const defaultTokens: TokenInfos = [
{
fractionalDigits: 6,
tokenName: "Atom (Cosmos Hub)",
tokenTicker: "ATOM" as TokenTicker,
denom: "uatom",
},
];
describe("encodePubKey", () => {
it("encodes a Secp256k1 pubkey", () => {
@ -52,7 +61,7 @@ describe("encode", () => {
describe("encodeAmount", () => {
it("encodes an amount", () => {
expect(encodeAmount(defaultAmount)).toEqual({
expect(encodeAmount(defaultAmount, defaultTokens)).toEqual({
denom: "uatom",
amount: "11657995",
});
@ -64,7 +73,7 @@ describe("encode", () => {
const fee = {
gasLimit: "200000",
};
expect(() => encodeFee(fee)).toThrowError(/cannot encode fee without tokens/i);
expect(() => encodeFee(fee, defaultTokens)).toThrowError(/cannot encode fee without tokens/i);
});
it("throws without gas limit", () => {
@ -75,7 +84,7 @@ describe("encode", () => {
tokenTicker: atom,
},
};
expect(() => encodeFee(fee)).toThrowError(/cannot encode fee without gas limit/i);
expect(() => encodeFee(fee, defaultTokens)).toThrowError(/cannot encode fee without gas limit/i);
});
it("encodes a fee", () => {
@ -87,7 +96,7 @@ describe("encode", () => {
},
gasLimit: "200000",
};
expect(encodeFee(fee)).toEqual({
expect(encodeFee(fee, defaultTokens)).toEqual({
amount: [{ denom: "uatom", amount: "5000" }],
gas: "200000",
});
@ -168,7 +177,9 @@ describe("encode", () => {
chainId: defaultChainId,
escrowId: "defg",
};
expect(() => buildUnsignedTx(tx)).toThrowError(/received transaction of unsupported kind/i);
expect(() => buildUnsignedTx(tx, defaultTokens)).toThrowError(
/received transaction of unsupported kind/i,
);
});
it("builds a send transaction without fee", () => {
@ -180,7 +191,7 @@ describe("encode", () => {
recipient: defaultRecipient,
memo: defaultMemo,
};
expect(buildUnsignedTx(tx)).toEqual({
expect(buildUnsignedTx(tx, defaultTokens)).toEqual({
type: "cosmos-sdk/StdTx",
value: {
msg: [
@ -225,7 +236,7 @@ describe("encode", () => {
gasLimit: "200000",
},
};
expect(buildUnsignedTx(tx)).toEqual({
expect(buildUnsignedTx(tx, defaultTokens)).toEqual({
type: "cosmos-sdk/StdTx",
value: {
msg: [
@ -286,7 +297,7 @@ describe("encode", () => {
},
],
};
expect(buildSignedTx(tx)).toEqual({
expect(buildSignedTx(tx, defaultTokens)).toEqual({
type: "cosmos-sdk/StdTx",
value: {
msg: [

View File

@ -13,7 +13,7 @@ import { Secp256k1 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import amino from "@tendermint/amino-js";
import { AminoTx } from "./types";
import { AminoTx, TokenInfos, amountToCoin } from "./types";
const { toBase64 } = Encoding;
@ -34,17 +34,11 @@ export function encodePubkey(pubkey: PubkeyBundle): amino.PubKey {
}
}
export function encodeAmount(amount: Amount): amino.Coin {
if (amount.tokenTicker !== "ATOM") {
throw new Error("Only ATOM amounts are supported");
}
return {
denom: "uatom",
amount: amount.quantity,
};
export function encodeAmount(amount: Amount, tokens: TokenInfos): amino.Coin {
return amountToCoin(tokens, amount);
}
export function encodeFee(fee: Fee): amino.StdFee {
export function encodeFee(fee: Fee, tokens: TokenInfos): amino.StdFee {
if (fee.tokens === undefined) {
throw new Error("Cannot encode fee without tokens");
}
@ -52,7 +46,7 @@ export function encodeFee(fee: Fee): amino.StdFee {
throw new Error("Cannot encode fee without gas limit");
}
return {
amount: [encodeAmount(fee.tokens)],
amount: [encodeAmount(fee.tokens, tokens)],
gas: fee.gasLimit,
};
}
@ -68,7 +62,7 @@ export function encodeFullSignature(fullSignature: FullSignature): amino.StdSign
};
}
export function buildUnsignedTx(tx: UnsignedTransaction): AminoTx {
export function buildUnsignedTx(tx: UnsignedTransaction, tokens: TokenInfos): AminoTx {
if (!isSendTransaction(tx)) {
throw new Error("Received transaction of unsupported kind");
}
@ -81,14 +75,14 @@ export function buildUnsignedTx(tx: UnsignedTransaction): AminoTx {
value: {
from_address: tx.sender,
to_address: tx.recipient,
amount: [encodeAmount(tx.amount)],
amount: [encodeAmount(tx.amount, tokens)],
},
},
],
memo: tx.memo || "",
signatures: [],
fee: tx.fee
? encodeFee(tx.fee)
? encodeFee(tx.fee, tokens)
: {
amount: [],
gas: "",
@ -97,8 +91,8 @@ export function buildUnsignedTx(tx: UnsignedTransaction): AminoTx {
};
}
export function buildSignedTx(tx: SignedTransaction): AminoTx {
const built = buildUnsignedTx(tx.transaction);
export function buildSignedTx(tx: SignedTransaction, tokens: TokenInfos): AminoTx {
const built = buildUnsignedTx(tx.transaction, tokens);
return {
...built,
value: {