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
Fix two bugs related to write notifications in masks #1794
Changes from 3 commits
7834a0a
5a141f3
616049a
aea0c99
7510ac5
2fed13a
6a910ca
4e53a9b
dd1ecf5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -117,4 +117,24 @@ struct | |
in | ||
ignore (unregister_mask_exn parent t_as_mask) ; | ||
List.iter dangling_masks ~f:(fun m -> ignore (register_mask parent m)) | ||
|
||
let batch_notify_children t accounts = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've noticed people, including me, sometimes confuse which is parent and which is child. Can we name this |
||
match Uuid.Table.find registered_masks (get_uuid t) with | ||
| None -> () | ||
| Some masks -> | ||
List.iter masks ~f:(fun mask -> | ||
List.iter accounts ~f:(fun account -> | ||
Mask.Attached.parent_set_notify mask account ) ) | ||
|
||
let set_batch t locations_and_accounts = | ||
Base.set_batch t locations_and_accounts ; | ||
batch_notify_children t (List.map locations_and_accounts ~f:snd) | ||
|
||
let set_batch_accounts t addresses_and_accounts = | ||
Base.set_batch_accounts t addresses_and_accounts ; | ||
batch_notify_children t (List.map addresses_and_accounts ~f:snd) | ||
|
||
let set_all_accounts_rooted_at_exn t address accounts = | ||
Base.set_all_accounts_rooted_at_exn t address accounts ; | ||
batch_notify_children t accounts | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,47 +125,47 @@ struct | |
let get_uuid t = assert_is_attached t ; t.uuid | ||
|
||
(* don't rely on a particular implementation *) | ||
let find_hash t address = | ||
let self_find_hash t address = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, these name changes help make it clear that these operations work just on the mask tables. |
||
assert_is_attached t ; | ||
Addr.Table.find t.hash_tbl address | ||
|
||
let set_hash t address hash = | ||
let self_set_hash t address hash = | ||
assert_is_attached t ; | ||
Addr.Table.set t.hash_tbl ~key:address ~data:hash | ||
|
||
let set_inner_hash_at_addr_exn t address hash = | ||
assert_is_attached t ; | ||
assert (Addr.depth address <= Base.depth) ; | ||
set_hash t address hash | ||
self_set_hash t address hash | ||
|
||
(* don't rely on a particular implementation *) | ||
let find_location t public_key = | ||
let self_find_location t public_key = | ||
assert_is_attached t ; | ||
Key.Table.find t.location_tbl public_key | ||
|
||
let set_location t public_key location = | ||
let self_set_location t public_key location = | ||
assert_is_attached t ; | ||
Key.Table.set t.location_tbl ~key:public_key ~data:location | ||
|
||
(* don't rely on a particular implementation *) | ||
let find_account t location = | ||
let self_find_account t location = | ||
assert_is_attached t ; | ||
Location.Table.find t.account_tbl location | ||
|
||
let find_all_accounts t = | ||
let self_find_all_accounts t = | ||
assert_is_attached t ; | ||
Location.Table.data t.account_tbl | ||
|
||
let set_account t location account = | ||
let self_set_account t location account = | ||
assert_is_attached t ; | ||
Location.Table.set t.account_tbl ~key:location ~data:account ; | ||
set_location t (Account.public_key account) location | ||
self_set_location t (Account.public_key account) location | ||
|
||
(* a read does a lookup in the account_tbl; if that fails, delegate to | ||
parent *) | ||
let get t location = | ||
assert_is_attached t ; | ||
match find_account t location with | ||
match self_find_account t location with | ||
| Some account -> Some account | ||
| None -> Base.get (get_parent t) location | ||
|
||
|
@@ -179,7 +179,7 @@ struct | |
(* first element in the path contains hash at sibling of address *) | ||
let curr_element = List.hd_exn path in | ||
let merkle_node_address = Addr.sibling address in | ||
let mask_hash = find_hash t merkle_node_address in | ||
let mask_hash = self_find_hash t merkle_node_address in | ||
let parent_hash = | ||
match curr_element with `Left h | `Right h -> h | ||
in | ||
|
@@ -240,14 +240,14 @@ struct | |
(* use mask Merkle root, if it exists, else get from parent *) | ||
let merkle_root t = | ||
assert_is_attached t ; | ||
match find_hash t (Addr.root ()) with | ||
match self_find_hash t (Addr.root ()) with | ||
| Some hash -> hash | ||
| None -> Base.merkle_root (get_parent t) | ||
|
||
let remove_account_and_update_hashes t location = | ||
assert_is_attached t ; | ||
(* remove account and key from tables *) | ||
let account = Option.value_exn (find_account t location) in | ||
let account = Option.value_exn (self_find_account t location) in | ||
Location.Table.remove t.account_tbl location ; | ||
(* TODO : use stack database to save unused location, which can be used | ||
when allocating a location *) | ||
|
@@ -267,13 +267,13 @@ struct | |
account_hash | ||
in | ||
List.iter addresses_and_hashes ~f:(fun (addr, hash) -> | ||
set_hash t addr hash ) | ||
self_set_hash t addr hash ) | ||
|
||
(* a write writes only to the mask, parent is not involved need to update | ||
both account and hash pieces of the mask *) | ||
let set t location account = | ||
assert_is_attached t ; | ||
set_account t location account ; | ||
self_set_account t location account ; | ||
let account_address = Location.to_path_exn location in | ||
let account_hash = Hash.hash_account account in | ||
let merkle_path = merkle_path t location in | ||
|
@@ -282,29 +282,26 @@ struct | |
account_hash | ||
in | ||
List.iter addresses_and_hashes ~f:(fun (addr, hash) -> | ||
set_hash t addr hash ) | ||
self_set_hash t addr hash ) | ||
|
||
(* if the mask's parent sets an account, we can prune an entry in the mask | ||
if the account in the parent is the same in the mask *) | ||
let parent_set_notify t account = | ||
assert_is_attached t ; | ||
match find_location t (Account.public_key account) with | ||
match self_find_location t (Account.public_key account) with | ||
| None -> () | ||
| Some location -> ( | ||
match find_account t location with | ||
match self_find_account t location with | ||
| Some existing_account -> | ||
if | ||
Key.equal | ||
(Account.public_key account) | ||
(Account.public_key existing_account) | ||
then remove_account_and_update_hashes t location | ||
if Account.equal account existing_account then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do all fields have to match? Is it enough that the key and balance are the same? I don't understand the receipt chain hash, so I don't know, myself. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, otherwise we're losing information. |
||
remove_account_and_update_hashes t location | ||
| None -> () ) | ||
|
||
(* as for accounts, we see if we have it in the mask, else delegate to | ||
parent *) | ||
let get_hash t addr = | ||
assert_is_attached t ; | ||
match find_hash t addr with | ||
match self_find_hash t addr with | ||
| Some hash -> Some hash | ||
| None -> ( | ||
try | ||
|
@@ -323,7 +320,7 @@ struct | |
let get_hash_batch_exn t addrs = | ||
assert_is_attached t ; | ||
List.map addrs ~f:(fun addr -> | ||
match find_hash t addr with | ||
match self_find_hash t addr with | ||
| Some account -> Some account | ||
| None -> ( | ||
try Some (Base.get_inner_hash_at_addr_exn (get_parent t) addr) | ||
|
@@ -394,11 +391,11 @@ struct | |
|
||
let set_raw_hash_batch t locations_and_hashes = | ||
List.iter locations_and_hashes ~f:(fun (location, hash) -> | ||
set_hash t (Location.to_path_exn location) hash ) | ||
self_set_hash t (Location.to_path_exn location) hash ) | ||
|
||
let set_raw_account_batch t locations_and_accounts = | ||
List.iter locations_and_accounts ~f:(fun (location, account) -> | ||
set_account t location account ) | ||
self_set_account t location account ) | ||
end) | ||
|
||
let set_batch_accounts t addresses_and_accounts = | ||
|
@@ -435,7 +432,7 @@ struct | |
|
||
let location_of_key t key = | ||
assert_is_attached t ; | ||
let mask_result = find_location t key in | ||
let mask_result = self_find_location t key in | ||
match mask_result with | ||
| Some _ -> mask_result | ||
| None -> Base.location_of_key (get_parent t) key | ||
|
@@ -456,7 +453,7 @@ struct | |
match keys with | ||
| [] -> (parent_keys, mask_locations) | ||
| key :: rest -> ( | ||
match find_location t key with | ||
match self_find_location t key with | ||
| None -> loop rest (key :: parent_keys) mask_locations | ||
| Some loc -> loop rest parent_keys (loc :: mask_locations) ) | ||
in | ||
|
@@ -561,9 +558,9 @@ struct | |
|
||
module For_testing = struct | ||
let location_in_mask t location = | ||
Option.is_some (find_account t location) | ||
Option.is_some (self_find_account t location) | ||
|
||
let address_in_mask t addr = Option.is_some (find_hash t addr) | ||
let address_in_mask t addr = Option.is_some (self_find_hash t addr) | ||
|
||
let current_location t = t.current_location | ||
end | ||
|
@@ -582,7 +579,7 @@ struct | |
(* NB: updates the mutable current_location field in t *) | ||
let get_or_create_account t key account = | ||
assert_is_attached t ; | ||
match find_location t key with | ||
match self_find_location t key with | ||
| None -> ( | ||
(* not in mask, maybe in parent *) | ||
match Base.location_of_key (get_parent t) key with | ||
|
@@ -598,7 +595,7 @@ struct | |
| None -> Or_error.error_string "Db_error.Out_of_leaves" | ||
| Some location -> | ||
set t location account ; | ||
set_location t key location ; | ||
self_set_location t key location ; | ||
t.current_location <- Some location ; | ||
Ok (`Added, location) ) ) | ||
| Some location -> Ok (`Existed, location) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should the different balances be mentioned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. I've clarified the string a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's some leftover text in the string