Virtual channels not only enable new application scenarios such as paid file streaming, but also simplify application scenarios such as decentralized Graph query payment and Filecoin content retrieval.
Original title: “Science | How to Use Virtual Channels to Create State Channel Networks”
Written by Mike Kerzhner, Andrew Stewart
Translation & Proofreading: Min Min & A Jian
In this article, we introduced a new state channel structure called virtual channel . The virtual channel not only makes new application scenarios such as paid file streaming (click here to view the demo!) possible, but also simplifies the decentralized Graph query payment, Filecoin content retrieval, and the state provider network with economic incentive mechanism. Application scenarios.
🥕 motivation
Let us design a trust-free paid file streaming payment system. There are seeder (file uploader) and leecher (file downloader) in this system. Leecher pays to download different parts of a file from multiple seeders. It is impossible to use Ethereum mainnet transactions to pay fees, because the throughput of the Ethereum mainnet is lower than 50 transactions per second, and (as of the time of publication on May 28) the minimum transfer cost is also more than $2. Optimistic Rollup and ZK Rollup can increase throughput and reduce transaction costs. StarkEx’s ZK Rollup can increase throughput to 3000 transactions per second while reducing the cost of each transaction to $0.03. Assuming that leecher is willing to pay $1 to download a 1GB file, and the entire file is divided into multiple parts in 256 KB units, leecher needs to pay about 5000 fees. When the network speed is 20MB/s, the user pays 80 times per second, and each fee is 0.0002 US dollars. Rollup’s throughput cannot meet many leaker requirements, and transaction costs are still too high.
In order to meet transaction throughput and cost requirements, the basic state channel is a good choice. After the state channel is created, leecher can make multiple small payments for free, and the throughput is only affected by the bandwidth of the communication channel between leecher and seeder and the hardware used by the two. The challenge brought by the basic state channel is that leecher needs to submit a transaction to the mainnet and establish a state channel with every seeder who has the part of the file he needs. Since leecher and multiple seeders need to interact briefly, the cost of creating multiple state channels is extremely expensive.
Virtual channels can perfectly solve our design problems. Virtual channels are especially suitable for hub and spoke topology. Multiple participants first establish a connection with a trust-free intermediary, and then any two (or more) participants create a private channel through pledge. The intermediary does not know what application is running in the private channel. In addition, any participant can initiate an on-chain challenge to retrieve his own funds, even if other participants and intermediaries in the channel are offline or commit malicious acts.
Connect all parties through a virtual channel
In general, as long as there is a path through the middle party between Alice and Bob, no matter what the network topology is, the virtual channel allows Alice to open a private channel with Bob.
📚 background knowledge
Different blockchain ecosystems treat state channels as a way that allows a small number of participants to:
Establish an on-chain connection (channel) and deposit funds;
Exchange information privately and conditionally transfer funds between participants;
The method of closing the channel on the chain to complete the settlement of funds between all parties
We have previously posted on the statechannels.org website to introduce how to build a state channel (Chinese translation), and how to use an architecture called a ledger channel to allow one state channel to fund another state channel. These architectures require channel participants to establish direct connections on the chain. In other words, if Alice and Bob have never interacted before and now want to open a state channel, they must sign an (off-chain) agreement and deposit funds into the contract.
But the virtual state channel can realize the following application scenarios:
Alice creates a state channel with a trust- free intermediary. Suppose this middle party is called Irene.
Same as above for Bob.
With the help of Irene and the created channel, Alice and Bob can create a new private channel and deposit funds. The creation of this private channel does not require on-chain interaction. We call the channel between Alice and Bob a virtual channel.
As far as the application scenario of paid file streaming is concerned, Alice first needs to create a channel with the intermediary Irene through the main network transaction. Then, she can connect to any number of peer nodes in a virtual way, as long as there is an on-chain channel between the latter and Irene. Once the connection is successful, Alice can continue to pay the data download fee.
Our protocol Nitro can realize the following application scenarios:
Irene, the intermediary who helped Alice and Bob create the virtual channel, is actually not in the virtual channel. Irene just helps to create the channel and settle the funds when the channel is closed. Therefore, Alice and Bob can communicate completely privately and exclude Irene from the critical path of this application. More importantly, Alice and Bob can run multiple different applications in the private channel without Irene implementing any new logic for these applications. Therefore, a virtual channel is a universally programmable multi-hop state channel (just like Ethereum gives blockchain programmability), because each state channel can be created according to its own set of “rules”. Alice can pay Bob to purchase the content of a certain file. Bob can also pay Alice to perform Graph queries.
All Nitro channels are combinable. Therefore, the channel that obtains funds can provide funds to other channels in a recursive manner, no matter how the former obtains funds. Once a channel (directly through on-chain contracts, ledger channels, or virtual financing) obtains funds, it can run any application or provide funds for other channels.
🎨 Nitro alternative
Other protocols (such as Raiden) allow two participants to create a channel through an intermediary without depositing additional funds on the chain. A mature model is to use a hashed time lock to route Alice’s payment to Bob through an intermediary. This model has an obvious disadvantage: all payments must be routed through an intermediate party.
Some relatively novel architectures (such as Scalar) allow Alice and Bob to create a channel through an intermediary to realize peer-to-peer payment. However, these architectures still require intermediaries to understand the applications run by Alice and Bob, because the channel balance will eventually be retrieved through the intermediary. With the Nitro virtual channel, the middle party can be isolated outside the channel between Alice and Bob.
💰 Fund transfer within the channel
This article will introduce in depth how the Nitro channel obtains funds, and how the trust-free secure virtual channel is realized!
The Nitro channel between Alice and Bob is funded by:
Alice and Bob jointly sign an off-chain agreement to create a channel with a specific initial result.
Alice and Bob deposit funds in the order specified by the initial result, and increase the channel
holdings
recorded in the adjudicator contract on the chain.
The “result” here is a structure that instructs the arbiter on how to allocate funds when the channel is finalized (check our latest article!) In Nitro, the “result” lists the priority of {target, quantity} pairs:
{A: 7, B: 3}
Order the arbiter of channel C
to first pay 7 tokens to A
(Alice), then pay 3 tokens to B
(Bob), and return the result of C
to zero.
This is not accurate: we are actually assigning priorities to targets in the order of the keys in the dictionary. Therefore, {B: 3, A: 7}
will pay Bob first, and then it will be Alice’s turn. You can think of it as an ordered dictionary in Python 3.7+ style.
The above figure shows how Alice and Bob withdrew tokens from channel C based on the result {A: 7, B: 3}. According to the record of the arbiter on the chain, there are a total of 10 tokens in the channel. Alice or Bob records the channel results to the chain. After this result is recorded, Alice and Bob can withdraw the tokens. As a result, Alice’s external account adds 7 tokens, and Bob’s external account adds 3 tokens
Although the above results imply that the target is the user account (EOA), in Nitro, the channel itself can also be the target. In this way, channel L can also act as a “private ledger”, because Nitro can deposit funds into the ledger channel at once, and then provide funds for multiple sub-channels. Nitro avoids the need to go back to Layer 1, and the delays and costs that result! E.g:
Assuming that C2
is a Nitro channel, {A: 4, B: 1, C2: 5}
order the adjudicator to pay Alice 4 tokens, then pay 1 token to Bob, and then increase the token holdings of C2
5.
C1 is the ledger channel, C2 is the channel to obtain funds from the ledger channel
The above is a brief introduction. If you want to learn more about Nitro, please check out our related blog post!
🔒 How to use assurance to achieve a trust-free architecture
Next, we will introduce how to create a three-way channel through a secure architecture when the two participants have no on-chain relationship . This architecture not only allows the ledger channel to provide funds for other channels, but also enables virtual channels. The two participants are Alice (A) and Bob (B), and the middle party is Irene (I).
We first tried to use a channel to connect A, B, and I. Please note that this is not a trustless architecture
Initial setup: three independent channels
First, there must be a pair of ledger channels L
(between Alice and Irene) and L'
(between Bob and Irene). Normally, L
and L'
are created long ago. This is because the purpose of Irene’s existence is to establish connections between people-Alice can use L to connect Bob, Cheryl, David, and Eve at the same time. If L
and L'
do not exist, L
can be created with the result {A: 4, I: 6}
, and L'
can be created with the result {B: 6, I: 4}
. L
and L'
each store 10 tokens on the chain.
There is also an independent channel J
created using the result {A: 4, B: 6, I: 10}
. Please note that before depositing funds to the channel, participants must first reach a consensus on this result. Once J
funds, this channel can be used to fund any private application channel created between Alice and Bob.
Steps 1 and 2: The ledger channel is transformed to provide funds to J
Alice and Irene transformed the result of L
into {J: 10}
. Bob and Irene convert the result of L'
into {J: 10}
.
Is this design good enough?
Alice must consider the following points:
Are Bob and Irene credible?
Alice cannot control what happens on
L'
.
Let’s think about how to withdraw J
‘s funds after step 2.
The results of
L
andL'
are recorded on the chain.Both
L
andL'
s funds are transferred toJ
Tokens are transferred from one channel to another via a transfer operation.J
now has 20 tokens, which can be said to have sufficient funds.From Alice
J
removed four tokens, Bob has fromJ
removed in six tokens. Irene can take 10 tokens fromJ
Pretty! Now everyone has taken the tokens they deserved. But let’s imagine a scenario: Alice and Bob conspire to deceive Irene. Suppose that after step 1 occurs, Bob refuses to participate in step 2. Then the following will happen:
The result of
L
is recorded on the chain. Now,J
10 tokens, and the result recorded on the chain is{A: 4, B: 6, I: 10}
.Alice and Bob took away 4 and 6 tokens respectively.
Please note that Bob obtained 6 tokens from J
, even though he himself did not transfer tokens to J
at all. The result becomes: Alice gets 4 tokens, Bob gets 6 tokens, Irene has nothing. Irene was miserable!
You might think that if you change the order of the goals in the result {A: 4, B: 6, I: 10}
, you can create a safe architecture. However, no matter how you change the order, someone will always suffer!
How guarantees work
In the above scenario, we used a transfer operation to transfer funds between channels. Through the _transfer_ operation, funds can be transferred from one channel to the target channel. In this section, we will introduce a claim operation to transfer funds from the target channel to a specific target address1 . In order to achieve the _claim_ operation, we need_guarantee .
Let’s first introduce a new data structure. The guarantee is the result of specifying the following:
The goal, that is, a channel;
Quantity
Priority, that is, the priority list of goals. The priority is to instruct the arbiter how to change the priority of the result item of the target channel.
For the second time we try to use a channel to connect A, B, and I. This time it is already a trust-free architecture!
Let’s take a look at how J
gets funding:
Initial setup: Create three independent channels.
Channel
J
was created using the result{A: 4, B: 6, I: 10}
.L
was created using the result{A: 4, I: 6}
.L'
was created using the result{B: 6, I:4}
.
Steps 1 and 2: The ledger channel is transformed to provide funds to J
(in no particular order):
The result of
L
is updated to{J: {amount: 10, priorities: [A, I]}
. Please note that we have used a new notation to indicate that the result ofL
has only one item, that is, the guarantee that contains the targetJ
, the quantity, and the address priority list.The result of
L'
is{J: {amount: 10, priorities: [B, I]}
.
The results of L
and L'
each contain a _guarantee_. Since the transfer operation does not support these guarantees, we will request the operation instead. Request the operation acceptance guarantee and the guaranteed target channel as input.
Let’s take a look at how the request operation works. Hypothesis
The result of
J
{A: 4, B: 6, I: 10}
is recorded on the chain.L
s result{J: {amount: 10, priorities: [A, I]}}
is recorded on the chain.
If someone requests a guarantee in the result of executing L
, three effects will be triggered:
Send 4 tokens to
A
and 6 tokens toI
Because of (1), the balances of
A
andI
are adjusted to{B: 6, I: 4}
in the result ofJ
The result of
L
is adjusted to{}
-guaranteed to be deleted.
In this operation, the purpose of priority is to tell the arbiter to _skip_ the result item with B
so that Irene can get back the part of the funds she gave when creating L
Therefore, the adjudicator will first see the target A
with the highest priority in the guarantee, and transfer 4 tokens to A
, and the result of J
will be updated accordingly. Then, the adjudicator will see the target I
In J
‘s result, Irene should get 10 tokens, but this time (in L’s result) there are only 6 tokens left. Therefore, these 6 tokens were sent to Irene, and J
‘s results were updated again. Please note that the priority must be [A, I]
instead of [I, A]
. If the priority is [I, A]
, Irene will obtain 10 tokens through the claim operation, and Alice will lose the 4 tokens that originally belonged to her!
With the claim operation, Alice and Bob can no longer conspire to defraud Irene’s funds.
🌴The most ideal situation
You may have noticed that in order for Alice and them to retrieve the funds, a total of 3 operations on the chain are required: record the joint channel and the transfer result on the chain, and call the _claim_ operation. Please note that this is the worst case. Suppose that after Bob transfers 4 tokens to Alice, Alice and Bob want to close J
If Bob and Irene cooperate, then:
Alice, Bob, and Irene agreed to finalize
J
with the result{A: 8, B: 2, I: 10}
.Alice and Irene can update
L
and safely delete the guarantee for fundingJ
The result ofL
becomes{A: 8, I: 5}
.Now, Alice can use the tokens in
L
to fund other channels. Alice can also choose to withdraw funds.
All in all, in a collaborative case, Alice can use the funds in L
to provide funds for multiple different application channels, and can also withdraw funds from these without any on-chain transactions.
🥅Virtual channel
In the previous section, we have introduced how to create a three-party channel when the two participants do not have an on-chain relationship. Attentive readers should have noticed that updating J
must be signed by the intermediary. At the beginning of this article, we intend to create a private channel between A
and B
Fortunately, Nitro’s composability allows us to create a private application channel X
funded by J
The specific structure is shown in the figure below. You have mastered all the concepts needed to understand this architecture. However, if you have any questions, please ask us!
X is a virtual channel
⛵ Future plan
The virtual channel architecture introduced in this article is an evolution of the architecture introduced in the Nitro protocol paper. The most worth mentioning is that this architecture does not need to create a dedicated guarantor channel.
The Nitro virtual channel is about to introduce another update, eliminating the need for joint channels. With this update, ledger channels L
and L'
can provide funds for application channel X
This article was written by Mike Kerzhner and Andrew Stewart based on the Nitro Protocol by Tom Close. Thanks to Robert Drost, Joseph Chow, George Knee, and Colin Kennedy for their feedback.
Note
We can also understand the request operation as:
Transfer funds from L to J, changing the result of J.
Transfer funds from J to the target address.
If the result of the ledger channel is {J: {amount: 10, priorities: [A, I]}
and the result of J
is {A: 4, B: 6, I: 10}
, the request can be described as:
Transfer 10 tokens from
L
toJ
The result of
J
becomes{A: 4, I: 6, B: 6, I: 4}
Then call the transfer for
A
andI
onJ
Source link: blog.statechannels.org