Skip to content

Commit

Permalink
Merge pull request #1187 from cosmos/large-voting-powers
Browse files Browse the repository at this point in the history
Support voting powers > MAX_SAFE_INTEGER
  • Loading branch information
webmaster128 committed Jun 29, 2022
2 parents 1e50f89 + f7c3ef7 commit 47bcd34
Show file tree
Hide file tree
Showing 17 changed files with 276 additions and 180 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ and this project adheres to
- all: Upgrade cosmjs-types to 0.5 ([#1131]).
- @cosmjs/stargate: Change `packetCommitment` parameter `sequence` type from
`Long` to `number` ([#1168]).
- @cosmjs/tendermint-rpc: The type of `votingPower` fields was changed from
`number` to `bigint` as those values can exceed the safe integer range
([#1133]).

[#1131]: https://github.com/cosmos/cosmjs/pull/1131
[#1168]: https://github.com/cosmos/cosmjs/pull/1168
[#1133]: https://github.com/cosmos/cosmjs/issues/1133

## [0.28.9] - 2022-06-21

Expand Down
40 changes: 40 additions & 0 deletions packages/tendermint-rpc/src/inthelpers.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { apiToBigInt } from "./inthelpers";

describe("inthelpers", () => {
describe("apiToBigInt", () => {
it("works for positive an negative ints", () => {
expect(apiToBigInt("0")).toEqual(BigInt(0));
expect(apiToBigInt("1")).toEqual(BigInt(1));
expect(apiToBigInt("100")).toEqual(BigInt(100));
expect(apiToBigInt("-1")).toEqual(BigInt(-1));
expect(apiToBigInt("-100")).toEqual(BigInt(-100));
expect(apiToBigInt("9007199254740991")).toEqual(BigInt(9007199254740991));
expect(apiToBigInt("-9007199254740991")).toEqual(BigInt(-9007199254740991));
// uint64 max
expect(apiToBigInt("18446744073709551615")).toEqual(BigInt("18446744073709551615"));
// int64 min/max
expect(apiToBigInt("-9223372036854775808")).toEqual(BigInt("-9223372036854775808"));
expect(apiToBigInt("9223372036854775807")).toEqual(BigInt("9223372036854775807"));
});

it("throws for ill-formatted inputs", () => {
// empty
expect(() => apiToBigInt("")).toThrowError(/invalid string format/i);
expect(() => apiToBigInt("-")).toThrowError(/invalid string format/i);

// non decimal representation
expect(() => apiToBigInt("0x0")).toThrowError(/invalid string format/i);
expect(() => apiToBigInt("0x01")).toThrowError(/invalid string format/i);
expect(() => apiToBigInt("0x")).toThrowError(/invalid string format/i);

// decimal points
expect(() => apiToBigInt("1.0")).toThrowError(/invalid string format/i);

// Invalid dashes
expect(() => apiToBigInt("1-")).toThrowError(/invalid string format/i);
expect(() => apiToBigInt("--1")).toThrowError(/invalid string format/i);
expect(() => apiToBigInt("1-1")).toThrowError(/invalid string format/i);
expect(() => apiToBigInt("-1-1")).toThrowError(/invalid string format/i);
});
});
});
36 changes: 36 additions & 0 deletions packages/tendermint-rpc/src/inthelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Int53 } from "@cosmjs/math";

import { assertString } from "./tendermint34/encodings";

/**
* Takes an integer value from the Tendermint RPC API and
* returns it as number.
*
* Only works within the safe integer range.
*/
export function apiToSmallInt(input: string | number): number {
const asInt = typeof input === "number" ? new Int53(input) : Int53.fromString(input);
return asInt.toNumber();
}

/**
* Takes an integer value from the Tendermint RPC API and
* returns it as BigInt.
*
* This supports the full uint64 and int64 ranges.
*/
export function apiToBigInt(input: string): bigint {
assertString(input); // Runtime check on top of TypeScript just to be safe for semi-trusted API types
if (!input.match(/^-?[0-9]+$/)) {
throw new Error("Invalid string format");
}
return BigInt(input);
}

/**
* Takes an integer in the safe integer range and returns
* a string representation to be used in the Tendermint RPC API.
*/
export function smallIntToApi(num: number): string {
return new Int53(num).toString();
}
25 changes: 13 additions & 12 deletions packages/tendermint-rpc/src/tendermint34/adaptor/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import { toBase64, toHex } from "@cosmjs/encoding";
import { JsonRpcRequest } from "@cosmjs/json-rpc";

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

interface HeightParam {
Expand All @@ -14,7 +15,7 @@ interface RpcHeightParam {
}
function encodeHeightParam(param: HeightParam): RpcHeightParam {
return {
height: may(Integer.encode, param.height),
height: may(smallIntToApi, param.height),
};
}

Expand All @@ -25,8 +26,8 @@ interface RpcBlockchainRequestParams {

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

Expand All @@ -39,8 +40,8 @@ interface RpcBlockSearchParams {
function encodeBlockSearchParams(params: requests.BlockSearchParams): RpcBlockSearchParams {
return {
query: params.query,
page: may(Integer.encode, params.page),
per_page: may(Integer.encode, params.per_page),
page: may(smallIntToApi, params.page),
per_page: may(smallIntToApi, params.per_page),
order_by: params.order_by,
};
}
Expand All @@ -57,7 +58,7 @@ function encodeAbciQueryParams(params: requests.AbciQueryParams): RpcAbciQueryPa
return {
path: assertNotEmpty(params.path),
data: toHex(params.data),
height: may(Integer.encode, params.height),
height: may(smallIntToApi, params.height),
prove: params.prove,
};
}
Expand Down Expand Up @@ -95,8 +96,8 @@ function encodeTxSearchParams(params: requests.TxSearchParams): RpcTxSearchParam
return {
query: params.query,
prove: params.prove,
page: may(Integer.encode, params.page),
per_page: may(Integer.encode, params.per_page),
page: may(smallIntToApi, params.page),
per_page: may(smallIntToApi, params.per_page),
order_by: params.order_by,
};
}
Expand All @@ -108,9 +109,9 @@ interface RpcValidatorsParams {
}
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),
height: may(smallIntToApi, params.height),
page: may(smallIntToApi, params.page),
per_page: may(smallIntToApi, params.per_page),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe("Adaptor Responses", () => {
});
expect(validator).toEqual({
address: fromHex("A03DC128D38DB0BC5F18AE1872F1CB2E1FD41157"),
votingPower: 169980,
votingPower: BigInt(169980),
pubkey: {
algorithm: "ed25519",
data: fromBase64("2BX6Zuj8RmdJAkD1BAg6KB0v04liyM7jBdwOGIb9F9Q="),
Expand Down Expand Up @@ -72,7 +72,7 @@ describe("Adaptor Responses", () => {
algorithm: "ed25519",
data: fromBase64("0kNlxBMpm+5WtfHIG1xsWatOXTKPLtmSqn3EiEIDZeI="),
},
votingPower: 11418237,
votingPower: BigInt(11418237),
});
});

Expand All @@ -93,7 +93,7 @@ describe("Adaptor Responses", () => {
algorithm: "ed25519",
data: fromBase64("HjSC7VkhKih6xMhudlqfaFE8ZZnP8RKJPv4iqR7RhcE="),
},
votingPower: 0,
votingPower: BigInt(0),
});
});
});
Expand All @@ -116,7 +116,7 @@ describe("Adaptor Responses", () => {
algorithm: "ed25519",
data: fromBase64("0kNlxBMpm+5WtfHIG1xsWatOXTKPLtmSqn3EiEIDZeI="),
},
votingPower: 11228980,
votingPower: BigInt(11228980),
proposerPriority: 62870960,
});
});
Expand Down
Loading

0 comments on commit 47bcd34

Please sign in to comment.