Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ertp): durability #5283

Merged
merged 1 commit into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

165 changes: 108 additions & 57 deletions packages/ERTP/src/issuerKit.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,37 @@

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 { vivifyPaymentLedger } from './paymentLedger.js';

import './types.js';

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

/**
* @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 {Baggage} 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,
* }}
* @returns {IssuerKit<K>}
*/
const makeIssuerKit = (
allegedName,
// @ts-expect-error K could be instantiated with a different subtype of AssetKind
assetKind = AssetKind.NAT,
displayInfo = harden({}),
export const vivifyIssuerKit = (
erights marked this conversation as resolved.
Show resolved Hide resolved
issuerBaggage,
optShutdownWithFailure = undefined,
{ elementSchema = undefined } = {},
) => {
assert.typeof(allegedName, 'string');
const name = issuerBaggage.get('name');
const assetKind = issuerBaggage.get('assetKind');
const displayInfo = issuerBaggage.get('displayInfo');
const elementSchema = issuerBaggage.get('elementSchema');
assert.typeof(name, 'string');
assertAssetKind(assetKind);

// Add assetKind to displayInfo, or override if present
Expand All @@ -63,32 +46,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(
allegedName,
brand,
const { issuer, mint, brand } = vivifyPaymentLedger(
issuerBaggage,
name,
assetKind,
cleanDisplayInfo,
brand.getAmountSchema(),
elementSchema,
optShutdownWithFailure,
);

Expand All @@ -99,9 +63,96 @@ const makeIssuerKit = (
displayInfo: cleanDisplayInfo,
});
};
harden(vivifyIssuerKit);

harden(makeIssuerKit);

export { makeIssuerKit };
/**
* @template {AssetKind} K
* The name becomes part of the brand in asset descriptions.
* The name is useful for debugging and double-checking
* assumptions, but should not be trusted wrt any external namespace.
* For example, anyone could create a new issuer kit with name 'BTC', but
* it is not bitcoin or even related. It is only the name according
* to that issuer and brand.
*
* 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 {Baggage} issuerBaggage
* @param {string} name
* @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 {IssuerKit<K>}
*/
export const makeDurableIssuerKit = (
issuerBaggage,
name,
// @ts-expect-error K could be instantiated with a different subtype of AssetKind
assetKind = AssetKind.NAT,
displayInfo = harden({}),
optShutdownWithFailure = undefined,
{ elementSchema = undefined } = {},
) => {
issuerBaggage.init('name', name);
issuerBaggage.init('assetKind', assetKind);
issuerBaggage.init('displayInfo', displayInfo);
issuerBaggage.init('elementSchema', elementSchema);
return vivifyIssuerKit(issuerBaggage, optShutdownWithFailure);
};
harden(makeDurableIssuerKit);

/** @typedef {ReturnType<typeof makeIssuerKit>} IssuerKit */
/**
* @template {AssetKind} K
* The name becomes part of the brand in asset descriptions.
* The name is useful for debugging and double-checking
* assumptions, but should not be trusted wrt any external namespace.
* For example, anyone could create a new issuer kit with name 'BTC', but
* it is not bitcoin or even related. It is only the name according
* to that issuer and brand.
*
* 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} name
* @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 {IssuerKit<K>}
*/
export const makeIssuerKit = (
erights marked this conversation as resolved.
Show resolved Hide resolved
name,
// @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 }),
name,
assetKind,
displayInfo,
optShutdownWithFailure,
{ elementSchema },
);
harden(makeIssuerKit);
19 changes: 12 additions & 7 deletions packages/ERTP/src/payment.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
// @ts-check

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

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

/**
* @template {AssetKind} K
* @param {string} allegedName
* @param {Brand<K>} brand
* @param {Baggage} issuerBaggage
* @param {string} name
* @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 vivifyPaymentKind = (issuerBaggage, name, getBrand) => {
const paymentKindHandle = provideKindHandle(issuerBaggage, `${name} payment`);
const makePayment = defineDurableKind(paymentKindHandle, () => ({}), {
getAllegedBrand: getBrand,
});
return makePayment;
};
harden(definePaymentKind);
harden(vivifyPaymentKind);
Loading