Skip to content

Latest commit

 

History

History
751 lines (627 loc) · 26.1 KB

File metadata and controls

751 lines (627 loc) · 26.1 KB

Interledger with Ethereum On-Ledger Settlement

A demo that sends payments between 2 Interledger.rs nodes and settles using Ethereum transactions.

Overview

This example shows how to configure Interledger.rs nodes and use an Ethereum network (testnet or mainnet) as a settlement ledger for payments sent between the nodes. If you are new to Ethereum, you can learn about it here. To learn about settlement in Interledger, refer to Peering, Clearing and Settling.

overview

Prerequisites

Rust

Because Interledger.rs is written in the Rust language, you need the Rust environment. Refer to the Getting started page or just curl https://sh.rustup.rs -sSf | sh and follow the instructions.

An Ethereum network

First, you need an Ethereum network. You can either use a local testnet, a remote testnet, or the mainnet.

For this example, we'll use ganache-cli which deploys a local Ethereum testnet at localhost:8545. To install ganache-cli, run npm install -g ganache-cli. If you do not already have Node.js installed on your computer, you can follow the instructions below to install it.

Advanced: You can run this against the Rinkeby Testnet by running a node that connects to Rinkeby (e.g. geth --rinkeby --syncmode "light") or use a third-party node provider such as Infura. You must also create a wallet and then obtain funds via the Rinkeby Faucet.

Install Node.js

