Skip to content

Commit

Permalink
Merge branch 'master' into xsnap-plat-app
Browse files Browse the repository at this point in the history
  • Loading branch information
dckc authored Aug 10, 2021
2 parents 57c0a5c + c47fe31 commit c0a2204
Show file tree
Hide file tree
Showing 71 changed files with 787 additions and 691 deletions.
18 changes: 9 additions & 9 deletions packages/SwingSet/docs/liveslots.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ Most SwingSet vats use liveslots (with the notable exception of the comms vat).
```js

export buildRootObject(_vatPowers) {
const obj0 = {
const obj0 = Far('root', {
foo(arg1, arg2) {
// implement foo
return 'value';
},
};
});
return harden(obj0);
}
```
Expand All @@ -33,7 +33,7 @@ This function returns the "root object". A remote reference to it will be made a

```js
foo(arg1) {
const obj2 = harden({
const obj2 = Far('obj2', {
bar(arg2) { return 'barbar'; }
});
return obj2;
Expand All @@ -53,17 +53,17 @@ The method name being invoked can be any string, or the special `Symbol.asyncIte

## What can be serialized

All objects must be frozen or hardened before serialization.
For safety, all objects should hardened before they are allowed to escape the scope of their construction (so that an adversarial counterparty cannot change their contents in surprising ways). However both method arguments and return values are currently automatically hardened for you.

* Data Objects: when an object's enumerable properties are all non-functions, and the object inherits from either `Object`, `Array`, or `null`, and the object is not empty (there is at least one enumerable property), the object is passed by copy: the receiving end gets an object with all the same enumerable properties and their values. The new object inherits from `Object`. These objects are "selfless": they do not retain object identity, so sending the same pass-by-copy object multiple times will result in values that are not `===` to each other.
* Pass-by-Presence objects: when all of an object's enumerable properties *are* functions, and it inherits from either `Object`, `null`, or another pass-by-presence object, the object is passed by presence. The receiving end gets a special Presence object, which can be wrapped by `E(presence)` to make method calls on the original object.
* plain data: anything that JSON can handle will be serialized as plain data, including Arrays, numbers (including -0, `NaN`, `Infinity`, `-Infinity`, and BigInts), some Symbols, and `undefined`.
* Data Objects: when an object's enumerable properties are all non-functions, and the object inherits from either `Object`, `Array`, or `null`, the object is passed by copy: the receiving end gets an object with all the same enumerable properties and their values. The new object inherits from `Object`. These objects are "selfless": they do not retain object identity, so sending the same pass-by-copy object multiple times will result in values that are not `===` to each other.
* Pass-by-Presence objects: when an object is marked with the special `Far` function (which requires that all its enumerable properties *are* functions), the object is passed by presence. The receiving end gets a special Presence object, which can be wrapped by `E(presence)` to make asynchronous remote method calls on the original object.
* plain data: anything that JSON can handle will be serialized as plain data, plus numbers (including -0, `NaN`, `Infinity`, `-Infinity`, and BigInts), some Symbols, and `undefined`.
* Promises: these are recognized as special, and delivered as pass-by-reference. The recipient gets their own Promise whose behavior is linked to the original. When the original Promise is resolved, the downstream version will eventually be resolved too.

Some useful things cannot be serialized: they will trigger an error.

* Functions: this may be fixed, but for now only entire objects are pass-by-presence, and bare functions cause an error. This includes resolvers for Promises.
* Promises: this needs to be fixed soon
* Mixed objects: objects with both function properties and non-function properties. We aren't really sure how to combine pass-by-presence and pass-by-copy.
* Mixed objects: objects with both function properties and non-function properties. We aren't really sure how to combine pass-by-presence and pass-by-copy, however look at issue #2069 ("auxilliary data") for some plans.
* Non-frozen objects: since the receiving end would not automatically get updated with changes to a non-frozen object's properties, it seems safer to require that all values be frozen before transmission

