sui icon indicating copy to clipboard operation
sui copied to clipboard

Support quasi-shared objects

Open lxfind opened this issue 3 years ago • 10 comments
trafficstars

This PR adds explicit support for special treating child objects of shared objects. I like the name that @gdanezis came up with in the meeting: quasi-shared object, which is shorter than effectively shared object.

The core of the PR is rather simple:

  1. Add a new argument type to indicate an object argument is a quasi-shared object
  2. When checking the transaction validity, we make sure that such object is indeed owned (either directly or indirectly) by a shared object.
  3. In transaction processing, we treat quasi-shared object the same way as shared object: no owned tx lock, is included in shared object ids of the tx and etc.

Some mechanical changes done in this PR:

  1. Some refactoring on the test utils to make it easier to write more tests around this
  2. Added a new struct InputObjects to wrap around a few common functions related to the inputs

TODO: Two things that I will be continue doing in this PR:

  1. Add more tests, to cover all kinds of strange cases (e.g. when the object is in different state in different validators).
  2. Add support on the gateway so that one can actually construct such transaction

Sending out early to get feedback.

This fixes https://github.com/MystenLabs/sui/issues/2417

lxfind avatar Jun 07 '22 23:06 lxfind

Here is a corner case, that worries me:

  • Say we have a quasi-shared object X owned by shared object S.
  • We make a transaction T1 that includes a coin Y, as well as S and X.
  • We send the transaction to all validators and get a certificate C1 on it.
  • But, just before someone else processes a transaction T2, on S and X, that transfers X to someone else. So now it is not owned any more.
  • Now validator V1 processes C1 -- I presume the outcome of the transaction is Abort.
  • Then the new owner of X transfers it, with T3, back to be owned by object S! (This is an owned objct transaction it is async in relation to consensus)
  • Now validator V2 processes C1 -- the object X is owned by S, and say the outcome is Success. We have V1 and V2 -- both honest -- in a conflicting state.

The sequence of transactions was: V1 : T2, T1, T3 V2: T2, T3, T1 I think both sequences are valid, and are different because T3 can happen either before or after T1

gdanezis avatar Jun 08 '22 09:06 gdanezis

Some follow-up thoughts:

  • I think that to ensure clear invariant it is easier for an owned object to be an owned object or quasi-owned object, and for shared objects to be shared or quasi-shared for ever.
  • This means we do not promote an object from owned to shared, or from shared to owned.
  • However, I think we are ok with wrapping objects into other objects: so I think it is safe to (1) create a fresh shared object, (2) wrap the owned object into the shared object, and then eventually (3) unwrap the object from the fresh shared object back into an owned object (with the same ID and bumped version number).
  • Why is the above safe? Because changing the ownership of an object to be quasi-shared requires including a shared object for mutation, which sequences this transaction in relation to all other shared object transactions. Same for unwrapping.

gdanezis avatar Jun 08 '22 09:06 gdanezis

  • Then the new owner of X transfers it, with T3, back to be owned by object S! (This is an owned objct transaction it is async in relation to consensus)

I think this is incorrect. To transfer an object to S, S must be passed as a parameter. Since it's a shared object, this transaction must go through consensus, and hence the order of T3 in relative to T1 must be consistent across validators.

lxfind avatar Jun 08 '22 14:06 lxfind

To transfer an object to S, S must be passed as a parameter.

Aha, I was missing this indeed. So to transfer an object's ownerwhip X to another object Y, both X and Y need to be locked, right? Need to re-reflect then, but for sure this removes some of the issues.

gdanezis avatar Jun 08 '22 15:06 gdanezis

Aha, I was missing this indeed. So to transfer an object's ownerwhip X to another object Y, both X and Y need to be locked, right? Need to re-reflect then, but for sure this removes some of the issues.

Correct! I haven't been able to construct a bad case, but I will definitely explore various examples in the test

lxfind avatar Jun 08 '22 15:06 lxfind

So I have a followup question: For the case where both X and Y are owned objects, is it also the case a transaction that assigns ownership of Y to X also takes both X and Y as inputs?

gdanezis avatar Jun 08 '22 17:06 gdanezis

So I have a followup question: For the case where both X and Y are owned objects, is it also the case a transaction that assigns ownership of Y to X also takes both X and Y as inputs?

Yes.

For more context, the reason this is true is that the API for transferring a child object to a parent requires a mutable reference to the parent.

We have been considering more permissive API's like transfer_child_to_id<T>(child: T, id: ID) that would violate your property. But it sounds like there may be compelling reasons not to do this...

sblackshear avatar Jun 08 '22 17:06 sblackshear

For more context, the reason this is true is that the API for transferring a child object to a parent requires a mutable reference to the parent.

Just want to clarify the above statement a bit, the emphasis in on the "reference to the parent", not on "mutable", i.e. even if the API takes a read-only reference to the parent, the parent still need to be in the input.

lxfind avatar Jun 08 '22 18:06 lxfind

Ah so to support quasi-shared object properly, we need to first support deleting shared objects. Deleting a quasi-shared object is basically the same thing as deleting a shared object. I will put this on-hold and wait for shared object deletion support first.

lxfind avatar Jun 09 '22 23:06 lxfind

Ah so to support quasi-shared object properly, we need to first support deleting shared objects. Deleting a quasi-shared object is basically the same thing as deleting a shared object. I will put this on-hold and wait for shared object deletion support first.

https://github.com/MystenLabs/sui/pull/2508#pullrequestreview-1002057257

asonnino avatar Jun 09 '22 23:06 asonnino

No longer need this. We will explore the dynamic child object loading path.

lxfind avatar Aug 31 '22 17:08 lxfind