diff --git a/.pnp.cjs b/.pnp.cjs index a010c15041..a6e863dbb5 100644 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -206,10 +206,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "@babel/types",\ "npm:7.23.0"\ ],\ - [\ - "@confio/ics23",\ - "npm:0.6.8"\ - ],\ [\ "@cosmjs/amino",\ "workspace:packages/amino"\ @@ -3228,17 +3224,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ - ["@confio/ics23", [\ - ["npm:0.6.8", {\ - "packageLocation": "./.yarn/cache/@confio-ics23-npm-0.6.8-c87607eb2c-376d72f644.zip/node_modules/@confio/ics23/",\ - "packageDependencies": [\ - ["@confio/ics23", "npm:0.6.8"],\ - ["@noble/hashes", "npm:1.0.0"],\ - ["protobufjs", "npm:6.11.4"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@cosmjs/amino", [\ ["workspace:packages/amino", {\ "packageLocation": "./packages/amino/",\ @@ -3809,7 +3794,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./packages/stargate/",\ "packageDependencies": [\ ["@cosmjs/stargate", "workspace:packages/stargate"],\ - ["@confio/ics23", "npm:0.6.8"],\ ["@cosmjs/amino", "workspace:packages/amino"],\ ["@cosmjs/crypto", "workspace:packages/crypto"],\ ["@cosmjs/encoding", "workspace:packages/encoding"],\ diff --git a/.yarn/cache/@confio-ics23-npm-0.6.8-c87607eb2c-376d72f644.zip b/.yarn/cache/@confio-ics23-npm-0.6.8-c87607eb2c-376d72f644.zip deleted file mode 100644 index 212282a05b..0000000000 --- a/.yarn/cache/@confio-ics23-npm-0.6.8-c87607eb2c-376d72f644.zip +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7959e8225888f3d910e5e0e42545b4d3650764d7707d426dbe4b6381099a0494 -size 77346 diff --git a/CHANGELOG.md b/CHANGELOG.md index ce5b2332c6..3dcefec93a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this project adheres to ## [Unreleased] +### Changed + +- @cosmjs/stargate: Removed support for verified queries. This feature depends + on a JavaScript implementation of ICS-23 but + [@confio/ics23 is unmaintained](https://github.com/cosmos/cosmjs/issues/1618) + without replacement. + ## [0.32.4] - 2024-06-26 ### Fixed diff --git a/packages/stargate/package.json b/packages/stargate/package.json index 27129ef06d..5d156d177a 100644 --- a/packages/stargate/package.json +++ b/packages/stargate/package.json @@ -38,7 +38,6 @@ "pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js" }, "dependencies": { - "@confio/ics23": "^0.6.8", "@cosmjs/amino": "workspace:^", "@cosmjs/encoding": "workspace:^", "@cosmjs/math": "workspace:^", diff --git a/packages/stargate/src/modules/ibc/queries.ts b/packages/stargate/src/modules/ibc/queries.ts index cbf2faacdc..33c27017ba 100644 --- a/packages/stargate/src/modules/ibc/queries.ts +++ b/packages/stargate/src/modules/ibc/queries.ts @@ -1,6 +1,4 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { toAscii } from "@cosmjs/encoding"; -import { Uint64 } from "@cosmjs/math"; import { Any } from "cosmjs-types/google/protobuf/any"; import { QueryClientImpl as TransferQuery, @@ -8,7 +6,6 @@ import { QueryDenomTracesResponse, QueryParamsResponse as QueryTransferParamsResponse, } from "cosmjs-types/ibc/applications/transfer/v1/query"; -import { Channel } from "cosmjs-types/ibc/core/channel/v1/channel"; import { QueryChannelClientStateResponse, QueryChannelConsensusStateResponse, @@ -166,22 +163,6 @@ export interface IbcExtension { readonly allDenomTraces: () => Promise; readonly params: () => Promise; }; - readonly verified: { - readonly channel: { - readonly channel: (portId: string, channelId: string) => Promise; - readonly packetCommitment: ( - portId: string, - channelId: string, - sequence: number, - ) => Promise; - readonly packetAcknowledgement: ( - portId: string, - channelId: string, - sequence: number, - ) => Promise; - readonly nextSequenceReceive: (portId: string, channelId: string) => Promise; - }; - }; }; } @@ -502,40 +483,6 @@ export function setupIbcExtension(base: QueryClient): IbcExtension { }, params: async () => transferQueryService.Params({}), }, - verified: { - channel: { - channel: async (portId: string, channelId: string) => { - // keeper: https://github.com/cosmos/cosmos-sdk/blob/3bafd8255a502e5a9cee07391cf8261538245dfd/x/ibc/04-channel/keeper/keeper.go#L55-L65 - // key: https://github.com/cosmos/cosmos-sdk/blob/ef0a7344af345882729598bc2958a21143930a6b/x/ibc/24-host/keys.go#L117-L120 - const key = toAscii(`channelEnds/ports/${portId}/channels/${channelId}`); - const { value } = await base.queryStoreVerified("ibc", key); - return value.length ? Channel.decode(value) : null; - }, - packetCommitment: async (portId: string, channelId: string, sequence: number) => { - // keeper: https://github.com/cosmos/cosmos-sdk/blob/3bafd8255a502e5a9cee07391cf8261538245dfd/x/ibc/04-channel/keeper/keeper.go#L128-L133 - // key: https://github.com/cosmos/cosmos-sdk/blob/ef0a7344af345882729598bc2958a21143930a6b/x/ibc/24-host/keys.go#L183-L185 - const key = toAscii(`commitments/ports/${portId}/channels/${channelId}/packets/${sequence}`); - const { value } = await base.queryStoreVerified("ibc", key); - // keeper code doesn't parse, but returns raw - return value; - }, - packetAcknowledgement: async (portId: string, channelId: string, sequence: number) => { - // keeper: https://github.com/cosmos/cosmos-sdk/blob/3bafd8255a502e5a9cee07391cf8261538245dfd/x/ibc/04-channel/keeper/keeper.go#L159-L166 - // key: https://github.com/cosmos/cosmos-sdk/blob/ef0a7344af345882729598bc2958a21143930a6b/x/ibc/24-host/keys.go#L153-L156 - const key = toAscii(`acks/ports/${portId}/channels/${channelId}/acknowledgements/${sequence}`); - const { value } = await base.queryStoreVerified("ibc", key); - // keeper code doesn't parse, but returns raw - return value; - }, - nextSequenceReceive: async (portId: string, channelId: string) => { - // keeper: https://github.com/cosmos/cosmos-sdk/blob/3bafd8255a502e5a9cee07391cf8261538245dfd/x/ibc/04-channel/keeper/keeper.go#L92-L101 - // key: https://github.com/cosmos/cosmos-sdk/blob/ef0a7344af345882729598bc2958a21143930a6b/x/ibc/24-host/keys.go#L133-L136 - const key = toAscii(`seqAcks/ports/${portId}/channels/${channelId}/nextSequenceAck`); - const { value } = await base.queryStoreVerified("ibc", key); - return value.length ? Uint64.fromBytes(value).toNumber() : null; - }, - }, - }, }, }; } diff --git a/packages/stargate/src/queryclient/queryclient.spec.ts b/packages/stargate/src/queryclient/queryclient.spec.ts index cfbf318521..891f0c50b9 100644 --- a/packages/stargate/src/queryclient/queryclient.spec.ts +++ b/packages/stargate/src/queryclient/queryclient.spec.ts @@ -1,10 +1,8 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { coin } from "@cosmjs/amino"; -import { toAscii } from "@cosmjs/encoding"; import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; import { CometClient, Tendermint34Client } from "@cosmjs/tendermint-rpc"; import { assert } from "@cosmjs/utils"; -import { Metadata } from "cosmjs-types/cosmos/bank/v1beta1/bank"; import { QueryAllBalancesRequest, QueryAllBalancesResponse, @@ -19,7 +17,6 @@ import { makeRandomAddress, pendingWithoutSimapp, simapp, - simapp44Enabled, unused, } from "../testutils.spec"; import { QueryClient } from "./queryclient"; @@ -29,69 +26,7 @@ async function makeClient(rpcUrl: string): Promise<[QueryClient, CometClient]> { return [QueryClient.withExtensions(cometClient), cometClient]; } -/** - * See - * - https://github.com/cosmos/cosmos-sdk/blob/v0.42.10/x/bank/types/key.go#L27 - * - https://github.com/cosmos/cosmos-sdk/blob/v0.44.2/x/bank/types/key.go#L28 - */ -const denomMetadataPrefix = new Uint8Array([0x01]); - describe("QueryClient", () => { - describe("queryStoreVerified", () => { - it("works via WebSockets", async () => { - pendingWithoutSimapp(); - const [client, cometClient] = await makeClient(simapp.tendermintUrlWs); - - // "keys before 0.45 had denom two times in the key" - // https://github.com/cosmos/cosmos-sdk/blob/10ad61a4dd/x/bank/migrations/v045/store_test.go#L91 - let queryKey: Uint8Array; - if (simapp44Enabled()) { - queryKey = Uint8Array.from([ - ...denomMetadataPrefix, - ...toAscii(simapp.denomFee), - ...toAscii(simapp.denomFee), - ]); - } else { - queryKey = Uint8Array.from([...denomMetadataPrefix, ...toAscii(simapp.denomFee)]); - } - const { key, value, height } = await client.queryStoreVerified("bank", queryKey); - expect(height).toBeGreaterThanOrEqual(1); - expect(key).toEqual(queryKey); - const response = Metadata.decode(value); - expect(response.base).toEqual(simapp.denomFee); - expect(response.description).toEqual("The fee token of this test chain"); - - cometClient.disconnect(); - }); - - it("works via http", async () => { - pendingWithoutSimapp(); - const [client, cometClient] = await makeClient(simapp.tendermintUrlHttp); - - // "keys before 0.45 had denom two times in the key" - // https://github.com/cosmos/cosmos-sdk/blob/10ad61a4dd/x/bank/migrations/v045/store_test.go#L91 - let queryKey: Uint8Array; - if (simapp44Enabled()) { - queryKey = Uint8Array.from([ - ...denomMetadataPrefix, - ...toAscii(simapp.denomFee), - ...toAscii(simapp.denomFee), - ]); - } else { - queryKey = Uint8Array.from([...denomMetadataPrefix, ...toAscii(simapp.denomFee)]); - } - - const { key, value, height } = await client.queryStoreVerified("bank", queryKey); - expect(height).toBeGreaterThanOrEqual(1); - expect(key).toEqual(queryKey); - const response = Metadata.decode(value); - expect(response.base).toEqual(simapp.denomFee); - expect(response.description).toEqual("The fee token of this test chain"); - - cometClient.disconnect(); - }); - }); - describe("queryAbci", () => { it("works via WebSockets", async () => { pendingWithoutSimapp(); diff --git a/packages/stargate/src/queryclient/queryclient.ts b/packages/stargate/src/queryclient/queryclient.ts index e839666cb0..1b5cf96b31 100644 --- a/packages/stargate/src/queryclient/queryclient.ts +++ b/packages/stargate/src/queryclient/queryclient.ts @@ -1,24 +1,12 @@ /* eslint-disable no-dupe-class-members, @typescript-eslint/ban-types, @typescript-eslint/naming-convention */ -import { iavlSpec, ics23, tendermintSpec, verifyExistence, verifyNonExistence } from "@confio/ics23"; -import { toAscii, toHex } from "@cosmjs/encoding"; import { firstEvent } from "@cosmjs/stream"; import { CometClient, tendermint34 } from "@cosmjs/tendermint-rpc"; -import { arrayContentEquals, assert, assertDefined, isNonNullObject, sleep } from "@cosmjs/utils"; +import { assert, assertDefined, isNonNullObject, sleep } from "@cosmjs/utils"; import { ProofOps } from "cosmjs-types/tendermint/crypto/proof"; import { Stream } from "xstream"; type QueryExtensionSetup

= (base: QueryClient) => P; -function checkAndParseOp(op: tendermint34.ProofOp, kind: string, key: Uint8Array): ics23.CommitmentProof { - if (op.type !== kind) { - throw new Error(`Op expected to be ${kind}, got "${op.type}`); - } - if (!arrayContentEquals(key, op.key)) { - throw new Error(`Proven key different than queried key.\nQuery: ${toHex(key)}\nProven: ${toHex(op.key)}`); - } - return ics23.CommitmentProof.decode(op.data); -} - export interface ProvenQuery { readonly key: Uint8Array; readonly value: Uint8Array; @@ -512,90 +500,6 @@ export class QueryClient { this.cometClient = cometClient; } - /** - * Queries the database store with a proof, which is then verified. - * - * Please note: the current implementation trusts block headers it gets from the PRC endpoint. - */ - public async queryStoreVerified( - store: string, - queryKey: Uint8Array, - desiredHeight?: number, - ): Promise { - const { height, proof, key, value } = await this.queryRawProof(store, queryKey, desiredHeight); - - const subProof = checkAndParseOp(proof.ops[0], "ics23:iavl", queryKey); - const storeProof = checkAndParseOp(proof.ops[1], "ics23:simple", toAscii(store)); - - // this must always be existence, if the store is not a typo - assert(storeProof.exist); - assert(storeProof.exist.value); - - // this may be exist or non-exist, depends on response - if (!value || value.length === 0) { - // non-existence check - assert(subProof.nonexist); - // the subproof must map the desired key to the "value" of the storeProof - verifyNonExistence(subProof.nonexist, iavlSpec, storeProof.exist.value, queryKey); - } else { - // existence check - assert(subProof.exist); - assert(subProof.exist.value); - // the subproof must map the desired key to the "value" of the storeProof - verifyExistence(subProof.exist, iavlSpec, storeProof.exist.value, queryKey, value); - } - - // the store proof must map its declared value (root of subProof) to the appHash of the next block - const header = await this.getNextHeader(height); - verifyExistence(storeProof.exist, tendermintSpec, header.appHash, toAscii(store), storeProof.exist.value); - - return { key, value, height }; - } - - public async queryRawProof( - store: string, - queryKey: Uint8Array, - desiredHeight?: number, - ): Promise { - const { key, value, height, proof, code, log } = await this.cometClient.abciQuery({ - // we need the StoreKey for the module, not the module name - // https://github.com/cosmos/cosmos-sdk/blob/8cab43c8120fec5200c3459cbf4a92017bb6f287/x/auth/types/keys.go#L12 - path: `/store/${store}/key`, - data: queryKey, - prove: true, - height: desiredHeight, - }); - - if (code) { - throw new Error(`Query failed with (${code}): ${log}`); - } - - if (!arrayContentEquals(queryKey, key)) { - throw new Error(`Response key ${toHex(key)} doesn't match query key ${toHex(queryKey)}`); - } - - if (!height) { - throw new Error("No query height returned"); - } - if (!proof || proof.ops.length !== 2) { - throw new Error(`Expected 2 proof ops, got ${proof?.ops.length ?? 0}. Are you using stargate?`); - } - - // we don't need the results, but we can ensure the data is the proper format - checkAndParseOp(proof.ops[0], "ics23:iavl", key); - checkAndParseOp(proof.ops[1], "ics23:simple", toAscii(store)); - - return { - key: key, - value: value, - height: height, - // need to clone this: readonly input / writeable output - proof: { - ops: [...proof.ops], - }, - }; - } - /** * Performs an ABCI query to Tendermint without requesting a proof. * diff --git a/yarn.lock b/yarn.lock index 867ad54d77..4da5118651 100644 --- a/yarn.lock +++ b/yarn.lock @@ -279,16 +279,6 @@ __metadata: languageName: node linkType: hard -"@confio/ics23@npm:^0.6.8": - version: 0.6.8 - resolution: "@confio/ics23@npm:0.6.8" - dependencies: - "@noble/hashes": ^1.0.0 - protobufjs: ^6.8.8 - checksum: 376d72f6440db60611b002b00a13e3a5bfd0d3503e7682358dbcf79641e74d8c26c234c321452fb4a758baf66eecef25d950e08bdea270486d9d03ee489e2960 - languageName: node - linkType: hard - "@cosmjs/amino@workspace:^, @cosmjs/amino@workspace:packages/amino": version: 0.0.0-use.local resolution: "@cosmjs/amino@workspace:packages/amino" @@ -838,7 +828,6 @@ __metadata: version: 0.0.0-use.local resolution: "@cosmjs/stargate@workspace:packages/stargate" dependencies: - "@confio/ics23": ^0.6.8 "@cosmjs/amino": "workspace:^" "@cosmjs/crypto": "workspace:^" "@cosmjs/encoding": "workspace:^" @@ -1250,7 +1239,7 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:^1, @noble/hashes@npm:^1.0.0": +"@noble/hashes@npm:^1": version: 1.0.0 resolution: "@noble/hashes@npm:1.0.0" checksum: bdf1c28a4b587e72ec6b0c504903239c6f96680b2c15a6d90d367512f468eeca12f2ee7bd25967a9529be2bedbf3f8d0a50c33368937f8dfef2a973d0661c7b5 @@ -6414,7 +6403,7 @@ __metadata: languageName: node linkType: hard -"protobufjs@npm:^6.8.8, protobufjs@npm:~6.11.4": +"protobufjs@npm:~6.11.4": version: 6.11.4 resolution: "protobufjs@npm:6.11.4" dependencies: