Skip to content

Commit

Permalink
feat(cosmic-swingset): new scripts/clean-core-eval.js
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Apr 8, 2022
1 parent e1c48b9 commit b2b0b5a
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 46 deletions.
10 changes: 6 additions & 4 deletions packages/cosmic-swingset/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ VOTE_OPTION = yes
GOSRC = ../../golang/cosmos
DEBUG ?= SwingSet:ls,SwingSet:vat
AG_SOLO = DEBUG=$(DEBUG) $(shell cd ../solo/bin && pwd)/ag-solo
AGC = DEBUG=$(DEBUG) PATH="$$PWD/bin:$$PATH" $(GOSRC)/build/agd
AGCH = $(GOSRC)/build/agd

SHELL = bash

default: all

# By default, make the fake chain in scenario3 produce
# "blocks" as soon as they come in.
FAKE_CHAIN_DELAY = 0
Expand All @@ -39,7 +43,7 @@ BIN := $(shell echo $${GOBIN-$${GOPATH-$$HOME/go}/bin})
EVAL_CLEAN=$(EVAL_CODE)-clean.js

$(EVAL_CLEAN): $(EVAL_CODE)
node test/runStake/checkGov.js $< >$@.t
./scripts/clean-core-eval.js $< >$@.t || { rm -f $@.t; exit 1; }
mv $@.t $@

start-runStake: test/runStake/gov-start-runStake.js
Expand All @@ -53,7 +57,7 @@ start-committee: test/runStake/gov-start-econCommittee.js
VOTE_PROPOSAL=$(VOTE_PROPOSAL) scenario2-core-eval scenario2-vote

gov-q:
../../golang/cosmos/build/agd query gov proposals --output json | \
$(AGCH) query gov proposals --output json | \
jq -c '.proposals[] | [.proposal_id,.voting_end_time,.status]'

deploy-runStake: ../run-protocol/test/runStake/runStake-deploy.js
Expand Down Expand Up @@ -87,8 +91,6 @@ scenario1-run-chain:
scenario1-run-client:
AG_SOLO_BASEDIR=$$PWD/t9/$(BASE_PORT) $(AG_SOLO) setup --network-config=http://localhost:8001/network-config --webport=$(BASE_PORT)

AGC = DEBUG=$(DEBUG) PATH="$$PWD/bin:$$PATH" $(GOSRC)/build/agd
AGCH = $(GOSRC)/build/agd
scenario2-setup: all scenario2-setup-nobuild
scenario2-setup-nobuild:
rm -rf t1
Expand Down
2 changes: 1 addition & 1 deletion packages/cosmic-swingset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
"@agoric/telemetry": "^0.1.1",
"@agoric/vats": "^0.7.0",
"@agoric/xsnap": "^0.11.2",
"@endo/far": "^0.1.9",
"@endo/import-bundle": "^0.2.41",
"@endo/init": "^0.5.37",
"@endo/marshal": "^0.6.3",
"@iarna/toml": "^2.2.3",
"@opentelemetry/sdk-metrics-base": "^0.27.0",
"agoric": "^0.14.1",
Expand Down
71 changes: 71 additions & 0 deletions packages/cosmic-swingset/scripts/clean-core-eval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#! /usr/bin/env node
import '@endo/init';
import * as farExports from '@endo/far';
import { isEntrypoint } from '../src/is-entrypoint.js';

export const compartmentEvaluate = code => {
// const permit = true;
// const powers = {};
const modules = {}; // TODO

// Inspired by ../repl.js:
const globals = harden({
...modules,
...farExports,
assert,
console: {
// Ensure we don't pollute stdout.
debug: console.warn,
log: console.warn,
info: console.warn,
warn: console.warn,
error: console.error,
},
});

// Evaluate the code in the context of the globals.
const compartment = new Compartment(globals);
harden(compartment.globalThis);
return compartment.evaluate(code);
};

