Skip to content

Commit

Permalink
docs: add details on install handling when building proposals (#10177)
Browse files Browse the repository at this point in the history
## Description

Improve documentation on what happens with installations during proposal building.

### Security Considerations

clarity for the developers.

### Scaling Considerations

N/A

### Documentation Considerations

Adding to the API docs.

### Testing Considerations

None

### Upgrade Considerations

It's about upgrade, but doesn't need to be upgraded.
  • Loading branch information
Chris-Hibbert authored Oct 10, 2024
1 parent d0a9e65 commit b12a0f1
Showing 1 changed file with 77 additions and 84 deletions.
161 changes: 77 additions & 84 deletions packages/deploy-script-support/README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,100 @@
# Deploy Script Support

To install code on chain or in the a3p-integration environment, you'll have to
generate a proposal, and write a script to build the core proposal. The
proposals have limited access to bootstrap powers, described by their manifests.
write a script to build the core proposal. The proposals' access to bootstrap
powers is limited by their manifests.

There are collections of proposals in .../vats/src/proposals,
smart-wallet/src/proposals, orchestration/src/proposals, pegasus/src/proposals.
There are collections of proposals in /vats/src/proposals,
smart-wallet/src/proposals, orchestration/src/proposals, pegasus/src/proposals,
and inter-protocol/src/proposals.

The overall format is a proposalBuilder script (There are several in
.../builders/scripts/vats/) which has a default export that passes resources to
the proposal. The resources include bundled source code and string-value
parameters. The ProposalBuilder specifies (as an import string) the proposal
it uses, identifies the "manifest", (which associates permissions to access
powers in the bootstrap space with functions to be called), and builds bundles
of source code needed by the proposal.
parameters. The script exports a CoreEvalBuilder named `defaultProposalBuilder`
that specifies (as an import string) the proposal it uses, identifies the
"manifest", (which associates permissions to access powers in the bootstrap
space with functions to be called), and builds bundles of source code needed by
the proposal.

`.../builders/scripts/vats/upgradeVaults.js` is a canonical example. It says the
proposal to run is '@agoric/inter-protocol/src/proposals/upgrade-vaults.js',
lists the manifest there as `'getManifestForUpgradeVaults'`, and directs the
creation of a bundle from
'@agoric/inter-protocol/src/vaultFactory/vaultFactory.js', which will be made
available to the proposal as `vaultsRef` in options.
Here's a simple example:

`upgrade-vaults.js` defines `getManifestForUpgradeVaults()`, which returns a
`manifest` that says `upgradeVaults()` should be executed, and specifies what
powers it should have access to.

### Proposal

The proposal is called with `(powers, options)` available. The manifest
detailing the powers that will be used is usually in the same file, and
conventionally provided by a function named `getManifestForFoo`. The manifest
needs to have a unique name, since it will be referenced by name from the
script. The usual format is
```js
export const foo = async (
{
consume: {
...
},
brands: {
...
}
},
options,
) => {
const { fooRef } = options;
// do the things using powers and options
};

export const getManifestForFoo = (powers, options) => {
manifest: {
[foo.name]: {
consume: {
...
},
options,
)};
```
`manifest` contains descriptions of powers to be provided to the proposals.
**TODO** what happens with the `installations` in [`startPsm.js`](https://github.com/Agoric/agoric-sdk/blob/b13743a2cccf0cb63a412b54384435596d4e81ea/packages/inter-protocol/src/proposals/startPSM.js#L496)?
`options` allows the proposal to be provided with arbitray other powerful
objects.
### proposalBuilder Script
The script describes how to build the core proposal. For
`agoric-3-proposals` and uploading to the chain, the script must be named in the
`CoreProposalSteps` section in [`upgrade.go`](../../golang/cosmos/app/upgrade.go),
and its `defaultProposalBuilder` will be invoked directly.
Script files should export `defaultProposalBuilder` and a `default` function
that invokes `writeCoreProposal` one or more times to generate sets of files
describing the proposal.
```js
export const defaultProposalBuilder = ({ publishRef, install }) => {
/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */
const game1ProposalBuilder = async ({ publishRef, install }) => {
return harden({
sourceSpec: '@agoric/vats/src/proposals/foo.js',
sourceSpec: '@agoric/smart-wallet/test/start-game1-proposal.js',
getManifestCall: [
'getManifestForFoo',
getManifestForGame1.name,
{
fooRef: publishRef(install('@agoric/...')),
...otherParams,
game1Ref: publishRef(
install(
'@agoric/smart-wallet/test/gameAssetContract.js',
'../bundles/bundle-game1.js',
{ persist: true },
),
),
},
],
});
};
`
export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('proposalName', defaultProposalBuilder);
const { writeCoreEval } = await makeHelpers(homeP, endowments);
await writeCoreEval('start-game1', game1ProposalBuilder);
};
```

The first element of `getManifestCall` is interpreted as the name of a proposal.
The second element of `getManifestCall` produces the `options` argument passed
to the proposal. (`fooRef` in the example above). A common thing to want to pass
in options is a reference to code to be installed on-chain. The `fooRef` example
above shows how. `publishRef(install(<path>))` is built from sources in the
sdk, and passed as a `bundleRef`, which contains a `bundleID` suitable for
passing to Zoe (for contracts) or `vatAdminService` (for non-contract vat code).
The first element of `getManifestCall` is interpreted as the name of a function
defining a behavior. The second element of `getManifestCall` produces the
`options` argument passed to the function (`{ game1Red }` in the example
above). A common thing to want to pass in `options` is a reference to code to be
installed on-chain. The example above shows how. `publishRef(install(<path>))`
is built from sources in agoric-sdk, and passed as a `bundleRef`, which contains
a `bundleID` suitable for passing to Zoe (for contracts) or `vatAdminService`
(for non-contract vat code).

The CoreEvalBuilder says the proposal to run is
'@agoric/smart-wallet/test/start-game1-proposal.js'. It says the manifest can be
produced by running `getManifestForGame1`, and directs the creation of bundles
from `@agoric/smart-wallet/test/gameAssetContract.js` which will be made
available to the proposal as `game1Ref` in `options`.

The manifest gives permissions for accessing objects in promise space, and
passes installations to the proposalBuilder. Notice that `game1Ref` from the
proposalBuilder is passed to `getManifestForGame1`, which adds it to
`installations`, with the name `game1`. The name provided for installations will
also be used to register the installation in `agoricNames`.

```
export const getManifestForGame1 = ({ restoreRef }, { game1Ref }) => {
return harden({
manifest: gameManifest,
installations: {
game1: restoreRef(game1Ref),
},
});
};
```

### Invoking the coreEval Behavior

The proposalBuilder script's default export is responsible for calling
`writeCoreEval()` to produce the scripts that will be evaluated by the chain.
These define behavior functions that will be invoked based on the keys in the
manifest and passed arguments declared in the manifest. The manifest is usually
in the same file, and conventionally provided by a function named
`getManifestForFoo`. The manifest needs to have a unique name, since it will be
referenced by name from the script.

### proposalBuilder Script

The script describes how to build the core proposal. Script files should export
`defaultProposalBuilder` and a `default` function that invokes
`writeCoreProposal` one or more times to generate sets of files describing the
proposal.

Chain-halting SoftwareUpgrades can include coreEvals, by adding them to the
`CoreProposalSteps` section in [`upgrade.go`](../../golang/cosmos/app/upgrade.go). To execute a proposal via
CoreEval, follow [the instructions at
docs.agoric.com](https://docs.agoric.com/guides/coreeval/local-testnet.html).

0 comments on commit b12a0f1

Please sign in to comment.