Skip to content

Commit

Permalink
feat(smart-wallet): upgrade walletFactory for non-vbank assets
Browse files Browse the repository at this point in the history
  - mint-ist.sh to pay for publish-bundle
    adapted from auctioneer-private-args branch
    - ensure GOV1ADDR is set
      so we don't give agd too few args and get a weird diagnostic
  - chore(walletFactory): initHandler / setHandler / upgrading
  - chore(walletFactory): start -> prepare for compat
  - chore(game contract): atomicRearrange -> zcf.reallocate() for compat
  - feat(smart-wallet): publishAgoricBrandsDisplayInfo to vstorage
  - test(smart-wallet): upgraded walletFactory handles game NFT
    - install game contract before walletFactory upgrade
    - move vat-status.mjs to tools/
    - move mint-ist, parseProposals to tools/
  - chore: split game1 proposal from walletFactory upgrade
  • Loading branch information
dckc committed Aug 24, 2023
1 parent 46a7b2e commit a0c4ecf
Show file tree
Hide file tree
Showing 19 changed files with 701 additions and 40 deletions.
5 changes: 3 additions & 2 deletions packages/builders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@
"@agoric/internal": "^0.3.2",
"@agoric/network": "^0.1.0",
"@agoric/notifier": "^0.6.2",
"@agoric/smart-wallet": "^0.5.3",
"@agoric/swingset-vat": "^0.32.2",
"@agoric/vat-data": "^0.5.2",
"@agoric/vats": "^0.15.1",
"@agoric/zoe": "^0.26.2",
"@endo/marshal": "^0.8.6",
"@endo/bundle-source": "^2.5.2",
"@endo/captp": "^3.1.2",
"@endo/eventual-send": "^0.17.3",
"@endo/init": "^0.5.57",
"@endo/far": "^0.2.19",
"@endo/init": "^0.5.57",
"@endo/marshal": "^0.8.6",
"@endo/promise-kit": "^0.2.57",
"@endo/stream": "^0.3.26",
"import-meta-resolve": "^2.2.1"
Expand Down
34 changes: 34 additions & 0 deletions packages/builders/scripts/smart-wallet/build-game1-start.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @file Proposal Builder: Start Game with non-vbank Place NFT asset
*
* Usage:
* agoric run build-game1-start.js
*/

import { makeHelpers } from '@agoric/deploy-script-support';
import { getManifestForGame1 } from '@agoric/smart-wallet/test/start-game1-proposal.js';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */
export const game1ProposalBuilder = async ({ publishRef, install }) => {
return harden({
sourceSpec: '@agoric/smart-wallet/test/start-game1-proposal.js',
getManifestCall: [
getManifestForGame1.name,
{
game1Ref: publishRef(
install(
'@agoric/smart-wallet/test/gameAssetContract.js',
'../bundles/bundle-game1.js',
{ persist: true },
),
),
},
],
});
};

/** @type {DeployScriptFunction} */
export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('start-game1', game1ProposalBuilder);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @file Proposal Builder: Upgrade walletFactory
*
* Usage:
* agoric run build-walletFactory-upgrade.js
*/

import { makeHelpers } from '@agoric/deploy-script-support';
import { getManifestForUpgrade } from '@agoric/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */
export const defaultProposalBuilder = async ({ publishRef, install }) => {
return harden({
sourceSpec:
'@agoric/smart-wallet/src/proposals/upgrade-walletFactory-proposal.js',
getManifestCall: [
getManifestForUpgrade.name,
{
walletFactoryRef: publishRef(
install(
'@agoric/smart-wallet/src/walletFactory.js',
'../bundles/bundle-walletFactory.js',
{ persist: true },
),
),
},
],
});
};

/** @type {DeployScriptFunction} */
export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('upgrade-walletFactory', defaultProposalBuilder);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
upgrade-walletFactory-permit.json
upgrade-walletFactory.js
29 changes: 25 additions & 4 deletions packages/deployment/upgrade-test/upgrade-test-scripts/agoric-upgrade-11/actions.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/bin/bash

. ./upgrade-test-scripts/env_setup.sh
# Dockerfile in upgrade-test sets:
# WORKDIR /usr/src/agoric-sdk/
# Overriding it during development has occasionally been useful.
SDK=${SDK:-/usr/src/agoric-sdk}
. $SDK/upgrade-test-scripts/env_setup.sh

# Enable debugging
set -x

# CWD is agoric-sdk
upgrade11=./upgrade-test-scripts/agoric-upgrade-11

