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

Completes some documentation tasks #41

Merged
merged 15 commits into from
Nov 2, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions main/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ module.exports = {
'/ertp/guide/label',
'/ertp/guide/unit-ops',
'/ertp/guide/default-configuration',
'/ertp/guide/contract-hosts'
'/ertp/guide/contract-hosts',
'/ertp/guide/other-concepts'
]
},
{
Expand All @@ -79,7 +80,8 @@ module.exports = {
'/ertp/api/purse',
'/ertp/api/payment',
'/ertp/api/extent-ops',
'/ertp/api/unit-ops'
'/ertp/api/unit-ops',
'/ertp/api/contract-hosts'
]
},
{
Expand Down
6 changes: 3 additions & 3 deletions main/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
####
home: true # use default home page layout (hero image with text, features section)
heroImage: https://agoric.com/assets/images/logo.svg
### Action button
# actionText: Get Started → # text that goes in the button
# actionLink: /guide/ # go-to link when clicking on button
## Action button
actionText: Get Started → # text that goes in the button
actionLink: /getting-started/ # go-to link when clicking on button
features:
- title: New Protocol
details: Agoric empowers individuals to securely execute transactions, establish new markets, and craft novel patterns of exchange — without centralized control.
Expand Down
158 changes: 158 additions & 0 deletions main/ertp/api/contract-hosts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Contract Hosts

ContractHost provides a way to install and run verifiable contracts.

Install(source) creates Installations. Installations represent particular
contract forms, which can be spawn()'d to create Contract instances
initialized with specific terms. These Contracts manage invitations for
multiple seats, each of which repesents a "role" in an interaction.

Some seats provide the methods `getWinnings()` and `getRefunds()`, which return
promises for payments for the outputs of the interaction. We provide the
`collect()` method (described later) to simplify collection of winnings and
refunds into appropriate purses.

## contractHost.install(contractSrc)
- `contractSrc` `{String}` - contractSrc is the source code for a Contract. See Contract for details.
- Returns: `{Installation}`

Install the source code for a Contract.

```js
const someEscrowInstallation = E(someHost).install(someEscrowExchangeSrc);
```

## contractHost.getInstallationSourceCode(installation)
- `installation` `{Installation}`
- Returns: `{String}`

Get the actual source code of the Installation.

```js
const theSourceCode = E(someHost).getInstallationSourceCode(someInstallation);
```

## contractHost.redeem(invite)
- `invite` `{Payment}`
- Returns: `{Object}`

Seat invitations are packaged as payments from the Invite Assay. Redeeming an invite returns a seat object with an arbitrary interface (the interface is at the discretion of the contract) which supports interaction according to the terms.

```js
const someSeat = E(someHost).redeem(someInvite);
```

## contractHost.getInviteAssay()
- Returns: `{Assay}`

The assay allows holders of seat invitations to get exclusive access to a Seat.

```js
const assayWithExclusiveAccess = E(someHost).getInviteAssay();
```

## installation.spawn(terms)
- `terms` `{Terms}`
- Returns: `{Invites <Object>}`

Create a new `InviteMaker`, then call the Contract's `start()` method and return its results. The results are often a collection of seat invitations for the seats in the contract, but see [`coveredCall`](https://github.com/Agoric/ERTP/blob/master/core/coveredCall.js) for an exception.

```js
import harden from '@agoric/harden';

const terms = harden({ left: whatPartyAWants, right: whatPartyBWants });
const invitePayments = E(someInstallation).spawn(terms);
```

## installation.checkUnits(installation, inviteUnits, terms)
- `installation` `{Installation}`
- `inviteUnits` `{Units}`
- `terms` `{Terms}`
- Returns:

### <span style="color:red">What does this method return? It's not stated in the chainmail file and it's not very clear in the code usage.</span>
dominiquejane marked this conversation as resolved.
Show resolved Hide resolved

### <span style="color:red">Are these params correct? In the code they follow this pattern instead: `{inviteUnits, terms, anOptionalString}`. Example from `ERTP/test/swingsetTests/contractHost/vat-alice.js`:</span>
dominiquejane marked this conversation as resolved.
Show resolved Hide resolved

```js
return E(escrowExchangeInstallationP)
.checkUnits(allegedInviteUnits, { left, right }, 'left')
.then(() => {
return E(inviteAssayP).claimExactly(
allegedInviteUnits,
allegedInvitePaymentP,
'verified invite',
);
});
```

The writer of the contract can provide methods to help users of the contract verify that the terms of the contract match their expectation. These methods are defined with the installation as the first parameter, so the verifiers can validate that the caller's invitation was issued by the same one. The invocation by clients should omit this parameter, as they will be supplied with a copy of the function with that information already supplied.

Users usually want to validate their invitation, the terms of the deal they're attempting to participate in, and which seat they are taking.

```js
```

## contract.start(terms, inviteMaker)
- `terms` `{Terms}`
- `inviteMaker` `{InviteMaker}`
- Returns: `{Object}`

Start execution of the contract. May return invites for seats.

### <span style="color:red">Need help writing/checking example.</span>
barbaraliau marked this conversation as resolved.
Show resolved Hide resolved
```js
import harden from '@agoric/harden';

const aNewContract = harden({
start: (terms, inviteMaker) => {
// add contract code
}
})

export { aNewContract }

// Now, `aNewContract` can be imported into other parts of your code
// and used as an Installation using `contractHost.install(aNewContract)`
// Also, see `installation.spawn()` above.
```

## inviteMaker.make(seatDesc, seat, name)
- `seatDesc` `{String}` - Must be unique for each contract instantiation.
- `seat` `{Object}` - An arbitrary object defined by the contract.
- `name` `{String}` - Labels the invite payment for this seat. Optional.
- Returns: `{Payment}`

### <span style="color:red">No description in chainmail file. Please double check that this description makes sense.</span>
barbaraliau marked this conversation as resolved.
Show resolved Hide resolved
Creates a payment for an invite for a seat in a contract. The returned Payment can be passed to `contractHost.redeem()` to get a seat Object.

```js
import harden from '@agoric/harden';

const aNewContract = harden({
start: (terms, inviteMaker) => {
// other contract code
const someSeat = harden({
// code for this seat
})
return inviteMaker.make('writer', someSeat)
}
})
```

## collector.collect(seatP, winPurseP, refundPurseP, name)
- `seatP` `{Object}`
- `winPurseP` `{Purse}`
- `refundPurseP` `{Purse}`
- `name` `{String}` - Default: 'collecting'
- Returns: `{winsAndRefunds <Object>}`

`collect()` calls `getWinnings()` and `getRefund()` on `seatP` and deposits the proceeds respectively into `winPurseP` and `refundPurseP`. `name` (which defaults to 'collecting') is converted to a String, and used for logging the results.

```js
const purseA = assayA.makeEmptyPurse();
const purseB = assayB.makeEmptyPurse();
const seatP = E(someHost).redeem(someInvite);

collect(seatP, purseA, purseB, 'a log message');
```
6 changes: 4 additions & 2 deletions main/ertp/api/payment.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Payment
Payments hold verified units of certain rights issued by Mints. Units from payments can be deposited in purses, but otherwise, the entire unit is available when the payment is transferred. A payment's balance can only fall, through the action of `depositExactly()`, `claimExactly()` or `burnExactly()`. Payments can be converted to Purses by getting a verified assay and calling `assay.makeEmptyPurse().depositAll(payment)`;
Payments hold verified units of certain rights issued by Mints. Units from payments can be deposited in purses, but otherwise, the entire unit is available when the payment is transferred. A payment's balance can only fall, through the action of `purse.depositExactly()`, `assay.claimExactly()` or `assay.burnExactly()`.

Payments can be converted to Purses by getting a verified assay and calling `assay.makeEmptyPurse().depositAll(payment)`;

## payment.getName()
- Returns: `{String}`
Expand Down Expand Up @@ -36,4 +38,4 @@ payments.push(purse.withdraw(20));

// Returns 20
payments.getBalance();
```
```
6 changes: 5 additions & 1 deletion main/ertp/api/purse.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Purse
Purses hold verified `units` of certain rights issued by Mints. Purses can transfer part of the balance they hold in a payment, which has a narrower interface. A purse's balance can rise and fall, through the action of depositExactly() and withdraw(). Operations on payments (`burnExactly()`, `depositExactly()`, `assay.claimExactly()`) kill the original payment and create new payments if applicable. The primary use for Purses and Payments is for currency-like and goods-like valuables, but they can also be used to represent other kinds of rights, such as the right to participate in a particular contract.
Purses hold verified `units` of certain rights issued by Mints. Purses can transfer part of the balance they hold in a payment, which has a narrower interface. A purse's balance can rise and fall, through the action of `purse.depositExactly()` and `purse.withdraw()`.

Operations on payments (`assay.burnExactly(units, payment)`, `purse.depositExactly(units, payment)`, `assay.claimExactly(units, payment, name)`) kill the original payment and create new payments if applicable.

The primary use for Purses and Payments is for currency-like and goods-like valuables, but they can also be used to represent other kinds of rights, such as the right to participate in a particular contract.

## purse.getName()
- Returns: `{String}`
Expand Down
2 changes: 1 addition & 1 deletion main/ertp/api/unit-ops.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const localLabel = localAssay.getLabel();
Make a new verified Units containing the `allegedExtent`.

```js
inviteMaker.make('writer', bobSeat);
const inviteUnits = inviteUnitOps.make(seatDescription);
```

## unitOps.coerce(allegedUnits)
Expand Down
24 changes: 0 additions & 24 deletions main/ertp/guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,30 +92,6 @@ For a demo on how ERTP can be used, check out our [Pixel Demo](https://github.co

All of the pixels (individual squares) on the demo webpage are owned by the gallery, the code that administrates the pixels. The gallery has the power to revoke the pixels from any user at any time. When a user calls `gallery!tapFaucet()`, the gallery takes the least recently colored pixel from its current holder (if anyone holds it) and gives it to the user in the form of an ERTP payment. The gallery is able to revoke the pixels held by users because the pixel demo creates a customized version of ERTP in which rights are hierarchical. Hierarchical rights are familiar in property. For instance, a property owner might lease an apartment to a tenant, who might in turn, lease it to a subtenant. Anyone higher in the hierarchy can take away access from anyone lower in the hierarchy, and give it to someone else.

## Gotchas

When looking at the code in our [tests](https://github.com/Agoric/ERTP/tree/master/test), you might see some new
concepts:

* __Vats__: All user code runs in what we call a `vat`. Within a vat,
code is run synchronously. Communication with another vat happens
asynchronously. The [SwingSet
infrastructure](https://github.com/Agoric/SwingSet) creates the vats
and makes communication between vats possible.

* __E() and infix bang (!)__: Instead of `obj.foo()`, we can write
`E(obj).foo()` or the syntactic sugar, `obj!foo()` and get a promise
for the result. The syntax means "deliver the message foo() to the
actual object asynchronously, in its own turn, wherever and whenever
it is, even if it is local." Using E or !, you can talk
asynchronously to local and remote objects in exactly the same way,
which is really cool!

* __Presences__: Presences are our name for the local object that
stands in for the remote object. If `obj` is a presence of a remote
object, we can send messages to the remote object by using
"!" on `obj`, as in the above example.

## More ERTP resources

Mark Miller explained ERTP on Oct 10, 2018 in his [Programming Secure Smart Contracts][watch] presentation
Expand Down
59 changes: 59 additions & 0 deletions main/ertp/guide/contract-hosts.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Contract Hosts

## Contract Hosts

ContractHost provides a way to install and run verifiable contracts.

Install(source) creates Installations. Installations represent particular
Expand All @@ -11,3 +13,60 @@ Some seats provide the methods `getWinnings()` and `getRefunds()`, which return
promises for payments for the outputs of the interaction. We provide the
`collect()` method (described later) to simplify collection of winnings and
refunds into appropriate purses.

## Installations

An installation of a Contract can spawn multiple copies each with the same or different terms. Each spawned instance has distinct invites and distinct seats representing a specific group of agents interacting according to the same prescribed roles.

### <span style="color:red">Possible typo on the next sentence?</span>
dominiquejane marked this conversation as resolved.
Show resolved Hide resolved
The Installation can also have functions with names starting 'check', as defined by the contract. They can be used to validate that the expected terms are actually the same as the terms of this spawned contract. The Installation is inserted by the ContactHost as the first parameter to these functions. The naming restriction is likely to be lifted.

## Contracts

Contracts are pass-by-text.

The ContractHost's `install()` method is called on the source code for a contract. The contract needs to have a `start()` method with arguments as described below. Creating the contract object by calling `evaluate()` on the source code enables the ContractHost to guarantee to its clients that the resulting object implements that specific algorithm, and doesn't have any hidden powers.

The form of the 'terms' argument to the contract's `start()` method is also completely up to the individual contract. It should represent all the information a participant needs in order to know they're participating in the contract they intended. As an example, the 'escrow' contract represents a simple exchange of one bundle of goods for another. Escrow's terms object has the units be traded as 'left' and 'right', which correspond to the units being offered and collected by the respective parties. The Object returned by escrow is an array containing two invitations, but this isn't required. The representation is flexible enough to support trading of money, non-fungible items, or partially-executed positions in other contracts among other possibilities. Other contracts take different paths.

Javascript gives access to the source from a function, but not from an object. We make the source accessible to the ContractHost by having contracts export a record containing the source. The contract can also define methods that can be called by participants in the contract to validate that the terms they expect the contract to have been installed with are in agreement with the contract.

```js
const escrowExchangeSrcs = {
start: `${escrowExchange.start}`,
checkUnits: `${escrowExchange.checkUnits}`,
};
```

## InviteMaker

An InviteMaker is provided to contracts as a parameter to `start()`. It allows the contract to issue invitations for seats, arbitrary objects whose interface defines the roles and interactions in the contract. The design of the InviteMaker allows recipients of invites to validate that the invite corresponds to the seat and contract that they expected.

`seatDesc` can be any truthy object, but Strings are convenient. They must be unique for each contract instantiation. `seat` is an arbitrary object defined by the contract. `name` is optional; it is used to label the invite payment corresponding to the seat.

The returned Payment is the invite that can be passed to `contractHost.redeem()` to get a seat object. The Payment's Units contains the installation, contract terms, a seatIdentity object, and a seat description formatted as `{installation, terms, seatIdentity, seatDesc}`. These are intended to be sufficient for the recipient to verify that the contract and terms are the ones they were expecting, and that the invite corresponds to the expected role in the contract. The installation can provide methods like `installation.checkUnits()` to simplify verification.

## Collector

`collect()` calls `getWinnings()` and `getRefund()` on `seatP` and deposits the proceeds respectively into `winPurseP` and `refundPurseP`. `name` (which defaults to 'collecting') is converted to a String, and used for logging the results.

### <span style="color:red">Is this sentence about Jessie supposed to be here?</span>
`collect()` is a pure function that can be imported from
`contractHost.js`. (Jessie will eventually provide assurances, because of
the way that we import modules, that it is confined.) Since it is confined,
users can be sure that it has no ability to skim any of the value being
transferred.

`collect()` violates our usual rule of only transferring payments, and never
sharing purses. This rule helps us ensure that users don't share a purse
when they only intended to share a portion of the contents. We allow
`collect()` to violate the rule because it's such a common pattern.

This function is a convenient wrapper that makes it easier to work with our
Escrow contract, and has no privileged access.

## Terms

Arbitrary terms defined by each contract.

These are defined by the contract, passed to `installation.spawn()`, and available to be validated in the check methods (or manually) by contract participants to ensure they are connected to a contract with matching expectations about what will be traded, and which seat they will occupy.
23 changes: 23 additions & 0 deletions main/ertp/guide/other-concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Other Concepts

When looking at the code in our [tests](https://github.com/Agoric/ERTP/tree/master/test), you might see some new
concepts:

* __Vats__: All user code runs in what we call a `vat`. Within a vat,
code is run synchronously. Communication with another vat happens
asynchronously. The [SwingSet
infrastructure](https://github.com/Agoric/SwingSet) creates the vats
and makes communication between vats possible.

* __E() and infix bang (!)__: Instead of `obj.foo()`, we can write
dominiquejane marked this conversation as resolved.
Show resolved Hide resolved
`E(obj).foo()` or the syntactic sugar, `obj!foo()` and get a promise
for the result. The syntax means "deliver the message foo() to the
actual object asynchronously, in its own turn, wherever and whenever
it is, even if it is local." Using E or !, you can talk
asynchronously to local and remote objects in exactly the same way,
which is really cool!

* __Presences__: Presences are our name for the local object that
stands in for the remote object. If `obj` is a presence of a remote
object, we can send messages to the remote object by using
"!" on `obj`, as in the above example.