Skip to content

Commit 44e1071

Browse files
authored
Merge pull request #1016 from Agoric/dc-vstorage-guide
docs: vstorage reference; chainStorage publishing guide
2 parents d495bc1 + 8c3dfaf commit 44e1071

File tree

5 files changed

+676
-95
lines changed

5 files changed

+676
-95
lines changed

main/guides/coreeval/permissions.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ export const main = startSellConcertTicketsContract;
3434

3535
In the top level promise space, we have:
3636

37-
- **agoricNames**: read-only access to the [agoricNames](../integration/name-services.md#agoricnames-agoricnamesadmin-well-known-names) name service.
37+
- **agoricNames**: read-only access to the [agoricNames](../integration/name-services#agoricnames-agoricnamesadmin-well-known-names) name service.
3838

39-
- **agoricNamesAdmin**: admin / update access to **agoricNames** and the name hubs it contains.
39+
- **agoricNamesAdmin**: admin / update access to [agoricNames](../integration/name-services#agoricnames-agoricnamesadmin-well-known-names) and the name hubs it contains.
40+
**Warning: this includes access to over-write existing bindings to instances, brands, etc.**
4041
**Warning: this includes the right to over-write existing bindings to instances, brands, etc.**
4142

4243
- **bankManager**: to manage reflection of cosmos
@@ -45,14 +46,14 @@ In the top level promise space, we have:
4546
- **board**: the [board](../integration/name-services.md#the-board-publishing-under-arbitrary-names) name service.
4647
**Note: the board only grows; no mechanism to reclaim storage has been established.**
4748

48-
- **chainStorage**: to make storage nodes to write to vstorage.
49-
**Warning: this includes the right to over-write previously allocated storage nodes.**
49+
- **chainStorage**: to make storage nodes to [write to vstorage](../zoe/pub-to-storage).
50+
**Warning: this includes access to over-write previously allocated storage nodes.**
5051

51-
- **chainTimerService**: for getting the current timer and setting timer wake-ups; for example, at the conclusion of a governance vote.
52-
**Note: this includes the right to schedule infinitely repeating events.**
52+
- **chainTimerService**: for getting the current [timer](../../reference/repl/timerServices) and setting timer wake-ups; for example, at the conclusion of a governance vote.
53+
**Note: this includes access to schedule infinitely repeating events.**
5354

5455
- **priceAuthority**: access to get price quotes and triggers; see [Price Authority Guide](../zoe/price-authority).
5556

5657
- **priceAuthorityAdmin**: access to add and replace sources of price quotes using [E(priceAuthorityAdmin).registerPriceAuthority()](../../reference/zoe-api/price-authority-admin#e-priceauthorityregistryadmin-registerpriceauthority-priceauthority-brandin-brandout-force)
5758

58-
- **zoe**: the Zoe service
59+
- **zoe**: the [Zoe service](../../reference/zoe-api//zoe)

main/guides/governance/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Adding parameter governance to a contract consists mainly of using `handleParamG
4646
We pass it `zcf` so that it can `getTerms()` for initial parameter values, and we
4747
pass `paramTypes` to specify governed parameters and their types. `initialPoserInvitation`
4848
is necessary to set up replacing the electorate. `storageNode` and `marshaller` are used
49-
to publish values of the parameters to vstorage.
49+
to [publish values of the parameters to vstorage](../zoe/pub-to-storage).
5050

5151
```js
5252
import { handleParamGovernance } from '@agoric/governance/src/contractHelper.js';

main/guides/zoe/pub-to-storage.md

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Publishing to chainStorage
2+
3+
Contracts can use [notifiers and subscriptions](../js-programming/notifiers)
4+
to publish to clients. To publish data visible to [vstorage queries](../getting-started/contract-rpc#querying-vstorage), contracts should connect
5+
a subscriber to a `chainStorage` node.
6+
7+
## Deployment Capabilities for Publishing to chainStorage
8+
9+
In [Adding Parameter Governance to a Contract](../governance/#adding-parameter-governance-to-a-contract),
10+
`storageNode` and `marshaller` are passed to the contract in its `privateArgs` so it can publish to chainStorage.
11+
12+
In [dapp-agoric-basics](https://github.com/Agoric/dapp-agoric-basics), the `startSwapContract` uses 2 [permitted deployment capabilities](../coreeval/permissions), `chainStorage` and `board` and uses them to make the `privateArgs`:
13+
14+
```js
15+
const marshaller = await E(board).getPublishingMarshaller();
16+
const storageNode = await E(chainStorage).makeChildNode(contractName);
17+
```
18+
19+
A `Marshaller` is parameterized by functions for mapping unforgeable object identities to plain data slot references and back. Using the [board](../integration/name-services#the-board-publishing-under-arbitrary-names) name service gives consistent slot references across contracts.
20+
As discussed in [Marshalling Amounts and Instances](../getting-started/contract-rpc#marshalling-amounts-and-instances), this lets
21+
off-chain clients use the same `@endo/marshal` API.
22+
23+
The `chainStorage` node corresponds to the `published` key in the
24+
[vstorage hierarchy](/reference/vstorage-ref).
25+
Using `E(chainStorage).makeChildNode(contractName)` gives the contract
26+
access to write to the `published.swaparoo` key and all keys under it.
27+
28+
The `swaparoo` contract delegates the rest of publishing governance parameters to the `@agoric/governance` package.
29+
30+
## Publishing structured data to chainStorage
31+
32+
Let's look at the Inter Protocol [assetReserve.js](https://github.com/Agoric/agoric-sdk/blob/agoric-upgrade-13/packages/inter-protocol/src/reserve/assetReserve.js) contract to get more of the details. It publishes to [published.reserve.metrics](https://github.com/Agoric/agoric-sdk/blob/agoric-upgrade-13/packages/inter-protocol/test/reserve/snapshots/test-reserve.js.md) data of the form
33+
34+
```js
35+
/**
36+
* @typedef {object} MetricsNotification
37+
* @property {AmountKeywordRecord} allocations
38+
* @property {Amount<'nat'>} shortfallBalance shortfall from liquidation that
39+
* has not yet been compensated.
40+
* @property {Amount<'nat'>} totalFeeMinted total Fee tokens minted to date
41+
* @property {Amount<'nat'>} totalFeeBurned total Fee tokens burned to date
42+
*/
43+
```
44+
45+
For example:
46+
47+
```js
48+
{
49+
allocations: {
50+
Fee: {
51+
brand: Object @Alleged: IST brand {},
52+
value: 64561373455n,
53+
},
54+
ATOM: {
55+
brand: Object @Alleged: ATOM brand {},
56+
value: 6587020n
57+
},
58+
},
59+
shortfallBalance: {
60+
brand: Object @Alleged: IST brand {},
61+
value: 5747205025n,
62+
},
63+
totalFeeBurned: {
64+
brand: Object @Alleged: IST brand {},
65+
value: n,
66+
},
67+
totalFeeMinted: {
68+
brand: Object @Alleged: IST brand {},
69+
value: 0n,
70+
},
71+
},
72+
```
73+
74+
The method that writes this data is:
75+
76+
```js
77+
writeMetrics() {
78+
const { state } = this;
79+
const metrics = harden({
80+
allocations: state.collateralSeat.getCurrentAllocation(),
81+
shortfallBalance: state.shortfallBalance,
82+
totalFeeMinted: state.totalFeeMinted,
83+
totalFeeBurned: state.totalFeeBurned,
84+
});
85+
void state.metricsKit.recorder.write(metrics);
86+
},
87+
```
88+
89+
The `metricsKit` is made with a `makeRecorderKit` function:
90+
91+
```js
92+
metricsKit: makeRecorderKit(
93+
metricsNode,
94+
/** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedMatcher<MetricsNotification>} */ (
95+
M.any()
96+
),
97+
),
98+
```
99+
100+
We "prepare" (in the [exo](https://endojs.github.io/endo/modules/_endo_exo.html) sense) that function for making
101+
a `RecorderKit` using [prepareRecorderKitMakers](/reference/zoe-api/zoe-helpers#preparerecorderkitmakers-baggage-marshaller).
102+
103+
```js
104+
const { makeRecorderKit } = prepareRecorderKitMakers(
105+
baggage,
106+
privateArgs.marshaller,
107+
);
108+
```
109+
110+
The contract gets `baggage`, along with `privateArgs` when it starts in
111+
[the usual way for upgradable contracts](./contract-upgrade.html#upgradable-declaration):
112+
113+
```js
114+
/**
115+
* Asset Reserve holds onto assets for the Inter Protocol, and ...
116+
*
117+
* @param {{
118+
* ...
119+
* marshaller: ERef<Marshaller>,
120+
* storageNode: ERef<StorageNode>,
121+
* }} privateArgs
122+
* @param {Baggage} baggage
123+
*/
124+
export const prepare = async (zcf, privateArgs, baggage) => {
125+
...
126+
};
127+
```
128+
129+
The reserve uses its `StorageNode` and makes a child to get `metricsNode`:
130+
131+
```js
132+
const metricsNode = await E(storageNode).makeChildNode('metrics');
133+
```
134+
135+
The `marshaller` is used to serialize data structures such as `MetricsNotification` above.
136+
137+
### Deployment Capabilities for the reserve
138+
139+
To start `assetReserve`, the [setupReserve](https://github.com/Agoric/agoric-sdk/blob/agoric-upgrade-13/packages/inter-protocol/src/proposals/econ-behaviors.js#L76) function again supplies
140+
the two relevant `privateArgs`, `marshaller` and `storageNode`:
141+
142+
```js
143+
const STORAGE_PATH = 'reserve';
144+
const storageNode = await E(storageNode).makeChildNode(STORAGE_PATH);
145+
const marshaller = await E(board).getReadonlyMarshaller();
146+
```
147+
148+
The `setupReserve` function gets `chainStorage` and `board` deployment capabilities passed in:
149+
150+
```js
151+
export const setupReserve = async ({
152+
consume: {
153+
board,
154+
chainStorage,
155+
...
156+
},
157+
...
158+
}) => { ... };
159+
```

0 commit comments

Comments
 (0)