Skip to content

Commit

Permalink
fix: start on zonifying ertp
Browse files Browse the repository at this point in the history
  • Loading branch information
erights committed Feb 20, 2024
1 parent 34ee0b7 commit 947c222
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 49 deletions.
1 change: 1 addition & 0 deletions packages/ERTP/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@agoric/notifier": "^0.6.2",
"@agoric/store": "^0.9.2",
"@agoric/vat-data": "^0.5.2",
"@agoric/zone": "^0.2.2",
"@endo/eventual-send": "^1.1.0",
"@endo/far": "^1.0.2",
"@endo/marshal": "^1.1.0",
Expand Down
14 changes: 9 additions & 5 deletions packages/ERTP/src/issuerKit.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { assert } from '@agoric/assert';
import { assertPattern } from '@agoric/store';
import { makeScalarBigMapStore } from '@agoric/vat-data';
import { makeDurableZone } from '@agoric/zone/durable.js';

import { AssetKind, assertAssetKind } from './amountMath.js';
import { coerceDisplayInfo } from './displayInfo.js';
Expand All @@ -13,6 +14,7 @@ import './types-ambient.js';
// TODO Why does TypeScript lose the `MapStore` typing of `Baggage` here, even
// though it knows the correct type at the exporting `@agoric/vat-data`
/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
/** @typedef {import('@agoric/zone').Zone} Zone */

