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

6880 bootstrap integration test of vaultFactory with smart wallet #7021

Merged
merged 15 commits into from
Feb 28, 2023

Conversation

turadg
Copy link
Member

@turadg turadg commented Feb 17, 2023

closes: #6880

Description

Tests Vault Factory integration with Smart Wallet, using a new kind of Swingset test.

vs contract tests:

  • integrates the full bootstrap so there's no config maintenance
  • runs on top of the same decentral-test-vaults-config.json as testnet
  • takes ~1m to run

vs chain tests:

  • fakes the Cosmos bridge
  • uses local instead of xs-worker so it's faster (e.g. xs about 50% slower than Node in local dev) and enables use of the Node debugger
  • can use Ava test runner and assertions

Security Considerations

Scaling Considerations

Documentation Considerations

Testing Considerations

@turadg turadg force-pushed the 6880-vaultFactory-wallets branch 5 times, most recently from 18998f8 to 137a8af Compare February 24, 2023 23:19
@turadg turadg changed the base branch from master to ta/drop-node-14 February 24, 2023 23:20
@turadg turadg changed the title 6880 test integration of vaultFactory with smart wallet 6880 bootstrap integration test of vaultFactory with smart wallet Feb 24, 2023
@turadg turadg requested review from warner and dckc February 24, 2023 23:21
@turadg turadg marked this pull request as ready for review February 24, 2023 23:21
* @param {(message: *) => void} [log]
*/
const load = async (rootPath, targetName, log = console.debug) => {
targetName ||= pathAmbient.basename(rootPath, '.js');
Copy link
Member Author

Choose a reason for hiding this comment

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

the ||= is why this PR is stacked on #7073

@dckc I know you'll have thoughts about pathAmbient. It was a hassle to wire it through the functions and they don't have types so that would be lost. I figure the module is like a closure in which an authority is available so this is not a violation of ocap.

I figure at some point we'll have things like Node's path not importable. Until then this feels pragmatic.

Copy link
Member

Choose a reason for hiding this comment

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

It was a hassle to wire it through the functions ...

Adding basename to readPowers isn't straightforward?

I figure the module is like a closure in which an authority is available so this is not a violation of ocap.

Hm. Exporting functions that close over ambient authority such as path.basename is one of the few crisp prohibitions we have managed to articulate (or... I thought we had managed...):

No modules should export powerful objects (for example, objects that close over fs or process.env).
-- OCap Discipline

Copy link
Member Author

@turadg turadg Feb 25, 2023

Choose a reason for hiding this comment

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

Adding basename to readPowers isn't straightforward?

Adding it to makeReadPowers isn't because that's in Endo. This works,

  const readPowers = {
    ...makeReadPowers({ fs, url, crypto }),
    basename: fs.basename,
  };

But it's confusing the makeReadPowers doesn't make readPowers. And the type information is lost. The net cost of repeating every fs function that we need strikes me as greater than its benefit.

No modules should export powerful objects (for example, objects that close over fs or process.env).

I don't think we fully follow that edict. A search of process.env shows 77 results in 40 files. Not all are functions closing over it but I see 10-20 that are.

I'll remove pathAmbient to get this PR in but I think the ocap coding guidelines could use some refinement.

Copy link
Member

Choose a reason for hiding this comment

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

No modules should export powerful objects (for example, objects that close over fs or process.env).

I don't think we fully follow that edict.

Indeed; #2160 represents the technical-debt to clean that up.

And the type information is lost.

That seems straightforward to address.

The net cost of repeating every fs function that we need strikes me as greater than its benefit.

It is unfortunate that node's fs API is awkward w.r.t. the principle of least authority. I hope we can use something shaped like this more widely...

export const makeFileReader = (fileName, { fs, path }) => {
const make = there => makeFileReader(there, { fs, path });
return harden({
toString: () => fileName,
readText: () => fs.promises.readFile(fileName, 'utf-8'),
neighbor: ref => make(path.resolve(fileName, ref)),
stat: () => fs.promises.stat(fileName),
absolute: () => path.normalize(fileName),
relative: there => path.relative(fileName, there),
exists: () => fs.existsSync(fileName),
});
};
export const makeFileWriter = (fileName, { fs, path }) => {
const make = there => makeFileWriter(there, { fs, path });
return harden({
toString: () => fileName,
writeText: txt => fs.promises.writeFile(fileName, txt),
readOnly: () => makeFileReader(fileName, { fs, path }),
neighbor: ref => make(path.resolve(fileName, ref)),
mkdir: opts => fs.promises.mkdir(fileName, opts),
});
};

Copy link
Member

Choose a reason for hiding this comment

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

Adding it to makeReadPowers isn't because that's in Endo.

Ah... I missed that point earlier. Now I appreciate why it's awkward.

Here's hoping I can sync up with endo on POLA-shaped IO soonish. Thanks for ef90a4f meanwhile.

Base automatically changed from ta/drop-node-14 to master February 24, 2023 23:38
@turadg
Copy link
Member Author

turadg commented Feb 25, 2023

Since these integrate bootstrap I'm wondering if the tests should be in 'packages/vats' instead. At least the supports module.

In some way "vats" is the product and these are functional tests of user flows so it makes sense for them to be there.

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.

very nice!

some stuff to consider, but nothing critical


async function getBundle(desc, mode, nameToBundle) {
if (mode === 'bundle') {
const bundleCache = await (config.bundleCachePath
Copy link
Member

Choose a reason for hiding this comment

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

👍

packages/SwingSet/src/controller/initializeSwingset.js Outdated Show resolved Hide resolved
Comment on lines 97 to 100
/**
*
* @param {Map<*, *>} state
*/
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/**
*
* @param {Map<*, *>} state
*/
/** @param {Map<*, *>} state */

is that type not inferred?

Copy link
Member Author

Choose a reason for hiding this comment

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

good point, this doesn't add anything. removed.

@@ -71,6 +86,10 @@ const kmarshal = makeMarshal(krefOf, kslot, {

export const kser = value => kmarshal.serialize(harden(value));

/**
* @param {import('@endo/marshal').CapData<any>} serializedValue
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 kernel slots are strings...

Suggested change
* @param {import('@endo/marshal').CapData<any>} serializedValue
* @param {import('@endo/marshal').CapData<string>} serializedValue

import { buildManualTimer } from '../tools/manual-timer.js';
import { makePassableEncoding } from '../tools/passableEncoding.js';
Copy link
Member

Choose a reason for hiding this comment

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

something to consider for this file:

const relayRoot = new Proxy(
{},
{
get:
(_t, prop, _rx) =>
(...args) =>
run(prop, args),
},
);
const EV = name =>
new Proxy(
{},
{
get:
(_t, prop, _rx) =>
(...args) =>
messageVat(name, prop, args),
},
);
const EP = presence =>
new Proxy(
{},
{
get:
(_t, prop, _rx) =>
(...args) =>
messageObject(presence, prop, args),
},
);

Copy link
Member Author

Choose a reason for hiding this comment

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

nifty! TALA 38cd282

Copy link
Member

Choose a reason for hiding this comment

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

@gibson042 check this out ^

packages/vats/test/bootstrapTests/supports.js Show resolved Hide resolved
const wd = await factoryDriver.provideSmartWallet('agoric1open');

const { agoricNamesRemotes } = t.context;
await wd.executeOffer({
Copy link
Member

Choose a reason for hiding this comment

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

static typechecking this big offer expression would be nifty

Copy link
Member Author

Choose a reason for hiding this comment

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

it checks the types of the properties, but for some reason it doesn't check the top level properties. gonna punt on that.

status: { id: 'open-vault', numWantsSatisfied: 1 },
});

// try giving more than is available in the purse/vbank
Copy link
Member

Choose a reason for hiding this comment

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

👏


Generated by [AVA](https://avajs.dev).

## makeAgoricNamesRemotesFromFakeStorage
Copy link
Member

Choose a reason for hiding this comment

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

It would be great to promote this to https://docs.agoric.com/

@turadg turadg added the automerge:no-update (expert!) Automatically merge without updates label Feb 28, 2023
@mergify mergify bot merged commit f8ca721 into master Feb 28, 2023
@mergify mergify bot deleted the 6880-vaultFactory-wallets branch February 28, 2023 00:56
Comment on lines -50 to +60
async function buildSwingset(
/**
* @param {Map<*, *>} mailboxStorage
* @param {*} bridgeOutbound
* @param {SwingStoreKernelStorage} kernelStorage
* @param {string} vatconfig absolute path
* @param {Record<string, any>} argv XXX argv should be an array but it's being called with object
* @param {{ ROLE: string }} env
* @param {*} options
*/
export async function buildSwingset(
Copy link
Member

Choose a reason for hiding this comment

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

I really wasn't expecting this to be exported, and to stay an internal concern.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not clear on what the intent of this comment is. Do you want it to be factored differently? If so, how?

Copy link
Member

Choose a reason for hiding this comment

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

I just have 3 pending PRs that are now failing/conflicting because of this change. I'm not sure if there is a better way to factor this, haven't looked closely yet. It's more of a process question, I wish I had known about this change coming.

@mhofman
Copy link
Member

mhofman commented Feb 28, 2023

  • fakes the Cosmos bridge

I hope this will be compatible with the bridge changes in #6741

Edit: confirmed to be compatible!

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.

integration tests of walletFactory and vaultFactory
4 participants