# hacky restore of pruned artifacts
killAgd
EXPORT_DIR=$(mktemp -t -d swing-store-export-upgrade-11-XXX)
Expand Down Expand Up @@ -46,6 +47,26 @@ test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.
test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.locked.value') "0" "vault3 contains no collateral"
test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault3 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault3 has no debt"
upgrade11=$SDK/upgrade-test-scripts/agoric-upgrade-11
cd $upgrade11
## build proposal and install bundles
waitForBlock 2
./tools/mint-ist.sh
./wallet-all-ertp/wf-install-bundles.sh
## upgrade wallet factory
./wallet-all-ertp/wf-propose.sh
## start game1
./wallet-all-ertp/wf-game-propose.sh
# Pay 0.25IST join the game and get some places
node ./wallet-all-ertp/gen-game-offer.mjs Shire Mordor >/tmp/,join.json
agops perf satisfaction --from $GOV1ADDR --executeOffer /tmp/,join.json --keyring-backend=test
cd $SDK
######################################################################
# FIXME: remove this line when these tests don't hardcode bundle hashes.
echo 1>&2 "FIXME: skipping zoe-full-upgrade tests"; return 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ waitForBlock 5
# CWD is agoric-sdk
upgrade11=./upgrade-test-scripts/agoric-upgrade-11

test_val "$(agd query vstorage children published.boardAux -o json | jq .children)" "[]" "no boardAux children yet"

# zoe vat is at incarnation 0
test_val "$(yarn --silent node $upgrade11/vat-status.mjs zoe)" "0" "zoe vat incarnation"
test_val "$(yarn --silent node $upgrade11/tools/vat-status.mjs zoe)" "0" "zoe vat incarnation"

# validate agoric-upgrade-10 metrics after update

Expand All @@ -30,4 +32,3 @@ test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.
test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.vaultState') "closed" "vault2 is closed"
test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.locked.value') "0" "vault2 contains no collateral"
test_val $(agoric follow -l -F :published.vaultFactory.managers.manager0.vaults.vault2 -o jsonlines | jq -r '.debtSnapshot.debt.value') "0" "vault2 has no debt"

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,48 @@ mv $TMP_GENESIS_DIR/* $HOME/.agoric/config/
startAgd
rm -rf $EXPORT_DIR

testMinChildren() {
path=$1
min=$2
line="$(agd query vstorage children $path -o jsonlines)"
ok=$(echo $line | jq ".children | length | . > $min")
test_val "$ok" "true" "$path: more than $min children"
}

# Check brand aux data for more than just vbank assets
testMinChildren published.boardAux 3

testDisplayInfo() {
name=$1
expected=$2

line="$(agoric follow -lF :published.agoricNames.brand -o text)"
# find brand by name, then corresponding slot
id=$(echo $line | jq --arg name "$name" -r '.slots as $slots | .body | gsub("^#";"") | fromjson | .[] | select(.[0] == $name) | .[1] | capture("^[$](?<slot>0|[1-9][0-9]*)") | .slot | $slots[. | tonumber]')
echo $name Id: $id

line="$(agoric follow -lF :published.boardAux.$id -o jsonlines)"
displayInfo="$(echo $line | jq -c .displayInfo)"
test_val "$displayInfo" "$expected" "$name displayInfo from boardAux"
}

testDisplayInfo IST '{"assetKind":"nat","decimalPlaces":6}'

testPurseValuePayload() {
addr=$1
wkAsset=$2
expected=$3

line="$(agoric follow -lF :published.wallet.$addr.current -o jsonlines)"
# HACK: selecting brand by allegedName
payload=$(echo $line | jq --arg name "$wkAsset" -c '.purses[] | select(.brand | contains($name)) | .balance.value.payload')
test_val "$payload" "$expected" "$wkAsset purse for $addr"
}

# Smart wallet handles game Place assets?
testDisplayInfo Place '{"assetKind":"copyBag"}'
testPurseValuePayload $GOV1ADDR Place '[["Shire","1"],["Mordor","1"]]'

# zoe vat is at incarnation 1
echo "FIXME: bypassed zoe-full-upgrade validation"; return 0
test_val "$(yarn --silent node $upgrade11/vat-status.mjs zoe)" "1" "zoe vat incarnation"
test_val "$(yarn --silent node $upgrade11/tools/vat-status.mjs zoe)" "1" "zoe vat incarnation"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

if [ -z "$GOV1ADDR" ]; then
echo run env_setup.sh to set GOV1ADDR
exit 1
fi

micro=000000

# send some collateral to gov1
agd tx bank send validator $GOV1ADDR 20123$micro${ATOM_DENOM} \
--keyring-backend=test --chain-id=agoriclocal --yes -bblock -o json

export PATH=/usr/src/agoric-sdk/packages/agoric-cli/bin:$PATH
agops vaults open --giveCollateral 5000 --wantMinted 20000 > /tmp/offer.json
agops perf satisfaction --executeOffer /tmp/offer.json --from gov1 --keyring-backend=test
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env node

import fs from 'fs';

const Fail = (template, ...args) => {
throw Error(String.raw(template, ...args.map(val => String(val))));
};

/**
* Parse output of `agoric run proposal-builder.js`
*
* @param {string} txt
*
* adapted from packages/boot/test/bootstrapTests/supports.js
*/
const parseProposalParts = txt => {
const evals = [
...txt.matchAll(/swingset-core-eval (?<permit>\S+) (?<script>\S+)/g),
].map(m => {
if (!m.groups) throw Fail`Invalid proposal output ${m[0]}`;
const { permit, script } = m.groups;
return { permit, script };
});
evals.length || Fail`No swingset-core-eval found in proposal output: ${txt}`;

const bundles = [...txt.matchAll(/swingset install-bundle @([^\n]+)/gm)].map(
([, bundle]) => bundle,
);
bundles.length || Fail`No bundles found in proposal output: ${txt}`;

return { evals, bundles };
};

