Skip to content

Commit

Permalink
Merge pull request Agoric#11 from Agoric/gallery-demo
Browse files Browse the repository at this point in the history
Gallery demo
  • Loading branch information
erights authored Jun 13, 2019
2 parents 1971700 + 09a97c8 commit 4bffd92
Show file tree
Hide file tree
Showing 24 changed files with 1,604 additions and 309 deletions.
9 changes: 7 additions & 2 deletions core/contractHost.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { insist } from '../util/insist';
import { mustBeSameStructure, allComparable } from '../util/sameStructure';
import { makeUniAssayMaker } from './assays';
import { makeMint } from './issuers';
import { makeBasicMintController } from './mintController';
import makePromise from '../util/makePromise';

function makeContractHost(E, evaluate) {
Expand All @@ -25,12 +26,16 @@ function makeContractHost(E, evaluate) {
return seatDesc;
}
const makeUniAssay = makeUniAssayMaker(descriptionCoercer);
const inviteMint = makeMint('contract host', makeUniAssay);
const inviteMint = makeMint(
'contract host',
makeBasicMintController,
makeUniAssay,
);
const inviteIssuer = inviteMint.getIssuer();
const inviteAssay = inviteIssuer.getAssay();

function redeem(allegedInvitePayment) {
const allegedInviteAmount = allegedInvitePayment.getXferBalance();
const allegedInviteAmount = allegedInvitePayment.getBalance();
const inviteAmount = inviteAssay.vouch(allegedInviteAmount);
insist(!inviteAssay.isEmpty(inviteAmount))`\
No invites left`;
Expand Down
132 changes: 65 additions & 67 deletions core/issuers.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,27 @@
/* eslint no-use-before-define: 0 */ // --> OFF
// Copyright (C) 2019 Agoric, under Apache License 2.0

import harden from '@agoric/harden';

import { makePrivateName } from '../util/PrivateName';
import { insist } from '../util/insist';
import { makeNatAssay } from './assays';
import { makeBasicMintController } from './mintController';

function makeMint(description, makeAssay = makeNatAssay) {
function makeMint(
description,
makeMintController = makeBasicMintController,
makeAssay = makeNatAssay,
) {
insist(description)`\
Description must be truthy: ${description}`;

// Map from purse or payment to the transfer rights it currently
// holds. Transfer rights can move via payments, or they can cause a
// transfer of both the transfer and use rights by depositing it
// into a purse.
const xferRights = makePrivateName();

// Map from purse to useRights, where useRights do not include the
// right to transfer. Creating a payment moves some xferRights into the
// payment, but no useRights. Depositing a payment into another
// purse transfers both the xferRights and the useRights.
const useRights = makePrivateName();

// Map from payment to the home purse the payment came from. When the
// payment is deposited elsewhere, useRights are transfered from the
// home purse to the destination purse.
const homePurses = makePrivateName();

// src is a purse or payment. Return a fresh payment. One internal
// function used for both cases, since they are so similar.
function takePayment(amount, isPurse, src, _name) {
// eslint-disable-next-line no-use-before-define
amount = assay.coerce(amount);
_name = `${_name}`;
if (isPurse) {
insist(useRights.has(src))`\
Purse expected: ${src}`;
} else {
insist(homePurses.has(src))`\
Payment expected: ${src}`;
}
const srcOldXferAmount = xferRights.get(src);
// eslint-disable-next-line no-use-before-define
const srcNewXferAmount = assay.without(srcOldXferAmount, amount);
const srcOldRightsAmount = mintController.getAmount(src);
const srcNewRightsAmount = assay.without(srcOldRightsAmount, amount);

// ///////////////// commit point //////////////////
// All queries above passed with no side effects.
Expand All @@ -51,33 +30,26 @@ Payment expected: ${src}`;

const payment = harden({
getIssuer() {
// eslint-disable-next-line no-use-before-define
return issuer;
},
getXferBalance() {
return xferRights.get(payment);
getBalance() {
return mintController.getAmount(payment);
},
});
xferRights.set(src, srcNewXferAmount);
xferRights.init(payment, amount);
const homePurse = isPurse ? src : homePurses.get(src);
homePurses.init(payment, homePurse);
mintController.recordPayment(src, payment, amount, srcNewRightsAmount);
return payment;
}

const issuer = harden({
getLabel() {
// eslint-disable-next-line no-use-before-define
return assay.getLabel();
},

getAssay() {
// eslint-disable-next-line no-use-before-define
return assay;
},

makeEmptyPurse(name = 'a purse') {
// eslint-disable-next-line no-use-before-define
return mint.mint(assay.empty(), name); // mint and issuer call each other
},

Expand All @@ -89,7 +61,12 @@ Payment expected: ${src}`;

getExclusiveAll(srcPaymentP, name = 'a payment') {
return Promise.resolve(srcPaymentP).then(srcPayment =>
takePayment(xferRights.get(srcPayment), false, srcPayment, name),
takePayment(
mintController.getAmount(srcPayment),
false,
srcPayment,
name,
),
);
},

Expand All @@ -109,31 +86,27 @@ Payment expected: ${src}`;
const label = harden({ issuer, description });

const assay = makeAssay(label);
const mintController = makeMintController(assay);

function depositInto(purse, amount, srcPayment) {
amount = assay.coerce(amount);
const purseOldXferAmount = xferRights.get(purse);
const srcOldXferAmount = xferRights.get(srcPayment);
// Also checks that the union is representable
const purseNewXferAmount = assay.with(purseOldXferAmount, amount);
const srcNewXferAmount = assay.without(srcOldXferAmount, amount);

const homePurse = homePurses.get(srcPayment);
const purseOldUseAmount = useRights.get(purse);
const homeOldUseAmount = useRights.get(homePurse);
const purseOldRightsAmount = mintController.getAmount(purse);
const srcOldRightsAmount = mintController.getAmount(srcPayment);
// Also checks that the union is representable
const purseNewUseAmount = assay.with(purseOldUseAmount, amount);
const homeNewUseAmount = assay.without(homeOldUseAmount, amount);
const purseNewRightsAmount = assay.with(purseOldRightsAmount, amount);
const srcNewRightsAmount = assay.without(srcOldRightsAmount, amount);

// ///////////////// commit point //////////////////
// All queries above passed with no side effects.
// During side effects below, any early exits should be made into
// fatal turn aborts.

xferRights.set(srcPayment, srcNewXferAmount);
xferRights.set(purse, purseNewXferAmount);
useRights.set(homePurse, homeNewUseAmount);
useRights.set(purse, purseNewUseAmount);
mintController.recordDeposit(
srcPayment,
assay.coerce(srcNewRightsAmount),
purse,
assay.coerce(purseNewRightsAmount),
);

return amount;
}
Expand All @@ -142,6 +115,19 @@ Payment expected: ${src}`;
getIssuer() {
return issuer;
},
destroyAll() {
mintController.destroyAll();
},
destroy(amount) {
amount = assay.coerce(amount);
// for non-fungible tokens that are unique, destroy them by removing them from
// the purses/payments that they live in
mintController.destroy(amount);
},
revoke(amount) {
this.destroy(amount);
return mint(amount);
},
mint(initialBalance, _name = 'a purse') {
initialBalance = assay.coerce(initialBalance);
_name = `${_name}`;
Expand All @@ -150,11 +136,8 @@ Payment expected: ${src}`;
getIssuer() {
return issuer;
},
getXferBalance() {
return xferRights.get(purse);
},
getUseBalance() {
return useRights.get(purse);
getBalance() {
return mintController.getAmount(purse);
},
deposit(amount, srcPaymentP) {
return Promise.resolve(srcPaymentP).then(srcPayment => {
Expand All @@ -163,21 +146,31 @@ Payment expected: ${src}`;
},
depositAll(srcPaymentP) {
return Promise.resolve(srcPaymentP).then(srcPayment => {
return depositInto(purse, xferRights.get(srcPayment), srcPayment);
return depositInto(
purse,
mintController.getAmount(srcPayment),
srcPayment,
);
});
},
withdraw(amount, name = 'a withdrawal payment') {
return takePayment(amount, true, purse, name);
},
withdrawAll(name = 'a withdrawal payment') {
return takePayment(xferRights.get(purse), true, purse, name);
return takePayment(
mintController.getAmount(purse),
true,
purse,
name,
);
},
});
xferRights.init(purse, initialBalance);
useRights.init(purse, initialBalance);
mintController.recordMint(purse, initialBalance);
return purse;
},
});

// TODO: pass along destroyMint capability too
return mint;
}
harden(makeMint);
Expand All @@ -186,7 +179,12 @@ harden(makeMint);
// currency. Returns a promise for a peg object that asynchonously
// converts between the two. The local currency is synchronously
// transferable locally.
function makePeg(E, remoteIssuerP, makeAssay = makeNatAssay) {
function makePeg(
E,
remoteIssuerP,
makeMintController,
makeAssay = makeNatAssay,
) {
const remoteLabelP = E(remoteIssuerP).getLabel();

// The remoteLabel is a local copy of the remote pass-by-copy
Expand All @@ -198,7 +196,7 @@ function makePeg(E, remoteIssuerP, makeAssay = makeNatAssay) {
const backingPurseP = E(remoteIssuerP).makeEmptyPurse('backing');

const { description } = remoteLabel;
const localMint = makeMint(description, makeAssay);
const localMint = makeMint(description, makeMintController, makeAssay);
const localIssuer = localMint.getIssuer();
const localLabel = localIssuer.getLabel();

Expand Down
50 changes: 50 additions & 0 deletions core/mintController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { makePrivateName } from '../util/PrivateName';

export function makeBasicMintController() {
// Map from purse or payment to the rights it currently
// holds. Rights can move via payments

// purse/payment to amount
let rights = makePrivateName();

function recordPayment(src, payment, amount, srcNewRightsAmount) {
rights.set(src, srcNewRightsAmount);
rights.init(payment, amount);
}

function destroy(_amount) {
throw new Error('destroy is not implemented');
}

function destroyAll() {
rights = makePrivateName(); // reset rights
}

function recordDeposit(
srcPayment,
srcNewRightsAmount,
purse,
purseNewRightsAmount,
) {
rights.set(srcPayment, srcNewRightsAmount);
rights.set(purse, purseNewRightsAmount);
}

function recordMint(purse, initialAmount) {
rights.init(purse, initialAmount);
}

function getAmount(pursePayment) {
return rights.get(pursePayment);
}

const mintController = {
destroy,
destroyAll,
recordPayment,
recordDeposit,
recordMint,
getAmount,
};
return mintController;
}
12 changes: 5 additions & 7 deletions demo/contractHost/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,17 @@ function build(E, log) {
// it.
function showPaymentBalance(name, paymentP) {
return E(paymentP)
.getXferBalance()
.then(amount => log(name, ' xfer balance ', amount));
.getBalance()
.then(amount => log(name, ' balance ', amount));
}
// TODO BUG: All callers should wait until settled before doing
// anything that would change the balance before show*Balance* reads
// it.
function showPurseBalances(name, purseP) {
return Promise.all([
E(purseP)
.getXferBalance()
.then(amount => log(name, ' xfer balance ', amount)),
E(purseP)
.getUseBalance()
.then(amount => log(name, ' use balance ', amount)),
.getBalance()
.then(amount => log(name, ' balance ', amount)),
]);
}

Expand Down Expand Up @@ -75,6 +72,7 @@ function build(E, log) {
function mintTestNumber(mint) {
log('starting mintTestNumber');
const mMintP = E(mint).makeMint('quatloos');
mMintP.then(newMint => console.log(newMint));

const alicePurseP = E(mMintP).mint(1000, 'alice');
const paymentP = E(alicePurseP).withdraw(50);
Expand Down
14 changes: 5 additions & 9 deletions demo/contractHost/vat-alice.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ function makeAliceMaker(E, host, log) {
// it.
function showPaymentBalance(name, paymentP) {
return E(paymentP)
.getXferBalance()
.then(amount => log(name, ' xfer balance ', amount));
.getBalance()
.then(amount => log(name, ' balance ', amount));
}

return harden({
Expand Down Expand Up @@ -48,9 +48,7 @@ function makeAliceMaker(E, host, log) {
log('++ alice.acceptInvite starting');
showPaymentBalance('alice invite', allegedInvitePaymentP);

const allegedInviteAmountP = E(
allegedInvitePaymentP,
).getXferBalance();
const allegedInviteAmountP = E(allegedInvitePaymentP).getBalance();

const verifiedInviteP = E.resolve(allegedInviteAmountP).then(
allegedInviteAmount => {
Expand Down Expand Up @@ -112,9 +110,7 @@ function makeAliceMaker(E, host, log) {
log('++ alice.acceptOptionDirectly starting');
showPaymentBalance('alice invite', allegedInvitePaymentP);

const allegedInviteAmountP = E(
allegedInvitePaymentP,
).getXferBalance();
const allegedInviteAmountP = E(allegedInvitePaymentP).getBalance();

const verifiedInvitePaymentP = E.resolve(allegedInviteAmountP).then(
allegedInviteAmount => {
Expand Down Expand Up @@ -174,7 +170,7 @@ function makeAliceMaker(E, host, log) {
acceptOptionForFred(allegedInvitePaymentP) {
log('++ alice.acceptOptionForFred starting');
const finNeededP = E(E(optFinIssuerP).getAssay()).make(55);
const inviteNeededP = E(allegedInvitePaymentP).getXferBalance();
const inviteNeededP = E(allegedInvitePaymentP).getBalance();

const terms = harden([finNeededP, inviteNeededP]);
const invitesP = E(escrowExchangeInstallationP).spawn(terms);
Expand Down
Loading

0 comments on commit 4bffd92

Please sign in to comment.