@freedomofpress/ics23 0.1.1 → 0.1.3
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.
- package/dist/ops.js +1 -1
- package/dist/ops.js.map +1 -1
- package/dist/tests/webcat.test.js +12 -13
- package/dist/tests/webcat.test.js.map +1 -1
- package/dist/webcat.d.ts +3 -3
- package/dist/webcat.js +88 -22
- package/dist/webcat.js.map +1 -1
- package/package.json +1 -1
package/dist/ops.js
CHANGED
|
@@ -4,7 +4,7 @@ async function sha256(preimage) {
|
|
|
4
4
|
if (!subtle) {
|
|
5
5
|
throw new Error("Web Crypto API is not available");
|
|
6
6
|
}
|
|
7
|
-
const digest = await subtle.digest("SHA-256", preimage);
|
|
7
|
+
const digest = await subtle.digest("SHA-256", new Uint8Array(preimage));
|
|
8
8
|
return new Uint8Array(digest);
|
|
9
9
|
}
|
|
10
10
|
export async function applyLeaf(leaf, key, value) {
|
package/dist/ops.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAGN,QAAQ,GACT,MAAM,gCAAgC,CAAC;AAExC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;AAEzC,KAAK,UAAU,MAAM,CAAC,QAAoB;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import leavesData from "../../testdata/webcat/leaves.json";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { calculateExistenceRoot
|
|
3
|
+
import { calculateExistenceRoot } from "../proofs";
|
|
4
4
|
import { verifyWebcatProof, webcatSpec } from "../webcat";
|
|
5
5
|
import { CommitmentProof } from "../proto/cosmos/ics23/v1/proofs";
|
|
6
6
|
import { fromHex, toHex } from "./testhelpers";
|
|
7
7
|
describe("verifyWebcatProof", () => {
|
|
8
|
-
it("verifies
|
|
9
|
-
const
|
|
10
|
-
const elementProof = CommitmentProof.decode(fromHex(elementBytes));
|
|
8
|
+
it("verifies canonical linkage and reconstruction", async () => {
|
|
9
|
+
const canonicalBytes = leavesData.proof.merkle_proof.proof_bytes[1];
|
|
11
10
|
const canonicalProof = CommitmentProof.decode(fromHex(canonicalBytes));
|
|
12
|
-
const elementRoot = await calculateExistenceRoot(elementProof.exist);
|
|
13
11
|
const canonicalRoot = await calculateExistenceRoot(canonicalProof.exist);
|
|
14
|
-
const elementKey = new TextEncoder().encode(leavesData.proof.merkle_proof.representative_key.replace(/^canonical\//, ""));
|
|
15
|
-
const elementValue = fromHex(leavesData.leaves[1][1]);
|
|
16
|
-
expect(elementProof.exist?.key).toEqual(elementKey);
|
|
17
|
-
await expect(verifyExistence(elementProof.exist, webcatSpec, fromHex(leavesData.proof.canonical_root_hash), elementKey, elementValue)).resolves.not.toThrow();
|
|
18
|
-
await expect(verifyExistence(canonicalProof.exist, webcatSpec, fromHex(leavesData.proof.app_hash), new TextEncoder().encode("canonical"), fromHex(leavesData.proof.canonical_root_hash))).resolves.not.toThrow();
|
|
19
|
-
expect(toHex(elementRoot)).toBe(leavesData.proof.canonical_root_hash);
|
|
20
12
|
expect(toHex(canonicalRoot)).toBe(leavesData.proof.app_hash);
|
|
21
|
-
await expect(verifyWebcatProof(leavesData)).resolves.
|
|
13
|
+
await expect(verifyWebcatProof(leavesData)).resolves.toEqual(leavesData.leaves);
|
|
22
14
|
});
|
|
23
15
|
it("fails when app hash linkage is modified", async () => {
|
|
24
16
|
const tampered = {
|
|
@@ -30,6 +22,13 @@ describe("verifyWebcatProof", () => {
|
|
|
30
22
|
};
|
|
31
23
|
await expect(verifyWebcatProof(tampered)).resolves.toBe(false);
|
|
32
24
|
});
|
|
25
|
+
it("fails when canonical root cannot be reconstructed", async () => {
|
|
26
|
+
const tamperedLeaves = {
|
|
27
|
+
...leavesData,
|
|
28
|
+
leaves: leavesData.leaves.map((leaf, index) => index === 0 ? [leaf[0], "00" + leaf[1].slice(2)] : leaf),
|
|
29
|
+
};
|
|
30
|
+
await expect(verifyWebcatProof(tamperedLeaves)).resolves.toBe(false);
|
|
31
|
+
});
|
|
33
32
|
it("exposes the webcat spec for manual validation", async () => {
|
|
34
33
|
const proofBytes = leavesData.proof.merkle_proof.proof_bytes[0];
|
|
35
34
|
const proof = CommitmentProof.decode(fromHex(proofBytes));
|
|
@@ -37,7 +36,7 @@ describe("verifyWebcatProof", () => {
|
|
|
37
36
|
...leavesData,
|
|
38
37
|
proof: leavesData.proof,
|
|
39
38
|
});
|
|
40
|
-
expect(validation).
|
|
39
|
+
expect(validation).toEqual(leavesData.leaves);
|
|
41
40
|
expect(webcatSpec.leafSpec?.prefix?.length).toBe(13);
|
|
42
41
|
expect(proof.exist?.leaf?.prefix).toEqual(webcatSpec.leafSpec?.prefix);
|
|
43
42
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webcat.test.js","sourceRoot":"","sources":["../../src/tests/webcat.test.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,mCAAmC,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"webcat.test.js","sourceRoot":"","sources":["../../src/tests/webcat.test.ts"],"names":[],"mappings":"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"}
|
package/dist/webcat.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { ProofSpec } from "./proto/cosmos/ics23/v1/proofs";
|
|
2
|
+
export type WebcatLeaf = readonly [string, string];
|
|
2
3
|
export interface WebcatLeavesFile {
|
|
3
4
|
readonly block_height: number;
|
|
4
|
-
readonly leaves: readonly (
|
|
5
|
+
readonly leaves: readonly (WebcatLeaf | readonly string[])[];
|
|
5
6
|
readonly proof: {
|
|
6
7
|
readonly app_hash: string;
|
|
7
8
|
readonly canonical_root_hash: string;
|
|
8
9
|
readonly merkle_proof: {
|
|
9
10
|
readonly proof_bytes: readonly string[];
|
|
10
|
-
readonly representative_key: string;
|
|
11
11
|
};
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
export declare const webcatSpec: ProofSpec;
|
|
15
|
-
export declare function verifyWebcatProof(data: WebcatLeavesFile): Promise<
|
|
15
|
+
export declare function verifyWebcatProof(data: WebcatLeavesFile): Promise<readonly WebcatLeaf[] | false>;
|
package/dist/webcat.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { doHash } from "./ops";
|
|
1
2
|
import { verifyExistence } from "./proofs";
|
|
2
3
|
import { CommitmentProof, HashOp, LengthOp, } from "./proto/cosmos/ics23/v1/proofs";
|
|
4
|
+
import { bytesEqual } from "./specs";
|
|
3
5
|
function fromHex(hexstring) {
|
|
4
6
|
if (hexstring.length % 2 !== 0) {
|
|
5
7
|
throw new Error("hex string length must be a multiple of 2");
|
|
@@ -16,7 +18,8 @@ function fromHex(hexstring) {
|
|
|
16
18
|
}
|
|
17
19
|
const utf8Encoder = new TextEncoder();
|
|
18
20
|
const leafPrefix = utf8Encoder.encode("JMT::LeafNode");
|
|
19
|
-
const innerPrefix = utf8Encoder.encode("JMT::
|
|
21
|
+
const innerPrefix = utf8Encoder.encode("JMT::IntrnalNode");
|
|
22
|
+
const placeholderMarker = "SPARSE_MERKLE_PLACEHOLDER_HASH__";
|
|
20
23
|
export const webcatSpec = {
|
|
21
24
|
leafSpec: {
|
|
22
25
|
hash: HashOp.SHA256,
|
|
@@ -29,7 +32,7 @@ export const webcatSpec = {
|
|
|
29
32
|
hash: HashOp.SHA256,
|
|
30
33
|
childOrder: [0, 1],
|
|
31
34
|
childSize: 32,
|
|
32
|
-
minPrefixLength: innerPrefix.length
|
|
35
|
+
minPrefixLength: innerPrefix.length,
|
|
33
36
|
maxPrefixLength: innerPrefix.length,
|
|
34
37
|
emptyChild: new Uint8Array(),
|
|
35
38
|
},
|
|
@@ -40,35 +43,98 @@ export const webcatSpec = {
|
|
|
40
43
|
function decodeProof(hex) {
|
|
41
44
|
return CommitmentProof.decode(fromHex(hex));
|
|
42
45
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
if (!match) {
|
|
46
|
-
throw new Error("Representative key is missing from leaf set");
|
|
47
|
-
}
|
|
48
|
-
return fromHex(match[1]);
|
|
46
|
+
function placeholderHash() {
|
|
47
|
+
return utf8Encoder.encode(placeholderMarker);
|
|
49
48
|
}
|
|
50
|
-
function
|
|
49
|
+
function canonicalizeKey(key) {
|
|
51
50
|
return key.replace(/^canonical\//, "");
|
|
52
51
|
}
|
|
52
|
+
function normalizeLeaf(leaf) {
|
|
53
|
+
if (leaf.length < 2) {
|
|
54
|
+
throw new Error("Leaf entry must contain a key and value");
|
|
55
|
+
}
|
|
56
|
+
return [leaf[0], leaf[1]];
|
|
57
|
+
}
|
|
58
|
+
async function leafHash(key, valueHex) {
|
|
59
|
+
const hashedKey = await doHash(HashOp.SHA256, utf8Encoder.encode(canonicalizeKey(key)));
|
|
60
|
+
const hashedValue = await doHash(HashOp.SHA256, fromHex(valueHex));
|
|
61
|
+
const preimage = new Uint8Array([
|
|
62
|
+
...leafPrefix,
|
|
63
|
+
...hashedKey,
|
|
64
|
+
...hashedValue,
|
|
65
|
+
]);
|
|
66
|
+
return doHash(HashOp.SHA256, preimage);
|
|
67
|
+
}
|
|
68
|
+
async function combineChildren(left, right) {
|
|
69
|
+
const preimage = new Uint8Array([...innerPrefix, ...left, ...right]);
|
|
70
|
+
return doHash(HashOp.SHA256, preimage);
|
|
71
|
+
}
|
|
72
|
+
function bitIsSet(hash, depth) {
|
|
73
|
+
const byteIndex = Math.floor(depth / 8);
|
|
74
|
+
const bitIndex = 7 - (depth % 8);
|
|
75
|
+
const byte = hash[byteIndex] ?? 0;
|
|
76
|
+
return ((byte >> bitIndex) & 1) === 1;
|
|
77
|
+
}
|
|
78
|
+
async function prepareLeaves(leaves) {
|
|
79
|
+
const prepared = [];
|
|
80
|
+
for (const [key, valueHex] of leaves) {
|
|
81
|
+
const keyHash = await doHash(HashOp.SHA256, utf8Encoder.encode(canonicalizeKey(key)));
|
|
82
|
+
const nodeHash = await leafHash(key, valueHex);
|
|
83
|
+
prepared.push({ keyHash, nodeHash });
|
|
84
|
+
}
|
|
85
|
+
return prepared;
|
|
86
|
+
}
|
|
87
|
+
async function buildJmtRoot(placeholder, leaves, depth = 0) {
|
|
88
|
+
if (leaves.length === 0) {
|
|
89
|
+
return placeholder;
|
|
90
|
+
}
|
|
91
|
+
if (leaves.length === 1 || depth >= 256) {
|
|
92
|
+
return leaves[0].nodeHash;
|
|
93
|
+
}
|
|
94
|
+
const left = [];
|
|
95
|
+
const right = [];
|
|
96
|
+
for (const leaf of leaves) {
|
|
97
|
+
(bitIsSet(leaf.keyHash, depth) ? right : left).push(leaf);
|
|
98
|
+
}
|
|
99
|
+
const leftHash = left.length
|
|
100
|
+
? await buildJmtRoot(placeholder, left, depth + 1)
|
|
101
|
+
: placeholder;
|
|
102
|
+
const rightHash = right.length
|
|
103
|
+
? await buildJmtRoot(placeholder, right, depth + 1)
|
|
104
|
+
: placeholder;
|
|
105
|
+
return combineChildren(leftHash, rightHash);
|
|
106
|
+
}
|
|
107
|
+
async function reconstructCanonicalRoot(leaves) {
|
|
108
|
+
const placeholder = placeholderHash();
|
|
109
|
+
if (leaves.length === 0) {
|
|
110
|
+
return placeholder;
|
|
111
|
+
}
|
|
112
|
+
const prepared = await prepareLeaves(leaves.map(normalizeLeaf));
|
|
113
|
+
return buildJmtRoot(placeholder, prepared);
|
|
114
|
+
}
|
|
115
|
+
async function verifyCanonicalRootLink(appHashHex, canonicalRootHex, proofBytes) {
|
|
116
|
+
if (proofBytes.length === 0) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const canonicalProof = decodeProof(proofBytes[proofBytes.length - 1]);
|
|
120
|
+
if (!canonicalProof.exist) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
await verifyExistence(canonicalProof.exist, webcatSpec, fromHex(appHashHex), utf8Encoder.encode("canonical"), fromHex(canonicalRootHex));
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
53
126
|
export async function verifyWebcatProof(data) {
|
|
54
127
|
try {
|
|
55
|
-
const
|
|
56
|
-
|
|
128
|
+
const normalizedLeaves = data.leaves.map(normalizeLeaf);
|
|
129
|
+
const reconstructedRoot = await reconstructCanonicalRoot(normalizedLeaves);
|
|
130
|
+
if (!bytesEqual(reconstructedRoot, fromHex(data.proof.canonical_root_hash))) {
|
|
57
131
|
return false;
|
|
58
132
|
}
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
const canonicalRoot = fromHex(data.proof.canonical_root_hash);
|
|
62
|
-
const appHash = fromHex(data.proof.app_hash);
|
|
63
|
-
const elementKey = utf8Encoder.encode(stripCanonicalPrefix(representative_key));
|
|
64
|
-
const elementValue = collectLeafValue(data, representative_key);
|
|
65
|
-
if (!elementProof.exist || !canonicalProof.exist) {
|
|
133
|
+
const canonicalLinkValid = await verifyCanonicalRootLink(data.proof.app_hash, data.proof.canonical_root_hash, data.proof.merkle_proof.proof_bytes);
|
|
134
|
+
if (!canonicalLinkValid) {
|
|
66
135
|
return false;
|
|
67
136
|
}
|
|
68
|
-
|
|
69
|
-
const canonicalKey = utf8Encoder.encode("canonical");
|
|
70
|
-
await verifyExistence(canonicalProof.exist, webcatSpec, appHash, canonicalKey, canonicalRoot);
|
|
71
|
-
return true;
|
|
137
|
+
return normalizedLeaves;
|
|
72
138
|
}
|
|
73
139
|
catch {
|
|
74
140
|
return false;
|
package/dist/webcat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webcat.js","sourceRoot":"","sources":["../src/webcat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,MAAM,EACN,QAAQ,GAET,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"webcat.js","sourceRoot":"","sources":["../src/webcat.ts"],"names":[],"mappings":"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"}
|