@freedomofpress/ics23 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/Readme.md +3 -0
  2. package/dist/.gitkeep +0 -0
  3. package/dist/compress.d.ts +3 -0
  4. package/dist/compress.js +96 -0
  5. package/dist/compress.js.map +1 -0
  6. package/dist/ics23.d.ts +18 -0
  7. package/dist/ics23.js +118 -0
  8. package/dist/ics23.js.map +1 -0
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.js +4 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/ops.d.ts +4 -0
  13. package/dist/ops.js +111 -0
  14. package/dist/ops.js.map +1 -0
  15. package/dist/proofs.d.ts +11 -0
  16. package/dist/proofs.js +235 -0
  17. package/dist/proofs.js.map +1 -0
  18. package/dist/proto/cosmos/ics23/v1/proofs.d.ts +264 -0
  19. package/dist/proto/cosmos/ics23/v1/proofs.js +1411 -0
  20. package/dist/proto/cosmos/ics23/v1/proofs.js.map +1 -0
  21. package/dist/specs.d.ts +7 -0
  22. package/dist/specs.js +105 -0
  23. package/dist/specs.js.map +1 -0
  24. package/dist/tests/ops.test.d.ts +1 -0
  25. package/dist/tests/ops.test.js +143 -0
  26. package/dist/tests/ops.test.js.map +1 -0
  27. package/dist/tests/proofs.test.d.ts +1 -0
  28. package/dist/tests/proofs.test.js +194 -0
  29. package/dist/tests/proofs.test.js.map +1 -0
  30. package/dist/tests/testhelpers.d.ts +3 -0
  31. package/dist/tests/testhelpers.js +35 -0
  32. package/dist/tests/testhelpers.js.map +1 -0
  33. package/dist/tests/testvectors.test.d.ts +1 -0
  34. package/dist/tests/testvectors.test.js +229 -0
  35. package/dist/tests/testvectors.test.js.map +1 -0
  36. package/dist/tests/webcat.test.d.ts +1 -0
  37. package/dist/tests/webcat.test.js +45 -0
  38. package/dist/tests/webcat.test.js.map +1 -0
  39. package/dist/webcat.d.ts +15 -0
  40. package/dist/webcat.js +77 -0
  41. package/dist/webcat.js.map +1 -0
  42. package/package.json +46 -0
