Merge pull request #430 from CosmWasm/tm34

Add Tendermint 0.34 support
This commit is contained in:
mergify[bot] 2020-09-30 14:15:16 +00:00 committed by GitHub
commit 11d712f9ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 87 additions and 41 deletions

View File

@ -81,6 +81,9 @@
- @cosmjs/tendermint-rpc: Remove trivial helpers `getTxEventHeight`,
`getHeaderEventHeight` and `getBlockEventHeight` because they don't do
anything else than accessing an object member.
- @cosmjs/tendermint-rpc: Add support for connecting to Tendermint RPC 0.34.
- @cosmjs/tendermint-rpc: Make `TxEvent.index` optional and deprecate it because
it is not set anymore in Tendermint 0.34.
- @cosmjs/utils: Add `assertDefined`.
- @cosmjs/faucet: Rename binary from `cosmwasm-faucet` to `cosmos-faucet`.

View File

@ -11,7 +11,7 @@ import { v0_33 } from "./v0-33";
* @param version full Tendermint version string, e.g. "0.20.1"
*/
export function adaptorForVersion(version: string): Adaptor {
if (version.startsWith("0.33.")) {
if (version.startsWith("0.33.") || version.startsWith("0.34.")) {
return v0_33;
} else {
throw new Error(`Unsupported tendermint version: ${version}`);

View File

@ -8,7 +8,7 @@ import { Stream } from "xstream";
import { Adaptor } from "./adaptor";
import { adaptorForVersion } from "./adaptorforversion";
import { Client } from "./client";
import { tendermintInstances } from "./config.spec";
import { ExpectedValues, tendermintInstances } from "./config.spec";
import { buildQuery } from "./requests";
import * as responses from "./responses";
import { HttpClient, RpcClient, WebsocketClient } from "./rpcclients";
@ -41,7 +41,7 @@ function randomString(): string {
.join("");
}
function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor): void {
function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expected: ExpectedValues): void {
it("can connect to tendermint with known version", async () => {
pendingWithoutTendermint();
const client = new Client(rpcFactory(), adaptor);
@ -133,13 +133,25 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor): void {
const client = new Client(rpcFactory(), adaptor);
const status = await client.status();
// node info
expect(status.nodeInfo.protocolVersion).toEqual({
p2p: expected.p2pVersion,
block: expected.blockVersion,
app: expected.appVersion,
});
expect(status.nodeInfo.network).toMatch(chainIdMatcher);
expect(status.nodeInfo.other.size).toBeGreaterThanOrEqual(2);
expect(status.nodeInfo.other.get("tx_index")).toEqual("on");
expect(status.validatorInfo.pubkey).toBeTruthy();
expect(status.validatorInfo.votingPower).toBeGreaterThan(0);
// sync info
expect(status.syncInfo.catchingUp).toEqual(false);
expect(status.syncInfo.latestBlockHeight).toBeGreaterThanOrEqual(1);
// validator info
expect(status.validatorInfo.pubkey).toBeTruthy();
expect(status.validatorInfo.votingPower).toBeGreaterThan(0);
client.disconnect();
});
});
@ -238,8 +250,8 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor): void {
// num_txs: jasmine.stringMatching(nonNegativeIntegerMatcher),
header: jasmine.objectContaining({
version: {
block: 10,
app: 1,
block: expected.blockVersion,
app: expected.appVersion,
},
chainId: jasmine.stringMatching(chainIdMatcher),
}),
@ -371,7 +383,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor): void {
});
}
function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, appCreator: string): void {
function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expected: ExpectedValues): void {
it("can subscribe to block header events", (done) => {
pendingWithoutTendermint();
@ -498,7 +510,6 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, appCr
const subscription = stream.subscribe({
next: (event) => {
expect(event.height).toBeGreaterThan(0);
expect(event.index).toEqual(0);
expect(event.result).toBeTruthy();
expect(event.result.events.length).toBeGreaterThanOrEqual(1);
@ -539,13 +550,12 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, appCr
const events: responses.TxEvent[] = [];
const client = new Client(rpcFactory(), adaptor);
const query = buildQuery({ tags: [{ key: "app.creator", value: appCreator }] });
const query = buildQuery({ tags: [{ key: "app.creator", value: expected.appCreator }] });
const stream = client.subscribeTx(query);
expect(stream).toBeTruthy();
const subscription = stream.subscribe({
next: (event) => {
expect(event.height).toBeGreaterThan(0);
expect(event.index).toEqual(0);
expect(event.result).toBeTruthy();
expect(event.result.events.length).toBeGreaterThanOrEqual(1);
events.push(event);
@ -622,7 +632,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, appCr
});
}
for (const { url, version, appCreator } of tendermintInstances) {
for (const { url, version, expected } of tendermintInstances) {
describe(`Client ${version}`, () => {
it("can connect to a given url", async () => {
pendingWithoutTendermint();
@ -654,7 +664,7 @@ for (const { url, version, appCreator } of tendermintInstances) {
describe("With HttpClient", () => {
const adaptor = adaptorForVersion(version);
defaultTestSuite(() => new HttpClient(url), adaptor);
defaultTestSuite(() => new HttpClient(url), adaptor, expected);
});
describe("With WebsocketClient", () => {
@ -662,8 +672,8 @@ for (const { url, version, appCreator } of tendermintInstances) {
const onError = process.env.TENDERMINT_ENABLED ? console.error : () => 0;
const factory = (): WebsocketClient => new WebsocketClient(url, onError);
const adaptor = adaptorForVersion(version);
defaultTestSuite(factory, adaptor);
websocketTestSuite(factory, adaptor, appCreator);
defaultTestSuite(factory, adaptor, expected);
websocketTestSuite(factory, adaptor, expected);
});
});
}

View File

@ -1,7 +1,17 @@
export interface ExpectedValues {
readonly appCreator: string;
readonly p2pVersion: number;
readonly blockVersion: number;
readonly appVersion: number;
}
export interface TendermintInstance {
readonly url: string;
readonly version: string;
readonly appCreator: string;
/** rough block time in ms */
readonly blockTime: number;
/** Values we expect in the backend */
readonly expected: ExpectedValues;
}
/**
@ -20,7 +30,24 @@ export const tendermintInstances: readonly TendermintInstance[] = [
{
url: "localhost:11133",
version: "0.33.x",
appCreator: "Cosmoshi Netowoko",
blockTime: 1000,
expected: {
appCreator: "Cosmoshi Netowoko",
p2pVersion: 7,
blockVersion: 10,
appVersion: 1,
},
},
{
url: "localhost:11134",
version: "0.34.x",
blockTime: 500,
expected: {
appCreator: "Cosmoshi Netowoko",
p2pVersion: 8,
blockVersion: 11,
appVersion: 1,
},
},
];

View File

@ -153,7 +153,8 @@ export interface TxEvent {
readonly tx: TxBytes;
readonly hash: TxHash;
readonly height: number;
readonly index: number;
/** @deprecated this value is not set in Tendermint 0.34+ */
readonly index?: number;
readonly result: TxData;
}

View File

@ -15,7 +15,7 @@ function pendingWithoutTendermint(): void {
}
describe("WebsocketClient", () => {
const tendermintUrl = defaultInstance.url;
const { blockTime, url: tendermintUrl } = defaultInstance;
it("can make a simple call", async () => {
pendingWithoutTendermint();
@ -48,27 +48,27 @@ describe("WebsocketClient", () => {
const events: SubscriptionEvent[] = [];
const sub = headers.subscribe({
const subscription = headers.subscribe({
error: done.fail,
complete: () => done.fail("subscription should not complete"),
next: (evt: SubscriptionEvent) => {
events.push(evt);
expect(evt.query).toEqual(query);
next: (event: SubscriptionEvent) => {
events.push(event);
expect(event.query).toEqual(query);
if (events.length === 2) {
// make sure they are consequtive heights
const height = (i: number): number => Integer.parse(events[i].data.value.header.height);
expect(height(1)).toEqual(height(0) + 1);
sub.unsubscribe();
subscription.unsubscribe();
// wait 1.5s and check we did not get more events
// wait 1.5 * blockTime and check we did not get more events
setTimeout(() => {
expect(events.length).toEqual(2);
client.disconnect();
done();
}, 1500);
}, 1.5 * blockTime);
}
},
});
@ -110,23 +110,23 @@ describe("WebsocketClient", () => {
const events: SubscriptionEvent[] = [];
const sub = headers.subscribe({
const subscription = headers.subscribe({
error: done.fail,
complete: () => done.fail("subscription should not complete"),
next: (evt: SubscriptionEvent) => {
events.push(evt);
expect(evt.query).toEqual(query);
next: (event: SubscriptionEvent) => {
events.push(event);
expect(event.query).toEqual(query);
if (events.length === 2) {
sub.unsubscribe();
subscription.unsubscribe();
// wait 1.5s and check we did not get more events
// wait 1.5 * blockTime and check we did not get more events
setTimeout(() => {
expect(events.length).toEqual(2);
client.disconnect();
done();
}, 1500);
}, 1.5 * blockTime);
}
},
});
@ -148,7 +148,7 @@ describe("WebsocketClient", () => {
const receivedEvents: SubscriptionEvent[] = [];
setTimeout(() => client.disconnect(), 1500);
setTimeout(() => client.disconnect(), blockTime);
headers.subscribe({
error: done.fail,

View File

@ -619,7 +619,8 @@ interface RpcTxEvent {
readonly tx: Base64String;
readonly result: RpcTxData;
readonly height: IntegerString;
readonly index: number;
/** Not set since Tendermint 0.34 */
readonly index?: number;
}
function decodeTxEvent(data: RpcTxEvent): responses.TxEvent {
@ -629,7 +630,7 @@ function decodeTxEvent(data: RpcTxEvent): responses.TxEvent {
hash: hashTx(tx),
result: decodeTxData(data.result),
height: Integer.parse(assertNotEmpty(data.height)),
index: Integer.parse(assertNumber(data.index)),
index: may(Integer.parse, data.index),
};
}

View File

@ -120,7 +120,8 @@ export interface TxEvent {
readonly tx: TxBytes;
readonly hash: TxHash;
readonly height: number;
readonly index: number;
/** @deprecated this value is not set in Tendermint 0.34+ */
readonly index?: number;
readonly result: TxData;
}
/** An event attribute */

View File

@ -4,7 +4,8 @@ command -v shellcheck > /dev/null && shellcheck "$0"
# Find latest patch releases at https://hub.docker.com/r/tendermint/tendermint/tags/
declare -a TM_VERSIONS
TM_VERSIONS[33]=v0.33.5
TM_VERSIONS[33]=v0.33.8
TM_VERSIONS[34]=latest
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

View File

@ -3,7 +3,8 @@ set -o errexit -o nounset -o pipefail
command -v shellcheck > /dev/null && shellcheck "$0"
declare -a TM_VERSIONS
TM_VERSIONS[33]=v0.33.5
TM_VERSIONS[33]=v0.33.8
TM_VERSIONS[34]=latest
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

View File

@ -46,6 +46,7 @@ if [ -n "${CI:-}" ]; then
# Give process some time to come alive. No idea why this helps. Needed for CI.
sleep 0.5
# Follow the logs in CI's background job
tail -f "$LOGFILE"
# Debug start
sleep 3
cat "$LOGFILE"
fi