@mikeargento/bitgraph-verify 1.1.1 → 1.1.2

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.
@@ -8,21 +8,22 @@ import type { BitGraphProof } from "./types.js";
8
8
  export declare function computeProofHash(proof: BitGraphProof | Record<string, unknown>): string;
9
9
  /**
10
10
  * Compute the CHAIN hash of a BitGraph proof: SHA-256 over the canonicalized
11
- * whole proof object, with the ledger-added `proofHash` field removed.
11
+ * whole proof object, with the ledger/service-added fields removed.
12
12
  *
13
13
  * This is the value the enclave writes into the NEXT proof's
14
14
  * `commit.prevB64` (and into `epochLink.prevProofHashB64` at an epoch
15
15
  * boundary): the enclave hashes the entire assembled proof, before the ledger
16
- * appends its convenience `proofHash` field. To link a chain, match a proof's
17
- * `commit.prevB64` against `computeChainHash(predecessor)`.
16
+ * or anchor service appends its convenience fields. To link a chain, match a
17
+ * proof's `commit.prevB64` against `computeChainHash(predecessor)`.
18
18
  *
19
19
  * This differs from computeProofHash, which hashes only the signed-body
20
- * subset. The chain hash covers every field (signer signature, attestation
21
- * report, slot allocation, attribution, and so on), so any change anywhere in
22
- * a proof breaks the link from its successor.
20
+ * subset. The chain hash covers every enclave-produced field (signer
21
+ * signature, attestation report, slot allocation, attribution, and so on), so
22
+ * any change anywhere in a proof breaks the link from its successor.
23
23
  *
24
- * @param proof - The full BitGraphProof object (or equivalent Record). A
25
- * top-level `proofHash` field, if present, is excluded before hashing.
24
+ * @param proof - The full BitGraphProof object (or equivalent Record). Any
25
+ * ledger/service-added field (see LEDGER_ADDED_FIELDS) is excluded before
26
+ * hashing.
26
27
  * @returns Base64-standard encoded SHA-256 hash
27
28
  */
28
29
  export declare function computeChainHash(proof: BitGraphProof | Record<string, unknown>): string;
