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: 53:kread-start proposal #16

Merged
merged 12 commits into from
Nov 9, 2023
3 changes: 3 additions & 0 deletions proposals/53:kread-start/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "/agoric.swingset.CoreEvalProposal"
}
151 changes: 151 additions & 0 deletions proposals/53:kread-start/core-eval-support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// @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
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is necessary for tests. The arguments I've heard for minimizing ambient authority don't apply:

  • testability (this is the test itself)
  • security (this is a test environment)

The levels of indirection with io in this repo are just cognitive overhead imo

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we haven't made much progress in convincing each other.

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 see it the other way around: it's not necessary to sprinkle ambient authority all over test code. That would be more cognitive overhead, for me.

// 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 });
};

/**
* Asserts that `haystack` includes `needle` (or when `sense` is false, that it
* does not), providing pretty output in the case of failure.
*
* @param {import('ava').ExecutionContext} t
* @param {unknown} needle
* @param {unknown[]} haystack
* @param {string} label
* @param {boolean} [sense] true to assert inclusion; false for exclusion
* @returns {void}
*/
export const testIncludes = (t, needle, haystack, label, sense = true) => {
const matches = haystack.filter(c => Object.is(c, needle));
t.deepEqual(matches, sense ? [needle] : [], label);
};

/**
* @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);
};
12 changes: 12 additions & 0 deletions proposals/53:kread-start/eval.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

# Exit when any command fails
set -e

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

ls -al

# XXX using Ava serial to script the core-eval
yarn ava mn2-start.test.js

Loading