export const htmlStartCommentPattern = new RegExp(`(${'<'})(!--)`, 'g');
export const htmlEndCommentPattern = new RegExp(`(--)(${'>'})`, 'g');
export const importPattern = new RegExp(
'(^|[^.])\\bimport(\\s*(?:\\(|/[/*]))',
'g',
);

// Neutralize HTML comments and import expressions.
export const defangEvaluableCode = code =>
code
.replace(importPattern, '$1import\\$2') // avoid SES_IMPORT_REJECTED
.replace(htmlStartCommentPattern, '$1\\$2') // avoid SES_HTML_COMMENT_REJECTED
.replace(htmlEndCommentPattern, '$1\\$2'); // avoid SES_HTML_COMMENT_REJECTED

export const main = async (argv, { readFile, stdout }) => {
const [_node, _script, fn] = argv;
if (fn === undefined) {
console.error(`Usage: ${_script} <filename>`);
process.exit(1);
}
const text = await readFile(fn, 'utf-8');
const clean = defangEvaluableCode(text);
const withURL = `${clean}\n//# sourceURL=${fn}\n`;

// end-of-line whitespace disrupts YAML formatting
const trimmed = withURL.replace(/[\r\t ]+$/gm, '');
compartmentEvaluate(trimmed);
stdout.write(trimmed);
};

if (isEntrypoint(import.meta.url)) {
/* global process */
main([...process.argv], {
readFile: (await import('fs/promises')).readFile,
stdout: process.stdout,
}).catch(err => {
process.exitCode = 1;
console.error(err);
});
}
7 changes: 7 additions & 0 deletions packages/cosmic-swingset/src/is-entrypoint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Detect if this is run as a script.
import url from 'url';
import process from 'process';

// FIXME: Should maybe be exported by '@endo/something'?
export const isEntrypoint = href =>
String(href) === url.pathToFileURL(process.argv[1] ?? '/').href;
2 changes: 2 additions & 0 deletions packages/cosmic-swingset/test/gov-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ const behavior = ({ consume: { client } }) => {
E(client).assignBundle([addr => ({ youAreGoverned: addr })]);
};

`import('foo')`;

// "export" our behavior by way of the completion value of this script.
behavior;
56 changes: 56 additions & 0 deletions packages/cosmic-swingset/test/test-clean-core-eval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import '@endo/init';
import test from 'ava';
import {
defangEvaluableCode,
compartmentEvaluate,
} from '../scripts/clean-core-eval.js';

test('defangEvaluableCode is working', t => {
const samples = [
[''],
[
`\n// <!-- foo\n\n`,
`\n// <\\!-- foo\n\n`,
{ message: /\(SES_HTML_COMMENT_REJECTED\)/ },
],
[
`\n// --> foo\n\n`,
`\n// --\\> foo\n\n`,
{ message: /\(SES_HTML_COMMENT_REJECTED\)/ },
],
[
`\n\`import('foo')\`\n`,
`\n\`import\\('foo')\`\n`,
{ message: /\(SES_IMPORT_REJECTED\)/ },
],
[
`\n123; import('foo')\n`,
`\n123; import\\('foo')\n`,
{ message: /\(SES_IMPORT_REJECTED\)/ },
{ message: /Invalid or unexpected token/ },
],
];
for (const [
code,
transformed,
originalExpected,
defangedExpected,
] of samples) {
const defanged = defangEvaluableCode(code);
if (originalExpected) {
// Transform is necessary, and the original code throws.
t.is(defanged, transformed);
t.throws(() => compartmentEvaluate(code), originalExpected);
} else {
// No transform is necessary, and the code doesn't throw.
t.is(defanged, code);
t.notThrows(() => compartmentEvaluate(code));
}
if (defangedExpected) {
t.throws(() => compartmentEvaluate(defanged), defangedExpected);
} else {
// The transformed code doesn't throw.
t.notThrows(() => compartmentEvaluate(defanged));
}
}
});
41 changes: 0 additions & 41 deletions packages/run-protocol/test/runStake/checkGov.js

This file was deleted.

0 comments on commit b2b0b5a

Please sign in to comment.