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

7495 price vat upgradable #7555

Merged
merged 9 commits into from
May 1, 2023
Merged

7495 price vat upgradable #7555

merged 9 commits into from
May 1, 2023

Conversation

turadg
Copy link
Member

@turadg turadg commented Apr 29, 2023

closes: #7495

Description

Makes the priceAuthority vat upgradable.

First clarifies the responsibility of the vat: to hold the registry of price authorities. Moreover it's the singular and canonical registry for the vat set. (If there needs to be another registry, there will have to be another vat made with its own baggage.)

This simplification allowed the durability to be implemented as singleton of two Exo facets instead of an Exo class.

Security Considerations

--

Scaling Considerations

--

Documentation Considerations

--

Testing Considerations

Has a test of restarting the vat. We'll need more test coverage but the requirements are being sorted out. I expect it will fall under #7562

@turadg turadg requested review from dckc and michaelfig April 29, 2023 18:02
Copy link
Member

@dckc dckc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSingleton API change seems fine

export function buildRootObject() {
return Far('root', {
makePriceAuthorityRegistry,
makeFakePriceAuthority: async options => makeFakePriceAuthority(options),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makeFakePriceAuthority isn't used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, not from the vat. whenever a fake is necessary it's because the vat is skipped.

Comment on lines 189 to 194
if (assetToPriceStore.has(brandIn)) {
priceStore = assetToPriceStore.get(brandIn);
} else {
priceStore = provideDurableMapStore(baggage, 'brandOut');
assetToPriceStore.init(brandIn, priceStore);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like the provide pattern. use provide()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed! done

Comment on lines 111 to 128
M.interface('compositePriceAuthority', {
getQuoteIssuer: M.call(BrandShape, BrandShape).returns(M.promise()),
getTimerService: M.call(BrandShape, BrandShape).returns(M.promise()),
quoteGiven: M.call(AmountShape, BrandShape).returns(M.promise()),
quoteWanted: M.call(BrandShape, AmountShape).returns(M.promise()),
makeQuoteNotifier: M.call(AmountShape, BrandShape).returns(M.promise()),
quoteAtTime: M.call(TimestampShape, AmountShape, BrandShape).returns(
M.promise(),
),
quoteWhenLT: GuardCallAmountTuple,
quoteWhenLTE: GuardCallAmountTuple,
quoteWhenGTE: GuardCallAmountTuple,
quoteWhenGT: GuardCallAmountTuple,
mutableQuoteWhenLT: GuardCallAmountTuple,
mutableQuoteWhenLTE: GuardCallAmountTuple,
mutableQuoteWhenGTE: GuardCallAmountTuple,
mutableQuoteWhenGT: GuardCallAmountTuple,
}),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised we haven't written this interface guard before. The fluxAggregator is an exo price authority, isn't it?

Hm... there's one price authority held in the prepareFluxAggregatorKit closure...

// not durable, held in closure and remade in every call of enclosing
const { priceAuthority } = makeOnewayPriceAuthorityKit({

It seems to be referenced by all instances of the fluxAggregator exo class kit.

const makeFluxAggregatorKit = prepareExoClassKit(
baggage,
'fluxAggregator',

Maybe that's OK, since there's only one instance of that exo class... but then shouldn't it be an exo singleton?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like scaledPriceAuthority.js should also use this interface guard. Is making that durable in our plans anywhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for scaledPriceAuthority I added some docs: 34d2d7d

for the Exo singleton idea let's chat

@@ -22,6 +22,10 @@ import { makeInitialTransform } from '../contractSupport/priceAuthorityInitial.j
* A contract that scales a source price authority to a target price authority
* via ratios.
*
* Not durable. Because it only transforms there's nothing important to save.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that much makes sense

Comment on lines 26 to 27
* The facets may sever upon vat restart, but the priceAuthorityRegistry that
* holds them can be given a fresh scaling contract to replace them.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. I wonder how that works. Replacing a price authority in the registry is one thing, but what about the reference from the vaultFactory terms?

const { priceAuthority, timerService, reservePublicFacet } = zcf.getTerms();

It makes more sense to me that we could upgrade or restart this contract than wire up a fresh one.

@turadg turadg force-pushed the 7495-price-vat-upgradable branch 2 times, most recently from f23d939 to 6e12a60 Compare April 30, 2023 21:02
@turadg turadg marked this pull request as ready for review April 30, 2023 21:05
Copy link
Member

@dckc dckc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good stuff

const reincarnatedRegistry = await EV.vat('priceAuthority').getRegistry();
// facet holder object changes but the members have the same identity
t.not(reincarnatedRegistry, registry);
t.is(reincarnatedRegistry.priceAuthority, registry.priceAuthority);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@turadg turadg added the automerge:no-update (expert!) Automatically merge without updates label Apr 30, 2023
@turadg turadg force-pushed the 7495-price-vat-upgradable branch from 6e12a60 to 7675e71 Compare April 30, 2023 21:59
@@ -6,6 +6,9 @@ import styles from 'ansi-styles'; // less authority than 'chalk'

const { quote: q, Fail } = assert;

/** @type {Map<string, Promise<BundleMeta>>} output filename to its meta info */
const fileMetas = new Map();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this state need to be shared across bundle caches?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes because each multiple bundle caches are trying to write to the same file paths. I suppose it would be better for "makeBundleCache" to be idempotent. I'll work on that. At least now for this PR I know that the failure is in the bundleTool

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelfig you recently did some work to address concurrent writes; take a look at this, please?

see also #3609

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes because each multiple bundle caches are trying to write to the same file paths.

I wonder if they're in the same process / heap, though. What @michaelfig did was to add .lock files, IIRC.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@turadg, can you document the issue you ran into with the bundle cache implementation that existed before this PR? I'm most curious how the problem manifested, such as unexpected output or exceptions.

The .lock file handshake should have been idempotent and robust against multiple uses of the same cache, whether or not they are inside the same process or multiple processes (including bundleTool.js).

Copy link
Member Author

@turadg turadg May 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's visible in the previous build: 7675e71

It failed but only in CI,

#   create initial version
#   now perform the upgrade
[bundleTool] bundles add: vat-board from /home/runner/work/agoric-sdk/agoric-sdk/packages/vats/src/vat-board.js
[bundleTool] bundles add: vat-bridge from /home/runner/work/agoric-sdk/agoric-sdk/packages/vats/src/vat-bridge.js
[bundleTool] bundles add: vat-priceAuthority from /home/runner/work/agoric-sdk/agoric-sdk/packages/vats/src/vat-priceAuthority.js
[bundleTool] bundles add: bootstrap-relay from /home/runner/work/agoric-sdk/agoric-sdk/packages/SwingSet/test/bootstrap-relay.js
[bundleTool] bundles add: bootstrap-relay from /home/runner/work/agoric-sdk/agoric-sdk/packages/SwingSet/test/bootstrap-relay.js
[bundleTool] bundles add: bootstrap-relay from /home/runner/work/agoric-sdk/agoric-sdk/packages/SwingSet/test/bootstrap-relay.js
REJECTED from ava test("upgrade vat-board"): (Error#1)
Error#1: config.vats.bootstrap: Invalid or unexpected token
  at packages/SwingSet/src/controller/initializeSwingset.js:538:15
  at async Promise.all (index 0)
  at async processGroup (packages/SwingSet/src/controller/initializeSwingset.js:541:27)
  at async initializeSwingset (packages/SwingSet/src/controller/initializeSwingset.js:571:31)
  at async buildVatController (packages/SwingSet/src/controller/controller.js:479:23)
  at async makeScenario (packages/vats/test/upgrading/test-upgrade-vats.js:53:13)
  at async packages/vats/test/upgrading/test-upgrade-vats.js:74:18

idempotent and robust against multiple uses of the same cache

Note that the problem here was three tests in the same file each having a cacher configured on the same path. Now they share one provided cache and bootstrap-relay gets bundled once.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's visible in the previous build: ...

Thanks for sharing that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Turns out in the bustle of trying to sync Endo, I forgot to create an Agoric SDK PR to have bundleTool.js use Endo's idempotent-between-processes bundle cache.

Now I did that in #7596.

@turadg turadg force-pushed the 7495-price-vat-upgradable branch from 7134270 to 026bcd4 Compare May 1, 2023 19:50
@mergify mergify bot merged commit 130d73f into master May 1, 2023
@mergify mergify bot deleted the 7495-price-vat-upgradable branch May 1, 2023 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge:no-update (expert!) Automatically merge without updates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

vat: priceAuthority is upgradable
3 participants