@xmbl/state-machine 0.1.11 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @xmbl/state-machine
2
2
 
3
+ ## 0.2.0
4
+
3
5
  ## 0.1.11
4
6
 
5
7
  ### Patch Changes
@@ -18,7 +20,7 @@
18
20
  never under the xid it claims (a datum fails `validateXid` precisely when that xid is somebody else's), and
19
21
  the anchor dedup key claimed before validation is released on every failure. Both doors are closed on BOTH
20
22
  entry points — `addTransaction` and `addSealedBatch`, the path a finalized transaction actually takes — and
21
- one invalid entry in a batch no longer discards the honest transactions behind it.
23
+ one invalid entry in a batch no longer discards the genuine transactions behind it.
22
24
  - consensus: a content-addressed type-6 value tx is admitted on its content address (it carries no in-body
23
25
  signature by design); a malformed anchor is refused at the door by the ledger's own `validateTransaction`;
24
26
  `finalizeTransaction` preserves the signed `id`.
@@ -28,7 +30,7 @@
28
30
  - networking: self-elected circuit-relay server; NO_FATAL transport tolerance; throttled bootstrap warnings.
29
31
  - storage-compute: `CoordinateDelivery` (broken: `require` in ESM, keyed on the public key) is removed.
30
32
  - core: ships the node daemon as the `xmbl-node` bin; the control socket implements the coordinator
31
- contract (`xsc`, `submit_batch`, `ledger_capabilities`, `identity_status`, a signed `chain` claim, honest
33
+ contract (`xsc`, `submit_batch`, `ledger_capabilities`, `identity_status`, a signed `chain` claim, genuine
32
34
  `submit_tx` rejections) and reports the RUNNING versions; boot waits for the stores.
33
35
  - every package exports a load-time `VERSION`.
34
36
  - PROTOCOL (operator, 2026-09-16): every transaction is typed by its xid (tokens.json type codes; `micromineTx`/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmbl/state-machine",
3
- "version": "0.1.11",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "exports": {
@@ -1,4 +1,4 @@
1
- // OUTCOME TEST: applied_tx_count after the convergence primitive. The metric the whole fleet reads.
1
+ // OUTCOME TEST: applied_tx_count after the convergence primitive. The metric every node reads.
2
2
  const { StateMachine } = await import("../index.js");
3
3
  const sm = new StateMachine({ dbPath: null });
4
4
  sm._dbOpen = false;
@@ -50,7 +50,7 @@ const close = async ({ dir, xclt, xvsm }) => {
50
50
  console.log('\n1. a SEALED face reaches the state tree (the missing block:added doorbell)');
51
51
  {
52
52
  const env = await fresh();
53
- await check('the tree starts empty — the honest baseline, not an assumption', async () => {
53
+ await check('the tree starts empty — the true baseline, not an assumption', async () => {
54
54
  eq(env.xvsm.getStateRoot(), ZERO, 'initial root');
55
55
  });
56
56
  await check('sealing 9 txs moves state_root off zero and applies 9 diffs', async () => {
@@ -1,4 +1,4 @@
1
- // THE THREE DEFECTS THAT KEPT NODES OFF A SHARED ROOT, each asserted by the symptom the fleet showed,
1
+ // THE THREE DEFECTS THAT KEPT NODES OFF A SHARED ROOT, each asserted by the symptom the nodes showed,
2
2
  // not by the mechanism. All three were measured live on 2026-09-15 before being fixed here.
3
3
  import { test } from 'node:test';
4
4
  import assert from 'node:assert';
@@ -25,7 +25,7 @@ test('a restarted node publishes a REAL root, not 64 zeros, from the state: keys
25
25
  await sm.db.close();
26
26
 
27
27
  // Reopen. The diff replay is NOT the thing under test — delete every diff row first, so the only
28
- // surviving source for the trie is `state:`. 39 of 44 reporting fleet nodes published ZERO here.
28
+ // surviving source for the trie is `state:`. 39 of 44 reporting nodes published ZERO here.
29
29
  sm = await open(dir);
30
30
  await sm.db.clear({ gte: 'diff:', lt: 'diff:\xFF' });
31
31
  await sm.db.close();
@@ -73,7 +73,7 @@ test('legacy rows keyed by block id are re-keyed to content identity on the next
73
73
  const dir = `/tmp/xvsm-rehydrate-${process.pid}-d`;
74
74
  rmSync(dir, { recursive: true, force: true });
75
75
  let sm = await open(dir);
76
- // Write rows the way every node on the fleet already has them: one per submission, keyed by block id.
76
+ // Write rows the way every node on the nodes already has them: one per submission, keyed by block id.
77
77
  const set = anchors(40);
78
78
  let written = 0;
79
79
  for (let pass = 0; pass < 3; pass++) for (const a of set) {
@@ -34,7 +34,7 @@ export class StateMachine extends EventEmitter {
34
34
 
35
35
  // Initialize database. KEEP THE PROMISE: `_dbOpen` flips true the moment Level opens, long before the
36
36
  // diff sweep and the tree rehydration have finished, so anything that polls `_dbOpen` and then reads a
37
- // count is reading a store mid-rebuild. `ready()` is the only honest join point.
37
+ // count is reading a store mid-rebuild. `ready()` is the only genuine join point.
38
38
  this._ready = this._initDb().catch(() => {});
39
39
 
40
40
  // Listen to ledger events if available
@@ -335,9 +335,9 @@ export class StateMachine extends EventEmitter {
335
335
  // ⛔ RECORD A DIFF FOR EVERY ANCHOR APPLIED, or applied_tx_count IS ZERO BY CONSTRUCTION. This loop wrote
336
336
  // straight into the tree and never touched `this.diffs`, which it had just emptied — and
337
337
  // getStatistics().totalTransactions is transactionLog.length + diffs.length. So the moment a node runs the
338
- // convergence primitive, the number the whole fleet reads as "is this node applying anything" resets to 0
338
+ // convergence primitive, the number every node reads as "is this node applying anything" resets to 0
339
339
  // and STAYS 0 no matter how many anchors it applied. MEASURED 2026-09-15: this node held a correct root
340
- // over 3,941 applied anchors and published applied_tx_count 0; across the fleet 42 of 46 reporting nodes
340
+ // over 3,941 applied anchors and published applied_tx_count 0; across the nodes 42 of 46 reporting nodes
341
341
  // read 0, and a design ruling was written on the premise that 41 of them had "applied nothing". They had.
342
342
  // The diff is not bookkeeping — it is the same StateDiff the block path records, keyed by the anchor's own
343
343
  // content, so a rebuild and a live apply of the same anchor upsert to ONE row rather than two.
@@ -9,7 +9,7 @@
9
9
  // leaf hash = sha256(value canonicalised) (value node at depth 32)
10
10
  // internal node hash = sha256( concat of 256 child slots, each 32 bytes; empty slot = 32 zeros )
11
11
  // a key's nibble at depth d = sha256(key)[d]
12
- // A proof carries, per level, the sibling hashes at that node; the honest verifier fills the key's own
12
+ // A proof carries, per level, the sibling hashes at that node; the correct verifier fills the key's own
13
13
  // slot with the hash carried up from below and every other slot from the siblings (or zeros), hashes,
14
14
  // and repeats to the root. The proof is SOUND iff the reconstructed root equals the tree's real root —
15
15
  // which the verifier learns independently (tree.getRoot()), never from the attacker-supplied proof.root.
@@ -10,7 +10,7 @@ import { join } from 'path';
10
10
  let pass = 0, fail = 0;
11
11
  const check = async (n, f) => { try { await f(); console.log(` ok ${n}`); pass++; } catch (e) { console.log(` FAIL ${n}\n ${e.message}`); fail++; } };
12
12
  const EMPTY = '0'.repeat(64);
13
- // Portable: this suite runs on the laptop AND on every Linux box in the fleet — so it JOINS on `ready()`
13
+ // Portable: this suite runs on the laptop AND on every Linux box among the nodes — so it JOINS on `ready()`
14
14
  // rather than sleeping. A fixed timeout is a guess about someone else's scheduler: this suite waited
15
15
  // 120/150/250/500ms for the store to open and the tree to rehydrate, which held on this laptop and LOST on
16
16
  // ubuntu-latest, where the restart check read 64 zeros — the 150ms wait expired before `_initDb` had opened
@@ -53,7 +53,7 @@ export class VerkleStateTree {
53
53
  // `this.root` a fresh empty VerkleNode. So a node that had loaded EVERY key off disk answered getRoot()
54
54
  // with 64 zeros: a tree that holds the whole state and commits to nothing. MEASURED 2026-09-15: after a
55
55
  // canonical rebuild of 10 anchors, restart loaded all 10 keys and published root 0000…0000; across the
56
- // fleet 39 of 44 reporting nodes published exactly that, including one with 11,691 blocks persisted. The
56
+ // nodes 39 of 44 reporting nodes published exactly that, including one with 11,691 blocks persisted. The
57
57
  // only boxes showing a real root were showing it by accident, via XVSM's diff replay re-inserting keys
58
58
  // through insert(). The state map is not the commitment — the hashed trie over it is, and it has to be
59
59
  // reconstructed on open or every restart silently un-commits the node's entire state.
@@ -201,7 +201,7 @@ export class VerkleStateTree {
201
201
  // transactions instead of the structure that actually commits them. This returns the real nodes and the
202
202
  // real parent->child edges, bounded, with the counts needed to say what was left out.
203
203
  //
204
- // Bounded on BOTH axes and honest about it: `maxDepth` limits how far down, `maxNodes` caps the total, and
204
+ // Bounded on BOTH axes and genuine about it: `maxDepth` limits how far down, `maxNodes` caps the total, and
205
205
  // the result carries `truncated` plus each node's own `descendants` so a cut branch reports its real size
206
206
  // rather than looking like a leaf. A viewer that silently stopped at 500 nodes would draw a tree that is
207
207
  // simply the wrong shape.
@@ -217,7 +217,7 @@ export class VerkleStateTree {
217
217
  }
218
218
  if (!start.hash) this._updateHash(start);
219
219
 
220
- // Subtree size is what makes a truncated branch honest, so it is computed for every node we emit.
220
+ // Subtree size is what makes a truncated branch genuine, so it is computed for every node we emit.
221
221
  const sizeOf = (node) => {
222
222
  let n = 1;
223
223
  for (const c of node.children.values()) n += sizeOf(c);