Blockchain in Travel Industry — Part 5: State Channels Hands-on Tutorial

István Takács
TUI Blockchain Lab
Published in
6 min readApr 8, 2019

In this article we go through the process of making a state channel using the Ethereum blockchain step-by-step. The steps will be the three steps announced in the previous article, (I.) opening the state channel, (II.) making transactions and (III.) closing the state channel.

The smart contract is written in Solidity, the signing is made both in JavaScript and in Python. As development environment we will be using Remix for the smart contracts, which is accessible with any internet browser.
JavaScript and Python are both scripting languages, so you can use a normal text editor to write your code and then run it via the command line. I used Visual Studio Code for Python and I ran my JavaScript code in a browser, but that’s only my preference.

I. Opening the state channel

To open a state channel, we have to register the addresses of the participants and they have to lock the funds. The smart contract should be able to store multiple address pairs; these create the state channels. We cannot know how many address pairs we are going to have. The best way to store this dynamically changing data is with the help of mapping. As key we can use an integer variable, the more interesting thing is what the keys are pointing at. There is no built-in type for address pairs in Solidity, therefore we have to create our own structure. This structure should include the addresses, the amount the participants wish to lock in the contract and the time when the channel expires by all means.

After creating the data structure, the next step is to create a function that opens the channel. The easiest way is to use a “fallback“ function, which is executed when money is sent to the smart contract. This function must examine the address the money is sent from and check if it is in the mapping and if the given number is a valid key for the address in the mapping.

II. Making transactions

This part of the state channel’s life is happening off chain. How participants interact with each other and manage to agree is not part of this article. What I will demonstrate here, is what happens when we agree on a transaction, how we sign this message.
First let’s see it in Python!

As you can see web3 is imported. This is crucial, because it allows us to use functions like
“w3.eth.Account.signHash(message_hash, private_key=private_key)”
Which is basically the signing.
However, it is not enough to just sign the message, we have to prepare it for Solidity. In the last step — closing the state channel — we will want to recover the address of the signer and for this we need variables, such as “h”, “r”, “s” and “v”.
Where “h” is the hash of the message, “s” is the second half if the signed message, “r” is the first half of the signed message and “v” is either 27 of 28, whichever comes from the end of the signature.
The second half of the Python code is basically providing us these variables.
In the beginning the private key is hard coded, which is a high security risk in a productive environment, however, here in this tutorial I wanted to leave it there, to show the format of a private key.

The JavaScript code has a very similar logic, we also get the values of “h”, “r”, “s” and “v”. These values are of course the same as in Python.
The private key is provided to us by MetaMask, so it is important, that our function should by “async”, so it can wait for us to interact with MetaMask.

If you want to implement this JavaScript code in an html file and run it in your browser, it is worth mentioning that MetaMask won’t let you sign the message if you are simply opening the html file by “double click”.
Meta Mask will only sign the message, if you run it on a local http server. To do this, I used a simple http server with Python. This is easy to do in Linux. I’m using Fedora, here you only have to type “python -m SimpleHTTPServer” in the command line.

III. Closing the channel

Now that we have all the information required to sign the transaction, we should be able to close the channel.
This happens with the help of the smart contract, so now we switch back to Solidity.

When closing, there are three options.
III/A) Both of us uploaded the latest transaction. This is the optimal way to close a state channel, both of us agree on what should happen and we get our funds from the smart contract.

III/B) Only one of us wants to close the channel.
This is the most complex situation of the three, where we must prevent cheating of any kind. The message that we upload contains the state channel’s ID in the mapping, the amount the smart contract should send to one of the participants and the transaction ID, which shows us the sequence number of the transaction, we want to upload. For each transaction we signed off-chain, we have to increase the transaction ID by 1.
This way we can block the three types of attacks mentioned under “security considerations”.
To answer the above mentioned questions:

1) How can we guarantee that the transaction uploaded when closing the channel is really the last one?

We have to upload the transaction ID, which is the sequence number of the transaction. The smart contract won’t allow anyone to upload a transaction that has a lower transaction ID than the latest transaction one of us uploaded.

2) What happens if a participant leaves after we lock the funds?

When registering a new state channel, we have to include a “timeout” in the structure. We have to wait for this to pass, and after that, the smart contract will send the amount, the latest uploaded transaction included. If there was no transaction, the smart contract sends us back the exact funds we locked in when opening the channel.

3) Can it cause any harm if one of the signed messages gets stolen?

If someone stole my signed message, they would have no use for it, because the state channel’s ID from the mapping is required. This way my signed message can only be used in the state channel it was intended for.


III/C) None of us uploaded any transactions.
There is a method to prevent our funds being locked in the smart contract in this case. We have to set a maximum time for the state channel to be open. If it is over, we can just ask our funds to be sent back to us.

I hope after reading the articles, you have a deeper understanding on how state channels work and you won’t shy away from using an existing state channel or creating your own.

--

--