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(vats): upgradeable board #6903

Merged
merged 13 commits into from
Feb 8, 2023
Merged

feat(vats): upgradeable board #6903

merged 13 commits into from
Feb 8, 2023

Conversation

dckc
Copy link
Member

@dckc dckc commented Feb 1, 2023

refs: #6553

Description

Use the prepareExoClassKit pattern make board state virtual, durable, and heritable by upgrade successors.

Marshallers are provided ephemerally, keyed by this.

Security Considerations

Interface guards tighten things up a bit.

Scaling Considerations

on getId(val):

      /**
       * Scaling Consideration: since we cannot know when consumers
       * are no longer interested in an ID, a board holds a strong reference
       * to `value` for its entire lifetime. For a well-known board, this
       * is essentially forever.
       */

Documentation Considerations

Since this was my first (non-trivial) work with the virtual, durable, upgrade APIs, I tried to leave cookie crumbs.

Since I touched so much code, I added external API documentation to lib-board.js while I was at it.

Testing Considerations

1 happy-path null upgrade test seemed sufficient to force me to get VDO / upgrade stuff right.

test-lib-board.js came in quite handy for testing interface guards and making sure I didn't break the marshal stuff.
I added 1 test to be more explicit that values have to be passable keys.

@dckc dckc self-assigned this Feb 1, 2023
@dckc dckc force-pushed the 6553-board-upgrade branch 4 times, most recently from d9ab429 to 2b73dfe Compare February 2, 2023 03:01
@dckc dckc changed the title feat(vats): upgradeable board (WIP) feat(vats): upgradeable board Feb 2, 2023
@dckc dckc marked this pull request as ready for review February 2, 2023 03:17
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
@dckc
Copy link
Member Author

dckc commented Feb 2, 2023

@warner @gibson042 @FUDCo I'd like to add a virtualization test that shows that heap size stays flat even with many items added to the board. Any suggestions on how to go about it?

