Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate go perun tutorial #48

Merged
1 change: 1 addition & 0 deletions .circleci/config.yml
Expand Up @@ -9,6 +9,7 @@ commands:
setup:
steps:
- checkout
- run: git submodule init && git submodule update
- add_ssh_keys:
fingerprints: "ba:c4:1d:f9:75:8e:45:6e:bb:30:0c:58:4d:28:40:32"
- restore_cache:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -4,4 +4,6 @@ build/
public/
tools/

_build/

*~
3 changes: 3 additions & 0 deletions .gitmodules
@@ -0,0 +1,3 @@
[submodule "source/perun-examples"]
path = source/perun-examples
url = https://github.com/perun-network/perun-examples
2 changes: 1 addition & 1 deletion Makefile
@@ -1,5 +1,5 @@
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXOPTS = -W --keep-going
SPHINXBUILD = sphinx-build
SPHINXPROJ = perun-doc
SOURCEDIR = source
Expand Down
8 changes: 8 additions & 0 deletions README.md
Expand Up @@ -14,6 +14,14 @@ HTML documentation is published at

## Build

Clone the repository with submodules.

```bash
git clone https://github.com/hyperledger-labs/perun-doc.git
cd perun-doc
git submodule update --init --recursive
```

To check if python, sphinx and sphinx-rtd-theme are installed, run
[setup.sh](setup.sh) from the project root directory. If any of the
components are missing, the script will install them.
Expand Down
2 changes: 1 addition & 1 deletion source/_templates/footer.html
Expand Up @@ -18,7 +18,7 @@
{%- if hasdoc('copyright') %}
{% trans path=pathto('copyright'), copyright=copyright|e %}<a href="{{ path }}">Copyright</a> &copy; {{ copyright }}.{% endtrans %}
{%- else %}
{% trans copyright=copyright|e %}Copyright &copy; 2020 Hyperledger {% endtrans %}
{% trans copyright=copyright|e %}Copyright &copy; 2020-2021, Perun Framework Contributors.{% endtrans %}
{%- endif %}
{%- endif %}
<br>
Expand Down
2 changes: 2 additions & 0 deletions source/concepts/state-channel.rst
Expand Up @@ -24,6 +24,8 @@ necessary security guarantees:
:align: Center
:alt: Image not available

.. _State Channels:

State Channels
==============

Expand Down
14 changes: 9 additions & 5 deletions source/conf.py
Expand Up @@ -19,9 +19,9 @@

# -- Project information -----------------------------------------------------

project = u'perun-doc'
copyright = u'2020, Hyperledger'
author = u'Hyperledger'
project = u'Perun Framework'
copyright = u'2020, Perun Framework Contributors'
matthiasgeihs marked this conversation as resolved.
Show resolved Hide resolved
author = u'Perun Framework Contributors'
matthiasgeihs marked this conversation as resolved.
Show resolved Hide resolved

# The short X.Y version
version = u'master'
Expand All @@ -41,7 +41,6 @@
extensions = [
'recommonmark',
'sphinx.ext.ifconfig',
'sphinx.ext.autosectionlabel',
'sphinx.ext.githubpages',
'sphinx.ext.todo'
]
Expand All @@ -68,7 +67,7 @@
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
exclude_patterns = ["perun-examples/*"]

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
Expand Down Expand Up @@ -176,3 +175,8 @@
'build_url': os.getenv('CIRCLE_BUILD_URL', ''),
'commit': os.getenv('GIT_COMMIT', '')[:7]
}

# Fix for linking to Github anchor link
linkcheck_ignore = [
'https://github.com/trufflesuite/ganache-cli#'
]
48 changes: 48 additions & 0 deletions source/go-perun/index.rst
@@ -0,0 +1,48 @@
Go-Perun
matthiasgeihs marked this conversation as resolved.
Show resolved Hide resolved
========

manoranjith marked this conversation as resolved.
Show resolved Hide resolved
`go-perun <https://github.com/hyperledger-labs/go-perun>`_ is a Go implementation of the Perun state channel protocols.

Developer Tutorial
------------------

The :ref:`developer-tutorial` shows how go-perun is used to build a simple scalable payment application on top of the Ethereum blockchain.

.. toctree::
:maxdepth: 2

tutorial/index

Feedback
--------

Feel free to send your feedback to `info@perun.network <mailto:info@perun.network>`_.

Additional Resources
--------------------

* `Perun Network Website <https://perun.network>`_
* `Perun CLI Demo <https://github.com/perun-network/perun-eth-demo>`_
* `Perun Node <https://github.com/hyperledger-labs/perun-node>`_

Security Disclaimer
-------------------

go-perun is still alpha software.
It should not be used in production.
The purpose of the `current release <https://github.com/hyperledger-labs/go-perun/releases>`_ is to give potential users a general impression and invite feedback.
The authors take no responsibility for any loss of digital assets or other damage caused by the use of this software.
**Do not use this software with real funds**.

Project Funding
---------------

We thank the German Federal Ministry of Education and Research (BMBF) for their funding through the StartUpSecure grants program as well as the German Science Foundation (DFG), the Foundation for Polish Science (FNP) and the Ethereum Foundation for their support in the research that preceded this implementation.

Copyright
---------

Copyright 2021 - PolyCrypt GmbH, Germany.
Use of the source code is governed by the Apache 2.0 license that can be found in the `LICENSE file <https://github.com/hyperledger-labs/go-perun/blob/dev/LICENSE>`_.

Contact us at `info@perun.network <mailto:info@perun.network>`_.
74 changes: 74 additions & 0 deletions source/go-perun/tutorial/channels/closing.rst
@@ -0,0 +1,74 @@
Closing
=======

Closing a channel can be done in two ways, either cooperative or non-cooperative. This example focuses on the cooperative way. As you would expect from closing an off-chain
channel, the on-chain balances will be updated accordingly. But before that can happen
there are some other steps that we will go through first.

.. _the-watcher:

The Watcher
^^^^^^^^^^^

*go-perun* reacts automatically to on-chain events of a channel as long as its `watcher` routine is running. You should start the watcher in the `NewChannel` handler in a new
go-routine since `channel.Watch`_ blocks.

.. _finalizing:

Finalizing
^^^^^^^^^^

The state of a channel in *go-perun* has a public boolean `IsFinal`_ flag.
Final states can directly be closed on-chain without raising a dispute.
This allows for a faster collaborative closing process.
manoranjith marked this conversation as resolved.
Show resolved Hide resolved
As soon as a channel has a final state, we call it *finalized* since it can not
be updated anymore. Have a look again at :ref:`updating` on how to do it.

Registering
^^^^^^^^^^^

Registering a channel means pushing its latest state onto the `Adjudicator`.
A registered channel state is openly visible on the blockchain. This should only be done
when a channel should be closed or disputed.

.. note::

Registering non-finalized channels will raise a dispute.

Settlement
^^^^^^^^^^

Settlement is the last step in the lifetime of a channel. It consists of two steps:
*conclude* and *withdraw*. *go-perun* takes care of both when `channel.Settle`_ is called.

*conclude* waits for any on-chain disputes to be resolved and then calls the `Adjudicator`
to close the channel. After this is done, the channel can be *withdrawn*. This is done only
once by one of the channel participants.

The last step is for each participant to *withdraw* their funds from the `AssetHolder`.
The balance that can be withdrawn is the same as the final balance of the channel.
Ethereum transaction fees still apply.

.. warning::

Trying to settle a channel that was not registered before is not advised and
can result in a dispute.

Keep in mind that we already *finalized* the channel in the update that we sent.
We therefore just need to *register* and *settle* which looks like this:

.. literalinclude:: ../../../perun-examples/simple-client/node.go
:language: go
:lines: 139-156

The other participant would then have its `AdjudicatorEvent` handler called with a
`ConcludedEvent`_ and should then also execute `closeChannel`.

.. literalinclude:: ../../../perun-examples/simple-client/node.go
:language: go
:lines: 158-164

.. _IsFinal: https://pkg.go.dev/perun.network/go-perun/channel#State
.. _channel.Settle: https://pkg.go.dev/perun.network/go-perun/client#Channel.Settle
.. _channel.Watch: https://pkg.go.dev/perun.network/go-perun/client#Channel.Watch
.. _ConcludedEvent: https://pkg.go.dev/perun.network/go-perun/channel#ConcludedEvent
23 changes: 23 additions & 0 deletions source/go-perun/tutorial/channels/disputes.rst
@@ -0,0 +1,23 @@
.. _disputes :

Disputes
matthiasgeihs marked this conversation as resolved.
Show resolved Hide resolved
========

