Skip to content

Instantly share code, notes, and snippets.

@homakov
Last active March 20, 2021 01:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save homakov/0b47f4ce7bdf9afc125db5aa66a45dbe to your computer and use it in GitHub Desktop.
Save homakov/0b47f4ce7bdf9afc125db5aa66a45dbe to your computer and use it in GitHub Desktop.
XLN channel lifecycle

Alice puts assets in channel

Alice downloads XLN wallet. After logging in with passphrase/mnemonic, it shows a list of hubs (downloaded from public hubs contract array), along with various metrics and data: name, total collateral locked around the hub, gasused (the most reliable one) etc.

Alice chooses Hub and sets up a channel offchain and adds asset_id=0,1 (weth/dai). Both parties sign off on a dispute proof

dispute_nonce=1
entries=[
[0,0], //asset_id, offdelta
[1,0]
]

Now Alice can deposit tokens to XLN contract (invoking TokenToReserve). Reserve is an intermediary balance, so in one batched tx Alice does TokenToReserve and ReserveToChannel(Alice, Hub, asset_id=0, amount=100).

ReserveToChannel deducts 100 from reserve[alice][0] and increases collaterals[alice_hub][0].collateral+=100 Let's assume Alice's address is lower than Hub's, meaning Alice is Left and Hub is Right.

When we deposit/withdraw on behalf of Left user, ondelta must be changed too (https://github.com/homakov/xlncontracts/blob/main/contracts/xln.sol#L243)

At any time, channel state can be expressed in just two numbers: (uint) collateral (stored onchain) and (int) delta = ondelta + offdelta. Think of collateral as a sausage and delta as a knife location. If delta is below 0, the right user gets the full sausage and a debt. And vice-versa from the other side.

Delta explains how the channel is "split" when dispute happens.

Bob wants to receive a payment

In order for someone to receive a payment they also download XLN wallet and choose a hub. However unlike LN, in XLN a user has to "extend credit line" to the hub. Credit line defines the maximum uncovered balance wallet allows hub to promise. Let's say Bob sets credit to 200 and autorebalance=100.

They also exchange empty dispute_proofs with nonce=1 to initialize the channel offchain.

Alice sends a $10 payment Alice->Hub

Current state of the system: Alice has $100 (all covered) with Hub, Bob has $0 and opened a $200 credit line i.e. can receive up to $200 (inbound capacity)

(Skipping complexity of HTLC atomic payments) She updates and signs off on a new dispute proof:

dispute_nonce=2
entries=[
[0,-10], //asset_id, offdelta
[1,0]
]

The offdelta for asset_id=0 has been decreased, effectively making delta=100 - 10 = 90 which means if either Hub or Alice will go to dispute with it, the onchain contract will split collateral giving left user (Hub) 10 and right user 90.

Hub mediates payment to Bob

Hub does the same, however let's assume in Hub-Bob channel Hub is the Right user and has higher address. It would result in dispute_proof:

dispute_nonce=2
entries=[
[0,10], //asset_id, offdelta
[1,0]
]

In the wallet UI Alice currently sees balance $90 (covered), the other $10 now belong to hub. Bob sees balance $10 (uncovered).

Bob is currently powerless and cannot do any onchain disputes with Hubs. However if someone refills Bob's EOA, he can go onchain with latest dispute_proof and enforce this uncovered balance against Hub's identity and reserves

Rebalancing

Once we repeat this procedure 9 more times, Bob's uncovered balance reaches $100, which is above previously set autorebalance limit. It means Bob's wallet asks the hub to provide collateral as the risk gets too high.

Hub asks Alice offchain for a WithdrawalProof (otherwise starts a dispute), and in a single batch transaction withdraws $100 from Alice-Hub channel to its reserve balance and puts $100 from reserve to newly created collaterals[Bob-Hub][0]+=100.

This transaction instantly turns all uncovered .----------| risky balance of Bob into covered .==========|

Covered assets have almost same security properties as onchain balance (with being online caveats).

Uncovered assets are protected by the identity of the hub. The hub cannot selectively censor a specific user, but can exit scam and all uncovered assets are lost. That's why credit_limit and autorebalance exist, to reduce the risk while keeping the system working with no payments failing. Inbound capacity is solved by a temporary credit buffer from users to hubs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment