Adieu, State Channels

Stoyan Dimitrov
Eco Engineering
Published in
5 min readJan 7, 2022
State Channels (Photo by Wendy Scofield on Unsplash)

At Eco, our goal of building a decentralized payments system lead us to use the only blockchain at the time that was both mature enough and had a large developer community, ethereum. A payments system in our view is comprised of a low-volatility currency, together with an identity, reputation and transaction platform. We knew that we would have to solve some challenges that choosing etherum’s chain would create.

The main challenge that our team would be responsible for solving would be transaction throughput of the chain itself. In order to build a truly useful payments systems, we need to be able to transact at much higher rates than the current ~15tx/sec that the ethereum chain provides. For comparison, Visa¹ runs at ~2000tx/sec, and ethereum’s 15tx/sec² is shared across all applications running on it in the world. When we started tackling our scalability problem, one of the more popular solutions being explored by the blockchain community was state channels. So we decided to implement a state channel solution of our own. In this article we will go over our implementation and explain why, in the end, we abandoned the idea that ethereum could ever be scaled for a payments network with state channels.

State Channels

State channels³ are a process of off-chain transacting with funds lockup that allow participating parties to make payments to each other through a process of off-chain receipt exchange, without having to deal with ethereum’s slow transaction rate. When transacting using state channels, the following steps are carried out in the given order:

  1. on-chain fund locking,
  2. off-chain exchange
  3. on-chain settlement

First, the two transacting parties together fund a smart contract, locking their funds into a blockchain controlled escrow. Each party is then given a signed receipt displaying the percentage of the deposit that belongs to them, along with the receipt number, which is initially 0. Whenever one of the parties wants to make a transaction, they send the other party a signed receipt communicating the desired updated balance for the contract, with an incremented receipt number. The second party then accepts the new balance by signing the receipt with its own key. These receipts are passed and signed off-chain via client software run by both parties. This step can be carried out multiple times, and is what gives state channels their scalability properties, since no on-chain interactions are required by this step. Finally, when either party wants to redeem their balance from the contract, they publish their most recent receipt to the smart contract on the blockchain.

Building State Channels

We decided to build on this basic state channel design. We figured that we would need code on-chain to manage fund lockups and unlocks and some code off-chain nodes that would deal with sending and signing receipts. One of the more challenging aspects proved to be the synchronization of off-chain and on-chain state, with fraud detection being a key issue.

Having to deal with only one system, the Ethereum Virtual Machine, the scope that the code had to manage became just the channels that held locked up funds. We expected the development of the on-chain code to be the easier part. However, since the tools for solidity development are still under development, they frequently broke, crashed, or forced us to create work-arounds that lengthened the development process. Solidity for instance has an arbitrary restriction on the number of arguments a function can take, or the number of stack variables that can be declared in a function. These types of “features” sometimes make it difficult/impossible to use best programming practices compared to other language environments.

Writing the on-chain portion of state channels, while unnecessarily tedious, proved to take far less time than getting anything to properly interact with the ethereum chain. It turns out that interacting with the ethereum chain is quite different from interacting with centralized servers. In order to communicate with an ethereum contract, it is first necessary to define an interface for writing messages to call functions on that contract, and then run a full ethereum geth node to send and process those messages. In addition, since ethereum is an availability and partition resistant blockchain (AP from CAP Theorem⁴), we cannot assume a transaction is part of the chain; instead we need to continually check the state of the blockchain, and assume statistically that after some period of time has passed, our transaction is final. This problem is generally referred to as statistical finality, and it complicates any touch-point between the user and the blockchain.

In order to deal with the statistical finality of ethereum, we had to develop monitoring services whose sole purpose was to check on the state of the on-chain state channels and notify the off-chain nodes if relevant events were detected. Since even these events where themselves only statistically final, we have to constantly freeze transactions on channels until the channels state becomes sufficiently final for us to act on.

While we managed to grind through all of the pain-points of building a state channel implementation on top of ethereum, we did not end up deploying it. Our initial plan had been to use our state channels implementation as part of a hub and spoke payments network. However, given that in such a network each hub operator is acting as a money transmitter, and thus needs to obtain all the money transmitter licenses required by the regulatory authorities, we decided in the end it was not feasible to continue with this approach.

Where we go from here

While we learned a lot from working on ethereum in building out our state channels solution, we have had to bury it and move on. We are open sourcing our work so that others can benefit from our work on here and here. While state channels do not seem like they can be used for a payments network, they might be suitable for other purposes. We are now looking at blockchains that have scalability already built in, as our experience of trying to scale a chain off-chain proved to be the wrong way to scale a blockchain. We expect a lot the community to come to understand this and move towards not only high transaction blockchains, but blockchains based on proof of stake or other consistency and partition tolerant, CP, consensus algorithms. These newer blockchains can be used to implement the volatility stabilization logic of our currency as well as an identity and reputation system all at scale natively without the need of layer 2 scaling solutions.

--

--