Introduce documentation of the current prototype with a contract programming tutorial (incomplete), using the Sphinx docs engine.

Actual generated HTML will follow in the next commit.
This commit is contained in:
Mike Hearn 2015-11-25 14:27:07 +01:00
parent ff05cb4a4c
commit 3dd10714df
10 changed files with 1248 additions and 0 deletions

192
docs/Makefile Normal file
View File

@ -0,0 +1,192 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Playground.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Playground.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Playground"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Playground"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

View File

@ -0,0 +1,20 @@
$(document).ready(function() {
$(".codeset").each(function(index, el) {
var c = $("<div class='codesnippet-widgets'><span class='current'>Kotlin</span><span>Java</span></div>");
var kotlinButton = c.children()[0];
var javaButton = c.children()[1];
kotlinButton.onclick = function() {
$(el).children(".highlight-java")[0].style.display = "none";
$(el).children(".highlight-kotlin")[0].style.display = "block";
javaButton.setAttribute("class", "");
kotlinButton.setAttribute("class", "current");
};
javaButton.onclick = function() {
$(el).children(".highlight-java")[0].style.display = "block";
$(el).children(".highlight-kotlin")[0].style.display = "none";
kotlinButton.setAttribute("class", "");
javaButton.setAttribute("class", "current");
};
c.insertBefore(el);
});
});

View File

@ -0,0 +1,27 @@
@import "theme.css";
.highlight .k, .highlight .kd {
color: blue;
}
.codesnippet-widgets {
min-width: 100%;
display: block;
background: lightskyblue;
color: white;
padding: 10px 0;
margin: 0 0 -1px 0;
}
.codesnippet-widgets > span {
padding: 10px;
cursor: pointer;
}
.codesnippet-widgets > .current {
background: deepskyblue;
}
.codeset > .highlight-java {
display: none;
}

291
docs/source/conf.py Normal file
View File

@ -0,0 +1,291 @@
# -*- coding: utf-8 -*-
#
# Playground documentation build configuration file, created by
# sphinx-quickstart on Mon Nov 23 21:19:35 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sphinx_rtd_theme
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Playground'
copyright = u'2015, R3 CEV'
author = u'R3 CEV'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
highlight_language = 'kotlin'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# html_theme = 'alabaster'
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_style = 'css/custom.css'
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'Playgrounddoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Playground.tex', u'Playground Documentation',
u'R3 CEV', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'playground', u'Playground Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Playground', u'Playground Documentation',
author, 'Playground', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

View File

@ -0,0 +1,32 @@
Getting set up
==============
Install the Oracle JDK 8u45 or higher. OpenJDK will probably also work but I'm not testing with that.
Then install IntelliJ version 15 community edition:
https://www.jetbrains.com/idea/download/
Upgrade the Kotlin plugin to the latest version (1.0-beta-2423) by clicking "Configure > Plugins" in the opening screen,
then clicking "Install JetBrains plugin", then searching for Kotlin, then hitting "Upgrade" and then "Restart".
Choose "Check out from version control" and use this git URL
https://your_username@bitbucket.org/R3-CEV/playground.git
Agree to the defaults for importing a Gradle project. Wait for it to think and download the dependencies.
Right click on the tests directory, click "Run -> All Tests" (note: NOT the first item in the submenu that has the
gradle logo next to it).
The code should build, the unit tests should show as all green.
You can catch up with the latest code by selecting "VCS -> Update Project" in the menu.
Doing it without IntelliJ
-------------------------
If you don't want to explore or modify the code in a local IDE, you can also just use the command line and a text editor:
* Run ``./gradlew test`` to run the unit tests.
* Run ``git pull`` to upgrade

21
docs/source/index.rst Normal file
View File

@ -0,0 +1,21 @@
Welcome to the Playground's documentation!
==========================================
This documentation describes the first prototype of the R3 shared ledger platform.
The goal of this prototype is to explore fundamentally better designs for transactions, states and smart contract APIs
than what presently exists on the market, tailor made for the needs of the financial industry. It does not at this
time include networking, database or user interface code.
Read on to learn:
.. toctree::
:maxdepth: 2
inthebox
overview
getting-set-up
tutorial
roadmap

