API for Upgradeable Zoe Contracts #5708
Replies: 1 comment 2 replies
-
Great start! Covers a lot of ground compactly. Altogether, I wonder if we should teach first only the I scanned our uses of the API and I think it fits this shift in perspective. All deviations that I found were making things durable but not reachably durable. Using only Some local comments:
Should be "that start with
Need to also say that the result of the thunk is stored in the baggage at that same key and returned, so the caller of the
The only special versions that provide durableKinds are vivifySomething.
I think it is more binary than this. Lexical variables for durable state are only a good choice when they are The offerHandler example should use vivifyKind rather than defineDurableKind, as the coveredCall-durable does. (I suspect this was snapshot from an earlier version of that code.) |
Beta Was this translation helpful? Give feedback.
-
An upgradeable Zoe contract has a
vivify
function instead of thestart
function. The first invocation ofvivify
, likestart
, must return at least one ofcreatorFacet
andpublicFacet
. (creatorInvitation
is deprecated; support will be dropped shortly.)The parameters for
vivify
andstart
arezcf
,privateArgs
, andbaggage
. The baggage should be used byvivify
(and can be used bystart
) to define kindHandles and durableKinds. The baggage instart
is there to allow the contract to save state that might be useful to a later version of the contract with avivify
function to be able to handle upgrade and restore the state. A contract with astart
function will not be used for upgrade.If the contract defines
vivify
, then on initial creation, it will get an empty baggage, and should callvivifyKind
(and similar functions) to define behavior.vivifyKind
and its siblings (see below) usemakeKindHandle
anddefineDurableKind
to declare kinds and associate behavior.vivifyKind
returns a maker function that is used to create new durable objects. Under upgrade, the samevivify
function will be called with the baggage containing the previously saved state. That invocation will retrieve the kindHandle that was previously associated with the name, and attach behavior to it.vivify
works in both scenarios because it uses functions likeprovide
. The most general version isprovide(baggage, identifier, thunk)
. If the identifier is not present in the baggage, the thunk is executed and its result is stored in the baggage at that key and returned. If the baggage has something stored under the identifier, then the previous value is retrieved. This combination means that the caller is insensitive to whether the provided thing is found or created.vivify
supplies new behavior that is attached to new or revived kinds.The
vivify
helpers bundle calls toprovideKindHandle
and the various forms ofdefineDurableKind
into simplervivifyDurableKind
variants:vivifyKind(baggage, kindName, init, methods, options)
vivifyKindMulti(baggage, kindName, init, behavior, options)
vivifySingleton(baggage, kindName, methods, options)
vivifyKind
wrapsdefineDurableKind
, which takes amethods
parameter that describes a single facet. Methods is a record containing named functions that take a context parameter.vivifyKindMulti
wrapsdefineDurableKindMulti
, which takes a behavior that describes multiple facets.Behavior
is a record containing named records containing methods records.vivifySingleton
wrapsdefineDurableKind
, and passes an emptyinit
. The methods access the state via lexical enclosure. (When "singleton" objects have mutable state, we use one of thevivifyKind
variants instead, so "singleton" really means "stateless".) Theinit
functions take whatever parameter will be required to create instance state. The resulting constructor takes exactly the parameters of theinit
function.For readability, there's a trade-off between accessing persistent variables using a
state
parameter, or via lexical variables. Forconst
values , lexical variables are often more convenient. For anything that is mutable,state
is better. One consequence of these constraints is that local stores/collections (Maps, Sets, etc.) can be stored in baggage, and then the collection accessed lexically. We've also found a few variables that were defined usinglet
because they can't be set up in theinit
function. These have mostly been put instate
, with a@ts-expect-error
where they get initialized, so they can be visibly immutable elsewhere.Offer Handlers that should survive upgrade (not true of all Handlers!) need to be made durable. This should define a durable object with a
handle
method.Beta Was this translation helpful? Give feedback.
All reactions