const main = (stdin, readFileSync) => {
const input = readFileSync(stdin.fd).toString();
const parts = parseProposalParts(input);
// relies on console.log printing to stdout unmodified
console.log(JSON.stringify(parts));
};

main(process.stdin, fs.readFileSync);
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/* eslint-disable @jessie.js/safe-await-separator */
/* global process */
import assert from 'assert';
import { execFile } from 'child_process';

const ISTunit = 1_000_000n; // aka displayInfo: { decimalPlaces: 6 }
const CENT = ISTunit / 100n;

const [_node, _script, ...choices] = process.argv;

const toSec = ms => BigInt(Math.round(ms / 1000));

const id = `join-${Date.now()}`;

// look up boardIDs for brands, instances in agoricNames

// poor-man's zx
const $ = cmd => {
console.error(cmd);
const [file, ...args] = cmd.split(' ');

return new Promise((resolve, reject) => {
execFile(file, args, { encoding: 'utf8' }, (err, out) => {
if (err) return reject(err);
resolve(out);
});
});
};

const zip = (xs, ys) => xs.map((x, i) => [x, ys[i]]);
const fromSmallCapsEntries = txt => {
const { body, slots } = JSON.parse(txt);
const theEntries = zip(JSON.parse(body.slice(1)), slots).map(
([[name, ref], boardID]) => {
const iface = ref.replace(/^\$\d+\./, '');
return [name, { iface, boardID }];
},
);
return Object.fromEntries(theEntries);
};

const wkInstance = fromSmallCapsEntries(
await $('agoric follow -lF :published.agoricNames.instance -o text'),
);
assert(wkInstance.VaultFactory);

const wkBrand = fromSmallCapsEntries(
await $('agoric follow -lF :published.agoricNames.brand -o text'),
);
assert(wkBrand.IST);
assert(wkBrand.Place);

const slots = []; // XXX global mutable state

// XXX should use @endo/marshal
const smallCaps = {
Nat: n => `+${n}`,
replacer: (k, v) =>
typeof v === 'bigint'
? `+${v}`
: typeof v === 'symbol'
? `%${v.description}`
: v,
// XXX mutates obj
ref: obj => {
if (obj.ix) return obj.ix;
const ix = slots.length;
slots.push(obj.boardID);
obj.ix = `$${ix}.Alleged: ${obj.iface}`;
return obj.ix;
},
};

const AmountMath = {
make: (brand, value) => ({
brand: smallCaps.ref(brand),
value: typeof value === 'bigint' ? smallCaps.Nat(value) : value,
}),
};

const makeTagged = (tag, payload) => ({
'#tag': tag,
payload,
});

const makeCopyBag = entries => makeTagged('copyBag', entries);
const want = {
Places: AmountMath.make(
wkBrand.Place,
makeCopyBag(choices.map(name => [name, 1n])),
),
};

const give = { Price: AmountMath.make(wkBrand.IST, 25n * CENT) };
const body = {
method: 'executeOffer',
offer: {
id,
invitationSpec: {
source: 'contract',
instance: smallCaps.ref(wkInstance.game1),
publicInvitationMaker: 'makeJoinInvitation',
},
proposal: { give, want },
},
};

console.error(JSON.stringify(body.offer, smallCaps.replacer, 1));

const capData = {
body: `#${JSON.stringify(body, smallCaps.replacer)}`,
slots,
};
const action = JSON.stringify(capData);

console.log(action);
Loading

0 comments on commit a0c4ecf

Please sign in to comment.