Skip to content

Latest commit

 

History

History
164 lines (132 loc) · 13.8 KB

tools.md

File metadata and controls

164 lines (132 loc) · 13.8 KB

The examples/ tools

Sixty small programs under crates/cli/examples/, each answering one question about a running or stopped node. They are cargo examples rather than subcommands so they stay out of the node binary and out of its argument surface: a diagnostic that only three people will ever run should not be a flag everyone has to read past.

Build and run one with:

cargo run --release -p rustock-cli --example <name> -- <args>

Most take a data directory and open it read-only, so they are safe to run against the live node. The ones marked (writes) do not: they modify the database, the head pointers or a segment store, and want the node stopped.

Each entry's description is the first line of the tool's own //! comment; the source is the reference, and run a tool with no arguments to see its usage.

Bridge and PowPeg

tool what it answers
powpeg_signature_audit Did a PowPeg functionary ever submit a signature the Bridge refused?
federation_intervals Which PowPeg functionary keys were active over which block range.
bridge_events Query the Bridge event index: every occurrence of one event, in block order.
bridge_method Identify a Bridge method from its 4-byte ABI selector, using the node's own table rather than a guess.
bridge_subtree How big is the Bridge's storage subtree, and how much of it is missing from a chunk?
pegin_refunds Did the Bridge's peg-in refund path ever execute on mainnet?
scan_pegin_calls Find registerBtcTransaction calls by reading blocks, without executing them.
scan_silent Read the silent-decision store: what the Bridge decided without logging it.
check_supply Replay canonical blocks and report any that do not conserve the native supply, changing nothing on disk.

Chain and block inspection

tool what it answers
block_info Prints stored block metadata for given heights, read-only.
height_peek Every block stored at a height, canonical or not, read-only.
dump_block Writes a block's stored bytes to disk, for attaching to a bug report.
inspect_block Execute one block against an archival trie and print what rustock computed: per-transaction gas and status, block gas, paid fees, and every root. Used to tell "we disagree about a fee" from "we disagree about what happened".
block_writes What did rustock write while executing one block?
scan_addr Diagnostic: scan canonical block bodies for transactions whose to (or sender, via recovered address) involves a target address. Used to locate the block/op that creates a given account in rskj but not rustock.
scan_edges Where on this chain is RSKIP-144 parallel execution actually used?
uncle_rpc_check Renders eth_getUncleByBlockHashAndIndex against the real mainnet store, read-only, alongside the running node.
dump_canonical_receipts Decode the canonical TransactionReceipts for a block from the snapshot receipts DB and print each receipt's fields (postTxState, cumulativeGas, gasUsed, status, bloom, #logs). Receipts DB is keyed by txHash -> RLP[ TransactionInfo[ [receiptRLP, blockHash, index], ... ] ].

State and trie

tool what it answers
dump_state Diagnostic: dump every leaf (key=value) of rustock's persisted unitrie at the executed head. Used to diff against rskj's unitrie for the same block to localize receipts-invisible state divergences.
diff_state Localize a post-wasabi state-root divergence to the exact diverging trie leaves. Replays canonical blocks from the executed head up to <number> in memory (computing rustock's — possibly wrong — post-state trie), then diffs it against rskj's own unitrie for the header's state root, read directly from rskj's LevelDB. The dual walk descends only where the two tries' subtree hashes differ, so it visits a handful of nodes and finishes instantly even on a multi-million-leaf state.
diff_roots Diff two unitrie roots that live in two different stores.
diff_self Diagnostic: show the unitrie leaf delta produced by executing a single block. Replays from the executed head to -1 (the base), then executes and hash-prune-diffs the two rustock-computed tries. Prints only the leaves that changed — the exact state delta of . No rskj DB needed (both sides are rustock-computed); use when rskj isn't synced past the target.
trie_footprint Measure the trie working set of a range of blocks.
trie_window Measure the miss rate of a sliding-window trie cache against window length.
lsm_stats LSM shape and table properties of a trie store: level layout, and whether the SSTs carry bloom filters at all.
detach_trie (writes) Copies the trie_nodes column family out of a node database into a standalone trie database.
drop_trie_cf (writes) Drops the trie_nodes column family from a node database.
flatdb_convert (writes) Copy a RocksDB trie store into a FlatDB one, node for node.
flatdb_migrate (writes) Move an epoch store from RocksDB to FlatDB, in place, node stopped.
flatdb_stats What a FlatDB store actually holds: record sizes, and how many cross the threshold that decides whether a key is stored or recomputed.
synthetic_state (writes) Build a synthetic world state of a chosen size, so that execution benchmarks start from a trie like a real one.
pre_unitrie_roots Replay the pre-RSKIP126 era from genesis, recording the Unitrie root each block computes, and optionally validating it against the header.

Snapshot sync and segments

tool what it answers
build_segments (writes) Replay a block range, verifying every state root, and build the range's trie segments as a by-product.
audit_chunk What does a segment chunk NOT contain that a consumer needs?
patch_size How many nodes would it take to make a chunk answer the lookups it cannot?
repair_chunk (writes) Make a segment chunk answer the lookups a foreign client issues.
probe_seed Is each segment chunk missing the parent state root of its own first block?
snap_serve_check Does snapshot sync work on the real trie?
pin_cost What does pinning the snapshot checkpoint cost the collector?

Recovery and surgery

tool what it answers
reset_exec_head (writes) Reset execution to genesis WITHOUT discarding downloaded blocks.
set_exec_head (writes) Rewinds (or advances) the executed head to a chosen canonical block.
rewind_to (writes) Rewind the download + executed head to a clean block and drop the canonical pointers above it, so the node re-downloads and re-executes the tail cleanly.
resume_point Where would execution resume? A read-only diagnostic.
replay_block Re-execute canonical blocks from the executed head up to a target block (in memory, nothing persisted) and report the target's per-transaction results, logs, and computed state/receipts roots vs the header. Deterministic, offline diagnostic for gas/state/receipts divergences.
verify_range Verify a range of blocks against rskj's own state, reporting every divergence rather than stopping at the first.

rskj interoperability

tool what it answers
rskj_blocks_probe Probe: can RocksDB open rskj's blocks LevelDB, and how far does it reach?
rskj_root_probe Does this rskj database still hold the state for a given block?
rskj_state_roots Look up rskj's stateRoots translation table.
dump_rskj_unitrie Dump every leaf of an rskj unitrie directly from its LevelDB, given a root hash. Post-RSKIP126 (wasabi100, #1,591,000) a header's state_root IS the unitrie root, so this lets us oracle-diff any post-wasabi block's state from Rust (no Java). rskj's unitrie LevelDB is content-addressed: nodeHash -> node message bytes, the same scheme rustock uses.

Benchmarks and measurement

tool what it answers
replay_bench Replay a block range against one trie store and report throughput.
read_bench Isolates read cost: one lookup in a large store versus N lookups across small ones.
batch_read_bench What a batched read buys, measured on the workload that uses one.
loadtest Measure block execution against a realistic trie, at a chosen number of threads.
gc_bench Synthetic trie-churn benchmark for the epoch garbage collector.
header_verify_bench How fast can this node verify headers under the full consensus rules?
btc_cache_bench Measure BTC main-chain block retrieval with and without the block cache, against a real database.
canonical_index_cost What the canonical number -> hash index costs.
validation_cost What a real block costs outside execution.
parallel_workload Generate a block workload with a known collision structure, mine it, and report how the RSKIP-144 miner partitioned it.

Configuration

tool what it answers
check_alerts_config Validate a peg-out alert configuration without starting a node or sending mail: parse it, resolve ${NAME} references against the env file, and report what would happen. Secrets are never printed — only whether they resolved and how long they are.

The PowPeg signature audit, in more detail

Two of these were written together to answer "did a PowPeg functionary ever submit an invalid signature", and they are worth a paragraph because the answer is not where you would first look for it.

There is no invalid-signature event. addSignature verifies each signature against its input's sighash and, on the first that does not verify, returns without applying anything: the call succeeds, spends its gas, changes no state and logs nothing. A malformed DER signature reverts; a well-formed signature over the wrong message is silent. a_member_signature_over_the_wrong_sighash_is_not_applied in crates/execution/src/bridge/peg.rs pins that.

What is observable is add_signature, and RSKIP326 (fingerroot500, mainnet #5,468,000) changed when it fires: from there, only once a signature has actually been applied. Below that height it fires before verification and cannot distinguish a good signature from a bad one.

So:

  1. federation_intervals <data-dir> [out.json] builds the ad-hoc database of which functionary keys could sign over which heights, from the sixteen commit_federation events — no state, no execution, which matters because a pruning node no longer holds the state those heights would need. It checks that every handover's outgoing key set is the set committed before it, and refuses to be trusted quietly if one does not close.

  2. powpeg_signature_audit <data-dir> <federations.json> [from] [to] [threads] scans for the calls: workers take contiguous height ranges and read bodies straight from the block store, pairing each call against the event index. Two benign causes are excluded — a pegout already released when the call arrived, and a federator that had already signed that pegout — and whatever survives goes to powpeg_unexplained.csv.

    Around 9.4 million blocks in half an hour on eight threads, with a progress line every thirty seconds.

Run them in that order; the second needs the first's JSON.