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

vat upgrade by replacing virtual-object behavior record #3062

Closed
warner opened this issue May 10, 2021 · 6 comments
Closed

vat upgrade by replacing virtual-object behavior record #3062

warner opened this issue May 10, 2021 · 6 comments
Assignees
Labels
enhancement New feature or request SwingSet package: SwingSet
Milestone

Comments

@warner
Copy link
Member

warner commented May 10, 2021

What is the Problem Being Solved?

@dtribble and I were brainstorming about upgrade pathways. I'm thinking of a taxonomy of upgrades, rated by depth/intricacy:

  1. changing a parameter, like an interest rate, or interval duration
  2. changing the behavior of some pure function in userspace vat code
  3. changing the behavior of data/reference-bearing userspace vat code (retaining the old data, but changing the code that runs against it)
  4. changing liveslots
  5. changing the kernel

The first two can be accomplished by having some object in the vat code which knows the interest rate or function in question. Operations ask it for the rate every time, or the submit data to the function and get something back. The vat code which initially creates this will create a special facet that allows the value to be changed, and it will give this facet to a governance contract. A governance decision (using whatever voting mechanism that other contract cares for) can invoke the facet and give it a new number, or a new bundle of code to evaluate and overwrite the old function.

But the third one is interesting. As an example, think about an Issuer which has some (large) number of outstanding Purses, Payments, and DepositFacets. We want to change the implementation, but retain the validity of all those exported objects.

Description of the Design

@dtribble 's idea was to lean on the fact that we're representing all of those things as virtual objects. Each call to makeKind() is effectively creating a table, and providing both a behavior record and a function to create new rows. We'll need to give a name to each table: perhaps we add a name argument to makeKind and we throw an error if it is not unique.

Now, the upgraded vat wants to connect new behavior to the old records. So imagine a vatPowers.replaceKind(name, behavior, initFunction) that does mostly the same thing as makeKind but instead of allocating a new table, it re-uses an old one. We might add arguments which let the upgraded code know when it's being given an old record (maybe a version number along with each state object), so it can react differently to the old data.

