@forestrie/receipt-verify 0.5.1 → 0.6.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.
- package/dist/find-grant-leaf.d.ts +37 -0
- package/dist/find-grant-leaf.d.ts.map +1 -0
- package/dist/find-grant-leaf.js +39 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/package.json +3 -3
- package/src/find-grant-leaf.ts +46 -0
- package/src/index.ts +8 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline grant-leaf lookup (FOR-344): locate a grant's sequenced leaf in a
|
|
3
|
+
* local massif blob using only the grant statement and the massif `.log`.
|
|
4
|
+
*
|
|
5
|
+
* The sequencer commits a grant to the log under its grant commitment hash
|
|
6
|
+
* (`grantCommitmentHashFromGrant` — the ContentHash enqueued in
|
|
7
|
+
* canopy-api `grant-sequencing.ts`), and the v2 urkle index region records that
|
|
8
|
+
* hash in each leaf's value column keyed by the leaf's 8-byte idtimestamp. So a
|
|
9
|
+
* client holding the owner-log massif can recover BOTH halves of the permanent
|
|
10
|
+
* entry id (`idtimestamp_be8 || mmrIndex_be8`) with no operator round-trip —
|
|
11
|
+
* the derivation that lets `forestrie complete-grant` build the completed grant
|
|
12
|
+
* header offline (grants are derivable from log data, not operator-issued).
|
|
13
|
+
*
|
|
14
|
+
* Pure over bytes; no network, no signing key. Browser-safe (ADR-0048).
|
|
15
|
+
*
|
|
16
|
+
* The lookup is a linear scan of the leaf-table value column. That is optimal
|
|
17
|
+
* here: recovering the entry id needs the leaf's *position* (ordinal → mmrIndex
|
|
18
|
+
* + idtimestamp key), and no content-hash→position index exists in the blob.
|
|
19
|
+
* The index region's bloom filter 0 IS keyed on the content hash, but a bloom
|
|
20
|
+
* only answers membership (maybe/definitely-not), never position — so it could
|
|
21
|
+
* at best short-circuit the not-present case, not the recovery; the positional
|
|
22
|
+
* structure (the urkle trie) is keyed by idtimestamp, which is exactly what we
|
|
23
|
+
* are recovering. Building a value→position map would itself be an O(n) scan.
|
|
24
|
+
*/
|
|
25
|
+
import { type LocatedLeaf } from "@forestrie/merklelog";
|
|
26
|
+
import type { Grant } from "@forestrie/encoding";
|
|
27
|
+
export type { LocatedLeaf };
|
|
28
|
+
/**
|
|
29
|
+
* Find the grant's leaf in `massifBytes` and return its `mmrIndex` and the
|
|
30
|
+
* 8-byte idtimestamp key, or `null` when the grant's commitment hash is not
|
|
31
|
+
* present in this massif's index region (searched, not found).
|
|
32
|
+
*
|
|
33
|
+
* Throws `MissingIndexError` (from `@forestrie/merklelog`) when the blob has no
|
|
34
|
+
* populated index region at all — distinguishable from a not-found `null`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function findGrantLeafInMassif(massifBytes: Uint8Array, grant: Grant): Promise<LocatedLeaf | null>;
|
|
37
|
+
//# sourceMappingURL=find-grant-leaf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-grant-leaf.d.ts","sourceRoot":"","sources":["../src/find-grant-leaf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,UAAU,EACvB,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAI7B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline grant-leaf lookup (FOR-344): locate a grant's sequenced leaf in a
|
|
3
|
+
* local massif blob using only the grant statement and the massif `.log`.
|
|
4
|
+
*
|
|
5
|
+
* The sequencer commits a grant to the log under its grant commitment hash
|
|
6
|
+
* (`grantCommitmentHashFromGrant` — the ContentHash enqueued in
|
|
7
|
+
* canopy-api `grant-sequencing.ts`), and the v2 urkle index region records that
|
|
8
|
+
* hash in each leaf's value column keyed by the leaf's 8-byte idtimestamp. So a
|
|
9
|
+
* client holding the owner-log massif can recover BOTH halves of the permanent
|
|
10
|
+
* entry id (`idtimestamp_be8 || mmrIndex_be8`) with no operator round-trip —
|
|
11
|
+
* the derivation that lets `forestrie complete-grant` build the completed grant
|
|
12
|
+
* header offline (grants are derivable from log data, not operator-issued).
|
|
13
|
+
*
|
|
14
|
+
* Pure over bytes; no network, no signing key. Browser-safe (ADR-0048).
|
|
15
|
+
*
|
|
16
|
+
* The lookup is a linear scan of the leaf-table value column. That is optimal
|
|
17
|
+
* here: recovering the entry id needs the leaf's *position* (ordinal → mmrIndex
|
|
18
|
+
* + idtimestamp key), and no content-hash→position index exists in the blob.
|
|
19
|
+
* The index region's bloom filter 0 IS keyed on the content hash, but a bloom
|
|
20
|
+
* only answers membership (maybe/definitely-not), never position — so it could
|
|
21
|
+
* at best short-circuit the not-present case, not the recovery; the positional
|
|
22
|
+
* structure (the urkle trie) is keyed by idtimestamp, which is exactly what we
|
|
23
|
+
* are recovering. Building a value→position map would itself be an O(n) scan.
|
|
24
|
+
*/
|
|
25
|
+
import { openMassifLeafIndex } from "@forestrie/merklelog";
|
|
26
|
+
import { grantCommitmentHashFromGrant } from "./grant-commitment.js";
|
|
27
|
+
/**
|
|
28
|
+
* Find the grant's leaf in `massifBytes` and return its `mmrIndex` and the
|
|
29
|
+
* 8-byte idtimestamp key, or `null` when the grant's commitment hash is not
|
|
30
|
+
* present in this massif's index region (searched, not found).
|
|
31
|
+
*
|
|
32
|
+
* Throws `MissingIndexError` (from `@forestrie/merklelog`) when the blob has no
|
|
33
|
+
* populated index region at all — distinguishable from a not-found `null`.
|
|
34
|
+
*/
|
|
35
|
+
export async function findGrantLeafInMassif(massifBytes, grant) {
|
|
36
|
+
const inner = await grantCommitmentHashFromGrant(grant);
|
|
37
|
+
const index = openMassifLeafIndex(massifBytes);
|
|
38
|
+
return index.findLeafByContentHash(inner);
|
|
39
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,4 +18,11 @@ export { decodeGrantPayload, decodeGrantResponse } from "./grant-codec.js";
|
|
|
18
18
|
export { HEADER_RECEIPT, attachReceiptAndIdtimestampToTransparentStatement, } from "./attach-transparent-statement-receipt.js";
|
|
19
19
|
export { decodeEntryIdHex, entryIdHexToIdtimestampBe8 } from "./entry-id.js";
|
|
20
20
|
export type { DecodedEntryId } from "./entry-id.js";
|
|
21
|
+
/** Grant commitment hash (ContentHash) — the value the sequencer commits. */
|
|
22
|
+
export { grantCommitmentHashFromGrant } from "./grant-commitment.js";
|
|
23
|
+
/** Offline grant-leaf lookup from a local massif blob (FOR-344). */
|
|
24
|
+
export { findGrantLeafInMassif } from "./find-grant-leaf.js";
|
|
25
|
+
export type { LocatedLeaf } from "./find-grant-leaf.js";
|
|
26
|
+
/** Re-exported so callers of findGrantLeafInMassif can catch it (FOR-344). */
|
|
27
|
+
export { MissingIndexError } from "@forestrie/merklelog";
|
|
21
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,oFAAoF;AACpF,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AACpC;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,0EAA0E;AAC1E,OAAO,EACL,cAAc,EACd,iDAAiD,GAClD,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC7E,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,oFAAoF;AACpF,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,YAAY,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AACpC;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,0EAA0E;AAC1E,OAAO,EACL,cAAc,EACd,iDAAiD,GAClD,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC7E,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,6EAA6E;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACrE,oEAAoE;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,8EAA8E;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,3 +12,9 @@ export { decodeGrantPayload, decodeGrantResponse } from "./grant-codec.js";
|
|
|
12
12
|
/** Deterministic receipt construction (plan-2607-12 Phase 2, FOR-353). */
|
|
13
13
|
export { HEADER_RECEIPT, attachReceiptAndIdtimestampToTransparentStatement, } from "./attach-transparent-statement-receipt.js";
|
|
14
14
|
export { decodeEntryIdHex, entryIdHexToIdtimestampBe8 } from "./entry-id.js";
|
|
15
|
+
/** Grant commitment hash (ContentHash) — the value the sequencer commits. */
|
|
16
|
+
export { grantCommitmentHashFromGrant } from "./grant-commitment.js";
|
|
17
|
+
/** Offline grant-leaf lookup from a local massif blob (FOR-344). */
|
|
18
|
+
export { findGrantLeafInMassif } from "./find-grant-leaf.js";
|
|
19
|
+
/** Re-exported so callers of findGrantLeafInMassif can catch it (FOR-344). */
|
|
20
|
+
export { MissingIndexError } from "@forestrie/merklelog";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forestrie/receipt-verify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Offline SCITT grant receipt verification (ADR-0045)",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@noble/hashes": "^1.7.1",
|
|
31
|
-
"@forestrie/
|
|
32
|
-
"@forestrie/
|
|
31
|
+
"@forestrie/encoding": "0.3.0",
|
|
32
|
+
"@forestrie/merklelog": "0.1.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"esbuild": "^0.24.0",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline grant-leaf lookup (FOR-344): locate a grant's sequenced leaf in a
|
|
3
|
+
* local massif blob using only the grant statement and the massif `.log`.
|
|
4
|
+
*
|
|
5
|
+
* The sequencer commits a grant to the log under its grant commitment hash
|
|
6
|
+
* (`grantCommitmentHashFromGrant` — the ContentHash enqueued in
|
|
7
|
+
* canopy-api `grant-sequencing.ts`), and the v2 urkle index region records that
|
|
8
|
+
* hash in each leaf's value column keyed by the leaf's 8-byte idtimestamp. So a
|
|
9
|
+
* client holding the owner-log massif can recover BOTH halves of the permanent
|
|
10
|
+
* entry id (`idtimestamp_be8 || mmrIndex_be8`) with no operator round-trip —
|
|
11
|
+
* the derivation that lets `forestrie complete-grant` build the completed grant
|
|
12
|
+
* header offline (grants are derivable from log data, not operator-issued).
|
|
13
|
+
*
|
|
14
|
+
* Pure over bytes; no network, no signing key. Browser-safe (ADR-0048).
|
|
15
|
+
*
|
|
16
|
+
* The lookup is a linear scan of the leaf-table value column. That is optimal
|
|
17
|
+
* here: recovering the entry id needs the leaf's *position* (ordinal → mmrIndex
|
|
18
|
+
* + idtimestamp key), and no content-hash→position index exists in the blob.
|
|
19
|
+
* The index region's bloom filter 0 IS keyed on the content hash, but a bloom
|
|
20
|
+
* only answers membership (maybe/definitely-not), never position — so it could
|
|
21
|
+
* at best short-circuit the not-present case, not the recovery; the positional
|
|
22
|
+
* structure (the urkle trie) is keyed by idtimestamp, which is exactly what we
|
|
23
|
+
* are recovering. Building a value→position map would itself be an O(n) scan.
|
|
24
|
+
*/
|
|
25
|
+
import { openMassifLeafIndex, type LocatedLeaf } from "@forestrie/merklelog";
|
|
26
|
+
import type { Grant } from "@forestrie/encoding";
|
|
27
|
+
import { grantCommitmentHashFromGrant } from "./grant-commitment.js";
|
|
28
|
+
|
|
29
|
+
export type { LocatedLeaf };
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Find the grant's leaf in `massifBytes` and return its `mmrIndex` and the
|
|
33
|
+
* 8-byte idtimestamp key, or `null` when the grant's commitment hash is not
|
|
34
|
+
* present in this massif's index region (searched, not found).
|
|
35
|
+
*
|
|
36
|
+
* Throws `MissingIndexError` (from `@forestrie/merklelog`) when the blob has no
|
|
37
|
+
* populated index region at all — distinguishable from a not-found `null`.
|
|
38
|
+
*/
|
|
39
|
+
export async function findGrantLeafInMassif(
|
|
40
|
+
massifBytes: Uint8Array,
|
|
41
|
+
grant: Grant,
|
|
42
|
+
): Promise<LocatedLeaf | null> {
|
|
43
|
+
const inner = await grantCommitmentHashFromGrant(grant);
|
|
44
|
+
const index = openMassifLeafIndex(massifBytes);
|
|
45
|
+
return index.findLeafByContentHash(inner);
|
|
46
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -35,3 +35,11 @@ export {
|
|
|
35
35
|
} from "./attach-transparent-statement-receipt.js";
|
|
36
36
|
export { decodeEntryIdHex, entryIdHexToIdtimestampBe8 } from "./entry-id.js";
|
|
37
37
|
export type { DecodedEntryId } from "./entry-id.js";
|
|
38
|
+
|
|
39
|
+
/** Grant commitment hash (ContentHash) — the value the sequencer commits. */
|
|
40
|
+
export { grantCommitmentHashFromGrant } from "./grant-commitment.js";
|
|
41
|
+
/** Offline grant-leaf lookup from a local massif blob (FOR-344). */
|
|
42
|
+
export { findGrantLeafInMassif } from "./find-grant-leaf.js";
|
|
43
|
+
export type { LocatedLeaf } from "./find-grant-leaf.js";
|
|
44
|
+
/** Re-exported so callers of findGrantLeafInMassif can catch it (FOR-344). */
|
|
45
|
+
export { MissingIndexError } from "@forestrie/merklelog";
|