From caf5ff7ce89df50eb8b89bade9afdff0185eea62 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Mon, 15 Jun 2020 16:47:55 +0100 Subject: [PATCH] tendermint-rpc: Remove v0.31 support --- packages/tendermint-rpc/README.md | 6 +- .../tendermint-rpc/src/adaptorforversion.ts | 6 +- packages/tendermint-rpc/src/config.spec.ts | 5 - packages/tendermint-rpc/src/index.ts | 2 +- .../tendermint-rpc/src/v0-31/hasher.spec.ts | 98 --- packages/tendermint-rpc/src/v0-31/hasher.ts | 71 -- packages/tendermint-rpc/src/v0-31/index.ts | 12 - packages/tendermint-rpc/src/v0-31/requests.ts | 142 ---- .../tendermint-rpc/src/v0-31/responses.ts | 773 ------------------ packages/tendermint-rpc/types/index.d.ts | 1 - .../tendermint-rpc/types/v0-31/hasher.d.ts | 4 - .../tendermint-rpc/types/v0-31/index.d.ts | 2 - .../tendermint-rpc/types/v0-31/requests.d.ts | 18 - .../tendermint-rpc/types/v0-31/responses.d.ts | 23 - 14 files changed, 5 insertions(+), 1158 deletions(-) delete mode 100644 packages/tendermint-rpc/src/v0-31/hasher.spec.ts delete mode 100644 packages/tendermint-rpc/src/v0-31/hasher.ts delete mode 100644 packages/tendermint-rpc/src/v0-31/index.ts delete mode 100644 packages/tendermint-rpc/src/v0-31/requests.ts delete mode 100644 packages/tendermint-rpc/src/v0-31/responses.ts delete mode 100644 packages/tendermint-rpc/types/v0-31/hasher.d.ts delete mode 100644 packages/tendermint-rpc/types/v0-31/index.d.ts delete mode 100644 packages/tendermint-rpc/types/v0-31/requests.d.ts delete mode 100644 packages/tendermint-rpc/types/v0-31/responses.d.ts diff --git a/packages/tendermint-rpc/README.md b/packages/tendermint-rpc/README.md index 0b7db502..95b6126f 100644 --- a/packages/tendermint-rpc/README.md +++ b/packages/tendermint-rpc/README.md @@ -16,9 +16,7 @@ automatically, and call: ```ts import { Client } from "@iov/tendermint-rpc"; -const client = await Client.connect( - "ws://rpc-private-a-x-exchangenet.iov.one:16657", -); +const client = await Client.connect("ws://rpc-private-a-x-exchangenet.iov.one:16657"); const genesis = await client.genesis(); const status = await client.status(); @@ -69,7 +67,7 @@ and another for decoding [Responses](https://iov-one.github.io/iov-core-docs/latest/iov-tendermint-rpc/classes/responses.html). The Tendermint version-specific functionality is implemented in global objects (like e.g. -[v0_31](https://iov-one.github.io/iov-core-docs/latest/iov-tendermint-rpc/globals.html#v0_31)). +[v0_32](https://iov-one.github.io/iov-core-docs/latest/iov-tendermint-rpc/globals.html#v0_32)). This knowledge is mainly for those who want to add support for new versions, which should be added to the [auto-detect method](https://iov-one.github.io/iov-core-docs/latest/iov-tendermint-rpc/classes/client.html#detectversion). diff --git a/packages/tendermint-rpc/src/adaptorforversion.ts b/packages/tendermint-rpc/src/adaptorforversion.ts index 5196b077..da7c0e6d 100644 --- a/packages/tendermint-rpc/src/adaptorforversion.ts +++ b/packages/tendermint-rpc/src/adaptorforversion.ts @@ -1,7 +1,7 @@ +/* eslint-disable @typescript-eslint/camelcase */ // This module exposes translators for multiple tendermint versions // Pick a version that matches the server to properly encode the data types import { Adaptor } from "./adaptor"; -import { v0_31 } from "./v0-31"; import { v0_32 } from "./v0-32"; /** @@ -11,9 +11,7 @@ import { v0_32 } from "./v0-32"; * @param version full Tendermint version string, e.g. "0.20.1" */ export function adaptorForVersion(version: string): Adaptor { - if (version.startsWith("0.31.")) { - return v0_31; - } else if (version.startsWith("0.32.")) { + if (version.startsWith("0.32.")) { return v0_32; } else { throw new Error(`Unsupported tendermint version: ${version}`); diff --git a/packages/tendermint-rpc/src/config.spec.ts b/packages/tendermint-rpc/src/config.spec.ts index f30aef54..68b28804 100644 --- a/packages/tendermint-rpc/src/config.spec.ts +++ b/packages/tendermint-rpc/src/config.spec.ts @@ -17,11 +17,6 @@ export interface TendermintInstance { * docker container kill */ export const tendermintInstances: readonly TendermintInstance[] = [ - { - url: "localhost:11131", - version: "0.31.x", - appCreator: "Cosmoshi Netowoko", - }, { url: "localhost:11132", version: "0.32.x", diff --git a/packages/tendermint-rpc/src/index.ts b/packages/tendermint-rpc/src/index.ts index f3b010ef..9fe8c2ac 100644 --- a/packages/tendermint-rpc/src/index.ts +++ b/packages/tendermint-rpc/src/index.ts @@ -1,5 +1,5 @@ +/* eslint-disable @typescript-eslint/camelcase */ // exported to access version-specific hashing -export { v0_31 } from "./v0-31"; export { v0_32 } from "./v0-32"; export { Client } from "./client"; diff --git a/packages/tendermint-rpc/src/v0-31/hasher.spec.ts b/packages/tendermint-rpc/src/v0-31/hasher.spec.ts deleted file mode 100644 index 95b8aea4..00000000 --- a/packages/tendermint-rpc/src/v0-31/hasher.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { fromBase64, fromHex } from "@cosmjs/encoding"; -import { ReadonlyDate } from "readonly-date"; - -import { ReadonlyDateWithNanoseconds } from "../responses"; -import { TxBytes } from "../types"; -import { hashBlock, hashTx } from "./hasher"; - -describe("Hasher", () => { - it("creates transaction hash equal to local test", () => { - // This was taken from a result from /tx_search of some random test transaction - // curl "http://localhost:11127/tx_search?query=\"tx.hash='5CB2CF94A1097A4BC19258BC2353C3E76102B6D528458BE45C855DC5563C1DB2'\"" - const txId = fromHex("5CB2CF94A1097A4BC19258BC2353C3E76102B6D528458BE45C855DC5563C1DB2"); - const txData = fromBase64("YUpxZDY2NURaUDMxPWd2TzBPdnNrVWFWYg==") as TxBytes; - expect(hashTx(txData)).toEqual(txId); - }); - - it("creates block hash equal to local test for empty block", () => { - // This was taken from a result from /block of some random empty block - // curl "http://localhost:11131/block" - const blockId = fromHex("5B5D3F7E77A4BD6CB6067947E478BC3BD493DD24A981535F0ADEBDAAA0498480"); - const time = new ReadonlyDate("2019-09-19T10:41:24.898178746Z"); - // tslint:disable-next-line:no-object-mutation - (time as any).nanoseconds = 178746; - const blockData = { - version: { - block: 10, - app: 1, - }, - chainId: "test-chain-RRlV24", - height: 2195, - time: time as ReadonlyDateWithNanoseconds, - numTxs: 0, - totalTxs: 20, - - lastBlockId: { - hash: fromHex("1D38C4FE5C1D8C3CC1F47602BF107C9B269BA7DA3514DEDF958F5A33AB75C06B"), - parts: { - total: 1, - hash: fromHex("C441341B7D846DDA6AF72F83DF68C9AF93665FE5280B136CA29C7411D280DAEC"), - }, - }, - - lastCommitHash: fromHex("0C5EEF7AE1275337BFAA173F57799AA90830E74AFF3FB03D1F579DA37BCAEAB1"), - dataHash: fromHex(""), - - validatorsHash: fromHex("44D7D0BE3C70B58DA87696102E3A52E5C9FA98A717E56D02987DA8CAE86F03F4"), - nextValidatorsHash: fromHex("44D7D0BE3C70B58DA87696102E3A52E5C9FA98A717E56D02987DA8CAE86F03F4"), - consensusHash: fromHex("048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F"), - appHash: fromHex("2800000000000000"), - lastResultsHash: fromHex(""), - - evidenceHash: fromHex(""), - proposerAddress: fromHex("057B8C349E591579EDFCC0E5D5402E3076E99675"), - }; - expect(hashBlock(blockData)).toEqual(blockId); - }); - - it("creates block hash equal to local test for block with a transaction", () => { - // This was taken from a result from /block of some random block with a transaction - // curl "http://localhost:11131/block?height=5940" - const blockId = fromHex("1C4777AFBBA49E15D031A830E62E7BE986823938732B872C02B8A3D16BD3163B"); - const time = new ReadonlyDate("2019-09-24T10:51:28.240847497Z"); - // tslint:disable-next-line:no-object-mutation - (time as any).nanoseconds = 847497; - const blockData = { - version: { - block: 10, - app: 1, - }, - chainId: "test-chain-lY9FO6", - height: 5940, - time: time as ReadonlyDateWithNanoseconds, - numTxs: 1, - totalTxs: 61, - - lastBlockId: { - hash: fromHex("D2983E6AEEFC55E0A46565CD2274CCD21CB013F5602B0C35A423A99D1120DB13"), - parts: { - total: 1, - hash: fromHex("AA55D7F92AD3A9CFDA8C5E45F95B03AEF9FB38AB984FD762E5CE20791324369D"), - }, - }, - - lastCommitHash: fromHex("5DBFFDBE41878AEB947176D3E0B0DC70850B0A61F8B709ED132FEA59664DFCE5"), - dataHash: fromHex("90FE1A62418F68B411915EEF6792B134693D9D0148432BA661D91213B0CCD15A"), - - validatorsHash: fromHex("0A4647900ED90CC605E851BBB4946D7B9D1830F293BC87F3CE16AEFF4E4C77E2"), - nextValidatorsHash: fromHex("0A4647900ED90CC605E851BBB4946D7B9D1830F293BC87F3CE16AEFF4E4C77E2"), - consensusHash: fromHex("048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F"), - appHash: fromHex("7800000000000000"), - lastResultsHash: fromHex("6E340B9CFFB37A989CA544E6BB780A2C78901D3FB33738768511A30617AFA01D"), - - evidenceHash: fromHex(""), - proposerAddress: fromHex("6BCBB90987613FE15D3DEFA4920E9F98425698FF"), - }; - expect(hashBlock(blockData)).toEqual(blockId); - }); -}); diff --git a/packages/tendermint-rpc/src/v0-31/hasher.ts b/packages/tendermint-rpc/src/v0-31/hasher.ts deleted file mode 100644 index eba23929..00000000 --- a/packages/tendermint-rpc/src/v0-31/hasher.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Sha256 } from "@cosmjs/crypto"; - -import { encodeBlockId, encodeBytes, encodeInt, encodeString, encodeTime, encodeVersion } from "../encodings"; -import { Header } from "../responses"; -import { BlockHash, TxBytes, TxHash } from "../types"; - -// hash is sha256 -// https://github.com/tendermint/tendermint/blob/master/UPGRADING.md#v0260 -export function hashTx(tx: TxBytes): TxHash { - const hash = new Sha256(tx).digest(); - return hash as TxHash; -} - -function getSplitPoint(n: number): number { - if (n < 1) throw new Error("Cannot split an empty tree"); - const largestPowerOf2 = 2 ** Math.floor(Math.log2(n)); - return largestPowerOf2 < n ? largestPowerOf2 : largestPowerOf2 / 2; -} - -function hashLeaf(leaf: Uint8Array): Uint8Array { - const hash = new Sha256(Uint8Array.from([0])); - hash.update(leaf); - return hash.digest(); -} - -function hashInner(left: Uint8Array, right: Uint8Array): Uint8Array { - const hash = new Sha256(Uint8Array.from([1])); - hash.update(left); - hash.update(right); - return hash.digest(); -} - -// See https://github.com/tendermint/tendermint/blob/v0.31.8/docs/spec/blockchain/encoding.md#merkleroot -// Note: the hashes input may not actually be hashes, especially before a recursive call -function hashTree(hashes: readonly Uint8Array[]): Uint8Array { - switch (hashes.length) { - case 0: - throw new Error("Cannot hash empty tree"); - case 1: - return hashLeaf(hashes[0]); - default: { - const slicePoint = getSplitPoint(hashes.length); - const left = hashTree(hashes.slice(0, slicePoint)); - const right = hashTree(hashes.slice(slicePoint)); - return hashInner(left, right); - } - } -} - -export function hashBlock(header: Header): BlockHash { - const encodedFields: readonly Uint8Array[] = [ - encodeVersion(header.version), - encodeString(header.chainId), - encodeInt(header.height), - encodeTime(header.time), - encodeInt(header.numTxs), - encodeInt(header.totalTxs), - encodeBlockId(header.lastBlockId), - - encodeBytes(header.lastCommitHash), - encodeBytes(header.dataHash), - encodeBytes(header.validatorsHash), - encodeBytes(header.nextValidatorsHash), - encodeBytes(header.consensusHash), - encodeBytes(header.appHash), - encodeBytes(header.lastResultsHash), - encodeBytes(header.evidenceHash), - encodeBytes(header.proposerAddress), - ]; - return hashTree(encodedFields) as BlockHash; -} diff --git a/packages/tendermint-rpc/src/v0-31/index.ts b/packages/tendermint-rpc/src/v0-31/index.ts deleted file mode 100644 index cdb29496..00000000 --- a/packages/tendermint-rpc/src/v0-31/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Adaptor } from "../adaptor"; -import { hashBlock, hashTx } from "./hasher"; -import { Params } from "./requests"; -import { Responses } from "./responses"; - -// tslint:disable-next-line:variable-name -export const v0_31: Adaptor = { - params: Params, - responses: Responses, - hashTx: hashTx, - hashBlock: hashBlock, -}; diff --git a/packages/tendermint-rpc/src/v0-31/requests.ts b/packages/tendermint-rpc/src/v0-31/requests.ts deleted file mode 100644 index 7526fe0a..00000000 --- a/packages/tendermint-rpc/src/v0-31/requests.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { toHex } from "@cosmjs/encoding"; -import { JsonRpcRequest } from "@iov/jsonrpc"; - -import { assertNotEmpty, Base64, Base64String, HexString, Integer, IntegerString, may } from "../encodings"; -import { createJsonRpcRequest } from "../jsonrpc"; -import * as requests from "../requests"; - -interface HeightParam { - readonly height?: number; -} -interface RpcHeightParam { - readonly height?: IntegerString; -} -function encodeHeightParam(param: HeightParam): RpcHeightParam { - return { - height: may(Integer.encode, param.height), - }; -} - -interface RpcBlockchainRequestParams { - readonly minHeight?: IntegerString; - readonly maxHeight?: IntegerString; -} -function encodeBlockchainRequestParams(param: requests.BlockchainRequestParams): RpcBlockchainRequestParams { - return { - minHeight: may(Integer.encode, param.minHeight), - maxHeight: may(Integer.encode, param.maxHeight), - }; -} - -interface RpcAbciQueryParams { - readonly path: string; - readonly data: HexString; - readonly height?: string; - readonly prove?: boolean; -} - -function encodeAbciQueryParams(params: requests.AbciQueryParams): RpcAbciQueryParams { - return { - path: assertNotEmpty(params.path), - data: toHex(params.data) as HexString, - height: may(Integer.encode, params.height), - prove: params.prove, - }; -} - -interface RpcBroadcastTxParams { - readonly tx: Base64String; -} -function encodeBroadcastTxParams(params: requests.BroadcastTxParams): RpcBroadcastTxParams { - return { - tx: Base64.encode(assertNotEmpty(params.tx)), - }; -} - -interface RpcTxParams { - readonly hash: Base64String; - readonly prove?: boolean; -} -function encodeTxParams(params: requests.TxParams): RpcTxParams { - return { - hash: Base64.encode(assertNotEmpty(params.hash)), - prove: params.prove, - }; -} - -interface RpcTxSearchParams { - readonly query: requests.QueryString; - readonly prove?: boolean; - readonly page?: IntegerString; - readonly per_page?: IntegerString; -} -function encodeTxSearchParams(params: requests.TxSearchParams): RpcTxSearchParams { - return { - query: params.query, - prove: params.prove, - page: may(Integer.encode, params.page), - // eslint-disable-next-line @typescript-eslint/camelcase - 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 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 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, encodeHeightParam(req.params)); - } -} diff --git a/packages/tendermint-rpc/src/v0-31/responses.ts b/packages/tendermint-rpc/src/v0-31/responses.ts deleted file mode 100644 index 86ea149a..00000000 --- a/packages/tendermint-rpc/src/v0-31/responses.ts +++ /dev/null @@ -1,773 +0,0 @@ -import { fromHex } from "@cosmjs/encoding"; -import { JsonRpcSuccessResponse } from "@iov/jsonrpc"; - -import { - assertArray, - assertBoolean, - assertNotEmpty, - assertNumber, - assertObject, - assertSet, - Base64, - Base64String, - DateTime, - DateTimeString, - dictionaryToStringMap, - Hex, - HexString, - Integer, - IntegerString, - may, - optional, -} from "../encodings"; -import * as responses from "../responses"; -import { SubscriptionEvent } from "../rpcclients"; -import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "../types"; -import { hashTx } from "./hasher"; - -interface AbciInfoResult { - readonly response: RpcAbciInfoResponse; -} - -interface RpcAbciInfoResponse { - readonly data?: string; - readonly last_block_height?: IntegerString; - readonly last_block_app_hash?: Base64String; -} - -function decodeAbciInfo(data: RpcAbciInfoResponse): responses.AbciInfoResponse { - return { - data: data.data, - lastBlockHeight: may(Integer.parse, data.last_block_height), - lastBlockAppHash: may(Base64.decode, data.last_block_app_hash), - }; -} - -interface AbciQueryResult { - readonly response: RpcAbciQueryResponse; -} - -interface RpcAbciQueryResponse { - readonly key: Base64String; - readonly value?: Base64String; - readonly proof?: Base64String; - readonly height?: IntegerString; - readonly index?: IntegerString; - readonly code?: IntegerString; // only for errors - readonly log?: string; -} - -function decodeAbciQuery(data: RpcAbciQueryResponse): responses.AbciQueryResponse { - return { - key: Base64.decode(optional(data.key, "" as Base64String)), - value: Base64.decode(optional(data.value, "" as Base64String)), - // proof: may(Base64.decode, data.proof), - height: may(Integer.parse, data.height), - code: may(Integer.parse, data.code), - index: may(Integer.parse, data.index), - log: data.log, - }; -} -interface RpcTag { - readonly key: Base64String; - readonly value: Base64String; -} - -function decodeTag(tag: RpcTag): responses.Tag { - return { - key: Base64.decode(assertNotEmpty(tag.key)), - value: Base64.decode(assertNotEmpty(tag.value)), - }; -} - -function decodeTags(tags: readonly RpcTag[]): readonly responses.Tag[] { - return assertArray(tags).map(decodeTag); -} - -interface RpcTxData { - readonly code?: number; - readonly log?: string; - readonly data?: Base64String; - readonly tags?: readonly RpcTag[]; -} - -function decodeTxData(data: RpcTxData): responses.TxData { - return { - data: may(Base64.decode, data.data), - log: data.log, - code: Integer.parse(assertNumber(optional(data.code, 0))), - tags: may(decodeTags, data.tags), - }; -} - -// yes, a different format for status and dump consensus state -interface RpcPubkey { - readonly type: string; - readonly value: Base64String; -} - -function decodePubkey(data: RpcPubkey): ValidatorPubkey { - if (data.type === "tendermint/PubKeyEd25519") { - // go-amino special code - return { - algorithm: "ed25519", - data: Base64.decode(assertNotEmpty(data.value)), - }; - } - throw new Error(`unknown pubkey type: ${data.type}`); -} - -// for evidence, block results, etc. -interface RpcValidatorUpdate { - readonly address: HexString; - readonly pub_key: RpcPubkey; - readonly voting_power: IntegerString; -} - -function decodeValidatorUpdate(data: RpcValidatorUpdate): responses.Validator { - return { - pubkey: decodePubkey(assertObject(data.pub_key)), - votingPower: Integer.parse(assertNotEmpty(data.voting_power)), - address: Hex.decode(assertNotEmpty(data.address)), - }; -} - -interface RpcBlockParams { - readonly max_bytes: IntegerString; - readonly max_gas: IntegerString; -} - -/** - * Note: we do not parse block.time_iota_ms for now because of this CHANGELOG entry - * - * > Add time_iota_ms to block's consensus parameters (not exposed to the application) - * https://github.com/tendermint/tendermint/blob/master/CHANGELOG.md#v0310 - */ -function decodeBlockParams(data: RpcBlockParams): responses.BlockParams { - return { - maxBytes: Integer.parse(assertNotEmpty(data.max_bytes)), - maxGas: Integer.parse(assertNotEmpty(data.max_gas)), - }; -} - -interface RpcEvidenceParams { - readonly max_age: IntegerString; -} - -function decodeEvidenceParams(data: RpcEvidenceParams): responses.EvidenceParams { - return { - maxAge: Integer.parse(assertNotEmpty(data.max_age)), - }; -} - -/** - * Example data: - * { - * "block": { - * "max_bytes": "22020096", - * "max_gas": "-1", - * "time_iota_ms": "1000" - * }, - * "evidence": { - * "max_age": "100000" - * }, - * "validator": { - * "pub_key_types": [ - * "ed25519" - * ] - * } - * } - */ -interface RpcConsensusParams { - readonly block: RpcBlockParams; - readonly evidence: RpcEvidenceParams; -} - -function decodeConsensusParams(data: RpcConsensusParams): responses.ConsensusParams { - return { - block: decodeBlockParams(assertObject(data.block)), - evidence: decodeEvidenceParams(assertObject(data.evidence)), - }; -} - -interface RpcBlockResultsResponse { - readonly height: IntegerString; - readonly results: { - readonly DeliverTx: readonly RpcTxData[]; - readonly EndBlock: { - readonly validator_updates?: readonly RpcValidatorUpdate[]; - readonly consensus_param_updates?: RpcConsensusParams; - readonly tags?: readonly RpcTag[]; - }; - }; -} - -function decodeBlockResults(data: RpcBlockResultsResponse): responses.BlockResultsResponse { - const res = optional(data.results.DeliverTx, [] as readonly RpcTxData[]); - const end = data.results.EndBlock; - const validators = optional(end.validator_updates, [] as readonly RpcValidatorUpdate[]); - return { - height: Integer.parse(assertNotEmpty(data.height)), - results: assertArray(res).map(decodeTxData), - endBlock: { - validatorUpdates: assertArray(validators).map(decodeValidatorUpdate), - consensusUpdates: may(decodeConsensusParams, end.consensus_param_updates), - tags: may(decodeTags, end.tags), - }, - }; -} - -interface RpcBlockId { - readonly hash: HexString; - readonly parts: { - readonly total: IntegerString; - readonly hash: HexString; - }; -} - -function decodeBlockId(data: RpcBlockId): responses.BlockId { - return { - hash: fromHex(assertNotEmpty(data.hash)), - parts: { - total: Integer.parse(assertNotEmpty(data.parts.total)), - hash: fromHex(assertNotEmpty(data.parts.hash)), - }, - }; -} - -interface RpcBlockVersion { - readonly block: IntegerString; - readonly app: IntegerString; -} - -function decodeBlockVersion(data: RpcBlockVersion): responses.Version { - return { - block: Integer.parse(data.block), - app: Integer.parse(data.app), - }; -} - -interface RpcHeader { - readonly version: RpcBlockVersion; - readonly chain_id: string; - readonly height: IntegerString; - readonly time: DateTimeString; - readonly num_txs: IntegerString; - readonly total_txs: IntegerString; - - readonly last_block_id: RpcBlockId; - - readonly last_commit_hash: HexString; - readonly data_hash: HexString; - - readonly validators_hash: HexString; - readonly next_validators_hash: HexString; - readonly consensus_hash: HexString; - readonly app_hash: HexString; - readonly last_results_hash: HexString; - - readonly evidence_hash: HexString; - readonly proposer_address: HexString; -} - -function decodeHeader(data: RpcHeader): responses.Header { - return { - version: decodeBlockVersion(data.version), - chainId: assertNotEmpty(data.chain_id), - height: Integer.parse(assertNotEmpty(data.height)), - time: DateTime.decode(assertNotEmpty(data.time)), - numTxs: Integer.parse(assertNotEmpty(data.num_txs)), - totalTxs: Integer.parse(assertNotEmpty(data.total_txs)), - - lastBlockId: decodeBlockId(data.last_block_id), - - lastCommitHash: fromHex(assertNotEmpty(data.last_commit_hash)), - dataHash: fromHex(assertSet(data.data_hash)), - - validatorsHash: fromHex(assertNotEmpty(data.validators_hash)), - nextValidatorsHash: fromHex(assertNotEmpty(data.next_validators_hash)), - consensusHash: fromHex(assertNotEmpty(data.consensus_hash)), - appHash: fromHex(assertNotEmpty(data.app_hash)), - lastResultsHash: fromHex(assertSet(data.last_results_hash)), - - evidenceHash: fromHex(assertSet(data.evidence_hash)), - proposerAddress: fromHex(assertNotEmpty(data.proposer_address)), - }; -} - -interface RpcBlockMeta { - readonly block_id: RpcBlockId; - readonly header: RpcHeader; -} - -function decodeBlockMeta(data: RpcBlockMeta): responses.BlockMeta { - return { - blockId: decodeBlockId(data.block_id), - header: decodeHeader(data.header), - }; -} - -interface RpcBlockchainResponse { - readonly last_height: IntegerString; - readonly block_metas: readonly RpcBlockMeta[]; -} - -function decodeBlockchain(data: RpcBlockchainResponse): responses.BlockchainResponse { - return { - lastHeight: Integer.parse(assertNotEmpty(data.last_height)), - blockMetas: assertArray(data.block_metas).map(decodeBlockMeta), - }; -} - -interface RpcBroadcastTxSyncResponse extends RpcTxData { - readonly hash: HexString; -} - -function decodeBroadcastTxSync(data: RpcBroadcastTxSyncResponse): responses.BroadcastTxSyncResponse { - return { - ...decodeTxData(data), - hash: fromHex(assertNotEmpty(data.hash)) as TxHash, - }; -} - -interface RpcBroadcastTxCommitResponse { - readonly height?: IntegerString; - readonly hash: HexString; - readonly check_tx: RpcTxData; - readonly deliver_tx?: RpcTxData; -} - -function decodeBroadcastTxCommit(data: RpcBroadcastTxCommitResponse): responses.BroadcastTxCommitResponse { - return { - height: may(Integer.parse, data.height), - hash: fromHex(assertNotEmpty(data.hash)) as TxHash, - checkTx: decodeTxData(assertObject(data.check_tx)), - deliverTx: may(decodeTxData, data.deliver_tx), - }; -} - -type RpcSignature = Base64String; - -function decodeSignature(data: RpcSignature): ValidatorSignature { - return { - algorithm: "ed25519", - data: Base64.decode(assertNotEmpty(data)), - }; -} - -interface RpcVote { - readonly type: number; - readonly validator_address: HexString; - readonly validator_index: IntegerString; - readonly height: IntegerString; - readonly round: IntegerString; - readonly timestamp: DateTimeString; - readonly block_id: RpcBlockId; - readonly signature: RpcSignature; -} - -function decodeVote(data: RpcVote): responses.Vote { - return { - type: Integer.parse(assertNumber(data.type)), - validatorAddress: fromHex(assertNotEmpty(data.validator_address)), - validatorIndex: Integer.parse(assertNotEmpty(data.validator_index)), - height: Integer.parse(assertNotEmpty(data.height)), - round: Integer.parse(assertNotEmpty(data.round)), - timestamp: DateTime.decode(assertNotEmpty(data.timestamp)), - blockId: decodeBlockId(assertObject(data.block_id)), - signature: decodeSignature(assertNotEmpty(data.signature)), - }; -} - -interface RpcCommit { - readonly block_id: RpcBlockId; - readonly precommits: readonly RpcVote[]; -} - -function decodeCommit(data: RpcCommit): responses.Commit { - return { - blockId: decodeBlockId(assertObject(data.block_id)), - precommits: assertArray(data.precommits).map(decodeVote), - }; -} - -interface RpcCommitResponse { - readonly signed_header: { - readonly header: RpcHeader; - readonly commit: RpcCommit; - }; - readonly canonical: boolean; -} - -function decodeCommitResponse(data: RpcCommitResponse): responses.CommitResponse { - return { - canonical: assertBoolean(data.canonical), - header: decodeHeader(data.signed_header.header), - commit: decodeCommit(data.signed_header.commit), - }; -} - -interface RpcValidatorGenesis { - readonly pub_key: RpcPubkey; - readonly power: IntegerString; - readonly name?: string; -} - -function decodeValidatorGenesis(data: RpcValidatorGenesis): responses.Validator { - return { - pubkey: decodePubkey(assertObject(data.pub_key)), - votingPower: Integer.parse(assertNotEmpty(data.power)), - name: data.name, - }; -} - -interface RpcGenesisResponse { - readonly genesis_time: DateTimeString; - readonly chain_id: string; - readonly consensus_params: RpcConsensusParams; - readonly validators: readonly RpcValidatorGenesis[]; - readonly app_hash: HexString; - readonly app_state: {} | undefined; -} - -interface GenesisResult { - readonly genesis: RpcGenesisResponse; -} - -function decodeGenesis(data: RpcGenesisResponse): responses.GenesisResponse { - return { - genesisTime: DateTime.decode(assertNotEmpty(data.genesis_time)), - chainId: assertNotEmpty(data.chain_id), - consensusParams: decodeConsensusParams(data.consensus_params), - validators: assertArray(data.validators).map(decodeValidatorGenesis), - appHash: fromHex(assertSet(data.app_hash)), // empty string in kvstore app - appState: data.app_state, - }; -} - -// this is in status -interface RpcValidatorInfo { - readonly address: HexString; - readonly pub_key: RpcPubkey; - readonly voting_power: IntegerString; -} - -function decodeValidatorInfo(data: RpcValidatorInfo): responses.Validator { - return { - pubkey: decodePubkey(assertObject(data.pub_key)), - votingPower: Integer.parse(assertNotEmpty(data.voting_power)), - address: fromHex(assertNotEmpty(data.address)), - }; -} - -interface RpcNodeInfo { - readonly id: HexString; - readonly listen_addr: IpPortString; - readonly network: string; - readonly version: string; - readonly channels: string; // ??? - readonly moniker: string; - readonly protocol_version: { - readonly p2p: IntegerString; - readonly block: IntegerString; - readonly app: IntegerString; - }; - /** - * Additional information. E.g. - * { - * "tx_index": "on", - * "rpc_address":"tcp://0.0.0.0:26657" - * } - */ - readonly other: object; -} - -function decodeNodeInfo(data: RpcNodeInfo): responses.NodeInfo { - return { - id: fromHex(assertNotEmpty(data.id)), - listenAddr: assertNotEmpty(data.listen_addr), - network: assertNotEmpty(data.network), - version: assertNotEmpty(data.version), - channels: assertNotEmpty(data.channels), - moniker: assertNotEmpty(data.moniker), - other: dictionaryToStringMap(data.other), - protocolVersion: { - app: Integer.parse(assertNotEmpty(data.protocol_version.app)), - block: Integer.parse(assertNotEmpty(data.protocol_version.block)), - p2p: Integer.parse(assertNotEmpty(data.protocol_version.p2p)), - }, - }; -} - -interface RpcSyncInfo { - readonly latest_block_hash: HexString; - readonly latest_app_hash: HexString; - readonly latest_block_height: IntegerString; - readonly latest_block_time: DateTimeString; - readonly catching_up: boolean; -} - -function decodeSyncInfo(data: RpcSyncInfo): responses.SyncInfo { - return { - latestBlockHash: fromHex(assertNotEmpty(data.latest_block_hash)), - latestAppHash: fromHex(assertNotEmpty(data.latest_app_hash)), - latestBlockTime: DateTime.decode(assertNotEmpty(data.latest_block_time)), - latestBlockHeight: Integer.parse(assertNotEmpty(data.latest_block_height)), - catchingUp: assertBoolean(data.catching_up), - }; -} - -interface RpcStatusResponse { - readonly node_info: RpcNodeInfo; - readonly sync_info: RpcSyncInfo; - readonly validator_info: RpcValidatorInfo; -} - -function decodeStatus(data: RpcStatusResponse): responses.StatusResponse { - return { - nodeInfo: decodeNodeInfo(data.node_info), - syncInfo: decodeSyncInfo(data.sync_info), - validatorInfo: decodeValidatorInfo(data.validator_info), - }; -} - -/** - * Example data: - * { - * "RootHash": "10A1A17D5F818099B5CAB5B91733A3CC27C0DB6CE2D571AC27FB970C314308BB", - * "Data": "ZVlERVhDV2lVNEUwPXhTUjc4Tmp2QkNVSg==", - * "Proof": { - * "total": "1", - * "index": "0", - * "leaf_hash": "EKGhfV+BgJm1yrW5FzOjzCfA22zi1XGsJ/uXDDFDCLs=", - * "aunts": [] - * } - * } - */ -interface RpcTxProof { - readonly Data: Base64String; - readonly RootHash: HexString; - readonly Proof: { - readonly total: IntegerString; - readonly index: IntegerString; - readonly leaf_hash: Base64String; - readonly aunts: readonly Base64String[]; - }; -} - -function decodeTxProof(data: RpcTxProof): responses.TxProof { - return { - data: Base64.decode(assertNotEmpty(data.Data)), - rootHash: fromHex(assertNotEmpty(data.RootHash)), - proof: { - total: Integer.parse(assertNotEmpty(data.Proof.total)), - index: Integer.parse(assertNotEmpty(data.Proof.index)), - leafHash: Base64.decode(assertNotEmpty(data.Proof.leaf_hash)), - aunts: assertArray(data.Proof.aunts).map(Base64.decode), - }, - }; -} - -interface RpcTxResponse { - readonly tx: Base64String; - readonly tx_result: RpcTxData; - readonly height: IntegerString; - readonly index: number; - readonly hash: HexString; - readonly proof?: RpcTxProof; -} - -function decodeTxResponse(data: RpcTxResponse): responses.TxResponse { - return { - tx: Base64.decode(assertNotEmpty(data.tx)) as TxBytes, - result: decodeTxData(assertObject(data.tx_result)), - height: Integer.parse(assertNotEmpty(data.height)), - index: Integer.parse(assertNumber(data.index)), - hash: fromHex(assertNotEmpty(data.hash)) as TxHash, - proof: may(decodeTxProof, data.proof), - }; -} - -interface RpcTxSearchResponse { - readonly txs: readonly RpcTxResponse[]; - readonly total_count: IntegerString; -} - -function decodeTxSearch(data: RpcTxSearchResponse): responses.TxSearchResponse { - return { - totalCount: Integer.parse(assertNotEmpty(data.total_count)), - txs: assertArray(data.txs).map(decodeTxResponse), - }; -} - -interface RpcTxEvent { - readonly tx: Base64String; - readonly result: RpcTxData; - readonly height: IntegerString; - readonly index: number; -} - -function decodeTxEvent(data: RpcTxEvent): responses.TxEvent { - const tx = Base64.decode(assertNotEmpty(data.tx)) as TxBytes; - return { - tx: tx, - hash: hashTx(tx), - result: decodeTxData(data.result), - height: Integer.parse(assertNotEmpty(data.height)), - index: Integer.parse(assertNumber(data.index)), - }; -} - -// for validators -interface RpcValidatorData extends RpcValidatorUpdate { - readonly accum?: IntegerString; -} - -function decodeValidatorData(data: RpcValidatorData): responses.Validator { - return { - ...decodeValidatorUpdate(data), - accum: may(Integer.parse, data.accum), - }; -} - -interface RpcValidatorsResponse { - readonly block_height: IntegerString; - readonly validators: readonly RpcValidatorData[]; -} - -function decodeValidators(data: RpcValidatorsResponse): responses.ValidatorsResponse { - return { - blockHeight: Integer.parse(assertNotEmpty(data.block_height)), - results: assertArray(data.validators).map(decodeValidatorData), - }; -} - -interface RpcEvidence { - readonly type: string; - readonly validator: RpcValidatorUpdate; - readonly height: IntegerString; - readonly time: IntegerString; - readonly totalVotingPower: IntegerString; -} - -function decodeEvidence(data: RpcEvidence): responses.Evidence { - return { - type: assertNotEmpty(data.type), - height: Integer.parse(assertNotEmpty(data.height)), - time: Integer.parse(assertNotEmpty(data.time)), - totalVotingPower: Integer.parse(assertNotEmpty(data.totalVotingPower)), - validator: decodeValidatorUpdate(data.validator), - }; -} - -function decodeEvidences(ev: readonly RpcEvidence[]): readonly responses.Evidence[] { - return assertArray(ev).map(decodeEvidence); -} - -interface RpcBlock { - readonly header: RpcHeader; - readonly last_commit: RpcCommit; - readonly data: { - readonly txs?: readonly Base64String[]; - }; - readonly evidence?: { - readonly evidence?: readonly RpcEvidence[]; - }; -} - -function decodeBlock(data: RpcBlock): responses.Block { - return { - header: decodeHeader(assertObject(data.header)), - lastCommit: decodeCommit(assertObject(data.last_commit)), - txs: data.data.txs ? assertArray(data.data.txs).map(Base64.decode) : [], - evidence: data.evidence && may(decodeEvidences, data.evidence.evidence), - }; -} - -interface RpcBlockResponse { - readonly block_meta: RpcBlockMeta; - readonly block: RpcBlock; -} - -function decodeBlockResponse(data: RpcBlockResponse): responses.BlockResponse { - return { - blockMeta: decodeBlockMeta(data.block_meta), - block: decodeBlock(data.block), - }; -} - -export class Responses { - public static decodeAbciInfo(response: JsonRpcSuccessResponse): responses.AbciInfoResponse { - return decodeAbciInfo(assertObject((response.result as AbciInfoResult).response)); - } - - public static decodeAbciQuery(response: JsonRpcSuccessResponse): responses.AbciQueryResponse { - return decodeAbciQuery(assertObject((response.result as AbciQueryResult).response)); - } - - public static decodeBlock(response: JsonRpcSuccessResponse): responses.BlockResponse { - return decodeBlockResponse(response.result as RpcBlockResponse); - } - - public static decodeBlockResults(response: JsonRpcSuccessResponse): responses.BlockResultsResponse { - return decodeBlockResults(response.result as RpcBlockResultsResponse); - } - - public static decodeBlockchain(response: JsonRpcSuccessResponse): responses.BlockchainResponse { - return decodeBlockchain(response.result as RpcBlockchainResponse); - } - - public static decodeBroadcastTxSync(response: JsonRpcSuccessResponse): responses.BroadcastTxSyncResponse { - return decodeBroadcastTxSync(response.result as RpcBroadcastTxSyncResponse); - } - - public static decodeBroadcastTxAsync(response: JsonRpcSuccessResponse): responses.BroadcastTxAsyncResponse { - return this.decodeBroadcastTxSync(response); - } - - public static decodeBroadcastTxCommit( - response: JsonRpcSuccessResponse, - ): responses.BroadcastTxCommitResponse { - return decodeBroadcastTxCommit(response.result as RpcBroadcastTxCommitResponse); - } - - public static decodeCommit(response: JsonRpcSuccessResponse): responses.CommitResponse { - return decodeCommitResponse(response.result as RpcCommitResponse); - } - - public static decodeGenesis(response: JsonRpcSuccessResponse): responses.GenesisResponse { - return decodeGenesis(assertObject((response.result as GenesisResult).genesis)); - } - - public static decodeHealth(): responses.HealthResponse { - return null; - } - - public static decodeStatus(response: JsonRpcSuccessResponse): responses.StatusResponse { - return decodeStatus(response.result as RpcStatusResponse); - } - - public static decodeNewBlockEvent(event: SubscriptionEvent): responses.NewBlockEvent { - return decodeBlock(event.data.value.block as RpcBlock); - } - - public static decodeNewBlockHeaderEvent(event: SubscriptionEvent): responses.NewBlockHeaderEvent { - return decodeHeader(event.data.value.header as RpcHeader); - } - - public static decodeTxEvent(event: SubscriptionEvent): responses.TxEvent { - return decodeTxEvent(event.data.value.TxResult as RpcTxEvent); - } - - public static decodeTx(response: JsonRpcSuccessResponse): responses.TxResponse { - return decodeTxResponse(response.result as RpcTxResponse); - } - - public static decodeTxSearch(response: JsonRpcSuccessResponse): responses.TxSearchResponse { - return decodeTxSearch(response.result as RpcTxSearchResponse); - } - - public static decodeValidators(response: JsonRpcSuccessResponse): responses.ValidatorsResponse { - return decodeValidators(response.result as RpcValidatorsResponse); - } -} diff --git a/packages/tendermint-rpc/types/index.d.ts b/packages/tendermint-rpc/types/index.d.ts index 547da1d2..8bc19a71 100644 --- a/packages/tendermint-rpc/types/index.d.ts +++ b/packages/tendermint-rpc/types/index.d.ts @@ -1,4 +1,3 @@ -export { v0_31 } from "./v0-31"; export { v0_32 } from "./v0-32"; export { Client } from "./client"; export { diff --git a/packages/tendermint-rpc/types/v0-31/hasher.d.ts b/packages/tendermint-rpc/types/v0-31/hasher.d.ts deleted file mode 100644 index de2e7e90..00000000 --- a/packages/tendermint-rpc/types/v0-31/hasher.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Header } from "../responses"; -import { BlockHash, TxBytes, TxHash } from "../types"; -export declare function hashTx(tx: TxBytes): TxHash; -export declare function hashBlock(header: Header): BlockHash; diff --git a/packages/tendermint-rpc/types/v0-31/index.d.ts b/packages/tendermint-rpc/types/v0-31/index.d.ts deleted file mode 100644 index 3d2d1e08..00000000 --- a/packages/tendermint-rpc/types/v0-31/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { Adaptor } from "../adaptor"; -export declare const v0_31: Adaptor; diff --git a/packages/tendermint-rpc/types/v0-31/requests.d.ts b/packages/tendermint-rpc/types/v0-31/requests.d.ts deleted file mode 100644 index af972c4a..00000000 --- a/packages/tendermint-rpc/types/v0-31/requests.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { JsonRpcRequest } from "@iov/jsonrpc"; -import * as requests from "../requests"; -export declare class Params { - static encodeAbciInfo(req: requests.AbciInfoRequest): JsonRpcRequest; - static encodeAbciQuery(req: requests.AbciQueryRequest): JsonRpcRequest; - static encodeBlock(req: requests.BlockRequest): JsonRpcRequest; - static encodeBlockchain(req: requests.BlockchainRequest): JsonRpcRequest; - static encodeBlockResults(req: requests.BlockResultsRequest): JsonRpcRequest; - static encodeBroadcastTx(req: requests.BroadcastTxRequest): JsonRpcRequest; - static encodeCommit(req: requests.CommitRequest): JsonRpcRequest; - static encodeGenesis(req: requests.GenesisRequest): JsonRpcRequest; - static encodeHealth(req: requests.HealthRequest): JsonRpcRequest; - static encodeStatus(req: requests.StatusRequest): JsonRpcRequest; - static encodeSubscribe(req: requests.SubscribeRequest): JsonRpcRequest; - static encodeTx(req: requests.TxRequest): JsonRpcRequest; - static encodeTxSearch(req: requests.TxSearchRequest): JsonRpcRequest; - static encodeValidators(req: requests.ValidatorsRequest): JsonRpcRequest; -} diff --git a/packages/tendermint-rpc/types/v0-31/responses.d.ts b/packages/tendermint-rpc/types/v0-31/responses.d.ts deleted file mode 100644 index 05fad338..00000000 --- a/packages/tendermint-rpc/types/v0-31/responses.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { JsonRpcSuccessResponse } from "@iov/jsonrpc"; -import * as responses from "../responses"; -import { SubscriptionEvent } from "../rpcclients"; -export declare class Responses { - static decodeAbciInfo(response: JsonRpcSuccessResponse): responses.AbciInfoResponse; - static decodeAbciQuery(response: JsonRpcSuccessResponse): responses.AbciQueryResponse; - static decodeBlock(response: JsonRpcSuccessResponse): responses.BlockResponse; - static decodeBlockResults(response: JsonRpcSuccessResponse): responses.BlockResultsResponse; - static decodeBlockchain(response: JsonRpcSuccessResponse): responses.BlockchainResponse; - static decodeBroadcastTxSync(response: JsonRpcSuccessResponse): responses.BroadcastTxSyncResponse; - static decodeBroadcastTxAsync(response: JsonRpcSuccessResponse): responses.BroadcastTxAsyncResponse; - static decodeBroadcastTxCommit(response: JsonRpcSuccessResponse): responses.BroadcastTxCommitResponse; - static decodeCommit(response: JsonRpcSuccessResponse): responses.CommitResponse; - static decodeGenesis(response: JsonRpcSuccessResponse): responses.GenesisResponse; - static decodeHealth(): responses.HealthResponse; - static decodeStatus(response: JsonRpcSuccessResponse): responses.StatusResponse; - static decodeNewBlockEvent(event: SubscriptionEvent): responses.NewBlockEvent; - static decodeNewBlockHeaderEvent(event: SubscriptionEvent): responses.NewBlockHeaderEvent; - static decodeTxEvent(event: SubscriptionEvent): responses.TxEvent; - static decodeTx(response: JsonRpcSuccessResponse): responses.TxResponse; - static decodeTxSearch(response: JsonRpcSuccessResponse): responses.TxSearchResponse; - static decodeValidators(response: JsonRpcSuccessResponse): responses.ValidatorsResponse; -}