Skip to content

Commit

Permalink
Merge pull request #1173 from cosmos/tendermint-0.35
Browse files Browse the repository at this point in the history
Add Tendermint 0.35 client
  • Loading branch information
webmaster128 authored Jun 14, 2022
2 parents b72e561 + 2fe4d51 commit 42e39f9
Show file tree
Hide file tree
Showing 22 changed files with 3,678 additions and 21 deletions.
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ jobs:
#
# Available images: https://circleci.com/docs/2.0/configuration-reference/#available-machine-images
image: ubuntu-2004:202107-02
resource_class: large
steps:
- run:
name: Install Git Large File Storage (LFS)
Expand Down Expand Up @@ -322,6 +323,7 @@ jobs:
#
# Available images: https://circleci.com/docs/2.0/configuration-reference/#available-machine-images
image: ubuntu-2004:202107-02
resource_class: large
steps:
- browser-tools/install-chrome # Slow because apt update but what can you do 🤷‍
- run:
Expand Down Expand Up @@ -420,6 +422,7 @@ jobs:
#
# Available images: https://circleci.com/docs/2.0/configuration-reference/#available-machine-images
image: ubuntu-2004:202107-02
resource_class: large
steps:
- run:
name: Install Git Large File Storage (LFS)
Expand Down
3 changes: 3 additions & 0 deletions packages/tendermint-rpc/src/tendermint34/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ export interface NodeInfo {
/** IP and port */
readonly listenAddr: string;
readonly network: string;
/**
* The Tendermint version. Can be empty (see https://github.com/cosmos/cosmos-sdk/issues/7963).
*/
readonly version: string;
readonly channels: string; // ???
readonly moniker: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { Stream } from "xstream";
import { HttpClient, RpcClient, WebsocketClient } from "../rpcclients";
import {
buildKvTx,
chainIdMatcher,
ExpectedValues,
pendingWithoutTendermint,
randomString,
Expand Down Expand Up @@ -203,7 +202,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, expected: ExpectedValues)
block: expected.blockVersion,
app: expected.appVersion,
});
expect(status.nodeInfo.network).toMatch(chainIdMatcher);
expect(status.nodeInfo.network).toMatch(expected.chainId);
expect(status.nodeInfo.other.size).toBeGreaterThanOrEqual(2);
expect(status.nodeInfo.other.get("tx_index")).toEqual("on");