packages/smart-wallet/src/marshal-contexts.js Outdated Show resolved Hide resolved
packages/vats/src/vat-board.js Outdated Show resolved Hide resolved
packages/vats/test/test-lib-board.js Show resolved Hide resolved
packages/vats/test/upgrading/bootstrapVatUpgrade.js Outdated Show resolved Hide resolved
packages/vats/test/upgrading/test-upgrade-vats.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Show resolved Hide resolved
@dckc dckc force-pushed the 6553-board-upgrade branch 2 times, most recently from 953ce44 to cab791f Compare February 3, 2023 04:40
@dckc dckc added the automerge:rebase Automatically rebase updates, then merge label Feb 3, 2023
@dckc dckc requested a review from turadg February 3, 2023 17:38
packages/smart-wallet/src/marshal-contexts.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Show resolved Hide resolved
packages/vats/src/lib-board.js Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Show resolved Hide resolved
packages/vats/test/upgrading/bootstrapVatUpgrade.js Outdated Show resolved Hide resolved
packages/vats/test/upgrading/bootstrapVatUpgrade.js Outdated Show resolved Hide resolved
@@ -1521,7 +1521,6 @@ export function makeWalletRoot({
return E(board)
.getValue(boardId)
.then(value => {
// @ts-expect-error type is too specific
Copy link
Member

Choose a reason for hiding this comment

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

I take it this is from the string template thing and not an implicit any

@dckc dckc removed the automerge:rebase Automatically rebase updates, then merge label Feb 3, 2023
@turadg turadg force-pushed the 6553-board-upgrade branch 2 times, most recently from 53579b6 to 9b600df Compare February 3, 2023 19:22
@turadg turadg added the automerge:no-update (expert!) Automatically merge without updates label Feb 3, 2023
Copy link
Member

@turadg turadg left a comment

Choose a reason for hiding this comment

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

Made the changes I proposed

packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
@turadg turadg removed the automerge:no-update (expert!) Automatically merge without updates label Feb 5, 2023
* @param {import('@agoric/vat-data').Baggage} baggage
*/
export function buildRootObject(_vatPowers, _vatParameters, baggage) {
const makeBoardKit = prepareBoardKit(baggage);
Copy link
Member

Choose a reason for hiding this comment

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

I think anything accepting a baggage argument to write into should also accept a key rather than hard-coding it.

Suggested change
const makeBoardKit = prepareBoardKit(baggage);
const makeBoardKit = prepareBoardKit(baggage, 'Board');

Copy link
Member

Choose a reason for hiding this comment

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

Disagree, but I see an extensive internal slack discussion, so will continue there. Whatever the outcome, someone should publicly summarize.

packages/vats/src/vat-board.js Outdated Show resolved Hide resolved
@@ -49,6 +49,14 @@ test('makeBoard', async t => {
t.is(idObj2b, 'tooboard012');
});

test('board values must be scalar keys', async t => {
const board = makeBoard();
const nonKey = harden({ a: 1 });
Copy link
Member

Choose a reason for hiding this comment

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

Can we get more test coverage here? Array, symbol, number, bigint, boolean, etc.?

Copy link
Member Author

Choose a reason for hiding this comment

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

Seems like the patterns API is reasonably well tested elsewhere.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, so what exactly is this testing? The "invalid key type" error seems to come from collectionManager.js, which means that the bad input was accepted by the method guard, which suggests to me that ValShape in packages/vats/src/lib-board.js should be M.scalar() rather than M.key().

Copy link
Member

@gibson042 gibson042 Feb 6, 2023

Choose a reason for hiding this comment

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

Digging deeper, I think this hits an issue that was apparently not caught by testing: makeScalarBigMapStore (the function that makes durable maps such as baggage, sometimes through provideDurableMapStore) is built on makeCollection, which defaults to a keyShape of M.scalar(). But if a board's values can be anything matched by M.key(), then it's valToId map should be specified with a corresponding keyShape of M.key() or else it won't actually be able to support non-scalar values (which seems like the testing gap here).

Copy link
Member

Choose a reason for hiding this comment

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

Currently, non-scalar keys are not yet implemented by *MapStore and *SetStore. We make the "Scalar" qualifier explicit in the maker names to emphasize that these implement only a subset of the full MapStore and SetStore semantics.

Non-scalar keys are implemented by CopyMap, CopySet, and CopyBag.

So whether the correct restriction to express is M.key() or M.scalar() depends on if you're trying to detect a violation of the specified semantics, or a violation of the current implementation restrictions. Either way, please put a comment at the relevant place in the code to explain.

Copy link
Member

@gibson042 gibson042 Feb 6, 2023

Choose a reason for hiding this comment

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

Currently, non-scalar keys are not yet implemented by *MapStore and *SetStore.

Hmm, then it seems like a problem for e.g. makeScalarBigMapStore("dummy", { keyShape: M.key() }).init(harden({ label: "not a scalar" }), "val") to succeed (which it currently does, at least in isolation). But more importantly, doesn't that restriction make Board durability (and thus upgradability) an order of magnitude more challenging? How should it store the value-to-id data if not in a durable map?

We make the "Scalar" qualifier explicit in the maker names to emphasize that these implement only a subset of the full MapStore and SetStore semantics.

D'oh! I should have picked up on/remembered that!

Copy link
Member

Choose a reason for hiding this comment

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

makeScalarBigMapStore("dummy", { keyShape: M.key() }).init(harden({ label: "not a scalar" }), "val") succeeds? Really? That is very surprising. Are you sure?

Copy link
Member

Choose a reason for hiding this comment

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

$ node --input-type=module -e '
  import "@agoric/swingset-vat/tools/prepare-test-env.js";
  import { M } from "@agoric/store";
  import { makeScalarBigMapStore } from "@agoric/vat-data";
  const bigMap = makeScalarBigMapStore("dummy", { keyShape: M.key() });
  const key = harden({ label: "not a scalar" });
  bigMap.init(key, "val");
  console.log(bigMap.get(key));
'
val

Copy link
Member

Choose a reason for hiding this comment

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

@FUDCo @warner , do you have any idea how this could possibly be working? Are our Big*Stores no longer limited to scalar keys? Did this happen in switching to sqlite?

Copy link
Member

@gibson042 gibson042 Feb 7, 2023

Choose a reason for hiding this comment

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

@erights I don't think we're that lucky; more likely the in-memory implementation set up for testing is just not very restrictive and the keyShape argument for makeScalarBigMapStore et al. is treated as a replacement for the M.scalar() default rather than a refinement of it. And assertKeyPattern(M.key()) passes, although I don't know whether or not that's appropriate because there's some mismatch between checkKeyPattern vs. checkKey (the former rejecting non-scalar specimens like harden({}) but not Matchers like the "match:key" tagged record returned from M.key() because checkKeyPattern internally delegates checking of a tagged record specimen that is a Matcher to the checkKeyPattern method of the corresponding matchHelper from HelpersByMatchTag, which for "match:key" accepts all input).

EDIT: Having explored that, I think something is indeed amiss in checkKeyPattern.

packages/vats/test/upgrading/test-upgrade-vats.js Outdated Show resolved Hide resolved
packages/smart-wallet/src/marshal-contexts.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
packages/vats/src/lib-board.js Outdated Show resolved Hide resolved
@erights erights self-requested a review February 6, 2023 22:09
@turadg turadg added automerge:no-update (expert!) Automatically merge without updates bypass:integration Prevent integration tests from running on PR labels Feb 7, 2023
@turadg
Copy link
Member

turadg commented Feb 7, 2023

It failed deployment-test due to GH's Ubuntu brownout which lasts for another couple hours. This doesn't change the behavior of vat-update so I am betting on it not affecting deployment-test and have added a bypass-integration label.

@turadg
Copy link
Member

turadg commented Feb 7, 2023

@Mergifyio requeue

@mergify mergify bot merged commit 1323a20 into master Feb 8, 2023
@mergify mergify bot deleted the 6553-board-upgrade branch February 8, 2023 02:20
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 bypass:integration Prevent integration tests from running on PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants