diff --git a/CHANGELOG.md b/CHANGELOG.md index 887b9edb..874feff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ and this project adheres to - @cosmjs/cosmwasm-stargate: Codec adapted to support wasmd 0.16. Older versions of wasmd are not supported anymore. +- @cosmjs/tendermint-rpc: The fields `CommitSignature.validatorAddress`, + `.timestamp` and `.signature` are now optional. They are unset when + `blockIdFlag` is `BlockIdFlag.Absent`. The decoding into `CommitSignature` is + only updated for the class `Tendermint34Client`, not for `Client`. Please + migrate to the former. ## [0.24.0] - 2021-03-11 diff --git a/packages/tendermint-rpc/src/legacy/client.spec.ts b/packages/tendermint-rpc/src/legacy/client.spec.ts index fc1dd0b2..a3c290a5 100644 --- a/packages/tendermint-rpc/src/legacy/client.spec.ts +++ b/packages/tendermint-rpc/src/legacy/client.spec.ts @@ -105,9 +105,9 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte expect(response).toBeTruthy(); expect(response.commit.signatures.length).toBeGreaterThanOrEqual(1); expect(response.commit.signatures[0].blockIdFlag).toEqual(2); - expect(response.commit.signatures[0].validatorAddress.length).toEqual(20); + expect(response.commit.signatures[0].validatorAddress?.length).toEqual(20); expect(response.commit.signatures[0].timestamp).toBeInstanceOf(Date); - expect(response.commit.signatures[0].signature.length).toEqual(64); + expect(response.commit.signatures[0].signature?.length).toEqual(64); client.disconnect(); }); diff --git a/packages/tendermint-rpc/src/tendermint34/adaptors/v0-34/responses.ts b/packages/tendermint-rpc/src/tendermint34/adaptors/v0-34/responses.ts index 42f98f3f..4a72eb8b 100644 --- a/packages/tendermint-rpc/src/tendermint34/adaptors/v0-34/responses.ts +++ b/packages/tendermint-rpc/src/tendermint34/adaptors/v0-34/responses.ts @@ -3,7 +3,7 @@ import { fromBase64, fromHex } from "@cosmjs/encoding"; import { JsonRpcSuccessResponse } from "@cosmjs/json-rpc"; import { assert } from "@cosmjs/utils"; -import { fromRfc3339WithNanoseconds } from "../../../dates"; +import { DateWithNanoseconds, fromRfc3339WithNanoseconds } from "../../../dates"; import { SubscriptionEvent } from "../../../rpcclients"; import { BlockIdFlag, CommitSignature, ValidatorPubkey } from "../../../types"; import { @@ -416,17 +416,23 @@ type RpcSignature = { readonly signature: string | null; }; +/** + * In some cases a timestamp is optional and set to the value 0 in Go. + * This can lead to strings like "0001-01-01T00:00:00Z" (see https://github.com/cosmos/cosmjs/issues/704#issuecomment-797122415). + * This decoder tries to clean up such encoding from the API and turn them + * into undefined values. + */ +function decodeOptionalTime(timestamp: string): DateWithNanoseconds | undefined { + const nonZeroTime = timestamp && !timestamp.startsWith("0001-01-01"); + return nonZeroTime ? fromRfc3339WithNanoseconds(timestamp) : undefined; +} + function decodeCommitSignature(data: RpcSignature): CommitSignature { - const nonZeroTime = data.timestamp && !data.timestamp.startsWith("0001-01-01"); return { blockIdFlag: decodeBlockIdFlag(data.block_id_flag), - // FIXME: Return an optional validatorAddress instead of an empty Uint8Array - // in the next breaking release. - validatorAddress: fromHex(data.validator_address), - timestamp: nonZeroTime ? fromRfc3339WithNanoseconds(data.timestamp) : undefined, - // FIXME: Return an optional signature instead of an empty Uint8Array - // in the next breaking release. - signature: fromBase64(data.signature || ""), + validatorAddress: data.validator_address ? fromHex(data.validator_address) : undefined, + timestamp: decodeOptionalTime(data.timestamp), + signature: data.signature ? fromBase64(data.signature) : undefined, }; } diff --git a/packages/tendermint-rpc/src/tendermint34/tendermint34client.spec.ts b/packages/tendermint-rpc/src/tendermint34/tendermint34client.spec.ts index e43d2311..90598acc 100644 --- a/packages/tendermint-rpc/src/tendermint34/tendermint34client.spec.ts +++ b/packages/tendermint-rpc/src/tendermint34/tendermint34client.spec.ts @@ -104,9 +104,9 @@ function defaultTestSuite(rpcFactory: () => RpcClient, expected: ExpectedValues) expect(response).toBeTruthy(); expect(response.commit.signatures.length).toBeGreaterThanOrEqual(1); expect(response.commit.signatures[0].blockIdFlag).toEqual(2); - expect(response.commit.signatures[0].validatorAddress.length).toEqual(20); + expect(response.commit.signatures[0].validatorAddress?.length).toEqual(20); expect(response.commit.signatures[0].timestamp).toBeInstanceOf(Date); - expect(response.commit.signatures[0].signature.length).toEqual(64); + expect(response.commit.signatures[0].signature?.length).toEqual(64); client.disconnect(); }); diff --git a/packages/tendermint-rpc/src/types.ts b/packages/tendermint-rpc/src/types.ts index d920f6d0..ae0c74b0 100644 --- a/packages/tendermint-rpc/src/types.ts +++ b/packages/tendermint-rpc/src/types.ts @@ -25,7 +25,7 @@ export enum BlockIdFlag { export interface CommitSignature { /** If this is BlockIdFlag.Absent, all other fields are expected to be unset */ blockIdFlag: BlockIdFlag; - validatorAddress: Uint8Array; - timestamp?: ReadonlyDateWithNanoseconds; - signature: Uint8Array; + validatorAddress: Uint8Array | undefined; + timestamp: ReadonlyDateWithNanoseconds | undefined; + signature: Uint8Array | undefined; }