mirror of
https://github.com/cosmos/cosmjs.git
synced 2025-03-10 21:49:15 +00:00
Parse ics23 proofs and do initial verification
This commit is contained in:
parent
f70b3a83fa
commit
f43870f818
@ -45,6 +45,7 @@
|
|||||||
"postdefine-proto": "prettier --write \"src/codec/generated/codecimpl.*\""
|
"postdefine-proto": "prettier --write \"src/codec/generated/codecimpl.*\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@confio/ics23": "^0.6.0",
|
||||||
"@cosmjs/encoding": "^0.22.2",
|
"@cosmjs/encoding": "^0.22.2",
|
||||||
"@cosmjs/launchpad": "^0.22.2",
|
"@cosmjs/launchpad": "^0.22.2",
|
||||||
"@cosmjs/math": "^0.22.2",
|
"@cosmjs/math": "^0.22.2",
|
||||||
|
@ -1,8 +1,44 @@
|
|||||||
/* eslint-disable no-dupe-class-members, @typescript-eslint/ban-types, @typescript-eslint/naming-convention */
|
/* eslint-disable no-dupe-class-members, @typescript-eslint/ban-types, @typescript-eslint/naming-convention */
|
||||||
import { toHex, fromAscii } from "@cosmjs/encoding";
|
import { ics23, verifyExistence } from "@confio/ics23";
|
||||||
|
import { fromAscii, toHex } from "@cosmjs/encoding";
|
||||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||||
import { arrayContentEquals, assert, isNonNullObject } from "@cosmjs/utils";
|
import { arrayContentEquals, assert, isNonNullObject } from "@cosmjs/utils";
|
||||||
|
|
||||||
|
// TODO: import these from @confio/ics23 when exported
|
||||||
|
export const IavlSpec: ics23.IProofSpec = {
|
||||||
|
leafSpec: {
|
||||||
|
prefix: Uint8Array.from([0]),
|
||||||
|
hash: ics23.HashOp.SHA256,
|
||||||
|
prehashValue: ics23.HashOp.SHA256,
|
||||||
|
prehashKey: ics23.HashOp.NO_HASH,
|
||||||
|
length: ics23.LengthOp.VAR_PROTO,
|
||||||
|
},
|
||||||
|
innerSpec: {
|
||||||
|
childOrder: [0, 1],
|
||||||
|
minPrefixLength: 4,
|
||||||
|
maxPrefixLength: 12,
|
||||||
|
childSize: 33,
|
||||||
|
hash: ics23.HashOp.SHA256,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TendermintSpec: ics23.IProofSpec = {
|
||||||
|
leafSpec: {
|
||||||
|
prefix: Uint8Array.from([0]),
|
||||||
|
hash: ics23.HashOp.SHA256,
|
||||||
|
prehashValue: ics23.HashOp.SHA256,
|
||||||
|
prehashKey: ics23.HashOp.NO_HASH,
|
||||||
|
length: ics23.LengthOp.VAR_PROTO,
|
||||||
|
},
|
||||||
|
innerSpec: {
|
||||||
|
childOrder: [0, 1],
|
||||||
|
minPrefixLength: 1,
|
||||||
|
maxPrefixLength: 1,
|
||||||
|
childSize: 32,
|
||||||
|
hash: ics23.HashOp.SHA256,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
type QueryExtensionSetup<P> = (base: QueryClient) => P;
|
type QueryExtensionSetup<P> = (base: QueryClient) => P;
|
||||||
|
|
||||||
export class QueryClient {
|
export class QueryClient {
|
||||||
@ -166,25 +202,46 @@ export class QueryClient {
|
|||||||
throw new Error(`Expected 2 proof ops, got ${response.proof.ops.length}. Are you using stargate?`);
|
throw new Error(`Expected 2 proof ops, got ${response.proof.ops.length}. Are you using stargate?`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const subProof = response.proof.ops[0];
|
const subOp = response.proof.ops[0];
|
||||||
if (subProof.type !== "ics23:iavl") {
|
if (subOp.type !== "ics23:iavl") {
|
||||||
throw new Error(`Sub-proof expected to be ics23:iavl, got "${subProof.type}`);
|
throw new Error(`Sub-proof expected to be ics23:iavl, got "${subOp.type}`);
|
||||||
}
|
}
|
||||||
if (!arrayContentEquals(key, subProof.key)) {
|
if (!arrayContentEquals(key, subOp.key)) {
|
||||||
throw new Error(`Proven key different than queried key.\nQuery: ${toHex(key)}\nProven: ${toHex(subProof.key)}`);
|
throw new Error(
|
||||||
}
|
`Proven key different than queried key.\nQuery: ${toHex(key)}\nProven: ${toHex(subOp.key)}`,
|
||||||
console.log(`Proof: ${toHex(subProof.data)}`);
|
);
|
||||||
|
|
||||||
const storeProof = response.proof.ops[1];
|
|
||||||
if (storeProof.type !== "ics23:simple") {
|
|
||||||
throw new Error(`Store-proof expected to be ics23:simple, got "${storeProof.type}`);
|
|
||||||
}
|
|
||||||
if (store !== fromAscii(storeProof.key)) {
|
|
||||||
throw new Error(`Proven store "${store}" different than queried store ${fromAscii(storeProof.key)}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement proof verification
|
const storeOp = response.proof.ops[1];
|
||||||
// https://github.com/CosmWasm/cosmjs/issues/347
|
if (storeOp.type !== "ics23:simple") {
|
||||||
|
throw new Error(`Store-proof expected to be ics23:simple, got "${storeOp.type}`);
|
||||||
|
}
|
||||||
|
if (store !== fromAscii(storeOp.key)) {
|
||||||
|
throw new Error(`Proven store "${store}" different than queried store ${fromAscii(storeOp.key)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(response.height);
|
||||||
|
assert(response.height > 0);
|
||||||
|
|
||||||
|
// parse proofs
|
||||||
|
const subProof = ics23.CommitmentProof.decode(subOp.data);
|
||||||
|
assert(subProof.exist);
|
||||||
|
assert(subProof.exist.value);
|
||||||
|
|
||||||
|
const storeProof = ics23.CommitmentProof.decode(storeOp.data);
|
||||||
|
assert(storeProof.exist);
|
||||||
|
assert(storeProof.exist.value);
|
||||||
|
|
||||||
|
// the subproof must map the desired key to the "value" of the storeProof
|
||||||
|
verifyExistence(subProof.exist, IavlSpec, storeProof.exist.value, key, response.value);
|
||||||
|
|
||||||
|
// the storeproof must may it's declared value (root of subProof) to the appHash
|
||||||
|
// TODO
|
||||||
|
// // get the header for height + 1
|
||||||
|
// await sleep(5000); // TODO: we can do better
|
||||||
|
// // TODO: why don't we expose the header query, just height?
|
||||||
|
// const header = await this.tmClient.block(response.height+1);
|
||||||
|
// verifyExistence(storeProof.exist, TendermintSpec, header.block.header.appHash, toAscii(store), storeProof.exist.value!);
|
||||||
|
|
||||||
return response.value;
|
return response.value;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ics23 } from "@confio/ics23";
|
||||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||||
declare type QueryExtensionSetup<P> = (base: QueryClient) => P;
|
declare type QueryExtensionSetup<P> = (base: QueryClient) => P;
|
||||||
export declare class QueryClient {
|
export declare class QueryClient {
|
||||||
@ -106,4 +107,6 @@ export declare class QueryClient {
|
|||||||
queryVerified(store: string, key: Uint8Array): Promise<Uint8Array>;
|
queryVerified(store: string, key: Uint8Array): Promise<Uint8Array>;
|
||||||
queryUnverified(path: string, request: Uint8Array): Promise<Uint8Array>;
|
queryUnverified(path: string, request: Uint8Array): Promise<Uint8Array>;
|
||||||
}
|
}
|
||||||
|
export declare const IavlSpec: ics23.IProofSpec;
|
||||||
|
export declare const TendermintSpec: ics23.IProofSpec;
|
||||||
export {};
|
export {};
|
||||||
|
@ -25,7 +25,6 @@ import * as responses from "../responses";
|
|||||||
import { SubscriptionEvent } from "../rpcclients";
|
import { SubscriptionEvent } from "../rpcclients";
|
||||||
import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "../types";
|
import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "../types";
|
||||||
import { hashTx } from "./hasher";
|
import { hashTx } from "./hasher";
|
||||||
import { isArgon2idOptions } from "@cosmjs/crypto";
|
|
||||||
|
|
||||||
interface AbciInfoResult {
|
interface AbciInfoResult {
|
||||||
readonly response: RpcAbciInfoResponse;
|
readonly response: RpcAbciInfoResponse;
|
||||||
|
28
yarn.lock
28
yarn.lock
@ -177,6 +177,15 @@
|
|||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
|
"@confio/ics23@^0.6.0":
|
||||||
|
version "0.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@confio/ics23/-/ics23-0.6.0.tgz#8c3e6508159bdbee02b12beeee9b369ea68ef6ba"
|
||||||
|
integrity sha512-P/NcAO3pz7xXg4cpwaKRUIN4PuOOxwY94n7WD+wod7UG5YlMLzb8Upv6nZo9/brnKXW4gXB2DccLTtV0Um1Wvw==
|
||||||
|
dependencies:
|
||||||
|
protobufjs "^6.8.8"
|
||||||
|
ripemd160 "^2.0.2"
|
||||||
|
sha.js "^2.4.11"
|
||||||
|
|
||||||
"@evocateur/libnpmaccess@^3.1.2":
|
"@evocateur/libnpmaccess@^3.1.2":
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845"
|
resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845"
|
||||||
@ -6764,6 +6773,25 @@ proto-list@~1.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
|
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
|
||||||
integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
|
integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
|
||||||
|
|
||||||
|
protobufjs@^6.8.8:
|
||||||
|
version "6.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2"
|
||||||
|
integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==
|
||||||
|
dependencies:
|
||||||
|
"@protobufjs/aspromise" "^1.1.2"
|
||||||
|
"@protobufjs/base64" "^1.1.2"
|
||||||
|
"@protobufjs/codegen" "^2.0.4"
|
||||||
|
"@protobufjs/eventemitter" "^1.1.0"
|
||||||
|
"@protobufjs/fetch" "^1.1.0"
|
||||||
|
"@protobufjs/float" "^1.0.2"
|
||||||
|
"@protobufjs/inquire" "^1.1.0"
|
||||||
|
"@protobufjs/path" "^1.1.2"
|
||||||
|
"@protobufjs/pool" "^1.1.0"
|
||||||
|
"@protobufjs/utf8" "^1.1.0"
|
||||||
|
"@types/long" "^4.0.1"
|
||||||
|
"@types/node" "^13.7.0"
|
||||||
|
long "^4.0.0"
|
||||||
|
|
||||||
protobufjs@~6.10.0:
|
protobufjs@~6.10.0:
|
||||||
version "6.10.0"
|
version "6.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.0.tgz#b0698a2a91fc597e2dc625dcf3539ece9675c8fd"
|
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.0.tgz#b0698a2a91fc597e2dc625dcf3539ece9675c8fd"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user