Repository navigation
Fix/shielded pool hardening - #176
Merged
Merged
Conversation
… window from its replacement, not its creation — the next insert no longer refuses spends proven against an old active root
…unshield change) in the pool, so two spends creating the same note are mutually exclusive / an invalid proof costs the sending peer too little reputation to get it banned — validators should take transactions only from their sentries
…roots keep a full retention window, pool tags for created notes (spec 20)
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
Two shielded-pool fixes for spend admission and execution, shipped in spec 20 with
pallet-shielded-pool0.25.2.RootRetentionBlocks. Its window used to count from when the root was created, so the next leaf insert, from anyone's shield, made it unknown at once. A spend proven a moment earlier was then refused withUnknownMerkleRoot(pool code 1). Now the root is recorded again when it is replaced, withnow + RootRetentionBlocks.provides a tag, so such spends are mutually exclusive in the pool, as the chain makes them.Changes
merkle/service.rs:insert_leafcallsretire_active_rooton the outgoing root. It is re-queued only when its expiry is shorter than a full window from now, which happens only for a root created in an earlier block. Cost: at most one extra historic-root slot per block.validate_unsigned/{transfer,unshield}.rs: one tag per created note,(OUTPUT_TAG, commitment). The tag never encodes like a bare nullifier tag, so a note one spend creates cannot block an unrelated spend whose nullifier has the same bytes.validate_unsigned/mod.rs: the doc comment no longer suggests that peer reputation limits invalid-proof spam. An invalid proof costs the sending peer too little reputation to get it banned, so validators should take transactions only from their sentries (--reserved-only).pallet-shielded-pool0.25.2, CHANGELOG, andRUNTIME_VERSIONS.md(spec 20).Testing
a_replaced_root_counts_its_window_from_its_replacementreplacing_a_root_from_the_same_block_queues_nothing_extratransfers_creating_the_same_note_are_mutually_exclusivean_unshield_change_note_is_tagged_like_a_transfer_outputan_output_tag_never_collides_with_a_nullifier_tag--reserved-onlybehind a sentry, spends sent through a public node--reserved-onlybehind a sentry: peers with the sentry alone, refuses an outside node, receives no invalid-proof spend from public nodes, legit spends still landNotes
orbinum/node-deploydocuments validators behind sentries (--reserved-only) and the RPC node's sentry role.