@@ -1 +1 @@
1
- {"version":3,"file":"proof-hash.d.ts","sourceRoot":"","sources":["../src/proof-hash.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA2BvF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAavF"}
1
+ {"version":3,"file":"proof-hash.d.ts","sourceRoot":"","sources":["../src/proof-hash.ts"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA2BvF;AAsBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAavF"}
@@ -69,34 +69,54 @@ export function computeProofHash(proof) {
69
69
  const hash = sha256(bytes);
70
70
  return base64(hash);
71
71
  }
72
+ /**
73
+ * Fields that are NOT produced by the enclave. They are appended to a proof
74
+ * AFTER it is signed, by the ledger or the anchor service, purely as read-time
75
+ * convenience. The enclave computed its chain hash before any of these
76
+ * existed, so they MUST be excluded from computeChainHash — otherwise a
77
+ * successor's `commit.prevB64` (computed by the enclave over the clean proof)
78
+ * can never match.
79
+ *
80
+ * proofHash — SHA-256 of the signed-body subset; added by the ledger at
81
+ * write time (see computeProofHash above).
82
+ * ethereum — { blockNumber, blockHash }; added by the anchor service to
83
+ * anchor records after the transaction is mined. Purely
84
+ * redundant: the block hash is already in the signed
85
+ * `attribution.message` and the block number in
86
+ * `attribution.title`. Present only on Ethereum-anchor proofs.
87
+ *
88
+ * Any future ledger/service-added field must be added here as well.
89
+ */
90
+ const LEDGER_ADDED_FIELDS = ["proofHash", "ethereum"];
72
91
  /**
73
92
  * Compute the CHAIN hash of a BitGraph proof: SHA-256 over the canonicalized
74
- * whole proof object, with the ledger-added `proofHash` field removed.
93
+ * whole proof object, with the ledger/service-added fields removed.
75
94
  *
76
95
  * This is the value the enclave writes into the NEXT proof's
77
96
  * `commit.prevB64` (and into `epochLink.prevProofHashB64` at an epoch
78
97
  * boundary): the enclave hashes the entire assembled proof, before the ledger
79
- * appends its convenience `proofHash` field. To link a chain, match a proof's
80
- * `commit.prevB64` against `computeChainHash(predecessor)`.
98
+ * or anchor service appends its convenience fields. To link a chain, match a
99
+ * proof's `commit.prevB64` against `computeChainHash(predecessor)`.
81
100
  *
82
101
  * This differs from computeProofHash, which hashes only the signed-body
83
- * subset. The chain hash covers every field (signer signature, attestation
84
- * report, slot allocation, attribution, and so on), so any change anywhere in
85
- * a proof breaks the link from its successor.
102
+ * subset. The chain hash covers every enclave-produced field (signer
103
+ * signature, attestation report, slot allocation, attribution, and so on), so
104
+ * any change anywhere in a proof breaks the link from its successor.
86
105
  *
87
- * @param proof - The full BitGraphProof object (or equivalent Record). A
88
- * top-level `proofHash` field, if present, is excluded before hashing.
106
+ * @param proof - The full BitGraphProof object (or equivalent Record). Any
107
+ * ledger/service-added field (see LEDGER_ADDED_FIELDS) is excluded before
108
+ * hashing.
89
109
  * @returns Base64-standard encoded SHA-256 hash
90
110
  */
91
111
  export function computeChainHash(proof) {
92
112
  const p = proof;
93
113
  let hashable = p;
94
- if (Object.prototype.hasOwnProperty.call(p, "proofHash")) {
95
- // Shallow copy without the ledger-added field; the enclave hashed the
96
- // proof before this field existed.
114
+ if (LEDGER_ADDED_FIELDS.some((k) => Object.prototype.hasOwnProperty.call(p, k))) {
115
+ // Shallow copy without the ledger/service-added fields; the enclave hashed
116
+ // the proof before these existed.
97
117
  hashable = {};
98
118
  for (const key of Object.keys(p)) {
99
- if (key !== "proofHash")
119
+ if (!LEDGER_ADDED_FIELDS.includes(key))
100
120
  hashable[key] = p[key];
101
121
  }
102
122
  }
@@ -1 +1 @@
1
- {"version":3,"file":"proof-hash.js","sourceRoot":"","sources":["../src/proof-hash.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA8C;IAC7E,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,MAA8C,CAAC;IAChE,MAAM,GAAG,GAAG,CAAC,CAAC,WAAyG,CAAC;IAExH,MAAM,UAAU,GAA4B;QAC1C,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,YAAY,EAAE,MAAM,EAAE,YAAY;QAClC,WAAW,EAAE,GAAG,EAAE,WAAW;QAC7B,WAAW,EAAE,GAAG,EAAE,WAAW;KAC9B,CAAC;IAEF,iCAAiC;IACjC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAClB,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC;IACzC,CAAC;IAED,wCAAwC;IACxC,IAAI,GAAG,EAAE,WAAW,EAAE,CAAC;QACrB,UAAU,CAAC,iBAAiB,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC;IACxD,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,UAAsC,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA8C;IAC7E,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,QAAQ,GAA4B,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;QACzD,sEAAsE;QACtE,mCAAmC;QACnC,QAAQ,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,IAAI,GAAG,KAAK,WAAW;gBAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAoC,CAAC,CAAC;IACjE,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,8DAA8D;AAC9D,SAAS,MAAM,CAAC,IAAgB;IAC9B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"proof-hash.js","sourceRoot":"","sources":["../src/proof-hash.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA8C;IAC7E,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,MAA8C,CAAC;IAChE,MAAM,GAAG,GAAG,CAAC,CAAC,WAAyG,CAAC;IAExH,MAAM,UAAU,GAA4B;QAC1C,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,YAAY,EAAE,MAAM,EAAE,YAAY;QAClC,WAAW,EAAE,GAAG,EAAE,WAAW;QAC7B,WAAW,EAAE,GAAG,EAAE,WAAW;KAC9B,CAAC;IAEF,iCAAiC;IACjC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAClB,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC;IACzC,CAAC;IAED,wCAAwC;IACxC,IAAI,GAAG,EAAE,WAAW,EAAE,CAAC;QACrB,UAAU,CAAC,iBAAiB,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC;IACxD,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,CAAC,UAAsC,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,mBAAmB,GAAsB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA8C;IAC7E,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,QAAQ,GAA4B,CAAC,CAAC;IAC1C,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,2EAA2E;QAC3E,kCAAkC;QAClC,QAAQ,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAoC,CAAC,CAAC;IACjE,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,8DAA8D;AAC9D,SAAS,MAAM,CAAC,IAAgB;IAC9B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikeargento/bitgraph-verify",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Offline verification of BitGraph proofs. Permissionless by design.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/proof-hash.ts CHANGED
@@ -78,34 +78,55 @@ export function computeProofHash(proof: BitGraphProof | Record<string, unknown>)
78
78
  return base64(hash);
79
79
  }
80
80
 
81
+ /**
82
+ * Fields that are NOT produced by the enclave. They are appended to a proof
83
+ * AFTER it is signed, by the ledger or the anchor service, purely as read-time
84
+ * convenience. The enclave computed its chain hash before any of these
85
+ * existed, so they MUST be excluded from computeChainHash — otherwise a
86
+ * successor's `commit.prevB64` (computed by the enclave over the clean proof)
87
+ * can never match.
88
+ *
89
+ * proofHash — SHA-256 of the signed-body subset; added by the ledger at
90
+ * write time (see computeProofHash above).
91
+ * ethereum — { blockNumber, blockHash }; added by the anchor service to
92
+ * anchor records after the transaction is mined. Purely
93
+ * redundant: the block hash is already in the signed
94
+ * `attribution.message` and the block number in
95
+ * `attribution.title`. Present only on Ethereum-anchor proofs.
96
+ *
97
+ * Any future ledger/service-added field must be added here as well.
98
+ */
99
+ const LEDGER_ADDED_FIELDS: readonly string[] = ["proofHash", "ethereum"];
100
+
81
101
  /**
82
102
  * Compute the CHAIN hash of a BitGraph proof: SHA-256 over the canonicalized
83
- * whole proof object, with the ledger-added `proofHash` field removed.
103
+ * whole proof object, with the ledger/service-added fields removed.
84
104
  *
85
105
  * This is the value the enclave writes into the NEXT proof's
86
106
  * `commit.prevB64` (and into `epochLink.prevProofHashB64` at an epoch
87
107
  * boundary): the enclave hashes the entire assembled proof, before the ledger
88
- * appends its convenience `proofHash` field. To link a chain, match a proof's
89
- * `commit.prevB64` against `computeChainHash(predecessor)`.
108
+ * or anchor service appends its convenience fields. To link a chain, match a
109
+ * proof's `commit.prevB64` against `computeChainHash(predecessor)`.
90
110
  *
91
111
  * This differs from computeProofHash, which hashes only the signed-body
92
- * subset. The chain hash covers every field (signer signature, attestation
93
- * report, slot allocation, attribution, and so on), so any change anywhere in
94
- * a proof breaks the link from its successor.
112
+ * subset. The chain hash covers every enclave-produced field (signer
113
+ * signature, attestation report, slot allocation, attribution, and so on), so
114
+ * any change anywhere in a proof breaks the link from its successor.
95
115
  *
96
- * @param proof - The full BitGraphProof object (or equivalent Record). A
97
- * top-level `proofHash` field, if present, is excluded before hashing.
116
+ * @param proof - The full BitGraphProof object (or equivalent Record). Any
117
+ * ledger/service-added field (see LEDGER_ADDED_FIELDS) is excluded before
118
+ * hashing.
98
119
  * @returns Base64-standard encoded SHA-256 hash
99
120
  */
100
121
  export function computeChainHash(proof: BitGraphProof | Record<string, unknown>): string {
101
122
  const p = proof as Record<string, unknown>;
102
123
  let hashable: Record<string, unknown> = p;
103
- if (Object.prototype.hasOwnProperty.call(p, "proofHash")) {
104
- // Shallow copy without the ledger-added field; the enclave hashed the
105
- // proof before this field existed.
124
+ if (LEDGER_ADDED_FIELDS.some((k) => Object.prototype.hasOwnProperty.call(p, k))) {
125
+ // Shallow copy without the ledger/service-added fields; the enclave hashed
126
+ // the proof before these existed.
106
127
  hashable = {};
107
128
  for (const key of Object.keys(p)) {
108
- if (key !== "proofHash") hashable[key] = p[key];
129
+ if (!LEDGER_ADDED_FIELDS.includes(key)) hashable[key] = p[key];
109
130
  }
110
131
  }
111
132
  const bytes = canonicalize(hashable as unknown as BitGraphProof);