Expand Down Expand Up @@ -391,7 +390,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, expected: ExpectedValues)
block: expected.blockVersion,
app: expected.appVersion,
},
chainId: jasmine.stringMatching(chainIdMatcher),
chainId: jasmine.stringMatching(expected.chainId),
}),
);
expect(meta.numTxs).toBeInstanceOf(Number);
Expand Down Expand Up @@ -570,7 +569,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, expected: ExpectedValue
expect(stream).toBeTruthy();
const subscription = stream.subscribe({
next: (event) => {
expect(event.chainId).toMatch(chainIdMatcher);
expect(event.chainId).toMatch(expected.chainId);
expect(event.height).toBeGreaterThan(0);
// seems that tendermint just guarantees within the last second for timestamp
expect(event.time.getTime()).toBeGreaterThan(testStart - 1000);
Expand Down Expand Up @@ -627,7 +626,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, expected: ExpectedValue
const stream = client.subscribeNewBlock();
const subscription = stream.subscribe({
next: (event) => {
expect(event.header.chainId).toMatch(chainIdMatcher);
expect(event.header.chainId).toMatch(expected.chainId);
expect(event.header.height).toBeGreaterThan(0);
// seems that tendermint just guarantees within the last second for timestamp
expect(event.header.time.getTime()).toBeGreaterThan(testStart - 1000);
Expand Down Expand Up @@ -807,7 +806,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, expected: ExpectedValue
}

describe("Tendermint34Client", () => {
const { url, expected } = tendermintInstances[0];
const { url, expected } = tendermintInstances[34];

it("can connect to a given url", async () => {
pendingWithoutTendermint();
Expand Down
13 changes: 13 additions & 0 deletions packages/tendermint-rpc/src/tendermint35/adaptor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { hashBlock, hashTx } from "../hasher";
import { Params } from "./requests";
import { Responses } from "./responses";
import { Adaptor } from "./types";

export { Decoder, Encoder, Params, Responses } from "./types";

export const adaptor35: Adaptor = {
params: Params,
responses: Responses,
hashTx: hashTx,
hashBlock: hashBlock,
};
184 changes: 184 additions & 0 deletions packages/tendermint-rpc/src/tendermint35/adaptor/requests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { toBase64, toHex } from "@cosmjs/encoding";
import { JsonRpcRequest } from "@cosmjs/json-rpc";

import { createJsonRpcRequest } from "../../jsonrpc";
import { assertNotEmpty, Integer, may } from "../encodings";
import * as requests from "../requests";

interface HeightParam {
readonly height?: number;
}
interface RpcHeightParam {
readonly height?: string;
}
function encodeHeightParam(param: HeightParam): RpcHeightParam {
return {
height: may(Integer.encode, param.height),
};
}

interface RpcBlockchainRequestParams {
readonly minHeight?: string;
readonly maxHeight?: string;
}

function encodeBlockchainRequestParams(param: requests.BlockchainRequestParams): RpcBlockchainRequestParams {
return {
minHeight: may(Integer.encode, param.minHeight),
maxHeight: may(Integer.encode, param.maxHeight),
};
}

interface RpcBlockSearchParams {
readonly query: string;
readonly page?: string;
readonly per_page?: string;
readonly order_by?: string;
}
function encodeBlockSearchParams(params: requests.BlockSearchParams): RpcBlockSearchParams {
return {
query: params.query,
page: may(Integer.encode, params.page),
per_page: may(Integer.encode, params.per_page),
order_by: params.order_by,
};
}

interface RpcAbciQueryParams {
readonly path: string;
/** hex encoded */
readonly data: string;
readonly height?: string;
readonly prove?: boolean;
}

function encodeAbciQueryParams(params: requests.AbciQueryParams): RpcAbciQueryParams {
return {
path: assertNotEmpty(params.path),
data: toHex(params.data),
height: may(Integer.encode, params.height),
prove: params.prove,
};
}

interface RpcBroadcastTxParams {
/** base64 encoded */
readonly tx: string;
}
function encodeBroadcastTxParams(params: requests.BroadcastTxParams): RpcBroadcastTxParams {
return {
tx: toBase64(assertNotEmpty(params.tx)),
};
}

interface RpcTxParams {
/** hex encoded */
readonly hash: string;
readonly prove?: boolean;
}
function encodeTxParams(params: requests.TxParams): RpcTxParams {
return {
hash: toHex(assertNotEmpty(params.hash)),
prove: params.prove,
};
}

interface RpcTxSearchParams {
readonly query: string;
readonly prove?: boolean;
readonly page?: string;
readonly per_page?: string;
readonly order_by?: string;
}
function encodeTxSearchParams(params: requests.TxSearchParams): RpcTxSearchParams {
return {
query: params.query,
prove: params.prove,
page: may(Integer.encode, params.page),
per_page: may(Integer.encode, params.per_page),
order_by: params.order_by,
};
}

interface RpcValidatorsParams {
readonly height?: string;
readonly page?: string;
readonly per_page?: string;
}
function encodeValidatorsParams(params: requests.ValidatorsParams): RpcValidatorsParams {
return {
height: may(Integer.encode, params.height),
page: may(Integer.encode, params.page),
per_page: may(Integer.encode, params.per_page),
};
}

export class Params {
public static encodeAbciInfo(req: requests.AbciInfoRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method);
}

public static encodeAbciQuery(req: requests.AbciQueryRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeAbciQueryParams(req.params));
}

public static encodeBlock(req: requests.BlockRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeHeightParam(req.params));
}

public static encodeBlockchain(req: requests.BlockchainRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeBlockchainRequestParams(req.params));
}

public static encodeBlockResults(req: requests.BlockResultsRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeHeightParam(req.params));
}

public static encodeBlockSearch(req: requests.BlockSearchRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeBlockSearchParams(req.params));
}

public static encodeBroadcastTx(req: requests.BroadcastTxRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeBroadcastTxParams(req.params));
}

public static encodeCommit(req: requests.CommitRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeHeightParam(req.params));
}

public static encodeGenesis(req: requests.GenesisRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method);
}

public static encodeHealth(req: requests.HealthRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method);
}

