Skip to content

starknet_patricia: use OnceLock for write-once filled-tree output maps#14622

Merged
yoavGrs merged 1 commit into
mainfrom
yoav/filled-tree-oncelock-output-maps
Jun 25, 2026
Merged

starknet_patricia: use OnceLock for write-once filled-tree output maps#14622
yoavGrs merged 1 commit into
mainfrom
yoav/filled-tree-oncelock-output-maps

Conversation

@yoavGrs

@yoavGrs yoavGrs commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

The filled-tree output maps are written exactly once per node and then
reclaimed, yet they used Mutex<Option<T>> and locked on every write and on
every reclaim - even though after Arc::into_inner the map is uniquely owned
and can never be contended.

Replace the output maps with OnceLock<T>, the primitive that matches this
write-once access pattern: write_to_output_map becomes a lock-free set
(a failed set is the double-update error), and reclaiming via
OnceLock::into_inner drops the locking entirely. Pre-allocate the collected
map with the known capacity. Leaf::Output gains a Sync bound, required for
OnceLock<L::Output>: Sync. The leaf input map keeps Mutex<Option<_>>,
since its values are moved out (take-once), not written.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

@cursor

cursor Bot commented Jun 24, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches core merkle tree fill concurrency and tightens the Leaf::Output trait bound; behavior should be equivalent but double-write and missing-placeholder semantics now depend on OnceLock instead of mutex take.

Overview
Filled-tree and leaf output maps now use OnceLock<T> instead of Mutex<Option<T>>, matching the write-once-per-slot pattern during parallel tree fill.

write_to_output_map uses lock-free OnceLock::set (a failed set still maps to DoubleUpdate). Final assembly goes through renamed collect_output_map, which uses OnceLock::into_inner without mutexes and pre-sizes the result HashMap. Leaf inputs still use Mutex<Option<_>> for take-once consumption.

The Leaf::Output associated type gains a Sync bound so shared OnceLock<L::Output> slots are valid across concurrent tasks.

Reviewed by Cursor Bugbot for commit e5f7ec4. Bugbot is set up for automated code reviews on this repo. Configure here.

The filled-tree output maps are written exactly once per node and then
reclaimed, yet they used `Mutex<Option<T>>` and locked on every write and on
every reclaim - even though after `Arc::into_inner` the map is uniquely owned
and can never be contended.

Replace the output maps with `OnceLock<T>`, the primitive that matches this
write-once access pattern: `write_to_output_map` becomes a lock-free `set`
(a failed `set` is the double-update error), and reclaiming via
`OnceLock::into_inner` drops the locking entirely. Pre-allocate the collected
map with the known capacity. `Leaf::Output` gains a `Sync` bound, required for
`OnceLock<L::Output>: Sync`. The leaf *input* map keeps `Mutex<Option<_>>`,
since its values are moved out (take-once), not written.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yoavGrs yoavGrs changed the base branch from assert_unmodified_subtree_child_present to graphite-base/14622 June 25, 2026 06:27
@yoavGrs yoavGrs force-pushed the graphite-base/14622 branch from 1e5c797 to a7255c4 Compare June 25, 2026 06:27
@yoavGrs yoavGrs force-pushed the yoav/filled-tree-oncelock-output-maps branch from b00c8c7 to e5f7ec4 Compare June 25, 2026 06:27
@yoavGrs yoavGrs changed the base branch from graphite-base/14622 to main June 25, 2026 06:27
@yoavGrs yoavGrs requested a review from nimrod-starkware June 25, 2026 07:50

@nimrod-starkware nimrod-starkware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nimrod-starkware reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on yoavGrs).


crates/starknet_patricia/src/patricia_merkle_tree/filled_tree/tree.rs line 112 at r1 (raw file):

                    existing_value_as_string: format!("{existing_node:?}"),
                }
            }),

I think that should work, the error is the value that was already set

Suggestion:

            Some(slot) => slot.set(output).map_err(|exisitng_node| {
                FilledTreeError::DoubleUpdate {
                    index,
                    existing_value_as_string: format!("{existing_node:?}"),
                }
            }),

@yoavGrs yoavGrs left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yoavGrs made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on nimrod-starkware).


crates/starknet_patricia/src/patricia_merkle_tree/filled_tree/tree.rs line 112 at r1 (raw file):

Previously, nimrod-starkware wrote…

I think that should work, the error is the value that was already set

The Err contains the value you just tried to set (the rejected output), not the value already
stored in the lock.

@nimrod-starkware nimrod-starkware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nimrod-starkware made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on yoavGrs).


crates/starknet_patricia/src/patricia_merkle_tree/filled_tree/tree.rs line 112 at r1 (raw file):

Previously, yoavGrs wrote…

The Err contains the value you just tried to set (the rejected output), not the value already
stored in the lock.

try_insert returns a reference to the stored value. you can use that

@nimrod-starkware nimrod-starkware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nimrod-starkware made 1 comment and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on yoavGrs).


crates/starknet_patricia/src/patricia_merkle_tree/filled_tree/tree.rs line 112 at r1 (raw file):

Previously, nimrod-starkware wrote…

try_insert returns a reference to the stored value. you can use that

nvm it's nightly only, unblocking

@yoavGrs yoavGrs added this pull request to the merge queue Jun 25, 2026
Merged via the queue into main with commit 0cc1644 Jun 25, 2026
29 of 53 checks passed

Copy link
Copy Markdown
Contributor

Security scan complete — no issues detected.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants