Skip to content

Commit e6f6aeb

Browse files
committed
feat(cosmic-swingset): add attenuated vattp to fake chain clients
1 parent cf5566f commit e6f6aeb

File tree

3 files changed

+78
-90
lines changed

3 files changed

+78
-90
lines changed

packages/cosmic-swingset/Makefile

+8-1
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,16 @@ scenario2-run-chain:
9494
$(AGC) `$(BREAK_CHAIN) && echo --inspect-brk` --home=t1/n0 start --pruning=nothing
9595

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

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

packages/cosmic-swingset/lib/ag-solo/fake-chain.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ export async function connectToFakeChain(basedir, GCI, role, delay, inbound) {
4040
const mailboxStorage = await readMap(mailboxFile);
4141

4242
const vatsdir = path.join(basedir, 'vats');
43-
const argv = [`--role=${role}`, bootAddress];
43+
const argv = [
44+
`--role=${role}`,
45+
`--give-me-all-the-agoric-powers`,
46+
bootAddress,
47+
];
4448
const stateDBdir = path.join(basedir, `fake-chain-${GCI}-state`);
4549
function doOutboundBridge(dstID, _obj) {
4650
// console.error('received', dstID, obj);

packages/cosmic-swingset/lib/ag-solo/vats/bootstrap.js

+65-88
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,13 @@ import { makeBridgeManager } from './bridge';
1414

1515
const NUM_IBC_PORTS = 3;
1616

17-
// The old way of provisioning used an environment variable that
18-
// was an account ACL. The new way uses "provisionpass", a
19-
// "bearer token" that is checked in handler.go before a provision
20-
// transaction is even sent to the JS side.
21-
const FIXME_DEPRECATED_BOOT_ADDRESS = true;
22-
2317
console.debug(`loading bootstrap.js`);
2418

2519
function parseArgs(argv) {
2620
let ROLE;
2721
let gotRoles = false;
28-
let bootAddress;
29-
const additionalAddresses = [];
22+
const hardcodedClientAddresses = [];
23+
let giveMeAllTheAgoricPowers = false;
3024
argv.forEach(arg => {
3125
const match = arg.match(/^--role=(.*)$/);
3226
if (match) {
@@ -35,24 +29,22 @@ function parseArgs(argv) {
3529
}
3630
[, ROLE] = match;
3731
gotRoles = true;
38-
} else if (!arg.match(/^-/)) {
39-
if (!bootAddress) {
40-
bootAddress = arg;
41-
} else {
42-
additionalAddresses.push(arg);
43-
}
32+
} else if (arg === `--give-me-all-the-agoric-powers`) {
33+
console.warn(`Giving all the Agoric powers to the client!`);
34+
giveMeAllTheAgoricPowers = true;
35+
} else if (arg.match(/^-/)) {
36+
throw Error(`Unrecognized option ${arg}`);
37+
} else {
38+
hardcodedClientAddresses.push(arg);
4439
}
4540
});
4641
if (!gotRoles) {
4742
ROLE = 'three_client';
4843
}
4944

50-
return [ROLE, bootAddress, additionalAddresses];
45+
return { ROLE, giveMeAllTheAgoricPowers, hardcodedClientAddresses };
5146
}
5247

53-
// Used in scenario 1 for coordinating on an index for registering public keys
54-
// while requesting provisioning.
55-
const KEY_REG_INDEX = 1;
5648
// Used for coordinating on an index in comms for the provisioning service
5749
const PROVISIONER_INDEX = 1;
5850

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

7769
// Make services that are provided on the real or virtual chain side
78-
async function makeChainBundler(vats, timerDevice, vatAdminSvc) {
70+
async function makeChainBundler(
71+
vats,
72+
timerDevice,
73+
vatAdminSvc,
74+
giveMeAllTheAgoricPowers = false,
75+
) {
7976
// Create singleton instances.
8077
const [
8178
sharingService,
@@ -112,15 +109,31 @@ export function buildRootObject(vatPowers) {
112109
);
113110

114111
return harden({
115-
async createUserBundle(_nickname) {
112+
async createUserBundle(_nickname, powerFlags = []) {
116113
// Bind to some fresh ports (unspecified name) on the IBC implementation
117114
// and provide them for the user to have.
118115
const ibcport = [];
119116
for (let i = 0; i < NUM_IBC_PORTS; i += 1) {
120117
// eslint-disable-next-line no-await-in-loop
121118
ibcport.push(await E(vats.network).bind('/ibc-port/'));
122119
}
120+
121+
const additionalPowers = {};
122+
const { vattp, comms } = vats;
123+
if (
124+
giveMeAllTheAgoricPowers ||
125+
powerFlags.includes('agoric.vattp.makeNetworkHost')
126+
) {
127+
// Give the authority to create a new host for vattp to share objects with.
128+
additionalPowers.vattp = {
129+
makeNetworkHost(allegedName) {
130+
return E(vattp).makeNetworkHost(allegedName, comms);
131+
},
132+
};
133+
}
134+
123135
const bundle = harden({
136+
...additionalPowers,
124137
chainTimerService,
125138
sharingService,
126139
contractHost,
@@ -287,7 +300,11 @@ export function buildRootObject(vatPowers) {
287300
async bootstrap(argv, vats, devices) {
288301
const bridgeManager =
289302
devices.bridge && makeBridgeManager(E, D, devices.bridge);
290-
const [ROLE, bootAddress, additionalAddresses] = parseArgs(argv);
303+
const {
304+
ROLE,
305+
giveMeAllTheAgoricPowers,
306+
hardcodedClientAddresses,
307+
} = parseArgs(argv);
291308

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

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

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

328340
// Must occur after makeChainBundler.
329341
await registerNetworkProtocols(vats, bridgeManager);
330-
331-
if (FIXME_DEPRECATED_BOOT_ADDRESS && bootAddress) {
332-
// accept provisioning requests from the controller
333-
const provisioner = harden({
334-
pleaseProvision(nickname, pubkey) {
335-
console.debug('Provisioning', nickname, pubkey);
336-
return E(vats.provisioning).pleaseProvision(
337-
nickname,
338-
pubkey,
339-
PROVISIONER_INDEX,
340-
);
341-
},
342-
});
343-
// bootAddress holds the pubkey of controller
344-
await E(vats.comms).addEgress(
345-
bootAddress,
346-
KEY_REG_INDEX,
347-
provisioner,
348-
);
349-
}
350-
break;
351-
}
352-
case 'controller':
353-
case 'one_controller': {
354-
if (!GCI) {
355-
throw new Error(`controller must be given GCI`);
356-
}
357-
358-
await registerNetworkProtocols(vats, bridgeManager);
359-
360-
// Wire up the http server.
361-
await setupCommandDevice(vats.http, devices.command, {
362-
controller: true,
363-
});
364-
// Create a presence for the on-chain provisioner.
365-
await addRemote(GCI);
366-
const chainProvisioner = await E(vats.comms).addIngress(
367-
GCI,
368-
KEY_REG_INDEX,
369-
);
370-
// Allow web requests from the provisioning server to call our
371-
// provisioner object.
372-
const provisioner = harden({
373-
pleaseProvision(nickname, pubkey) {
374-
return E(chainProvisioner).pleaseProvision(nickname, pubkey);
375-
},
376-
});
377-
await E(vats.http).setProvisioner(provisioner);
378342
break;
379343
}
344+
// ag-setup-solo runs this.
380345
case 'client':
381346
case 'one_client': {
382347
if (!GCI) {
@@ -421,6 +386,7 @@ export function buildRootObject(vatPowers) {
421386
vats,
422387
devices.timer,
423388
vatAdminSvc,
389+
giveMeAllTheAgoricPowers,
424390
);
425391

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

433399
await registerNetworkProtocols(vats, bridgeManager);
434-
if (FIXME_DEPRECATED_BOOT_ADDRESS && bootAddress) {
435-
const demoProvider = harden({
436-
// build a chain-side bundle for a client.
437-
async getDemoBundle(nickname) {
438-
return chainBundler.createUserBundle(nickname);
439-
},
440-
});
441-
await Promise.all(
442-
[bootAddress, ...additionalAddresses].map(addr =>
443-
E(vats.comms).addEgress(addr, PROVISIONER_INDEX, demoProvider),
444-
),
445-
);
446-
}
400+
401+
// Allow some hardcoded client address connections into the chain.
402+
// This is necessary for fake-chain, which does not have Cosmos SDK
403+
// transactions to provision its client.
404+
const demoProvider = harden({
405+
// build a chain-side bundle for a client.
406+
async getDemoBundle(nickname) {
407+
return chainBundler.createUserBundle(nickname);
408+
},
409+
});
410+
await Promise.all(
411+
hardcodedClientAddresses.map(async addr => {
412+
const { transmitter, setReceiver } = await E(
413+
vats.vattp,
414+
).addRemote(addr);
415+
await E(vats.comms).addRemote(addr, transmitter, setReceiver);
416+
await E(vats.comms).addEgress(
417+
addr,
418+
PROVISIONER_INDEX,
419+
demoProvider,
420+
);
421+
}),
422+
);
423+
447424
break;
448425
}
449426
case 'two_client': {

0 commit comments

Comments
 (0)