-
Notifications
You must be signed in to change notification settings - Fork 11.3k
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
[sui-adapter][sui-framework] Add child_count to Move objects #3730
Conversation
tnowacki
commented
Aug 3, 2022
•
edited
Loading
edited
- Added a count of children to objects
- The count is incremented/decremented in the adapter when children are added, transferred away, or deleted
- The count must be zero when an object is deleted, frozen, or wrapped
- Wrapped objects with children cannot be supported without adding the child count to the parent_sync. @lxfind seemed unsure if this was a wise idea
- We can always come back and do that later if we want to
1183fcb
to
84f755b
Compare
@@ -26,7 +26,7 @@ module sui::transfer { | |||
/// module. The object's module can expose a function that returns a reference to the object's | |||
/// UID, `&UID`. Which can then be used with this function. | |||
/// The child object is specified in `obj`, and the parent object id is specified in `owner_id`. | |||
public fun transfer_to_object_id<T: key>(obj: T, owner_id: &UID) { | |||
public fun transfer_to_object_id<T: key>(obj: T, owner_id: &mut UID) { |
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.
Why mut here (doc needs to be updated, and worth explaining there too)?
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.
Sure I can update the doc here, but it makes it easier to block immutable objects from adding children
state_view.log_event(Event::delete_object( | ||
module_id.address(), | ||
module_id.name(), | ||
ctx.sender(), | ||
*obj_id, | ||
)); | ||
state_view.delete_object(obj_id, version, DeleteKind::Normal) | ||
if let Owner::ObjectOwner(parent_id) = owner { | ||
let delta = child_count_deltas.entry(parent_id.into()).or_insert(0); |
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.
Does 0 defaults to i64? Might be worth annotating the type of child_count_deltas
just to make sure we don't accidentally break the type
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.
I added an annotation. Just very nervous about or_default
in general. But I can switch to that if you think it makes it more clear
state_view.log_event(Event::delete_object( | ||
module_id.address(), | ||
module_id.name(), | ||
ctx.sender(), | ||
*obj_id, | ||
)); | ||
state_view.delete_object(obj_id, version, DeleteKind::Normal) | ||
if let Owner::ObjectOwner(parent_id) = owner { |
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.
Why don't we check here whether the object to be deleted has 0 child at this point? Wonder if that would simplify things (always check child count at deletion point)
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.
We might not have processed the children yet. It is so you can delete all children and all parents in the same txn.
We could instead process the transfers children-first, but it would require some sorting here
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.
Shouldn't the events be processed in the order they are created?
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.
Do we want to enforce that the parents must be deleted exactly before the children? It feels like an unnecessary footgun. Especially when a lot of this complexity is still needed for dealing with wrapped objects.
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.
Did you mean "the parents must be deleted after all the children were deleted"?
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.
yes, sorry
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.
That seems a reasonable requirement?
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.
First, it doesn't make the code any easier. As we only know if an object has been wrapped at the end. So this code won't get get any less complex.
Second, I don't think it is a great requirement, because there is nothing in the Move layer that indicates you will bump into this. We have the ability to easily make people's lives easier without changing the complexity of the code, so why not?
let mut object = self.objects[id].clone(); | ||
// Active input object must be Move object. | ||
object.data.try_as_move_mut().unwrap().increment_version(); | ||
self.written.insert(*id, object); |
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.
I don't quite understand this.
btw any object update now must be done through self.write_object() to make sure previous transaction is updated.
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.
I can try to do that. But it is just trying to mark the object as written if the child_count has changed
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.
Changed this a bit, but I'm still manually inspecting the _written map
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.
hmm actually, this may be an issue. So some objects may get to be written twiece
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.
I'm not sure I understand the concern
} | ||
} | ||
for (id, delta) in deltas { | ||
match (self.written.get_mut(&id), self.deleted.get_mut(&id)) { |
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.
Having trouble wrapping my head around this match, some comments would help
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.
Added comments
84f755b
to
0492ef2
Compare
0492ef2
to
6b5c746
Compare
32a3aca
to
d48adbe
Compare
- Added a count of children to objects - The count is incremented/decremented in the adapter when children are added, transferred away, or deleted - The count must be zero when an object is deleted, frozen, or wrapped
d48adbe
to
a500e39
Compare