Skip to content

Commit

Permalink
feat(cosmic-swingset): add attenuated vattp to fake chain clients
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Aug 2, 2020
1 parent cf5566f commit e6f6aeb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 90 deletions.
9 changes: 8 additions & 1 deletion packages/cosmic-swingset/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,16 @@ scenario2-run-chain:
$(AGC) `$(BREAK_CHAIN) && echo --inspect-brk` --home=t1/n0 start --pruning=nothing

# Provision and start a client.
scenario2-run-client: t1-provision-one t1-start-ag-solo
scenario2-run-client: t1-provision-one-with-powers t1-start-ag-solo

# Provision the ag-solo from an provisionpass-holding address (idempotent).
t1-provision-one-with-powers:
addr=$$(cat t1/$(BASE_PORT)/ag-cosmos-helper-address); \
$(AGCH) --home=t1/bootstrap query swingset egress $$addr --chain-id=$(CHAIN_ID) || \
$(AGCH) --home=t1/bootstrap tx swingset provision-one --keyring-backend=test --from=bootstrap \
--gas=auto --gas-adjustment=1.3 --broadcast-mode=block --yes --chain-id=$(CHAIN_ID) \
t1/$(BASE_PORT) $$addr agoric.vattp.makeNetworkHost | tee /dev/stderr | grep -q 'code: 0'

