mirror of
https://github.com/luxfi/chains.git
synced 2026-09-24 00:26:00 +00:00
loadUTXOs was `return nil`. The in-memory set was never rebuilt, so a restarted node came back with an empty one: it accepted a commitment it already held — reaching the opposite verdict from a running node on the same block — and reported no commitments and no UTXOs at any height. The count came from a separately persisted key, a second copy of the truth that a crash between the two writes leaves disagreeing with the records, and one removal from there drives an unsigned counter below zero. That is the same defect just removed from the nullifier count, so the UTXO set now works the same way: the records are the set, and the count is read off it. Blocks live in the same database under their raw ids, and one id in 256 begins with the UTXO prefix. The loader now counts a record as a UTXO only when it names the commitment its own key is made of; a block frame parses as a UTXO otherwise, since the accessors are bounds-safe and return zeros, and a garbage commitment would join the set. Both read paths memoized what they loaded while holding only a read lock. The memo is deleted rather than the lock upgraded: the map is loaded with the whole set at startup and maintained by the writers, so the disk read already returns what the memo would have, and a write lock on a path consensus and RPC share would serialize every reader to save a lookup. A nullifier value that is not eight bytes is now a miss rather than a panic in a consensus path; the loader already skipped those. Co-authored-by: Hanzo Dev <[email protected]>