/**
* @template {AssetKind} K
Expand All @@ -28,7 +30,7 @@ import './types-ambient.js';
*
* @template {AssetKind} K
* @param {IssuerRecord<K>} issuerRecord
* @param {Baggage} issuerBaggage
* @param {Zone} issuerZone
* @param {ShutdownWithFailure} [optShutdownWithFailure] If this issuer fails in
* the middle of an atomic action (which btw should never happen), it
* potentially leaves its ledger in a corrupted state. If this function was
Expand All @@ -40,7 +42,7 @@ import './types-ambient.js';
*/
const setupIssuerKit = (
{ name, assetKind, displayInfo, elementShape },
issuerBaggage,
issuerZone,
optShutdownWithFailure = undefined,
) => {
assert.typeof(name, 'string');
Expand All @@ -60,7 +62,7 @@ const setupIssuerKit = (
/** @type {PaymentLedger<K>} */
// @ts-expect-error could be instantiated with different subtype of AssetKind
const { issuer, mint, brand, mintRecoveryPurse } = preparePaymentLedger(
issuerBaggage,
issuerZone,
name,
assetKind,
cleanDisplayInfo,
Expand Down Expand Up @@ -101,7 +103,8 @@ export const upgradeIssuerKit = (
optShutdownWithFailure = undefined,
) => {
const issuerRecord = issuerBaggage.get(INSTANCE_KEY);
return setupIssuerKit(issuerRecord, issuerBaggage, optShutdownWithFailure);
const issuerZone = makeDurableZone(issuerBaggage);
return setupIssuerKit(issuerRecord, issuerZone, optShutdownWithFailure);
};
harden(upgradeIssuerKit);

Expand Down Expand Up @@ -167,7 +170,8 @@ export const makeDurableIssuerKit = (
) => {
const issuerData = harden({ name, assetKind, displayInfo, elementShape });
issuerBaggage.init(INSTANCE_KEY, issuerData);
return setupIssuerKit(issuerData, issuerBaggage, optShutdownWithFailure);
const issuerZone = makeDurableZone(issuerBaggage);
return setupIssuerKit(issuerData, issuerZone, optShutdownWithFailure);
};
harden(makeDurableIssuerKit);

Expand Down
10 changes: 4 additions & 6 deletions packages/ERTP/src/payment.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
// @jessie-check

import { initEmpty } from '@agoric/store';
import { prepareExoClass } from '@agoric/vat-data';

/** @typedef {import('@endo/patterns').MethodGuard} MethodGuard */
/**
* @template {Record<string | symbol, MethodGuard>} [T=Record<string | symbol, MethodGuard>]
* @typedef {import('@endo/patterns').InterfaceGuard<T>} InterfaceGuard
*/
/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
/** @typedef {import('@agoric/zone').Zone} Zone */

/**
* @template {AssetKind} K
* @param {Baggage} issuerBaggage
* @param {Zone} issuerZone
* @param {string} name
* @param {Brand<K>} brand
* @param {InterfaceGuard} PaymentI
* @returns {() => Payment<K>}
*/
export const preparePaymentKind = (issuerBaggage, name, brand, PaymentI) => {
const makePayment = prepareExoClass(
issuerBaggage,
export const preparePaymentKind = (issuerZone, name, brand, PaymentI) => {
const makePayment = issuerZone.exoClass(
`${name} payment`,
PaymentI,
initEmpty,
Expand Down
64 changes: 35 additions & 29 deletions packages/ERTP/src/paymentLedger.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
/* eslint-disable no-use-before-define */
import { isPromise } from '@endo/promise-kit';
import { mustMatch, M, keyEQ } from '@agoric/store';
import {
provideDurableWeakMapStore,
prepareExo,
provide,
} from '@agoric/vat-data';
import { AmountMath } from './amountMath.js';
import { preparePaymentKind } from './payment.js';
import { preparePurseKind } from './purse.js';

import '@agoric/store/exported.js';
import { BrandI, makeIssuerInterfaces } from './typeGuards.js';

/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
/** @typedef {import('@agoric/zone').Zone} Zone */

const { details: X, quote: q, Fail } = assert;

Expand Down Expand Up @@ -74,7 +69,7 @@ const amountShapeFromElementShape = (brand, assetKind, elementShape) => {
* minting and transfer authority originates here.
*
* @template {AssetKind} K
* @param {Baggage} issuerBaggage
* @param {Zone} issuerZone
* @param {string} name
* @param {K} assetKind
* @param {DisplayInfo<K>} displayInfo
Expand All @@ -83,16 +78,20 @@ const amountShapeFromElementShape = (brand, assetKind, elementShape) => {
* @returns {PaymentLedger<K>}
*/
export const preparePaymentLedger = (
issuerBaggage,
issuerZone,
name,
assetKind,
displayInfo,
elementShape,
optShutdownWithFailure = undefined,
) => {
/** @type {Brand<K>} */
// @ts-expect-error XXX callWhen
const brand = prepareExo(issuerBaggage, `${name} brand`, BrandI, {
// Should be
// at-ts-expect-error XXX callWhen
// but ran into the usual disagreement between local lint and CI
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
const brand = issuerZone.exo(`${name} brand`, BrandI, {
isMyIssuer(allegedIssuer) {
// BrandI delays calling this method until `allegedIssuer` is a Remotable
return allegedIssuer === issuer;
Expand Down Expand Up @@ -121,7 +120,7 @@ export const preparePaymentLedger = (
amountShape,
);

const makePayment = preparePaymentKind(issuerBaggage, name, brand, PaymentI);
const makePayment = preparePaymentKind(issuerZone, name, brand, PaymentI);

/** @type {ShutdownWithFailure} */
const shutdownLedgerWithFailure = reason => {
Expand All @@ -139,11 +138,9 @@ export const preparePaymentLedger = (
};

/** @type {WeakMapStore<Payment, Amount>} */
const paymentLedger = provideDurableWeakMapStore(
issuerBaggage,
'paymentLedger',
{ valueShape: amountShape },
);
const paymentLedger = issuerZone.weakMapStore('paymentLedger', {
valueShape: amountShape,
});

/**
* A withdrawn live payment is associated with the recovery set of the purse
Expand All @@ -164,10 +161,7 @@ export const preparePaymentLedger = (
*
* @type {WeakMapStore<Payment, SetStore<Payment>>}
*/
const paymentRecoverySets = provideDurableWeakMapStore(
issuerBaggage,
'paymentRecoverySets',
);
const paymentRecoverySets = issuerZone.weakMapStore('paymentRecoverySets');

/**
* To maintain the invariants listed in the `paymentRecoverySets` comment,
Expand Down Expand Up @@ -293,7 +287,7 @@ export const preparePaymentLedger = (
/** @type {() => Purse<K>} */
// @ts-expect-error type parameter confusion
const makeEmptyPurse = preparePurseKind(
issuerBaggage,
issuerZone,
name,
assetKind,
brand,
Expand All @@ -305,8 +299,12 @@ export const preparePaymentLedger = (
);

/** @type {Issuer<K>} */
// @ts-expect-error cast due to callWhen discrepancy
const issuer = prepareExo(issuerBaggage, `${name} issuer`, IssuerI, {
// Should be
// at-ts-expect-error cast due to callWhen discrepancy
// but ran into the usual disagreement between local lint and CI
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
const issuer = issuerZone.exo(`${name} issuer`, IssuerI, {
getBrand() {
return brand;
},
Expand Down Expand Up @@ -359,20 +357,28 @@ export const preparePaymentLedger = (
* Because the `mintRecoveryPurse` is placed in baggage, even if the caller of
* `makeIssuerKit` drops it on the floor, it can still be recovered in an
* emergency upgrade.
*
* @type {Purse<K>}
*/
const mintRecoveryPurse = provide(issuerBaggage, 'mintRecoveryPurse', () =>
makeEmptyPurse(),
// Should be
// at-ts-expect-error checked cast
// but ran into the usual disagreement between local lint and IDE lint.
// Don't know yet about lint under CI.
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
const mintRecoveryPurse = /** @type {Purse<K>} */ (
issuerZone.makeOnce('mintRecoveryPurse', () => makeEmptyPurse())
);

/** @type {Mint<K>} */
const mint = prepareExo(issuerBaggage, `${name} mint`, MintI, {
const mint = issuerZone.exo(`${name} mint`, MintI, {
getIssuer() {
return issuer;
},
mintPayment(newAmount) {
// @ts-expect-error checked cast
// Should be
// at-ts-expect-error checked cast
// but ran into the usual disagreement between local lint and CI
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// @ts-ignore
newAmount = coerce(newAmount);
mustMatch(newAmount, amountShape, 'minted amount');
// `rawPayment` is not associated with any recovery set, and
Expand Down
15 changes: 6 additions & 9 deletions packages/ERTP/src/purse.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { M } from '@agoric/store';
import { prepareExoClassKit, makeScalarBigSetStore } from '@agoric/vat-data';
import { AmountMath } from './amountMath.js';
import { makeTransientNotifierKit } from './transientNotifier.js';
import { makeAmountStore } from './amountStore.js';

// TODO `InterfaceGuard` type parameter
/** @typedef {import('@endo/patterns').InterfaceGuard} InterfaceGuard */
/** @typedef {import('@agoric/vat-data').Baggage} Baggage */
/** @typedef {import('@agoric/zone').Zone} Zone */

const { Fail } = assert;

/**
* @param {Baggage} issuerBaggage
* @param {Zone} issuerZone
* @param {string} name
* @param {AssetKind} assetKind
* @param {Brand} brand
Expand All @@ -25,7 +24,7 @@ const { Fail } = assert;
* }} purseMethods
*/
export const preparePurseKind = (
issuerBaggage,
issuerZone,
name,
assetKind,
brand,
Expand All @@ -36,6 +35,7 @@ export const preparePurseKind = (

// Note: Virtual for high cardinality, but *not* durable, and so
// broken across an upgrade.
// TODO propagate zonifying to notifiers, maybe?
const { provideNotifier, update: updateBalance } = makeTransientNotifierKit();

// - This kind is a pair of purse and depositFacet that have a 1:1
Expand All @@ -45,17 +45,14 @@ export const preparePurseKind = (
// that created depositFacet as needed. But this approach ensures a constant
// identity for the facet and exercises the multi-faceted object style.
const { depositInternal, withdrawInternal } = purseMethods;
const makePurseKit = prepareExoClassKit(
issuerBaggage,
const makePurseKit = issuerZone.exoClassKit(
`${name} Purse`,
PurseIKit,
() => {
const currentBalance = AmountMath.makeEmpty(brand, assetKind);

/** @type {SetStore<Payment>} */
const recoverySet = makeScalarBigSetStore('recovery set', {
durable: true,
});
const recoverySet = issuerZone.detached().setStore('recovery set');

return {
currentBalance,
Expand Down

0 comments on commit 947c222

Please sign in to comment.