Skip to content

Commit

Permalink
test: upgrade tests for 8488 smartWallet with promiseWatchers
Browse files Browse the repository at this point in the history
Inserted walletFactory as a:

built submission files in #8488

enhanced vat-status.js to look up vats by name (as substring)
  • Loading branch information
Chris-Hibbert committed Nov 29, 2023
1 parent 3ed7ca8 commit 8dd4670
Show file tree
Hide file tree
Showing 18 changed files with 2,920 additions and 12 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ If the proposal is _pending_ and does not yet have a number, use a letter. The p

## Development

```
npm install -g tsx
```

To build the test images,

```
Expand Down
46 changes: 46 additions & 0 deletions debugTestImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env tsx
/**
* @file like runTestImages.ts, but for a single proposal,
* and with a bash entrypoint
*/
import { parseArgs } from 'node:util';
import { execSync } from 'node:child_process';
import { imageNameForProposalTest, readProposals } from './common';
import assert from 'node:assert';

const options = {
match: { short: 'm', type: 'string' },
} as const;
const { values } = parseArgs({ options });

const { match } = values;

const allProposals = readProposals();

const proposals = match
? allProposals.filter(p => p.proposalName.includes(match))
: allProposals;

assert(proposals.length > 0, 'no proposals match');
assert(proposals.length === 1, 'too many proposals match');

for (const proposal of proposals) {
console.log(
`Starting shell of test image for proposal ${proposal.proposalName}`,
);
// SLOGFILE isn't in the regular build because it's huge
console.log('If you want a SLOGFILE:');
console.log(' export SLOGFILE=slog.slog');
console.log(
'At the shell prompt, run the following command to start a chain:',
);
console.log(' agd start --log_level warn');
console.log('And then this to get a shell:');
console.log(
' docker exec -it `docker ps --latest --format json | jq -r .Names` bash',
);
const { name } = imageNameForProposalTest(proposal);
// start the chain
const cmd = `docker run -it --entrypoint bash ${name}`;
execSync(cmd, { stdio: 'inherit' });
}
1 change: 1 addition & 0 deletions proposals/a:wallet-factory1/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
17 changes: 17 additions & 0 deletions proposals/a:wallet-factory1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Proposal to upgrade Smart Wallet to incarnation 1

This uses the smart Wallet code in https://github.com/Agoric/agoric-sdk/pull/8488

It's currently a draft proposal, built from that branch with,

```
# whatever your checkout
A3P=/opt/agoric/agoric-3-proposals
cd packages/builders
# build the proposal
agoric run scripts/vats/upgrade-wallet-factory.js | tee run-report.txt
# copy the proposal
cp upgrade-wallet-factory* $A3P/proposals/c:wallet-factory/submission
# copy the bundles built for the proposal
cat run-report.txt | grep install-bundle | sed "s/agd tx swingset install-bundle @//" |xargs -I _ cp _ $A3P/proposals/c:wallet-factory1/submission
```
3 changes: 3 additions & 0 deletions proposals/a:wallet-factory1/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "/agoric.swingset.CoreEvalProposal"
}
135 changes: 135 additions & 0 deletions proposals/a:wallet-factory1/core-eval-support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// @ts-check
import {
Far,
makeMarshal,
makeTranslationTable,
} from '../../upgrade-test-scripts/lib/unmarshal.js';
import { Fail, NonNullish } from '../../upgrade-test-scripts/lib/assert.js';

// TODO: factor out ambient authority from these
// or at least allow caller to supply authority.
import { mintIST } from '../../upgrade-test-scripts/lib/econHelpers.js';
import { agoric } from '../../upgrade-test-scripts/lib/cliHelper.js';

// move to unmarshal.js?
const makeBoardUnmarshal = () => {
const synthesizeRemotable = (_slot, iface) =>
Far(iface.replace(/^Alleged: /, ''), {});

const { convertValToSlot, convertSlotToVal } = makeTranslationTable(
slot => Fail`unknown id: ${slot}`,
synthesizeRemotable,
);

return makeMarshal(convertValToSlot, convertSlotToVal);
};

export const getContractInfo = async (path, io = {}) => {
const m = makeBoardUnmarshal();
const {
agoric: { follow = agoric.follow },
prefix = 'published.',
} = io;
console.log('@@TODO: prevent agoric follow hang', prefix, path);
const txt = await follow('-lF', `:${prefix}${path}`, '-o', 'text');
const { body, slots } = JSON.parse(txt);
return m.fromCapData({ body, slots });
};

/**
* @param {Record<string, string>} record - e.g. { color: 'blue' }
* @returns {string[]} - e.g. ['--color', 'blue']
*/
export const flags = record => {
return Object.entries(record)
.map(([k, v]) => [`--${k}`, v])
.flat();
};

export const txAbbr = tx => {
const { txhash, code, height, gas_used } = tx;
return { txhash, code, height, gas_used };
};

export const loadedBundleIds = swingstore => {
const ids = swingstore`SELECT bundleID FROM bundles`.map(r => r.bundleID);
return ids;
};

/**
* @param {string} cacheFn - e.g. /home/me.agoric/cache/b1-DEADBEEF.json
*/
export const bundleDetail = cacheFn => {
const fileName = NonNullish(cacheFn.split('/').at(-1));
const id = fileName.replace(/\.json$/, '');
const hash = id.replace(/^b1-/, '');
return { fileName, endoZipBase64Sha512: hash, id };
};

const importBundleCost = (bytes, price = 0.002) => {
return bytes * price;
};

/**
* @typedef {{
* bundles: string[],
* evals: { permit: string; script: string }[],
* }} ProposalInfo
*/

const myISTBalance = async (agd, addr, denom = 'uist', unit = 1_000_000) => {
const coins = await agd.query(['bank', 'balances', addr]);
const coin = coins.balances.find(a => a.denom === denom);
return Number(coin.amount) / unit;
};

/**
* @param {number} myIST
* @param {number} cost
* @param {{
* unit?: number, padding?: number, minInitialDebt?: number,
* collateralPrice: number,
* }} opts
* @returns
*/
const mintCalc = (myIST, cost, opts) => {
const {
unit = 1_000_000,
padding = 1,
minInitialDebt = 6,
collateralPrice,
} = opts;
const { round, max } = Math;
const wantMinted = max(round(cost - myIST + padding), minInitialDebt);
const giveCollateral = round(wantMinted / collateralPrice) + 1;
const sendValue = round(giveCollateral * unit);
return { wantMinted, giveCollateral, sendValue };
};

/**
*
* @param {ReturnType<typeof import('../lib/agd-lib.js').makeAgd>} agd
* @param {*} config
* @param {number} bytes total bytes
* @param {{ log: (...args: any[]) => void }} io
* @returns
*/
export const ensureISTForInstall = async (agd, config, bytes, { log }) => {
const cost = importBundleCost(bytes);
log({ totalSize: bytes, cost });
const { installer } = config;
const addr = agd.lookup(installer);
const istBalance = await myISTBalance(agd, addr);

if (istBalance > cost) {
log('balance sufficient', { istBalance, cost });
return;
}
const { sendValue, wantMinted, giveCollateral } = mintCalc(
istBalance,
cost,
config,
);
log({ wantMinted });
await mintIST(addr, sendValue, wantMinted, giveCollateral);
};
15 changes: 15 additions & 0 deletions proposals/a:wallet-factory1/eval.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

# Exit when any command fails
set -e

source /usr/src/upgrade-test-scripts/env_setup.sh

ls -al

npm install --global tsx

./performActions.ts

# let CORE_EVAL settle
waitForBlock 5
15 changes: 15 additions & 0 deletions proposals/a:wallet-factory1/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"type": "module",
"license": "Apache-2.0",
"dependencies": {
"@endo/zip": "^0.2.35",
"ava": "^5.3.1",
"better-sqlite3": "^8.5.1",
"execa": "^7.2.0",
"tmp": "^0.2.1"
},
"scripts": {
"agops": "yarn --cwd /usr/src/agoric-sdk/ --silent agops"
},
"packageManager": "[email protected]"
}
Loading

0 comments on commit 8dd4670

Please sign in to comment.