Uncertain:
Expand Down
5 changes: 3 additions & 2 deletions packages/SwingSet/src/vats/network/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ export default function makeRouter() {
});
}
/**
* @typedef {Protocol} RouterProtocol
* @property {(prefix: string, protocolHandler: ProtocolHandler) => void} registerProtocolHandler
* @typedef {Object} RouterProtocol
* @property {(prefix: string) => Promise<Port>} bind
* @property {(paths: string[], protocolHandler: ProtocolHandler) => void} registerProtocolHandler
* @property {(prefix: string, protocolHandler: ProtocolHandler) => void} unregisterProtocolHandler
*/

Expand Down
92 changes: 58 additions & 34 deletions packages/agoric-cli/lib/install.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global __dirname process */
/* global __dirname process Buffer */
import path from 'path';
import chalk from 'chalk';
import { makePspawn } from './helpers';
Expand All @@ -13,15 +13,43 @@ export default async function installMain(progname, rawArgs, powers, opts) {
const pspawn = makePspawn({ log, spawn, chalk });

const rimraf = file => pspawn('rm', ['-rf', file]);
const existingSubdirs = await Promise.all(
['.', '_agstate/agoric-servers', 'contract', 'api', 'ui']
.sort()
.map(async subd => {
const exists = await fs.stat(`${subd}/package.json`).catch(_ => false);
return exists && subd;
}),
);
const subdirs = existingSubdirs.filter(subd => subd);

async function workspaceDirectories(cwd = '.') {
// run `yarn workspaces info` to get the list of directories to
// use, instead of a hard-coded list
const p = pspawn('yarn', ['workspaces', '--silent', 'info'], {
cwd,
stdio: ['inherit', 'pipe', 'inherit'],
});
const stdout = [];
p.childProcess.stdout.on('data', out => stdout.push(out));
await p;
const d = JSON.parse(Buffer.concat(stdout).toString('utf-8'));
const subdirs = Object.values(d).map(v => v.location);
return subdirs;
}

let subdirs;
const dappPackageJSON = await fs
.readFile(`package.json`, 'utf-8')
.then(data => JSON.parse(data))
.catch(err => log('error reading', `package.json`, err));
if (dappPackageJSON.useWorkspaces) {
subdirs = await workspaceDirectories();
subdirs.unshift('.');
} else {
const existingSubdirs = await Promise.all(
['.', '_agstate/agoric-servers', 'contract', 'api', 'ui']
.sort()
.map(async subd => {
const exists = await fs
.stat(`${subd}/package.json`)
.catch(_ => false);
return exists && subd;
}),
);
subdirs = existingSubdirs.filter(subd => subd);
}

const linkFolder = path.resolve(`_agstate/yarn-links`);
const linkFlags = [`--link-folder=${linkFolder}`];
Expand All @@ -35,32 +63,28 @@ export default async function installMain(progname, rawArgs, powers, opts) {
log('removing', linkFolder);
await rimraf(linkFolder);

const sdkRoot = path.resolve(__dirname, `../../..`);
const sdkDirs = await workspaceDirectories(sdkRoot);
await Promise.all(
['packages', 'golang'].map(async pkgSubdir => {
const pkgRoot = path.resolve(__dirname, `../../../${pkgSubdir}`);
const allPackages = await fs.readdir(pkgRoot);
await Promise.all(
allPackages.map(async pkg => {
const dir = `${pkgRoot}/${pkg}`;
const packageJSON = await fs
.readFile(`${dir}/package.json`, 'utf-8')
.catch(err => log('error reading', `${dir}/package.json`, err));
if (!packageJSON) {
return;
}
sdkDirs.map(async location => {
const dir = `${sdkRoot}/${location}`;
const packageJSON = await fs
.readFile(`${dir}/package.json`, 'utf-8')
.catch(err => log('error reading', `${dir}/package.json`, err));
if (!packageJSON) {
return;
}

const pj = JSON.parse(packageJSON);
if (pj.private) {
log('not linking private package', pj.name);
return;
}
const pj = JSON.parse(packageJSON);
if (pj.private) {
log('not linking private package', pj.name);
return;
}

// Save our metadata.
dirPackages.push([dir, pj.name]);
packages.set(pkg, pj.name);
versions.set(pj.name, pj.version);
}),
);
// Save our metadata.
dirPackages.push([dir, pj.name]);
packages.set(dir, pj.name);
versions.set(pj.name, pj.version);
}),
);

Expand Down Expand Up @@ -160,7 +184,7 @@ export default async function installMain(progname, rawArgs, powers, opts) {
const sdkPackages = [...packages.values()].sort();
for (const subdir of subdirs) {
// eslint-disable-next-line no-await-in-loop
const exists = await fs.stat(`${subdir}/yarn.lock`).catch(_ => false);
const exists = await fs.stat(`${subdir}/package.json`).catch(_ => false);
if (
exists &&
// eslint-disable-next-line no-await-in-loop
Expand Down
2 changes: 0 additions & 2 deletions packages/cosmic-swingset/bin/ag-chain-cosmos

This file was deleted.

1 change: 1 addition & 0 deletions packages/cosmic-swingset/bin/ag-chain-cosmos
15 changes: 6 additions & 9 deletions packages/cosmic-swingset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
"name": "@agoric/cosmic-swingset",
"version": "0.31.10",
"description": "Agoric's Cosmos blockchain integration",
"parsers": {
"js": "mjs"
},
"type": "module",
"bin": {
"ag-chain-cosmos": "./src/entrypoint.cjs"
"ag-chain-cosmos": "./src/entrypoint.js"
},
"main": "src/chain-main.js",
"repository": "https://github.com/Agoric/agoric-sdk",
"scripts": {
"build": "exit 0",
"test": "ava",
"test:c8": "c8 $C8_OPTIONS ava --config=ava-nesm.config.js",
"test:xs": "exit 0",
"pretty-fix": "prettier --write '**/*.js'",
"pretty-check": "prettier --check '**/*.js'",
Expand Down Expand Up @@ -43,12 +42,13 @@
"agoric": "^0.13.11",
"anylogger": "^0.21.0",
"deterministic-json": "^1.0.5",
"esm": "agoric-labs/esm#Agoric-built",
"import-meta-resolve": "^1.1.1",
"node-lmdb": "^0.9.4",
"tmp": "^0.2.1"
},
"devDependencies": {
"ava": "^3.12.1"
"ava": "^3.12.1",
"c8": "^7.7.2"
},
"eslintConfig": {
"extends": [
Expand All @@ -69,9 +69,6 @@
"files": [
"test/**/test-*.js"
],
"require": [
"esm"
],
"timeout": "20m"
}
}
20 changes: 13 additions & 7 deletions packages/cosmic-swingset/src/chain-main.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
/* global require setInterval */
import stringify from '@agoric/swingset-vat/src/kernel/json-stable-stringify';
/* global setInterval */
import { resolve as importMetaResolve } from 'import-meta-resolve';
import stringify from '@agoric/swingset-vat/src/kernel/json-stable-stringify.js';
import {
importMailbox,
exportMailbox,
} from '@agoric/swingset-vat/src/devices/mailbox';
} from '@agoric/swingset-vat/src/devices/mailbox.js';

import { assert, details as X } from '@agoric/assert';

import { launch } from './launch-chain';
import makeBlockManager from './block-manager';
import { getMeterProvider } from './kernel-stats';
import { launch } from './launch-chain.js';
import makeBlockManager from './block-manager.js';
import { getMeterProvider } from './kernel-stats.js';

const AG_COSMOS_INIT = 'AG_COSMOS_INIT';

Expand Down Expand Up @@ -227,7 +228,12 @@ export default async function main(progname, args, { env, homedir, agcc }) {
}
}

const vatconfig = require.resolve('@agoric/vats/decentral-config.json');
const vatconfig = new URL(
await importMetaResolve(
'@agoric/vats/decentral-config.json',
import.meta.url,
),
).pathname;
const argv = {
ROLE: 'chain',
noFakeCurrencies: env.NO_FAKE_CURRENCIES,
Expand Down
3 changes: 0 additions & 3 deletions packages/cosmic-swingset/src/entrypoint.cjs

This file was deleted.

2 changes: 1 addition & 1 deletion packages/cosmic-swingset/src/entrypoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import os from 'os';
import path from 'path';
import process from 'process';

import './anylogger-agoric';
import './anylogger-agoric.js';
import anylogger from 'anylogger';
import main from './chain-main.js';

Expand Down
2 changes: 1 addition & 1 deletion packages/cosmic-swingset/src/kernel-stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { makeLegacyMap } from '@agoric/store';
import {
KERNEL_STATS_SUM_METRICS,
KERNEL_STATS_UPDOWN_METRICS,
} from '@agoric/swingset-vat/src/kernel/metrics';
} from '@agoric/swingset-vat/src/kernel/metrics.js';

/**
* TODO Would be nice somehow to label the vats individually, but it's too
Expand Down
2 changes: 1 addition & 1 deletion packages/cosmic-swingset/src/launch-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
DEFAULT_METER_PROVIDER,
exportKernelStats,
makeSlogCallbacks,
} from './kernel-stats';
} from './kernel-stats.js';

const console = anylogger('launch-chain');

Expand Down
24 changes: 15 additions & 9 deletions packages/cosmic-swingset/src/sim-chain.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
/* global require process setTimeout clearTimeout */
/* global process setTimeout clearTimeout */
/* eslint-disable no-await-in-loop */
import path from 'path';
import fs from 'fs';
import stringify from '@agoric/swingset-vat/src/kernel/json-stable-stringify';
import stringify from '@agoric/swingset-vat/src/kernel/json-stable-stringify.js';
import {
importMailbox,
exportMailbox,
} from '@agoric/swingset-vat/src/devices/mailbox';
} from '@agoric/swingset-vat/src/devices/mailbox.js';

import anylogger from 'anylogger';

import { resolve as importMetaResolve } from 'import-meta-resolve';
import { assert, details as X } from '@agoric/assert';
import { makeWithQueue } from '@agoric/vats/src/queue';
import { makeBatchedDeliver } from '@agoric/vats/src/batched-deliver';
import { launch } from './launch-chain';
import makeBlockManager from './block-manager';
import { getMeterProvider } from './kernel-stats';
import { makeWithQueue } from '@agoric/vats/src/queue.js';
import { makeBatchedDeliver } from '@agoric/vats/src/batched-deliver.js';
import { launch } from './launch-chain.js';
import makeBlockManager from './block-manager.js';
import { getMeterProvider } from './kernel-stats.js';

const console = anylogger('fake-chain');

Expand Down Expand Up @@ -51,7 +52,12 @@ export async function connectToFakeChain(basedir, GCI, delay, inbound) {

const mailboxStorage = await makeMapStorage(mailboxFile);

const vatconfig = require.resolve('@agoric/vats/decentral-config.json');
const vatconfig = new URL(
await importMetaResolve(
'@agoric/vats/decentral-config.json',
import.meta.url,
),
).pathname;
const argv = {
ROLE: 'sim-chain',
giveMeAllTheAgoricPowers: true,
Expand Down
9 changes: 6 additions & 3 deletions packages/cosmic-swingset/test/test-make.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/* global __dirname */
import test from 'ava';
import { spawn } from 'child_process';
import path from 'path';

const filename = new URL(import.meta.url).pathname;
const dirname = path.dirname(filename);

test('make and exec', async t => {
await new Promise(resolve =>
spawn('make', {
cwd: `${__dirname}/..`,
cwd: `${dirname}/..`,
stdio: ['ignore', 'ignore', 'inherit'],
}).addListener('exit', code => {
t.is(code, 0, 'make exits successfully');
Expand All @@ -14,7 +17,7 @@ test('make and exec', async t => {
);
await new Promise(resolve =>
spawn('bin/ag-chain-cosmos', {
cwd: `${__dirname}/..`,
cwd: `${dirname}/..`,
stdio: ['ignore', 'ignore', 'inherit'],
}).addListener('exit', code => {
t.is(code, 0, 'exec exits successfully');
Expand Down
5 changes: 4 additions & 1 deletion packages/marshal/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export { PASS_STYLE } from './src/helpers/passStyleHelpers.js';
export { getErrorConstructor } from './src/helpers/error.js';
export { getInterfaceOf } from './src/helpers/remotable.js';
export {
getInterfaceOf,
ALLOW_IMPLICIT_REMOTABLES,
} from './src/helpers/remotable.js';

export { passStyleOf, everyPassableChild } from './src/passStyleOf.js';

Expand Down
Loading

0 comments on commit c0a2204

Please sign in to comment.