Create queryStoreVerified and deprecate queryVerified
This commit is contained in:
parent
e015f947ba
commit
037dc3d69f
@ -18,6 +18,8 @@ and this project adheres to
|
||||
|
||||
- @cosmjs/stargate: Deprecate `QueryClient.queryUnverified` in favour of newly
|
||||
added `QueryClient.queryAbci`.
|
||||
- @cosmjs/stargate: Deprecate `QueryClient.queryVerified` in favour of newly
|
||||
added `QueryClient.queryStoreVerified`.
|
||||
|
||||
## [0.29.4] - 2022-11-15
|
||||
|
||||
|
||||
@ -110,6 +110,7 @@ export {
|
||||
ProtobufRpcClient,
|
||||
QueryAbciResponse,
|
||||
QueryClient,
|
||||
QueryStoreResponse,
|
||||
} from "./queryclient";
|
||||
export {
|
||||
isSearchByHeightQuery,
|
||||
|
||||
@ -510,31 +510,31 @@ export function setupIbcExtension(base: QueryClient): IbcExtension {
|
||||
// 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 responseData = await base.queryVerified("ibc", key);
|
||||
return responseData.length ? Channel.decode(responseData) : null;
|
||||
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 responseData = await base.queryVerified("ibc", key);
|
||||
const { value } = await base.queryStoreVerified("ibc", key);
|
||||
// keeper code doesn't parse, but returns raw
|
||||
return responseData;
|
||||
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 responseData = await base.queryVerified("ibc", key);
|
||||
const { value } = await base.queryStoreVerified("ibc", key);
|
||||
// keeper code doesn't parse, but returns raw
|
||||
return responseData;
|
||||
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 responseData = await base.queryVerified("ibc", key);
|
||||
return responseData.length ? Uint64.fromBytes(responseData).toNumber() : null;
|
||||
const { value } = await base.queryStoreVerified("ibc", key);
|
||||
return value.length ? Uint64.fromBytes(value).toNumber() : null;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export { QueryAbciResponse, QueryClient } from "./queryclient";
|
||||
export { QueryAbciResponse, QueryClient, QueryStoreResponse } from "./queryclient";
|
||||
export {
|
||||
createPagination,
|
||||
createProtobufRpcClient,
|
||||
|
||||
@ -37,26 +37,27 @@ async function makeClient(rpcUrl: string): Promise<[QueryClient, Tendermint34Cli
|
||||
const denomMetadataPrefix = new Uint8Array([0x01]);
|
||||
|
||||
describe("QueryClient", () => {
|
||||
describe("queryVerified", () => {
|
||||
describe("queryStoreVerified", () => {
|
||||
it("works via WebSockets", async () => {
|
||||
pendingWithoutSimapp();
|
||||
const [client, tmClient] = 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 key: Uint8Array;
|
||||
let queryKey: Uint8Array;
|
||||
if (simapp44Enabled()) {
|
||||
key = Uint8Array.from([
|
||||
queryKey = Uint8Array.from([
|
||||
...denomMetadataPrefix,
|
||||
...toAscii(simapp.denomFee),
|
||||
...toAscii(simapp.denomFee),
|
||||
]);
|
||||
} else {
|
||||
key = Uint8Array.from([...denomMetadataPrefix, ...toAscii(simapp.denomFee)]);
|
||||
queryKey = Uint8Array.from([...denomMetadataPrefix, ...toAscii(simapp.denomFee)]);
|
||||
}
|
||||
const data = await client.queryVerified("bank", key);
|
||||
|
||||
const response = Metadata.decode(data);
|
||||
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");
|
||||
|
||||
@ -69,20 +70,21 @@ describe("QueryClient", () => {
|
||||
|
||||
// "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 key: Uint8Array;
|
||||
let queryKey: Uint8Array;
|
||||
if (simapp44Enabled()) {
|
||||
key = Uint8Array.from([
|
||||
queryKey = Uint8Array.from([
|
||||
...denomMetadataPrefix,
|
||||
...toAscii(simapp.denomFee),
|
||||
...toAscii(simapp.denomFee),
|
||||
]);
|
||||
} else {
|
||||
key = Uint8Array.from([...denomMetadataPrefix, ...toAscii(simapp.denomFee)]);
|
||||
queryKey = Uint8Array.from([...denomMetadataPrefix, ...toAscii(simapp.denomFee)]);
|
||||
}
|
||||
|
||||
const data = await client.queryVerified("bank", key);
|
||||
|
||||
const response = Metadata.decode(data);
|
||||
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");
|
||||
|
||||
|
||||
@ -26,6 +26,13 @@ export interface ProvenQuery {
|
||||
readonly height: number;
|
||||
}
|
||||
|
||||
export interface QueryStoreResponse {
|
||||
/** The response key from Tendermint. This is the same as the query key in the request. */
|
||||
readonly key: Uint8Array;
|
||||
readonly value: Uint8Array;
|
||||
readonly height: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The response of an ABCI query to Tendermint.
|
||||
* This is a subset of `tendermint34.AbciQueryResponse` in order
|
||||
@ -505,10 +512,27 @@ export class QueryClient {
|
||||
this.tmClient = tmClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use queryStoreVerified instead
|
||||
*/
|
||||
public async queryVerified(store: string, key: Uint8Array, desiredHeight?: number): Promise<Uint8Array> {
|
||||
const { height, proof, value } = await this.queryRawProof(store, key, desiredHeight);
|
||||
const { value } = await this.queryStoreVerified(store, key, desiredHeight);
|
||||
return value;
|
||||
}
|
||||
|
||||
const subProof = checkAndParseOp(proof.ops[0], "ics23:iavl", key);
|
||||
/**
|
||||
* 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<QueryStoreResponse> {
|
||||
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
|
||||
@ -520,20 +544,20 @@ export class QueryClient {
|
||||
// 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, key);
|
||||
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, key, value);
|
||||
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 value;
|
||||
return { key, value, height };
|
||||
}
|
||||
|
||||
public async queryRawProof(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user