t1-provision-one:
addr=$$(cat t1/$(BASE_PORT)/ag-cosmos-helper-address); \
$(AGCH) --home=t1/bootstrap query swingset egress $$addr --chain-id=$(CHAIN_ID) || \
Expand Down
6 changes: 5 additions & 1 deletion packages/cosmic-swingset/lib/ag-solo/fake-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export async function connectToFakeChain(basedir, GCI, role, delay, inbound) {
const mailboxStorage = await readMap(mailboxFile);

const vatsdir = path.join(basedir, 'vats');
const argv = [`--role=${role}`, bootAddress];
const argv = [
`--role=${role}`,
`--give-me-all-the-agoric-powers`,
bootAddress,
];
const stateDBdir = path.join(basedir, `fake-chain-${GCI}-state`);
function doOutboundBridge(dstID, _obj) {
// console.error('received', dstID, obj);
Expand Down
153 changes: 65 additions & 88 deletions packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,13 @@ import { makeBridgeManager } from './bridge';

const NUM_IBC_PORTS = 3;

// The old way of provisioning used an environment variable that
// was an account ACL. The new way uses "provisionpass", a
// "bearer token" that is checked in handler.go before a provision
// transaction is even sent to the JS side.
const FIXME_DEPRECATED_BOOT_ADDRESS = true;

console.debug(`loading bootstrap.js`);

function parseArgs(argv) {
let ROLE;
let gotRoles = false;
let bootAddress;
const additionalAddresses = [];
const hardcodedClientAddresses = [];
let giveMeAllTheAgoricPowers = false;
argv.forEach(arg => {
const match = arg.match(/^--role=(.*)$/);
if (match) {
Expand All @@ -35,24 +29,22 @@ function parseArgs(argv) {
}
[, ROLE] = match;
gotRoles = true;
} else if (!arg.match(/^-/)) {
if (!bootAddress) {
bootAddress = arg;
} else {
additionalAddresses.push(arg);
}
} else if (arg === `--give-me-all-the-agoric-powers`) {
console.warn(`Giving all the Agoric powers to the client!`);
giveMeAllTheAgoricPowers = true;
} else if (arg.match(/^-/)) {
throw Error(`Unrecognized option ${arg}`);
} else {
hardcodedClientAddresses.push(arg);
}
});
if (!gotRoles) {
ROLE = 'three_client';
}

return [ROLE, bootAddress, additionalAddresses];
return { ROLE, giveMeAllTheAgoricPowers, hardcodedClientAddresses };
}

// Used in scenario 1 for coordinating on an index for registering public keys
// while requesting provisioning.
const KEY_REG_INDEX = 1;
// Used for coordinating on an index in comms for the provisioning service
const PROVISIONER_INDEX = 1;

Expand All @@ -75,7 +67,12 @@ export function buildRootObject(vatPowers) {
}

// Make services that are provided on the real or virtual chain side
async function makeChainBundler(vats, timerDevice, vatAdminSvc) {
async function makeChainBundler(
vats,
timerDevice,
vatAdminSvc,
giveMeAllTheAgoricPowers = false,
) {
// Create singleton instances.
const [
sharingService,
Expand Down Expand Up @@ -112,15 +109,31 @@ export function buildRootObject(vatPowers) {
);

return harden({
async createUserBundle(_nickname) {
async createUserBundle(_nickname, powerFlags = []) {
// Bind to some fresh ports (unspecified name) on the IBC implementation
// and provide them for the user to have.
const ibcport = [];
for (let i = 0; i < NUM_IBC_PORTS; i += 1) {
// eslint-disable-next-line no-await-in-loop
ibcport.push(await E(vats.network).bind('/ibc-port/'));
}

const additionalPowers = {};
const { vattp, comms } = vats;
if (
giveMeAllTheAgoricPowers ||
powerFlags.includes('agoric.vattp.makeNetworkHost')
) {
// Give the authority to create a new host for vattp to share objects with.
additionalPowers.vattp = {
makeNetworkHost(allegedName) {
return E(vattp).makeNetworkHost(allegedName, comms);
},
};
}

const bundle = harden({
...additionalPowers,
chainTimerService,
sharingService,
contractHost,
Expand Down Expand Up @@ -287,7 +300,11 @@ export function buildRootObject(vatPowers) {
async bootstrap(argv, vats, devices) {
const bridgeManager =
devices.bridge && makeBridgeManager(E, D, devices.bridge);
const [ROLE, bootAddress, additionalAddresses] = parseArgs(argv);
const {
ROLE,
giveMeAllTheAgoricPowers,
hardcodedClientAddresses,
} = parseArgs(argv);

async function addRemote(addr) {
const { transmitter, setReceiver } = await E(vats.vattp).addRemote(
Expand All @@ -298,12 +315,6 @@ export function buildRootObject(vatPowers) {

D(devices.mailbox).registerInboundHandler(vats.vattp);
await E(vats.vattp).registerMailboxDevice(devices.mailbox);
if (FIXME_DEPRECATED_BOOT_ADDRESS && bootAddress) {
// FIXME: The old way: register egresses for the addresses.
await Promise.all(
[bootAddress, ...additionalAddresses].map(addr => addRemote(addr)),
);
}

const vatAdminSvc = await E(vats.vatAdmin).createVatAdminService(
devices.vatAdmin,
Expand All @@ -315,6 +326,7 @@ export function buildRootObject(vatPowers) {
// client (python) on localhost, which creates client solo node on
// localhost, with HTML frontend. Multi-player mode.
switch (ROLE) {
// REAL VALIDATORS run this.
case 'chain':
case 'one_chain': {
// provisioning vat can ask the demo server for bundles, and can
Expand All @@ -327,56 +339,9 @@ export function buildRootObject(vatPowers) {

// Must occur after makeChainBundler.
await registerNetworkProtocols(vats, bridgeManager);

if (FIXME_DEPRECATED_BOOT_ADDRESS && bootAddress) {
// accept provisioning requests from the controller
const provisioner = harden({
pleaseProvision(nickname, pubkey) {
console.debug('Provisioning', nickname, pubkey);
return E(vats.provisioning).pleaseProvision(
nickname,
pubkey,
PROVISIONER_INDEX,
);
},
});
// bootAddress holds the pubkey of controller
await E(vats.comms).addEgress(
bootAddress,
KEY_REG_INDEX,
provisioner,
);
}
break;
}
case 'controller':
case 'one_controller': {
if (!GCI) {
throw new Error(`controller must be given GCI`);
}

await registerNetworkProtocols(vats, bridgeManager);

// Wire up the http server.
await setupCommandDevice(vats.http, devices.command, {
controller: true,
});
// Create a presence for the on-chain provisioner.
await addRemote(GCI);
const chainProvisioner = await E(vats.comms).addIngress(
GCI,
KEY_REG_INDEX,
);
// Allow web requests from the provisioning server to call our
// provisioner object.
const provisioner = harden({
pleaseProvision(nickname, pubkey) {
return E(chainProvisioner).pleaseProvision(nickname, pubkey);
},
});
await E(vats.http).setProvisioner(provisioner);
break;
}
// ag-setup-solo runs this.
case 'client':
case 'one_client': {
if (!GCI) {
Expand Down Expand Up @@ -421,6 +386,7 @@ export function buildRootObject(vatPowers) {
vats,
devices.timer,
vatAdminSvc,
giveMeAllTheAgoricPowers,
);

// Allow manual provisioning requests via `agoric cosmos`.
Expand All @@ -431,19 +397,30 @@ export function buildRootObject(vatPowers) {
);

await registerNetworkProtocols(vats, bridgeManager);
if (FIXME_DEPRECATED_BOOT_ADDRESS && bootAddress) {
const demoProvider = harden({
// build a chain-side bundle for a client.
async getDemoBundle(nickname) {
return chainBundler.createUserBundle(nickname);
},
});
await Promise.all(
[bootAddress, ...additionalAddresses].map(addr =>
E(vats.comms).addEgress(addr, PROVISIONER_INDEX, demoProvider),
),
);
}

// Allow some hardcoded client address connections into the chain.
// This is necessary for fake-chain, which does not have Cosmos SDK
// transactions to provision its client.
const demoProvider = harden({
// build a chain-side bundle for a client.
async getDemoBundle(nickname) {
return chainBundler.createUserBundle(nickname);
},
});
await Promise.all(
hardcodedClientAddresses.map(async addr => {
const { transmitter, setReceiver } = await E(
vats.vattp,
).addRemote(addr);
await E(vats.comms).addRemote(addr, transmitter, setReceiver);
await E(vats.comms).addEgress(
addr,
PROVISIONER_INDEX,
demoProvider,
);
}),
);

break;
}
case 'two_client': {
Expand Down

0 comments on commit e6f6aeb

Please sign in to comment.