package/Readme.md ADDED
@@ -0,0 +1,3 @@
1
+ Forked from the deprecated www.npmjs.com/package/@confio/ics23 commit b04a0987049611c8d564672d0b74b9f4bc036de6
2
+
3
+ Modified to support webcat proofs, otherwise not maintained to be in sync with the cosmos spec. Usage discouraged.
package/dist/.gitkeep ADDED
File without changes
@@ -0,0 +1,3 @@
1
+ import { CommitmentProof } from "./proto/cosmos/ics23/v1/proofs";
2
+ export declare function compress(proof: CommitmentProof): CommitmentProof;
3
+ export declare function decompress(proof: CommitmentProof): CommitmentProof;
@@ -0,0 +1,96 @@
1
+ import { InnerOp, } from "./proto/cosmos/ics23/v1/proofs";
2
+ export function compress(proof) {
3
+ if (!proof.batch) {
4
+ return proof;
5
+ }
6
+ return { compressed: compressBatch(proof.batch) };
7
+ }
8
+ export function decompress(proof) {
9
+ if (!proof.compressed) {
10
+ return proof;
11
+ }
12
+ return { batch: decompressBatch(proof.compressed) };
13
+ }
14
+ function compressBatch(proof) {
15
+ const centries = [];
16
+ const lookup = [];
17
+ const registry = new Map();
18
+ for (const entry of proof.entries) {
19
+ if (entry.exist) {
20
+ const centry = { exist: compressExist(entry.exist, lookup, registry) };
21
+ centries.push(centry);
22
+ }
23
+ else if (entry.nonexist) {
24
+ const non = entry.nonexist;
25
+ const centry = {
26
+ nonexist: {
27
+ key: non.key,
28
+ left: compressExist(non.left, lookup, registry),
29
+ right: compressExist(non.right, lookup, registry),
30
+ },
31
+ };
32
+ centries.push(centry);
33
+ }
34
+ else {
35
+ throw new Error("Unexpected batch entry during compress");
36
+ }
37
+ }
38
+ return {
39
+ entries: centries,
40
+ lookupInners: lookup,
41
+ };
42
+ }
43
+ function compressExist(exist, lookup, registry) {
44
+ if (!exist) {
45
+ return undefined;
46
+ }
47
+ const path = exist.path.map((inner) => {
48
+ const sig = InnerOp.encode(inner).finish();
49
+ let idx = registry.get(sig);
50
+ if (idx === undefined) {
51
+ idx = lookup.length;
52
+ lookup.push(inner);
53
+ registry.set(sig, idx);
54
+ }
55
+ return idx;
56
+ });
57
+ return {
58
+ key: exist.key,
59
+ value: exist.value,
60
+ leaf: exist.leaf,
61
+ path,
62
+ };
63
+ }
64
+ function decompressBatch(proof) {
65
+ const lookup = proof.lookupInners;
66
+ const entries = proof.entries.map((comp) => {
67
+ if (comp.exist) {
68
+ return { exist: decompressExist(comp.exist, lookup) };
69
+ }
70
+ else if (comp.nonexist) {
71
+ const non = comp.nonexist;
72
+ return {
73
+ nonexist: {
74
+ key: non.key,
75
+ left: decompressExist(non.left, lookup),
76
+ right: decompressExist(non.right, lookup),
77
+ },
78
+ };
79
+ }
80
+ else {
81
+ throw new Error("Unexpected batch entry during compress");
82
+ }
83
+ });
84
+ return {
85
+ entries,
86
+ };
87
+ }
88
+ function decompressExist(exist, lookup) {
89
+ if (!exist) {
90
+ return undefined;
91
+ }
92
+ const { key, value, leaf, path } = exist;
93
+ const newPath = (path || []).map((idx) => lookup[idx]);
94
+ return { key, value, leaf, path: newPath };
95
+ }
96
+ //# sourceMappingURL=compress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compress.js","sourceRoot":"","sources":["../src/compress.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,OAAO,GACR,MAAM,gCAAgC,CAAC;AAExC,MAAM,UAAU,QAAQ,CAAC,KAAsB;IAC7C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE/C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAQ,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;YACvE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC3B,MAAM,MAAM,GAAG;gBACb,QAAQ,EAAE;oBACR,GAAG,EAAE,GAAG,CAAC,GAAG;oBACZ,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;oBAC/C,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC;iBAClD;aACF,CAAC;YACF,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,QAAQ;QACjB,YAAY,EAAE,MAAM;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CACpB,KAAwC,EACxC,MAAiB,EACjB,QAAiC;IAEjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAK,CAAC,GAAG,CAAC,CAAC,KAAc,EAAE,EAAE;QAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC3C,IAAI,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI;KACL,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAA2B;IAClD,MAAM,MAAM,GAAG,KAAK,CAAC,YAAa,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAQ,CAAC,GAAG,CAAC,CAAC,IAA0B,EAAE,EAAE;QAChE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;QACxD,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC1B,OAAO;gBACL,QAAQ,EAAE;oBACR,GAAG,EAAE,GAAG,CAAC,GAAG;oBACZ,IAAI,EAAE,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;oBACvC,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;iBAC1C;aACF,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO;QACL,OAAO;KACR,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CACtB,KAAkD,EAClD,MAA0B;IAE1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { CommitmentRoot } from "./proofs";
2
+ import { CommitmentProof, ProofSpec } from "./proto/cosmos/ics23/v1/proofs";
3
+ /**
4
+ * verifyMembership ensures proof is (contains) a valid existence proof for the given
5
+ */
6
+ export declare function verifyMembership(proof: CommitmentProof, spec: ProofSpec, root: CommitmentRoot, key: Uint8Array, value: Uint8Array): Promise<boolean>;
7
+ /**
8
+ * verifyNonMembership ensures proof is (contains) a valid non-existence proof for the given key
9
+ */
10
+ export declare function verifyNonMembership(proof: CommitmentProof, spec: ProofSpec, root: CommitmentRoot, key: Uint8Array): Promise<boolean>;
11
+ /**
12
+ * batchVerifyMembership ensures proof is (contains) a valid existence proof for the given
13
+ */
14
+ export declare function batchVerifyMembership(proof: CommitmentProof, spec: ProofSpec, root: CommitmentRoot, items: Map<Uint8Array, Uint8Array>): Promise<boolean>;
15
+ /**
16
+ * batchVerifyNonMembership ensures proof is (contains) a valid existence proof for the given
17
+ */
18
+ export declare function batchVerifyNonMembership(proof: CommitmentProof, spec: ProofSpec, root: CommitmentRoot, keys: readonly Uint8Array[]): Promise<boolean>;
package/dist/ics23.js ADDED
@@ -0,0 +1,118 @@
1
+ import { decompress } from "./compress";
2
+ import { verifyExistence, verifyNonExistence } from "./proofs";
3
+ import { keyForComparison } from "./proofs";
4
+ import { bytesBefore, bytesEqual } from "./specs";
5
+ /*
6
+ This implements the client side functions as specified in
7
+ https://github.com/cosmos/ics/tree/master/spec/ics-023-vector-commitments
8
+
9
+ In particular:
10
+
11
+ // Assumes ExistenceProof
12
+ type verifyMembership = (root: CommitmentRoot, proof: CommitmentProof, key: Key, value: Value) => boolean
13
+
14
+ // Assumes NonExistenceProof
15
+ type verifyNonMembership = (root: CommitmentRoot, proof: CommitmentProof, key: Key) => boolean
16
+
17
+ // Assumes BatchProof - required ExistenceProofs may be a subset of all items proven
18
+ type batchVerifyMembership = (root: CommitmentRoot, proof: CommitmentProof, items: Map<Key, Value>) => boolean
19
+
20
+ // Assumes BatchProof - required NonExistenceProofs may be a subset of all items proven
21
+ type batchVerifyNonMembership = (root: CommitmentRoot, proof: CommitmentProof, keys: Set<Key>) => boolean
22
+
23
+ We make an adjustment to accept a Spec to ensure the provided proof is in the format of the expected merkle store.
24
+ This can avoid an range of attacks on fake preimages, as we need to be careful on how to map key, value -> leaf
25
+ and determine neighbors
26
+ */
27
+ /**
28
+ * verifyMembership ensures proof is (contains) a valid existence proof for the given
29
+ */
30
+ export async function verifyMembership(proof, spec, root, key, value) {
31
+ const norm = decompress(proof);
32
+ const exist = getExistForKey(norm, key);
33
+ if (!exist) {
34
+ return false;
35
+ }
36
+ try {
37
+ await verifyExistence(exist, spec, root, key, value);
38
+ return true;
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ /**
45
+ * verifyNonMembership ensures proof is (contains) a valid non-existence proof for the given key
46
+ */
47
+ export async function verifyNonMembership(proof, spec, root, key) {
48
+ const norm = decompress(proof);
49
+ const nonexist = await getNonExistForKey(spec, norm, key);
50
+ if (!nonexist) {
51
+ return false;
52
+ }
53
+ try {
54
+ await verifyNonExistence(nonexist, spec, root, key);
55
+ return true;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ /**
62
+ * batchVerifyMembership ensures proof is (contains) a valid existence proof for the given
63
+ */
64
+ export async function batchVerifyMembership(proof, spec, root, items) {
65
+ const norm = decompress(proof);
66
+ for (const [key, value] of items.entries()) {
67
+ if (!(await verifyMembership(norm, spec, root, key, value))) {
68
+ return false;
69
+ }
70
+ }
71
+ return true;
72
+ }
73
+ /**
74
+ * batchVerifyNonMembership ensures proof is (contains) a valid existence proof for the given
75
+ */
76
+ export async function batchVerifyNonMembership(proof, spec, root, keys) {
77
+ const norm = decompress(proof);
78
+ for (const key of keys) {
79
+ if (!(await verifyNonMembership(norm, spec, root, key))) {
80
+ return false;
81
+ }
82
+ }
83
+ return true;
84
+ }
85
+ function getExistForKey(proof, key) {
86
+ const match = (p) => !!p && bytesEqual(key, p.key);
87
+ if (match(proof.exist)) {
88
+ return proof.exist;
89
+ }
90
+ else if (proof.batch) {
91
+ return proof.batch
92
+ .entries.map((x) => x.exist || null)
93
+ .find(match);
94
+ }
95
+ return undefined;
96
+ }
97
+ async function getNonExistForKey(spec, proof, key) {
98
+ const match = async (p) => {
99
+ return (!!p &&
100
+ (!p.left ||
101
+ bytesBefore(await keyForComparison(spec, p.left.key), await keyForComparison(spec, key))) &&
102
+ (!p.right ||
103
+ bytesBefore(await keyForComparison(spec, key), await keyForComparison(spec, p.right.key))));
104
+ };
105
+ if (await match(proof.nonexist)) {
106
+ return proof.nonexist;
107
+ }
108
+ else if (proof.batch) {
109
+ for (const entry of proof.batch.entries || []) {
110
+ const candidate = entry.nonexist || null;
111
+ if (await match(candidate)) {
112
+ return candidate;
113
+ }
114
+ }
115
+ }
116
+ return undefined;
117
+ }
118
+ //# sourceMappingURL=ics23.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ics23.js","sourceRoot":"","sources":["../src/ics23.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { verifyMembership, verifyNonMembership } from "./ics23";
2
+ export { calculateExistenceRoot, CommitmentRoot, iavlSpec, tendermintSpec, verifyExistence, verifyNonExistence, } from "./proofs";
3
+ export { verifyWebcatProof, webcatSpec } from "./webcat";
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { verifyMembership, verifyNonMembership } from "./ics23";
2
+ export { calculateExistenceRoot, iavlSpec, tendermintSpec, verifyExistence, verifyNonExistence, } from "./proofs";
3
+ export { verifyWebcatProof, webcatSpec } from "./webcat";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EACL,sBAAsB,EAEtB,QAAQ,EACR,cAAc,EACd,eAAe,EACf,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
package/dist/ops.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { HashOp, InnerOp, LeafOp } from "./proto/cosmos/ics23/v1/proofs";
2
+ export declare function applyLeaf(leaf: LeafOp, key: Uint8Array, value: Uint8Array): Promise<Uint8Array>;
3
+ export declare function applyInner(inner: InnerOp, child: Uint8Array): Promise<Uint8Array>;
4
+ export declare function doHash(hashOp: HashOp, preimage: Uint8Array): Promise<Uint8Array>;
package/dist/ops.js ADDED
@@ -0,0 +1,111 @@
1
+ import { HashOp, LengthOp, } from "./proto/cosmos/ics23/v1/proofs";
2
+ const subtle = globalThis.crypto?.subtle;
3
+ async function sha256(preimage) {
4
+ if (!subtle) {
5
+ throw new Error("Web Crypto API is not available");
6
+ }
7
+ const digest = await subtle.digest("SHA-256", preimage);
8
+ return new Uint8Array(digest);
9
+ }
10
+ export async function applyLeaf(leaf, key, value) {
11
+ if (key.length === 0) {
12
+ throw new Error("Missing key");
13
+ }
14
+ if (value.length === 0) {
15
+ throw new Error("Missing value");
16
+ }
17
+ const pkey = await prepareLeafData(ensureHash(leaf.prehashKey), ensureLength(leaf.length), key);
18
+ const pvalue = await prepareLeafData(ensureHash(leaf.prehashValue), ensureLength(leaf.length), value);
19
+ const data = new Uint8Array([
20
+ ...ensureBytes(leaf.prefix),
21
+ ...pkey,
22
+ ...pvalue,
23
+ ]);
24
+ return doHash(ensureHash(leaf.hash), data);
25
+ }
26
+ export async function applyInner(inner, child) {
27
+ if (child.length === 0) {
28
+ throw new Error("Inner op needs child value");
29
+ }
30
+ const preimage = new Uint8Array([
31
+ ...ensureBytes(inner.prefix),
32
+ ...child,
33
+ ...ensureBytes(inner.suffix),
34
+ ]);
35
+ return doHash(ensureHash(inner.hash), preimage);
36
+ }
37
+ function ensure(maybe, value) {
38
+ return maybe === undefined || maybe === null ? value : maybe;
39
+ }
40
+ const ensureHash = (h) => ensure(h, HashOp.NO_HASH);
41
+ const ensureLength = (l) => ensure(l, LengthOp.NO_PREFIX);
42
+ const ensureBytes = (b) => ensure(b, new Uint8Array([]));
43
+ async function prepareLeafData(hashOp, lengthOp, data) {
44
+ const h = await doHashOrNoop(hashOp, data);
45
+ return doLengthOp(lengthOp, h);
46
+ }
47
+ // doHashOrNoop will return the preimage untouched if hashOp == NONE,
48
+ // otherwise, perform doHash
49
+ async function doHashOrNoop(hashOp, preimage) {
50
+ if (hashOp === HashOp.NO_HASH) {
51
+ return preimage;
52
+ }
53
+ return doHash(hashOp, preimage);
54
+ }
55
+ // doHash will perform the specified hash on the preimage.
56
+ // if hashOp == NONE, it will return an error (use doHashOrNoop if you want different behavior)
57
+ export async function doHash(hashOp, preimage) {
58
+ if (hashOp === HashOp.SHA256) {
59
+ return sha256(preimage);
60
+ }
61
+ throw new Error(`Unsupported hashop: ${hashOp}`);
62
+ }
63
+ // doLengthOp will calculate the proper prefix and return it prepended
64
+ // doLengthOp(op, data) -> length(data) || data
65
+ function doLengthOp(lengthOp, data) {
66
+ switch (lengthOp) {
67
+ case LengthOp.NO_PREFIX:
68
+ return data;
69
+ case LengthOp.VAR_PROTO:
70
+ return new Uint8Array([...encodeVarintProto(data.length), ...data]);
71
+ case LengthOp.REQUIRE_32_BYTES:
72
+ if (data.length !== 32) {
73
+ throw new Error(`Length is ${data.length}, not 32 bytes`);
74
+ }
75
+ return data;
76
+ case LengthOp.REQUIRE_64_BYTES:
77
+ if (data.length !== 64) {
78
+ throw new Error(`Length is ${data.length}, not 64 bytes`);
79
+ }
80
+ return data;
81
+ case LengthOp.FIXED32_LITTLE:
82
+ return new Uint8Array([...encodeFixed32Le(data.length), ...data]);
83
+ // TODO
84
+ // case LengthOp_VAR_RLP:
85
+ // case LengthOp_FIXED32_BIG:
86
+ // case LengthOp_FIXED64_BIG:
87
+ // case LengthOp_FIXED64_LITTLE:
88
+ }
89
+ throw new Error(`Unsupported lengthop: ${lengthOp}`);
90
+ }
91
+ function encodeVarintProto(n) {
92
+ let enc = [];
93
+ let l = n;
94
+ while (l >= 128) {
95
+ const b = (l % 128) + 128;
96
+ enc = [...enc, b];
97
+ l = l / 128;
98
+ }
99
+ enc = [...enc, l];
100
+ return new Uint8Array(enc);
101
+ }
102
+ function encodeFixed32Le(n) {
103
+ const enc = new Uint8Array(4);
104
+ let l = n;
105
+ for (let i = enc.length; i > 0; i--) {
106
+ enc[Math.abs(i - enc.length)] = l % 256;
107
+ l = Math.floor(l / 256);
108
+ }
109
+ return enc;
110
+ }
111
+ //# sourceMappingURL=ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops.js","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { ExistenceProof, InnerOp, InnerSpec, NonExistenceProof, ProofSpec } from "./proto/cosmos/ics23/v1/proofs";
2
+ export declare const iavlSpec: ProofSpec;
3
+ export declare const tendermintSpec: ProofSpec;
4
+ export declare const smtSpec: ProofSpec;
5
+ export type CommitmentRoot = Uint8Array;
6
+ export declare function keyForComparison(spec: ProofSpec, key: Uint8Array): Promise<Uint8Array>;
7
+ export declare function verifyExistence(proof: ExistenceProof, spec: ProofSpec, root: CommitmentRoot, key: Uint8Array, value: Uint8Array): Promise<void>;
8
+ export declare function verifyNonExistence(proof: NonExistenceProof, spec: ProofSpec, root: CommitmentRoot, key: Uint8Array): Promise<void>;
9
+ export declare function calculateExistenceRoot(proof: ExistenceProof): Promise<CommitmentRoot>;
10
+ export declare function ensureSpec(proof: ExistenceProof, spec: ProofSpec): void;
11
+ export declare function ensureLeftNeighbor(spec: InnerSpec, left: readonly InnerOp[], right: readonly InnerOp[]): void;
package/dist/proofs.js ADDED
@@ -0,0 +1,235 @@
1
+ import { applyInner, applyLeaf, doHash } from "./ops";
2
+ import { HashOp, LengthOp, } from "./proto/cosmos/ics23/v1/proofs";
3
+ import { bytesEqual, ensureBytesBefore, ensureBytesEqual, ensureInner, ensureLeaf, } from "./specs";
4
+ export const iavlSpec = {
5
+ leafSpec: {
6
+ prefix: Uint8Array.from([0]),
7
+ hash: HashOp.SHA256,
8
+ prehashValue: HashOp.SHA256,
9
+ prehashKey: HashOp.NO_HASH,
10
+ length: LengthOp.VAR_PROTO,
11
+ },
12
+ innerSpec: {
13
+ childOrder: [0, 1],
14
+ minPrefixLength: 4,
15
+ maxPrefixLength: 12,
16
+ childSize: 33,
17
+ hash: HashOp.SHA256,
18
+ emptyChild: new Uint8Array(),
19
+ },
20
+ minDepth: 0,
21
+ maxDepth: 255,
22
+ prehashKeyBeforeComparison: false,
23
+ };
24
+ export const tendermintSpec = {
25
+ leafSpec: {
26
+ prefix: Uint8Array.from([0]),
27
+ hash: HashOp.SHA256,
28
+ prehashValue: HashOp.SHA256,
29
+ prehashKey: HashOp.NO_HASH,
30
+ length: LengthOp.VAR_PROTO,
31
+ },
32
+ innerSpec: {
33
+ childOrder: [0, 1],
34
+ minPrefixLength: 1,
35
+ maxPrefixLength: 1,
36
+ childSize: 32,
37
+ hash: HashOp.SHA256,
38
+ emptyChild: new Uint8Array(),
39
+ },
40
+ minDepth: 0,
41
+ maxDepth: 255,
42
+ prehashKeyBeforeComparison: false,
43
+ };
44
+ export const smtSpec = {
45
+ leafSpec: {
46
+ hash: HashOp.SHA256,
47
+ prehashKey: HashOp.SHA256,
48
+ prehashValue: HashOp.SHA256,
49
+ length: LengthOp.NO_PREFIX,
50
+ prefix: Uint8Array.from([0]),
51
+ },
52
+ innerSpec: {
53
+ childOrder: [0, 1],
54
+ childSize: 32,
55
+ minPrefixLength: 1,
56
+ maxPrefixLength: 1,
57
+ emptyChild: new Uint8Array(32),
58
+ hash: HashOp.SHA256,
59
+ },
60
+ maxDepth: 256,
61
+ minDepth: 0,
62
+ prehashKeyBeforeComparison: true,
63
+ };
64
+ export async function keyForComparison(spec, key) {
65
+ if (!spec.prehashKeyBeforeComparison) {
66
+ return key;
67
+ }
68
+ return doHash(spec.leafSpec.prehashKey, key);
69
+ }
70
+ // verifyExistence will throw an error if the proof doesn't link key, value -> root
71
+ // or if it doesn't fulfill the spec
72
+ export async function verifyExistence(proof, spec, root, key, value) {
73
+ ensureSpec(proof, spec);
74
+ const calc = await calculateExistenceRoot(proof);
75
+ ensureBytesEqual(calc, root);
76
+ ensureBytesEqual(key, proof.key);
77
+ ensureBytesEqual(value, proof.value);
78
+ }
79
+ // Verify does all checks to ensure the proof has valid non-existence proofs,
80
+ // and they ensure the given key is not in the CommitmentState,
81
+ // throwing an error if there is an issue
82
+ export async function verifyNonExistence(proof, spec, root, key) {
83
+ let leftKey;
84
+ let rightKey;
85
+ if (proof.left) {
86
+ await verifyExistence(proof.left, spec, root, proof.left.key, proof.left.value);
87
+ leftKey = proof.left.key;
88
+ }
89
+ if (proof.right) {
90
+ await verifyExistence(proof.right, spec, root, proof.right.key, proof.right.value);
91
+ rightKey = proof.right.key;
92
+ }
93
+ if (!leftKey && !rightKey) {
94
+ throw new Error("neither left nor right proof defined");
95
+ }
96
+ if (leftKey) {
97
+ ensureBytesBefore(await keyForComparison(spec, leftKey), await keyForComparison(spec, key));
98
+ }
99
+ if (rightKey) {
100
+ ensureBytesBefore(await keyForComparison(spec, key), await keyForComparison(spec, rightKey));
101
+ }
102
+ if (!spec.innerSpec) {
103
+ throw new Error("no inner spec");
104
+ }
105
+ if (!leftKey) {
106
+ ensureLeftMost(spec.innerSpec, proof.right.path);
107
+ }
108
+ else if (!rightKey) {
109
+ ensureRightMost(spec.innerSpec, proof.left.path);
110
+ }
111
+ else {
112
+ ensureLeftNeighbor(spec.innerSpec, proof.left.path, proof.right.path);
113
+ }
114
+ return;
115
+ }
116
+ // Calculate determines the root hash that matches the given proof.
117
+ // You must validate the result is what you have in a header.
118
+ // Returns error if the calculations cannot be performed.
119
+ export async function calculateExistenceRoot(proof) {
120
+ if (!proof.key || !proof.value) {
121
+ throw new Error("Existence proof needs key and value set");
122
+ }
123
+ if (!proof.leaf) {
124
+ throw new Error("Existence proof must start with a leaf operation");
125
+ }
126
+ const path = proof.path || [];
127
+ let res = await applyLeaf(proof.leaf, proof.key, proof.value);
128
+ for (const inner of path) {
129
+ res = await applyInner(inner, res);
130
+ }
131
+ return res;
132
+ }
133
+ // ensureSpec throws an Error if proof doesn't fulfill spec
134
+ export function ensureSpec(proof, spec) {
135
+ if (!proof.leaf) {
136
+ throw new Error("Existence proof must start with a leaf operation");
137
+ }
138
+ if (!spec.leafSpec) {
139
+ throw new Error("Spec must include leafSpec");
140
+ }
141
+ if (!spec.innerSpec) {
142
+ throw new Error("Spec must include innerSpec");
143
+ }
144
+ ensureLeaf(proof.leaf, spec.leafSpec);
145
+ const path = proof.path || [];
146
+ if (spec.minDepth && path.length < spec.minDepth) {
147
+ throw new Error(`Too few inner nodes ${path.length}`);
148
+ }
149
+ if (spec.maxDepth && path.length > spec.maxDepth) {
150
+ throw new Error(`Too many inner nodes ${path.length}`);
151
+ }
152
+ for (const inner of path) {
153
+ ensureInner(inner, spec.leafSpec.prefix, spec.innerSpec);
154
+ }
155
+ }
156
+ function ensureLeftMost(spec, path) {
157
+ const { minPrefix, maxPrefix, suffix } = getPadding(spec, 0);
158
+ // ensure every step has a prefix and suffix defined to be leftmost
159
+ for (const step of path) {
160
+ if (!hasPadding(step, minPrefix, maxPrefix, suffix)) {
161
+ throw new Error("Step not leftmost");
162
+ }
163
+ }
164
+ }
165
+ function ensureRightMost(spec, path) {
166
+ const len = spec.childOrder.length - 1;
167
+ const { minPrefix, maxPrefix, suffix } = getPadding(spec, len);
168
+ // ensure every step has a prefix and suffix defined to be leftmost
169
+ for (const step of path) {
170
+ if (!hasPadding(step, minPrefix, maxPrefix, suffix)) {
171
+ throw new Error("Step not leftmost");
172
+ }
173
+ }
174
+ }
175
+ export function ensureLeftNeighbor(spec, left, right) {
176
+ const mutleft = [...left];
177
+ const mutright = [...right];
178
+ let topleft = mutleft.pop();
179
+ let topright = mutright.pop();
180
+ while (bytesEqual(topleft.prefix, topright.prefix) &&
181
+ bytesEqual(topleft.suffix, topright.suffix)) {
182
+ topleft = mutleft.pop();
183
+ topright = mutright.pop();
184
+ }
185
+ // now topleft and topright are the first divergent nodes
186
+ // make sure they are left and right of each other
187
+ if (!isLeftStep(spec, topleft, topright)) {
188
+ throw new Error(`Not left neightbor at first divergent step`);
189
+ }
190
+ // make sure the paths are left and right most possibilities respectively
191
+ ensureRightMost(spec, mutleft);
192
+ ensureLeftMost(spec, mutright);
193
+ }
194
+ // isLeftStep assumes left and right have common parents
195
+ // checks if left is exactly one slot to the left of right
196
+ function isLeftStep(spec, left, right) {
197
+ const leftidx = orderFromPadding(spec, left);
198
+ const rightidx = orderFromPadding(spec, right);
199
+ return rightidx === leftidx + 1;
200
+ }
201
+ function orderFromPadding(spec, inner) {
202
+ for (let branch = 0; branch < spec.childOrder.length; branch++) {
203
+ const { minPrefix, maxPrefix, suffix } = getPadding(spec, branch);
204
+ if (hasPadding(inner, minPrefix, maxPrefix, suffix)) {
205
+ return branch;
206
+ }
207
+ }
208
+ throw new Error(`Cannot find any valid spacing for this node`);
209
+ }
210
+ function hasPadding(op, minPrefix, maxPrefix, suffix) {
211
+ if ((op.prefix || []).length < minPrefix) {
212
+ return false;
213
+ }
214
+ if ((op.prefix || []).length > maxPrefix) {
215
+ return false;
216
+ }
217
+ return (op.suffix || []).length === suffix;
218
+ }
219
+ function getPadding(spec, branch) {
220
+ const idx = getPosition(spec.childOrder, branch);
221
+ // count how many children are in the prefix
222
+ const prefix = idx * spec.childSize;
223
+ const minPrefix = prefix + spec.minPrefixLength;
224
+ const maxPrefix = prefix + spec.maxPrefixLength;
225
+ // count how many children are in the suffix
226
+ const suffix = (spec.childOrder.length - 1 - idx) * spec.childSize;
227
+ return { minPrefix, maxPrefix, suffix };
228
+ }
229
+ function getPosition(order, branch) {
230
+ if (branch < 0 || branch >= order.length) {
231
+ throw new Error(`Invalid branch: ${branch}`);
232
+ }
233
+ return order.findIndex((val) => val === branch);
234
+ }
235
+ //# sourceMappingURL=proofs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proofs.js","sourceRoot":"","sources":["../src/proofs.ts"],"names":[],"mappings":"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"}