28
docs/source/inthebox.rst Normal file
View File

@ -0,0 +1,28 @@
What's included?
================
The current prototype consists of a small amount of code that defines:
* Key data structures
* Algorithms that work with them, such as serialising, hashing, signing, and verification of the signatures.
* Two smart contracts that implement a notion of a cash claim, and a notion of commercial paper. These are simplified
versions of the real things.
* Unit tests that check the algorithms do what is expected, and which verify the behaviour of the smart contracts.
* API documentation and tutorials (what you're reading)
Some things it does not currently include but should gain later are:
* Sandboxing of smart contract code
* A peer to peer network
* Database persistence
* An API for integrating external software
* A user interface for administration
* Many other things
You can browse `the JIRA bug tracker <https://r3-cev.atlassian.net/>`_.
The prototype's goal is rapid exploration of ideas. Therefore in places it takes shortcuts that a production system
would not in order to boost productivity:
* It uses a serialization framework instead of a well specified, vendor neutral protocol.
* It uses secp256r1, an obsolete elliptic curve.

147
docs/source/overview.rst Normal file
View File

@ -0,0 +1,147 @@
Overview
========
This article covers the data model: how *states*, *transactions* and *code contracts* interact with each other and
how they are represented in the code. It doesn't attempt to give detailed design rationales or information on future
design elements: please refer to the R3 wiki for background information.
Data model
----------
We begin with the idea of a global ledger. In our model, although the ledger is shared, it is not always the case that
transactions and ledger entries are globally visible. In cases where a set of transactions stays within a small subgroup of
users it should be possible to keep the relevant data purely within that group.
To ensure consistency in a global, shared system where not all data may be visible to all participants, we rely
heavily on secure hashes like SHA-256 to identify things. The ledger is defined as a set of immutable **states**, which
are created and destroyed by digitally signed **transactions**. Each transaction points to a set of states that it will
consume/destroy, these are called **inputs**, and contains a set of new states that it will create, these are called
**outputs**.
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.
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.
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
well known, that is, appears in some sort of public identity registry. In this case we say the key is owned by an
**institution**, which is defined (for now) as being merely a (public key, name) pair.
A transaction may also be **timestamped**. A timestamp is a (hash, datetime, signature) triple from a
*timestamping authority* (TSA). The notion of a TSA is not ledger specific and is defined by
`IETF RFC 3161 <https://www.ietf.org/rfc/rfc3161.txt>`_ which defines the internet standard Timestamping Protocol (TSP).
The purpose of the TSA is to attach a single, globally agreed upon time which a contract may use to enforce certain
types of time-based logic. The TSA's do not need to know about the contents of the transaction in order to provide a
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.
Comparison with Bitcoin
^^^^^^^^^^^^^^^^^^^^^^^
Similarities:
* The basic notion of immutable states that are consumed and created by transactions is the same.
* The notion of transactions having multiple inputs and outputs is the same. Bitcoin sometimes refers to the ledger
as the unspent transaction output set (UTXO set) as a result.
* Like in Bitcoin, a contract is pure function. Contracts do not have storage or the ability to interact with anything.
Given the same transaction, a contract's accept function always yields exactly the same result.
* Bitcoin output scripts are parameterised by the input scripts in the spending transaction. This is somewhat similar
to our notion of a *command*.
* Bitcoin transactions, like ours, refer to the states they consume by using a (txhash, index) pair. The Bitcoin
protocol calls these "outpoints". In our prototype code they are known as ``StateRefs`` but the concept is identical.
* Bitcoin transactions have an associated timestamp (the time at which they are mined).
Differences:
* A Bitcoin transaction has a single, rigid data format. A "state" in Bitcoin is always a (quantity of bitcoin, script)
pair and cannot hold any other data. Some people have been known to try and hack around this limitation by embedding
data in semi-standardised places in the contract code so the data can be extracted through pattern matching, but this
is a poor approach. Our states can include arbitrary typed data.
* A Bitcoin transaction's acceptance is controlled only by the contract code in the consumed input states. In practice
this has proved limiting. Our transactions invoke not only input contracts but also the contracts of the outputs.
* 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
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
(this is often called "wallet code" in Bitcoin).
Comparison with Ethereum
^^^^^^^^^^^^^^^^^^^^^^^^
Similarities:
* Like Ethereum, code runs inside a relatively powerful virtual machine and can contain complex logic. Non-assembly
based programming languages can be used for contract programming.
* They are both intended for the modelling of many different kinds of financial contract.
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
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.
* As contracts don't have any kind of mutable storage, there is no notion of a "message" as in Ethereum.
* Ethereum claims to be a platform not only for financial logic, but literally any kind of application at all. Our
platform considers non-financial applications to be out of scope.
Contracts
---------
The primary goal of this prototype is to implement various kinds of contracts and verify that useful business logic
can be expressed with the data model, developing and refining an API along the way. To that end there are currently
two contracts in the repository:
1. Cash
2. Commercial paper
``Cash`` implements the idea of a claim on some quantity of deposits at some institution, denominated in some currency,
identified by some *deposit reference*. A deposit reference is an opaque byte array which is usable by
the issuing institution for internal bookkeeping purposes.
Cash states are *fungible* with each other (can be merged and split arbitrarily) if they use the same currency,
institution and deposit reference.
``CommercialPaper`` implements an asset with a *face value* denominated in a certain currency, which may be redeemed at
the issuing institution after a certain time. Commercial paper states define the face value (e.g. $1000) and the time
at which they may be redeemed. The contract allows the paper to be issued, traded and redeemed. The commercial paper
contract is implemented twice, once in Java and once in a language called Kotlin.
Each contract comes with unit tests.
Kotlin
------
The prototype is written in a language called `Kotlin <https://kotlinlang.org/>`_. Kotlin is a language that targets the JVM
and can be thought of as a simpler Scala, with much better Java interop. It is developed by and has commercial support
from JetBrains, the makers of the IntelliJ IDE and other popular developer tools.
As Kotlin is very new, without a doubt you have not encountered it before. Don't worry: it is designed as a better
Java for industrial use and as such, the syntax was carefully designed to be readable even to people who don't know
the language, after only a few minutes of introduction.
Due to the seamless Java interop the use of Kotlin to extend the platform is *not* required and the tutorial shows how
to write contracts in both Kotlin and Java. You can `read more about why Kotlin is a potentially strong successor to Java here <https://medium.com/@octskyward/why-kotlin-is-my-next-programming-language-c25c001e26e3>`_.
Kotlin programs use the regular Java standard library and ordinary Java frameworks. Frameworks used at this time are:
* JUnit for unit testing
* Kryo for serialisation (this is not intended to be permanent)
* Gradle for the build
* Guava for a few utility functions

25
docs/source/roadmap.rst Normal file
View File

@ -0,0 +1,25 @@
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.

465
docs/source/tutorial.rst Normal file
View File

@ -0,0 +1,465 @@
.. highlight:: kotlin
.. raw:: html
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/codesets.js"></script>
Tutorial
========
This tutorial will take you through how the commercial paper contract works, and then teaches you how to define your own
"hello world" contract for managing the ownership of an office building.
The code in this tutorial is available in both Kotlin and Java. You can quickly switch between them to get a feeling
for how Kotlin syntax works.
Starting the commercial paper class
-----------------------------------
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
.. sourcecode:: kotlin
class CommercialPaper : Contract {
override val legalContractReference: SecureHash = SecureHash.sha256("https://en.wikipedia.org/wiki/Commercial_paper");
override fun verify(tx: TransactionForVerification) {
TODO()
}
}
.. sourcecode:: java
public class Cash implements Contract {
@Override
public SecureHash getLegalContractReference() {
return SecureHash.Companion.sha256("https://en.wikipedia.org/wiki/Commercial_paper");
}
@Override
public void verify(TransactionForVerification tx) {
throw new UnsupportedOperationException();
}
}
Every contract must have at least a ``getLegalContractReference()`` and a ``verify()`` method. In Kotlin we express
a getter without a setter as an immutable property (val). The *legal contract reference* is supposed to be a hash
of a document that describes the legal contract and may take precedence over the code, in case of a dispute.
The verify method returns nothing. This is intentional: the function either completes correctly, or throws an exception,
in which case the transaction is rejected.
We also need to define a constant hash that would, in a real system, be the hash of the program bytecode. For now
we just set it to a dummy value as dynamic loading and sandboxing of bytecode is not implemented. This constant
isn't shown in the code snippet but is called `CP_PROGRAM_ID`.
So far, so simple. Now we need to define the commercial paper *state*, which represents the fact of ownership of a
piece of issued paper.
States
------
A state is a class that stores data that is checked by the contract.
.. container:: codeset
.. sourcecode:: kotlin
data class State(
val issuance: InstitutionReference,
val owner: PublicKey,
val faceValue: Amount,
val maturityDate: Instant
) : ContractState {
override val programRef = CP_PROGRAM_ID
fun withoutOwner() = copy(owner = NullPublicKey)
}
.. sourcecode:: java
public static class State implements ContractState, SerializeableWithKryo {
private InstitutionReference issuance;
private PublicKey owner;
private Amount faceValue;
private Instant maturityDate;
public State() {} // For serialization
public State(InstitutionReference issuance, PublicKey owner, Amount faceValue, Instant maturityDate) {
this.issuance = issuance;
this.owner = owner;
this.faceValue = faceValue;
this.maturityDate = maturityDate;
}
public InstitutionReference getIssuance() {
return issuance;
}
public PublicKey getOwner() {
return owner;
}
public Amount getFaceValue() {
return faceValue;
}
public Instant getMaturityDate() {
return maturityDate;
}
@NotNull
@Override
public SecureHash getProgramRef() {
return SecureHash.Companion.sha256("java commercial paper (this should be a bytecode hash)");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
State state = (State) o;
if (issuance != null ? !issuance.equals(state.issuance) : state.issuance != null) return false;
if (owner != null ? !owner.equals(state.owner) : state.owner != null) return false;
if (faceValue != null ? !faceValue.equals(state.faceValue) : state.faceValue != null) return false;
return !(maturityDate != null ? !maturityDate.equals(state.maturityDate) : state.maturityDate != null);
}
@Override
public int hashCode() {
int result = issuance != null ? issuance.hashCode() : 0;
result = 31 * result + (owner != null ? owner.hashCode() : 0);
result = 31 * result + (faceValue != null ? faceValue.hashCode() : 0);
result = 31 * result + (maturityDate != null ? maturityDate.hashCode() : 0);
return result;
}
public State withoutOwner() {
return new State(issuance, NullPublicKey.INSTANCE, faceValue, maturityDate);
}
}
We define a class that implements the `ContractState` and `SerializableWithKryo` interfaces. The
latter is an artifact of how the prototype implements serialization and can be ignored for now: it wouldn't work
like this in any final product.
The `ContractState` interface requires us to provide a `getProgramRef` method that is supposed to return a hash of
the bytecode of the contract itself. For now this is a dummy value and isn't used: later on, this mechanism will change.
Beyond that it's a freeform object into which we can put anything which can be serialized.
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.
* `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.
States are immutable, and thus the class is defined as immutable as well. The `data` modifier in the Kotlin version
causes the compiler to generate the equals/hashCode/toString methods automatically, along with a copy method that can
be used to create variants of the original object. Data classes are similar to case classes in Scala, if you are
familiar with that language. The `withoutOwner` method uses the auto-generated copy method to return a version of
the state with the owner public key blanked out: this will prove useful later.
The Java code compiles to the same bytecode as the Kotlin version, but as you can see, is much more verbose.
Commands
--------
The logic for a contract may vary depending on what stage of a lifecycle it is automating. So it can be useful to
pass additional data into the contract code that isn't represented by the states which exist permanently in the ledger.
For this purpose we have commands. Often, they don't need to contain any data at all, they just need to exist. A command
is a piece of data associated with some *signatures*. By the time the contract runs the signatures have already been
checked, so from the contract code's perspective, a command is simply a data structure with a list of attached
public keys. Each key had a signature proving that the corresponding private key was used to sign.
Let's define a couple of commands now:
.. container:: codeset
.. sourcecode:: kotlin
sealed class Commands : Command {
object Move : Commands()
object Redeem : 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 Redeem 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
case, they can be empty and we just use their type as the important information. Java has no syntax for declaring
singletons, so we just define a class that considers any other instance to be equal and that's good enough.
The verify function
-------------------
The heart of a smart contract is the code that verifies a set of state transitions (a *transaction*). The function is
simple: it's given a class representing the transaction, and if the function returns then the transaction is considered
acceptable. If it throws an exception, the transaction is rejected.
Each transaction can have multiple input and output states of different types. The set of contracts to run is decided
by taking the code references inside each state. Each contract is run only once. As an example, a contract that includes
2 cash states and 1 commercial paper state as input, and has as output 1 cash state and 1 commercial paper state, will
run two contracts one time each: Cash and CommercialPaper.
.. container:: codeset
.. sourcecode:: kotlin
override fun verify(tx: TransactionForVerification) {
// Group by everything except owner: any modification to the CP at all is considered changing it fundamentally.
val groups = tx.groupStates<State>() { it.withoutOwner() }
// There are two possible things that can be done with this CP. The first is trading it. The second is redeeming
// it for cash on or after the maturity date.
val command = tx.commands.requireSingleCommand<CommercialPaper.Commands>()
.. sourcecode:: java
@Override
public void verify(@NotNull TransactionForVerification tx) {
// There are two possible things that can be done with CP. The first is trading it. The second is redeeming it
// for cash on or after the maturity date.
List<InOutGroup<State>> groups = tx.groupStates(State.class, State::withoutOwner);
// Find the command that instructs us what to do and check there's exactly one.
AuthenticatedObject<Command> cmd = requireSingleCommand(tx.getCommands(), Commands.class);
We start by using the `groupStates` method, which takes a type and a function (in functional programming a function
that takes another function as an argument is called a *higher order function*). State grouping is a way of handling
*fungibility* in a contract, which is explained next. The second line does what the code suggests: it searches for
a command object that inherits from the `CommercialPaper.Commands` supertype, and either returns it, or throws an
exception if there's zero or more than one such command.
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
$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.
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
combinations of states. For example, our cash contract might end up lazily assuming there's only one currency involved
in a transaction, whereas in reality we would like the ability to model a currency trade in which two parties contribute
inputs of different currencies, and both parties get outputs of the opposite currency.
Consider the following simplified currency trade transaction:
* **Input**: $12,000 owned by Alice (A)
* **Input**: $3,000 owned by Alice (A)
* **Input**: £10,000 owned by Bob (B)
* **Output**: £10,000 owned by Alice (B)
* **Output**: $15,000 owned by Bob (A)
In this transaction Alice and Bob are trading $15,000 for £10,000. Alice has her money in the form of two different
inputs e.g. because she received the dollars in two payments. The input and output amounts do balance correctly, but
the cash smart contract must consider the pounds and the dollars separately because they are not fungible: they cannot
be merged together. So we have two groups: A and B.
The `TransactionForVerification.groupStates` method handles this logic for us: firstly, it selects only states of the
given type (as the transaction may include other types of state, such as states representing bond ownership, or a
multi-sig state) and then it takes a function that maps a state to a grouping key. All states that share the same key are
grouped together. In the case of the cash example above, the grouping key would be the currency.
In our commercial paper contract, we don't want CP to be fungible: merging and splitting is (in our example) not allowed.
So we just use a copy of the state minus the owner field as the grouping key. As a result, a single transaction can
trade many different pieces of commercial paper in a single atomic step.
A group may have zero inputs or zero outputs: this can occur when issuing assets onto the ledger, or removing them.
Checking the requirements
-------------------------
After extracting the command and the groups, we then iterate over each group and verify it meets the required business
logic.
.. container:: codeset
.. sourcecode:: kotlin
for (group in groups) {
val input = group.inputs.single()
requireThat {
"the transaction is signed by the owner of the CP" by (command.signers.contains(input.owner))
}
val output = group.outputs.singleOrNull()
when (command.value) {
is Commands.Move -> requireThat { "the output state is present" by (output != null) }
is Commands.Redeem -> {
val received = tx.outStates.sumCashOrNull() ?: throw IllegalStateException("no cash being redeemed")
requireThat {
"the paper must have matured" by (input.maturityDate < tx.time)
"the received amount equals the face value" by (received == input.faceValue)
"the paper must be destroyed" by (output == null)
}
}
}
}
.. sourcecode:: java
for (InOutGroup<State> group : groups) {
List<State> inputs = group.getInputs();
List<State> outputs = group.getOutputs();
// For now do not allow multiple pieces of CP to trade in a single transaction. Study this more!
State input = single(filterIsInstance(inputs, State.class));
if (!cmd.getSigners().contains(input.getOwner()))
throw new IllegalStateException("Failed requirement: the transaction is signed by the owner of the CP");
if (cmd.getValue() instanceof JavaCommercialPaper.Commands.Move) {
// Check the output CP state is the same as the input state, ignoring the owner field.
State output = single(outputs);
if (!output.getFaceValue().equals(input.getFaceValue()) ||
!output.getIssuance().equals(input.getIssuance()) ||
!output.getMaturityDate().equals(input.getMaturityDate()))
throw new IllegalStateException("Failed requirement: the output state is the same as the input state except for owner");
} else if (cmd.getValue() instanceof JavaCommercialPaper.Commands.Redeem) {
Amount received = CashKt.sumCashOrNull(inputs);
if (received == null)
throw new IllegalStateException("Failed requirement: no cash being redeemed");
if (input.getMaturityDate().isAfter(tx.getTime()))
throw new IllegalStateException("Failed requirement: the paper must have matured");
if (!input.getFaceValue().equals(received))
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");
}
}
This loop is the core logic of the contract.
The first line (first three lines in Java) impose a requirement that there be a single piece of commercial paper in
this group. We do not allow multiple units of CP to be split or merged even if they are owned by the same owner. The
`single()` method is a static *extension method* defined by the Kotlin standard library: given a list, it throws an
exception if the list size is not 1, otherwise it returns the single item in that list. In Java, this appears as a
regular static method of the type familiar from many FooUtils type singleton classes. In Kotlin, it appears as a
method that can be called on any JDK list. The syntax is slightly different but behind the scenes, the code compiles
to the same bytecodes.
Next, we check that the transaction was signed by the public key that's marked as the current owner of the commercial
paper. Because the platform has already verified all the digital signatures before the contract begins execution,
all we have to do is verify that the owner's public key was one of the keys that signed the transaction. The Java code
is straightforward. The Kotlin version looks a little odd: we have a *requireThat* construct that looks like it's
built into the language. In fact *requireThat* is an ordinary function provided by the platform's contract API. Kotlin
supports the creation of *domain specific languages* through the intersection of several features of the language, and
we use it here to support the natural listing of requirements. To see what it compiles down to, look at the Java version.
Each `"string" by (expression)` statement inside a `requireThat` turns into an assertion that the given expression is
true, with an exception being thrown that contains the string if not. It's just another way to write out a regular
assertion, but with the English-language requirement being put front and center.
Next, we take one of two paths, depending on what the type of the command object is.
If the command is a `Move` command, then we simply verify that the output state is actually present: a move is not
allowed to delete the CP from the ledger. The grouping logic already ensured that the details are identical and haven't
been changed, save for the public key of the owner.
If the command is a `Redeem` command, then the requirements are more complex:
1. We want to see that the face value of the CP is being moved as a cash claim against some institution, that is, the
issuer of the CP is really paying back the face value.
2. The transaction must be happening after the maturity date.
3. The commercial paper must *not* be propagated by this transaction: it must be deleted, by the group having no
output state. This prevents the same CP being considered redeemable multiple times.
To calculate how much cash is moving, we use the `sumCashOrNull` utility method. Again, this is an extension method,
so in Kotlin code it appears as if it was a method on the `List<Cash.State>` type even though JDK provides no such
method. In Java we see its true nature: it is actually a static method named `CashKt.sumCashOrNull`. This method simply
returns an `Amount` object containing the sum of all the cash states in the transaction output, or null if there were
no such states *or* if there were different currencies represented in the outputs! So we can see that this contract
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.
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
that is something that should be tightened. Likewise, there is no logic handling what happens if the issuer has gone
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.
Adding a crafting API to your contract
--------------------------------------
TODO: Write this after the CP contract has had a crafting API actually added.
How to test your contract
-------------------------
TODO: Write this next
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.