Statechains

Disclaimer This section can be bypassed if the reader understands statechains, which are used as a building block for what follows. This section provides a high-level overview of how statechains work. Please note that the description here is intentionally simplified and may not be entirely accurate; its purpose is to convey the core functionality of statechains in an accessible manner.

Statechains are a way to transfer ownership of a UTXO off-chain. In this example, all key signing operations are performed with Schnorr.

First, begin with the assumption that keys can be linearly added together to form a single key. We will start with two parties holding keys - one is the user Alice (A), and the other will be called the statechain entity (SE), which can be composed of any number of members but will be shown as a single entity below.

(SE+A=Key1)(SE+A=Key1)

Each key is represented as a large random number. In this example, SE’s key is represented by the value 100, and A’s key is represented by the value 50.

(100+50=150=Key1)(100+50=150=Key1)

Now assume that a signature is simply multiplying the key by the hash of some object. The hash will also be represented by a number. In this example, our hash will be represented by the value 2. Thus, a signature of this hash will be:

((100+50)2=300)((100+50)*2=300)

To deposit funds into the statechain, Alice first creates a transaction to send money to a joint address controlled by the SE and herself (using their combined key of 150). However, she doesn’t broadcast this transaction immediately. Instead, Alice and the SE collaborate to create and sign an exit transaction. This exit transaction is designed to transfer the coins directly to Alice, but it is locked with an absolute timelock set to an arbitrary amount of blocks in the future. Once Alice has the signed exit transaction in her possession, she then broadcasts the original deposit transaction. This creates a UTXO with a spending condition that requires the combined signature of SE and Alice. This careful sequencing ensures that Alice always has the ability to exit the statechain at any moment, even before the deposit is confirmed. This setup forms the foundation of the statechain mechanism.

Alice now wishes to transfer ownership of this UTXO to Bob (B), but she wants to do so without putting the transaction on-chain. Bob’s randomly generated key is represented by the number 40. He then calculates that the difference between his key and Alice’s key is 10 (50 - 40 = 10). For Bob plus the SE to sign using the same value as Alice+SE (150), the SE needs to tweak their key by 10. So, the SE discards the old key (100) and only keeps a copy of the newly tweaked key 110 (100 + 10 = 110). Now, SE+Bob still equals 150 (110 + 40 = 150), so the UTXO can be spent by signing using the combined 150. This meets the original spending condition of the UTXO. Alice can’t sign a new transaction anymore because the SE discarded the 100 key. If Alice tried to sign, Alice+SE would now equal 160 (50 + 110 = 160), which isn’t a valid key to sign the transaction. This process effectively transfers control of the UTXO from Alice to Bob without requiring an on-chain transaction.

During the key handoff process, the new owner collaborates with the SE to create and sign a new exit transaction. This new exit transaction features a lower timelock compared to the previous owner’s exit transaction. For instance, if Alice’s original exit transaction had a timelock of 100 blocks, Bob (the new owner) might set his timelock to 90 blocks. This process of decreasing timelocks continues with each subsequent transfer. When Bob transfers to Carol, her exit transaction might have a timelock of 80 blocks, and when Carol transfers to Dave, his could be set to 70 blocks. This decreasing timelock pattern ensures that the most recent owner always has the earliest opportunity to claim the UTXO on-chain. It’s important to note that these exit transactions can only be executed on-chain once their respective timelocks expire. This mechanism provides a safeguard, allowing the current owner to claim the funds before any previous owners, while still maintaining the off-chain nature of the transfers until necessary.

It’s important to understand that this mechanism imposes a time limit on how long a UTXO can remain within a statechain. The current owner must claim the funds on-chain before the absolute timelock expires. If they fail to do so, previous owners will have the opportunity to claim the UTXO on-chain. This time constraint prevents indefinite off-chain existence of UTXOs in vanilla Statechains.

Timelocks

Timelocks on Bitcoin can either be absolute or relative. An absolute timelock specifies a block height after which a transaction can be broadcasted. A relative timelock specifies a number of blocks after the parent transaction is included in a block before the child transaction can be broadcasted.

The diagram below shows how statechains typically work:

In the above diagram, transactions 1 through 3 are all held off-chain. They all spend the same output from Txn0 and are replacements for each other. They use decreasing timelocks such that Txn4 can be put on-chain prior to Txn3, which could be put on-chain prior to Txn2. In this way, when ownership of the key controlling the funds is transferred to a new user, they can check the prior transactions and be assured that they can publish their new transaction first. These timelocks create a timebomb where the off-chain transaction with the lowest timelock will need to be put on-chain when its timelock expires, otherwise there is a risk that other transactions can claim the funds.

This can, however, be eliminated by the following flow:

Txn1 spends the output of Txn0. Txn1 has no timelock. When users transfer keys, they transfer ownership of the key that encumbers the output of Txn1. The transactions that spend from Txn1’s output look like the normal statechain transactions that include decreasing timelocks relative to their parent transaction. But because Txn1 is held off-chain, there is no absolute timebomb.