A *dispute* occurs when the channel participants cannot agree on the current state.
Say for example *Bob* is sure that he has 5 *ETH* but *Alice* insists that he has only 4 *ETH*.

Disputes are resolved on-chain.
The Perun protocols guarantee that the most recent state agreed to by all channel participants can be redeemed.
Disputes are handled by the `Adjudicator` contract which determines the valid state by comparing the version numbers of the provided channel states.

A dispute is raised as soon as one participant registers a non-final state in the
`Adjudicator`. The other participant then has `challengeDuration`-seconds time to react by submitting a newer state to prove that he is honest and knows a newer valid state.
If the other participant cannot do this, he loses the dispute and the first state is
accepted as final. The disputed channel is then *settled* and therefore closed.

.. note::

The `challengeDuration` is part of the `channel proposal`_ and is agreed upon by
both participants.

.. _channel proposal: https://pkg.go.dev/perun.network/go-perun/client#NewLedgerChannelProposal
14 changes: 14 additions & 0 deletions source/go-perun/tutorial/channels/index.rst
@@ -0,0 +1,14 @@
Channels
========

With all the components explained, we can now look at channels.
The following pages will explain how to open, update and close a channel.
Disputes will only be outlined as they are not focused on in this tutorial.

.. toctree::
:maxdepth: 1

opening
updating
closing
disputes
51 changes: 51 additions & 0 deletions source/go-perun/tutorial/channels/opening.rst
@@ -0,0 +1,51 @@
Opening
=======

Opening a state channel works by defining the initial asset allocation, setting the
channel parameters, creating a proposal and sending that proposal to all participants.
The channel is open after all participants accept the proposal and finish the on-chain funding.

It looks like this:

.. literalinclude:: ../../../perun-examples/simple-client/node.go
:language: go
:lines: 48-78

The `ProposeChannel` call blocks until *Alice* either accepted or rejected the channel
and funded it.

.. warning::

The channel that is returned by `ProposeChannel` should only be used to retrieve
its *id*.

HandleProposal
^^^^^^^^^^^^^^

An example Proposal handler looks like this:

.. literalinclude:: ../../../perun-examples/simple-client/node.go
:language: go
:lines: 80-99

You can add additional check logic here but in our simple use case we always accept
incoming proposals. After the channel is open, both participants will have their `NewChannel` callback called.

.. warning:: The `Channel` that `ProposalResponder.Accept`_ returns should only be used to retrieve its *ID*.

NewChannel
^^^^^^^^^^

*go-perun* expects this handler to finish quickly. Use *go* routines if you want to do
time-intensive tasks. You should also start the :ref:`watcher <the-watcher>` as shown below:

.. literalinclude:: ../../../perun-examples/simple-client/node.go
:language: go
:lines: 101-110

.. note::

Starting the watcher is not mandatory but strongly advised. *go-perun* can otherwise
not react to malicious behavior of other participants.

.. _ProposalResponder.Accept: https://pkg.go.dev/perun.network/go-perun/client#ProposalResponder.Accept
40 changes: 40 additions & 0 deletions source/go-perun/tutorial/channels/updating.rst
@@ -0,0 +1,40 @@
.. _updating:

Updating
========

We now give the `node` an `updateChannel` function to update the channel by sending Ether from
*Bob* to *Alice*.

.. literalinclude:: ../../../perun-examples/simple-client/node.go
:language: go
:lines: 111-124
:emphasize-lines: 8,9

In the highlighted lines you can see that we use index `0` for the `Balances` slice.
This means that we access the funds of the first asset. Since there is only one asset,
this is the only entry. We also :ref:`finalize <finalizing>` the channel, which will be important later and implies that it can not be updated again.

.. note::

*go-perun* checks that an update preserves the sum of each asset.

HandleUpdate
^^^^^^^^^^^^

The update that was initiated with the `updateChannel` function above would then arrive
at the `HandleUpdate` function of the other participant. In `HandleUpdate` you can decide on whether you want to accept the incoming update or not.
This example function accepts all updates:

.. literalinclude:: ../../../perun-examples/simple-client/node.go
:language: go
:lines: 126-133

An update can also be rejected with a reason. This starts the :ref:`dispute process <disputes>`.

.. code-block:: go

responder.Reject(ctx, "do not like")

.. _UpdateBy: https://pkg.go.dev/perun.network/go-perun/client#Channel.UpdateBy
.. _Update: https://pkg.go.dev/perun.network/go-perun/client#Channel.Update