To trigger this upgrade, we might use the vatAdmin facet and add a method which behaves like the "spawn zygote vat" API (#2268), except that it takes a new vat code bundle. When invoked, a new vatID is created, all the virtual-object exports of the old vat are re-targeted to point at the new one, all the non-virtual-object exports are left on the old vat, and the old vat is terminated. This would retain the identity of things which we can't carry over, they'd just be dead references (like exports of a terminated vat).

For non-virtual exports that need to be retained, we could introduce a way to assign labels to certain exports (vatPowers.nameExport('name', remotable)), and then the new vat code could claim those exports (vatPowers.reconnectOldExport('name', newRemotable)). We'd use this for contract entrypoints and root objects, things which are widely referenced singletons that aren't suitable for making into virtual objects. This might look a little bit like the #1692 "move" API.

Security Considerations

We need to be super-careful about the authority patterns here. Arbitrary vat code should not be able to steal control over tables or previously-exported objects, so putting these powers on vatPowers (vs makeKind, which is ambient) makes it easier to the upgraded vat code to limit access.

@warner warner added enhancement New feature or request SwingSet package: SwingSet labels May 10, 2021
@dckc
Copy link
Member

dckc commented Jul 21, 2021

Some version of upgrade is in the treasury launch critical path; this is the closest I can find.

@dckc dckc added this to the Mainnet: Phase 1 - Treasury Launch milestone Jul 21, 2021
@warner
Copy link
Member Author

warner commented Sep 16, 2021

In today's kernel meeting we walked through some possibilities for upgrading the Treasury to fix a hypothetical bug in which some vaults ceased to allow close operations. In one approach, we declared that all upgradeable objects must be virtual. This gives us a principled way for the successor vat to provide replacement behavioral code for the predecessors exported objects (which the successor must honor, or revoke). In this case, we'd use virtual objects for low-cardinality (even singleton) objects too, not just for high-cardinality things. The predecessor must prepare for upgrade by registering each makeKind category with a name; the successor would use their super-upgrade-power object to supply a replacement kind constructor for each named entry. I'm thinking that the successor would call some sort of finishedUpgrade() method when they're done with the registration, and any remaining kinds would have their exported objects enumerated and revoked (somehow).

In this approach, any Remotables (other than the root object) cannot be replaced, since they aren't registered. I think it would be useful to be able to register and replace such Remotables, not just virtual objects, but I think @erights or @dtribble was keen on restricting that ability to virtual objects.. we need to discuss it more.

@erights
Copy link
Member

erights commented Sep 30, 2021

I think @erights or @dtribble was keen on restricting that ability to virtual objects.. we need to discuss it more.

As Norm says, there's always a bigger hammer. I'm keen on having a small well behaved hammer adequate for many "normal" upgrades, where we stay within the computational model, and the programmer intention on each side of the temporal boundary: The early programmer who prepares their contract's estates, keeps their affairs and will in order, so on the event of its sudden death, that estate is supposed to be adequate for the heir to pick up that state and resume operation. If we give the heir too much power to maybe potentially reconstruct from additional stuff that's lying around and may be helpful, the ancestor may be too willing to assume that the heir will find some way to cope.

The next bigger hammer is when the ancestor, whether they made a good try or not, has failed to prepare an estate adequate for the heir to resume operation. The heir now has an emergency. We should find ways to help it cope with that emergency. But it is not the normal orderly transfer of operation.

As we dive into the patterns and stores stuff, I'll explain the further distinction I think necessary between "virtual ephemeral" and "virtual persistent". Everything in the intended estate, to be communicated intentionally from ancestor to heir, must not only be virtual. It must be virtual persistent. The key difference is that non-virtual (and therefore necessarily ephemeral) things can be reached from virtual ephemeral. But with few exceptions, everything reachable from virtual persistent must not be local-non-virtual. It must be state that survives the ancestor's sudden death.

@Tartuffo
Copy link
Contributor

@warner to refine the ticket.

@Tartuffo Tartuffo assigned warner and unassigned warner Jan 27, 2022
@Tartuffo Tartuffo added MN-1 and removed MN-1 labels Feb 2, 2022
@Tartuffo Tartuffo removed this from the Mainnet: Phase 1 - RUN Protocol milestone Feb 8, 2022
@warner warner removed their assignment Feb 22, 2022
FUDCo added a commit that referenced this issue Mar 19, 2022
This implements the primary vat-side interface for upgrade (#4325, #4382).
However, it does not yet implement the set of post upgrade checks (#3062) that
will be required (e.g., check upon return from `buildRootObject` to verify that
all the durable kinds have had behavior associated with them or have been
explicitly dismissed); the ability to test or otherwise exercise the latter
portion of the upgrade machinery will have to wait until the kernel-side
interfaces (#1848, #3062) are in place.

I am going to tentative declarely that this PR closes #4325, leaving the
remaining work to be covered by #3062.
FUDCo added a commit that referenced this issue Mar 20, 2022
This implements the primary vat-side interface for upgrade (#4325, #4382).
However, it does not yet implement the set of post upgrade checks (#3062) that
will be required (e.g., check upon return from `buildRootObject` to verify that
all the durable kinds have had behavior associated with them or have been
explicitly dismissed); the ability to test or otherwise exercise the latter
portion of the upgrade machinery will have to wait until the kernel-side
interfaces (#1848, #3062) are in place.

I am going to tentative declarely that this PR closes #4325, leaving the
remaining work to be covered by #3062.
FUDCo added a commit that referenced this issue Mar 21, 2022
This implements the primary vat-side interface for upgrade (#4325, #4382).
However, it does not yet implement the set of post upgrade checks (#3062) that
will be required (e.g., check upon return from `buildRootObject` to verify that
all the durable kinds have had behavior associated with them or have been
explicitly dismissed); the ability to test or otherwise exercise the latter
portion of the upgrade machinery will have to wait until the kernel-side
interfaces (#1848, #3062) are in place.

I am going to tentative declarely that this PR closes #4325, leaving the
remaining work to be covered by #3062.
@Tartuffo Tartuffo added this to the Mainnet 1 milestone Mar 23, 2022
@Tartuffo Tartuffo modified the milestones: Mainnet 1, RUN Protocol RC0 Apr 5, 2022
@Tartuffo Tartuffo modified the milestones: RUN Protocol RC0, Mainnet 1 Apr 6, 2022
@FUDCo
Copy link
Contributor

FUDCo commented Apr 26, 2022

@warner Given #4873 and #4962 (and their antecedents) can we mark this as closed?

@FUDCo
Copy link
Contributor

FUDCo commented Apr 29, 2022

Accomplished via #4873 and #4962. Closing.

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

5 participants