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

syscall.move() to transfer ownership of kernel objects #1692

Open
warner opened this issue Sep 4, 2020 · 1 comment
Open

syscall.move() to transfer ownership of kernel objects #1692

warner opened this issue Sep 4, 2020 · 1 comment
Labels
enhancement New feature or request SwingSet package: SwingSet

Comments

@warner
Copy link
Member

warner commented Sep 4, 2020

What is the Problem Being Solved?

System upgrades might need to move references from one old vat to some new vat (created during the upgrade process). This would be a path-shortening operation, causing clients to point directly at the new vat, rather than going through the old one. This should allow the old vat to be deleted when the upgrade is complete.

Suppose that we start with one vat hosting a simple Mint for some sort of token. During the early stages of the chain, it makes a bunch of Purses, which are referenced by various other vats (many of which might be off-chain, so really the comms vat owns them all). But in version 2, we want something more sophisticated, and we want those Purses to be owned by something else. Maybe we had two separate vats and we want their Mints to be colocated for some synchronous purpose.

The protocol described in #1691 can change the behavior of a vat, but doesn't change the shape of the reference graph. We can't easily convince all Purse holders to replace their object reference with a different one. But we can arrange for their existing reference to point to something different.

Description of the Design

A new syscall.move operation would modify the kernel object table, to change the owner of a given kernel object. It would also update the c-lists to basically merge two objects together.

Suppose the simple Mint in vat-old has exported object o+3 and the kernel assigned this reference ko3. Some user code in vat-client has imported ko3 as o-6. The kernel remembers that ko3 is owned by vat-old, so that any messages sent to ko3 will be delivered to vat-old.

Now the cutover code in vat-old iterates through all the old Purses, finds their balance, and sends a message to vat-new to create a new Purse with an equivalent value. The new vat exports o+4 for the new Purse, and the kernel assigns ko4. The result gets back to vat-old, adding ko4 to the c-list. At this point, the tables are:

  • vat-old clist: o+3 <-> ko3, o-7 <-> ko4
  • vat-client clist: o-6 <-> ko3
  • vat-new clist: o+4 <-> ko4
  • kernel object-owner table: ko3 -> vat-old, ko4 -> vat-new

Now we want vat-client to point at the new purse instead of the old one. vat-old will call syscall.move(o+3, o-7), to tell the kernel "please forward any ko3 message to ko4 instead". The kernel updates the object table to make ko3 owned by vat-new instead of vat-old. And it changes vat-new's clist to replace o+4 <-> ko4 with o+4 <-> ko3. vat-old's clist is changed to remove the object export, and change the target of the import.

The new tables are:

  • vat-old clist: o-7 <-> ko3
  • vat-client clist: o-6 <-> ko3
  • vat-new clist: o+4 <-> ko3
  • kernel object-owner table: ko3 -> vat-new

Security Considerations

Clearly we need to think through the authorities involved to make sure we're not enabling vats to create mayhem. vat-old has every right to make ko3 behave as it pleases, and to send arbitrary messages to ko4. syscall.move should be indistinguishable from having vat-old simply forward all messages to ko4 in vat-new (except that it should be more efficient, and allow vat-old to be deleted).

Once we change the owner table, we must make sure vat-new can handle the messages coming its way. Adding the new name to the c-list provides this, but we can't have two kernel-side names (ko3 and ko4) associated with the same vat-side name (o+4), because then we don't know which one to use when converting outbound references made by vat-new. The biggest authority question is why vat-old should be allowed to remove the old name from vat-new's c-list.

Closely related is what to do about any other vats which might have a reference to ko4. Perhaps vat-new should somehow mark it's o+4 export as "intended for transfer", which would 1: allow vat-old to change its c-list, and 2: prohibit vat-old from sharing the reference with anybody else. I'm looking for something to achieve an exclusive transfer. As @FUDCo pointed out, this is suspiciously similar to the property that ERTP offers on top of plain Purses, which might suggest a source of inspiration. Maybe some kernel-side Payment-like protocol to exclusively transfer ownership of an object reference.

@warner
Copy link
Member Author

warner commented Sep 8, 2020

I thought of another use for this, in a simpler form that could maybe be called syscall.rename(old, new). Suppose we needed to upgrade a "large" vat (say a Mint that exports lots of Purses) from the early kind that uses distinct o+NN references for each exported object (which all live in RAM), to a newer kind that uses hierarchical o+NN.NN references (and keeps the state in secondary storage rather than RAM). The "sleeper agent" upgrade code would create a Set or Array of all the Purses so it could enumerate them. Then the activation step wants to move the state from RAM to secondary storage, and rename the o+NN reference with a new o+NN.NN one.

The transition doesn't affect the kernel's koNN reference for the Purse, nor does it change any of the client vats (they still have some o-NN import reference in their c-lists, mapping to the koNN identifier). But the Mint vat wants to change its own clist: where it used to map koNN <-> o+NN, now it wants to have koNN <-> o+NN.NN. After this change, the vat's liveslots layer no longer needs to remember a separate table entry for every Purse: instead, it only remembers the o+NN. prefix, and fetches the individual Purse data on demand.

The last step of this transition is to ask the kernel to change the c-list entry, by invoking syscall.rename('o+NN', 'o+NN.NN').

This would be a simpler (less authority-interesting) form of syscall.move, because there's only one vat involved. Also, since it only affects an export of the vat calling it, it's a linear transformation: we start with one export, and we finish with one export. The more general syscall.move is really merging two values (one export, one import) into a single import, but also changes the source vat's c-list in a way that requires attention to the authority involved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request SwingSet package: SwingSet
Projects
None yet
Development

No branches or pull requests

2 participants