Skip to content

Commit 33ad612

Browse files
committed
Build cross-chain state proof verifier utility
1 parent d9bf40f commit 33ad612

10 files changed

Lines changed: 1291 additions & 2 deletions

File tree

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,43 @@ All fields are validated locally and strictly: private key format/length, `chain
144144

145145
`OfflineSigner` guarantees that the **signing step itself** performs no network I/O — that guarantee is enforced in code and covered by tests. It **cannot** guarantee the security of anything around that step: the operating system on the air-gapped machine, the removable media used to move data across the gap, how or where the private key is generated and stored, or the physical transfer process. Those remain entirely your responsibility. Treat the offline machine as if it will eventually be compromised, and design your key-management practices accordingly.
146146

147+
## 🌉 Cross-Chain State Proof Verifier
148+
149+
`whitechain-sdk/crypto` also exposes a local verifier for Ethereum [EIP-1186](https://eips.ethereum.org/EIPS/eip-1186) account and storage proofs — the Merkle Patricia Trie proofs a cross-chain bridge uses to prove "this account/storage slot had this value" against a specific chain state, without trusting the node that served the data.
150+
151+
**Verified against a `stateRoot`, never a block hash.** A block hash identifies a block; it is not itself a trie root. Callers must supply the block's trusted `stateRoot` explicitly (e.g. from a header they've already verified elsewhere) — this module never fetches a block header and has no parameter slot for a block hash in its place.
152+
153+
**Zero network dependencies, by construction, same as `OfflineSigner`:** verification runs entirely over the proof data you already have in hand (typically the result of an `eth_getProof` call made elsewhere). There is no RPC, HTTP, provider, transport, walletClient, or publicClient involved — never `fetch`, never a viem client action. This is enforced in code and covered by the same style of static + runtime network-stubbing tests as `OfflineSigner`.
154+
155+
```ts
156+
import { verifyEIP1186Proof, isValidStateProof } from 'whitechain-sdk/crypto'
157+
158+
// `proof` is the (unmodified) result of an `eth_getProof` JSON-RPC call —
159+
// fetched by your own RPC client, wherever that lives; this function never
160+
// makes that call itself.
161+
const proof = await publicClient.request({
162+
method: 'eth_getProof',
163+
params: [address, [storageSlot], blockNumber],
164+
})
165+
166+
// `stateRoot` must come from a source you trust independently — e.g. a
167+
// block header you've already validated (its `stateRoot` field), not from
168+
// the same untrusted RPC response you're trying to verify.
169+
const result = verifyEIP1186Proof(trustedStateRoot, proof)
170+
171+
if (result.valid) {
172+
// result.account and result.storageProofs[i].result each carry
173+
// `{ valid: true, kind: 'inclusion' | 'exclusion' }` — an exclusion
174+
// result proves the account/slot is *absent*, which is just as
175+
// meaningful to a bridge as a proven value.
176+
}
177+
178+
// Or, if you only need a pass/fail:
179+
const ok = isValidStateProof(trustedStateRoot, proof)
180+
```
181+
182+
`verifyAccountProof`/`verifyStorageProof` are also exported individually for verifying just one half of a proof (e.g. an account proof with no storage slots requested). All four functions return a structured result rather than a plain boolean by default — `{ valid: false, reason }` tells you *why* a proof failed (hash mismatch, value mismatch, malformed encoding, oversized input) rather than collapsing everything to `false`.
183+
147184
## 🔌 Plugin System
148185

149186
The SDK ships a first-class plugin architecture so community developers can extend the `WhitechainSDK` instance with custom namespaces — NFT marketplace helpers, lending calculators, analytics modules — without forking the core SDK or adding bloat to the core bundle.

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@
8282
"@vitest/coverage-v8": "^1.6.1",
8383
"typedoc": "^0.28.20",
8484
"typescript": "^5.4.0",
85-
"ws": "^8.16.0",
86-
"vitest": "^1.3.1"
8785
"vitest": "^1.3.1",
8886
"ws": "^8.16.0"
8987
}

0 commit comments

Comments
 (0)