Skip to content

Commit

Permalink
refactor: Durability for ERTP
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris-Hibbert authored and erights committed Jul 1, 2022
1 parent cafa284 commit d2ad04b
Show file tree
Hide file tree
Showing 32 changed files with 819 additions and 376 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/swingset-vat": "^0.28.0",
"@agoric/vat-data": "^0.3.1",
"@endo/eventual-send": "^0.15.5",
"@endo/far": "^0.2.5",
"@endo/marshal": "^0.6.9",
"@endo/promise-kit": "^0.2.43"
},
Expand Down
81 changes: 0 additions & 81 deletions packages/ERTP/src/brand.js

This file was deleted.

147 changes: 110 additions & 37 deletions packages/ERTP/src/issuerKit.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

import { assert } from '@agoric/assert';
import { assertPattern } from '@agoric/store';
import { makeScalarBigMapStore } from '@agoric/vat-data';

import { AssetKind, assertAssetKind } from './amountMath.js';
import { coerceDisplayInfo } from './displayInfo.js';
import { makeBrand } from './brand.js';
import { makePaymentLedger } from './paymentLedger.js';
import { makeDurablePaymentLedger } from './paymentLedger.js';

import './types.js';

Expand All @@ -24,32 +24,29 @@ import './types.js';
*
* `displayInfo` gives information to the UI on how to display the amount.
*
* @param {string} allegedName
* @param {K} [assetKind=AssetKind.NAT]
* @param {AdditionalDisplayInfo} [displayInfo={}]
* @param {MapStore<string,any>} issuerBaggage
* @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
* provided, then the failed atomic action will call it, so that some
* larger unit of computation, like the enclosing vat, can be shutdown
* before anything else is corrupted by that corrupted state.
* See https://github.com/Agoric/agoric-sdk/issues/3434
* @param {Partial<{elementSchema: Pattern}>} [options]
* @returns {{
* mint: Mint<K>,
* issuer: Issuer<K>,
* brand: Brand<K>,
* displayInfo: DisplayInfo,
* }}
*/
const makeIssuerKit = (
allegedName,
// @ts-expect-error K could be instantiated with a different subtype of AssetKind
assetKind = AssetKind.NAT,
displayInfo = harden({}),
export const provideDurableIssuerKit = (
issuerBaggage,
optShutdownWithFailure = undefined,
{ elementSchema = undefined } = {},
) => {
const allegedName = issuerBaggage.get('allegedName');
const assetKind = issuerBaggage.get('assetKind');
const displayInfo = issuerBaggage.get('displayInfo');
const elementSchema = issuerBaggage.get('elementSchema');
assert.typeof(allegedName, 'string');
assertAssetKind(assetKind);

Expand All @@ -63,32 +60,13 @@ const makeIssuerKit = (
assertPattern(elementSchema);
}

/**
* We can define this function to use the in-scope `issuer` variable
* before that variable is initialized, as long as the variable is
* initialized before the function is called.
*
* @param {Issuer} allegedIssuer
* @returns {boolean}
*/
// eslint-disable-next-line no-use-before-define
const isMyIssuerNow = allegedIssuer => allegedIssuer === issuer;

const brand = makeBrand(
allegedName,
isMyIssuerNow,
cleanDisplayInfo,
assetKind,
elementSchema,
);

// Attenuate the powerful authority to mint and change balances
const { issuer, mint } = makePaymentLedger(
const { issuer, mint, brand } = makeDurablePaymentLedger(
issuerBaggage,
allegedName,
brand,
assetKind,
cleanDisplayInfo,
brand.getAmountSchema(),
elementSchema,
optShutdownWithFailure,
);

Expand All @@ -99,9 +77,104 @@ const makeIssuerKit = (
displayInfo: cleanDisplayInfo,
});
};
harden(provideDurableIssuerKit);

harden(makeIssuerKit);
/** @typedef {ReturnType<typeof makeDurableIssuerKit>} IssuerKit */

export { makeIssuerKit };
/**
* @template {AssetKind} K
* The allegedName becomes part of the brand in asset descriptions. The
* allegedName doesn't have to be a string, but it will only be used for
* its value. The allegedName is useful for debugging and double-checking
* assumptions, but should not be trusted.
*
* The assetKind will be used to import a specific mathHelpers
* from the mathHelpers library. For example, natMathHelpers, the
* default, is used for basic fungible tokens.
*
* `displayInfo` gives information to the UI on how to display the amount.
*
* @param {MapStore<string,any>} issuerBaggage
* @param {string} allegedName
* @param {K} [assetKind=AssetKind.NAT]
* @param {AdditionalDisplayInfo} [displayInfo={}]
* @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
* provided, then the failed atomic action will call it, so that some
* larger unit of computation, like the enclosing vat, can be shutdown
* before anything else is corrupted by that corrupted state.
* See https://github.com/Agoric/agoric-sdk/issues/3434
* @param {Partial<{elementSchema: Pattern}>} [options]
* @returns {{
* mint: Mint<K>,
* issuer: Issuer<K>,
* brand: Brand<K>,
* displayInfo: DisplayInfo,
* }}
*/
export const makeDurableIssuerKit = (
issuerBaggage,
allegedName,
// @ts-expect-error K could be instantiated with a different subtype of AssetKind
assetKind = AssetKind.NAT,
displayInfo = harden({}),
optShutdownWithFailure = undefined,
{ elementSchema = undefined } = {},
) => {
issuerBaggage.init('allegedName', allegedName);
issuerBaggage.init('assetKind', assetKind);
issuerBaggage.init('displayInfo', displayInfo);
issuerBaggage.init('elementSchema', elementSchema);
return provideDurableIssuerKit(issuerBaggage, optShutdownWithFailure);
};
harden(makeDurableIssuerKit);

/** @typedef {ReturnType<typeof makeIssuerKit>} IssuerKit */
/**
* @template {AssetKind} K
* The allegedName becomes part of the brand in asset descriptions. The
* allegedName doesn't have to be a string, but it will only be used for
* its value. The allegedName is useful for debugging and double-checking
* assumptions, but should not be trusted.
*
* The assetKind will be used to import a specific mathHelpers
* from the mathHelpers library. For example, natMathHelpers, the
* default, is used for basic fungible tokens.
*
* `displayInfo` gives information to the UI on how to display the amount.
*
* @param {string} allegedName
* @param {K} [assetKind=AssetKind.NAT]
* @param {AdditionalDisplayInfo} [displayInfo={}]
* @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
* provided, then the failed atomic action will call it, so that some
* larger unit of computation, like the enclosing vat, can be shutdown
* before anything else is corrupted by that corrupted state.
* See https://github.com/Agoric/agoric-sdk/issues/3434
* @param {Partial<{elementSchema: Pattern}>} [options]
* @returns {{
* mint: Mint<K>,
* issuer: Issuer<K>,
* brand: Brand<K>,
* displayInfo: DisplayInfo,
* }}
*/
export const makeIssuerKit = (
allegedName,
// @ts-expect-error K could be instantiated with a different subtype of AssetKind
assetKind = AssetKind.NAT,
displayInfo = harden({}),
optShutdownWithFailure = undefined,
{ elementSchema = undefined } = {},
) =>
makeDurableIssuerKit(
makeScalarBigMapStore('dropped issuer kit', { durable: true }),
allegedName,
assetKind,
displayInfo,
optShutdownWithFailure,
{ elementSchema },
);
harden(makeIssuerKit);
22 changes: 16 additions & 6 deletions packages/ERTP/src/payment.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
// @ts-check

import { defineKind } from '@agoric/vat-data';
import { defineDurableKind, provideKindHandle } from '@agoric/vat-data';

/**
* @template {AssetKind} K
* @param {MapStore<string,any>} issuerBaggage
* @param {string} allegedName
* @param {Brand<K>} brand
* @param {() => Brand<K>} getBrand must not be called before the issuerKit is
* created
* @returns {() => Payment<K>}
*/
export const definePaymentKind = (allegedName, brand) => {
const makePayment = defineKind(`${allegedName} payment`, () => ({}), {
getAllegedBrand: () => brand,
export const defineDurablePaymentKind = (
issuerBaggage,
allegedName,
getBrand,
) => {
const paymentKindHandle = provideKindHandle(
issuerBaggage,
`${allegedName} payment`,
);
const makePayment = defineDurableKind(paymentKindHandle, () => ({}), {
getAllegedBrand: getBrand,
});
return makePayment;
};
harden(definePaymentKind);
harden(defineDurablePaymentKind);
Loading

0 comments on commit d2ad04b

Please sign in to comment.