@secondlayer/verify 0.1.0 → 0.3.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/README.md +21 -6
- package/dist/index.d.ts +200 -22
- package/dist/index.js +375 -27
- package/dist/index.js.map +10 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,7 +6,15 @@ Check a Stacks block yourself instead of trusting the API or node that served it
|
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
checkpoint -> Bitcoin headers (proof of work) -> burn block -> signer set (MARF proof)
|
|
9
|
-
-> header signatures (70% of signer weight) ->
|
|
9
|
+
-> header signatures (70% of signer weight) -> transactions (tx merkle root)
|
|
10
|
+
-> state witness (state root) -> state diff
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Blocks below the checkpoint take a shorter chain. The checkpoint's header commits to every ancestor by hash, so no signatures are needed:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
checkpoint -> block id at that height (parent links, or one MARF proof) -> header hashes to the id
|
|
17
|
+
-> transactions (tx merkle root) -> state witness (state root) -> state diff
|
|
10
18
|
```
|
|
11
19
|
|
|
12
20
|
Every byte comes from a source you don't have to trust. A lying source can make a link fail, never pass. Powers `secondlayer verify block` in [`@secondlayer/cli`](https://www.npmjs.com/package/@secondlayer/cli).
|
|
@@ -43,9 +51,11 @@ const source = {
|
|
|
43
51
|
};
|
|
44
52
|
```
|
|
45
53
|
|
|
54
|
+
Heights below the checkpoint need no extra options: `verifyBlock(150_000, { source })` derives the direction. Within 16 blocks of a trusted block the verifier follows `parent_block_id` links. Farther down it asks the source for one MARF proof of `__MARF_BLOCK_HEIGHT_TO_HASH::<height>` at the checkpoint: each block writes its parent's id there, so the proof names the ancestor and is checked against the checkpoint's state root. Pre-Nakamoto (2.x) blocks need a source with `getEpoch2Header`, which both sources here implement.
|
|
55
|
+
|
|
46
56
|
`verifyBlock` never throws for bad source data: it returns `ok: false` with `failures`, the first entry being the first broken link. Use `BlockVerifier` to verify many blocks from one checkpoint and reuse the synced Bitcoin headers and proven signer sets.
|
|
47
57
|
|
|
48
|
-
By default only proofs are read, and proofs are free.
|
|
58
|
+
By default only proofs are read, and proofs are free. That includes the block's state writes (`/v1/proofs/writes/{height}`), which name every written leaf of the diff; `result.writes` holds them and each named `diff.writes` entry carries its proven `value`. A source with no writes for the block (the API answers 404 until its node delivers `state_writes` for that height) leaves the diff proven but unnamed, with a note; it is never a failure. Pass `rows: true` to also check the indexed `vm_events` rows, which bill as Index rows on the Secondlayer API.
|
|
49
59
|
|
|
50
60
|
```ts
|
|
51
61
|
await verifyBlock(9_137_005, { source, rows: true });
|
|
@@ -59,16 +69,21 @@ await verifyBlock(9_137_005, { source, rows: true });
|
|
|
59
69
|
| It was elected by a Bitcoin block | consensus hash preimage, burn header in the synced chain |
|
|
60
70
|
| The Bitcoin chain | every header from the checkpoint: proof of work, retargets, median time |
|
|
61
71
|
| The cycle's signers signed it | signer set proven by MARF against an earlier signed block, then 70% of weight |
|
|
72
|
+
| Its transactions | every transaction parses and the txids hash to the header's tx merkle root (`result.transactions`) |
|
|
62
73
|
| Its state | the witness recomputes the header's state root |
|
|
63
|
-
| Every key it wrote |
|
|
74
|
+
| Every key it wrote | a source with `state_writes` for the block: each written leaf is named, nothing hidden |
|
|
64
75
|
| Indexed rows | `rows: true`: each `vm_events` row matches a leaf the block wrote |
|
|
76
|
+
| Below the checkpoint: it is the checkpoint chain's block at that height | parent links or a MARF proof from the checkpoint's state root, then the header (Nakamoto or 2.x) hashes to that id |
|
|
65
77
|
|
|
66
78
|
## What it trusts, and what it doesn't cover
|
|
67
79
|
|
|
68
80
|
- **The checkpoint.** `MAINNET_CHECKPOINT` (Stacks block 8,956,304, cycle 143 signers, Bitcoin block 967,680) is trusted as-is. Pass `checkpoint` to use your own.
|
|
69
|
-
- **Bitcoin heights.**
|
|
70
|
-
- **
|
|
71
|
-
- **
|
|
81
|
+
- **Bitcoin heights.** At or above the checkpoint, a block's burn block must be at or above the checkpoint's Bitcoin block. Below the checkpoint the burn block is checked only when it is (with the baked checkpoint it never is); the hash chain pins those blocks instead. Headers are checked for valid work, not compared against a competing chain, and reorgs past the synced tip are not followed.
|
|
82
|
+
- **MARF proofs of `__MARF_*` keys.** A node's `/v2/clarity/marf` answers only keys with a stored value string, and these have none. The API's `/v1/proofs/marf` falls back to its proof sidecar for them; with `NodeRpcProofSource` alone, blocks more than 16 below a trusted block fail `ancestry` as `unavailable`.
|
|
83
|
+
- **Epoch 2.x consensus hashes.** A 2.x header commits to its parent's block hash, not its id. The id always comes from a trusted descendant (its header, or a MARF proof), and the source's consensus hash must hash with the header to it. State proofs for 2.x heights are against the anchored block's root, which covers the microblocks it confirms.
|
|
84
|
+
- **Names need `state_writes`.** Without them every write is still proven, but unnamed; `notes` says so.
|
|
85
|
+
- **Transactions need the block body.** Epoch 2.x blocks, and a source that serves the header only, skip the `txs` link with a note. The root binds each transaction's bytes (sender, type, call target, arguments), not which transaction made which write, nor whether it succeeded.
|
|
86
|
+
- **Not covered:** print events and transaction results (Stacks headers don't commit to them).
|
|
72
87
|
|
|
73
88
|
## Docs
|
|
74
89
|
|
package/dist/index.d.ts
CHANGED
|
@@ -30,8 +30,43 @@ declare function parseNakamotoHeader(raw: Bytes): NakamotoHeader;
|
|
|
30
30
|
* except the signer signatures. Also the header's block_hash.
|
|
31
31
|
*/
|
|
32
32
|
declare const signerSignatureHash: (h: NakamotoHeader) => Bytes;
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Epoch 2.x anchored block header. It commits to the parent's block hash, not
|
|
35
|
+
* its index block hash, and carries no consensus hash: the source supplies
|
|
36
|
+
* that, and `blockId` binds it to an id proven elsewhere.
|
|
37
|
+
*/
|
|
38
|
+
interface Epoch2Header {
|
|
39
|
+
version: number;
|
|
40
|
+
/** total_work.burn: burn spent on the fork so far. */
|
|
41
|
+
burnSpent: bigint;
|
|
42
|
+
/** total_work.work: the Stacks chain length (one per anchored block). */
|
|
43
|
+
chainLength: bigint;
|
|
44
|
+
vrfProof: Bytes;
|
|
45
|
+
parentBlockHash: Bytes;
|
|
46
|
+
parentMicroblock: Bytes;
|
|
47
|
+
parentMicroblockSequence: number;
|
|
48
|
+
txMerkleRoot: Bytes;
|
|
49
|
+
/** Covers the block and the parent microblock stream it confirms. */
|
|
50
|
+
stateIndexRoot: Bytes;
|
|
51
|
+
microblockPubkeyHash: Bytes;
|
|
52
|
+
/** sha512/256 of the serialized header. */
|
|
53
|
+
blockHash: Bytes;
|
|
54
|
+
consensusHash: Bytes;
|
|
55
|
+
}
|
|
56
|
+
type StacksHeader = NakamotoHeader | Epoch2Header;
|
|
57
|
+
/**
|
|
58
|
+
* Parse the epoch 2.x StacksBlockHeader at the start of `raw` (a header from
|
|
59
|
+
* `/v2/headers`, or block bytes from `/v2/blocks/<id>`), with the 20-byte
|
|
60
|
+
* consensus hash of the sortition that elected it.
|
|
61
|
+
*/
|
|
62
|
+
declare function parseEpoch2Header(raw: Bytes, consensusHash: Bytes): Epoch2Header;
|
|
63
|
+
declare const isEpoch2Header: (h: StacksHeader) => h is Epoch2Header;
|
|
64
|
+
/**
|
|
65
|
+
* StacksBlockId (index block hash) = sha512/256(block_hash || consensus_hash).
|
|
66
|
+
* A Nakamoto block hash is its signer signature hash; a 2.x one hashes the
|
|
67
|
+
* whole header.
|
|
68
|
+
*/
|
|
69
|
+
declare const blockId2: (h: StacksHeader) => Bytes;
|
|
35
70
|
/** TrieHash::from_key: sha512/256(utf8(key)). */
|
|
36
71
|
declare const marfPath: (key: string) => Bytes;
|
|
37
72
|
/** MARFValue::from_value: sha512/256(utf8(value)) padded to 40 bytes. */
|
|
@@ -59,7 +94,7 @@ interface MarfProofInput {
|
|
|
59
94
|
* vouched for by header bytes (a bare root->id map would let a forged
|
|
60
95
|
* ancestor trie through).
|
|
61
96
|
*/
|
|
62
|
-
headers:
|
|
97
|
+
headers: StacksHeader[];
|
|
63
98
|
}
|
|
64
99
|
/**
|
|
65
100
|
* TrieMerkleProof::verify. True iff `value` is stored at `path` in the MARF
|
|
@@ -257,8 +292,8 @@ interface VerifyCheckpoint {
|
|
|
257
292
|
/**
|
|
258
293
|
* Mainnet: Stacks block 8,956,304 (`3914ea5f…74bb`) holding the cycle 143
|
|
259
294
|
* signer set (29 signers, weight 4000), and Bitcoin block 967,680 (a
|
|
260
|
-
* retarget-period start inside cycle 143).
|
|
261
|
-
* height
|
|
295
|
+
* retarget-period start inside cycle 143). Later blocks verify forward
|
|
296
|
+
* (burn height 967,680 or later); earlier ones by hash chain from 8,956,304.
|
|
262
297
|
*/
|
|
263
298
|
declare const MAINNET_CHECKPOINT: VerifyCheckpoint;
|
|
264
299
|
/** Sortition preimage behind a consensus hash. */
|
|
@@ -297,17 +332,36 @@ interface VmEventRow {
|
|
|
297
332
|
raw_key?: string | null;
|
|
298
333
|
raw_value?: string | null;
|
|
299
334
|
}
|
|
335
|
+
/** An epoch 2.x header and the consensus hash its index block hash commits to. */
|
|
336
|
+
interface Epoch2HeaderResponse {
|
|
337
|
+
/** Consensus-serialized StacksBlockHeader. */
|
|
338
|
+
header: Bytes;
|
|
339
|
+
consensusHash: Bytes;
|
|
340
|
+
}
|
|
300
341
|
interface ProofSource {
|
|
301
342
|
/** Raw Nakamoto block bytes (header first), by block id or height. */
|
|
302
343
|
getBlock(ref: string | number): Promise<Bytes>;
|
|
303
|
-
/**
|
|
344
|
+
/**
|
|
345
|
+
* Epoch 2.x block header by index block hash: blocks below the checkpoint
|
|
346
|
+
* from before Nakamoto. Without it only Nakamoto blocks verify.
|
|
347
|
+
*/
|
|
348
|
+
getEpoch2Header?(blockId: string): Promise<Epoch2HeaderResponse>;
|
|
349
|
+
/**
|
|
350
|
+
* MARF inclusion proof for a 32-byte path at `tipId`; null when the key is
|
|
351
|
+
* absent. Blocks below the checkpoint also ask for
|
|
352
|
+
* `__MARF_BLOCK_HEIGHT_TO_HASH::<height>`, whose value is no stored string:
|
|
353
|
+
* only `proof` is read for it.
|
|
354
|
+
*/
|
|
304
355
|
getMarfProof(pathHex: string, tipId: string): Promise<MarfProofResponse | null>;
|
|
305
356
|
/** State witness (wire v3) for a block. */
|
|
306
357
|
getWitness(blockId: string): Promise<Bytes>;
|
|
307
358
|
getBurnPreimage(consensusHash: string): Promise<BurnPreimage>;
|
|
308
359
|
/** Raw 80-byte Bitcoin headers (hex or bytes) from height `from`. */
|
|
309
360
|
getBitcoinHeaders(from: number, count: number): Promise<(string | Bytes)[]>;
|
|
310
|
-
/**
|
|
361
|
+
/**
|
|
362
|
+
* Every MARF write of the block, in ordinal order; null (or empty) when
|
|
363
|
+
* the source has none for it. Names the block's diff.
|
|
364
|
+
*/
|
|
311
365
|
getStateWrites?(height: number): Promise<StateWrite[] | null>;
|
|
312
366
|
/** Indexed vm_events write rows of the block, checked against its proven diff. */
|
|
313
367
|
getVmEvents?(height: number): Promise<VmEventRow[]>;
|
|
@@ -327,14 +381,16 @@ interface SecondlayerSourceOptions {
|
|
|
327
381
|
fetch?: Fetch;
|
|
328
382
|
}
|
|
329
383
|
/**
|
|
330
|
-
* Every proof input from the Secondlayer API: `/v1/proofs/*`
|
|
331
|
-
*
|
|
332
|
-
*
|
|
384
|
+
* Every proof input from the Secondlayer API: `/v1/proofs/*` (free, rate
|
|
385
|
+
* limited) for blocks, epoch 2.x headers, MARF proofs, witnesses, burn
|
|
386
|
+
* preimages, Bitcoin headers and each block's state writes; the Index API
|
|
387
|
+
* (metered rows) for vm_events, read only when verifyBlock gets `rows: true`.
|
|
333
388
|
* Methods are own properties, so a partial source spreads over it:
|
|
334
389
|
* `{ ...new SecondlayerProofSource(o), ...new NodeRpcProofSource(n) }`.
|
|
335
390
|
*/
|
|
336
391
|
declare class SecondlayerProofSource implements ProofSource {
|
|
337
392
|
getBlock: (ref: string | number) => Promise<Bytes>;
|
|
393
|
+
getEpoch2Header: (blockId: string) => Promise<Epoch2HeaderResponse>;
|
|
338
394
|
getMarfProof: (pathHex: string, tipId: string) => Promise<MarfProofResponse | null>;
|
|
339
395
|
getWitness: (blockId: string) => Promise<Bytes>;
|
|
340
396
|
getBurnPreimage: (consensusHash: string) => Promise<BurnPreimage>;
|
|
@@ -349,11 +405,13 @@ interface NodeRpcSourceOptions {
|
|
|
349
405
|
fetch?: Fetch;
|
|
350
406
|
}
|
|
351
407
|
/**
|
|
352
|
-
* Blocks and MARF proofs straight from a Stacks node's RPC.
|
|
353
|
-
* preimages and Bitcoin headers need another source: spread
|
|
408
|
+
* Blocks, epoch 2.x headers and MARF proofs straight from a Stacks node's RPC.
|
|
409
|
+
* Witnesses, burn preimages and Bitcoin headers need another source: spread
|
|
410
|
+
* this over one.
|
|
354
411
|
*/
|
|
355
|
-
declare class NodeRpcProofSource implements Pick<ProofSource, "getBlock" | "getMarfProof"> {
|
|
412
|
+
declare class NodeRpcProofSource implements Pick<ProofSource, "getBlock" | "getEpoch2Header" | "getMarfProof"> {
|
|
356
413
|
getBlock: (ref: string | number) => Promise<Bytes>;
|
|
414
|
+
getEpoch2Header: (blockId: string) => Promise<Epoch2HeaderResponse>;
|
|
357
415
|
getMarfProof: (pathHex: string, tipId: string) => Promise<MarfProofResponse | null>;
|
|
358
416
|
constructor(opts: NodeRpcSourceOptions);
|
|
359
417
|
}
|
|
@@ -366,6 +424,8 @@ interface DiffWrite {
|
|
|
366
424
|
valueHash: string;
|
|
367
425
|
/** Transaction of the last write; null for block-level writes. */
|
|
368
426
|
txIndex?: number | null;
|
|
427
|
+
/** The stored value string (hex of a Clarity value) the leaf holds; named writes only. */
|
|
428
|
+
value?: string;
|
|
369
429
|
/** False when the source had no state_writes: the leaf may also be a carried copy. */
|
|
370
430
|
named: boolean;
|
|
371
431
|
}
|
|
@@ -432,8 +492,33 @@ interface BlockStateResult {
|
|
|
432
492
|
* `parentLeaves`, and the remaining writes come back unnamed.
|
|
433
493
|
*/
|
|
434
494
|
declare function verifyBlockState(input: BlockStateInput): Promise<BlockStateResult>;
|
|
435
|
-
|
|
436
|
-
|
|
495
|
+
interface BlockTransaction {
|
|
496
|
+
/** sha512/256 of the transaction bytes, hex. */
|
|
497
|
+
txid: string;
|
|
498
|
+
/** The consensus-serialized transaction. */
|
|
499
|
+
raw: Bytes;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* tx_merkle_root over txids: leaf = H(0x00 ‖ txid), node = H(0x01 ‖ l ‖ r),
|
|
503
|
+
* an odd level duplicates its last node, and a lone leaf is still paired with
|
|
504
|
+
* itself (one-tx blocks hash H(0x01 ‖ leaf ‖ leaf)).
|
|
505
|
+
*/
|
|
506
|
+
declare function txMerkleRoot2(txids: Bytes[]): Bytes;
|
|
507
|
+
declare class TransactionsError extends Error {
|
|
508
|
+
readonly code: "malformed" | "tx-root-mismatch";
|
|
509
|
+
constructor(code: "malformed" | "tx-root-mismatch", message: string);
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* The block's transactions, each hashed to its txid, checked against the
|
|
513
|
+
* header's tx_merkle_root. The body after `header.byteLength` is a u32 count
|
|
514
|
+
* then the transactions back to back. Null when the bytes are the header
|
|
515
|
+
* alone (a source that serves headers only): nothing to check. Throws
|
|
516
|
+
* {@link TransactionsError} on a malformed body, trailing bytes or a root
|
|
517
|
+
* mismatch.
|
|
518
|
+
*/
|
|
519
|
+
declare function blockTransactions(raw: Bytes, header: NakamotoHeader): BlockTransaction[] | null;
|
|
520
|
+
type VerifyStep = "ancestry" | "block" | "bitcoin" | "burn" | "signer-set" | "signatures" | "txs" | "witness" | "names" | "rows";
|
|
521
|
+
type VerifyFailureCode = StateFailureCode | "unavailable" | "id-mismatch" | "tx-root-mismatch" | "height-mismatch" | "invalid-header" | "preimage-mismatch" | "burn-not-in-chain" | "before-checkpoint" | "not-ancestor" | "ancestry-proof-invalid" | "anchor-not-found" | "anchor-outside-window" | "anchor-unsigned" | "set-proof-invalid" | "below-threshold" | "unknown-signer" | "duplicate-signer" | "bad-signature";
|
|
437
522
|
interface VerifyFailure {
|
|
438
523
|
step: VerifyStep;
|
|
439
524
|
code: VerifyFailureCode;
|
|
@@ -446,13 +531,37 @@ interface VerifyFailure {
|
|
|
446
531
|
path?: string;
|
|
447
532
|
ordinal?: number;
|
|
448
533
|
}
|
|
534
|
+
/** How a block below the checkpoint was tied to it. */
|
|
535
|
+
interface Ancestry {
|
|
536
|
+
/** Trusted descendant it was proven from: the checkpoint, or a block proven below it earlier. */
|
|
537
|
+
fromHeight: number;
|
|
538
|
+
fromBlockId: string;
|
|
539
|
+
/**
|
|
540
|
+
* `parents`: each header hashes to the parent id its child commits to.
|
|
541
|
+
* `marf`: one MARF proof of `__MARF_BLOCK_HEIGHT_TO_HASH::<height>` against
|
|
542
|
+
* the descendant's state root.
|
|
543
|
+
*/
|
|
544
|
+
via: "parents" | "marf";
|
|
545
|
+
}
|
|
449
546
|
interface BlockVerification {
|
|
450
|
-
/**
|
|
547
|
+
/**
|
|
548
|
+
* Every step passed. At or above the checkpoint: header, burn binding,
|
|
549
|
+
* signatures, state root, names and rows. Below it: ancestry, header,
|
|
550
|
+
* state root, names and rows (and the burn binding when Bitcoin reaches it).
|
|
551
|
+
*/
|
|
451
552
|
ok: boolean;
|
|
452
553
|
height?: number;
|
|
453
554
|
blockId?: string;
|
|
555
|
+
/** Nakamoto block hash (the header's signer sighash), hex. Absent for epoch 2.x. */
|
|
556
|
+
blockHash?: string;
|
|
557
|
+
/** The header's consensus hash, hex. */
|
|
558
|
+
consensusHash?: string;
|
|
559
|
+
/** Nakamoto header timestamp, Unix seconds. Absent for epoch 2.x. */
|
|
560
|
+
timestamp?: number;
|
|
454
561
|
/** The header's state_index_root, hex: what the witness must hash to. */
|
|
455
562
|
stateRoot?: string;
|
|
563
|
+
/** Set for blocks below the checkpoint, which need no signatures. */
|
|
564
|
+
ancestry?: Ancestry;
|
|
456
565
|
cycle?: number;
|
|
457
566
|
burnHeight?: number;
|
|
458
567
|
/** Display-order hex. */
|
|
@@ -460,7 +569,14 @@ interface BlockVerification {
|
|
|
460
569
|
signerWeight?: bigint;
|
|
461
570
|
totalWeight?: bigint;
|
|
462
571
|
threshold?: bigint;
|
|
572
|
+
/**
|
|
573
|
+
* The block's transactions, checked against the header's tx_merkle_root.
|
|
574
|
+
* Absent for epoch 2.x blocks and when the source served the header only.
|
|
575
|
+
*/
|
|
576
|
+
transactions?: BlockTransaction[];
|
|
463
577
|
diff?: ProvenDiff;
|
|
578
|
+
/** Every state_writes row the names step checked, in ordinal order. */
|
|
579
|
+
writes?: StateWrite[];
|
|
464
580
|
/** vm_events rows proven against the diff. */
|
|
465
581
|
rowsChecked?: number;
|
|
466
582
|
notes: string[];
|
|
@@ -472,9 +588,10 @@ interface VerifyOptions {
|
|
|
472
588
|
/** Defaults to MAINNET_CHECKPOINT. */
|
|
473
589
|
checkpoint?: VerifyCheckpoint;
|
|
474
590
|
/**
|
|
475
|
-
* Also
|
|
476
|
-
* source's `
|
|
477
|
-
*
|
|
591
|
+
* Also prove the block's indexed vm_events rows against its diff: reads
|
|
592
|
+
* the source's `getVmEvents`, which bill as Index rows on the Secondlayer
|
|
593
|
+
* API. Off by default. Naming the diff's writes (`getStateWrites`, free on
|
|
594
|
+
* `/v1/proofs`) is always on when the source has them.
|
|
478
595
|
*/
|
|
479
596
|
rows?: boolean;
|
|
480
597
|
}
|
|
@@ -491,18 +608,78 @@ declare class BlockVerifier {
|
|
|
491
608
|
private readonly sets;
|
|
492
609
|
/** Where each proven set was anchored: the lower bound for the next search. */
|
|
493
610
|
private readonly anchors;
|
|
611
|
+
/** Headers fetched by id, each checked to hash to it. */
|
|
494
612
|
private readonly headers;
|
|
613
|
+
/** Blocks proven on the checkpoint's chain below it, by height. */
|
|
614
|
+
private readonly below;
|
|
495
615
|
private readonly burns;
|
|
496
616
|
/** Unverified source answers by consensus hash. */
|
|
497
617
|
private readonly preimages;
|
|
618
|
+
/** Raw bytes of the last few blocks fetched, so the txs step reuses the
|
|
619
|
+
* block an ancestry walk just read. Bounded: blocks can be megabytes. */
|
|
620
|
+
private readonly raws;
|
|
498
621
|
private readonly start;
|
|
499
622
|
constructor(opts: VerifyOptions);
|
|
500
623
|
/** Verify one block by id (hex) or height. Never throws for bad source data. */
|
|
501
624
|
verify(ref: string | number): Promise<BlockVerification>;
|
|
502
625
|
private run;
|
|
503
|
-
/**
|
|
626
|
+
/** At or above the checkpoint: Bitcoin, burn binding, signer set, signatures, state. */
|
|
627
|
+
private runForward;
|
|
628
|
+
/**
|
|
629
|
+
* Below the checkpoint: prove the checkpoint chain's id at `height` (and
|
|
630
|
+
* that it is `claimed`, when the caller asked by id), then the header that
|
|
631
|
+
* hashes to it, then its state. Signatures add nothing to a header pinned
|
|
632
|
+
* by hash from a trusted descendant.
|
|
633
|
+
*/
|
|
634
|
+
private runBelow;
|
|
635
|
+
private rememberRaw;
|
|
636
|
+
/**
|
|
637
|
+
* The block's transactions against the authenticated header's
|
|
638
|
+
* tx_merkle_root: binds every txid, sender, type and call target to the
|
|
639
|
+
* signed (or hash-linked) header.
|
|
640
|
+
*/
|
|
641
|
+
private checkTransactions;
|
|
642
|
+
/**
|
|
643
|
+
* The checkpoint chain's block id at `height`, from the nearest trusted
|
|
644
|
+
* block above it: parent links when within MAX_WALK, else one MARF proof.
|
|
645
|
+
*/
|
|
646
|
+
private ancestor;
|
|
647
|
+
/** The lowest trusted block above `height`: the checkpoint or one proven below it. */
|
|
648
|
+
private nearestAbove;
|
|
649
|
+
/**
|
|
650
|
+
* Follow parent ids down from `from`: each parent header must hash to the
|
|
651
|
+
* id its child committed to. Null when a 2.x header stops the walk: it
|
|
652
|
+
* commits to its parent's block hash, not the parent's id.
|
|
653
|
+
*/
|
|
654
|
+
private walk;
|
|
655
|
+
/**
|
|
656
|
+
* Read the id at `height` from `from`'s state: block `height + 1` wrote it
|
|
657
|
+
* to `__MARF_BLOCK_HEIGHT_TO_HASH::<height>`, and the proof must recompute
|
|
658
|
+
* `from`'s state root through the header of every trie it crosses.
|
|
659
|
+
*/
|
|
660
|
+
private jump;
|
|
661
|
+
/**
|
|
662
|
+
* Below the checkpoint the hash chain already pins the block; still bind
|
|
663
|
+
* its burn block when the Bitcoin checkpoint reaches it. The burn height
|
|
664
|
+
* here is the source's hint, so a low one only skips this extra check.
|
|
665
|
+
*/
|
|
666
|
+
private bindBurnBelow;
|
|
667
|
+
/** Witness against the authenticated header's root, then the named diff and rows. */
|
|
668
|
+
private verifyState;
|
|
669
|
+
/**
|
|
670
|
+
* The block's state writes, to name its diff. Optional evidence: a source
|
|
671
|
+
* with none for the block (404, empty) or that fails leaves the diff
|
|
672
|
+
* proven but unnamed, with a note, never a failure.
|
|
673
|
+
*/
|
|
674
|
+
private stateWrites;
|
|
675
|
+
/** Header by id, from the cache or the source; it must hash to `id`. */
|
|
504
676
|
private header;
|
|
505
677
|
/**
|
|
678
|
+
* A Nakamoto block by id, or when the source has none (epoch 2.x blocks are
|
|
679
|
+
* not served as Nakamoto blocks) its epoch 2.x header.
|
|
680
|
+
*/
|
|
681
|
+
private fetchHeader;
|
|
682
|
+
/**
|
|
506
683
|
* Prove `value` at `path` in `tip`'s state, fetching the header of every
|
|
507
684
|
* ancestor trie the proof crosses.
|
|
508
685
|
*/
|
|
@@ -515,7 +692,8 @@ declare class BlockVerifier {
|
|
|
515
692
|
private parentLeaves;
|
|
516
693
|
/**
|
|
517
694
|
* A carried leaf holds the parent's value. The parent header is
|
|
518
|
-
* authenticated by hash: its id is committed in the
|
|
695
|
+
* authenticated by hash: its id is committed in the authenticated child
|
|
696
|
+
* (its header, or for 2.x its own trie).
|
|
519
697
|
*/
|
|
520
698
|
private parentHolds;
|
|
521
699
|
/** Consensus hash -> PoW-verified burn block, via the sortition preimage. */
|
|
@@ -544,4 +722,4 @@ declare class BlockVerifier {
|
|
|
544
722
|
}
|
|
545
723
|
/** One-shot: verify a block from a checkpoint (MAINNET_CHECKPOINT by default). */
|
|
546
724
|
declare const verifyBlock: (ref: string | number, opts: VerifyOptions) => Promise<BlockVerification>;
|
|
547
|
-
export { BlockDiff, BlockDiffInput, BlockStateInput, BlockStateResult, BlockVerification, BlockVerifier, BurnPreimage, Bytes, Checkpoint, ClassifiedLeaf, DiffLeaf, DiffWrite, HeaderChain, HeaderRule, HeaderValidationError, MAINNET_CHECKPOINT, MAINNET_FIRST_BURN_HEIGHT, MAINNET_PREPARE_LENGTH, MAINNET_REWARD_CYCLE_LENGTH, MarfProofInput, MarfProofResponse, NakamotoHeader, NodeRpcProofSource, NodeRpcSourceOptions, ProofSource, ProvenDiff, SIGNERS_CONTRACT, SecondlayerProofSource, SecondlayerSourceOptions, SignerCheck, SignerSet, SourceError, StateFailure, StateFailureCode, StateWitness, StateWrite, VerifyCheckpoint, VerifyFailure, VerifyFailureCode, VerifyOptions, VerifyStep, VmEventRow, WitnessLeaf, blockId2 as blockId, classifyBlockDiff, cycleStart, dataVarKey, decodeSignerSet, ftBalanceKey, hex, mapEntryKey, marfPath, marfProofAncestors, marfValue, parseNakamotoHeader, parseWitness, rewardCycle, signerSignatureHash, unhex, verifyBlock, verifyBlockState, verifyConsensusPreimage, verifyMarfProof, verifySignerSignatures };
|
|
725
|
+
export { Ancestry, BlockDiff, BlockDiffInput, BlockStateInput, BlockStateResult, BlockTransaction, BlockVerification, BlockVerifier, BurnPreimage, Bytes, Checkpoint, ClassifiedLeaf, DiffLeaf, DiffWrite, Epoch2Header, Epoch2HeaderResponse, HeaderChain, HeaderRule, HeaderValidationError, MAINNET_CHECKPOINT, MAINNET_FIRST_BURN_HEIGHT, MAINNET_PREPARE_LENGTH, MAINNET_REWARD_CYCLE_LENGTH, MarfProofInput, MarfProofResponse, NakamotoHeader, NodeRpcProofSource, NodeRpcSourceOptions, ProofSource, ProvenDiff, SIGNERS_CONTRACT, SecondlayerProofSource, SecondlayerSourceOptions, SignerCheck, SignerSet, SourceError, StacksHeader, StateFailure, StateFailureCode, StateWitness, StateWrite, TransactionsError, VerifyCheckpoint, VerifyFailure, VerifyFailureCode, VerifyOptions, VerifyStep, VmEventRow, WitnessLeaf, blockId2 as blockId, blockTransactions, classifyBlockDiff, cycleStart, dataVarKey, decodeSignerSet, ftBalanceKey, hex, isEpoch2Header, mapEntryKey, marfPath, marfProofAncestors, marfValue, parseEpoch2Header, parseNakamotoHeader, parseWitness, rewardCycle, signerSignatureHash, txMerkleRoot2 as txMerkleRoot, unhex, verifyBlock, verifyBlockState, verifyConsensusPreimage, verifyMarfProof, verifySignerSignatures };
|