The obvious problem with this is that if someone double-spends the output consumed by Txn1, then all of the leaves (Txn2..4) become invalid. To avoid this, the “SE” key is deleted by the SE - resulting in only one transaction ever generated for Txn0’s output. The exact mechanics of this will be discussed later.

Splitting a Leaf

We split leaves to spend smaller denominations. We do so by constructing a Bitcoin transaction that takes the parent UTXO as an input and produces multiple outputs, each controlled by a new key, which is split off from the original key. The sum of the new keys in all branches equals the original key, this allows for re-aggregation of leaves and more flexible leaf management without on-chain transactions.

To split a leaf in Spark, we need to split its existing key into multiple keys such that the sum of the new keys equals the original key. This can be represented as follows:

Original key: (a0=150)(a_0=150)

Split into two keys: (a1=100)(a_1=100) (a2=50)(a_2=50)

Ensuring (a0=a1+a2)(a_0= a_1+a_2)

If the parent leaf is encumbered by the spending condition of (a0)(a_0) it can then alternatively be spent using (a1+a2)(a_1+a_2) as they sum up to (a0)(a_0)

We want to ensure the following:

(PrivKeyUser_Old+PrivKeySE_Old=i=1n(PrivKeyUseri+PrivKeySEi))(\text{PrivKey}_{\text{User\_Old}} + \text{PrivKey}_{\text{SE\_Old}} = \sum_{i=1}^{n} \left( \text{PrivKey}_{\text{User}_i} + \text{PrivKey}_{\text{SE}_i} \right))

  1. User Key Splitting

    • Generate (n)(n) new user private keys
    • Calculate the difference (t)(t) between old and new keys: (t=PrivKeyUser_Oldi=1nPrivKeyUseri)(t = \text{PrivKey}_{\text{User\_Old}} - \sum_{i=1}^{n} \text{PrivKey}_{\text{User}_i})
  2. SE Key Splitting

    • Calculate the new SE key sum: (PSE_New=PSE_Old+t)(P_{\text{SE\_New}} = P_{\text{SE\_Old}} + t)
    • Generate (n1)(n-1) randomly generated SE private keys.
    • Calculate the final SE key to satisfy the key sum equality: (PSE_New_n=PSE_Old+ti=1n1PSE_New_i)(P_{\text{SE\_New\_n}} = P_{\text{SE\_Old}} + t - \sum_{i=1}^{n-1} P_{\text{SE\_New\_i}})
  3. Branch Transaction Creation

    • Create transaction with (i)(i) outputs, each locked by a new combined public key (SEn+Un)(\text{SE}_n+\text{U}_n)
  4. Intermediate Branch and Exit Transactions for Each Leaf

    • Create and sign intermediate branch and exit transactions for each new leaf using the new keys
  5. Key Deletion

    • Securely delete original private keys
  6. Finalization

    • Store the branch transaction off-chain.
    • Record the new leaves for use within Spark.

Spark Tree

A Spark tree is made up of both Leaf-Transactions as well as Branch-Transactions.

We extend a UTXO within Spark into branches and leaves. Txn0 is spent by Txn1, which is held off-chain. Txn1 is the first branch transaction. As mentioned above, the absolute timelock timebombs are removed from the tree.

Aggregation

When a transaction branches, the key that controls the parent input is divided into multiple child keys. These child keys are created in such a way that their sum equals the parent key. For example, Txn1 could be replaced by a new transaction, which would be valid if it’s signed using the combined (aggregated) signatures from all the child keys at the bottom of the tree. In other words, the following keys, when aggregated, can spend Txn1:

((B0.1.1.1.1+SE0.1.1.1.1)+(B0.1.2.1.1+SE0.1.2.1.1)+(B0.2.1.1.1+SE0.2.1.1.1)+(B0.2.2.1.1+SE0.2.2.1.1))( (B_{0.1.1.1.1} + SE_{0.1.1.1.1}) + (B_{0.1.2.1.1} + SE_{0.1.2.1.1}) + (B_{0.2.1.1.1} + SE_{0.2.1.1.1}) + (B_{0.2.2.1.1} + SE_{0.2.2.1.1}) )

Which is equivalent to all the following:

(B0+SE0)(B_0 + SE_0)

(B0.1+SE0.1+B0.2+SE0.2)(B_{0.1} + SE_{0.1} + B_{0.2} + SE_{0.2})

(B0.1.1+SE0.1.1+B0.1.2+SE0.1.2+B0.2.1+SE0.2.1+B0.2.2+SE0.2.2)(B_{0.1.1} + SE_{0.1.1} + B_{0.1.2} + SE_{0.1.2} + B_{0.2.1} + SE_{0.2.1} + B_{0.2.2} + SE_{0.2.2})

((B0.1.1.1+SE0.1.1.1)+(B0.1.2.1+SE0.1.2.1)+(B0.2.1.1+SE0.2.1.1)+(B0.2.2.1+SE0.2.2.1))((B_{0.1.1.1} + SE_{0.1.1.1}) + (B_{0.1.2.1} + SE_{0.1.2.1}) + (B_{0.2.1.1} + SE_{0.2.1.1}) + (B_{0.2.2.1} + SE_{0.2.2.1}))