public static encodeNumUnconfirmedTxs(req: requests.NumUnconfirmedTxsRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method);
}

public static encodeStatus(req: requests.StatusRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method);
}

public static encodeSubscribe(req: requests.SubscribeRequest): JsonRpcRequest {
const eventTag = { key: "tm.event", value: req.query.type };
const query = requests.buildQuery({ tags: [eventTag], raw: req.query.raw });
return createJsonRpcRequest("subscribe", { query: query });
}

public static encodeTx(req: requests.TxRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeTxParams(req.params));
}

// TODO: encode params for query string???
public static encodeTxSearch(req: requests.TxSearchRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeTxSearchParams(req.params));
}

public static encodeValidators(req: requests.ValidatorsRequest): JsonRpcRequest {
return createJsonRpcRequest(req.method, encodeValidatorsParams(req.params));
}
}
77 changes: 77 additions & 0 deletions packages/tendermint-rpc/src/tendermint35/adaptor/responses.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { fromBase64, fromHex } from "@cosmjs/encoding";

import { decodeValidatorGenesis, decodeValidatorInfo, decodeValidatorUpdate } from "./responses";

describe("Adaptor Responses", () => {
describe("decodeValidatorGenesis", () => {
it("works for genesis format", () => {
// from https://raw.githubusercontent.com/cosmos/mainnet/master/genesis.json
const validator = decodeValidatorGenesis({
address: "A03DC128D38DB0BC5F18AE1872F1CB2E1FD41157",
name: "真本聪&IOSG",
power: "169980",
pub_key: {
type: "tendermint/PubKeyEd25519",
value: "2BX6Zuj8RmdJAkD1BAg6KB0v04liyM7jBdwOGIb9F9Q=",
},
});
expect(validator).toEqual({
address: fromHex("A03DC128D38DB0BC5F18AE1872F1CB2E1FD41157"),
votingPower: 169980,
pubkey: {
algorithm: "ed25519",
data: fromBase64("2BX6Zuj8RmdJAkD1BAg6KB0v04liyM7jBdwOGIb9F9Q="),
},
});
});
});

describe("decodeValidatorUpdate", () => {
it("works for block results format", () => {
// from https://rpc.cosmos.network/block_results?height=10539773
const update = decodeValidatorUpdate({
pub_key: {
Sum: {
type: "tendermint.crypto.PublicKey_Ed25519",
value: {
ed25519: "0kNlxBMpm+5WtfHIG1xsWatOXTKPLtmSqn3EiEIDZeI=",
},
},
},
power: "11418237",
});
expect(update).toEqual({
pubkey: {
algorithm: "ed25519",
data: fromBase64("0kNlxBMpm+5WtfHIG1xsWatOXTKPLtmSqn3EiEIDZeI="),
},
votingPower: 11418237,
});
});
});

describe("decodeValidatorInfo", () => {
it("works for validators format", () => {
// from https://rpc.cosmos.network/validators?height=10601034
const info = decodeValidatorInfo({
address: "AC2D56057CD84765E6FBE318979093E8E44AA18F",
pub_key: {
type: "tendermint/PubKeyEd25519",
value: "0kNlxBMpm+5WtfHIG1xsWatOXTKPLtmSqn3EiEIDZeI=",
},
voting_power: "11228980",
proposer_priority: "62870960",
});
expect(info).toEqual({
address: fromHex("AC2D56057CD84765E6FBE318979093E8E44AA18F"),
pubkey: {
algorithm: "ed25519",
data: fromBase64("0kNlxBMpm+5WtfHIG1xsWatOXTKPLtmSqn3EiEIDZeI="),
},
votingPower: 11228980,
proposerPriority: 62870960,
});
});
});
});
Loading

0 comments on commit 42e39f9

Please sign in to comment.