Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow merkle masks to handle empty accounts directly #14585

Conversation

mrmr1993
Copy link
Member

This PR builds upon #14571, implementing a similar preloading mechanism for empty accounts to avoid falling back to the database.

Checklist:

  • Dependency versions are unchanged
    • Notify Velocity team if dependencies must change in CI
  • Modified the current draft of release notes with details on what is completed or incomplete within this project
  • Document code purpose, how to use it
    • Mention expected invariants, implicit constraints
  • Tests were added for the new behavior
    • Document test purpose, significance of failures
    • Test names should reflect their purpose
  • All tests pass (CI will check this if you didn't)
  • Serialized types are in stable-versioned modules
  • Does this close issues? List them

@mrmr1993
Copy link
Member Author

!ci-build-me

@mrmr1993
Copy link
Member Author

!ci-nightly-me

@mrmr1993
Copy link
Member Author

!ci-build-me

@@ -188,17 +188,6 @@ module Make (Test : Test_intf) = struct
(* verify all hashes to root are same in mask and parent *)
compare_maskable_mask_hashes maskable attached_mask dummy_address )

let%test "mask delegates to parent" =
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove invalid test: mask parents should not be changed

Is this actually an invalid test ? Masks parents are sometimes changed/modified.
It is the reason why there is the method Mask.Attached.parent_set_notify:

Mask.Attached.parent_set_notify mask account )

Removing this test means we're breaking the relation parent/child described in specs/merkle_tree.md

Copy link
Member

Choose a reason for hiding this comment

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

@georgeee Can we add this test back? If the dummy account is added before the child mask is attached, it should do as expected, right?

@@ -181,7 +181,16 @@ module Make (Inputs : Inputs_intf.S) = struct
| Some account ->
Some account
| None ->
Base.get (get_parent t) location
let is_empty =
match t.current_location with
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
match t.current_location with
match (last_filled t) with

(last_filled t) should probably be used here ? to get updated location from all the parents.
This would allow to keep the test above to pass.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll defer to @nholland94, but IMO we break a bunch of invariants (e.g. merkle paths) if we allow incompatible writes to the parent ledger, and the test is misguided.

Copy link
Contributor

Choose a reason for hiding this comment

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

This affects masks behavior: that would break this property of masks, which is quite important IMO:

Whenever a read occurs on a mask, the mask will first attempt to retrieve the node from its internal sparse collection, and if it does not exist there, will forward the read request to its parent.

(text from specs/merkle_tree.md)

If the performance of (last_filled t) is the concern, it could be called only once in get_batch and self_merkle_path

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, this is confusing. We should probably update the mask interface to not allow updating parent masks if it breaks the invariants. I'm seeing calls to parent_set_notify which is to notify child masks about updates in the parent mask?
Re the test, if the dummy account was added to the parent mask before creating the child mask, then it should pass?

Copy link
Member

Choose a reason for hiding this comment

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

We should probably update the mask interface to not allow updating parent masks if it breaks the invariants.

This was my suggestion last week, but I believe consensus was that this will be too big of a change to implement right now.

But in general I agree with this, though supposedly related functionalities are just dead code (the riskiness of a change lies in the fact that it'd require a complicated analysis of the whole codebase to prove it's actually dead, though I'd argue seeing it alive is worse and we'd better throw a runtime error when such things occur).

Copy link
Member

Choose a reason for hiding this comment

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

Ok. created #14631 to track this. We should address this before making any planned changes to this library

@mrmr1993 mrmr1993 marked this pull request as ready for review November 21, 2023 18:21
@mrmr1993 mrmr1993 requested a review from a team as a code owner November 21, 2023 18:21
@georgeee georgeee force-pushed the feature/merkle-mask-preloading branch from df57650 to 344a10d Compare November 27, 2023 16:53
@georgeee georgeee force-pushed the feature/merkle-mask-empty-account-preloading branch 2 times, most recently from e26350e to 64e75d1 Compare November 27, 2023 18:00
self_find_or_batch_lookup self_find_location
Base.location_of_account_batch
let location_of_account_batch t =
(* TODO consider handling special case of empty addresses *)
Copy link
Member

Choose a reason for hiding this comment

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

@mrmr1993 looks like this is needed. self_find_or_batch_lookup would end up accessing disk for empty accounts otherwise, no?

Copy link
Member

@georgeee georgeee Nov 28, 2023

Choose a reason for hiding this comment

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

P.S. this is my TODO which I left when doing rebases

I believe we need it, I will be able to implement it I think

Copy link
Member

Choose a reason for hiding this comment

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

We can have a follow-up PR for this, I think

Copy link
Member

@georgeee georgeee Nov 28, 2023

Choose a reason for hiding this comment

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

@deepthiskumar I guess we don't have a choice in this function because unlike loading an account by location here we can't tell of an account whether it's a new one or just wasn't loaded from parent.

It might have an implication to performance of transaction processing (I do see some db lookups despite the fact that we preload a lot of stuff). But I think we'll handle it via special-casing unsafe_preload function, not right here.

P.S. I removed the TODO

@georgeee georgeee force-pushed the feature/merkle-mask-preloading branch from a0c92df to 576bc95 Compare November 28, 2023 17:56
@georgeee georgeee force-pushed the feature/merkle-mask-empty-account-preloading branch 2 times, most recently from e8ee28a to 4a9f96f Compare November 28, 2023 18:27
@georgeee georgeee force-pushed the feature/merkle-mask-preloading branch from 576bc95 to d530750 Compare November 28, 2023 20:07
@georgeee georgeee force-pushed the feature/merkle-mask-empty-account-preloading branch from 4a9f96f to 4a490a8 Compare November 28, 2023 20:07
@georgeee georgeee force-pushed the feature/merkle-mask-preloading branch from d530750 to b3525d3 Compare November 28, 2023 20:13
@georgeee georgeee force-pushed the feature/merkle-mask-empty-account-preloading branch from 4a490a8 to 94cfcd1 Compare November 28, 2023 20:14
@georgeee georgeee force-pushed the feature/merkle-mask-preloading branch from b3525d3 to 5e71099 Compare November 28, 2023 20:29
mrmr1993 and others added 5 commits November 28, 2023 21:30
Justification: we don't have a choice in this function because unlike
loading an account by location here we can't tell of an account whether
it's a new one or just wasn't loaded from parent.

It might have an implication to performance of transaction processing (I
do see some db lookups despite the fact that we preload a lot of stuff).
But I think we'll handle it via special-casing unsafe_preload
function, not right here.
@deepthiskumar
Copy link
Member

!ci-build-me

deepthiskumar and others added 24 commits December 1, 2023 21:56
Includes a bugfix in Merkle_ledger.Database.wide_merkle_path_batch
…e-merkle-paths

Use 'wide merkle paths' to optimize `Sparse_ledger.of_ledger_subset_exn`
…subset-no-mutability

Avoid ledger copy and mutation in `Sparse_ledger.of_ledger_subset_exn`
@deepthiskumar deepthiskumar merged commit 4b56a35 into feature/merkle-mask-preloading Dec 5, 2023
1 check passed
@deepthiskumar deepthiskumar deleted the feature/merkle-mask-empty-account-preloading branch December 5, 2023 06:32
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.

None yet

6 participants