(In case you don't have Node.js) There are a few ways to install Node.js. If you work on multiple JavaScript or TypeScript projects which require different node versions, using nvm may be suitable.

  • nvm (node version manager)
    • macOS: If you use Homebrew, run brew install nvm and you'll see some additional instructions. Follow it and nvm install node and nvm use node.
    • others: Refer to nvm site.
  • Install independently
    • macOS: If you use Homebrew, run brew install node
    • Ubuntu: sudo apt-get install nodejs npm

Then you should be able to use npm. To install ganache-cli, run npm install -g ganache-cli.

Redis

The Interledger.rs nodes and settlement engines currently use Redis to store their data (SQL database support coming soon!). Nodes and settlement engines can use different Redis instances.

  • Compile and install from the source code
  • Install using package managers
    • Ubuntu: run sudo apt-get install redis-server
    • macOS: If you use Homebrew, run brew install redis

Make sure your Redis is empty. You could run redis-cli flushall to clear all the data.

Instructions

1. Build interledger.rs

First of all, let's build interledger.rs. (This may take a couple of minutes)

cargo build --all-features --bin ilp-node

2. Launch Redis

# Create the logs directory if it doesn't already exist
mkdir -p logs

# Start Redis
redis-server --port 6379 &> logs/redis-a-node.log &
redis-server --port 6380 &> logs/redis-a-se.log &
redis-server --port 6381 &> logs/redis-b-node.log &
redis-server --port 6382 &> logs/redis-b-se.log &

To remove all the data in Redis, you might additionally perform:

for port in `seq 6379 6382`; do
    redis-cli -p $port flushall
done

When you want to watch logs, use the tail command. You can use the command like: tail -f logs/redis-a-node.log

3. Launch Ganache

This will launch an Ethereum testnet with 10 prefunded accounts. The mnemonic is used because we want to know the keys we'll use for Alice and Bob (otherwise they are randomized).

ganache-cli -m "abstract vacuum mammal awkward pudding scene penalty purchase dinner depart evoke puzzle" -i 1 &> logs/ganache.log &

4. Launch Settlement Engines

Because each node needs its own settlement engine, we need to launch both a settlement engine for Alice's node and another settlement engine for Bob's node.

Note: The engines are part of a separate repository so you have to clone and install them according to the instructions

# Turn on debug logging for all of the interledger.rs components
export RUST_LOG=interledger=debug
git clone https://github.com/interledger-rs/settlement-engines
cd settlement-engines

# Start Alice's settlement engine
cargo run --features "ethereum" -- ethereum-ledger \
--private_key 380eb0f3d505f087e438eca80bc4df9a7faa24f868e69fc0440261a0fc0567dc \
--confirmations 0 \
--poll_frequency 1000 \
--ethereum_url http://127.0.0.1:8545 \
--connector_url http://127.0.0.1:7771 \
--redis_url redis://127.0.0.1:6380/ \
--settlement_api_bind_address 127.0.0.1:3000 \
&> logs/node-alice-settlement-engine.log &

# Start Bob's settlement engine
cargo run --features "ethereum" -- ethereum-ledger \
--private_key cc96601bc52293b53c4736a12af9130abf347669b3813f9ec4cafdf6991b087e \
--confirmations 0 \
--poll_frequency 1000 \
--ethereum_url http://127.0.0.1:8545 \
--connector_url http://127.0.0.1:8771 \
--redis_url redis://127.0.0.1:6382/ \
--settlement_api_bind_address 127.0.0.1:3001 \
&> logs/node-bob-settlement-engine.log &

cd ..

5. Launch 2 Nodes

# Start Alice's node
ILP_ADDRESS=example.alice \
ILP_SECRET_SEED=8852500887504328225458511465394229327394647958135038836332350604 \
ILP_ADMIN_AUTH_TOKEN=hi_alice \
ILP_REDIS_URL=redis://127.0.0.1:6379/ \
ILP_HTTP_BIND_ADDRESS=127.0.0.1:7770 \
ILP_SETTLEMENT_API_BIND_ADDRESS=127.0.0.1:7771 \
cargo run --all-features --bin ilp-node &> logs/node-alice.log &

# Start Bob's node
ILP_ADDRESS=example.bob \
ILP_SECRET_SEED=1604966725982139900555208458637022875563691455429373719368053354 \
ILP_ADMIN_AUTH_TOKEN=hi_bob \
ILP_REDIS_URL=redis://127.0.0.1:6381/ \
ILP_HTTP_BIND_ADDRESS=127.0.0.1:8770 \
ILP_SETTLEMENT_API_BIND_ADDRESS=127.0.0.1:8771 \
cargo run --all-features --bin ilp-node &> logs/node-bob.log &

6. Configure the Nodes

# This alias makes our CLI invocations more natural
alias ilp-cli="cargo run --quiet --bin ilp-cli --"

export ILP_CLI_API_AUTH=hi_alice
# Adding settlement accounts should be done at the same time because it checks each other

printf "Adding Alice's account...\n"
ilp-cli accounts create alice \
    --ilp-address example.alice \
    --asset-code ETH \
    --asset-scale 18 \
    --max-packet-amount 100 \
    --ilp-over-http-incoming-token in_alice \
    --ilp-over-http-url http://localhost:7770/ilp \
    --settle-to 0 > logs/account-alice-alice.log

printf "Adding Bob's Account...\n"
ilp-cli --node http://localhost:8770 accounts create bob \
    --auth hi_bob \
    --ilp-address example.bob \
    --asset-code ETH \
    --asset-scale 18 \
    --max-packet-amount 100 \
    --ilp-over-http-incoming-token in_bob \
    --ilp-over-http-url http://localhost:8770/ilp \
    --settle-to 0 > logs/account-bob-bob.log

printf "Adding Bob's account on Alice's node...\n"
ilp-cli accounts create bob \
    --ilp-address example.bob \
    --asset-code ETH \
    --asset-scale 18 \
    --max-packet-amount 100 \
    --settlement-engine-url http://localhost:3000 \
    --ilp-over-http-incoming-token bob_password \
    --ilp-over-http-outgoing-token alice:alice_password \
    --ilp-over-http-url http://localhost:8770/ilp \
    --settle-threshold 500 \
    --min-balance -1000 \
    --settle-to 0 \
    --routing-relation Peer > logs/account-alice-bob.log &

printf "Adding Alice's account on Bob's node...\n"
ilp-cli --node http://localhost:8770 accounts create alice \
    --auth hi_bob \
    --ilp-address example.alice \
    --asset-code ETH \
    --asset-scale 18 \
    --max-packet-amount 100 \
    --settlement-engine-url http://localhost:3000 \
    --ilp-over-http-incoming-token alice_password \
    --ilp-over-http-outgoing-token bob:bob_password \
    --ilp-over-http-url http://localhost:7770/ilp \
    --settle-threshold 500 \
    --settle-to 0 \
    --routing-relation Peer > logs/account-bob-alice.log &

sleep 2

Now two nodes and its settlement engines are set and accounts for each node are also set up.

Notice how we use Alice's settlement engine endpoint while registering Bob. This means that whenever Alice interacts with Bob's account, she'll use that Settlement Engine.

The settle_threshold and settle_to parameters control when settlements are triggered. The node will send a settlement when an account's balance reaches the settle_threshold, and it will settle for balance - settle_to.

7. Sending a Payment

The following script sends a payment from Alice to Bob.

ilp-cli pay alice --auth in_alice \
    --amount 500 \
    --to http://localhost:8770/accounts/bob/spsp

8. Check Balances

printf "\nAlice's balance on Alice's node: "
ilp-cli accounts balance alice

printf "\nBob's balance on Alice's node: "
ilp-cli accounts balance bob

printf "\nAlice's balance on Bob's node: "
ilp-cli --node http://localhost:8770 accounts balance alice \
    --auth alice:alice_password

printf "\nBob's balance on Bob's node: "
ilp-cli --node http://localhost:8770 accounts balance bob \
    --auth bob:in_bob

9. Kill All the Services

Finally, you can stop all the services as follows:

for port in `seq 6379 6382`; do
    if lsof -Pi :${port} -sTCP:LISTEN -t >/dev/null ; then
        redis-cli -p ${port} shutdown
    fi
done

if [ -f dump.rdb ] ; then
    rm -f dump.rdb
fi

for port in 8545 7770 8770 3000 3001; do
    if lsof -tPi :${port} >/dev/null ; then
        kill `lsof -tPi :${port}`
    fi
done

If you are using Docker, try the following.

# Depending on your OS, you might not need to prefix with `sudo` necessarily.
sudo docker stop \
    interledger-rs-node_a \
    interledger-rs-node_b \
    interledger-rs-se_a \
    interledger-rs-se_b \
    ganache \
    redis-alice_node \
    redis-alice_se \
    redis-bob_node \
    redis-bob_se

Advanced

Check the Settlement Block Generation

To check whether the settlement block is generated, we use geth. geth is the abbreviation of go-ethereum which is an Ethereum client written in the go language. If you don't already have geth, refer to the following.

  • Compile and install from the source code
  • Install using package managers
    • Ubuntu: Follow the instructions here.
    • macOS: If you use Homebrew, run brew tap ethereum/ethereum and brew install ethereum. Details are found here.
    • others: Refer to Building Ethereum page.

Then dump transaction logs as follows. You will see generated block information. Be aware that ganache takes 10 to 20 seconds to generate a block. So you will have to wait for it before you check with geth.

printf "Last block: "
geth --exec "eth.getTransaction(eth.getBlock(eth.blockNumber-1).transactions[0])" attach http://localhost:8545 2>/dev/null
printf "\nCurrent block: "
geth --exec "eth.getTransaction(eth.getBlock(eth.blockNumber).transactions[0])" attach http://localhost:8545 2>/dev/null

If you inspect ganache-cli's output, you will notice that the block number has increased as a result of the settlement executions as well.

Troubleshooting

# When installing ganache-cli
gyp ERR! find Python Python is not set from command line or npm configuration
gyp ERR! find Python Python is not set from environment variable PYTHON
gyp ERR! find Python checking if "python" can be used
gyp ERR! find Python - executable path is "/Users/xxxx/anaconda3/bin/python"
gyp ERR! find Python - version is "3.6.2"
gyp ERR! find Python - version is 3.6.2 - should be >=2.6.0 <3.0.0
gyp ERR! find Python - THIS VERSION OF PYTHON IS NOT SUPPORTED
gyp ERR! find Python checking if "python2" can be used
gyp ERR! find Python - "python2" is not in PATH or produced an error

If you see an error like the above, you have to install Python 2.7.

# When installing Node.js with apt-get
E: Unable to locate package nodejs
E: Unable to locate package npm

Try sudo apt-get update.

# When you try run-md.sh
Fatal: Failed to start the JavaScript console: api modules: Post http://localhost:8545: context deadline exceeded

It seems that you failed to install ganache-cli. Try to install it.

# When running with Docker
Error starting userland proxy: listen tcp 0.0.0.0:6379: bind: address already in use.

You might have run another example. Stop them first and try again. How to stop the services is written in each example page.

Conclusion

This example showed an SPSP payment sent between two Interledger.rs nodes that settled using on-ledger Ethereum transactions.

Check out the other examples for more complex demos that show other features of Interledger, including multi-hop routing and cross-currency payments.