Raiden Network 3.0.1 Documentation
Note
This is the documentation for the 3.0.1 version of the Raiden Network. You can find the source code in our Github Repository.
What is the Raiden Network?
The Raiden Network is an off-chain scaling solution, enabling fast, low-fee and scalable token transfers. It’s complementary to the Ethereum blockchain and works with any ERC20 compatible token.
New to Raiden?
If you’re new to Raiden and just want to install it and try it out, go to the Quick Start. Afterwards you can do token transfers using the Raiden WebUI.
For a more advanced usage, read about the different options for installing and firing up a Raiden client.
Developing on Raiden?
If you want to use Raiden for your project the following links have relevant documentation:
Check out the examples on the developer portal
Read a detailed guide on how to get started using the Raiden API
Read the complete documentation of the Raiden API
Contributing to Raiden?
If you are looking to get an in-depth understanding of Raiden or if you’re interested in contributing to Raiden, a good start is to:
Read the on-boarding guide
Read the Raiden specification.
Take a look at the source code
Read the “tech deep dive” series on our blog
Need help?
If you run into problems or discover bugs, you can:
Ask for help in the Raiden gitter chat
Create a Github issue for either a bug report or feature request
Disclaimer
Please note, that even though we do our best to ensure the quality and accuracy of the information provided, this publication may contain views and opinions, errors and omissions for which the content creator(s) and any represented organization cannot be held liable. The wording and concepts regarding financial terminology (e.g. “payments”, “checks”, “currency”, “transfer” [of value]) are exclusively used in an exemplary way to describe technological principles and do not necessarily conform to the real world or legal equivalents of these terms and concepts.
Contents
System Requirements and Installation Guide
Installation
To install Raiden you can either:
Below we will give details on how to use the self-contained application bundles on different platforms, as well as the other installation methods.
Installation via Raiden Wizard
If you are new to Raiden or just want to use it without caring too much for the technical details, we recommend the Raiden Wizard to get started. It will help you to install Raiden and to acquire all necessary tokens for running it on the Ethereum mainnet.
Overview
This quick start section will help you install Raiden and run a Raiden node on the Ethereum mainnet using the Raiden Wizard. We will walk through the steps to:
Note
If you want to try out Raiden on a testnet before running it on mainnet, the Quick start on Görli page will help you.
Prerequisites
In order to use the Raiden Wizard and Raiden you’ll need:
Get MetaMask (optional)
Instead of using MetaMask you can buy ETH directly in the Raiden Wizard via fiat money.
MetaMask is an in-browser Ethereum wallet. It allows us to send and sign transactions on the Ethereum blockchain.
To install MetaMask:
Visit the MetaMask website.
Follow the instructions to add MetaMask as a browser extension.
Restart your browser. You should now see the MetaMask icon in the top right corner of your browser.
With the newly installed MetaMask extension click the icon in your browser. This will open up MetaMask with a setup guide for creating a new account (wallet).
After following the instructions you should see a screen with information about your newly created Ethereum account.
Get an Infura ID
Note
Why do I need Infura?
The Raiden Wizard aims to make installing Raiden as easy as possible. By using Infura you don’t have to worry about layer 1, that is running your own synced Ethereum node. You can simply access all testnets and the Ethereum mainnet through the API endpoints provided by Infura.
To get an Infura project ID:
Visit infura.io and sign up for a new account.
Create a new project.
View your project and you’ll find the project ID under the KEYS tab.
Download and run the Raiden Wizard
Warning
You need an internet connection to run the Raiden Wizard. The Wizard will launch in your default browser.
The setup process can take up to five minutes, make sure not to close the browser.
Extract and click the
raiden_wizard
program to run the installer.Your web browser should open a new window with the Raiden Wizard. If not, you can manually type http://localhost:1994 to access the Wizard.
The installation steps of the Raiden Wizard will let you:
Create a new Ethereum Account (the “Raiden Account”) specifically for using with the Wizard.
Fund this new Raiden Account with ETH, either from your MetaMask account or by buying ETH via fiat money.
Acquire
RDN
tokens for using the pathfinding and monitoring services.Acquire
DAI
tokens for making payments in the Raiden Network.
When you have finished the steps of the Wizard, you can LAUNCH
Raiden and start interacting with the Raiden
Webinterface.
Handle Limitations
The Raiden Wizard will display an Internal Server Error if an invalid project ID is provided. To solve this you have to manually delete the configuration file that got created.
The Wizard does not provide a way of shutting down the Raiden node. You have to cancel the process to stop Raiden.
MacOS: Use the activity monitor for cancelling Raiden.
Linux: Use any Linux process manager for stopping Raiden.
You might want to delete configuration files if the wizard is taking a long time to start or if an invalid project ID has been provided and the wizard won’t start at all.
Navigate to the following folder:
MacOS: /Users/<username>/.local/share/raiden/
Linux: /home/<username>/.local/share/raiden/
Delete desired .toml file/files.
Need help?
If you run into problems or discover bugs, you can:
Ask for help in the Raiden gitter chat
Create a GitHub issue for either a bug report or feature request
If you want to try out Raiden with test tokens on a testnet before running it on mainnet, you can use the Görli Wizard for installing Raiden and receiving tokens:
Quick Start on Görli Testnet
You might want to try out Raiden on a testnet before using it on mainnet or might need a development environment. For this reasons we provide a stable demo environment on Görli. The quickest way to get a Raiden node set up on this environment is to use the Raiden Wizard for Görli. This page will guide you through the process.
In order to use the Raiden Wizard and Raiden you’ll need:
A computer running Linux or macOS.
An Infura ID. Click here to get one.
Extract and run the
raiden_wizard
program.Your web browser should open a new window with the Raiden Wizard. If not, you can manually type http://localhost:2640 to access the Wizard.
The Raiden Wizard will do the following for you:
Create a new Ethereum Account (the “Raiden Account”) specifically for using with the Wizard.
Fund this new Raiden Account with ETH from a faucet.
Mint
SVT
tokens for using the pathfinding and monitoring services.Mint
WIZ
tokens for making payments in the Raiden Network.Launch your Raiden node.
Note
Note that the Görli Wizard uses test tokens, so don’t be confused by the RDN and DAI symbols.
After the completion of the Wizard you will get redirected to the web interface of your Raiden node. See this page for a guide to the interface.
You can try to do your first payment by opening a channel with the
Raiden Hub
0x1F916ab5cf1B30B22f24Ebf435f53Ee665344Acf
and sending some WIZ
tokens to it. The payment should show up on the hub’s
webpage.
After you have shut down your Raiden node, the Raiden Wizard can be used as a launcher for your node. When you start the Wizard, it will recognise that you already created a configuration for your node and show a “Launch” button.
Installation from GitHub
Linux
Download the latest raiden-<version>-linux-x86_64.tar.gz
, and extract it:
tar -xvzf raiden-<version>-linux-x86_64.tar.gz
The Raiden binary should work on most 64bit GNU/Linux distributions without any specific system dependencies, other
than an Ethereum client installed in your system (see below). The Raiden binary takes the same command line
arguments as the raiden
script.
macOS
Download the latest raiden-<version>-macOS-x86_64.zip
, and extract it:
unzip raiden-<version>-macOS-x86_64.zip
The resulting binary will work on any version of macOS from 10.12 onwards without any other dependencies.
Or you can use Homebrew to install the most up to date binary:
brew tap raiden-network/raiden
brew install raiden
An Ethereum client is required in both cases. The Raiden binary takes the same command line
arguments as the raiden
script.
Raiden is also available as a PyPi package and can be installed with :ref:pip <installation_pip>
.
Raspberry Pi
Currently we don’t provide any pre-built executables for the Raspberry Pi. You can still install
Raiden from a PyPi package with :ref:pip <installation_pip>
.
This process will work on any Raspberry Pi from Model 2B onwards without any other dependencies. Please be patient for the installation process, since there might not be pre-built wheels available for most dependencies.
An Ethereum client is required to run Raiden.
Installation using pip
To get the latest available stable version via pip
:
pip install raiden
If you’d like to give the pre-releases a spin, use pip’s --pre
flag:
pip install --pre raiden
Installation via Docker
There are two options to run a raiden docker image:
Create the Image yourself and use our Dockerfile as template or use the already built image from Dockerhub:
docker run -it raidennetwork/raiden:latest
The required keystore can easily be mounted in the docker container:
docker run -it --mount src=/PATH/TO/LOCAL/KEYSTORE,target=/keystore,type=bind raidennetwork/raiden:latest --keystore-path /keystore
Other flags such as the JSON-RPC endpoint to an Ethereum node can easily be chained to the command.
Dependencies
You will need a local or remote Ethereum node to connect Raiden to.
Check this link to install the Geth client.
Download and install OpenEthereum from here.
Or sign up at a service like Infura to set up a remote node.
Now you are ready to get started.
For developers
If you plan to develop on the Raiden source code, or the binary distributions do not work for your system, you can follow these steps to install a development version.
Linux
You will also need to obtain the system dependencies for pyethapp.
Clone the repository:
git clone https://github.com/raiden-network/raiden.git
Navigate to the directory:
cd raiden
It’s strongly advised to create a virtualenv for Raiden (requires python3.8) and install all python dependencies there.
After you have done that you can proceed to install the dependencies:
make install-dev
You will also need to connect your Ethereum client to the Ropsten testnet. See below for guidelines on how to connect with both OpenEthereum and Geth.
macOS
Please refer to the detailed step-by-step guide for setting up a macOS development environment.
nix
Please refer to the nix setup guide for setting up a development environment using the nix package manager.
Run it
- To fire up Raiden you need at least
a synced Ethereum Node - using Geth, OpenEthereum or Infura
an Ethereum keystore file - whereas the address holds ETH, RDN, and the ERC20 token you want to transfer
If you want to use Raiden services that charge a fee, a deposit of RDN tokens to pay the services with.
More about the Raiden services (pathfinding and monitoring service) will be explained below. On the testnets there are also free services available, and on any network it is possible (though not recommended) to use Raiden without Raiden services.
We will provide you with the necessary cli arguments step by step. Full example is at the end of each section.
1. and 2. The synced Ethereum Node & Keystore
Using Geth
Run the Ethereum client and let it sync:
geth --syncmode fast --rpc --rpcapi eth,net,web3
Note
When you want to use a testnet add one of the --testnet
, --rinkeby
or --goerli
flags or set the network id with --network-id
directly.
Unless you already have an account you can also create one in the console by invoking personal.newAccount()
.
If problems arise for above method, please see the Ropsten README for further instructions.
Then launch Raiden with the default testnet keystore path:
raiden --keystore-path ~/.ethereum/testnet/keystore
Using OpenEthereum
Run the client and let it sync:
openethereum --no-warp --jsonrpc-apis=web3,eth,net,parity
Note
When you want to use a testnet add the --chain ropsten
or --chain kovan
flags or set the network id with --network-id
directly.
Attention
OpenEthereum sometimes loses its historical DB (potentially after updates). Due to this some events might be lost which will result in Raiden not being able to fetch all events. Therefore it is recommended to make sure to have OpenEthereum fully synced with the --no-warp
option.
After syncing the chain, an existing Ethereum account can be used or a new one can be generated using ethkey. After account creation, launch Raiden with the path of your keystore supplied:
raiden --keystore-path ~/.local/share/openethereum/keys/ethereum
Using Infura
Sign up with Infura to get an API token. After that you can start using Raiden directly:
raiden --keystore-path ~/.ethereum/keystore --eth-rpc-endpoint "https://<network>.infura.io/v3/<yourToken>"
Where <network>
can be mainnet, ropsten, etc.
Select the desired Ethereum account when prompted, and type in the account’s password.
Optional CLI arguments
There are further CLI arguments with which you can control, among other things
The choice of a pathfinding service
The choice of a monitoring service
Logging
In doubt, you can use the following to see all possible CLI arguments:
raiden --help
1. Pathfinding service
A pathfinding service is a third party service helping your node with efficient transfer routing. It is usually paid in RDN tokens.
Direct channels to other nodes can be used without asking the PFS for a route.
If you want to stop broadcasting information about your channel states to
PFSes, use --routing-mode private
. As a result, PFSes won’t create routes
that include your node as a mediator.
If you want to use a particular pathfinding service, you can
do so with --pathfinding-service-address <url>
. Otherwise Raiden will automatically pick one of the pathfinding
services from the registry.
The default setting for the pathfinding options is to use a pathfinding service and choose it automatically
(--routing-mode pfs --pathfinding-service-address auto
).
2. Monitoring service
A monitoring service watches a client’s open channels while it is offline, and represents the client in case of settlement.
Like the pathfinding service, it is paid in RDN tokens. If you want to use a monitoring service, use the option
--enable-monitoring
and Raiden will automatically pick one from its service registry.
By default the monitoring services are disabled.
Enabling monitoring of channels will require a default reward value of 5 RDN for successfully monitoring your channel.
3. Logging configuration
By default raiden keeps a “debug” log file so that people who have not configured logging but are facing problems can still provide us with some logs to debug their problems.
For expert users of raiden who want to configure proper logging we recommend disabling the debug log file and configuring normal logging appropriately.
To disable the log file the --disable-debug-logfile
argument should be passed.
To specify the logging level add: --log-config ":debug"
if you want all debug statements to be logged. The logging level can actually be configured down to the module level through this argument.
To provide the filename for the logs use --log-file XXX
where XXX
is the full path and filename to the log you want to create or append to. Note that Raiden uses a python WatchedFileHandler for this log. That means that if you or your system moves the logfile (for example due to log rotation) then Raiden will detect that and close and reopen the log file handler with the same name.
Finally by default the output of the logs are in plain readable text format. In order to make them machine readable and parsable json add the --log-json
argument.
Summing up these are the arguments you need to append if you want to disable the debug log and want to configure normal logging for up to debug statement in json inside a file called raiden.log
--disable-debug-logfile --log-config ":debug" --log-file raiden.log --log-json
Getting Started
Now that your Raiden node is up and running, you can choose from the following tutorials, depending on your Raiden use case:
See Using Raiden on Mainnet for getting started to use Raiden on the Ethereum mainnet. The Raiden Web Interface is the easiest way to use Raiden interactively. For programmatic use of Raiden, see The Raiden API Tutorial.
Using Raiden on Mainnet
Warning
Before you start, make sure Raiden is correctly installed and configured by following the installation instructions.
Also make sure you have read and understood the safe usage guidelines before starting to use Raiden.
Get Whitelisted Tokens
The Raiden Coruscant release puts a certain limit on the amount of tokens that can be deposited into a channel. This is to minimize potential loss of funds in case of bugs.
The global limit per token network is approximately $5000000.
The limit per channel side is approximately $5000.
Note
These dollar values of these limits are calculated at contract deployment time and vary with the exchange rates of the underlying tokens.
W-ETH
W-ETH stands for Wrapped Ether and is essentially Ether that has been packaged to become ERC-20 compatible.
There are several ways in which you can get W-ETH from your Ether.
Deposit Tokens to the UDC
To do mediated transfers we need to have RDN (Raiden Network Tokens) in the UDC (User Deposit Contract) for paying the monitoring and pathfinding services. This section will describe how to add Raiden Network Tokens to the UDC by making a call to the User Deposit endpoint of the Raiden API. The following POST request will deposit 100 RDN tokens to the UDC:
curl -i -X POST \
http://localhost:5001/api/v1/user_deposit \
-H 'Content-Type: application/json' \
--data-raw '{"total_deposit": "100000000000000000000"}'
Note
Raiden utilizes a RESTful API where all URL paths starts with /api/
followed by a version number. The current API version is 1
and therefore all requests begins with /api/v1/
.
The request will take a couple of minutes, because two on-chain transactions are performed: Approving the UDC to use RDN and Depositing RDN to the UDC. When successfully completed the API will respond with a transaction hash.
Open a Channel
Opening a channel and depositing tokens in it allows you to transfer these tokens to your channel partner - and indirectly to other nodes connected to you partner. To open a channel, a PUT request is made to the channels endpoint that includes a JSON object containing:
The address of the node you’d like to open the channel with. If you don’t know to which partner you should connect, have a look at Find suitable partner nodes.
The token address. We use W-ETH token in this example.
The amount of tokens you want to deposit in the channel (Remember that it is always possible to deposit more tokens later). 1 W-ETH is equivalent to 10^18 WEI.
The settle timeout period which corresponds to the number of blocks that have to be mined before a closed channel can be settled.
curl -i -X PUT \
http://localhost:5001/api/v1/channels \
-H 'Content-Type: application/json' \
--data-raw '{"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "total_deposit": "1337", "settle_timeout": "500"}'
This will create a new channel and a successful request will return you the following response object:
HTTP/1.1 201 CREATED
Content-Type: application/json
{
"token_network_address": "0x3C158a20b47d9613DDb9409099Be186fC272421a",
"channel_identifier": "99",
"network_state": "unknown",
"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9",
"token_address": "0x9aBa529db3FF2D8409A1da4C9eB148879b046700",
"balance": "1337",
"total_deposit": "1337",
"total_withdraw": "0",
"state": "opened",
"settle_timeout": "500",
"reveal_timeout": "50"
}
As you can tell by the response object a channel identifier has been generated. This means that there now is a channel with that identifier inside the token network.
We’re now ready to start sending W-ETH tokens!
Make a Payment
Payments are made from the payments endpoint via a POST request that has to include:
The address of the W-ETH token as a path parameter.
The address of the node receiving your payment as a path parameter.
The amount you would like to pay as a body parameter.
curl -i -X POST \
http://localhost:5001/api/v1/payments/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/<target_address> \
-H 'Content-Type: application/json' \
--data-raw '{"amount":"42"}'
You will receive a success response once the payment goes through.
Payments in Raiden can be done either as:
Direct payments
Mediated payments
Note
It is possible to receive tokens through the Raiden Network without having any initial Ether or tokens. The receiving peer just needs to have a Raiden full node running and the sender must be willing to pay the fees for the on-chain transactions.
Direct payments
You can open a channel directly with any node you know the address of. You might want to open a direct channel if you know you’ll be making frequent payments to a specific peer. Each payment will then go straight to that peer via the open channel. This is called a direct payment.
Mediated payments
If you don’t have a direct channel to a node for whom you want to send a payment, Raiden will try to find a path from you to the recipient node through the network of channels. This is called mediated payments.
Mediated payments are a powerful feature in Raiden since it lets you pay anyone in the network by leverging the path of connected payment channels.
By making no more than two API calls - one call to join the token network and one call to make the payment - we can send payments to anyone who is part of the W-ETH token network.
Deposit Tokens
You deposit in a channel by making a PATCH request to the channels endpoint that includes:
The address of the W-ETH token as a path parameter.
The address of the partner node as a path parameter.
The amount of tokens you want to deposit in the channel as a body parameter.
curl -i -X PATCH \
http://localhost:5001/api/v1/channels/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/<partner_address> \
-H 'Content-Type: application/json' \
--data-raw '{"total_deposit":"4000"}'
Note
Notice how we are specifying the total_deposit
in the request and not only the amount we want to “top-up” with. This means that if we initially deposited 2000 WEI and want to increase the amount with 2000 we would need to make a total deposit of 4000 WEI.
This is done to prevent requests that are sent repeatedly (by accident or as part of an attack) from having any further consequences.
View Channel Status
To view the status of a channel you have to make a GET request to the channels endpoint and provide:
The address of the W-ETH token as a path parameter.
The address of the partner node as a path parameter.
curl -i \
http://localhost:5001/api/v1/channels/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C
This will return the following response object:
HTTP/1.1 201 CREATED
Content-Type: application/json
{
"token_network_address": "0xE5637F0103794C7e05469A9964E4563089a5E6f2",
"channel_identifier": "0xa24f51685de3effe829f7c2e94b9db8e9e1b17b137da5",
"network_state": "unknown",
"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9",
"token_address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"balance": "3958",
"state": "open",
"settle_timeout": "500",
"reveal_timeout": "50"
}
As you can tell by the response, the current balance in the channel is
3958
which matches the two deposits and one payment you’ve just made
(2000
+ 2000
- 42
= 3958
).
Mediation Fees
What are Mediation Fees?
Raiden lets users pay anyone in the network by using a path of connected payment channels to mediate the payment. Mediating nodes, which are the nodes between the initiator and target on the selected payment path, can earn mediation fees.
Mediation fees are paid by the initiator by slightly increasing the amount of tokens above the amount intended for the target. This also means that mediation fees are always paid in tokens of the kind that is being transferred.
Benefits of Mediation Fees
Mediation fees increase the health of the payment network by:
incentivizing users to run mediating nodes
choosing lower fees for routes that balance the involved payment channels
A healthy payment network allows cheap and reliable payments for users. So even though users have to pay mediation fees when initiating payments, these fees are ultimately to their own benefit.
Calculation of Mediation Fees
Each mediator can choose a fee schedule for mediating payments. This fee schedule consists of three parts:
a flat fee per mediation
a fee proportional to the mediated amount of tokens
an imbalance fee that increases when the payment exhausts channel capacity, which might prevent the channel from being used in future payments
The sum of these fee components represents the fee for a single mediator. Summing the fees for all mediators in the payment route yields the total amount of mediation fees for a payment.
Since the fees can change between the time of fee calculation by the initiator (or the pathfinding service on his behalf) and the time of mediation, a safety margin is added on top of the mediation fee. Without this, a mediator might drop the payment because its imbalance fee has increased due to another payment taking place within this time span.
For more details on the calculation of fees, see the blog post and the architecture decision record.
Default Fee Schedule
You don’t need to configure the fee schedule yourself if you don’t want to, since Raiden comes with a default fee schedule. The default values are
flat fee
DAI: 10^-6 DAI
W-ETH: 10^-8 W-ETH
proportional: 0.4% of the mediated tokens
imbalance: up to 0.3% of the mediated tokens (usually much less)
and apply to all transferred tokens, unless specified differently by the user.
Changing Your Fee Schedule
As with all Raiden settings, you can get a short summary of the
available options by running raiden --help
:
$ raiden --help
...
Mediation Fee Options:
--flat-fee <ADDRESS INTEGER RANGE>...
Sets the flat fee required for every mediation in wei of the mediated token
for a certain token address. Must be bigger or equal to 0.
--proportional-fee <ADDRESS INTEGER RANGE>...
Mediation fee as ratio of mediated amount in parts-per-million (10^-6) for a
certain token address. Must be in [0, 1000000].
--proportional-imbalance-fee <ADDRESS INTEGER RANGE>...
Set the worst-case imbalance fee relative to the channels capacity in
parts-per-million (10^-6) for a certain token address. Must be in [0, 50000].
--cap-mediation-fees / --no-cap-mediation-fees
Cap the mediation fees to never get negative. [default: True]
The first three parameters each set one of the three fee components. Each parameter takes two values: a token address and a fee value. When mediating a payment for the given token, the corresponding fee value will be used. Here are some examples of fee parameters that could be used for the DAI token:
--flat-fee 0x6B175474E89094C44Da98b954EedeAC495271d0F 1000000000000000
Ask for 1000000000000000/10^18 = 0.001 DAI per mediation
--proportional-fee 0x6B175474E89094C44Da98b954EedeAC495271d0F 1000
Ask for 1000/10^6 = 0.1% of the mediated tokens
--proportional-imbalance-fee 0x6B175474E89094C44Da98b954EedeAC495271d0F 10000
Apply up to 10000/10^6 = 1% of the mediated tokens as imbalance fee. This fee will be positive when increasing imbalance and negative when decreasing imbalance. It will usually stay far below this maximum value, because the maximum applies only when the channel goes from perfectly balanced to completely imbalanced due to a single payment.
Since imbalance fees can be negative to incentivize payments that
balance your channels, the sum of all three mediation fee components
could go negative, too. This can make sense, but it is counter-intuitive
for the mediating user and it might open up certain classes of attacks
against mediators. For these reasons, the total mediation fee per
mediator is capped to not go below zero by default. If you want to allow
the fee total to be negative, use the --no-cap-mediation-fees
flag.
Frequently Asked Questions
As noted in the “Calculation of Mediation Fees” section above, a small safety margin is added on top of the mediation fees when initiating a payment. This safety margin is only used by the mediators when the channel balances change to the initiator’s disadvantage immediately before initiating the payment. So usually this margin is not or only partially used up before reaching the payment target. The remainder reaches the target along with the intended payment amount itself, thereby slightly increasing the amount received by the target.
Currently the Raiden client cancels payments that would require more than 20% of the transferred amount in fee costs. This is the maximum fee limit. As noted in “Default Fee Schedule”, there are fees for both the DAI and W-ETH token networks by default.
This means that the transferred amount has to be big enough, so that the fees do not surpass 20% of the transferred amount. This results in the following minimum amounts for the token networks when mediation is used:
DAI: Min. 0.00001 DAI (10^-5)
W-ETH: Min 0.0000001 W-ETH (10^-7)
As direct payments do not need mediation fees, this does not apply for direct transfers.
Raiden Web Interface Tutorial
The Raiden web interface (WebUI) helps you to interact with your Raiden node and aims to inspire to create own applications that utilize the Raiden REST API endpoints.
Run the Raiden web application
To run the WebUI you need to install Raiden and set up a Raiden node. The easiest way to do so is by using the quick start guide.
Once you have a Raiden node up and running the WebUI will be available on http://localhost:5001.
Manage UDC funds
On the top bar you can click the button next to the “UDC Deposit” to open a dialog for managing your funds in the User Deposit Contract. This dialog allows you to perform deposits and withdrawals. It will show you the amount of Raiden Network Tokens (RDN) you have on-chain, which are necessary for deposits.
For a deposit, click the “Deposit” button and enter the amount of RDN tokens you would like to have in the UDC. This will trigger all necessary on-chain transactions.
For a withdrawal, you first need to click “Plan Withdrawal”. After entering the amount of tokens you would like to withdraw, you have to wait for at least 100 blocks on-chain before you can perform the actual withdrawal. When these 100 blocks have passed, a “Withdraw” button will show up. Clicking it will trigger another on-chain transaction.
Note
What is the User Deposit Contract (UDC)?
The UDC is a smart contract where you deposit RDN (Raiden Network Tokens) for later paying the Raiden Services. For sending a mediated transfer it is even necessary to have RDN tokens in the UDC.
Join a Token Network
To make payments in Raiden you first need to join the network by opening channels for the token you want to make payments with. You can join a token network by either:
Note
What is a token?
Each token complies to its own ERC20 smart contract which has a total supply of tokens.
These token contracts are like a registry where different amounts of the total supply is mapped to different owners.
Note
What is a token network?
Anyone running a Raiden node and owns a token can join a network with other nodes who own the very same token.
All nodes registered within such network form a token network.
Quick Connect
Quick Connect lets you automatically open channels to nodes recommended by a Path Finding Service.
If you click the “Transfer” button without having any open channels for the selected token you will get prompted to use Quick Connect. Alternatively you can click the three dots on the top right of a token network view and choose “Quick Connect”.
When using Quick Connect:
Enter the total number of tokens you want to allocate
Distribute the token amount between the recommended partner nodes. Only if a deposit is selected for a node, a channel will be opened.
The amount you choose when connecting is what will be available for making payments. You can always add more funds by depositing to a channel.
Warning
Quick Connect is an on-chain activity that will consume some of your ETH. Opening fewer channels will reduce the gas cost proportionally.
You are now ready to make your first payment!
Registering a new token
Warning
Registering a new token is only relevant on the testnets. The tokens allowed on mainnet for the Coruscant release are DAI and W-ETH.
If you want to join the network for a token and that token is not displayed in the list of tokens it might mean that it has not been registered.
To register a token yourself:
Click “Select network” in the tokens view.
Click “Add new network”.
Enter the address of the token you’d like to register and click “Register”.
You can follow the steps for Quick Connect to join the network of your newly registered token.
Make a Payment
Payment channels allow for Raiden transfers to be made without the need to involve the actual blockchain. If you have one or more channels open you can start making payments. If you used Quick Connect three channels were automatically opened with three nodes.
Let’s walk through how to make a transfer.
Transfer
After selecting a token network with open channels. Click on the “Transfer” button, this will bring open the transfer dialog.
If you accessed the transfer dialog from the all networks view, you can select the token network you want to make payments in also here.
Enter the receiving address.
Enter the amount.
Click “Send” to complete the transfer.
Note
Minting tokens
When running Raiden on a testnet the WebUI lets you mint tokens to fund your account with additional tokens.
To mint tokens, click the three dots on the top right of the token network view and choose “Mint”.
Minting tokens is an on-chain transaction that will consume some of your ETH.
Note
How do payment channels work?
Payment channels enable parties to exchange tokens off-chain without involving the blockchain for every transaction.
This helps to avoid the blockchain consensus bottleneck and makes transfers both faster and cheaper.
Raiden lets users pay anyone in the network by using a path of connected payment channels to mediate payments. This means that a user don’t need to open channels with every node they want to send payments to.
A payment channel in Raiden is always backed by an on-chain deposit of tokens. Depositing tokens or opening payment channels are on-chain transactions which require transaction fees (gas) that are paid in ETH.
Add More Tokens
At some point, you might need to top up your channels with tokens to be able to send more payments. You can allocate more tokens by depositing to a channel.
Deposit to a channel
Depositing tokens to a specific channel lets you allocate more funds to that channel. You can compare this to “topping up” a prepaid card.
In the “Channels” screen:
Click the three dots on the channel where you want to make the deposit and choose “Deposit”.
Enter an amount.
Click “Deposit”.
The amount you choose will be subtracted from your on-chain token balance and added to the channel balance.
Settle Payments and Close Channels
To get your tokens back on-chain you need to either withdraw them from a channel or close and settle the channel. You have a couple of ways for getting your tokens back on-chain:
Withdraw tokens
In the “Channels” screen:
Click the three dots on the channel from which you would like to make the withdraw and then the “Withdraw” button.
Enter the amount for your withdraw.
Click “Withdraw”.
The token amount will be added to your on-chain token balance. Your payment channel with the partner will remain open and you can continue exchanging payments (if your balance allows it).
Close a channel
If you don’t plan to use a specific channel anymore you can close it. A closed channel is no longer available for making payments.
In the “Channels” screen:
Click the three dots on the channel you wish to close and then the “Close Channel” button.
Click “Confirm” to finish closing the channel.
As soon as the channel is settled the token amount will be payed out in accordance to the transfers that have been made between the channel participants.
Note
When the channel is closed the settle timeout period will start. The channel is settled once the settle timeout period is over. The tokens can then be used on-chain.
Leave a token network
Leaving a network has the same outcome as closing a channel with the difference that all channels belonging to the network you’re leaving get closed.
In the “Transfers” screen:
Select the token network you wish to leave.
Click the three dots and then the “Leave network” button.
Click “Confirm” to finish leaving the network.
API Tutorial
This tutorial will show you how to use Raiden via the API by walking you through a few API calls. The steps are similar to the WebUI tutorial, but directly use the API endpoints. We will outline the steps necessary for participating in a token network. To see all available endpoints visit the resources part of the documentation.
In the examples throughout this tutorial we will be using a hypothetical
ERC20 token with the address 0x9aBa529db3FF2D8409A1da4C9eB148879b046700
.
Check if Raiden was started correctly
Before we start we’ll make sure that Raiden is running correctly.
This gives us an opportunity to introduce the address endpoint.
curl -i http://localhost:5001/api/v1/address
Your Raiden node is up and running if the response returns the same address as the Ethereum address used for starting Raiden.
You’re now ready to start interacting with the different endpoints and learn how they can be used.
Create a Token Network
Check if the token is registered
Before you can join a token network you need to determine whether the token has been registered and a network for the token has been created.
We can verify this by making a query to the tokens endpoint.
curl -i http://localhost:5001/api/v1/tokens
If the address exists in the list returned by the response you can go ahead and open a channel in that token network.
If the address is not in the list you’ll have to register the token before you can open a channel.
Register a new token
Registering a new token is as simple as calling the tokens endpoint with a PUT request while providing the address of the token you want to register as a path parameter.
curl -i -X PUT http://localhost:5001/api/v1/tokens/0x9aBa529db3FF2D8409A1da4C9eB148879b046700 \
-H 'Content-Type: application/json'
If the call is successful the response will return a new address of the now newly created token network.
HTTP:/1.1 201 CREATED
Content-Type: application/json
{
"token_network_address": "0xC4F8393fb7971E8B299bC1b302F85BfFB3a1275a"
}
Because this token was just registered by you, no one else will be connected to its network and you’ll have to open a channel with another Raiden node.
Note
Payment channels between parties are opened in token networks.
Warning
Registering a new token is currently only relevant on the testnets. The tokens allowed on the mainnet for the Coruscant release are DAI and W-ETH. At some point in future, you will be able to register new token networks for the Ethereum mainnet, too.
Open a Channel
This section will cover the endpoints you would use to:
Find suitable partner nodes
Find suitable partner nodes
To make payments, you need to be connected to the target node either directly, or indirectly by having a channel with a well connected that mediates your payment to the target. If you already know to which node you want to connect, skip ahead to the next section.
The Path Finding Service (PFS) can suggest partners that are highly connected. These nodes will be able to mediate your payments to a large amount of potential targets and are thus a good choice for your first channel(s). Ask the PFS by sending a GET request to its partner suggestion endpoint for the token you want to use.
curl https://pfs.of.your.choice/api/v1/0x9aBa529db3FF2D8409A1da4C9eB148879b046700/suggest_partner
If you don’t know which PFS to ask, you can get the URL of the PFS used by your Raiden node from the settings endpoint. The list of suggested partners is sorted with the most recommended ones coming first. If you want to open just a single channel, picking the address of the first partner in the results is a reasonable choice.
[
{
"address": "0x99eB1aADa98f3c523BE817f5c45Aa6a81B7c734B",
"score": 2906634538666422000,
"centrality": 0.0004132990448199853,
"uptime": 7032.763746,
"capacity": 1000000000000000000
},
{
"address": "0x4Fc53fBa9dFb545B66a0524216c982536012186e",
"score": 2906693668947465000,
"centrality": 0.0004132990448199853,
"uptime": 7032.906815,
"capacity": 1000000000000000000
}
]
Open a channel
To open a channel a PUT request is made to the channels endpoint that includes a JSON object containing:
The address of the node you’d like to open the channel with.
The amount of tokens you want to deposit in the channel. (Remember that it is always possible to deposit more tokens later.)
The settle timeout period which corresponds to the number of blocks that have to be mined before a closed channel can be settled.
curl -i -X PUT \
http://localhost:5001/api/v1/channels \
-H 'Content-Type: application/json' \
--data-raw '{"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0x9aBa529db3FF2D8409A1da4C9eB148879b046700", "total_deposit": "1337", "settle_timeout": "500"}'
This will create a new channel and a successful request will return you the following response object:
HTTP/1.1 201 CREATED
Content-Type: application/json
{
"token_network_address": "0x3C158a20b47d9613DDb9409099Be186fC272421a",
"channel_identifier": "99",
"network_state": "unknown",
"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9",
"token_address": "0x9aBa529db3FF2D8409A1da4C9eB148879b046700",
"balance": "1337",
"total_deposit": "1337",
"total_withdraw": "0",
"state": "opened",
"settle_timeout": "500",
"reveal_timeout": "50"
}
As you can tell by the response object a channel identifier has been generated. This means that there now is a channel with that identifier inside the token network.
You’re now ready to start making payments.
Note
Opening a channel with a partner node is not dependent on whether the partner node holds tokens or not. It will work either way.
Query the state of a channel
Checking the current state of a channel is as easy as making a query to the channels endpoint while providing:
The token address as a path parameter.
The address of the partner node as a path parameter.
curl -i \
http://localhost:5001/api/v1/channels/0x9aBa529db3FF2D8409A1da4C9eB148879b046700/0x61C808D82A3Ac53231750daDc13c777b59310bD9
This will give you the same response object as when opening a channel.
Deposit Tokens
If you opened a channel by yourself you most likely already deposited tokens when sending the request. However, in case someone opened a channel with you, you will not have any tokens at your end of the channel.
You need to make a deposit whenever you want to:
Add tokens to an empty channel
Top up the amount of tokens in a channel
Deposit into a channel
The channel endpoint together with a PATCH request is used for depositing tokens into a channel. When making the call you need to include:
The token address as a path parameter.
The address of the partner node as a path parameter.
The amount of tokens you want to deposit in the channel as a body parameter.
curl -i -X PATCH \
http://localhost:5001/api/v1/channels/0x9aBa529db3FF2D8409A1da4C9eB148879b046700/0x61C808D82A3Ac53231750daDc13c777b59310bD9 \
-H 'Content-Type: application/json' \
--data-raw '{"total_deposit": "7331"}'
This will give you the same response object as when opening a channel or querying the state of a channel.
Now, once there are tokens at your end of the channel, let’s start making payments.
Make a Payment
A powerful feature of Raiden is the ability to let you pay anyone in the network by using a path of connected payment channels to mediate the payment and not only directly connected nodes. These payments are called mediated transfers.
Pay
Payments are made from the payments endpoint via a POST request that needs to include:
The address of the token you want to pay with as a path parameter.
The address of the node receiving your payment as a path parameter.
The amount you would like to pay as a body parameter.
curl -i -X POST \
http://localhost:5001/api/v1/payments/0x9aBa529db3FF2D8409A1da4C9eB148879b046700/0x61C808D82A3Ac53231750daDc13c777b59310bD9 \
-H 'Content-Type: application/json' \
--data-raw '{"amount": "42"}'
Note
You can provide the body parameter with an additional identifier key with a value of your choice. This value can be a number ("identifier": 42
) or the stringified number ("identifier": "42"
).
This is optional and the purpose of the identifier is to give dApps built on Raiden a way to tag payments.
Your payment will most likely succeed if:
The path of channels leading from your node to the node receiving your payment has enough capacity.
All nodes needed to mediate the payment are online.
You have enough tokens in the channel from which you intend to pay out the amount specified in the request body.
To get your tokens out of a channel and back on-chain you either have to withdraw the tokens or close the channel.
View payment history
You can view all transactions you’ve made with a partner node by querying the payments endpoint in a GET request, using the same path parameters as when making a payment.
curl -i \
http://localhost:5001/api/v1/payments/0x9aBa529db3FF2D8409A1da4C9eB148879b046700/0x61C808D82A3Ac53231750daDc13c777b59310bD9
In the response you will be able to see all successful payments, all failed payments and all payments you have received.
Withdraw Tokens
Similar to depositing, a PATCH call to the
channel endpoint is used
for withdrawing with the difference that a value for total_withdraw
is provided in the request body.
So, whenever you’d like to make a withdraw your request needs to include:
The token address as a path parameter.
The address of the node you have the channel with as a path parameter.
The amount of tokens you want to withdraw as a body parameter.
curl -i -X PATCH \
http://localhost:5001/api/v1/channels/0x9aBa529db3FF2D8409A1da4C9eB148879b046700/0x61C808D82A3Ac53231750daDc13c777b59310bD9 \
-H 'Content-Type: application/json' \
--data-raw '{"total_withdraw": "200"}'
In the next section we will take a look at how to withdraw all tokens for a channel and how to leave a token network completely.
Settle Payments and Close Channels
You can choose to either:
Close a specific channel
Leave a token network and close all channels
Close a specific channel
Closing a specific channel is done with a PATCH request to the channels endpoint that includes:
The token address as a path parameter.
The address of the partner node as a path parameter.
The state set to “closed” in the body parameter.
curl -i -X PATCH \
http://localhost:5001/api/v1/channels/0x9aBa529db3FF2D8409A1da4C9eB148879b046700/0x61C808D82A3Ac53231750daDc13c777b59310bD9 \
-H 'Content-Type: application/json' \
--data-raw '{"state": "closed"}'
A successful response will return a normal channel object with the state
set to "closed"
.
HTTP/1.1 200 OK
Content-Type: application/json
{
"token_network_address": "0x3C158a20b47d9613DDb9409099Be186fC272421a",
"channel_identifier": "99",
"network_state": "unknown",
"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9",
"token_address": "0x9aBa529db3FF2D8409A1da4C9eB148879b046700",
"balance": "350",
"total_deposit": "7331",
"total_withdraw": "0",
"state": "closed",
"settle_timeout": "500",
"reveal_timeout": "50"
}
Note
The settle timeout period will start as soon as a channel is closed and the channel is settled once the settle timeout period is over. The state of the channel will then be changed to settled
.
Leave a token network and close all channels
If you wish to leave a token network altogether you can do so by making a DELETE request to the connections endpoint with the token address as a path parameter.
curl -i -X DELETE \
http://localhost:5001/api/v1/connections/0x9aBa529db3FF2D8409A1da4C9eB148879b046700 \
-H 'Content-Type: application/json'
Once done, the response will return a list of channel-state objects of all closed channels.
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"token_network_address": "0x3C158a20b47d9613DDb9409099Be186fC272421a",
"channel_identifier": "99",
"network_state": "unknown",
"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9",
"token_address": "0x9aBa529db3FF2D8409A1da4C9eB148879b046700",
"balance": "350",
"total_deposit": "7331",
"total_withdraw": "0",
"state": "closed",
"settle_timeout": "500",
"reveal_timeout": "50"
}
]
Note
Please note that leaving a token network will take some time since you need to wait for the settle timeout to expire for each channel before a settle can happen.
Raiden’s API Documentation
Introduction
The Raiden API is organized around REST and has resource-oriented URL endpoints that accept and return JSON-encoded responses.
The Raiden API uses standard HTTP response codes and verbs.
The Raiden RESTful API endpoints correspond to the interactions allowed by a Raiden node.
The URL path always contains the API version as an integer.
All endpoints start with /api/<version>/
JSON Object Encoding
The objects that are sent to and received from the API are JSON-encoded. Following are the common objects used in the API.
Channel Object
{
"channel_identifier": "21",
"network_state": "unknown",
"token_network_address": "0x2a65Aca4D5fC5B5C859090a6c34d164135398226",
"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9",
"token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8",
"balance": "25000000",
"total_deposit": "35000000",
"total_withdraw": "15000000",
"state": "opened",
"settle_timeout": "500",
"reveal_timeout": "50"
}
A channel object consists of a
channel_identifier
: string containing the identifier of the channel.partner_address
: string containing the EIP55-encoded address of the partner with whom we have opened a channel.token_address
: string containing the EIP55-encoded address of the token we are trading in the channel.token_network_address
: string containing the EIP55-encoded address of the token network the channel is part of.balance
: string of the amount of thetoken_address
token we have available for payments.network_state
: string representing the online/offline status of the partner node for the channel. Possibly values are:"unknown"
: Network status is not known (currently this is the only value returned)"reachable"
: The node is known to be online and ready to send and receive messages"unreachable"
: The node is known to be offline and not ready to send and receive messages
total_deposit
: string of the amount of thetoken_address
token we have deposited into the contract for this channel.total_withdraw
: string of the amount of thetoken_address
token we have withdrawn from the channel on-chain.state
: current state of the channel represented by a string. Possible values are:"opened"
: The channel is open and tokens are tradeable"closed"
: The channel has been closed by a participant"settled"
: The channel has been closed by a participant and also settled.
settle_timeout
: The number of blocks that are required to be mined from the time thatclose()
is called until the channel can be settled with a call tosettle()
.reveal_timeout
: The maximum number of blocks allowed between the setting of a hashlock and the revealing of the related secret.
Errors
For any non-successful http status code, e.g. 409 Conflict or 400 Bad Request there will be an accompanying errors
field in the response json which you can check for more information on what went wrong with your request.
However, when Raiden fails to process the incoming request and raises an exception, the returned http status code will be 500 Internal Server Error. The caveat of this is that the response body will be just a string message which says “Internal server error”.
This is because we rely on our underlying stack to handle this while we take care of shutting down the API server preventing further incoming requests caused the exception in the first place from tampering with a state that was corrupted.
In any way, we consider 500 Internal Server Error errors as bugs in the Raiden client. If you encounter such errors, please report the bug here.
Resources
All objects that are sent and received from the Raiden API are JSON encoded. The following outlines each of the Raiden API endpoints.
Address
- GET /api/(version)/address
Queries the Ethereum address you choose when starting Raiden. A Raiden node is up and running correctly if the response returns that same address.
Example Request:
GET /api/v1/address HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/address
wget -S -O- http://localhost:5001/api/v1/address
http http://localhost:5001/api/v1/address
requests.get('http://localhost:5001/api/v1/address')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "our_address": "0x2a65Aca4D5fC5B5C859090a6c34d164135398226" }
Version
- GET /api/(version)/version
You can query the version endpoint to see which version of Raiden you’re currently running.
Example Request:
GET /api/v1/version HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/version
wget -S -O- http://localhost:5001/api/v1/version
http http://localhost:5001/api/v1/version
requests.get('http://localhost:5001/api/v1/version')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "version": "0.100.5a1.dev157+geb2af878d" }
Status
- GET /api/(version)/status
Query the node status. The responses
status
attribute can be one of:"ready"
: The node is listening on its API endpoints."syncing"
: The node is still in the initial sync. Number of remaining blocks to sync will also be given."unavailable"
: The node is unavailable for some other reason.
Example Request:
GET /api/v1/status HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/status
wget -S -O- http://localhost:5001/api/v1/status
http http://localhost:5001/api/v1/status
requests.get('http://localhost:5001/api/v1/status')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "status": "syncing", "blocks_to_sync": "130452" }
- Status Codes
200 OK – Successful query
500 Internal Server Error – Internal Raiden error
Settings
- GET /api/(version)/settings
Queries the settings of your Raiden node. At the moment only the URL of the pathfinding service is returned. The endpoint will provide more settings in the future.
Example Request:
GET /api/v1/settings HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/settings
wget -S -O- http://localhost:5001/api/v1/settings
http http://localhost:5001/api/v1/settings
requests.get('http://localhost:5001/api/v1/settings')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "pathfinding_service_address": "https://pfs.transport04.raiden.network" }
Contracts
- GET /api/(version)/contracts
By querying the contracts endpoint you can check which on-chain smart contracts are used. Returns the addresses of the smart contracts in use.
Example Request:
GET /api/v1/contracts HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/contracts
wget -S -O- http://localhost:5001/api/v1/contracts
http http://localhost:5001/api/v1/contracts
requests.get('http://localhost:5001/api/v1/contracts')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "contracts_version": "0.37.1", "monitoring_service_address": "0x20e8e5181000e60799A523a2023d630868f378Fd", "one_to_n_address": "0xA514Da2418576CeC4070C82996f30532dDa99706", "secret_registry_address": "0x9fC80eb1939d8147aB90BAC01AD585f3a71BeE7e", "service_registry_address": "0x3bc9C8d34f5714327095358668fD436D7c457C6C", "token_network_registry_address": "0x5a5CF4A63022F61F1506D1A2398490c2e8dfbb98", "user_deposit_address": "0x0794F09913AA8C77C8c5bdd1Ec4Bb51759Ee0cC5" }
Tokens
The tokens endpoints are used for registering new tokens and querying information about already registered tokens.
Note
For the Coruscant release two tokens are registered, DAI and WETH.
Information about Tokens
- GET /api/(version)/tokens
Returns a list of addresses of all registered tokens.
Example Request:
GET /api/v1/tokens HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/tokens
wget -S -O- http://localhost:5001/api/v1/tokens
http http://localhost:5001/api/v1/tokens
requests.get('http://localhost:5001/api/v1/tokens')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json [ "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "0x61bB630D3B2e8eda0FC1d50F9f958eC02e3969F6" ]
- Status Codes
200 OK – Successful query
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- GET /api/(version)/tokens/(token_address)
Returns the address of the corresponding token network for the given token, if the token is registered.
Example Request:
GET /api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8 HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
wget -S -O- http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
http http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
requests.get('http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json "0x61bB630D3B2e8eda0FC1d50F9f958eC02e3969F6"
- Status Codes
200 OK – Successful query
404 Not Found – No token network found for the provided token address
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- GET /api/(version)/tokens/(token_address)/partners
Returns a list of all partner nodes with unsettled channels for a specific token.
Example Request:
GET /api/v1/tokens/0x61bB630D3B2e8eda0FC1d50F9f958eC02e3969F6/partners HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/tokens/0x61bB630D3B2e8eda0FC1d50F9f958eC02e3969F6/partners
wget -S -O- http://localhost:5001/api/v1/tokens/0x61bB630D3B2e8eda0FC1d50F9f958eC02e3969F6/partners
http http://localhost:5001/api/v1/tokens/0x61bB630D3B2e8eda0FC1d50F9f958eC02e3969F6/partners
requests.get('http://localhost:5001/api/v1/tokens/0x61bB630D3B2e8eda0FC1d50F9f958eC02e3969F6/partners')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json [ { "partner_address": "0x2a65aca4d5fc5b5c859090a6c34d164135398226", "channel": "/api/<version>/channels/0x61C808D82A3Ac53231750daDc13c777b59310bD9/0x2a65aca4d5fc5b5c859090a6c34d164135398226" } ]
- Status Codes
200 OK – Successful query
302 Found – If the user accesses the channel link endpoint
The token does not exist
The token address is not a valid EIP55-encoded Ethereum address
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- Response JSON Array of Objects
partner_address (address) – The partner we have a channel with
channel (link) – A link to the channel resource
Register a Token
Warning
For the Coruscant release it is not be possible to register more than two tokens, due to security reasons in order to minimise possible loss of funds in the case of bugs. The two token that are registered are DAI and WETH.
- PUT /api/(version)/tokens/(token_address)
Registers a token. If a token is not registered yet (i.e.: A token network for that token does not exist in the registry), we need to register it by deploying a token network contract for that token.
Example Request:
PUT /api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8 HTTP/1.1 Host: localhost:5001
curl -i -X PUT http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
wget -S -O- --method=PUT http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
http PUT http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
requests.put('http://localhost:5001/api/v1/tokens/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8')
Example Response:
HTTP/1.1 201 CREATED Content-Type: application/json { "token_network_address": "0xC4F8393fb7971E8B299bC1b302F85BfFB3a1275a" }
- Status Codes
201 Created – A token network for the token has been successfully created.
402 Payment Required – Insufficient ETH to pay for the gas of the register on-chain transaction.
403 Forbidden – Maximum of allowed token networks reached. No new token networks can be registered.
404 Not Found – The given token address is invalid.
The token was already registered before, or
The registering transaction failed.
501 Not Implemented – Registering a token only works on testnet temporarily. On mainnet this error is returned.
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- Response JSON Object
token_network_address (address) – The deployed token networks address.
Channels
The channels endpoints allow you to open channels with other Raiden nodes as well as closing channels, querying them for information and making deposits or withdrawals.
Warning
The maximum deposits per token and node for the Coruscant release are:
DAI: The deposit limit is 5000 worth of DAI per channel participant making the maximum amount of DAI 10000 per channel.
WETH: The deposit limit is around 1.1905 worth of WETH per channel participant making the maximum amount of around WETH 2.3810 per channel.
Information about Channels
- GET /api/(version)/channels
Get a list of all unsettled channels.
Example Request:
GET /api/v1/channels HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/channels
wget -S -O- http://localhost:5001/api/v1/channels
http http://localhost:5001/api/v1/channels
requests.get('http://localhost:5001/api/v1/channels')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json [ { "token_network_address": "0xE5637F0103794C7e05469A9964E4563089a5E6f2", "channel_identifier": "20", "network_state": "unknown", "partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "balance": "25000000", "total_deposit": "35000000", "total_withdraw": "5000000", "state": "opened", "settle_timeout": "500", "reveal_timeout": "50" } ]
- Status Codes
200 OK – Successful query
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- GET /api/(version)/channels/(token_address)
Get a list of all unsettled channels for the given token address.
Example Request:
GET /api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8 HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
wget -S -O- http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
http http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8
requests.get('http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json [ { "token_network_address": "0xE5637F0103794C7e05469A9964E4563089a5E6f2", "channel_identifier": "20", "network_state": "unknown", "partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "balance": "25000000", "total_deposit": "35000000", "total_withdraw": "5000000", "state": "opened", "settle_timeout": "500", "reveal_timeout": "50" } ]
- Status Codes
200 OK – Successful query
404 Not Found – The given token address is not a valid EIP55-encoded Ethereum address
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- GET /api/(version)/channels/(token_address)/(partner_address)
Query information about one of your channels. The channel is specified by the address of a token and the address of the partner node which the channel is opened with.
Example Request:
GET /api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9
wget -S -O- http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9
http http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9
requests.get('http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "token_network_address": "0xE5637F0103794C7e05469A9964E4563089a5E6f2", "channel_identifier": "20", "network_state": "unknown", "partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "balance": "25000000", "total_deposit": "35000000", "total_withdraw": "5000000", "state": "opened", "settle_timeout": "500", "reveal_timeout": "50" }
- Status Codes
200 OK – Successful query
The given token and / or partner addresses are not valid EIP55-encoded Ethereum addresses, or
The channel does not exist
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Create a Channel
- PUT /api/(version)/channels
The request will open a channel and return the newly created channel object.
Example Request:
PUT /api/v1/channels HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "total_deposit": "35000000", "settle_timeout": "500", "reveal_timeout": "50" }
curl -i -X PUT http://localhost:5001/api/v1/channels -H "Content-Type: application/json" --data-raw '{"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "reveal_timeout": "50", "settle_timeout": "500", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "total_deposit": "35000000"}'
wget -S -O- --method=PUT http://localhost:5001/api/v1/channels --header="Content-Type: application/json" --body-data='{"partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "reveal_timeout": "50", "settle_timeout": "500", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "total_deposit": "35000000"}'
echo '{ "partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "reveal_timeout": "50", "settle_timeout": "500", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "total_deposit": "35000000" }' | http PUT http://localhost:5001/api/v1/channels Content-Type:application/json
requests.put('http://localhost:5001/api/v1/channels', headers={ 'Content-Type': 'application/json', }, json={ 'partner_address': '0x61C808D82A3Ac53231750daDc13c777b59310bD9', 'reveal_timeout': '50', 'settle_timeout': '500', 'token_address': '0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8', 'total_deposit': '35000000', })
- Request JSON Object
partner_address (address) – Address of the partner node with whom we’re opening the channel.
token_address (address) – Address of the token to be used in the channel.
total_deposit (string) – Amount of tokens to be deposited into the channel.
settle_timeout (string) – The number of blocks after which a channel can be settled.
reveal_timeout (string) – The number of blocks that are allowed between setting a hashlock and the revealing of the related secret.
Example Response:
HTTP/1.1 201 CREATED Content-Type: application/json { "token_network_address": "0xE5637F0103794C7e05469A9964E4563089a5E6f2", "channel_identifier": "20", "network_state": "unknown", "partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "balance": "25000000", "total_deposit": "35000000", "total_withdraw": "0", "state": "opened", "settle_timeout": "500", "reveal_timeout": "50" }
- Status Codes
201 Created – Channel created successfully
400 Bad Request – Provided JSON is in some way malformed
402 Payment Required – Insufficient ETH to pay for the gas of the channel open on-chain transaction
409 Conflict – Invalid input, e. g. too low a settle timeout
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Modify a Channel
- PATCH /api/(version)/channels/(token_address)/(partner_address)
This request is used to close a channel, to increase the deposit in it, to withdraw tokens from it or to update its reveal timeout. The channel is specified by the address of a token and the address of the partner node which the channel is opened with.
Close Channel Example Request:
PATCH /api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "state": "closed" }
curl -i -X PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 -H "Content-Type: application/json" --data-raw '{"state": "closed"}'
wget -S -O- --method=PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 --header="Content-Type: application/json" --body-data='{"state": "closed"}'
echo '{ "state": "closed" }' | http PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 Content-Type:application/json
requests.patch('http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9', headers={ 'Content-Type': 'application/json', }, json={ 'state': 'closed', })
- Request JSON Object
state (string) – Can only be set to
"closed"
Increase Deposit Example Request:
PATCH /api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "total_deposit": "100" }
curl -i -X PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 -H "Content-Type: application/json" --data-raw '{"total_deposit": "100"}'
wget -S -O- --method=PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 --header="Content-Type: application/json" --body-data='{"total_deposit": "100"}'
echo '{ "total_deposit": "100" }' | http PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 Content-Type:application/json
requests.patch('http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9', headers={ 'Content-Type': 'application/json', }, json={ 'total_deposit': '100', })
- Request JSON Object
total_deposit (string) – The increased total deposit
Withdraw Tokens Example Request:
PATCH /api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "total_withdraw": "100" }
curl -i -X PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 -H "Content-Type: application/json" --data-raw '{"total_withdraw": "100"}'
wget -S -O- --method=PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 --header="Content-Type: application/json" --body-data='{"total_withdraw": "100"}'
echo '{ "total_withdraw": "100" }' | http PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 Content-Type:application/json
requests.patch('http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9', headers={ 'Content-Type': 'application/json', }, json={ 'total_withdraw': '100', })
- Request JSON Object
total_withdraw (string) – The increased total withdraw
Update Reveal Timeout Example Request:
PATCH /api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "reveal_timeout": "50" }
curl -i -X PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 -H "Content-Type: application/json" --data-raw '{"reveal_timeout": "50"}'
wget -S -O- --method=PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 --header="Content-Type: application/json" --body-data='{"reveal_timeout": "50"}'
echo '{ "reveal_timeout": "50" }' | http PATCH http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9 Content-Type:application/json
requests.patch('http://localhost:5001/api/v1/channels/0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8/0x61C808D82A3Ac53231750daDc13c777b59310bD9', headers={ 'Content-Type': 'application/json', }, json={ 'reveal_timeout': '50', })
- Request JSON Object
reveal_timeout (string) – The new reveal timeout value
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "token_network_address": "0xE5637F0103794C7e05469A9964E4563089a5E6f2", "channel_identifier": "20", "network_state": "unknown", "partner_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "balance": "25000000", "total_deposit": "35000000", "total_withdraw": "5000000", "state": "closed", "settle_timeout": "500", "reveal_timeout": "50" }
- Status Codes
200 OK – Success
The provided JSON is in some way malformed, or
there is nothing to do since none of
state
,total_deposit
ortotal_withdraw
have been given, orthe value of
state
is not a valid channel state.
402 Payment Required – Insufficient balance to do a deposit, or insufficient ETH to pay for the gas of the on-chain transaction
404 Not Found – The given token and / or partner addresses are not valid EIP55-encoded Ethereum addresses
Provided channel does not exist or
state
,total_deposit
andtotal_withdraw
have been attempted to update in the same request orattempt to deposit token amount lower than on-chain balance of the channel or
attempt to deposit more tokens than the testing limit
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Payments
The payment endpoint is used for transferring tokens to another node. You can send the desired amount of tokens by providing the address of the token and the address of the receiving node. Besides you can query all payments that you sent or received.
Query the Payment History
- GET /api/(version)/payments/(token_address)/(partner_address)
When querying the payment history the response will include:
“EventPaymentSentSuccess” for successful payments
“EventPaymentSentFailed” for failed payments
“EventPaymentReceivedSuccess” for received payments
token_address
andpartner_address
are optional and will filter the list of events accordingly.Example Request:
GET /api/v1/payments/0x0f114A1E9Db192502E7856309cc899952b3db1ED/0x82641569b2062B545431cF6D7F0A418582865ba7 HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/payments/0x0f114A1E9Db192502E7856309cc899952b3db1ED/0x82641569b2062B545431cF6D7F0A418582865ba7
wget -S -O- http://localhost:5001/api/v1/payments/0x0f114A1E9Db192502E7856309cc899952b3db1ED/0x82641569b2062B545431cF6D7F0A418582865ba7
http http://localhost:5001/api/v1/payments/0x0f114A1E9Db192502E7856309cc899952b3db1ED/0x82641569b2062B545431cF6D7F0A418582865ba7
requests.get('http://localhost:5001/api/v1/payments/0x0f114A1E9Db192502E7856309cc899952b3db1ED/0x82641569b2062B545431cF6D7F0A418582865ba7')
- Query Parameters
limit (int) – Limits the payment history result to the specified amount
offset (int) – Offsets the payment history result by the specified amount
Example Response:
HTTP/1.1 200 OK Content-Type: application/json [ { "event": "EventPaymentSentSuccess", "amount": "20", "target": "0x82641569b2062B545431cF6D7F0A418582865ba7", "identifier": "3", "log_time": "2018-10-30T07:10:13.122", "token_address": "0x62083c80353Df771426D209eF578619EE68D5C7A" }, { "target": "0x82641569b2062B545431cF6D7F0A418582865ba7", "event": "EventPaymentSentFailed", "log_time": "2018-10-30T07:04:22.293", "reason": "there is no route available", "token_address": "0x62083c80353Df771426D209eF578619EE68D5C7A" }, { "event": "EventPaymentReceivedSuccess", "amount": "5", "initiator": "0x82641569b2062B545431cF6D7F0A418582865ba7", "identifier": "1", "log_time": "2018-10-30T07:03:52.193", "token_address": "0x62083c80353Df771426D209eF578619EE68D5C7A" } ]
- Status Codes
200 OK – For successful query
404 Not Found – The given token and / or partner addresses are not valid EIP55-encoded Ethereum addresses
409 Conflict – If the given block number or token_address arguments are invalid
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- Response JSON Array of Objects
event (string) – One of “EventPaymentSentSuccess”, “EventPaymentSentFailed” and “EventPaymentReceivedSuccess”.
amount (string) – Token amount of the payment.
target (string) – Address of the node which received the payment.
initiator (string) – Address of the node which initiated the payment.
identifier (string) – Identifier of the payment.
log_time (string) – Time when the payment event was written to the write-ahead log. The format of
log_time
is ISO8601 with milliseconds.token_address (string) – Address of token that was transferred.
reason (string) – Gives an explanation why a payment failed.
Initiate a Payment
- POST /api/(version)/payments/(token_address)/(target_address)
The request will only return once the payment either succeeds or fails.
Note
A payment can fail due to:
The secret for opening the hashlock not being revealed in time and the lock expires
The target node being offline
The channels leading to the target node not having enough
settle_timeout
andreveal_timeout
The funds not being enough
Example Request:
POST /api/v1/payments/0x2a65Aca4D5fC5B5C859090a6c34d164135398226/0x61C808D82A3Ac53231750daDc13c777b59310bD9 HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "amount": "200", "identifier": "42", "paths": [ { "route": ["0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "0x61C808D82A3Ac53231750daDc13c777b59310bD9"], "address_metadata": { "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8": { "user_id": "@0xea674fdde714fd979de3edf0f56aa9716b898ec8:localhost:8502", "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0xdf714485248a7d83f29e059622004acbb8a6b8a09c1506c304c2748e4e941cf769e864764ef028b31da525280d35d5ab87ee196dc738bc0f8de81ca3355a0c111b" }, "0x61C808D82A3Ac53231750daDc13c777b59310bD9": { "user_id": "@0x61c808d82a3ac53231750dadc13c777b59310bd9:localhost:8502", "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0x56682a1fecb4df0ce8e0e3aa9a0eaae4a6bc1a6265284f3fffbb1423e018122838353e6930c6000892e94f305b97c726a8e74c27dcce98adda9340f93555f5bb1c" } } } ] }
curl -i -X POST http://localhost:5001/api/v1/payments/0x2a65Aca4D5fC5B5C859090a6c34d164135398226/0x61C808D82A3Ac53231750daDc13c777b59310bD9 -H "Content-Type: application/json" --data-raw '{"amount": "200", "identifier": "42", "paths": [{"route": ["0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "0x61C808D82A3Ac53231750daDc13c777b59310bD9"], "address_metadata": {"0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8": {"user_id": "@0xea674fdde714fd979de3edf0f56aa9716b898ec8:localhost:8502", "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0xdf714485248a7d83f29e059622004acbb8a6b8a09c1506c304c2748e4e941cf769e864764ef028b31da525280d35d5ab87ee196dc738bc0f8de81ca3355a0c111b"}, "0x61C808D82A3Ac53231750daDc13c777b59310bD9": {"user_id": "@0x61c808d82a3ac53231750dadc13c777b59310bd9:localhost:8502", "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0x56682a1fecb4df0ce8e0e3aa9a0eaae4a6bc1a6265284f3fffbb1423e018122838353e6930c6000892e94f305b97c726a8e74c27dcce98adda9340f93555f5bb1c"}}}]}'
wget -S -O- http://localhost:5001/api/v1/payments/0x2a65Aca4D5fC5B5C859090a6c34d164135398226/0x61C808D82A3Ac53231750daDc13c777b59310bD9 --header="Content-Type: application/json" --post-data='{"amount": "200", "identifier": "42", "paths": [{"route": ["0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "0x61C808D82A3Ac53231750daDc13c777b59310bD9"], "address_metadata": {"0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8": {"user_id": "@0xea674fdde714fd979de3edf0f56aa9716b898ec8:localhost:8502", "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0xdf714485248a7d83f29e059622004acbb8a6b8a09c1506c304c2748e4e941cf769e864764ef028b31da525280d35d5ab87ee196dc738bc0f8de81ca3355a0c111b"}, "0x61C808D82A3Ac53231750daDc13c777b59310bD9": {"user_id": "@0x61c808d82a3ac53231750dadc13c777b59310bd9:localhost:8502", "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0x56682a1fecb4df0ce8e0e3aa9a0eaae4a6bc1a6265284f3fffbb1423e018122838353e6930c6000892e94f305b97c726a8e74c27dcce98adda9340f93555f5bb1c"}}}]}'
echo '{ "amount": "200", "identifier": "42", "paths": [ { "address_metadata": { "0x61C808D82A3Ac53231750daDc13c777b59310bD9": { "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0x56682a1fecb4df0ce8e0e3aa9a0eaae4a6bc1a6265284f3fffbb1423e018122838353e6930c6000892e94f305b97c726a8e74c27dcce98adda9340f93555f5bb1c", "user_id": "@0x61c808d82a3ac53231750dadc13c777b59310bd9:localhost:8502" }, "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8": { "capabilities": "mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1", "displayname": "0xdf714485248a7d83f29e059622004acbb8a6b8a09c1506c304c2748e4e941cf769e864764ef028b31da525280d35d5ab87ee196dc738bc0f8de81ca3355a0c111b", "user_id": "@0xea674fdde714fd979de3edf0f56aa9716b898ec8:localhost:8502" } }, "route": [ "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "0x61C808D82A3Ac53231750daDc13c777b59310bD9" ] } ] }' | http POST http://localhost:5001/api/v1/payments/0x2a65Aca4D5fC5B5C859090a6c34d164135398226/0x61C808D82A3Ac53231750daDc13c777b59310bD9 Content-Type:application/json
requests.post('http://localhost:5001/api/v1/payments/0x2a65Aca4D5fC5B5C859090a6c34d164135398226/0x61C808D82A3Ac53231750daDc13c777b59310bD9', headers={ 'Content-Type': 'application/json', }, json={ 'amount': '200', 'identifier': '42', 'paths': [{ 'route': ['0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8', '0x61C808D82A3Ac53231750daDc13c777b59310bD9'], 'address_metadata': { '0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8': { 'user_id': '@0xea674fdde714fd979de3edf0f56aa9716b898ec8:localhost:8502', 'capabilities': 'mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1', 'displayname': '0xdf714485248a7d83f29e059622004acbb8a6b8a09c1506c304c2748e4e941cf769e864764ef028b31da525280d35d5ab87ee196dc738bc0f8de81ca3355a0c111b', }, '0x61C808D82A3Ac53231750daDc13c777b59310bD9': { 'user_id': '@0x61c808d82a3ac53231750dadc13c777b59310bd9:localhost:8502', 'capabilities': 'mxc://raiden.network/cap?Receive=1&Mediate=1&Delivery=1&webRTC=1&toDevice=1&immutableMetadata=1', 'displayname': '0x56682a1fecb4df0ce8e0e3aa9a0eaae4a6bc1a6265284f3fffbb1423e018122838353e6930c6000892e94f305b97c726a8e74c27dcce98adda9340f93555f5bb1c', }, }, }], })
- Request JSON Object
amount (string) – Amount to be sent to the target
identifier (string) – Identifier of the payment (optional)
lock_timeout (string) – lock timeout, in blocks, to be used with the payment. Default is 2 * channel’s reveal_timeout, Value must be greater than channel’s reveal_timeout (optional)
secret (string) – secret for the HTL, if this should not be randomly generated (optional)
secret_hash (string) – The hash of the provided secret (
sha256(secret)
) this feature currently only works ifsecret
is provided. Ifsecret
is provided, butsecret_hash
is omitted the hash will be calculated by the client automatically (optional)path (string) – static route to the target node (optional)
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "initiator_address": "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", "target_address": "0x61C808D82A3Ac53231750daDc13c777b59310bD9", "token_address": "0x2a65Aca4D5fC5B5C859090a6c34d164135398226", "amount": "200", "identifier": "42", "secret": "0x4c7b2eae8bbed5bde529fda2dcb092fddee3cc89c89c8d4c747ec4e570b05f66", "secret_hash": "0x1f67db95d7bf4c8269f69d55831e627005a23bfc199744b7ab9abcb1c12353bd" }
- Status Codes
200 OK – Successful payment
400 Bad Request – The provided json is in some way malformed
402 Payment Required – The payment can’t start due to insufficient balance
404 Not Found – The given token and / or target addresses are not valid EIP55-encoded Ethereum addresses
409 Conflict – The address or the amount is invalid, or there is no path to the target, or the identifier is already in use for a different payment, or the static path sent is not usable.
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Note
This endpoint will return as soon the initiator has unlocked the payment(i.e Unlock message is sent). However, this does not necessarily mean that querying the balance from the target node, immediately after the initiator returns, will return the new balance amount due to the fact that the target might not have received or processed the unlock.
User Deposit
For paying the Raiden Services it is necessary to have RDN (Raiden Network Tokens) in the User Deposit Contract (UDC). This endpoint can be used to deposit to and withdraw from the UDC.
Deposit
- POST /api/(version)/user_deposit
Deposit RDN tokens to the UDC.
Example Request:
POST /api/v1/user_deposit HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "total_deposit": "200000" }
curl -i -X POST http://localhost:5001/api/v1/user_deposit -H "Content-Type: application/json" --data-raw '{"total_deposit": "200000"}'
wget -S -O- http://localhost:5001/api/v1/user_deposit --header="Content-Type: application/json" --post-data='{"total_deposit": "200000"}'
echo '{ "total_deposit": "200000" }' | http POST http://localhost:5001/api/v1/user_deposit Content-Type:application/json
requests.post('http://localhost:5001/api/v1/user_deposit', headers={ 'Content-Type': 'application/json', }, json={ 'total_deposit': '200000', })
- Request JSON Object
total_deposit (string) – The total deposit token amount. Should be the sum of the current total value and the desired (relative) deposit.
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "transaction_hash": "0xc5988c93c07cf1579e73d39ee2a3d6e948d959d11015465a77817e5239165170" }
- Status Codes
200 OK – Deposit was successful
400 Bad Request – The provided JSON is in some way malformed
402 Payment Required – Insufficient balance to do a deposit or insufficient ETH to pay for the gas of the on-chain transaction
404 Not Found – No UDC is configured on the Raiden node
409 Conflict – The provided
total_deposit
is not higher than the previoustotal_deposit
or attempted to deposit more RDN than the UDC limit would allow500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Plan a withdraw
- POST /api/(version)/user_deposit
Before RDN can be withdrawn from the UDC the withdraw must be planned.
Example Request:
POST /api/v1/user_deposit HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "planned_withdraw_amount": "1500" }
curl -i -X POST http://localhost:5001/api/v1/user_deposit -H "Content-Type: application/json" --data-raw '{"planned_withdraw_amount": "1500"}'
wget -S -O- http://localhost:5001/api/v1/user_deposit --header="Content-Type: application/json" --post-data='{"planned_withdraw_amount": "1500"}'
echo '{ "planned_withdraw_amount": "1500" }' | http POST http://localhost:5001/api/v1/user_deposit Content-Type:application/json
requests.post('http://localhost:5001/api/v1/user_deposit', headers={ 'Content-Type': 'application/json', }, json={ 'planned_withdraw_amount': '1500', })
- Request JSON Object
planned_withdraw_amount (string) – The amount of tokens for which a withdrawal should get planned.
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "planned_withdraw_block_number": 4269933, "transaction_hash": "0xec6a0d010d740df20ca8b3b6456e9deaab8abf3787cb676ee244bef7d28aa4fc" }
- Status Codes
200 OK – Withdraw plan was successful
400 Bad Request – The provided JSON is in some way malformed
402 Payment Required – Insufficient ETH to pay for the gas of the on-chain transaction
404 Not Found – No UDC is configured on the Raiden node
409 Conflict – The provided
planned_withdraw_amount
is higher than the balance in the UDC or not greater than zero500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Withdraw
- POST /api/(version)/user_deposit
Withdraw RDN from the UDC. Can only be done 100 blocks after the withdraw was planned.
Example Request:
POST /api/v1/user_deposit HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "withdraw_amount": "1500" }
curl -i -X POST http://localhost:5001/api/v1/user_deposit -H "Content-Type: application/json" --data-raw '{"withdraw_amount": "1500"}'
wget -S -O- http://localhost:5001/api/v1/user_deposit --header="Content-Type: application/json" --post-data='{"withdraw_amount": "1500"}'
echo '{ "withdraw_amount": "1500" }' | http POST http://localhost:5001/api/v1/user_deposit Content-Type:application/json
requests.post('http://localhost:5001/api/v1/user_deposit', headers={ 'Content-Type': 'application/json', }, json={ 'withdraw_amount': '1500', })
- Request JSON Object
withdraw_amount (string) – The amount of tokens which should get withdrawn.
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "transaction_hash": "0xfc7edd195c6cc0c9391d84dd83b7aa9dbfffbcfc107e5c33a5ab912c0d92416c" }
- Status Codes
200 OK – Withdraw was successful
400 Bad Request – The provided JSON is in some way malformed
402 Payment Required – Insufficient ETH to pay for the gas of the on-chain transaction
404 Not Found – No UDC is configured on the Raiden node
409 Conflict – The provided
withdraw_amount
is higher than the planned amount or not greater than zero or the withdraw is too early500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Connections
The connections endpoints allow you to query details about all joined token networks as well as leave a token network by closing and settling all open channels.
Details of All Joined Token Networks
- GET /api/(version)/connections
The request will return a JSON object where each key is a token address for which you have open channels.
Example Request:
GET /api/v1/connections HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/connections
wget -S -O- http://localhost:5001/api/v1/connections
http http://localhost:5001/api/v1/connections
requests.get('http://localhost:5001/api/v1/connections')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "0x2a65Aca4D5fC5B5C859090a6c34d164135398226": { "sum_deposits": "67", "channels": "3" }, "0x0f114A1E9Db192502E7856309cc899952b3db1ED": { "sum_deposits": "31", "channels": "1" } }
- Status Codes
200 OK – For a successful query
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- Response JSON Array of Objects
sum_deposits (string) – Sum of deposits in all currently open channels
channels (string) – Number of channels currently open for the specific token
Leave a Token Network
- DELETE /api/(version)/connections/(token_address)
The request might take some time because it will only return once all blockchain calls for closing and settling a channel have been completed.
The response is a list of all the channel state objects of the channels that have been closed.
Example Request:
DELETE /api/v1/connections/0x2a65Aca4D5fC5B5C859090a6c34d164135398226 HTTP/1.1 Host: localhost:5001 Content-Type: application/json
curl -i -X DELETE http://localhost:5001/api/v1/connections/0x2a65Aca4D5fC5B5C859090a6c34d164135398226 -H "Content-Type: application/json"
wget -S -O- --method=DELETE http://localhost:5001/api/v1/connections/0x2a65Aca4D5fC5B5C859090a6c34d164135398226 --header="Content-Type: application/json"
http DELETE http://localhost:5001/api/v1/connections/0x2a65Aca4D5fC5B5C859090a6c34d164135398226 Content-Type:application/json
requests.delete('http://localhost:5001/api/v1/connections/0x2a65Aca4D5fC5B5C859090a6c34d164135398226', headers={ 'Content-Type': 'application/json', })
Example Response:
HTTP/1.1 200 OK Content-Type: application/json ~ [ { "balance": "0", "channel_identifier": "8854", "network_state": "unknown", "partner_address": "0x4D156A78Ed6dFDfBbF3E569558eAF895b40217D6", "reveal_timeout": "50", "settle_timeout": "500", "state": "closed", "token_address": "0x59105441977ecD9d805A4f5b060E34676F50F806", "token_network_address": "0x625F82D937ccA0f1fF0097864895ba91635309A3", "total_deposit": "100000000000000000", "total_withdraw": "100000000000000000" }, { "balance": "0", "channel_identifier": "81", "network_state": "unknown", "partner_address": "0xbea332584a468b462100f8bfe5b38b0573ef1e36", "reveal_timeout": "50", "settle_timeout": "500", "state": "closed", "token_address": "0x59105441977ecD9d805A4f5b060E34676F50F806", "token_network_address": "0x625F82D937ccA0f1fF0097864895ba91635309A3", "total_deposit": "2000000000000", "total_withdraw": "2000000000000" } ]
- Status Codes
200 OK – Successfully leaving a token network
404 Not Found – The given token address is not a valid EIP55-encoded Ethereum address
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
Note
Currently, the API calls are blocking. This means that in the case of long running calls like leave a token network, if an API call is currently being processed by Raiden, all pending calls will be queued and processed with their passed API call argument.
Pending Transfers
The pending transfers endpoints let you query information about transfers that have not been completed yet.
- GET /api/(version)/pending_transfers
Returns a list of all transfers that have not been completed yet.
Example Request:
GET /api/v1/pending_transfers HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/pending_transfers
wget -S -O- http://localhost:5001/api/v1/pending_transfers
http http://localhost:5001/api/v1/pending_transfers
requests.get('http://localhost:5001/api/v1/pending_transfers')
See below for an example response.
- GET /api/(version)/pending_transfers/(token_address)
Limits the response to pending transfers of the specified token.
Example Request:
GET /api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C
wget -S -O- http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C
http http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C
requests.get('http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C')
See below for an example response.
- GET /api/(version)/pending_transfers/(token_address)/(partner_address)
Limits the response to pending transfers of the specified token and channel.
Example Request:
GET /api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C/0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685 HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C/0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685
wget -S -O- http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C/0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685
http http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C/0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685
requests.get('http://localhost:5001/api/v1/pending_transfers/0xd0A1E359811322d97991E03f863a0C30C2cF029C/0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json [ { "channel_identifier": "255", "initiator": "0x5E1a3601538f94c9e6D2B40F7589030ac5885FE7", "locked_amount": "119", "payment_identifier": "1", "role": "initiator", "target": "0x00AF5cBfc8dC76cd599aF623E60F763228906F3E", "token_address": "0xd0A1E359811322d97991E03f863a0C30C2cF029C", "token_network_address": "0x111157460c0F41EfD9107239B7864c062aA8B978", "transferred_amount": "331" } ]
- Status Codes
200 OK – Successful query
404 Not Found – The queried channel or token was not found
500 Internal Server Error – Internal Raiden node error
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- Response JSON Array of Objects
role (string) – One of “initiator”, “mediator” and “target”
Notifications
- GET /api/(version)/notifications
Raiden can inform the user about conditions that may require an action by the user or their attention. These are the types of notifications that currently can be returned, listed by
id
:low_rdn
: RDN tokens deposited in the UDC are below a threshold.version_outdated
: Running an outdated version of Raiden.missing_gas_reserve
: ETH balance is below a threshold and you may not be able to perform on-chain transactions.version_security_warning
: There is an important security update.
Example Request:
GET /api/v1/notifications HTTP/1.1 Host: localhost:5001
curl -i -X GET http://localhost:5001/api/v1/notifications
wget -S -O- http://localhost:5001/api/v1/notifications
http http://localhost:5001/api/v1/notifications
requests.get('http://localhost:5001/api/v1/notifications')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json [ { "body": "WARNING\nYour account's RDN balance deposited in the UserDepositContract of 0.0 is below the minimum threshold 5.5. Provided that you have either a monitoring service or a path finding service activated, your node is not going to be able to pay those services which may lead to denial of service or loss of funds.", "id": "low_rdn", "summary": "RDN balance too low", "urgency": "normal" }, { "body": "You're running version 1.1.1.dev630+g43ae6e32b. The latest version is 1.2.0It's time to update! Releases: https://github.com/raiden-network/raiden/releases", "id": "version_outdated", "summary": "Your version is outdated", "urgency": "normal" } ]
Shutdown
- POST /api/(version)/shutdown
You can call the shutdown endpoint to stop a running Rainde node.
Example Request:
POST /api/v1/shutdown HTTP/1.1 Host: localhost:5001
curl -i -X POST http://localhost:5001/api/v1/shutdown
wget -S -O- http://localhost:5001/api/v1/shutdown
http POST http://localhost:5001/api/v1/shutdown
requests.post('http://localhost:5001/api/v1/shutdown')
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "status": "shutdown" }
Testing
You can mint tokens for testing purposes by making a request to the _testing
endpoint.
This is only possible on testnets.
Mint Tokens
- POST /api/(version)/_testing/tokens/(token_address)/mint
This requires the token at
token_address
to implement a minting method with one of the common interfaces:mint(address,uint256)
mintFor(uint256,address)
increaseSupply(uint256,address)
Depending on the token, it may also be necessary to have minter privileges.
Example Request:
POST /api/v1/_testing/tokens/0x782CfA3c74332B52c6f6F1758913815128828209/mint HTTP/1.1 Host: localhost:5001 Content-Type: application/json { "to": "0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685", "value": "1000" }
curl -i -X POST http://localhost:5001/api/v1/_testing/tokens/0x782CfA3c74332B52c6f6F1758913815128828209/mint -H "Content-Type: application/json" --data-raw '{"to": "0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685", "value": "1000"}'
wget -S -O- http://localhost:5001/api/v1/_testing/tokens/0x782CfA3c74332B52c6f6F1758913815128828209/mint --header="Content-Type: application/json" --post-data='{"to": "0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685", "value": "1000"}'
echo '{ "to": "0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685", "value": "1000" }' | http POST http://localhost:5001/api/v1/_testing/tokens/0x782CfA3c74332B52c6f6F1758913815128828209/mint Content-Type:application/json
requests.post('http://localhost:5001/api/v1/_testing/tokens/0x782CfA3c74332B52c6f6F1758913815128828209/mint', headers={ 'Content-Type': 'application/json', }, json={ 'to': '0x2c4b0Bdac486d492E3cD701F4cA87e480AE4C685', 'value': '1000', })
- Request JSON Object
to (address) – The address to assign the minted tokens to.
value (string) – The amount of tokens to be minted.
Example Response:
HTTP/1.1 200 OK Content-Type: application/json { "transaction_hash": "0x90896386c5b218d772c05586bde5c37c9dc90db5de660bba5bd897705c976edb" }
- Status Codes
200 OK – The transaction was successful.
400 Bad Request – Something went wrong.
503 Service Unavailable – The API is currently unavailable, e. g. because the Raiden node is still in the initial sync or shutting down.
- Response JSON Object
transaction_hash (string) – The hash of the minting transaction.
Raiden Services
Introduction
The Raiden network includes auxiliary services, that enhance the overall user experience. These services include
finding short or cheap routes through the network and
allowing users to go offline safely by monitoring open payment channels.
Pathfinding Services
Pathfinding services have a global view on a token network and can provide suitable payment paths for Raiden nodes.
The service will keep its view on the token network updated by listening to blockchain events and messages send from individual nodes in which current capacities and fees are being published. Nodes can voluntarily publish this information in order to advertise their channels and mediate payments.
Choosing a Pathfinding Service
By default the Raiden client will chose a suitable Pathfinding service for you. As all PFSs are registered in the service registry, it will iterate over all of them and choose one that has a fee which is lower then a given threshold.
This threshold can be changed with the --pathfinding-max-fee
command line
flag and is set to 0.05 RDN by default.
If you want to use a certain PFS, then you can set it by using the
--pathfinding-service-address
command line flag.
Sent information
The PFS relies on information from the individual Raiden nodes to keep its network representation up-to-date. Therefore the Raiden clients will send information about channel capacities and fees to the PFS by default.
This can be disabled by using the private
routing mode, where no such
updates are broadcasted. However, this also means that the PFS has no
information about the channels of that node and will never mediate payments
over these channels.
Monitoring Services
Monitoring services can watch open payment channels when the user is not online. In case one channel partner closes a channel while the counterparty is offline (or doesn’t react for 80% of the settlement timeout after close has been called), the Monitoring service sends the latest balance proof to the channel smart contract and thus ensures correct settlement of the channel.
Monitoring for channels is disabled by default. To enable it, the
--enable-monitoring
command line flag is used. This will enable monitoring
for all open channels.
Note
It is currently not possible to enable monitoring for selected channels, but this will be possible in future version. This feature is tracked in this issue.
Sent information
In order to update the channel state the monitoring services need information about the channel state. For that reason, when monitoring is enabled, the client will send the latest received balance proof with additional information necessary for the payment of the monitoring services (see the spec for more information) to the monitoring services.
Monitoring rewards
The Monitoring Service expects a reward when it updates a channel on the user’s behalf. This reward is only paid out when the user did not update the channel state itself (this is handled by the Raiden client automatically). The reward is not configurable and has a value of 5 RDN.
Custom Setups
This section provides tutorials for using Raiden in custom setups. You can either read about how to run Raiden on a private Ethereum network or how to create a custom token for using it with Raiden in a testnet.
Raiden on Private Network Tutorial
Introduction
This tutorial shows how to run Raiden on a private network, using the master
branch (this is useful when you are working on a pull-request). This tutorial assumes Ubuntu 18.04.2 LTS and bash
.
Creating a Virtual Environment
In a shell, run
$ sudo apt-get install libncurses5-dev
$ mkdir priv_chain
If mkdir
fails, choose a different name, or move the existing priv_chain
directory to somewhere else.
$ cd priv_chain
$ virtualenv -p python3.9 env
$ source env/bin/activate
You should now be in the virtual environment, where all Python package installations are separately managed.
Now the command prompt should look like:
(env) $
Install Raiden and dependencies
(env) $ pwd
<snip>/priv_chain
(env) $ git clone https://github.com/raiden-network/raiden
(env) $ cd raiden
(env) $ pip install pip-tools
(env) $ make install-dev
Launch a private network
Installing Geth
Follow the guide and install Geth. A command geth
should be available in your shell. This guide assumes version 1.10.6, but other versions might work.
Preparing a genesis config
Prepare a file genesis.json
with the following content.
(env) $ cd ..
(env) $ pwd
<snip>/priv_chain
(env) $ cat genesis.json
{
"config": {
"chainId": 4321,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"ByzantiumBlock": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"ConstantinopleBlock": 0,
"PetersburgBlock": 0
},
"alloc": {},
"difficulty": "0x1",
"gasLimit": "0x9880000"
}
Starting a chain
With the genesis.json
you can initialize a blockchain.
(env) $ pwd
<snip>/priv_chain
(env) $ geth --datadir blkchain1 init genesis.json
(env) $ geth --rpc --datadir blkchain1 --networkid 4321 --rpcapi "eth,net,web3" console
<snip>
> personal.newAccount()
"0xd4de892c06cf4a0557c7d515f79fd20b8356d6cf"
Copy the shown address somewhere and shutdown geth. And start mining on your own private blockchain using the following command so that geth creates a stable stream of blocks at regular intervals.
(env) $ geth --rpc --datadir blkchain1 --networkid 4321 --rpcapi "eth,net,web3" --allow-insecure-unlock --mine --miner.threads=1 --miner.etherbase=0xd4de892c06cf4a0557c7d515f79fd20b8356d6cf
In this console geth
should keep running.
In another console navigate to the priv_chain folder and an IPC connection can be established with geth using:
geth attach ipc:blkchain1/geth.ipc
Figure out the contract version
Open a new console, and load the Python environment.
$ pwd
<snip>/priv_chain
$ source env/bin/activate
(env) $
Figure out the value CONTRACTS_VERSION
(env) $ cd raiden
(env) $ grep 'CONTRACTS_VERSION = ' -r ../env/lib/python3.9/site-packages/raiden_contracts
../env/lib/python3.9/site-packages/raiden_contracts/constants.py:CONTRACTS_VERSION = "0.37.0"
Copy the shown version somewhere.
Define constants
The contract version will be used quite often, so let bash remember it.
(env) $ export VERSION="0.37.0"
You will need your private key for the account you created.
(env) $ cd ..
(env) $ pwd
<snip>/priv_chain
(env) $ export PRIV_KEY=./blkchain1/keystore/UTC-<use TAB-completion to fill in>
If the TAB-completion shows more than two files, something has gone wrong. In that case, back up all files and start over.
The biggest 256-bit unsigned int is a useful default as deposit limits and the max number of TokenNetwork contracts.
(env) $ export MAX_UINT256=115792089237316195423570985008687907853269984665640564039457584007913129639935
The RPC connection point is used often.
(env) $ export PROVIDER="http://127.0.0.1:8545"
Deploy contracts
Now we can start deploying the Raiden smart contracts on the private chain.
(env) $ pwd
<snip>/priv_chain
(env) $ python -m raiden_contracts.deploy raiden --rpc-provider $PROVIDER --private-key $PRIV_KEY --gas-price 10 --gas-limit 6000000 --contracts-version $VERSION --max-token-networks $MAX_UINT256
{
"SecretRegistry": "0x6436d3B7205F18044a320403b1Cd0FfFd7e5D998",
"TokenNetworkRegistry": "0xC5e4a9189ac801077317CD6BCFA643677897D15B"
}
We will use these addresses later, so let’s remember them.
(env) $ export TokenNetworkRegistry="0xC5e4a9189ac801077317CD6BCFA643677897D15B"
(env) $ export SecretRegistry="0x6436d3B7205F18044a320403b1Cd0FfFd7e5D998"
Before we deploy the other contracts, we need a token contract for service payments.
(env) $ python -m raiden_contracts.deploy token --rpc-provider $PROVIDER --private-key $PRIV_KEY --gas-price 10 --gas-limit 6000000 --token-supply 10000000000 --token-name ServiceToken --token-decimals 18 --token-symbol SVT --contracts-version $VERSION
{
"CustomToken": "0xC5e9F7407359d1492d515C303A3aeDB434D3f0e1"
}
We use the address of this token to deploy service contracts.
First note down the address that you generated earlier on the geth console using:
> eth.accounts
["0xb97d3df9f9d112e1fe8f95f9608ffbd52e07a995"]
Then deploy the service contracts
(env) $ export ServiceRegistryController="0xb97d3df9f9d112e1fe8f95f9608ffbd52e07a995"
(env) $ export SERVICE_TOKEN="0xC5e9F7407359d1492d515C303A3aeDB434D3f0e1"
(env) $ python -m raiden_contracts.deploy services --rpc-provider $PROVIDER --private-key $PRIV_KEY --gas-price 10 --gas-limit 6000000 --token-address $SERVICE_TOKEN --user-deposit-whole-limit $MAX_UINT256 --service-deposit-bump-numerator 5 --service-deposit-bump-denominator 4 --service-deposit-decay-constant 100000000 --initial-service-deposit-price 100000000000 --service-deposit-min-price 1000 --service-registration-duration 234000000 --contracts-version $VERSION --token-network-registry-address $TokenNetworkRegistry --service-registry-controller $ServiceRegistryController
From the output, we remember the address of the UserDeposit contract.
(env) $ export UserDeposit="0x50E5f50b98a78615163E89A65fD60D551933CaE2"
We deploy another Token contract that’s going to be transferred on Raiden network.
(env) $ python -m raiden_contracts.deploy token --rpc-provider $PROVIDER --private-key $PRIV_KEY --gas-price 10 --gas-limit 6000000 --token-supply 10000000000 --token-name Token --token-decimals 18 --token-symbol TKN --contracts-version $VERSION
{
"CustomToken": "0x818cBB172D1a1b769acaA94e80e4c71ba40bdc79"
}
We register this token to the TokenNetworkRegistry.
(env) $ export TOKEN="0x818cBB172D1a1b769acaA94e80e4c71ba40bdc79"
(env) $ python -m raiden_contracts.deploy register --rpc-provider $PROVIDER --private-key $PRIV_KEY --gas-price 10 --gas-limit 6000000 --token-address $TOKEN --token-network-registry-address $TokenNetworkRegistry --contracts-version $VERSION --channel-participant-deposit-limit 10000000 --token-network-deposit-limit 1000000000
Start Raiden Client
In geth
console, figure out the deployer’s address.
> web3.toChecksumAddress(eth.accounts[0])
"0x35ebA3Dc57D2A66D378638B19A7CEb194dc29eb6"
Find the relevant contract addresses.
(env) $ export DeployerAddress="0x35ebA3Dc57D2A66D378638B19A7CEb194dc29eb6"
Store the password associated with the private key.
(env) $ echo "password" > passwd_file
And you can start the Raiden client:
(env) $ raiden --datadir exchange-a --keystore-path ./blkchain1/keystore/ --network-id 4321 --accept-disclaimer --address $DeployerAddress --rpc --api-address 0.0.0.0:5001 --web-ui --environment-type development --console --no-sync-check --accept-disclaimer --user-deposit-contract-address $UserDeposit --routing-mode private --password-file passwd_file
Use Custom Token
Introduction
In this guide, we will walk through the process of creating a custom token. A custom token can be used for any use-case but we will be adding and using it with the Raiden Network. In order to deploy the Custom Token, you will need to:
Get Goerli Testnet ETH (GÖETH)
Goerli is the name of the testnet on Ethereum where we will be deploying our token. To pay for the on-chain transactions you’ll first need to get some Goerli ETH (GÖETH) on your Ethereum account.
Since we will be using the Goerli testnet you’ll have to switch from “Main Ethereum Network” to “Goerli Test Network” in your MetaMask by selecting it from the top right dropdown.
After switching to the Goerli testnet you can go ahead and acquire some Goerli testnet ETH. One option to do so is to follow these steps:
Visit app.mycrypto.com
When asked how to access your assets, choose MetaMask and connect your account
On the Dashboard, go to Tools -> Use Testnet Faucet
Choose your account from the list and Request Access
You will see a success message showing the corresponding transaction on the Goerli testnet.
You can verify that 0.01 GÖETH was actually received by opening MetaMask and see if your Goerli Test Network shows a balance of total 0.01 GÖETH.
Import Custom Token
The Raiden Network supports transactions of ERC20 compliant tokens. Any smart contract that implements the ERC20 interface can be used with Raiden.
Importing the custom token Solidity code is done via the Remix Ethereum IDE (Ethereum’s integrated development environment). You can read more about ERC20 tokens in this GitHub repo.
Start off by getting the Solidity code for an ERC20 token from this GitHub gist.
Enter the URL for the Remix Ethereum IDE in your browser.
Under “Environments” click “Solidity”.
Under “File” choose to import from “Gist”.
In the pop-up that appears enter the ID, a779c0277f2fc5c935e2b2f62e49da49, of the gist you just viewed.
If the import was successful you should be able to open the imported code from the file explorer on the left hand side menu.
Compile Imported Token Code
Before a token can be deployed the imported token code has to be compiled into Ethereum Virtual Machine Code.
Click on the icon underneath the “FILE EXPLORER” in the left hand side menu to view the “SOLIDITY COMPILER”.
In the compiler you need to:
Select “0.5.4+commit…” from the “Compiler” dropdown.
Click on “Compile CustomErc20Token.sol”.
This will compile the token code and once the compiling step is done you’re ready to deploy your custom token.
Deploy Custom Token
In this step, we will be setting all parameters and finally deploy the custom token to the Goerli testnet.
Navigate to “DEPLOY & RUN TRANSACTIONS” in the left hand side menu.
Select “Injected Web3” from the “Environment” dropdown. This will open up MetaMask.
Connect with MetaMask when prompted.
Click on the arrow next to the orange “Deploy” button to expand the configure parameters.
Use the following parameter values:
initial_supply = 10000
decimal_units = 0
token_name = MyToken
token_symbol = TKN
Click the “transact” button.
Confirm the transaction from MetaMask when prompted.
In the Remix Ethereum IDE terminal you should now see an output similar to the picture below. Congratulations, you have now successfully deployed a token to Ethereum!
You can copy the transaction-hash and insert it in the seach-bar at “https://goerli.etherscan.io” to inspect all details of the transaction you just sent.
All you need to do to start using your token is to download and install Raiden and register your token in Raiden, either in the Web Interface or by using the API.
Raiden Developer Onboarding Guide
Introduction
This is a general onboarding guide whose main purpose is to help people who want to develop Raiden. It provides an explanation of the protocol followed by an explanation of the architecture.
For information on coding style, commit rules and other development rules please refer to the Contributing Guide.
The Raiden Protocol
In this section we will have the general explanation of how the Raiden protocol works, starting from the smart contracts and ending with the offchain messages that are exchanged between Raiden nodes. For a quick overview, please watch the video “Raiden Network Protocol Explained”. For a more formal definition of the protocol please refer to the specification.
Smart contracts
Raiden has 4 smart contracts that are needed to support the protocol. They can all be found at the smart contracts repository. The repository also contains scripts to deploy and verify the contracts on different networks. For more information on the contracts and the channel lifecycle check the smart contract specification.
Messages Exchanged during a Raiden Transfer
The Happy Case
Let’s first look at the messages exchanged in the happy path of a Raiden Transfer. Each Transfer has an Initiator
, a Target
and zero or more Mediators
. The Initiator
creates a Locked Transfer message and propagates it to the Target
through multiple Mediators. A LockedTransfer
message reserves the amount for the pending payment in each channel between Initiator
/Mediator
and Mediator
/Target
.
Once the LockedTransfer
reaches the Target
then they request the secret from the Initiator
by sending a Secret Request message. When the Initiator
receives the SecretRequest
message, the Initiator
can safely assume that a mediated locked transfer with the required amount has arrived to the Target
, since Target
as a payment receiver has all the incentives to be honest.
When the Initiator
gets the secret request message, they check to make sure that it’s a valid one and that it corresponds to a locked transfer that they sent out. If all checks out they send a RevealSecret message back to the Target
. The RevealSecret
message contains a secret that allows each Mediator
or the Target
along the path to claim the locked amount in the pending transfer.
The Target
will process the secret message, register it into their state and then proceed to reveal the secret backwards by sending their own RevealSecret
message to their counterparty.
The counterparty which can either be a Mediator
or the Initiator
will receive this RevealSecret
message and process it. This message tells them that the payee (either the target or another mediator if we got multiple hops) knows the secret and wants to claim the lock off-chain. So then they may unlock the lock and send an up-to date balance proof to the payee. This is done by sending what we call the Unlock message back to the partner who sent the RevealSecret
.
This concludes the transfer for that hop. If the receiver of RevealSecret
was the Initiator
then the transfer is finished end-to-end. If it was just a Mediator
then they will have to propagate the transfer backwards by sending a RevealSecret
message backwards to their partner repeating the procedure outlined above.
In this manner, two nodes can send the same amounts of token back-and-forth theoretically an unlimited amount of times The partner’s channel states will retain the same properties as before the complementary payments and from an on-chain perspective (if the channels will ever be closed) it looks like the complementary transfers never happened.
An Unhappy Case
Looking at a similar network topology as shown in the happy case above, let’s see how the protocol behaves when something goes wrong and our partner does not follow the protocol.
As seen in the figure above once the payee sends the RevealSecret
message the payer does not respond with the expected balance proof message. If that happens the payee has two choices:
If the amount involved in the token is really small then the payee can just do nothing and forfeit it.
If the amount is worth an on-chain transaction then the payee can go on-chain by registering the secret on the
SecretRegistry
contract and prove he knew the secret before the block of the lock expiration. From that point on the protocol can continue as before but now the secret is visible onchain so everyone along the path now knows it.
Offchain messages at Lock Expiration
If for some reason the protocol does not proceed and the Target never requests for the secret then the pending transfer lock will at some point expire. At the point of expiration in a payer-payee channel the payer will have to notify the payee that the lock has expired by sending a LockExpired message.
The payee receives the LockExpired
message, removes the lock from its pending locks for the partner and updates the state with the new balance proof.
Routing
At the moment routing in Raiden is handled by an external service, the :ref:Pathfinding Service (PFS) <services-pathfinding>
. The PFS tries to keep a global view of the network by listening to the Raiden nodes’ capacity updates, that they the nodes can chose to send to the PFS.
With this information the PFS can compute routes based on the current network state, which are available for the Raiden nodes to query for a small fee.
For a given payment the node asks the pathfinding service for a set of possible routes. It then tries those in order and if any payment fails, the next on will be tried and the failing one expires eventually.
The :ref:payment REST endpoint <api-init-payment>
does provide an optional argument, where a manually determined route can be given, if the route-request to the PFS should be bypassed.
If the transfer reaches the target and the protocol is followed properly as we saw in the happy transfer case above then all the pending transfers in the path will be unlocked and the node balances will be updated.
Pending Transfers
When a node mediates transfers all of the locks are kept on the state of the mediator node inside a merkle tree. For each new transfer the lock is appended to the merkle tree.
If the protocol is followed as shown in the happy transfer case above then the corresponding lock is unlocked and removed from the merkle tree.
Unlocking Pending Transfers
At this section we are going to look in more detail how the unlocking of pending transfers mentioned in the previous section works.
Continuing from the example seen in the pending transfers section above let’s explore what happens when B
’s partner closes the channel while there are transfers pending.
In the figure above the following things happen:
For the payment A->B->C ,
C
follows the protocol and send the secret back toB
.At the same time
A
closes the channel and so the normal offchain protocol can not be followed. Instead we enter the channel settlement lifecycle we saw in the previous section withA
closing the channel with what he received from his partnerB
.Now
B
has to register the secret received byC
onchain as he can no longer do it offchain. He has to prove that he knew the secret at a block height before the pending transfer’s expiration. He does that by calling registerSecret on theSecretRegistry
contract.Now it’s
B
’s turn to update the contract with what he has received fromA
. He will provide a hash of the merkle root, the transferred amount and the locked amount to the contract via the updateNonclosingbalanceproof call.After both are done and the settlement period has passed then anyone can settle the channel and send the tokens amounts owed to
A
andB
respectively back to its owners.After settlement whoever has pending transfers that need to be unlocked on chain has to unlock them onchain. In this example
B
will provide the merkle tree to the contract via the unlock function. That will result in the contract checking each one of the locks and send the locked tokens for which the secret was registered on time to the intended receiver (B
) and those for which it wasn’t back to the payer (A
).
Raiden Architecture
In this section we are going to see an explanation of how the code of the Raiden client is structured and how it implements the protocol detailed in the previous section.
Architecture Overview
At the core of the Raiden architecture lies a state machine. The state machine gets fed state changes from various sources.
Action*
state changes are caused by user commands directly from the user through the REST API.ContractReceive*
state changes are caused by blockchain events fetched via polling.Receive*
state changes are caused by receiving an offchain message.
All these state changes are processed along with the current state and produce a new state along with something that we call the “Raiden Internal Events” which is essentially I/O since the state machine can’t do I/O on its own.
Processing those raiden internal events performs all kinds of I/O.
Send*
events send offchain messages.ContractSend*
events send onchain transactions.Event*
events cause node events (for example, logging a debug message).
The State Machine
The entire state machine code is located under the transfer directory. For a good overview of all the classes used in the state machine check the architecture file.
The WriteAheadLog class is where the application state is stored. Also at the dispatch() function is where the state changes are applied to the current state through the state transition function and produce the next state and a list of Raiden Internal events.
The result of the application of a state change is represented by the TransitionResult class. It is essentially a tuple containing the new state and a list of Raiden internal events produced by the state transition.
The state in Raiden is kept in a hierarchical manner in what we call “Tasks”. At the top is the node state represented by the ChainState class.
Whenever a node starts up the first state change we get is the state is initialised state change and through its application we create the aforementioned Chain State. All state changes first pass through this level via the node state transition function, where the state-changes get subdispatched to different state-transition functions, depending on what state-change is handled.
When we start we also create a new TokenNetworkRegistry state corresponding to the default Token Network Registry contract. In the future there could be multiple token network registries but at the moment we only register the default.
Whenever we get a blockchain event denoting that a new Token Network was created then an ContractReceiveNewTokenNetwork state change is created. Processing that state change a TokenNetworkState is added to the TokenNetworkRegistryState
. All state changes that need to go down to the TokenNetwork are eventually subdispatched from the node state to the Token Network’s state transition function.
ChannelOpened
is a blockchain event denoting that a new channel was opened.
Whenever we receive ChannelOpened
and we are a participant, a ContractReceiveChannelNew state change is generated and sent into the state machine. The state change contains the channel’s NettingChannelState. When the state change is processed, the NettingChannelState
is added into the corresponding TokenNetworkState
. From this point on all state changes that concern a specific channel are subdispatched from the TokenNetwork processing to the channel’s state transition function.
All the state related to mediated transfers is kept under the transfer/mediated_transfer directory.
If our node initiates a transfer then it takes on the role of the Initiator and an ActionInitInitiator state change is generated. Upon processing a new InitiatorPaymentState task will be created. From now on all state changes that affect this transfer will be subdispatched to this Initiator task.
If our node mediated a transfer then it takes on the role of the mediator and an ActionInitMediator state change is generated. Then it’s subdispatched to the mediator’s state transition function where a new MediatorTransferState task will be created. From now on all state changes that affect this transfer will be subdispatched to this Mediator Task.
Finally if our node receives a transfer whose intended recipient is the node itself then it takes on the role of the target and an ActionInitTarget state change is generated. Then it’s subdispatched to the target’s state transition function where a new TargetTransferState task will be created. From now on all state changes that affect this transfer will be subdispatched to this Target Task.
Raiden Internal Events
As mentioned before all state transitions may generate a list of Raiden Events.
Since the state machine itself can have no side effects or I/O these events act as a trigger for all side effects. After a state change has been processed we get the event list. For each of these events we invoke the RaidenEventHandler which will process the events and trigger the appropriate side effects.
For example send a locked transfer or settle a channel if the settlement period has ended.
The Write Ahead Log
Before a state change is dispatched to the state machine for processing we write it into a Database called the Write Ahead Log. This allows Raiden to be persistent in case of crashes or other forms of irregular shutdown.
All that is needed in order to recreate the latest state is the initial state and the sum of state changes that lead up to it. So during a restart we read all the state changes in the WAL and replay them to recreate the latest state.
If Raiden has been running for many days then a lot of state changes will have gathered. Replaying all of these state changes at restart would take a lot of time so as an optimization at regular internals we are taking a snapshot of the current state. Subsequently at restart we restore the snapshotted state, retrieve the state changes since the snapshots and replay only those state changes to get to the final state.
The Transport Layer
The Raiden Transport layer is responsible for the receiving and sending of the off-chain messages. The current architecture allows for a pluggable transport layer through the use of a common transport interface. We have one implementation of this interface. The MatrixTransport.
Irrespective of the transport layer once a message is received it will eventually be forwarded to the MessageHandler which will generate the proper state changes and dispatch them to the state machine described in the previous section.
The Matrix Transport
The reasoning behind the choice of Matrix as a transport layer for Raiden is nicely explained in this blogpost.
In this section we are going to only look over the main points in the code which are the entries to the transport layer. For more information please check out the matrix transport spec.
In Matrix each user has a userid in the form of @<userId>:<homeserver_uri>
. userId
is the lowercased Ethereum address of the node, possibly followed by a 4-bytes hex-encoded random suffix, separated from the address by a dot. The homeserver_uri
is the URI of the matrix homeserver at which the user registers.
The nodes communicate via Matrix toDevice
messages. Once a message is received by a recipient, the messages will there be processed in batch by MatrixTransport._handle_messages, after decoding and validation these messages are forwarded to RaidenService.on_messages and processed by the node.
As for sending messages to a partner in a channel the send_async() function is the entry point. It essentially populates the sending queue for the partner. The actual messages will be sent from the queue during the main loop of the transport through the _check_and_send() function.
Messages acknowledgment and processing
All the messages seen in the offchain messages section need to be (1) seen and (2) succesfully processed by the partner node. To facilitate synchronization of that fact the transport layer makes sure that all messages except for Delivered
itself cause a Delivered
to be sent.
The Delivered message is sent right when the transport receives a message and before processing. It just tells the sender that the message was received and will be processed.
The Processed message is sent for the following cases (essentially messages containing a BP):
Succesfully handling a valid unlock (aka Secret) message at both target and mediator.
Handling a valid lock expired message
Handling a valid locked transfer message
On the sender’s side for the messages in the unordered queue:
Secret Request
Secret Reveal
Processed
Receiving a Delivered
is enough to remove them from the queue triggering the transport to stop retrying sending them.
On the sender’s side for the specific queues they’ll wait for the Processed message, signaling not only that the message was delivered, but also that the processing of the respective state change occurred successfully, or else keep retrying. If a Processed
is received the specific queue is cleared.
So, for a specific queue message, e.g. a LockedTransfer
in a specific channel:
-> A sends a
LockedTransfer
and starts a retry loop for it with message_id=123<- B receives it and sends
Delivered(123)
.<- B accepts it (i.e. succesfully processes it). Then sends
Processed(123)
and starts a retry loop for it.-> A receives
Delivered(123)
. Stops retry loop for any message_id=123 from B in its unordered queue, which is none, so it effectivelly skips it.-> A receives
Processed(123)
, stops retry loop for any message_id=123 from B in its specific queue (in this case,LockedTransfer
), sendsDelivered(123)
in reply toProcessed(123)
.<- B receives
Delivered(123)
, stops retry loop for any message_id=123 from A in its unordered queue (in this case,Processed
).
Blockchain Communication
We communicate with the blockchain through the JSONRPCClient class. That class is a wrapper of web3.py
for all blockchain JSON RPC calls and also checks that the underlying Ethereum client is compatible with Raiden. Checks things such as that all required interfaces are enabled and that the version is high enough (Byzantium enabled).
We communicate with each smart contract through the notion of a smart contract proxy. Each proxy is a essentially a class exposing the functionality of a specific contract using the JSONRPCClient
.
We have proxies for all the contracts:
PaymentChannel - This is just a wrapper of the token network functions for a specific channel.
Processing onchain events
All the events that happen onchain are polled after a new block is received and all found events are converted to Raiden internal state-changes.
From there each different event is processed and appropriate state changes are generated and dispatched to the state machine to be processed by it as we saw before.
Sending onchain transactions
As mentioned before a byproduct of state transitions in the state machine are Raiden Internal events. A certain subset of those events, the ContractSendEvent is what allows us to send on chain transactions.
As seen in the Raiden Internal Events section if a ContractSendXXX
event is sent to the RaidenEventHandler
then it will be processed and eventually the appropriate proxy will generate an onchain transaction.
The Rest API
All Raiden user facing actions are exposed via a REST API. For a full documentation of the endpoints check the REST API documentation.
As far as the code is concerned all of the functionality to interact with Raiden is inside what we call the Python API. The RaidenAPI
class has all the functions which deal with channel operations, transfers e.t.c.
These functions are exposed to the user through the REST API endpoints of the APIServer class.
The WebUI
Raiden has a graphical user interface. It’s an angular application running by default along with the raiden node and exposing an interface that can be accessed via the user’s Browser
Frequently Asked Questions
- What is MS/PFS?
These are smart contracts to be deployed in the future. See Monitoring Service and Pathfinding Service in the smart contract specification.
- How are messages encoded?
The messages specification should describe the message formats. On the implementation side, the messages module contains the message schemas. The serialisation of Python internal objects to messages happens in the MessageSerializer.serialize() and the mapping of the python type to the message encoding is specified in the
TYPE_MAPPING
of the BaseSchema.- Why does updateNonClosingBalanceProof() require one more signatures than closeChannel()?
The two functions authenticate the beneficiary of the balance proof in different ways.
closeChannel()
usesmsg.sender
whileupdateNonClosingBalanceProof()
checks thenon_closing_signature
argument. This allows a delegate (like Monitoring Services) to callupdateNonClosingBalanceProof()
, which has to be called during a limited challenge period.- Why do closeChannel() and updateNonClosingBalanceProof() authenticate both parties of the channel?
The authors of the balance proofs control their tokens, so their signatures must be checked. The receiver’s signatures must be checked because they should be able to refuse balance proofs. For example, when the transferred amount decreases in a newer balance proof, the receiver can choose not to add the second signature on the balance proof.
- Why are balance hashes used in closeChannel() and updateNonClosingBalanceProof() instead of plain balance proofs?
For privacy reasons. If
updateNonClosingBalanceProof()
required plain balance proofs, actual token amounts would be visible in all balance proofs sent to Monitoring Services. The Monitoring Services and eavesdroppers would learn a lot about transfer patterns of each user.
Contract Proxies Guide
Introduction
A Raiden node accesses smart contracts through wrappers called proxies. The proxies are implemented in raiden/network/proxies
directory. The proxies are supposed to be used with some special care, and they are implemented in a specific way.
The complication exists because there is always the possibility of a race between our node, the blockchain(s) and other parties. The Raiden node usually recognizes events on the blockchain only after some confirmation period. By the time the Raiden node recognizes an onchain event, the Raiden node has seen several blocks have been mined on top. However, when Raiden posts a transaction to the blockchain, the transaction is sent to miners who operate on the newest available block.
The proxies try to prevent the users from spending gas costs for transactions that fail anyway, and also to give a reasonable diagnosis why a transaction doesn’t (or didn’t go through).
A Proxy’s Workflow
Read-only case
If the call is read-only, the proxy never throws a transaction to the blockchain. The proxy asks the Ethereum client to execute the call in the specified blockhash.
State-modifying case
If the call modifies the state, the proxy does the following things in the successful case:
the proxy checks conditions on the specified block, and sees whether the call would fail (the post-condition checks)
the proxy then asks the Ethereum client to estimate gas, which might fail.
the proxy then asks the Ethereum client to submit the transaction to the blockchain.
the proxy sees the transaction receipt and sees if it’s successful.
When the precondition checks fail, the proxy raises BrokenPreconditionError
, blaming the caller for making a call without proper checks.
When the gas estimation fails, the proxy performs additional checks on the latest available block in order to determine the cause of the failure.
When the transaction was included in a block but the execution has failed, the proxy performs additional checks on that block in order to determine the cause of the failure. The checks use the chain state at the end of the failing block.
Depending on the cause of the failure, the proxy raises different kinds of exceptions. If you use the proxies, you’ll need to make sense of these exceptions (see below).
A Guide for Using Proxies
Before calling a proxy, make sure that the call is going to succeed in a confirmed block. Pick a confirmed block and query the blockchain so that the chain state allows a successful execution at that moment. And then, pass the blockhash of the confirmed block to the proxy when you call it.
The proxy checks the preconditions on the confirmed block. If any of the preconditions fail
because of the chain state, it raises BrokenPreconditionError
. This means there is a
mistake in the Raiden codebase, and a check must be added before calling the proxy.
However, the proxy raises BrokenPreconditionError
only when the error is about the chain state.
There are values that are invalid regardless of the chain state. These cause RaidenValidationError
instead of BrokenPreconditionError
. The RaidenValidationError
is not considered as
a bug in the codebase.
When the proxy doesn’t raise an exception, the call was successful. A transaction was included in a block and the transaction has been executed successfully. Moreover the proxy has waited for the block to be confirmed so that the state change is visible to the Raiden node.
When the proxy raises RaidenUnrecoverableError
, it means that there is a bug in the
client codebase or in the smart contracts.
When the proxy raises RaidenRecoverableError
, it might mean:
somebody else posted another transaction that altered the chain state in a conflicting way.
a third party smart contract behaved weirdly.
The proxy tries hard to determine whether the problem is in the Raiden codebase (client
or smart contract), but ultimately, if the proxy is not sure, it raises RaidenRecoverableError
.
A Guide for Implementing Proxies
When you implement proxies, the best documentation to follow is the source of TokenNetwork proxy.
Sometimes precondition checks are impossible because the specified block is too old (pruned in the Ethereum client). In this case, the precondition check can be skipped.
Checks before the gas estimation should raise one of the following exceptions:
BrokenPreconditionError
when the specified block has an unsuitable chain state for the call.RaidenValidationError
when the given argument is invalid regardless of the chain state.Instead of
RaidenValidationError
, you can also raise a special exception that you derive fromRaidenError
, but make sure you catch it. The typical use case is to provide a nice HTTP status number.
When you implement a new method of a proxy, consider refusing the string "latest"
as the block identifier.
Usually passing "latest"
as a block identifier to a proxy method poses a possibility of BrokenPreconditionError
.
The method can raise a ValueError
when "latest"
is passed as the block identifier.
Or, you might want to introduce a new type so that mypy
complains against using "latest"
as the block identifier.
Mind the number of RPC calls you are making. Instead of fetching a block number and then the block hash, there is usually a way to get the whole block in a single RPC call. When you post multiple RPC calls, you introduce more race conditions and performance bottlenecks.
How is Raiden tested
Raiden tests are split into these categories. The following categories are ordered from the faster and easier to debug to the slower and harder to debug:
Unit tests: A collection of fast tests that do not require external services to run. Because these tests don’t require any services nor threads to run, they don’t have problems with flakyness and are easy to debug. They are located under
raiden/tests/unit
.Property tests: These tests use randomly generated events. These tests are important ensure the system does not break when an unexpected series of events happen. Because of the architecture used by the project these tests are deterministic and do not require threads, therefore they are not flaky, but can be harder to debug because of their random nature. These tests are located under
raiden/tests/fuzz
.Smoketest: This is a quick self contained test, that can be ran by a user or prior to the integration tests, to ensure the basics are working properly. It will start a private chain, the necessary infrastructure for the transport layer, deploy the smart contracts, start a Raiden instance and interact with the blockchain. This test is available as a command line command, and it’s entry point is under
raiden/ui/cli.py
.Integration tests: These are long running tests, that require external services to run. Integration tests are slower to run, they have to start a local private blockchain, a local transport infrastructure, multiple Raiden nodes, and the REST API for these nodes. A fresh set of smart contracts are deployed into this private chain, including Tokens and Raiden’s smart contracts. These tests are important to make sure Raiden will work as expected with the Ethereum clients, however because they orchestrate multiple systems they are considerably slower than the previous categories, susceptible to flakyness, and harder to debug. These tests are located under
raiden/tests/integration
.Scenario tests: These tests run multiple times against the available testnets. They exercise the Raiden nodes through the available REST API, in the same way a user application would. These tests are important to test the system against real life conditions (using the internet). These tests use the scenario-player utility, and the scenarios are available under
raiden/tests/scenarios
.
Unit tests
Unit tests are deterministic, single threaded, and side-effect free. Because these tests don’t interact with other systems there isn’t any orchestration nor synchronization, so the tests cannot be flaky and are easy to debug.
This the preferred type of test for business logic, and should always be the preferred type of test to add to Raiden’s test suite.
Integration Tests
These tests exist to make sure that Raiden works properly with the other systems. Including the Ethereum client, Matrix, and the services for path finding and monitoring channels.
These tests are written in python and rely heavily on the pytest fixture system. This is necessary because these tests will run multiple Raiden nodes in a single process, exchange messages, and assert on the expected state of each individual node.
Here is an overview of the fixture system:
Configuration variables are defined in
raiden/tests/fixtures/variables
. This file contains the default settings for a test. These settings can be overwritten by thepytest.mark.paremetrize
decorator to change the test environment. Good examples are thenumber_of_nodes
which configures how many Raiden nodes should be started for the test,number_of_channels
which configure how many channels each of these nodes should have at the start of the test.The fixtures responsible to start a private chain are defined in
raiden/tests/integration/fixtures/blockchain.py
. These will start a new private chain, eithergeth
oropenethereum
, withblockchain_number_of_nodes
nodes. This private chain will have one prefunded account for each Raiden node, which allows these nodes to send on-chain transactions.The fixtures responsible to deploy the smart contracts are defined in
raiden/tests/integration/fixtures/smart_contracts.py
. These fixtures depend on the private chain, and will deploy the necessary Raiden and Token Smart Contracts for the test.The fixtures responsible to start the transport are defined in
raiden/tests/integration/fixtures/transport.py
. These fixtures will configure a local cluster of Matrix servers to run the tests.The fixtures responsible to start the raiden nodes and open the initial channels are defined in
raiden/tests/integration/fixtures/raiden_network.py
. These fixtures depend on both the previous fixtures, the private blockchain, the smart contract, and the transport fixtures. The raiden network fixtures will then create the Raiden apps and open the necessary channels for the test.
Which of the above fixtures are used depends on the test function, and it is determined by pytest through its fixture system. A test that uses a raiden_network fixture will have a fresh set of matrix servers, a new private chain with newly deployed smart contracts, and running Raiden nodes with open channels, ready to do transfers.
Because of all the moving parts, there are a few important things that have to be kept in mind while writting a test:
If a failure is not expected, it should make the test fail. In order to achieve this all tests are executed by a call to
raise_on_failure
, which monitors all the Raiden nodes, and if any unexpected exception is raised on one of these nodes, the test fails. This works because all the spawned threads are monitored, and unhandled exceptions are always propagated in the code base.Each individual system may hang for different reasons. The teardown of the blockchain can hang while waiting for the sockets to close, the integration test may hang because a bug (e.g. deadlocks, missing events, race conditions, etc.). Because it is important to be careful while watching for events and setting proper timeouts.
Changelog
Next 3.x feature release
[Support] #7493: Update
raiden-contracts
package.
3.0.0 2021-12-23
[Feature] #1541: Add support for cooperative settlement. If both parties are online and agree to settle cooperatively, closing and settling a channel is performed much quicker without having to wait for the on-chain settlement timeout. Closing a channel will now automatically try to perform a cooperative settlement first.
[Feature] #7195: Enable Raiden Node communication over WebRTC. This will allow payments to complete faster due to direct communication between peers.
[Feature] #7196: Send encrypted secret with the initial LockedTransfer message, obviating the need for SecretRequest and SecretReveal messages. This reduces the time needed to complete a payment.
2.0.0 2021-06-09
[Feature] #6541: Remove internal routing.
[Feature] #6657: Support for recent geth versions.
[Feature] #6582: Add
/settings
endpoint with information about the used pathfinding service.[Feature] #4730: Remove “join token network” feature from API. Explicitly create and fund channels, instead.
[Feature]: Update WebUI to version 1.2.1. Introduces a new “Quick Connect”, that is simpler and more transparent than the old “join token network” feature, and adds a dialog for interacting with the UserDeposit contract (UDC).
[Feature] #6563: Faster syncing with the blockchain.
[Feature] #6838: Add
/notifcations
endpoint for showing notifications and warnings to the user.[Feature] #6763: Ensure that pending messages are sent before Raiden is stopped.
[Feature] #6821: API endpoint for UserDeposit contract deposits/withdraws.
[Feature] #6947: Add support for Python 3.9.
[Feature] #6898: Add support for Geth 1.10.
[Feature] #6851: Raiden does not use Matrix rooms anymore. This greatly reduces the load on the matrix servers and increases the reliability of the transport layer.
[Feature] #6986: Increment DB version - this will make this release incompatible with previous releases. Please refer to the known issues section in the docs for details.
[Feature] #7064: Fix building of binary bundles which was broken for a while.
[Feature] #6673: Remove refund transfers. Refunds were intended as a way to quickly unlock funds in case a transfer can’t be completed without having to wait for the lock to expire. Unfortunately they were never very good at achieving this goal and added a lot of complications to the codebase. Therefore they got removed. See the linked issue for more details.
[Bug] #7120: Fix for transport potentially blocks at long http response times.
1.2.0 2020-11-06
[Feature]: Adds minimum required balance to send out MonitorRequest on mainnet.
[Feature] #5407: Add
/contracts
endpoint with information about the used contracts.[Feature]: Update WebUI to version 1.0.2 https://github.com/raiden-network/webui/releases/tag/v1.0.2
[Feature] #6482: Add support for client capabilities. Raiden clients can now negotiate supported features via their matrix profile.
[Feature] #6608: Compatibility with Synapse >= 1.12 and MSC2432
[Feature] #6646: add Matrix toDevice message support in transport layer
[Bug] #6444: Fix a race condition when processing blockchain events.
1.1.1 2020-07-20
1.1.0 2020-06-18
[Feature] #6220: Make sure the configured PFS and Matrix servers use the same chain and smart contracts.
[Feature]: Update WebUI to version 1.0.0 https://github.com/raiden-network/webui/releases/tag/v1.0.0
[Feature]: Update WebUI to version 1.0.1 https://github.com/raiden-network/webui/releases/tag/v1.0.1
1.0.1 2020-06-15
[Bug] #6224: Fix ULID generation under Windows, nanosecond clock resolution is not necessary anymore.
1.0.0 2020-05-26
[Feature]: Update WebUI to version 0.11.1 https://github.com/raiden-network/webui/releases/tag/v0.11.1
0.200.0-rc8 2020-04-21
[Feature] #5338: The number of blocks queried for events is now dynamically adjusted. This is necessary to prevent timeouts because the Ethereum client is overloaded.
[Bug] #6075: Fixed serialization problem for pending transactions.
[Bug] #6071: Fixed transport race condition which prevented a node to restart after a failure.
[Bug] #6083: Weakened byte code check to prevent errors with client pruning.
[Bug] #6082: Small bug fix, use of undefined variable.
0.200.0-rc7 2020-04-16
[Bug] #6077: Fix missing requirement to build macOS binaries
0.200.0-rc6 2020-04-16
0.200.0-rc3 2020-03-26
[Feature]: Update WebUI to version 0.11.0 https://github.com/raiden-network/webui/releases/tag/v0.11.0
[Feature] #5589: The Rest API now includes the token address in all returned payment related events.
[Feature] #4588: Remove the echo_node subcommand of the command line interface.
[Feature] #5281: Add a /status endpoint; start the API earlier and return 503 SERVICE UNAVAILABLE during the initial sync.
[Bug] #5395: Convert and return big integers as strings in the API response body.
[Bug] #5591: Rest API payment events can now be properly filtered by token address.
[Bug] #5583: The connection manager no longer opens channels with offline nodes when trying to connect to a token network.
[Bug] #5779: Handle the API exception when no further token networks can be registered by returning 403 FORBIDDEN.
0.200.0-rc2 2019-11-25
[Feature]: Update WebUI to version 0.10.1 https://github.com/raiden-network/webui/releases/tag/v0.10.1
[Feature] #5053: Make mediation fees non-negative by default. This fixes some counter-intuitive behaviour.
[Feature] #5217: Fully support infura as an underlying ethereum rpc node.
[Feature] #5278: Always use private rooms in the matrix transport.
[Feature] #5050: Raiden’s argument –debug-logfile-name has been renamed to –debug-logfile-path to better reflect the argument’s function.
[Bug] #4835: Fix etherscan sync by passing user-agent in the HTTP request. The request was failing because etherscan is protected by Cloudflare.
[Bug] #5055: Fix withdraw messages deserialization when the messages are queued in
queueids_to_queues
.[Bug] #5064: Display a user-friendly error message when the PFS info request fails.
[Bug] #5050: Raiden now works on OSX Catalina. Debug logfile is no longer written in the current directory.
0.200.0-rc1 2019-08-12
[Feature]: Added a new api endpoint
/api/v1/version
to query the raiden version via the Rest API.[Feature]: Update WebUI to version 0.10.0 https://github.com/raiden-network/webui/releases/tag/v0.10.0
[Feature] #4102: Display progress during syncing the blockchain.
[Feature] #4653: Allow setting per token network flat mediation fee from CLI.
[Feature] #4653: Allow setting per token network flat fees from CLI
[Feature] #4697: lock_timeout can be provided when making a payment.
[Feature] #4654: Define imbalance fees relative to channel balance.
[Feature] #4731: Setting fee defaults for Alderaan
[Feature] #4751: Add Fees to internal Routing
[Feature] #4815: Exclude direct transfers from fees
[Feature] #4844: Formalize fee calculation
[Feature] #4858: Add check for bound in med fee calculation
[Feature] #4860: Update per-channel proportional fee calculation
[Feature] #4917: Added documentation on using Raiden for atomic swaps.
[Feature] #4976: Geth users no longer need to activate the special txpool RPC api when starting their geth node.
[Feature]: The lowest supported geth version is now 1.8.21.
[Feature] #4905: Added API parameter to the PATCH channel endpoint to update channel’s reveal timeout.
[Bug] #4446: Fix assertion error in ‘calculate_imbalance_fees’
[Bug] #4561: Limit and offset should now work properly in the payment API event queries.
[Bug] #4560: Formatting of timestamp fields on the API should follow ISO8601.
[Bug] #4685: Invalidate a withdraw transaction on restart if the channel is closed.
[Bug] #4762: Properly check the withdraw expiration on the TokenNetworkProxy. This gives a better error message to the users and prevents a corner case error.
[Bug] #4835: Catch undefined med fee inside the sate machine
0.100.5-a0 2019-08-12
[Feature]: Update WebUI to version 0.9.2 https://github.com/raiden-network/webui/releases/tag/v0.9.2
[Bug] #4502: Fix a Raiden crash related to routing feedback
[Bug] #4348: Fix wrong calculation of
balance
field of channel information when tokens are locked in payments[Bug] #4498: Raiden now waits for synchronization with the blockchain events before finishing its startup and opening the API.
0.100.5-dev0 2019-07-30
[Feature]: Update WebUI to version 0.9.1 https://github.com/raiden-network/webui/releases/tag/v0.9.1
[Feature] #4457: Raiden now checks the version of the ethereum node at startup and if it is not supported quits with an appropriate message.
[Bug] #4301: Providing an endpoint argument without a port no longer leads to a crash.
[Bug] #4377: The client now sends proper capacity updates to the PFS.
[Bug] #4373: Fix a deserialization error for imbalance penalty
[Bug] #4378: Fix json decoding error that could lead to a crash.
[Bug] #4383: Fix locked transfer not being sent due to global queue handling.
[Bug] #4446: Fix problems with the calculation of mediation fees
0.100.4 2019-06-08
[Feature] #1498: Implement on-chain channel withdraw
[Feature] #3303: Use direct channels for payments when possible, without asking PFS
[Feature] #3754: Publish mediation fee infos to PFS
[Feature] #3863: Implement permissive source routing
[Feature] #3894: Drop support for UDP transport
[Feature] #4062: Use PFS requested fee instead of client max fee
[Feature] #4088: Check PFS info about registry address, prevent use of a PFS that doesn’t support the current network.
[Feature] #4095: Prevent Raiden from sending IOU to PFS when fee is 0
[Bug] #3778: Fix handling of pruned blocks in proxies.
[Bug] #4036: Initiator should check the state of the partner nodes
0.100.3 2019-05-22
[Feature] #3461: Static PFS payment for provided routes through the user deposits contract. Only usable if Raiden is run in development environment
[Feature] #3462: Static Monitoring service reward through user deposits contract. Only usable if Raiden is run in development environment
[Feature] #3464: Raiden will warn users about insufficient user deposit funds (If monitoring service or path-finding service are enabled and used).
[Feature] #3697: Make sure a token implements the ERC20 interface when registering a new token network. In this case, totalSupply function existence is implemented
[Feature] #4043: Update raiden-contracts to 0.19.0 with Görli Testnet support
[Bug] #3566: Handle cases where Raiden tries to query blocks which are old and pruned by the blockchain client (Geth & Parity)
[Bug] #3567: Resolve an issue in route filtering where the partner’s network state is taken into account when choosing a route
[Bug] #3687: Fix startup initialization issue which caused Raiden to crash on private chains
[Bug] #3832: Fix Raiden startup when a previous run aborted during migrations
[Bug] #3856: Handle pruned blocks during settle/unlock when requesting on-chain state, use latest if block is pruned
[Bug] #3874: Fix invalidation of a batch-unlock transaction in case a similar transaction was already sent/mined by channel partner
[Bug] #4024: Fix clearing a channel state iff all unlocks are done by channel participants
0.100.3-rc3 2019-04-15
[Feature]: Add support for Görli testnet in Raiden.
0.100.3-rc1 2019-03-29
[Feature] #3425: Update raiden-contracts package to version 0.9.0
[Feature] #3318: allow secret and/or hash with payment request
[Feature] #2436: Add an API endpoint to list pending transfers
[Feature] #3467: Raiden now chooses a PFS from a provided registry. Also added a new argument
--routing-mode
to configure the routing mode to either be PFS or BASIC.[Bug] #3475: Properly check async_result in rest api payments
[Bug] #3567: Properly check handling offline partners
[Bug] #3558: Raiden will no longer crash if starting with a fresh DB due to the ethereum node queries timing out.
0.100.2 2019-02-21
0.100.2-rc4 2019-02-04
[Feature] #2793: Faster restarts, transactions are sent in parallel on restarts.
[Feature]: Set python 3.7 as a minimum python version requirement to run Raiden.
[Feature] #3317: Return the secretHash and the Secret as part of payment response
[Bug] #2974: Alarm task is not longer blocking until transactions are mined.
[Bug] #3369: Fix high CPU usage when the raiden node is idle.
[Bug] #3380: Connection manager no longer attempts deposit if per partner funds are zero.
0.100.2-rc3 2019-01-25
[Feature] #2988: If estimateGas returns failure don’t send a transaction.
[Feature] #3236: Add backwards-compatible PFS integration in the routing layer
[Feature]: Update WebUI to version 0.8.0 https://github.com/raiden-network/webui/releases/tag/v0.8.0
[Bug] #3196: Proper fix for the bug that caused not finding locksroot in the DB during unlock
0.100.2-rc2 2019-01-11
[Feature]: Update WebUI to version 0.7.1 https://github.com/raiden-network/webui/releases/tag/v0.7.1
[Bug] #3257: Requesting the channel list with a token address and not a partner address via the API should no longer cause a 500 server error.
0.100.2-rc1 2019-01-04
[Feature] #3217: If channel is already updated onchain don’t call updateNonClosingBalanceProof.
[Bug] #3190: Prevents removal of initiator task when one of the transfers is expired.
[Bug] #3201: Workaround for gas price strategy crashing Raiden with an Infura ethereum node.
[Bug] #3121: If the same payment identifier is reused avoid a specific race condition that can crash Raiden.
[Bug] #3211: If using parity and getting the already imported error, attempt to handle it and not crash the client.
[Bug] #3216: If coming online after partner closed channel don’t try to send updateNonClosingBalanceProof twice and crash Raiden.
0.100.1 2018-12-21
[Bug] #3146: If a refund transfer is received and there are no other routes, keep the payment task so that the channel does not hang when mediator sends a LockExpired.
[Bug] #3170: If the same refund transfer is received multiple times, the mediator state machine will reject subsequent ones rather than clearing up the mediator task.
[Bug] #3175: If Github checking of latest version returns unexpected response do not let Raiden crash.
[Bug] #3179: Properly process a SendRefundTransfer event if it’s the last one before settlement and not crash the client.
[Bug] #3183: If as initiator our nodes receives a RefundTransfer then do not delete the payment task at the lock expiration block but wait for a LockExpired message. Solves one hanging transfer case.
[Bug] #3193: Channel balance shown to the user now takes locked amount into account.
[Bug] #3196: If our partner updates onchain with earlier balance proof find the event in the DB and properly perform the unlock onchain.
[Bug] #3171: Do not crash raiden if the Matrix server is offline when joining a discovery room.
0.19.0 2018-12-14
[Feature] #3157: Change REST api version prefix from 1 to v1.
[Bug] #3135: In development mode if more than 100 * (10^18) tokens are deposited then raiden no longer crashes.
[Bug] #3152: If the onchain unlock has already been mined when we try to send the transaction don’t crash Raiden.
[Bug] #3153: If a non-contract address is given for token_address in the channel open REST API call, the client no longer crashes.
0.18.1 2018-12-07
[Bug] #3093: Getting raiden payment history will no longer crash raiden for failed sent payment events.
[Bug] #3094: Raiden will now properly return payment failure and no longer hang if a payment times out due to a lock expiration.
[Bug] #3103: Fixes a bug in matrix which prevented retries of messages.
[Bug] #2779: Fixes a long standing bug that could cause payments to hang indefinitely.
0.18.0 2018-11-30
[Bug] #3046: Sync with the matrix server using the last known sync token. This solves the issue of missing messages during restart as previously only the last 10 were fetched.
[Bug] #3054: Client will now reject any signatures with
v
not in (0, 1, 27, 28)[Bug] #3091: Client will no longer accept secret of 0x0 or secrethash keccak(0x0).
0.17.0 2018-11-16
[Bug] #2931: Fixes serialization of state changes for refund transfers, allowing it to be used for unlocks.
[Bug] #3001: Don’t delete payment task when receiving invalid secret request.
[Bug] #2932: Node will no longer crash if it mediated a transfer and the channel cycle for mediation has completed.
[Bug] #3022: Reject REST API channel opening with an error if there is not enough token balance for the initial deposit.
[Bug] #3013: Encode all integers before saving to the sqlite database
[Bug] #3035: Registering a token twice should now return a proper error.
0.16.0 2018-11-09
[Feature] #2962: Check that the ethereum node has all required json rpc interfaces enabled when Raiden starts. If not fail with a proper error.
[Feature] #2946: Do not show full block information in the INFO logging message.
[Bug] #2923: Fix a race with multiple calls circumventing the gas reserve check.
[Bug] #2918: Fixed a synchronization problem, where a node would send invalid balance proofs.
[Bug] #2938: Don’t cleanup mediator if the transfer could not be forwarded. Could lead to stuck channels.
[Bug] #2934: Don’t send unecessary register secret transactions.
[Bug] #2951: Fallback to eth_getTransactionCount if there is no api to get the next available nonce.
[Bug] #2921: Properly estimate gas cost of transactions so that we have a more reasonable minimal amount of ETH required to run Raiden.
[Bug] #2973: Introduce special handling of infura endpoints so that the old getTransactionCount is used.
[Bug] #2963: Fixes an overflow issue with the hint of the join network dialog.
0.15.1 2018-11-03
[Bug] #2933: Raiden can now recover from crashes/restarts when there are pending onchain transactions.
0.15.0 2018-10-27
[Feature] #2858: Changed contract address argument names to be consistent with the names of the contracts in the contracts repository.
[Feature] #2857: Respect the
--environment-type
for private chain setup.[Feature] #2909: Add explicit flag
--unrecoverable-error-should-crash
to control UnrecoverableError crashing behaviour.[Bug] #2894: Raiden will no longer miss confirmation blocks at restart and will emit the block state change only for confirmed blocks.
[Bug] #2905: Mediator task must wait for the expired message, not just for the lock to expire, otherwise the channel will be unsychronized.
0.14.0 2018-10-20
[Feature] #2752: Renamed
--network-type
cli option to--environment-type
.[Bug] #2664: Raiden node will now wait for 5 block confirmations before processing a given transaction.
[Bug] #2794: UnlockPartialProofState does no longer raise AttributeError when accessing lockhash.
[Bug] #2813: Fixed swapped message and payment id, which caused problems on node restart.
[Bug] #2827: Fixed a typo in the handle_secretrequest function.
[Bug] #2449: Only polling events from confirmed blocks to prevent conflicts with reorgs.
[Bug] #2836: Contract version check now works for any deployed contract version.
[Bug] #2835: Incorrectly accepting a
RemoveLockExpired
is no longer possible[Bug] #2845: Properly update local state balance proof during a lock expiration.
0.13.1 2018-10-15
0.13.0 2018-10-12
[Feature] #2708: Add
--showconfig
CLI flag which dumps all configuration values that will control Raiden behavior.[Feature] #2713: Added the protocol version in the Ping message.
[Feature] #2764: Support pre-deployed contracts on Kovan and Rinkeby testnets
[Bug] #2720: A lock expired message must be considered invalid if the block in which the lock expired has not been confirmed.
[Bug] #2730: Refuse to send a transfer and ignore it during receiving, if its secret is already registered on-chain.
[Bug] #2662: Fix wrong deserialization of snapshots in special cases.
[Bug] #2746: Refuse to process a payment with an identifier already in use for another payment, and return a 409 Conflict in that case.
0.12.0 2018-10-05
[Feature] #2568: Validate the state changes for the Delivered and Processed sender.
[Feature] #2699: Add
/channels/<token_address>
REST-API endpoint to query all node’s channels for a specific token.[Bug] #2630: If a smaller deposit than
total_deposit
is given to the deposit RPC call then return 409 Conflict and not 200 OK.[Bug] #2655: Raiden node will now properly crash if communication with the ethereum node is lost.
[Bug] #2676: Return an error if an invalid
joinable_funds_target
value is provided to the connect endpoint.[Bug] #2567: Increase default channel reveal timeout to 50 blocks.
0.11.0 2018-09-28
[Feature] #2600: Improve logging for on-chain transactions
[Bug] #2535: Registering a secret on-chain for a locked transfer is now checked if it was received before the lock has expired.
[Bug] #2577: Small logging improvements
[Bug] #2602: On-chain secret reveal forces off-chain reveal
[Bug] #2603: Prevent crash in case of invalid Matrix server response
[Bug] #2609: Allow numeric network ids in the config file
[Bug] #2566: Warn the user about older existing database versions
[Bug] #2631: Prevent excessive state replay on restart
0.10.0 2018-09-21
[Feature] #2470: Add a main/test network switch enabling or disabling specific functionality depending on the network type.
[Feature] #2517: Increase the time a notification stays visible on the webui.
[Bug] #2414: If partner uses our old balance proof on-chain, the raiden client will now recover it from the WAL and properly use it on-chain.
[Bug] #2449: Fix a race condition when handling channel close events.
[Bug] #2501: Adds a matrix.private_rooms config to communicate only through private rooms in Matrix
[Bug] #2507: Fix a security issue where an attacker could eavesdrop Matrix communications between two nodes in private rooms
[Bug] #2512: Add descending order by block_number as default for blockchain events on webui.
[Bug] #2515: Adds validation for settle timeout against reveal timeout when opening a channel from the webui.
0.9.0 2018-09-14
[Feature] #2460: Pinned depedencies versions, builds are now reproducible and build artifacts won’t break because of downstream dependencies.
[Feature] #1473: Add gas price strategies that adapt the gas price to the network conditions.
[Feature] #2252: Adds payment history page to the webui.
[Feature] #2307: Matrix discovery rooms now are decentralized, aliased and shared by all servers in the federation
[Feature] #2287: Internal events now have timestamps.
[Bug] #2431: Do not crash on recoverable errors during settlement
[Bug] #2427: Fix a bug crashing the client when an unlock event for our address is seen on the chain
[Bug] #2419: Fix Matrix transport crash due to inability to decode events
[Bug] #2439: Return properly filtered results from the API payments event endpoint
[Bug] #2370: Fixes a few issues with the token amount input.
[Bug] #2437: Fix a bug where neighbors couldn’t communicate through matrix after restart
[Bug] #2453: Connection manager will no longer be stuck if there are no available channel partners
[Bug] #2367: Token network selection dropdown will not filter out not connected networks.
[Bug] #2461: For received payments events filter based on the initiator.
0.8.0 2018-09-07
[Feature] #2340: Add
--accept-disclaimer
argument to bypass the experimental software disclaimer.[Feature] #2363: Add copy functionality for addresses shown on the webui.
[Feature] #862: Switch WAL serialization format to JSON in order to facilitate for WAL upgradability.
[Feature] #1894: We now start having nightly releases found here: https://raiden-nightlies.ams3.digitaloceanspaces.com/index.html
[Bug] #2336: Fixes webui wallet page not loading data due to error.
[Bug] #2283: Fix API server Internal server error at token deposits.
[Bug] #2291: Adds EIP55 address validation to webui address inputs.
[Bug] #2362: Renamed wallet to tokens in the webui.
[Bug] #2356: Create a new database per token network registry.
[Bug] #2373: Include events for received payments in the payment events API endpoint.
0.7.0 2018-08-31
[Feature] #2225: Using a constant expiration for lock, making sure that on-chain unlocks are atomic.
[Feature] #2285: Request user acknowledgement for the experimental software disclaimer.
[Feature] #2251: Add webui support for switching token input between decimal and integer values.
[Feature] #2296: Gracefully handle malformed messages
[Bug] #2170: Removed block number from internal events and rearranged REST API debug endpoints
[Bug] #2264: Notification fonts are now aligned with the rest of the WebUI.
[Bug] #2278: Fixes leave network button request.
[Bug] #2277: Fixes sorting by balance for tokens and channels.
[Bug] #2284: Fixes balance notifications showing for wrong channels.
[Bug] #2282: Fixes internal webui error that would not propagate channel updates.
[Bug] #2275: Adds scientific notation for really small fractions when displaying balances.
[Bug] #2293: Initiator had the payment and message identifiers swapped.
0.6.0 2018-08-24
[Feature] #2253: Make addresses in REST logging user readable
[Feature] #2134: Database is now versioned and the DB directory path now uses that version
[Feature] #2192: Show notification on the WebUI when transfer is received or when channel is opened
[Feature] #2034: Update WebUI’s design
[Bug] #2197: WebUI now handles token decimals
[Bug] #2233: Fix MatrixTransport exception for invalid user displayname
[Bug] #2176: Expose total_deposit in the Rest API and fix depositing in the WebUI
[Bug] #2198: Fix building of the WebUI in the linux bundle.
0.5.1 2018-08-17
0.5.0 2018-08-10
[Feature] #1950: Breaking change: Better transaction handling on restart. This change breaks binary compatibility with the previous WAL.
[Feature] #1998: Add a strategy to make sure that the account Raiden runs on always has enough balance to settle all channels. No new channels can be openend when no sufficient balance for the whole channel lifecycle is available.
[Feature] #2084: Rename the
/transfers/
endpoint to/payments/
.[Feature] #1949: Add an endpoint to query the payment history.
[Feature] #682: Store a Snapshot of WAL state as recovery optimization.
[Feature] #2090: Rename transfers to payments in the webui.
[Bug] #2027: Raiden should now be able to connect to Infura.
[Bug] #2125: Show proper error message for invalid tokens on
/connections
.[Bug] #2149: Don’t crash if reusing same payment identifier for a payment
0.4.2 2018-08-02
[Feature] #1844: Log debug output to a file to make debugging of problems easier.
[Feature] #2011: Add a
--disable-debug-logfile
argument to disable the always on debug file if required by the user.[Bug] #1994: Starting Raiden with a corrupt database will now throw a proper error instead of crashing with an exception.
[Bug] #1996: Providing contracts addresses via the CLI that either have no code or contain unexpected code will now result in an error and not crash Raiden.
[Bug] #1817: Change the webui error message when the token registration fails.
[Bug] #1821: Show a better error message when channel creation fails.
[Bug] #2039: Return error for negative deposits via REST API
[Bug] #2004: Show a webui error when JSON-RPC requests fail.
0.4.1 2018-07-27
[Feature] #1825: Added periodical update notification and security releases checks.
[Bug] #1975: Fix balance hash generation for zero transfers and empty locksroot
[Bug] #1899: Print proper error without throwing exception if no accounts are found in the keystore
[Bug] #1911: The syncing message is now printed properly and does not repeat across the screen
[Bug] #1902: Check for ethnode connection at start and print proper error if Raiden can not connect
[Bug] #1869: Various matrix improvements. Prevent DOS attacks, and race conditions that caused client crashes. Require peers to be present to send message to them. Improves user discovery across Matrix federation.
[Bug] #1916: Return E409 on two concurrent conflicting channel deposits
[Bug] #1960: Return E409 when trying to open a channel for a token that is not registered
[Bug] #1969: Return E409 if negative
initial_funds
are given to the connect endpoint[Bug] #1883: Properly update menu state when channel state changes on webui
[Bug] #1976: Remove the ability to removedb. User should not be able to easily delete local state.
[Bug] #1897: Limit number of concurrent matrix connections so that raiden client does not crash.
[Bug] #1879: Leaving a token network should now work. Also removed the
only_receiving
parameter from the leave endpoint
0.4.0 2018-07-19
[Feature] #1328: Use separate database directory per network id. This is a breaking change. You will need to copy your data from the previous directory to the new network id subdirectory.
[Feature] #1195: Improve AccountManager error handling if keyfile is invalid.
[Feature] #1518: Update installation docs with Homebrew tap and update Homebrew formula on release.
[Feature]: Restartability in case of a proper shutdown of the Raiden node.
[Feature]: Smart contracts refactoring for readability, gas costs and new features.
[Feature]: New Matrix transport protocol.
[Feature]: Considerable codebase refactoring.
[Bug] #1237: Inform the user if geth binary is missing during raiden smoketest.
0.3.0 2018-02-22
[Feature] #921: Add
/api/1/connection
API endpoint returning information about all connected token networks.[Feature] #1022: Include an
errors
field in all unsuccessful API responses.[Feature] #1010: Add
amount
andtarget
toEventTransferSentSuccess
event.[Feature] #670: Block raiden startup until ethereum node is fully synchronized.
[Feature] #1037: Add
show_default
to CLI options.[Feature] #507: Making python’s channels crash resilient (recoverable). Note, this is a breaking change, the serialization format of channel objects changed to a WAL compatible representation.
[Feature] #1038: Introduce an upper limit for the
settle_timeout
attribute of the netting channel.[Feature] #1097: Added
--gas-price
command line option.[Feature] #1093: Reconnect raiden to ethereum node after disconnect.
[Feature] #1015: Added macOS compatibility and binary releases.
[Feature] #87: Update raiden to use Python 3 and the latest version of pyethereum.
[Feature] #1230: Unless specifically provided gas price and gas limit are now dynamically calculated from the
eth_gasPrice()
and latest blocks limit respectively.[Bug] #1011: Remove
settled
attribute from the NettingChannel smart contract.[Bug] #870: User selectable NAT traversal.
[Bug] #450: Removed
block_number
from contracts events, using block_number from block on which it was mined.[Bug] #1049: Make raiden byzantium compatible by no longer relying on
estimateGas
.[Bug] #1044: Rename
/connection
API endpoint to/connections
for consistency.[Bug] #1138: REST and Python API close did not work if a transfer was made.
[Bug] #1261: REST API now returns json error for invalid endpoints.
[Bug] #1224: Fix internal server error on REST endpoint
/events/tokens/
for non-existing tokens.[Bug] #1217: Correctly decode network events in the REST API.
[Bug] #1273: Don’t crash when using the
--nat=ext:IP
command line option.
0.1.0 2017-09-12
[Feature]: This is the Raiden Developer Preview release. Introduces a raiden test network on ropsten, the API and all the basic functionality required to use Raiden in Dapps. For more information read the blog post or the documentation of v0.1.0.
Safe Usage
Important security notes for usage
Warning
Despite the fact that Coruscant is the most mature and reliable release, it might contain bugs. Please make sure to follow the below security notes and system requirements to avoid increasing the risk of losing funds. Note that the loss of tokens could happen even if you follow these guidelines.
Ethereum node in sync and running reliably: Ensure that layer 1 works reliably. This means that you have to have an Ethereum node, either Geth or OpenEthereum, that is synced and working reliably. If there are any problems or bugs on the client then Raiden can not work reliably.
Ethereum client always online: Make sure that your Ethereum client is always online during operation of a Raiden node. As stated above, you can safely go offline if channel monitoring is enabled, but in order to use the Raiden nodes for doing transfers you have to have an online and synced Ethereum node, too. We recommend running it inside a monitor which will restart it if, for some reason, it crashes.
Ethereum Client can not be changed: Swapping the Ethereum client while transactions are not mined is considered unsafe. We recommend avoiding switching Ethereum clients once the Raiden node is running.
Raiden online for operations: Currently all nodes participating in a transfer need to be online in order for a transfer to be carried out. Hence, make sure that your Raiden node is always working, your network connection is stable and that the Raiden node is always online. As mentioned above, if a node has monitoring enabled it is safe to shut it down, but it will not be able to receive, mediate or send transfers while offline.
Unique account for Raiden: Raiden requires you to have a specific Ethereum account solely dedicated to Raiden. Creating any manual transaction with the Ethereum account that Raiden uses, while the Raiden client is running, can result in undefined behaviour. It is, however, safe to do manual transactions with the account if Raiden is not running.
Raiden account has sufficient ETH: Raiden will try to warn you if there is not enough ETH in your Raiden account in order to maintain your current open channels and allow them to go through their entire cycle. However, it is your job to refill your account with ETH and to make sure it is filled sufficiently once warned.
Raiden account has sufficient UserDeposit: If you are using pathfinding or monitoring service, you will pay for using these with IOUs through the UserDeposit smart contract. This deposit is done in RDN and if the user deposit does not have a sufficient balance, the Raiden services will not kick in, since they are not getting paid.
Do not transfer too small amounts for mediated transfers: Currently the Raiden client cancels payments that would require more than 20% of the transferred amount in fee costs. This means that the transferred amount has to be big enough, so that the fees do not surpass 20% of the transferred amount. This results in the following minimum amounts for the token networks when mediation is used:
DAI: Min 0.00001 DAI
WETH: Min Min 0.0000001 WETH
Persistency of local DB: Your local state database is located at ~/.raiden. This data should not be deleted by the user or tampered with in any way. Frequent backups are recommended. Deleting this directory can result in a loss of funds.
Never expose the Raiden REST API to the public: For Raiden’s operation, the client needs to be able to sign transactions at any point in time. Therefore you should never expose the Raiden Rest API to the public. Be very careful when changing the –rpc and –rpccorsdomain values.
Be patient: Do not mash buttons in the webUI and do not shut down the client while on-chain transactions are on the fly and have not yet been confirmed.
Testing Raiden on a slow network
In order to analyze Raiden performance on slow networks, it is useful to have a way of
introducing latencies. On Linux this can be achieved by making use of the tc
utility.
Note
These instructions are Linux-specific. You will need the ip
, tc
and
iptables
utilities. If you’re using Arch Linux, you can get these by
installing the iproute2
and iptables
packages.
The following script can be used to prepare the interfaces:
#!/usr/bin/env bash
# The network interface to the outside, i.e. the Internet.
IFACE="wlan0"
IP=$(ip addr show dev ${IFACE} | grep -Po 'inet \K[\d.]+')
NSNAME="slow"
VETHA="veth-a"
VETHB="veth-b"
VETHPREFIX="192.168.163.0/24"
VETHNETMASK="255.255.255.0"
VETHAIP="192.168.163.1"
VETHBIP="192.168.163.254"
ip netns add ${NSNAME}
ip link add ${VETHA} type veth peer name ${VETHB}
ip link set ${VETHA} netns ${NSNAME}
ip netns exec ${NSNAME} ip link set dev ${VETHA} up
ip netns exec ${NSNAME} ip addr add ${VETHAIP}/24 brd ${VETHNETMASK} dev ${VETHA}
ip link set dev ${VETHB} up
ip addr add ${VETHBIP}/24 brd ${VETHNETMASK} dev ${VETHB}
ip netns exec ${NSNAME} route add default gw ${VETHBIP} dev ${VETHA}
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s ${VETHPREFIX} -o ${IFACE} -j SNAT --to-source ${IP}
Note
All of the things here require root privileges.
The script will create a virtual Ethernet interface pair (veth-a, veth-b) and move one of the interfaces (veth-b) into a newly created network namespace. After setting up the interfaces’ addresses and adding the default route, the script will configure packet forwarding to the real interface (wlan0) connected to the Internet.
Once the interfaces are prepared, we can simulate a network delay of, say, 200ms by
using tc (replace ${VETHB}
with its value defined in the above script):
tc qdisc add dev ${VETHB} root netem delay 200ms
Now we just need to start Raiden from within the network namespace that we created:
ip netns exec ${NSNAME} bash
# switch to a normal user
# enter virtual environment
# run Raiden
Known Issues
Below you find a non-exhaustive list of known issues, which you should be aware of while using the current version of the software. Most of these issues are not Raiden specific, but rather apply to all blockchain applications.
Compromised user system: If the system of the user is compromised and accessed by an attacker or if a malicious application is running, then the write-ahead logging (WAL) could be accessed and valuable information leaked through it, since the WAL is not yet encrypted as such: raiden-network/raiden#579
Disk Full: The client does not properly handle the cases where the user’s disk may be full. This could lead to a loss of data due to the Raiden node crashing. In the future, we want to handle the detection of a full disk and gracefully quit the app: raiden-network/raiden#675
Blockchain Congestion: If the blockchain is congested and there is no space for the Raiden node to submit transactions on-chain, the client could end up being unable to settle the channel on-chain. The development of a gas slot based settlement timeout definition has been suggested in order to address blockchain congestion: raiden-network/raiden#383
Chain reorganizations: The client used to have an issue with edge cases of chain reorganizations. These issues have been hot fixed by only polling events that are confirmed for 5 blocks. Same applies to processing transactions, which are assumed to be valid only after a confirmation period of 5 blocks. This results in 15 blocks wait time for opening a channel (three on-chain transactions).
Database Upgrades
The database layout can change between versions. For patch and minor change releases, Raiden will do automatic upgrades in the background, as soon as you start the client with the new version. Your old database will always be kept as a backup.
However, for major change releases, this may not always be possible. If the client tells you, that the database migration was not possible, you are left with two options:
to recover all allocated funds, you should run the previous version of Raiden and close and settle all channels. Afterwards you can move your old database directory out of the way and join the network again with the same Ethereum keystore file.
if there are no funds worth recovering, you can also simply start over with a new Ethereum keystore file and start over. This should be true for all usage on testnet and in cases where your channel balances are very low on mainnet. Don’t hesitate to ask for help!
Raiden Config File
Raiden supports reading configuration parameters from a configuration file.
Raiden configuration parameter can also be given as environment variables - the variable has to be prefixed
with RAIDEN_
- otherwise the options are the same as the commandline arguments.
Location
The default location is <datadir>/config.toml
(where datadir defaults to ~/.raiden
).
It is possible to override the datadir
in the config file but please be aware that at that point
the config file will already have been loaded from the default location and therefore won’t be
re-read from the ‘new’ datadir.
Precedence
The precedence order in which configuration option values are applied is as follows (high to low):
Option given on the command line
Option read from the prefixed
RAIDEN_<config option>
environment variablesOption read from the config file
Option default value (as seen in the output of
raiden --help
)
Format
The config file uses the TOML format.
Option names may be quoted unless they contain punctuation in which case they must be. Values except numbers must always be quoted. Both single or double quotes are acceptable.
Lines starting with a #
are comments.
Parameter Naming
All parameters that can be given as command line options are also settable in the config file.
The name corresponds to the long option name without the leading double dash (--
). For example
the CLI option --password-file
would be called password-file
inside the config file.
The only option deviating from this scheme is the logging configuration which is explained below.
Logging Configuration
Raiden allows configuration of the logging system using a concise syntax on the command line. Inside the configuration file this is split out into a somewhat more expanded syntax.
The logging configuration is placed inside a section called [log-config]
which each following
lines key representing the logger name and the value the log level.
Example:
# CLI:
--log-config ':debug,raiden.network:info'
# Config file equivalent:
[log-config]
"" = "debug"
"raiden.network" = "info"
Raiden Glossary
Payments and Transfers
- Available balance
The available balance of a channel participant is:
\(B_{available} = B_{participant} - B_{locked}\)
- Balance
The balance determines how many tokens one specific channel participant holds.
You can calculate the balance by taking the total amount of tokens deposited, adding the total amount of tokens received and subtracting the total amount of tokens sent for a participant.
\(B_{participant} = P_{total\ token\ deposit} + P_{total\ tokens\ received} - P_{total\ tokens\ sent}\)
- Balance proof
Balance proof is any kind of message used in order to cryptographically prove on the blockchain what the latest transferred amount and locked amount received from a counterparty is.
- Channel capacity
The channel capacity determines how many tokens a channel holds. You can calculate the capacity by either:
Taking the total amount of tokens deposited and subtracting the total amount of tokens withdrawn by both participants that have a channel open with each other.
Taking the sum of both channel participants’ balance.
- Hashlock
A hashlock is the hashed secret that accompanies a locked message:
sha3(secret)
.- Lock expiration
The lock expiration is the highest
block_number
until which the transfer can be settled.- Locked amount
The locked amount is the total amount of tokens one participant of a payment channel has locked in pending transfers towards his counterparty
- Locked balance
The locked balance of a channel participant is the sum of the locked amount for all pending transfers \(T_{pending}\).
\(B_{locked} = \sum_{k=0}^{N-1} T_{pending}\) where \(N\) is the number of pending transfers
- MediatedTransfer
A mediated transfer is a hashlocked transfer between an initiator and a target propagated through nodes in the network.
- Merkletree root
- Locksroot
The root of the
merkle tree
which holds the hashes of all the locks in the channel.- Payment
A payment in Raiden is the process of sending tokens from one account to another. Each payment has an initiator and a target and can be composed of multiple transfers.
- Payment channel
The on-chain payment channel between two Raiden nodes.
- Preimage
- Secret
The preimage, what we call the secret in Raiden, is 32 bytes of random cryptographically secure data whose keccak hash ends up being the hashlock.
- Reveal timeout
The number of blocks in a channel allowed for learning about a secret being revealed through the blockchain and acting on it.
- RevealSecret
The reveal secret message is sent to a node that is known to have an interest to learn the secret.
- Secret message
The secret message is a message containing the secret and used for synchronization between mediated transfer participants.
- SecretRequest
The secret request message is sent by the target of a mediated transfer to its initiator in order to request the secret to unlock the transfer.
- Settlement timeout
- Settlement window
The number of blocks after the closing of a channel within which the counterparty is able to call
updateNonClosingBalanceProof
with the latest balance proof they received.- Transfer
A transfer in Raiden happens each time tokens are sent inside a payment channel.
- Transferred amount
The transferred amount is the total amount of tokens sent from a participant’s account to the account of a counterparty.
Participants
Overview of a payment with one mediator:
Transfer1 Transfer2
[Initiator] -----------> [Mediator] -----------> [Target]
Payer Payee Payer Payee
- Counterparty
The counterparty of a channel is the other channel participant with whom you have opened a channel.
- Initiator
The initiator is the Raiden node which initiates (starts) a payment.
- Payee
The payee is the participant who receives a transfer.
- Payer
The payer is the participant who sends a transfer.
- Target
The target is the Raiden node which receives a payment from the initiator.
Trademark Attributions
MacOS® is a trademark of Apple Inc., registered in the U.S. and other countries.
Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries.
Raiden ADRs
The Raiden project utilizes the Architectural Decision Records (ADR) system to capture the important architectural decisions made during development along with their context and consequences.
The following is an overview of the Raiden ADRs
Finished ADRs
Better testing framework for the entire Raiden suite (client, MS and PFS)
Status: proposed
Deciders: @czepluch, @stefante
Date: 2019-11-03 (last updated)
Context and Problem Statement
@rakanalh @karlb @LefterisJP and @czepluch had a meeting to discuss testing moving forward. More precisely how we can test the client together with the MS and PFS. Most of the discussion was focused on whether it makes sense to continue to support the scenario player and update it to support the third party services. Currently the SP is good for testing happy cases, but it is not easy to debug when errors occur and it doesn’t allow for introspection in the same way as pytest does. On the other hand, the current way that the integration tests work by spinning up a new blockchain per test is very inefficient. It’s also quite intimidating for people new to the project or less experienced to grasp how the integration tests work. Based on these short comings of the current two solutions, we discussed what could be done to create a setup that solves both problems.
Decision Drivers
Lack debug options for scenario player
Slow to spin up a fresh blockchain for every integration test
Duplicated tests between integration tests and SP
Make it easier for people new to the project or less experienced people to write tests
Have a way of testing all Raiden components
Considered Options
Option1: New repo that integrate the client with the MS/PFS with rewritten fixtures that only spins up one blockchain per test suit session. Link to meeting discussing this
Option2: Stick with things as they are and focus on adding functionality to the scenario player
Decision Outcome
TBD
Pros and Cons of the Options
Good, because writing what we currently call integration tests will be easier
Good, because there will be one blockchin spun up per testing session instead of per test
Good, because we will use pytest and make debugging easier than it currently is with the SP
Good, because we will enforce a “language” that interacts with the API server instead of python functions
Good, because we don’t need to maintain the SP anymore
Bad, because it will be quite some effort to rewrite all the fixtures to use one blockchain per session
Good, because we don’t have to create a new repo and rewrite the fixtures
Bad, because we have to maintain the SP and write scenarios
Bad, because the SP offer limited flexibility
Bad, because debugging scenarios that fail can be very difficult
Bad, because it’s difficult to get started writing integration tests at the moment
Raiden Team - Git Workflow
Status: proposed
Deciders: @lefterisjp, @hackaugusto, @konradkonrad, @rakanalh
Date: 2019-04-15
Context and Problem Statement
The current workflow team members in the Raiden team currently use is as simple as pick issues, create a respective branch for that issue and present a PR once the bug/feature is fixed/implemented.
This newly created branch will be merged into master regardless of what category the implementation falls into. There are currently 3 categories that a single PR can have: 1. Bug fix 2. Feature 3. Enhancement / Refactorings
Right now, all of these branches which can have any combination of those 3 categories will be merged into the master branch once it undergoes code review. However, we have come to realize that merging everything into master will cause our code to have a mixture of: 1. The bug fixes that we should release to the public. 2. Features that move Raiden forward into integrating with the PFS / MS services (which are under heavy development) 3. Code refactorings that address certain technical debts the team is constantly finding issues in, and/or is annoying and hard to work with.
The set of problems that the team finds in this approach is: 1. It is getting harder to make faster release cycles provided that some new code paths might be executed which are intended to support a new feature that Red-Eyes users should not / are not supposed to use. 2. Large issues are broken into smaller, self-contained PRs which move Raiden forward towards resolving the issue collectively but not individually. The justification for this is to have smaller PRs to review which is a huge advantange. However, this could potentially leave us with a state where the master branch is broken.
Decision Drivers
Increase the velocity of progress
Pave the way for faster mainnet release cycles
Have certain recent checkpoints in the project’s codebase where new features / functionalities are known to be stable.
Considered Options
After discussing this with @hackaugusto, @LefterisJP and @konradkonrad, we realized that we need to come up with a better way to separate our workflow for bug fixing from the ones for introducing new features and refactoring of the code base.
So, we seem to agree on using parts of the git-workflow where: 1. A develop branch is introduced. 2. The master branch will be our “production-ready” branch. 3. When a bug is reported, the assignee of the issue will branch of the latest master, provide a fix which will be merged into both master and develop. 4. The develop branch will contain all the work we do for new features and code refactorings. 5. Once any code changes are merged to master, develop should be merged on top of the latest master to ensure that our fixes are also residing in the develop branch in case any team member is working on the same code base.
The Pros of this new workflow: 1. Resolving bugs, merging them to master and instantly creating a release which contains the new bug fix(es) 2. Removing the worry about a broken master branch because the develop branch is going to contain all the potential breaking changes whose issues will be resolved separately. 3. Enable separate test configurations where the master would run tests on CI with production settings while develop runs with development configurations.
The Cons of this approach: 1. Rebasing develop should some how be automated as soon as any changes are merged into master, or otherwise if both branches diverge alot from each other, this could be a pain to resolve all the conflicts and get the develop branch back in shape. 2. It’s a new workflow so team members have to get used to this and map what they’re working on to the destination branch on which their implementation will land.
It was suggested to follow The Successful git branching model which is quite similar to the original proposal.
Decision Outcome
It was decided to follow the “Successful git branching model” option which is conveyed by the following:
Where:
master is maintained to be production-ready branch.
develop is the target branch for new features.
New feature branches are merged into develop.
Bug fixes are merged into both develop and master.
Nightly builds are created on latest develop.
If a certain nightly is to be released, a release branch is created to include changes required for creating that release such as bumpversion. Bug fixes specific to a certain release would be merged into that release branch.
Once a mainnet release is out, develop is merged into master and the process is restarted.
Provided we follow the sematic versioning scheme, every bug fix should be rolled out with a new minor version.
[Python Package Dependency Management]
Status: proposed
Deciders: TBD
Date: 2019-06-18
Context and Problem Statement
We as a team have been struggling with dependency management for a while now. Our current approach (‘manual’ requirements + pip constraints files) is cumbersome and error prone especially in case of dependency package version upgrades. Generally better tool support was seen as a solution to the issue.
Decision Drivers
The Process of upgrading a Python package dependency is an error prone, cumbersome and manual process
There were multiple occasions of failed dependency upgrades leading to failed CI builds and downstream incompatibilities
Decision Outcome
pip-tools
was chosen after a discussion between @hackaugusto, @konradkonrad, @palango and
@ulope as it currently seems to be the least disruptive and most well-used tool available.
Medium term poetry
might become the preferred solution but didn’t appear mature enough currently.
Pros and Cons of the Options
pip-tools
Currently the most mature tool.
Pros
Small scope, only manages dependencies
(Relatively) easy to understand operation model
Stable with a long history of being maintained
Better dependency solver than pip (which doesn’t have one)
Cons
No built-in support for dependencies between various requirement types (e.g. prod, dev). Requiring a custom wrapper tool.
CLI isn’t very intuitive
poetry
Looks to be a good candidate to switch to in the medium future.
Pros
Very polished cli
Handles the complete package life-cycle including optional venv management
Proper dependency solver
Cons
Still very new with some bugs and some usage types not supported (yet)
Very much a departure from the established ‘way of doing things’
Dependency resolution can currently be very slow
pipenv
Similar in concept to poetry, yet seems to be not a stable tool to build upon.
Pros
?
Cons
Also a very new tools
Many reports of arbitrary breakage with minor upgrades
Dependency resolution appears not to be stable
Withdraw & Expiry
Status: implemented Deciders: @konradkonrad @palango @hackaugusto @rakanalh Date: 2019-07-03
Context and Problem Statement
Withdraw functionality was introduced into Raiden to enable users to withdraw funds from their open channels into their accounts. The implemented flow works as follows:
Alice initiates the withdraw by dispatching ActionInitWithdraw with a monitonic total withdraw value.
Alice sends a signed WithdrawRequest message to its partner to agree on the new total withdraw.
Bob receives the withdraw request, validates it and replies with a signed WithdrawConfirmation message to Alice.
Alice receives the withdraw confirmation, validates it and uses signatures from step (2) and step(3) to send an on-chain transaction to withdraw the funds.
Here, a problem arises when Bob is unavailable or is not cooperative. In this case, Alice would have sent a withdraw request, locked part or all of its deposited amount for withdraw and no confirmation was received from Bob. This will lead to Alice not being able to use the locked funds for withdraw until Bob replies. In the case of Bob not being cooperative on this withdraw request, Alice’s locked withdraw funds are unavailable indefinitely until the channel is closed.
Considered Options
Option 1: Alice could close the channel with Bob. In this case, Alice gets back the funds it originally locked for withdraw. One downside of this approach is forcing the user to close the channel just to be able to unlock the withdraw funds. However, the counter-argument for this downside is a question of whether the user would want to have an open channel with a non-cooperating partner node.
Option 2: Implement withdraw expiry messages where Alice calculates a block at which the withdraw request expires. Bob will have to be aware of this expiry option and be able to react to a WithdrawExpired message which will clear the expired withdraw state for the partner. This approach resolves the issue of having the locked funds indefinitely or until the channel is closed with a non-cooperating partner node because once the withdraw request expires, Alice will remove the expired total withdraw state and locked withdraw will be unlocked.
Decision
Option 2 of WithdrawExpiry has the disadvantage of adding a collection of new messages to the protocol, which could be seen as further complication of the protocol. However, it has the advantage that amounts locked for withdraw can be unlocked and used for transfers instead in case of an expired withdraw attempt.
Though Option 1 can be argued that its much simpler, the benefit of unlocking funds previously locked for withdraw was seen as more viable solution even with the added complexity.
Examples of Option 2
Alice’s balance = 100 tokens
Alice requests a withdraw of 50 tokens. In this case, usable balance of Alice is 50 (assuming it did not send/receive transfers to/from Bob). total_withdraw=50.
Bob does not confirm with withdraw.
Alice sends Bob a WithdrawExpired message. Alice only had 1 pending withdraw state of 50. Before sending WithdrawExpired, Alice clears the expired withdraw state and total_withdraw is set to 0 because that is the only withdraw state that was requested.
Alice’s balance = 100 tokens
Alice requests a withdraw of 10 tokens. In this case, usable balance of Alice is 50 (assuming it did not send/receive transfers to/from Bob). total_withdraw=10.
Alice requests a withdraw of another 10 tokens. total_withdraw=20.
Alice requests a withdraw of another 20 tokens. total_withdraw=40.
Alice withdraw states look as follows:
[ { "total_withdraw": 10, }, { "total_withdraw": 20, } { "total_withdraw": 30, } ]
Bob does not confirm any withdraw.
Alice sends Bob a WithdrawExpired message for the first withdraw request which had a total_withdraw=10. Before sending WithdrawExpired, Alice clears the expired withdraw state total_withdraw=10. However, that doesn’t affect Alice’s total_withdraw because the latest one is 30 and stays 30.
Alice sends Bob a WithdrawExpired again for the second withdraw request which had a total_withdraw=20. Same as before applies.
Alice sends Bob a WithdrawExpired again for the third and last withdraw request which had a total_withdraw=30. Similar to the simple case, this was the only withdraw state that is pending, therefore expiring this withdraw state means that the total_withdraw of Alice goes back to zero.
Why Nonce was included in a non-balance proof message
Previously, only balance-proof messages had a nonce. The nonce value provides certain guarantees one of which is the fact that we are able to process messages in the exact order in which they were sent. Though WithdrawRequest, WithdrawConfirmation and WithdrawExpired messages are not balance-proof messages, a nonce value was required to make sure that these messages are also processed in the order in which they were sent. To accomodate for this change, the nonce field has to be decoupled from being based on the latest balance proof to a value that is maintained for the two sides of the channel state so that the next value is requested by either balance-proof based messages or withdraw messages.
Transport: Using multilayer transport with WebRTC
Status: Under investigation
Deciders: Raiden Core Team
Date: 2020-03-17
Context and Problem Statement
Matrix is likely to become the bottleneck for payment speed as well as throughput with a reasonable number of users and payments per second. Out of a Tech Deep Dive Session the raiden team considered different alternatives to the problem. The current implemented transport based on Matrix meets all of the necessary requirements Raiden has from a transport. Also the solution is working but with downsides regarding throughput and payment speed (message delivery speed).
Considered Options
Option 1: Multi layer transport. A multi layer transport has a robust base transport layer which meets all requirements. Raiden must work on this transport layer although with performance issues possible. Different Requirements can be outsourced to different other protocols which scale with the number of users in order to A) improve performance and B) take of load from base layer. If anything goes wrong in the outsourced layers, the base serves as a fallback. The Downside lies in increased complexity of implementing and maintaining multiple protocols.
Option 2: Go-libp2p-daemon. Libp2p is a very promising alternative p2p communication framework. It is configurable on multiple layers of transmission protocols. In the current stage it is still in a very experimental state. It probably does not fullfill all requirements for being a full transport layer for Raiden.
Option 3: Custom websocket solution. Another alternative is an inhouse built solution. Since the current Matrix transport is designed for its purpose being a chat protocol for humans there has been work done to abstract it to Raiden’s needs. A customized solution can be “tailored” to adapt perfectly to raiden’s use case and would probably be more lightweight than the current Matrix. A self-built transport of course requires additional maintainance capacity.
Decision
Option 1 was decided to be a short term solution to improve performance and scalability. Matrix already facilitates easy connection establishment of WebRTC through special events which can be send via rooms. It seems to be a reasonable amount of effort to implement in comparison to the gains in performance and speed. Examples have shown that subsecond payments are possible with WebRTC. Matrix as the base layer provides a complete functionality and serves as a fallback. Whereas payments are communicated via p2p WebRTC channels between the participants.
After a longer period (6+ months) the performance and throughput will be reevaluated. This also gives other protocols the chance to mature.
Examples of Option 1
Alice’s opens a matrix room with Bob
Bob receives the invite and joins
Alice as well as Bob use a signalling server to receive WebRTC
Both use the room and the special events to exchange canditates
Once they negotiated, they gonna open WebRTC data channels outside of Matrix.
If the connection breaks, the private room between Alice and Bob still exists as a fallback and will be used immediately.
Why WebRTC as the above layer solution
WebRTC is usually already built-in into any browser and very easy to use. As a matter of fact, the light client already implemented a proof of concept. Additionaly, as mentioned above, Matrix already provides a supported channel negotiation for their VoIP. In some examples, WebRTC proved to realize subsecond mediated payments. Ideally with this solution, Matrix only serves for discovery and presence and can therefore accept a much higher number of users until it becomes the bottleneck.
Current Status
The implementation for the light client is almost merged.
The implementation for the python client is still under investigation. It needs to be solved how and which framework to use for handling WebRTC data channels.
Risk of draining funds through imbalance fees
Summary
When a channel is opened, it is imbalanced according to the default imbalance fee settings. This means that when two channels are freshly opened and I mediate a payment through those, I will pay for the improved state of those channels. If the other participants collude, they can keep the negative fees and close the channel afterwards, so that I paid without actually being able to benefit from the new channel state.
Prerequisites
Imbalance fees are turned on for the mediator
The mediator must have opened (and deposited to) a channel. Otherwise, there would not be sufficient capacity to mediate.
Channel partners must be willing to close the channel when it is in a balanced state. Otherwise it is not an attack, but the intended result of incentivizing channel balancing.
Value at risk
When the mediator deposited \(d\) and has the proportional imbalance fee setting of \(i_p\) the channel partner can collude with an attacker who opens a channel to the mediator and initiates a payment with the amount \(a\). To receive the highest negative fee, he would choose \(a=\frac{d}{2}\). In that case the mediator pays
as imbalance fees, because fees apply for both channels. If flat or proportional are set, the paid amount will be lower
Costs for the attacker
An attacker has to pay for at least four transactions:
open channel to the mediator
deposit
close the new channel
settle channel
These have a total gas cost of
which at the current gas costs amounts to
If these exceed the earned fees, the attack is not profitable. If the mediator has high proportional fees, lowering the payment amount might make sense to only act on the steepest part of the IP curve.
Results for default settings
The default settings are \(i_p = 0.3%\) and \(p = 0.4%\) and flat fees are turned off. For \(a = \frac{d}{2}\) this results in mediation fees of
The worst case will happen with lower amounts (due to decreased proportional fees and the flatness of the IP function near the middle) and is between \(0.04\%\) and \(0.06\%\).
Possible conclusions
If I don’t mediate (e.g. light clients) or don’t open channels myself, I’m not at risk at all. If I open a channel to another node that is interested in mediating, that node won’t close the channel and everything is working as intended. If a node closes a channel after it is balanced, I can avoid being scammed again by not depositing into any channels to the same node.
However, it is very hard to judge what kind of similar attacks can be done when balances change through mediation and deposits/withdraws.
An obvious way to avoid all such problems would be to not do negative fees. The imbalance fee component could still be negative and cancel out other fee components, but the total will not go below zero. This could be done as a config setting, so that people willing to mediate with negative fees could still do that and gather real world experience on it.
When another party opens a channel to me, I could refuse to pay any balancing incentives until the channel has been balanced once. This would mitigate the problem while not impacting balancing on long lived channels. The details should be a bit more sophisticated and play well with deposits/withdraws.
Connection Manager Preventing Fast Sync
What Does the Connection Manager Do?
The connection manager (CM) allows “joining” a token network. This means that the CM will open channels to other nodes that already take part in channels in the same token network. If not enough other nodes have joined the network, it will wait for them to do so and then open channels. It also deposits tokens into channels which are opened to the node, but that part is not particularly relevant for this document.
Why Does That Make Things Slow?
Fetching large amounts of historic events on Ethereum is slow. The light client gets around this problem by only fetching events for channels in which the node participates. We want to do the same in the python client to solve the known extreme slowness on mainnet syncs.
But without fetching events about all channels, the node does not know which other nodes are in the token network. Therefore, the CM can’t connect to other nodes the way it used to.
Why Now?
We see this rear its ugly head on the Raiden mainnet where Raiden nodes won’t start within two hours unless Infura is used.
Solutions
The PFS has an endpoint with suggestions for nodes to which to connect. The CM could use that information for initial connections. If not enough suggestions are returned, it could either stop its work at that point or regularly re-query the PFS for suggestions until it connected to the desired amount of nodes.
Instead of querying Ethereum nodes, we could fetch the events from a different source. This could be a JSON file we create and host somewhere or a service like Anyblock Analytics. However, this would run counter to our decentralization efforts and could open up attack vectors if we trust these event sources too much.
The CM is not easy to understand for both users and developers. There are code paths in the Raiden code base that are only required by the CM that caused bugs in the past. It is not clear if the CM in its current form helps us to achieve our goals and its behavior of doing transactions at times after joining a TN can make Raiden look bad at times of high gas costs. In other words, the user is not made explicitly aware that these channels incur gas costs and this problem is even more pronounced during times of high gas costs.
Removing the CM and delegating the task of opening the right channels to a layer above Raiden would simplify the Raiden core and would be a better fit for many use cases.
See https://github.com/raiden-network/raiden/issues/4730 for previous discussion of this idea.
Final Decision by the Team
Providing a functionality similar to the CM is valuable, but it does not need to be part of the Raiden client’s core. Removing it from the client will reduce the likelihood of complicated bugs. Adding a simplified replacement to the WebUI will allow us to use the PFS’s partner suggestion endpoint and will make it easier to provide user feedback for the process of joining a token network. It might even be possible to share code for this between the python and light client.
Refunds
Why Would Anyone Do Refunds?
Sometimes, a payment can’t proceed as planned. This usually happens when nodes go offline, the channel capacity decreases, nodes change their behavior (e.g. fees) or nodes misbehave for other reasons.
When that happens, the initiator could just start a new payment over a different route until it succeeds. But the funds used in the first transfer will stay locked until the failed payment times out, thereby reducing the networks liquidity.
Refunds return the funds to undo the payment to a certain degree. If the funds are returned all the way to the initiator, he can remove the lock by revealing the secret. Refunds to mediators allow mediators to retry the mediation along a different path.
Current Implementation
At the moment, refunds are always propagated all the way back to the initiator. The initiator does not do anything on receiving the refund and the payment times out. This is the worst possible apporoach because:
Refunds don’t provide any benefit
Refunds lock up additional funds until the payment times out
Refunds significantly increase complexity of the mediation code
The light client has an incomplete and untested refund implementation, and Andre prefers to “research better approaches to the issue than to revive the Refund”.
Potential Solutions
Without significant improvements in our refund handling, the benefits are dubious. The upside of removing refunds is quite clear: reduced complexity in implementation, testing, documentation and the overall concept.
The existing implementation can certainly be improved, but there are open questions for nearly every potential improvement. Some of the questions are:
Should the refunds go back along the same route (might lack capacity) or choose a new route (who will pay the PFS)?
How likely are refunds to succeed?
Is the increased liquidity due to early lock release bigger than the amount of tokens locked by the refunds during the refund process (and until the timeout if the refund fails)?
Will refunds be visible to end users? How?
Should refunds incur mediation fees?
Should mediation fees for the forward payment be refunded?
Should the initiator reveal the secret for a fully refunded payment even when he will have to pay mediation fees?
Even if the current refunds are useless, they might serve as a foudation for a better but similar refund mechanism. Things to consider:
Can we remove the liquidity requirements for refunds by going back along the original route? The refund might be able to free the locked liquidity on each step instead of locking up more tokens, even before the secret is revealed
The mediation code could be simplified by limiting the allowed cases (e.g. only refund back all the way to the initiator, no new routes tried by mediators)
There are other ways to do refunds or cancel payments, which might be worth further investigation:
One suggestions by Augusto: https://github.com/raiden-network/raiden-contracts/issues/1216 (could not be made into a viable suggestion, yet)
Lightning has some kind of refund or cancellation mechanism
Final Decision by the Team
After discussion, only two options were left that could be implemented without huge effort:
Removing refunds
Do refunds back to the initiator, including all fees. Revealing the secret will free up the locked funds, without moving any tokens. This way, everyone has an incentive to participate.
The seconds approach still has the problem of locking up additional funds and potentially failing. The benefits are too small to justify the increased complexity. So the recommendation is to remove the refunds.
This discussion was based on the assumption of strict routing, i.e. strictly following the route planned by the initiator. If we allow retrying different routes at any node, the results might be different.
Discussion Documents
Routing With Built-In Token Swaps
Use Case
Buyers and sellers usually each have a preferred currency/token. When both parties prefer different tokens, one party has to accept dealing with a non-preferred token. In addition to being inconvenient, this can also require open a new channel, this making the payment slow and expensive. Dealing with a different token might not even be possible for some parties (e.g. due to bookkeeping restrictions). If the Raiden Network provided a way to swap tokens while doing the payment, both parties could deal with their preferred token and transaction would be quick, cheap and convenient.
Concept
Node A wants to pay node B an amount of 10 T2 tokens, but A only has T1 tokens. Node A requests a route from the PFS:
source: A
target: B
target_amount: 10 T2
source_token: T1
The PFS looks for a route that minimizes the amount of T1 tokens that A has to spend in order for B to receive 10 T2, taking into account both mediation fees and the required token swap. The returned route might look like
T1 T1 T2
A --> M1 --> M2 --> B
meaning that mediator M2 accepts T1 and sends T2, thereby providing both mediation and token conversion. Despite using different token networks, the payment will still be atomic by using the same hash time lock across the whole path.
Problems
Nodes willing to do token swaps have to tell the PFS their exchange rate. Broadcasting could be much traffic, polling would slow down routing.
The PFS has to be able to route through multiple token networks at the same time.
Behavior not clear for non-strict routing
The route can fail due to changes in conversion rate. This can be mitigated by adding some safety margin, but this increases the price for the sender.
Token Swaps in Raiden
Use Cases
A merchant wants to be paid in DAI to avoid exchange rate risks for crypto currencies. The buyer only has WETH in his wallet. The buyer can use his WETH to pay, a mediator will swap the WETH to DAI and the merchant will receive DAI.
A user has WETH and wants to buy RDN without going onchain. He already has a channel for both WETH and RDN. He can use Raiden token swaps to do this. This might be the same operation as above, since he could pay himself in a different token.
Even if no suitable route to a target can be found within a token network, there might be a route between initiator and target when funds are allowed to move through a different token network for a subset of the path. This will only be useful if the swaps are very cheap.
In addition to providing normal mediation, mediators can also choose to act as an exchange between different token networks. The mediator will have to explicitly accept the legal risks and choose reasonable exchange rates.
Raiden does not provide upgradable contracts. When deploying new contract versions, the only way to move the liquidity in the old contracts to the new ones is to close the existing channels and open new ones in the updated contracts. Doing that will incur high gas costs once the Raiden Network has many users.
This can be mitigated by having some mediators open channels in the new contracts while keeping their old channels open. Then these mediators can mediate payments between the old and new networks.
This will require support for multiple token network registries in the client. As a consequence, multiple token networks for the same token also have to be supported.
As long as the HTLs are compatible, a payment can work across any number of different blockchains. A Raiden payment can be used to swap between BTC, tokens on Ethereum, tokens on sidechains or other blockchains.
Compared to the other use cases, this brings additional problems, since the PFS will not be able to find routes outside of Ethereum and we will have to coordinate with non-Raiden clients. As a consequence, this should be left out of the initial implementation. But we should keep it in mind, so that we don’t accidentally make it harder to add support for this in a later step.
Problems
For many token pairs, the exchange rates will change too frequently to allow manual rate updates.
Possible approaches: * Provide an API where exchange rates can be updated * Include code to fetch exchange rates from external sources in Raiden
As a safety measure, we should save the timestamp of the last exchange rate update and not allow swaps when the rate is too old.
Users expect the PFS not only to return a working route, but also to return a cheap route. To do this, the PFS needs to know about exchange rates when planning a route.
Possible approaches: * Push: Mediators broadcast exchange rates, like they do with fees (high traffic) * Pull: Mediators broadcast the supported tokens (or token pairs?). Exchange rates are requested by the PFS as needed. This increases the path finding latency. * Relative rates: Mediators broadcast rates relative to a well respected source of exchange rates (e.g. Uniswap + 3%)
An additional problem is the handling of slippage. When exchanging large amounts of tokens, the exchange rates should get worse. To a certain degree, this is taken care of by increasing imbalance fees, but that might not be sufficient.
After a mediator made a token swap, the payment should be forced to succeed or fail quickly. Otherwise a considerable free option problem will arise.
Currently, the PFS handles each token network separately, which prevents it from finding routes across different token networks. Implementing support for cross-TN-routes requires some changes to the data structures used in the PFS. Doing this naively will result in slow pathfinding, since the combined graph of all token networks grows large quickly.
Raiden currently expects payments to stay within one token network. To make this work we need:
Changes to the REST API (prefixing a payment with the TN address does not work, anymore)
For migration between contract versions: support for multiple TN registries and multiple TNs for same token
Definition of the payment route has to include additional information (like token network contract for each hop, assumed exchange rate per mediator…)
… (Please add more here!)
Modular vs. In-protocol Approach
As of the last discussion nearly all of the features above can be implemented in two different design approaches:
Modular Approach - using existing functionalities and combining them
In-Protocol Approach - the protocol can natively handle new features
In the following the two design approaches are described on the example of multi token network payments.
The modular approach aims to keep the Raiden core protocol lean and simple. This should keep the Raiden protocol robust. Less features introduce less edge cases which would have to be taken into account. This all would lead to less potential exploits in the core codebase. Depending on the feature to be implemented proxy smart contracts and off-chain controlling modules would have to be implemented to compound the Raiden core functionalities to a more powerful feature. These proxies and modules communicate with each other and control a classic Raiden node.
If the Raiden protocol were only be able to handle single token payments another idea is to assemble a multi token payment by initiating multiple payments. This would require the mediator who exchanges into a different token to accept a payment and forwarding it by initiating a next payment as defined by the PFS. A controlling module must understand that for the incoming payment the mediator is not the payee rather than a mediator. This results in two conditions:
The mediator must not trigger a secret request (or at least will not receive an answer)
The next payment must be initiated with the same secret hash as the incoming payment
The control module is responsible for forwarding the payments and contains the logic of handling and accepting mediation. A user can easily place his desired exchange rate. The module coordinates between the PFS and verifies that the current payment is acceptable to the user’s desired exchange rate.
The opposite approach implements this feature directly into the protocol such as payments can be forward to channels from a different token network.