mirror of
https://github.com/corda/corda.git
synced 2025-02-21 09:51:57 +00:00
Docs: regenerate the HTML
This commit is contained in:
parent
1ce9bdeba0
commit
2f1a91c101
2
docs/build/html/_sources/inthebox.txt
vendored
2
docs/build/html/_sources/inthebox.txt
vendored
@ -12,7 +12,7 @@ The current prototype consists of a small amount of code that defines:
|
||||
|
||||
Some things it does not currently include but should gain later are:
|
||||
|
||||
* Sandboxing of smart contract code
|
||||
* Sandboxing, distribution or publication of smart contract code
|
||||
* A peer to peer network
|
||||
* Database persistence
|
||||
* An API for integrating external software
|
||||
|
22
docs/build/html/_sources/overview.txt
vendored
22
docs/build/html/_sources/overview.txt
vendored
@ -21,13 +21,17 @@ consume/destroy, these are called **inputs**, and contains a set of new states t
|
||||
States contain arbitrary data, but they always contain at minimum a pointer to the bytecode of a
|
||||
**code contract**, which is a program expressed in some byte code that runs sandboxed inside a virtual machine. Code
|
||||
contracts (or just "contracts" in the rest of this document) are globally shared pieces of business logic. Contracts
|
||||
define a **verify function**, which is a pure function of the entire transaction.
|
||||
define a **verify function**, which is a pure function given the entire transaction as input.
|
||||
|
||||
To be considered valid, the transaction must be **accepted** by the verify function of every contract pointed to by the
|
||||
input and output states. Beyond inputs and outputs, transactions may also contain **commands**, small data packets that
|
||||
the platform does not interpret itself, but which can parameterise execution of the contracts. They can be thought of as
|
||||
arguments to the verify function.
|
||||
|
||||
Note that there is nothing that explicitly binds together specific inputs, outputs or commands. Instead it's up to the
|
||||
contract code to interpret the pieces inside the transaction and ensure they fit together correctly. This is done to
|
||||
maximise flexibility for the contract developer.
|
||||
|
||||
A transaction has one or more **signatures** attached to it. The signatures do not mean anything by themselves, rather,
|
||||
their existence is given as input to the contract which can then decide which set of signatures it demands (if any).
|
||||
Signatures may be from an arbitrary, random **public key** that has no identity attached. A public key may be
|
||||
@ -44,7 +48,16 @@ timestamp, and they are therefore never exposed to private data.
|
||||
.. note:: In the current code, use of TSAs is not implemented.
|
||||
|
||||
As the same terminology often crops up in different distributed ledger designs, let's compare this to other
|
||||
distributed ledger systems you may be familiar with.
|
||||
distributed ledger systems you may be familiar with. You can find more detailed design rationales for why the platform
|
||||
differs from existing systems in `the R3 wiki <https://r3-cev.atlassian.net/wiki/>`_, but to summarise, the driving
|
||||
factors are:
|
||||
|
||||
* Improved contract flexibility vs Bitcoin
|
||||
* Improved scalability vs Ethereum, as well as ability to keep parts of the transaction graph private (yet still uniquely addressable)
|
||||
* No reliance on proof of work
|
||||
* Re-us of existing sandboxing virtual machines
|
||||
* Use of type safe GCd implementation languages.
|
||||
* Simplified auditing
|
||||
|
||||
Comparison with Bitcoin
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -73,7 +86,7 @@ Differences:
|
||||
* A Bitcoin script can only be given a fixed set of byte arrays as the input. This means there's no way for a contract
|
||||
to examine the structure of the entire transaction, which severely limits what contracts can do.
|
||||
* Our contracts are Turing-complete and can be written in any ordinary programming language that targets the JVM.
|
||||
* Our transactions and contracts have get their time from an attached timestamp rather than a block chain. This is
|
||||
* Our transactions and contracts have to get their time from an attached timestamp rather than a block chain. This is
|
||||
important given that we are currently considering block-free conflict resolution algorithms.
|
||||
* We use the term "contract" to refer to a bundle of business logic that may handle various different tasks, beyond
|
||||
transaction verification. For instance, currently our contracts also include code for creating valid transactions
|
||||
@ -92,7 +105,7 @@ Differences:
|
||||
|
||||
* The term "contract" in Ethereum refers to an *instantiation* of a program that is replicated and maintained by
|
||||
every participating node. This instantiation is very much like an object in an OO program: it can receive and send
|
||||
messages, update local storage and so on. In contrast, use the term "contract" to refer to a set of functions, only
|
||||
messages, update local storage and so on. In contrast, we use the term "contract" to refer to a set of functions, only
|
||||
one of which is a part of keeping the system synchronised (the verify function). That function is pure and
|
||||
stateless i.e. it may not interact with any other part of the system whilst executing.
|
||||
* There is no notion of an "account", as there is in Ethereum.
|
||||
@ -101,6 +114,7 @@ Differences:
|
||||
platform considers non-financial applications to be out of scope.
|
||||
|
||||
|
||||
|
||||
Contracts
|
||||
---------
|
||||
|
||||
|
23
docs/build/html/_sources/roadmap.txt
vendored
23
docs/build/html/_sources/roadmap.txt
vendored
@ -1,4 +1,25 @@
|
||||
Roadmap
|
||||
=======
|
||||
|
||||
roadmap
|
||||
The canonical place to learn about pending tasks is the `R3 JIRA <https://r3-cev.atlassian.net/>`_ site. This
|
||||
page gives some examples of tasks that we wish to explore in future milestones:
|
||||
|
||||
M1 is this release.
|
||||
|
||||
Milestone 2
|
||||
-----------
|
||||
|
||||
Contracts API:
|
||||
|
||||
* Example implementations of more advanced use cases, possibly an interest rate swap.
|
||||
* Support for lifting transaction sub-graphs out of the global ledger and evolving them privately within a subgroup
|
||||
of users (helpful for privacy, scalability).
|
||||
* An improved unit test DSL.
|
||||
|
||||
Platform:
|
||||
|
||||
* Storage of states to disk and initial support for network synchronisation (does not have to be the final network
|
||||
layer: just something good enough to get us to the next stage of prototyping).
|
||||
* Dynamic loading and first-pass sandboxing of contract code.
|
||||
* Simple test/admin user interface for performing various kinds of trades.
|
||||
|
||||
|
286
docs/build/html/_sources/tutorial.txt
vendored
286
docs/build/html/_sources/tutorial.txt
vendored
@ -16,7 +16,9 @@ for how Kotlin syntax works.
|
||||
Starting the commercial paper class
|
||||
-----------------------------------
|
||||
|
||||
A smart contract is a class that implements the ``Contract`` interface. Therefore, we start like this:
|
||||
A smart contract is a class that implements the ``Contract`` interface. For now, they have to be a part of the main
|
||||
codebase, as dynamic loading of contract code is not yet implemented. Therefore, we start by creating a file named
|
||||
either `CommercialPaper.kt` or `CommercialPaper.java` in the src/contracts directory with the following contents:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
@ -157,7 +159,10 @@ We have four fields in our state:
|
||||
|
||||
* `issuance`: a reference to a specific piece of commercial paper at an institution
|
||||
* `owner`: the public key of the current owner. This is the same concept as seen in Bitcoin: the public key has no
|
||||
attached identity and is expected to be one-time-use for privacy reasons.
|
||||
attached identity and is expected to be one-time-use for privacy reasons. However, unlike in Bitcoin, we model
|
||||
ownership at the level of individual contracts rather than as a platform-level concept as we envisage many
|
||||
(possibly most) contracts on the platform will not represent "owner/issuer" relationships, but "party/party"
|
||||
relationships such as a derivative contract.
|
||||
* `faceValue`: an `Amount`, which wraps an integer number of pennies and a currency.
|
||||
* `maturityDate`: an `Instant <https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html>`, which is a type
|
||||
from the Java 8 standard time library. It defines a point on the timeline.
|
||||
@ -187,28 +192,36 @@ Let's define a couple of commands now:
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
sealed class Commands : Command {
|
||||
object Move : Commands()
|
||||
object Redeem : Commands()
|
||||
interface Commands : Command {
|
||||
object Move : Commands
|
||||
object Redeem : Commands
|
||||
object Issue : Commands
|
||||
}
|
||||
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
public static class Commands implements core.Command {
|
||||
public static class Move extends Commands {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Move;
|
||||
}
|
||||
}
|
||||
public static class Move extends Commands {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Move;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Redeem extends Commands {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Redeem;
|
||||
}
|
||||
}
|
||||
public static class Redeem extends Commands {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Redeem;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Issue extends Commands {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Redeem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The `object` keyword in Kotlin just defines a singleton object. As the commands don't need any additional data in our
|
||||
@ -262,12 +275,17 @@ Understanding fungibility
|
||||
We say states are *fungible* if they are treated identically to each other by the recipient, despite the fact that they
|
||||
aren't quite identical. Dollar bills are fungible because even though one may be worn/a bit dirty and another may
|
||||
be crisp and new, they are still both worth exactly $1. Likewise, ten $1 bills are almost exactly equivalent to
|
||||
one $10 bill. On the other hand, $10 and £10 are not fungible: if you tried to pay for something that cost $20 with
|
||||
one $10 bill. On the other hand, $10 and £10 are not fungible: if you tried to pay for something that cost £20 with
|
||||
$10+£10 notes your trade would not be accepted.
|
||||
|
||||
So whilst our ledger could represent every monetary amount with a collection of states worth one penny, this would become
|
||||
extremely unwieldy. It's better to allow states to represent varying amounts and then define rules for merging them
|
||||
and splitting them.
|
||||
and splitting them. Similarly, we could also have considered modelling cash as a single contract that records the
|
||||
ownership of all holders of a given currency from a given issuer. Whilst this is possible, and is effectively how
|
||||
some other platforms work, this prototype favours a design that doesn't necessarily require state to be shared between
|
||||
multiple actors if they don't have a direct relationship with each other (as would implicitly be required if we had a
|
||||
single state representing multiple people's ownership). Keeping the states separated also has scalability benefits, as
|
||||
different parts of the global transaction graph can be updated in parallel.
|
||||
|
||||
To make this easier the contract API provides a notion of groups. A group is a set of input states and output states
|
||||
that should be checked for validity independently. It solves the following problem: because every contract sees every
|
||||
@ -328,6 +346,21 @@ logic.
|
||||
"the paper must be destroyed" by (output == null)
|
||||
}
|
||||
}
|
||||
|
||||
is Commands.Issue -> {
|
||||
val output = group.outputs.single()
|
||||
requireThat {
|
||||
// Don't allow people to issue commercial paper under other entities identities.
|
||||
"the issuance is signed by the claimed issuer of the paper" by
|
||||
(command.signers.contains(output.issuance.institution.owningKey))
|
||||
"the face value is not zero" by (output.faceValue.pennies > 0)
|
||||
"the maturity date is not in the past" by (output.maturityDate > tx.time)
|
||||
// Don't allow an existing CP state to be replaced by this issuance.
|
||||
"there is no input state" by group.inputs.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("Unrecognised command")
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,6 +394,8 @@ logic.
|
||||
throw new IllegalStateException("Failed requirement: the received amount equals the face value");
|
||||
if (!outputs.isEmpty())
|
||||
throw new IllegalStateException("Failed requirement: the paper must be destroyed");
|
||||
} else if (cmd.getValue() instanceof JavaCommercialPaper.Commands.Issue) {
|
||||
// .. etc .. (see Kotlin for full definition)
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,6 +443,9 @@ imposes a limitation on the structure of a redemption transaction: you are not a
|
||||
transaction that the CP does not involve. This limitation could be addressed with better APIs, if it were to be a
|
||||
real limitation.
|
||||
|
||||
Finally, we support an `Issue` command, to create new instances of commercial paper on the ledger. It likewise
|
||||
enforces various invariants upon the issuance.
|
||||
|
||||
This contract is extremely simple and does not implement all the business logic a real commercial paper lifecycle
|
||||
management program would. For instance, there is no logic requiring a signature from the issuer for redemption:
|
||||
it is assumed that any transfer of money that takes place at the same time as redemption is good enough. Perhaps
|
||||
@ -415,4 +453,212 @@ that is something that should be tightened. Likewise, there is no logic handling
|
||||
bankrupt, if there is a dispute, and so on.
|
||||
|
||||
As the prototype evolves, these requirements will be explored and this tutorial updated to reflect improvements in the
|
||||
contracts API.
|
||||
contracts API.
|
||||
|
||||
How to test your contract
|
||||
-------------------------
|
||||
|
||||
Of course, it is essential to unit test your new nugget of business logic to ensure that it behaves as you expect.
|
||||
Although you can write traditional unit tests in Java, the platform also provides a *domain specific language*
|
||||
(DSL) for writing contract unit tests that automates many of the common patterns. This DSL builds on top of JUnit yet
|
||||
is a Kotlin DSL, and therefore this section will not show Java equivalent code (for Java unit tests you would not
|
||||
benefit from the DSL and would write them by hand).
|
||||
|
||||
We start by defining a new test class, with a basic CP state:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
class CommercialPaperTests {
|
||||
val PAPER_1 = CommercialPaper.State(
|
||||
issuance = InstitutionReference(MEGA_CORP, OpaqueBytes.of(123)),
|
||||
owner = MEGA_CORP_KEY,
|
||||
faceValue = 1000.DOLLARS,
|
||||
maturityDate = TEST_TX_TIME + 7.days
|
||||
)
|
||||
|
||||
@Test
|
||||
fun key_mismatch_at_issue() {
|
||||
transactionGroup {
|
||||
transaction {
|
||||
output { PAPER_1 }
|
||||
arg(DUMMY_PUBKEY_1) { CommercialPaper.Commands.Issue() }
|
||||
}
|
||||
|
||||
expectFailureOfTx(1, "signed by the claimed issuer")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
We start by defining a commercial paper state. It will be owned by a pre-defined unit test institution, affectionately
|
||||
called `MEGA_CORP` (this constant, along with many others, is defined in `TestUtils.kt`). Due to Kotin's extensive
|
||||
type inference, many types are not written out explicitly in this code and it has the feel of a scripting language.
|
||||
But the types are there, and you can ask IntelliJ to reveal them by pressing Alt-Enter on a "val" or "var" and selecting
|
||||
"Specify type explicitly".
|
||||
|
||||
There are a few things that are unusual here:
|
||||
|
||||
* We can specify quantities of money by writing 1000.DOLLARS or 1000.POUNDS
|
||||
* We can specify quantities of time by writing 7.days
|
||||
* We can add quantities of time to the TEST_TX_TIME constant, which merely defines an arbitrary java.time.Instant
|
||||
|
||||
If you examine the code in the actual repository, you will also notice that it makes use of method names with spaces
|
||||
in them by surrounding the name with backticks, rather than using underscores. We don't show this here as it breaks the
|
||||
doc website's syntax highlighting engine.
|
||||
|
||||
The `1000.DOLLARS` construct is quite simple: Kotlin allows you to define extension functions on primitive types like
|
||||
Int or Double. So by writing 7.days, for instance, the compiler will emit a call to a static method that takes an int
|
||||
and returns a `java.time.Duration`.
|
||||
|
||||
As this is JUnit, we must remember to annotate each test method with @Test. Let's examine the contents of the first test.
|
||||
We are trying to check that it's not possible for just anyone to issue commercial paper in MegaCorp's name. That would
|
||||
be bad!
|
||||
|
||||
The `transactionGroup` function works the same way as the `requireThat` construct above. It is an example of what
|
||||
Kotlin calls a type safe builder, which you can read about in `the documentation for builders <https://kotlinlang.org/docs/reference/type-safe-builders.html>`_.
|
||||
The code block that follows it is run in the scope of a freshly created `TransactionGroupForTest` object, which assists
|
||||
you with building little transaction graphs and verifying them as a whole. Here, our "group" only actually has a
|
||||
single transaction in it, with a single output, no inputs, and an Issue command signed by `DUMMY_PUBKEY_1` which is just
|
||||
an arbitrary public key. As the paper claims to be issued by `MEGA_CORP`, this doesn't match and should cause a
|
||||
failure. The `expectFailureOfTx` method takes a 1-based index (in this case we expect the first transaction to fail)
|
||||
and a string that should appear in the exception message. Then it runs the `TransactionGroup.verify()` method to
|
||||
invoke all the involved contracts.
|
||||
|
||||
It's worth bearing in mind that even though this code may look like a totally different language to normal Kotlin or
|
||||
Java, it's actually not, and so you can embed arbitrary code anywhere inside any of these blocks.
|
||||
|
||||
Let's set up a full trade and ensure it works:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
// Generate a trade lifecycle with various parameters.
|
||||
private fun trade(redemptionTime: Instant = TEST_TX_TIME + 8.days,
|
||||
aliceGetsBack: Amount = 1000.DOLLARS,
|
||||
destroyPaperAtRedemption: Boolean = true): TransactionGroupForTest {
|
||||
val someProfits = 1200.DOLLARS
|
||||
return transactionGroup {
|
||||
roots {
|
||||
transaction(900.DOLLARS.CASH owned_by ALICE label "alice's $900")
|
||||
transaction(someProfits.CASH owned_by MEGA_CORP_KEY label "some profits")
|
||||
}
|
||||
|
||||
// Some CP is issued onto the ledger by MegaCorp.
|
||||
transaction {
|
||||
output("paper") { PAPER_1 }
|
||||
arg(MEGA_CORP_KEY) { CommercialPaper.Commands.Issue() }
|
||||
}
|
||||
|
||||
// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,
|
||||
// that sounds a bit too good to be true!
|
||||
transaction {
|
||||
input("paper")
|
||||
input("alice's $900")
|
||||
output { 900.DOLLARS.CASH owned_by MEGA_CORP_KEY }
|
||||
output("alice's paper") { PAPER_1 owned_by ALICE }
|
||||
arg(ALICE) { Cash.Commands.Move }
|
||||
arg(MEGA_CORP_KEY) { CommercialPaper.Commands.Move }
|
||||
}
|
||||
|
||||
// Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200
|
||||
// as a single payment from somewhere and uses it to pay Alice off, keeping the remaining $200 as change.
|
||||
transaction(time = redemptionTime) {
|
||||
input("alice's paper")
|
||||
input("some profits")
|
||||
|
||||
output { aliceGetsBack.CASH owned_by ALICE }
|
||||
output { (someProfits - aliceGetsBack).CASH owned_by MEGA_CORP_KEY }
|
||||
if (!destroyPaperAtRedemption)
|
||||
output { PAPER_1 owned_by ALICE }
|
||||
|
||||
arg(MEGA_CORP_KEY) { Cash.Commands.Move }
|
||||
arg(ALICE) { CommercialPaper.Commands.Redeem }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
In this example we see some new features of the DSL:
|
||||
|
||||
* The `roots` construct. Sometimes you don't want to write transactions that laboriously issue everything you need
|
||||
in a formally correct way. Inside `roots` you can create a bunch of states without any contract checking what you're
|
||||
doing. As states may not exist outside of transactions, each line inside defines a fake/invalid transaction with the
|
||||
given output states, which may be *labelled* with a short string. Those labels can be used later to join transactions
|
||||
together.
|
||||
* The `.CASH` suffix. This is a part of the unit test DSL specific to the cash contract. It takes a monetary amount
|
||||
like 1000.DOLLARS and then wraps it in a cash ledger state, with some fake data.
|
||||
* The owned_by `infix function <https://kotlinlang.org/docs/reference/functions.html#infix-notation>`_. This is just
|
||||
a normal function that we're allowed to write in a slightly different way, which returns a copy of the cash state
|
||||
with the owner field altered to be the given public key. `ALICE` is a constant defined by the test utilities that
|
||||
is, like `DUMMY_PUBKEY_1`, just an arbitrary keypair.
|
||||
* We are now defining several transactions that chain together. We can optionally label any output we create. Obviously
|
||||
then, the `input` method requires us to give the label of some other output that it connects to.
|
||||
* The `transaction` function can also be given a time, to override the default timestamp on a transaction.
|
||||
|
||||
The `trade` function is not itself a unit test. Instead it builds up a trade/transaction group, with some slight
|
||||
differences depending on the parameters provided (Kotlin allows parameters to have default valus). Then it returns
|
||||
it, unexecuted.
|
||||
|
||||
We use it like this:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
@Test
|
||||
fun ok() {
|
||||
trade().verify()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun not_matured_at_redemption() {
|
||||
trade(redemptionTime = TEST_TX_TIME + 2.days).expectFailureOfTx(3, "must have matured")
|
||||
}
|
||||
|
||||
That's pretty simple: we just call `verify` in order to check all the transactions in the group. If any are invalid,
|
||||
an exception will be thrown indicating which transaction failed and why. In the second case, we call `expectFailureOfTx`
|
||||
again to ensure the third transaction fails with a message that contains "must have matured" (it doesn't have to be
|
||||
the exact message).
|
||||
|
||||
|
||||
Adding a crafting API to your contract
|
||||
--------------------------------------
|
||||
|
||||
TODO: Write this after the CP contract has had a crafting API actually added.
|
||||
|
||||
|
||||
Non-asset-oriented based smart contracts
|
||||
----------------------------------------
|
||||
|
||||
It is important to distinguish between the idea of a legal contract vs a code contract. In this document we use the
|
||||
term *contract* as a shorthand for code contract: a small module of widely shared, simultaneously executed business
|
||||
logic that uses standardised APIs and runs in a sandbox.
|
||||
|
||||
Although this tutorial covers how to implement an owned asset, there is no requirement that states and code contracts
|
||||
*must* be concerned with ownership of an asset. It is better to think of states as representing useful facts about the
|
||||
world, and (code) contracts as imposing logical relations on how facts combine to produce new facts.
|
||||
|
||||
For example, in the case that the transfer of an asset cannot be performed entirely on-ledger, one possible usage of
|
||||
the model is to implement a delivery-vs-payment lifecycle in which there is a state representing an intention to trade,
|
||||
another state representing an in-progress delivery, and a final state in which the delivery is marked as complete and
|
||||
payment is being awaited.
|
||||
|
||||
As another example, consider multi-signature transactions, a feature which is commonly used in Bitcoin to implement
|
||||
various kinds of useful protocols. This technique allows you to lock an asset to ownership of a group, in which a
|
||||
threshold of signers (e.g. 3 out of 4) must all sign simultaneously to enable the asset to move. It is initially
|
||||
tempting to simply add this as another feature to each existing contract which someone might want to treat in this way.
|
||||
But that could lead to unnecessary duplication of work.
|
||||
|
||||
A better approach is to model the fact of joint ownership as a new contract with its own state. In this approach, to
|
||||
lock up your commercial paper under multi-signature ownership you would make a transaction that looks like this:
|
||||
|
||||
* **Input**: the CP state
|
||||
* **Output**: a multi-sig state that contains the list of keys and the signing threshold desired (e.g. 3 of 4). The state has a hash of H.
|
||||
* **Output**: the same CP state, with a marker that says a state with hash H must exist in any transaction that spends it.
|
||||
|
||||
The CP contract then needs to be extended only to verify that a state with the required hash is present as an input.
|
||||
The logic that implements measurement of the threshold, different signing combinations that may be allowed etc can then
|
||||
be implemented once in a separate contract, with the controlling data being held in the named state.
|
||||
|
||||
Future versions of the prototype will explore these concepts in more depth.
|
5
docs/build/html/_static/codesets.js
vendored
5
docs/build/html/_static/codesets.js
vendored
@ -15,6 +15,11 @@ $(document).ready(function() {
|
||||
kotlinButton.setAttribute("class", "");
|
||||
javaButton.setAttribute("class", "current");
|
||||
};
|
||||
|
||||
if ($(el).children(".highlight-java").length == 0) {
|
||||
// No Java for this example.
|
||||
javaButton.style.display = "none";
|
||||
}
|
||||
c.insertBefore(el);
|
||||
});
|
||||
});
|
8
docs/build/html/index.html
vendored
8
docs/build/html/index.html
vendored
@ -157,9 +157,15 @@ time include networking, database or user interface code.</p>
|
||||
<li class="toctree-l2"><a class="reference internal" href="tutorial.html#the-verify-function">The verify function</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="tutorial.html#understanding-fungibility">Understanding fungibility</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="tutorial.html#checking-the-requirements">Checking the requirements</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="tutorial.html#how-to-test-your-contract">How to test your contract</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="tutorial.html#adding-a-crafting-api-to-your-contract">Adding a crafting API to your contract</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="tutorial.html#non-asset-oriented-based-smart-contracts">Non-asset-oriented based smart contracts</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="roadmap.html#milestone-2">Milestone 2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
2
docs/build/html/inthebox.html
vendored
2
docs/build/html/inthebox.html
vendored
@ -144,7 +144,7 @@ versions of the real things.</li>
|
||||
</ul>
|
||||
<p>Some things it does not currently include but should gain later are:</p>
|
||||
<ul class="simple">
|
||||
<li>Sandboxing of smart contract code</li>
|
||||
<li>Sandboxing, distribution or publication of smart contract code</li>
|
||||
<li>A peer to peer network</li>
|
||||
<li>Database persistence</li>
|
||||
<li>An API for integrating external software</li>
|
||||
|
21
docs/build/html/overview.html
vendored
21
docs/build/html/overview.html
vendored
@ -158,11 +158,14 @@ consume/destroy, these are called <strong>inputs</strong>, and contains a set of
|
||||
<p>States contain arbitrary data, but they always contain at minimum a pointer to the bytecode of a
|
||||
<strong>code contract</strong>, which is a program expressed in some byte code that runs sandboxed inside a virtual machine. Code
|
||||
contracts (or just “contracts” in the rest of this document) are globally shared pieces of business logic. Contracts
|
||||
define a <strong>verify function</strong>, which is a pure function of the entire transaction.</p>
|
||||
define a <strong>verify function</strong>, which is a pure function given the entire transaction as input.</p>
|
||||
<p>To be considered valid, the transaction must be <strong>accepted</strong> by the verify function of every contract pointed to by the
|
||||
input and output states. Beyond inputs and outputs, transactions may also contain <strong>commands</strong>, small data packets that
|
||||
the platform does not interpret itself, but which can parameterise execution of the contracts. They can be thought of as
|
||||
arguments to the verify function.</p>
|
||||
<p>Note that there is nothing that explicitly binds together specific inputs, outputs or commands. Instead it’s up to the
|
||||
contract code to interpret the pieces inside the transaction and ensure they fit together correctly. This is done to
|
||||
maximise flexibility for the contract developer.</p>
|
||||
<p>A transaction has one or more <strong>signatures</strong> attached to it. The signatures do not mean anything by themselves, rather,
|
||||
their existence is given as input to the contract which can then decide which set of signatures it demands (if any).
|
||||
Signatures may be from an arbitrary, random <strong>public key</strong> that has no identity attached. A public key may be
|
||||
@ -179,7 +182,17 @@ timestamp, and they are therefore never exposed to private data.</p>
|
||||
<p class="last">In the current code, use of TSAs is not implemented.</p>
|
||||
</div>
|
||||
<p>As the same terminology often crops up in different distributed ledger designs, let’s compare this to other
|
||||
distributed ledger systems you may be familiar with.</p>
|
||||
distributed ledger systems you may be familiar with. You can find more detailed design rationales for why the platform
|
||||
differs from existing systems in <a class="reference external" href="https://r3-cev.atlassian.net/wiki/">the R3 wiki</a>, but to summarise, the driving
|
||||
factors are:</p>
|
||||
<ul class="simple">
|
||||
<li>Improved contract flexibility vs Bitcoin</li>
|
||||
<li>Improved scalability vs Ethereum, as well as ability to keep parts of the transaction graph private (yet still uniquely addressable)</li>
|
||||
<li>No reliance on proof of work</li>
|
||||
<li>Re-us of existing sandboxing virtual machines</li>
|
||||
<li>Use of type safe GCd implementation languages.</li>
|
||||
<li>Simplified auditing</li>
|
||||
</ul>
|
||||
<div class="section" id="comparison-with-bitcoin">
|
||||
<h3>Comparison with Bitcoin<a class="headerlink" href="#comparison-with-bitcoin" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Similarities:</p>
|
||||
@ -206,7 +219,7 @@ this has proved limiting. Our transactions invoke not only input contracts but a
|
||||
<li>A Bitcoin script can only be given a fixed set of byte arrays as the input. This means there’s no way for a contract
|
||||
to examine the structure of the entire transaction, which severely limits what contracts can do.</li>
|
||||
<li>Our contracts are Turing-complete and can be written in any ordinary programming language that targets the JVM.</li>
|
||||
<li>Our transactions and contracts have get their time from an attached timestamp rather than a block chain. This is
|
||||
<li>Our transactions and contracts have to get their time from an attached timestamp rather than a block chain. This is
|
||||
important given that we are currently considering block-free conflict resolution algorithms.</li>
|
||||
<li>We use the term “contract” to refer to a bundle of business logic that may handle various different tasks, beyond
|
||||
transaction verification. For instance, currently our contracts also include code for creating valid transactions
|
||||
@ -225,7 +238,7 @@ based programming languages can be used for contract programming.</li>
|
||||
<ul class="simple">
|
||||
<li>The term “contract” in Ethereum refers to an <em>instantiation</em> of a program that is replicated and maintained by
|
||||
every participating node. This instantiation is very much like an object in an OO program: it can receive and send
|
||||
messages, update local storage and so on. In contrast, use the term “contract” to refer to a set of functions, only
|
||||
messages, update local storage and so on. In contrast, we use the term “contract” to refer to a set of functions, only
|
||||
one of which is a part of keeping the system synchronised (the verify function). That function is pure and
|
||||
stateless i.e. it may not interact with any other part of the system whilst executing.</li>
|
||||
<li>There is no notion of an “account”, as there is in Ethereum.</li>
|
||||
|
28
docs/build/html/roadmap.html
vendored
28
docs/build/html/roadmap.html
vendored
@ -82,10 +82,13 @@
|
||||
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="inthebox.html">What’s included?</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="overview.html">Overview</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="tutorial.html">Tutorial</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="">Roadmap</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="">Roadmap</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#milestone-2">Milestone 2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
@ -132,7 +135,26 @@
|
||||
|
||||
<div class="section" id="roadmap">
|
||||
<h1>Roadmap<a class="headerlink" href="#roadmap" title="Permalink to this headline">¶</a></h1>
|
||||
<p>roadmap</p>
|
||||
<p>The canonical place to learn about pending tasks is the <a class="reference external" href="https://r3-cev.atlassian.net/">R3 JIRA</a> site. This
|
||||
page gives some examples of tasks that we wish to explore in future milestones:</p>
|
||||
<p>M1 is this release.</p>
|
||||
<div class="section" id="milestone-2">
|
||||
<h2>Milestone 2<a class="headerlink" href="#milestone-2" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Contracts API:</p>
|
||||
<ul class="simple">
|
||||
<li>Example implementations of more advanced use cases, possibly an interest rate swap.</li>
|
||||
<li>Support for lifting transaction sub-graphs out of the global ledger and evolving them privately within a subgroup
|
||||
of users (helpful for privacy, scalability).</li>
|
||||
<li>An improved unit test DSL.</li>
|
||||
</ul>
|
||||
<p>Platform:</p>
|
||||
<ul class="simple">
|
||||
<li>Storage of states to disk and initial support for network synchronisation (does not have to be the final network
|
||||
layer: just something good enough to get us to the next stage of prototyping).</li>
|
||||
<li>Dynamic loading and first-pass sandboxing of contract code.</li>
|
||||
<li>Simple test/admin user interface for performing various kinds of trades.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
2
docs/build/html/searchindex.js
vendored
2
docs/build/html/searchindex.js
vendored
File diff suppressed because one or more lines are too long
262
docs/build/html/tutorial.html
vendored
262
docs/build/html/tutorial.html
vendored
@ -92,6 +92,9 @@
|
||||
<li class="toctree-l2"><a class="reference internal" href="#the-verify-function">The verify function</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#understanding-fungibility">Understanding fungibility</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#checking-the-requirements">Checking the requirements</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#how-to-test-your-contract">How to test your contract</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#adding-a-crafting-api-to-your-contract">Adding a crafting API to your contract</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#non-asset-oriented-based-smart-contracts">Non-asset-oriented based smart contracts</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
|
||||
@ -148,7 +151,9 @@
|
||||
for how Kotlin syntax works.</p>
|
||||
<div class="section" id="starting-the-commercial-paper-class">
|
||||
<h2>Starting the commercial paper class<a class="headerlink" href="#starting-the-commercial-paper-class" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A smart contract is a class that implements the <code class="docutils literal"><span class="pre">Contract</span></code> interface. Therefore, we start like this:</p>
|
||||
<p>A smart contract is a class that implements the <code class="docutils literal"><span class="pre">Contract</span></code> interface. For now, they have to be a part of the main
|
||||
codebase, as dynamic loading of contract code is not yet implemented. Therefore, we start by creating a file named
|
||||
either <cite>CommercialPaper.kt</cite> or <cite>CommercialPaper.java</cite> in the src/contracts directory with the following contents:</p>
|
||||
<div class="codeset container">
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="k">class</span> <span class="nc">CommercialPaper</span> <span class="p">:</span> <span class="n">Contract</span> <span class="p">{</span>
|
||||
<span class="k">override</span> <span class="k">val</span> <span class="py">legalContractReference</span><span class="p">:</span> <span class="n">SecureHash</span> <span class="p">=</span> <span class="n">SecureHash</span><span class="p">.</span><span class="n">sha256</span><span class="p">(</span><span class="s">"https://en.wikipedia.org/wiki/Commercial_paper"</span><span class="p">);</span>
|
||||
@ -277,7 +282,10 @@ Beyond that it’s a freeform object into which we can put anything which ca
|
||||
<ul class="simple">
|
||||
<li><cite>issuance</cite>: a reference to a specific piece of commercial paper at an institution</li>
|
||||
<li><cite>owner</cite>: the public key of the current owner. This is the same concept as seen in Bitcoin: the public key has no
|
||||
attached identity and is expected to be one-time-use for privacy reasons.</li>
|
||||
attached identity and is expected to be one-time-use for privacy reasons. However, unlike in Bitcoin, we model
|
||||
ownership at the level of individual contracts rather than as a platform-level concept as we envisage many
|
||||
(possibly most) contracts on the platform will not represent “owner/issuer” relationships, but “party/party”
|
||||
relationships such as a derivative contract.</li>
|
||||
<li><cite>faceValue</cite>: an <cite>Amount</cite>, which wraps an integer number of pennies and a currency.</li>
|
||||
<li><cite>maturityDate</cite>: an <cite>Instant <https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html></cite>, which is a type
|
||||
from the Java 8 standard time library. It defines a point on the timeline.</li>
|
||||
@ -299,26 +307,34 @@ checked, so from the contract code’s perspective, a command is simply a da
|
||||
public keys. Each key had a signature proving that the corresponding private key was used to sign.</p>
|
||||
<p>Let’s define a couple of commands now:</p>
|
||||
<div class="codeset container">
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="n">sealed</span> <span class="k">class</span> <span class="nc">Commands</span> <span class="p">:</span> <span class="n">Command</span> <span class="p">{</span>
|
||||
<span class="k">object</span> <span class="nc">Move</span> <span class="p">:</span> <span class="n">Commands</span><span class="p">()</span>
|
||||
<span class="k">object</span> <span class="nc">Redeem</span> <span class="p">:</span> <span class="n">Commands</span><span class="p">()</span>
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="n">interface</span> <span class="n">Commands</span> <span class="p">:</span> <span class="n">Command</span> <span class="p">{</span>
|
||||
<span class="k">object</span> <span class="nc">Move</span> <span class="p">:</span> <span class="n">Commands</span>
|
||||
<span class="k">object</span> <span class="nc">Redeem</span> <span class="p">:</span> <span class="n">Commands</span>
|
||||
<span class="k">object</span> <span class="nc">Issue</span> <span class="p">:</span> <span class="n">Commands</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-java"><div class="highlight"><pre><span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Commands</span> <span class="kd">implements</span> <span class="n">core</span><span class="o">.</span><span class="na">Command</span> <span class="o">{</span>
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Move</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Move</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Move</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Move</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Redeem</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Redeem</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Redeem</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Redeem</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Issue</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Redeem</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
@ -368,11 +384,16 @@ exception if there’s zero or more than one such command.</p>
|
||||
<p>We say states are <em>fungible</em> if they are treated identically to each other by the recipient, despite the fact that they
|
||||
aren’t quite identical. Dollar bills are fungible because even though one may be worn/a bit dirty and another may
|
||||
be crisp and new, they are still both worth exactly $1. Likewise, ten $1 bills are almost exactly equivalent to
|
||||
one $10 bill. On the other hand, $10 and £10 are not fungible: if you tried to pay for something that cost $20 with
|
||||
one $10 bill. On the other hand, $10 and £10 are not fungible: if you tried to pay for something that cost £20 with
|
||||
$10+£10 notes your trade would not be accepted.</p>
|
||||
<p>So whilst our ledger could represent every monetary amount with a collection of states worth one penny, this would become
|
||||
extremely unwieldy. It’s better to allow states to represent varying amounts and then define rules for merging them
|
||||
and splitting them.</p>
|
||||
and splitting them. Similarly, we could also have considered modelling cash as a single contract that records the
|
||||
ownership of all holders of a given currency from a given issuer. Whilst this is possible, and is effectively how
|
||||
some other platforms work, this prototype favours a design that doesn’t necessarily require state to be shared between
|
||||
multiple actors if they don’t have a direct relationship with each other (as would implicitly be required if we had a
|
||||
single state representing multiple people’s ownership). Keeping the states separated also has scalability benefits, as
|
||||
different parts of the global transaction graph can be updated in parallel.</p>
|
||||
<p>To make this easier the contract API provides a notion of groups. A group is a set of input states and output states
|
||||
that should be checked for validity independently. It solves the following problem: because every contract sees every
|
||||
input and output state in a transaction, it would easy to accidentally write a contract that disallows useful
|
||||
@ -423,6 +444,21 @@ logic.</p>
|
||||
<span class="s">"the paper must be destroyed"</span> <span class="k">by</span> <span class="p">(</span><span class="n">output</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">is</span> <span class="n">Commands</span><span class="p">.</span><span class="n">Issue</span> <span class="p">-></span> <span class="p">{</span>
|
||||
<span class="k">val</span> <span class="py">output</span> <span class="p">=</span> <span class="n">group</span><span class="p">.</span><span class="n">outputs</span><span class="p">.</span><span class="n">single</span><span class="p">()</span>
|
||||
<span class="n">requireThat</span> <span class="p">{</span>
|
||||
<span class="c1">// Don't allow people to issue commercial paper under other entities identities.</span>
|
||||
<span class="s">"the issuance is signed by the claimed issuer of the paper"</span> <span class="k">by</span>
|
||||
<span class="p">(</span><span class="n">command</span><span class="p">.</span><span class="n">signers</span><span class="p">.</span><span class="n">contains</span><span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">issuance</span><span class="p">.</span><span class="n">institution</span><span class="p">.</span><span class="n">owningKey</span><span class="p">))</span>
|
||||
<span class="s">"the face value is not zero"</span> <span class="k">by</span> <span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">faceValue</span><span class="p">.</span><span class="n">pennies</span> <span class="p">></span> <span class="m">0</span><span class="p">)</span>
|
||||
<span class="s">"the maturity date is not in the past"</span> <span class="k">by</span> <span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">maturityDate</span> <span class="p">></span> <span class="n">tx</span><span class="p">.</span><span class="n">time</span><span class="p">)</span>
|
||||
<span class="c1">// Don't allow an existing CP state to be replaced by this issuance.</span>
|
||||
<span class="s">"there is no input state"</span> <span class="k">by</span> <span class="n">group</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">isEmpty</span><span class="p">()</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">else</span> <span class="p">-></span> <span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s">"Unrecognised command"</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
@ -455,6 +491,8 @@ logic.</p>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalStateException</span><span class="o">(</span><span class="s">"Failed requirement: the received amount equals the face value"</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="n">outputs</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">())</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="n">IllegalStateException</span><span class="o">(</span><span class="s">"Failed requirement: the paper must be destroyed"</span><span class="o">);</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">cmd</span><span class="o">.</span><span class="na">getValue</span><span class="o">()</span> <span class="k">instanceof</span> <span class="n">JavaCommercialPaper</span><span class="o">.</span><span class="na">Commands</span><span class="o">.</span><span class="na">Issue</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="c1">// .. etc .. (see Kotlin for full definition)</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
@ -498,6 +536,8 @@ no such states <em>or</em> if there were different currencies represented in the
|
||||
imposes a limitation on the structure of a redemption transaction: you are not allowed to move currencies in the same
|
||||
transaction that the CP does not involve. This limitation could be addressed with better APIs, if it were to be a
|
||||
real limitation.</p>
|
||||
<p>Finally, we support an <cite>Issue</cite> command, to create new instances of commercial paper on the ledger. It likewise
|
||||
enforces various invariants upon the issuance.</p>
|
||||
<p>This contract is extremely simple and does not implement all the business logic a real commercial paper lifecycle
|
||||
management program would. For instance, there is no logic requiring a signature from the issuer for redemption:
|
||||
it is assumed that any transfer of money that takes place at the same time as redemption is good enough. Perhaps
|
||||
@ -506,6 +546,190 @@ bankrupt, if there is a dispute, and so on.</p>
|
||||
<p>As the prototype evolves, these requirements will be explored and this tutorial updated to reflect improvements in the
|
||||
contracts API.</p>
|
||||
</div>
|
||||
<div class="section" id="how-to-test-your-contract">
|
||||
<h2>How to test your contract<a class="headerlink" href="#how-to-test-your-contract" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Of course, it is essential to unit test your new nugget of business logic to ensure that it behaves as you expect.
|
||||
Although you can write traditional unit tests in Java, the platform also provides a <em>domain specific language</em>
|
||||
(DSL) for writing contract unit tests that automates many of the common patterns. This DSL builds on top of JUnit yet
|
||||
is a Kotlin DSL, and therefore this section will not show Java equivalent code (for Java unit tests you would not
|
||||
benefit from the DSL and would write them by hand).</p>
|
||||
<p>We start by defining a new test class, with a basic CP state:</p>
|
||||
<div class="codeset container">
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="k">class</span> <span class="nc">CommercialPaperTests</span> <span class="p">{</span>
|
||||
<span class="k">val</span> <span class="py">PAPER_1</span> <span class="p">=</span> <span class="n">CommercialPaper</span><span class="p">.</span><span class="n">State</span><span class="p">(</span>
|
||||
<span class="n">issuance</span> <span class="p">=</span> <span class="n">InstitutionReference</span><span class="p">(</span><span class="n">MEGA_CORP</span><span class="p">,</span> <span class="n">OpaqueBytes</span><span class="p">.</span><span class="n">of</span><span class="p">(</span><span class="m">123</span><span class="p">)),</span>
|
||||
<span class="n">owner</span> <span class="p">=</span> <span class="n">MEGA_CORP_KEY</span><span class="p">,</span>
|
||||
<span class="n">faceValue</span> <span class="p">=</span> <span class="m">1000.</span><span class="n">DOLLARS</span><span class="p">,</span>
|
||||
<span class="n">maturityDate</span> <span class="p">=</span> <span class="n">TEST_TX_TIME</span> <span class="p">+</span> <span class="m">7.</span><span class="n">days</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="n">@Test</span>
|
||||
<span class="k">fun</span> <span class="nf">key_mismatch_at_issue</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="n">transactionGroup</span> <span class="p">{</span>
|
||||
<span class="n">transaction</span> <span class="p">{</span>
|
||||
<span class="n">output</span> <span class="p">{</span> <span class="n">PAPER_1</span> <span class="p">}</span>
|
||||
<span class="n">arg</span><span class="p">(</span><span class="n">DUMMY_PUBKEY_1</span><span class="p">)</span> <span class="p">{</span> <span class="n">CommercialPaper</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Issue</span><span class="p">()</span> <span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="n">expectFailureOfTx</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="s">"signed by the claimed issuer"</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<p>We start by defining a commercial paper state. It will be owned by a pre-defined unit test institution, affectionately
|
||||
called <cite>MEGA_CORP</cite> (this constant, along with many others, is defined in <cite>TestUtils.kt</cite>). Due to Kotin’s extensive
|
||||
type inference, many types are not written out explicitly in this code and it has the feel of a scripting language.
|
||||
But the types are there, and you can ask IntelliJ to reveal them by pressing Alt-Enter on a “val” or “var” and selecting
|
||||
“Specify type explicitly”.</p>
|
||||
<p>There are a few things that are unusual here:</p>
|
||||
<ul class="simple">
|
||||
<li>We can specify quantities of money by writing 1000.DOLLARS or 1000.POUNDS</li>
|
||||
<li>We can specify quantities of time by writing 7.days</li>
|
||||
<li>We can add quantities of time to the TEST_TX_TIME constant, which merely defines an arbitrary java.time.Instant</li>
|
||||
</ul>
|
||||
<p>If you examine the code in the actual repository, you will also notice that it makes use of method names with spaces
|
||||
in them by surrounding the name with backticks, rather than using underscores. We don’t show this here as it breaks the
|
||||
doc website’s syntax highlighting engine.</p>
|
||||
<p>The <cite>1000.DOLLARS</cite> construct is quite simple: Kotlin allows you to define extension functions on primitive types like
|
||||
Int or Double. So by writing 7.days, for instance, the compiler will emit a call to a static method that takes an int
|
||||
and returns a <cite>java.time.Duration</cite>.</p>
|
||||
<p>As this is JUnit, we must remember to annotate each test method with @Test. Let’s examine the contents of the first test.
|
||||
We are trying to check that it’s not possible for just anyone to issue commercial paper in MegaCorp’s name. That would
|
||||
be bad!</p>
|
||||
<p>The <cite>transactionGroup</cite> function works the same way as the <cite>requireThat</cite> construct above. It is an example of what
|
||||
Kotlin calls a type safe builder, which you can read about in <a class="reference external" href="https://kotlinlang.org/docs/reference/type-safe-builders.html">the documentation for builders</a>.
|
||||
The code block that follows it is run in the scope of a freshly created <cite>TransactionGroupForTest</cite> object, which assists
|
||||
you with building little transaction graphs and verifying them as a whole. Here, our “group” only actually has a
|
||||
single transaction in it, with a single output, no inputs, and an Issue command signed by <cite>DUMMY_PUBKEY_1</cite> which is just
|
||||
an arbitrary public key. As the paper claims to be issued by <cite>MEGA_CORP</cite>, this doesn’t match and should cause a
|
||||
failure. The <cite>expectFailureOfTx</cite> method takes a 1-based index (in this case we expect the first transaction to fail)
|
||||
and a string that should appear in the exception message. Then it runs the <cite>TransactionGroup.verify()</cite> method to
|
||||
invoke all the involved contracts.</p>
|
||||
<p>It’s worth bearing in mind that even though this code may look like a totally different language to normal Kotlin or
|
||||
Java, it’s actually not, and so you can embed arbitrary code anywhere inside any of these blocks.</p>
|
||||
<p>Let’s set up a full trade and ensure it works:</p>
|
||||
<div class="codeset container">
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre> <span class="c1">// Generate a trade lifecycle with various parameters.</span>
|
||||
<span class="k">private</span> <span class="k">fun</span> <span class="nf">trade</span><span class="p">(</span><span class="n">redemptionTime</span><span class="p">:</span> <span class="n">Instant</span> <span class="p">=</span> <span class="n">TEST_TX_TIME</span> <span class="p">+</span> <span class="m">8.</span><span class="n">days</span><span class="p">,</span>
|
||||
<span class="n">aliceGetsBack</span><span class="p">:</span> <span class="n">Amount</span> <span class="p">=</span> <span class="m">1000.</span><span class="n">DOLLARS</span><span class="p">,</span>
|
||||
<span class="n">destroyPaperAtRedemption</span><span class="p">:</span> <span class="n">Boolean</span> <span class="p">=</span> <span class="k">true</span><span class="p">):</span> <span class="n">TransactionGroupForTest</span> <span class="p">{</span>
|
||||
<span class="k">val</span> <span class="py">someProfits</span> <span class="p">=</span> <span class="m">1200.</span><span class="n">DOLLARS</span>
|
||||
<span class="k">return</span> <span class="n">transactionGroup</span> <span class="p">{</span>
|
||||
<span class="n">roots</span> <span class="p">{</span>
|
||||
<span class="n">transaction</span><span class="p">(</span><span class="m">900.</span><span class="n">DOLLARS</span><span class="p">.</span><span class="n">CASH</span> <span class="n">owned_by</span> <span class="n">ALICE</span> <span class="n">label</span> <span class="s">"alice's $900"</span><span class="p">)</span>
|
||||
<span class="n">transaction</span><span class="p">(</span><span class="n">someProfits</span><span class="p">.</span><span class="n">CASH</span> <span class="n">owned_by</span> <span class="n">MEGA_CORP_KEY</span> <span class="n">label</span> <span class="s">"some profits"</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="c1">// Some CP is issued onto the ledger by MegaCorp.</span>
|
||||
<span class="n">transaction</span> <span class="p">{</span>
|
||||
<span class="n">output</span><span class="p">(</span><span class="s">"paper"</span><span class="p">)</span> <span class="p">{</span> <span class="n">PAPER_1</span> <span class="p">}</span>
|
||||
<span class="n">arg</span><span class="p">(</span><span class="n">MEGA_CORP_KEY</span><span class="p">)</span> <span class="p">{</span> <span class="n">CommercialPaper</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Issue</span><span class="p">()</span> <span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="c1">// The CP is sold to alice for her $900, $100 less than the face value. At 10% interest after only 7 days,</span>
|
||||
<span class="c1">// that sounds a bit too good to be true!</span>
|
||||
<span class="n">transaction</span> <span class="p">{</span>
|
||||
<span class="n">input</span><span class="p">(</span><span class="s">"paper"</span><span class="p">)</span>
|
||||
<span class="n">input</span><span class="p">(</span><span class="s">"alice's $900"</span><span class="p">)</span>
|
||||
<span class="n">output</span> <span class="p">{</span> <span class="m">900.</span><span class="n">DOLLARS</span><span class="p">.</span><span class="n">CASH</span> <span class="n">owned_by</span> <span class="n">MEGA_CORP_KEY</span> <span class="p">}</span>
|
||||
<span class="n">output</span><span class="p">(</span><span class="s">"alice's paper"</span><span class="p">)</span> <span class="p">{</span> <span class="n">PAPER_1</span> <span class="n">owned_by</span> <span class="n">ALICE</span> <span class="p">}</span>
|
||||
<span class="n">arg</span><span class="p">(</span><span class="n">ALICE</span><span class="p">)</span> <span class="p">{</span> <span class="n">Cash</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Move</span> <span class="p">}</span>
|
||||
<span class="n">arg</span><span class="p">(</span><span class="n">MEGA_CORP_KEY</span><span class="p">)</span> <span class="p">{</span> <span class="n">CommercialPaper</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Move</span> <span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="c1">// Time passes, and Alice redeem's her CP for $1000, netting a $100 profit. MegaCorp has received $1200</span>
|
||||
<span class="c1">// as a single payment from somewhere and uses it to pay Alice off, keeping the remaining $200 as change.</span>
|
||||
<span class="n">transaction</span><span class="p">(</span><span class="n">time</span> <span class="p">=</span> <span class="n">redemptionTime</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="n">input</span><span class="p">(</span><span class="s">"alice's paper"</span><span class="p">)</span>
|
||||
<span class="n">input</span><span class="p">(</span><span class="s">"some profits"</span><span class="p">)</span>
|
||||
|
||||
<span class="n">output</span> <span class="p">{</span> <span class="n">aliceGetsBack</span><span class="p">.</span><span class="n">CASH</span> <span class="n">owned_by</span> <span class="n">ALICE</span> <span class="p">}</span>
|
||||
<span class="n">output</span> <span class="p">{</span> <span class="p">(</span><span class="n">someProfits</span> <span class="p">-</span> <span class="n">aliceGetsBack</span><span class="p">).</span><span class="n">CASH</span> <span class="n">owned_by</span> <span class="n">MEGA_CORP_KEY</span> <span class="p">}</span>
|
||||
<span class="k">if</span> <span class="p">(!</span><span class="n">destroyPaperAtRedemption</span><span class="p">)</span>
|
||||
<span class="n">output</span> <span class="p">{</span> <span class="n">PAPER_1</span> <span class="n">owned_by</span> <span class="n">ALICE</span> <span class="p">}</span>
|
||||
|
||||
<span class="n">arg</span><span class="p">(</span><span class="n">MEGA_CORP_KEY</span><span class="p">)</span> <span class="p">{</span> <span class="n">Cash</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Move</span> <span class="p">}</span>
|
||||
<span class="n">arg</span><span class="p">(</span><span class="n">ALICE</span><span class="p">)</span> <span class="p">{</span> <span class="n">CommercialPaper</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Redeem</span> <span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<p>In this example we see some new features of the DSL:</p>
|
||||
<ul class="simple">
|
||||
<li>The <cite>roots</cite> construct. Sometimes you don’t want to write transactions that laboriously issue everything you need
|
||||
in a formally correct way. Inside <cite>roots</cite> you can create a bunch of states without any contract checking what you’re
|
||||
doing. As states may not exist outside of transactions, each line inside defines a fake/invalid transaction with the
|
||||
given output states, which may be <em>labelled</em> with a short string. Those labels can be used later to join transactions
|
||||
together.</li>
|
||||
<li>The <cite>.CASH</cite> suffix. This is a part of the unit test DSL specific to the cash contract. It takes a monetary amount
|
||||
like 1000.DOLLARS and then wraps it in a cash ledger state, with some fake data.</li>
|
||||
<li>The owned_by <a class="reference external" href="https://kotlinlang.org/docs/reference/functions.html#infix-notation">infix function</a>. This is just
|
||||
a normal function that we’re allowed to write in a slightly different way, which returns a copy of the cash state
|
||||
with the owner field altered to be the given public key. <cite>ALICE</cite> is a constant defined by the test utilities that
|
||||
is, like <cite>DUMMY_PUBKEY_1</cite>, just an arbitrary keypair.</li>
|
||||
<li>We are now defining several transactions that chain together. We can optionally label any output we create. Obviously
|
||||
then, the <cite>input</cite> method requires us to give the label of some other output that it connects to.</li>
|
||||
<li>The <cite>transaction</cite> function can also be given a time, to override the default timestamp on a transaction.</li>
|
||||
</ul>
|
||||
<p>The <cite>trade</cite> function is not itself a unit test. Instead it builds up a trade/transaction group, with some slight
|
||||
differences depending on the parameters provided (Kotlin allows parameters to have default valus). Then it returns
|
||||
it, unexecuted.</p>
|
||||
<p>We use it like this:</p>
|
||||
<div class="codeset container">
|
||||
<div class="highlight-kotlin"><div class="highlight"><pre><span class="n">@Test</span>
|
||||
<span class="k">fun</span> <span class="nf">ok</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="n">trade</span><span class="p">().</span><span class="n">verify</span><span class="p">()</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="n">@Test</span>
|
||||
<span class="k">fun</span> <span class="nf">not_matured_at_redemption</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="n">trade</span><span class="p">(</span><span class="n">redemptionTime</span> <span class="p">=</span> <span class="n">TEST_TX_TIME</span> <span class="p">+</span> <span class="m">2.</span><span class="n">days</span><span class="p">).</span><span class="n">expectFailureOfTx</span><span class="p">(</span><span class="m">3</span><span class="p">,</span> <span class="s">"must have matured"</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<p>That’s pretty simple: we just call <cite>verify</cite> in order to check all the transactions in the group. If any are invalid,
|
||||
an exception will be thrown indicating which transaction failed and why. In the second case, we call <cite>expectFailureOfTx</cite>
|
||||
again to ensure the third transaction fails with a message that contains “must have matured” (it doesn’t have to be
|
||||
the exact message).</p>
|
||||
</div>
|
||||
<div class="section" id="adding-a-crafting-api-to-your-contract">
|
||||
<h2>Adding a crafting API to your contract<a class="headerlink" href="#adding-a-crafting-api-to-your-contract" title="Permalink to this headline">¶</a></h2>
|
||||
<p>TODO: Write this after the CP contract has had a crafting API actually added.</p>
|
||||
</div>
|
||||
<div class="section" id="non-asset-oriented-based-smart-contracts">
|
||||
<h2>Non-asset-oriented based smart contracts<a class="headerlink" href="#non-asset-oriented-based-smart-contracts" title="Permalink to this headline">¶</a></h2>
|
||||
<p>It is important to distinguish between the idea of a legal contract vs a code contract. In this document we use the
|
||||
term <em>contract</em> as a shorthand for code contract: a small module of widely shared, simultaneously executed business
|
||||
logic that uses standardised APIs and runs in a sandbox.</p>
|
||||
<p>Although this tutorial covers how to implement an owned asset, there is no requirement that states and code contracts
|
||||
<em>must</em> be concerned with ownership of an asset. It is better to think of states as representing useful facts about the
|
||||
world, and (code) contracts as imposing logical relations on how facts combine to produce new facts.</p>
|
||||
<p>For example, in the case that the transfer of an asset cannot be performed entirely on-ledger, one possible usage of
|
||||
the model is to implement a delivery-vs-payment lifecycle in which there is a state representing an intention to trade,
|
||||
another state representing an in-progress delivery, and a final state in which the delivery is marked as complete and
|
||||
payment is being awaited.</p>
|
||||
<p>As another example, consider multi-signature transactions, a feature which is commonly used in Bitcoin to implement
|
||||
various kinds of useful protocols. This technique allows you to lock an asset to ownership of a group, in which a
|
||||
threshold of signers (e.g. 3 out of 4) must all sign simultaneously to enable the asset to move. It is initially
|
||||
tempting to simply add this as another feature to each existing contract which someone might want to treat in this way.
|
||||
But that could lead to unnecessary duplication of work.</p>
|
||||
<p>A better approach is to model the fact of joint ownership as a new contract with its own state. In this approach, to
|
||||
lock up your commercial paper under multi-signature ownership you would make a transaction that looks like this:</p>
|
||||
<ul class="simple">
|
||||
<li><strong>Input</strong>: the CP state</li>
|
||||
<li><strong>Output</strong>: a multi-sig state that contains the list of keys and the signing threshold desired (e.g. 3 of 4). The state has a hash of H.</li>
|
||||
<li><strong>Output</strong>: the same CP state, with a marker that says a state with hash H must exist in any transaction that spends it.</li>
|
||||
</ul>
|
||||
<p>The CP contract then needs to be extended only to verify that a state with the required hash is present as an input.
|
||||
The logic that implements measurement of the threshold, different signing combinations that may be allowed etc can then
|
||||
be implemented once in a separate contract, with the controlling data being held in the named state.</p>
|
||||
<p>Future versions of the prototype will explore these concepts in more depth.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user