Skip to content

Repository files navigation

play-tools

Small Node.js scripts for deriving a v3 Merkle root from a secret file and building anchored binary Merkle trees for local debugging.

Architecture (why Merkle trees)

RemotePlayWorld is expected to carry many agents and many values; those values are contrasted across agents for comparison and monitoring. Merkle trees support flexible visibility (address and prove subsets of the world) and delta-oriented replication: peers can sync only what is missing or new along the tree instead of the full dataset, then merge updates into local world state on each client. The v3 anchor (buffer.txt.root) plus player-chain digests bind that structure to one deployment root. For the full rationale, see node-validation.md (section World architecture: RemotePlayWorld and why Merkle trees).

Operation logs

Each run of tool.js, create-merkle-tree.js, and validate-merkle-node.js writes a timestamped file under logs/ with a short header describing the operation. Diagnostic lines are copied there from stderr; the tree builder also stores the JSON shape in the log file. Stderr ends with [operation log: …]. logs/*.log is gitignored (the logs/ folder is kept via .gitkeep).

Requirements

  • Node.js (uses built-in crypto; no npm install required)

All commands below assume you run them from this directory:

cd /path/to/play-tools

1. Derive the anchor root from buffer.txt (tool.js)

Writes a short banner to stdout, then a single line of 64 lowercase hex characters (the derived root). The script always reads buffer.txt next to tool.js, not from your shell’s current working directory.

node tool.js

Example (last line is the root you typically save as your anchor id):

Merkle root (v3): scrypt(dkLen=32) over buffer.txt bytes; salt=SHA-256(domain label). See file header comment for full spec.
a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456

Redirect only the hex line if you need it in a file:

node tool.js | tail -n 1 > .root

Ensure buffer.txt exists and is non-empty before running.


2. Build a Merkle tree (create-merkle-tree.js)

Reads an anchor id (non-empty text, usually 64 hex chars) from a file, builds a binary Merkle subtree of N leaves under that anchor, writes leaf credentials to agent-play-debug.passw, prints debug views on stderr, and prints the tree shape as JSON on stdout.

Usage

node create-merkle-tree.js [--count N] [--root-file PATH] [--buffer PATH] [--validate]
Option Default Meaning
--count N 2 Number of leaf nodes (non-negative integer).
--root-file PATH See note below File whose trimmed contents are the anchor id.
--buffer PATH ./buffer.txt (next to script) Secret bytes used only with --validate.
--validate off Check that buffer.txt derives the same root as the anchor id in --root-file; does not build a tree.
-h, --help Print usage and exit.

Default --root-file: the script ships with a hard-coded path to a .root file on the maintainer’s machine. On your machine, pass an explicit path (for example the file you created with tool.js):

node create-merkle-tree.js --root-file ./.root --count 4

Generate a tree (typical)

node create-merkle-tree.js --root-file ./.root --count 4
  • Stdout: indented JSON tree shape (safe to pipe or save).
  • Stderr: ASCII tree diagram and flat merge-level debug output, plus a line like Wrote N entries to .../agent-play-debug.passw.

Split JSON and debug output

node create-merkle-tree.js --root-file ./.root --count 2 2>merkle-debug.log | tee tree-shape.json

Validate anchor against buffer.txt

Checks that scrypt-v3 derivation from the buffer matches the anchor id (exit 0 if match, 1 if not):

node create-merkle-tree.js --root-file ./.root --validate

Custom buffer path:

node create-merkle-tree.js --root-file ./.root --buffer ./buffer.txt --validate

Zero leaves

node create-merkle-tree.js --root-file ./.root --count 0

Produces an anchor-only tree (no binary subtree); stderr explains that the merge ladder is omitted.


3. Validate a node id (validate-merkle-node.js)

Checks whether a node id is consistent with the cryptography you expect. Exit code 0 means valid, 1 means not valid (or usage error).

Anchor / trust root (buffer + node id)

The secret file must be the same raw bytes used for Merkle root v3 (buffer.txt). The node id must be exactly the 64-character lowercase hex root derived from that file (same as tool.js output). This is the check described in node-validation.md for the trust anchor.

node validate-merkle-node.js --node-id "$(node tool.js | tail -n 1)" --buffer ./buffer.txt

Or put the id in a file:

node validate-merkle-node.js --node-id-file ./.root --buffer ./buffer.txt

Default --buffer is buffer.txt next to the script.

Leaf agent (anchor + index + password)

A leaf id is not determined by the buffer alone; it is digestLeaf(\${anchor}:${index}:${password}`). Use --leafplus the anchor string (your.rootline), the leaf index, and the password fromagent-play-debug.passw`:

node validate-merkle-node.js --leaf \
  --node-id '<64-hex from node-id:... line>' \
  --anchor "$(cat ./.root)" \
  --index 0 \
  --password '<hex after passw:>'

--anchor-file ./.root is equivalent to passing the anchor on the command line.


4. Supporting modules (for imports, not CLI)

File Role
merkle-tree-node.js MerkleTreeNode, tree builders, prettyPrintMerkleTree, serializeShape.
agent-play-merkle.js digestLeaf, digestPair, buildMerkleRootHex, prettyPrintDigestLevels.
merkle-root-v3.js Same v3 scrypt derivation as tool.js (for reuse in other scripts).

More detail

See node-validation.md for how the pieces fit together and how MerkleTreeNode.validate ties the anchor to buffer.txt. The anchor check in validate-merkle-node.js matches that behavior.

About

a bunch of scripts for agent play tooling

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages