perf(node): cut redundant chain-state work in info/nonce/persist paths - #72
Open
v0id-byte wants to merge 9 commits into
Open
perf(node): cut redundant chain-state work in info/nonce/persist paths#72v0id-byte wants to merge 9 commits into
v0id-byte wants to merge 9 commits into
Conversation
Social design docs live in the private v0id-social repository. This monorepo keeps a pointer and the multi-pillar roadmap narrative.
Add memo-convention public posts: contentHash on-chain, body off-chain. parseSocialPosts is deterministic; protocol memos stay out of DMs. Includes social-selftest for hash stability, mint path, and supply checks.
Fixes confirmed-real items from a perf audit at 100k-block scale, deliberately scoped to changes that don't touch consensus/validation logic (the bigger computeState-caching + incremental-addBlock rework is a separate, higher-risk follow-up PR). - node info() computed full chain state twice (balanceOf called separately for self + burned address); now one computeState() call, read twice. - Node had no /nonce endpoint at all; game-server's getNonce() and faucet.ts each independently forced a full chain fetch+parse+local-recompute to get a single address's nonce. Added /nonce, /balance-shaped /account (nonce+ balance from one computeState so both come from the same chain height), switched both callers to hit the node directly instead. - persist() wrote the full chain+mempool to disk synchronously on every send/tx/block (~7 call sites) - now debounced 500ms, flushed immediately on SIGINT/SIGTERM/uncaughtException/unhandledRejection so normal and crash-path shutdown don't silently drop the last half-second of state. - seenTx (P2P gossip dedup set) was memory-only, cleared every restart; now persisted to seenTx.json alongside chain state. - game-server's chainCache was a single-entry 2s-TTL cache with no request coalescing - concurrent misses each independently re-fetched the full chain. Now stale-while-revalidate with a shared in-flight promise. - Added graceful shutdown to both node and game-server (neither had one). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Add computeSocialBurnMin so post/reply minimum burns fall as difficulty rises (scheme 2), with hard floors. Parse uses inclusion-block difficulty.
Social funding can credit coinbase to a user address without importing their private key.
Difficulty retarget now aims for ~1s blocks so post/mine-enough needs fewer wall-clock seconds. Soft-fork: all validators must upgrade.
HTTP /mine (social coinbase-to-user) no longer races continuous --mine on the same tip. Continuous mining with interval 0 uses setImmediate.
Changing the retarget target rewrites historical expectedDifficulty and makes loadChain reject the whole chain. Document that --mine-interval 0 is the non-consensus way to avoid artificial gaps between blocks.
Social mine-enough (miner≠node wallet) now holds a demand lock so background --mine does not interleave and double wall-clock time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Low-risk half of a two-part perf fix, following up on an external audit doc (
v0idchain-perf-fix-list.md) claiming several O(chain)-per-call hotspots at 100k-block scale. Every claim below was independently re-verified against the current code (not taken at face value — a few of the doc's specific mechanisms turned out to be wrong even though the underlying perf problem was real) and confirmed live with a real node + game-server integration test, not justscripts/smoke.ts.Deliberately excludes the highest-value fix (
Blockchain.cachedState+ incrementaladdBlock, which would makecomputeState()O(1) instead of O(chain)) — that touches consensus/validation code directly reachable from untrusted P2P peers, so it's staged as a separate follow-up PR with its own dedicated equivalence tests rather than bundled here.info()computed chain state twice (balanceOfcalled once for self, once for the burn address, each a full chain walk) — now onecomputeState()call, read twice./nonceendpoint existed on the node.game-server'sgetNonce()and, separately,faucet.tseach forced a full chain fetch + JSON parse + local Blockchain rebuild just to read one address's nonce. Added/nonce, plus/account(nonce+balance from a singlecomputeState()call so both values come from the same chain height — fixes a real atomicity gap a reviewer caught: two separate/nonce+/balancecalls could straddle a block boundary). Bothgame-servercall sites now hit the node directly.persist()wrote the entire chain+mempool to disk synchronously on every send/tx/received-block (7 call sites). Now debounced 500ms and flushed immediately onSIGINT/SIGTERM/uncaughtException/unhandledRejection, so neither a normal shutdown nor a crash silently drops the last half-second of state.seenTx(P2P gossip-echo dedup) was memory-only, cleared every restart — now persisted toseenTx.json.game-server'schainCachewas a single-entry 2s-TTL cache with no request coalescing — concurrent cache misses each independently re-fetched and re-parsed the full chain (cache stampede). Now stale-while-revalidate with a shared in-flight promise.nodeandgame-server(neither had any signal handling before).Also tried lowering the PoW mining
BATCHconstant (20000→5000) per the audit doc; reverted after review turned up a legitimate hashrate-cost concern that wasn't worth trading for an unquantified responsiveness gain — left at its original value.Test plan
pnpm -r run typecheck— clean across all 6 packagespnpm run smoke— 163/163 checks pass/nonce,/balance,/accountcross-checked for consistencyinfo()balance/burned correctness after the dedup changechain.jsonmtime unchanged immediately after a send, flushed shortly after; correct final contentseenTx.jsoncreated with correct content + 0600 perms/accountpath, including duplicate-claim rejection (pre-existing logic, unaffected)/api/chaincalls spanning the cache TTL boundary: fast responses throughout, eventually consistent, no errors/accountendpoint, deadforceparam removed, shutdown-handler asymmetry fixed, BATCH reverted) rather than shipped as-is🤖 Generated with Claude Code