Introducing Brollup v2, Now Without The Trusted Setup.

9 min readJun 28, 2024


Last week, I introduced Brollups, a Bitcoin-native rollup design that works with a native Bitcoin peg and does not require any changes to the Bitcoin protocol. The design, however, generally relied on a trusted setup, requiring at least one member to act honestly.

With some clever design adjustments, I’ve found a way to eliminate the need for the trusted setup. And now, presenting the v2 design!

Brollup v2 introduces a new state channel design and eliminates the need for a trusted setup by making the global state statechannel-aware. The core idea is to execute payable conditions based on state updates rather than creating new VTXOs. This decouples finality from block production and ties it directly to state updates.

This is similar to the Lightning Network; however, Lightning operates in a 2-of-2 setting, where only the involved parties are aware of the channel’s state. The channel state remains private, with outsiders gaining limited information only in the event of a force closure.

The strategy involves making channel states publicly accessible to everyone at all times. By publicly exposing channel content and ensuring accessibility at the DA layer, the global state becomes aware of individual channel states. Implementing this for all channels enables our Bitcoin Virtual Machine to verify payments between specific channels and execute payable conditions accordingly.

While one might expect storing channel content in the DA to consume a significant number of bytes, this isn’t the case! Brollup v2 employs an efficient approach where the only overhead comes from an 8 vByte signature commitment s by the operator. All other channel content can be derived from the calldata field outlined in my earlier announcement.

We can already determine the sender (msg.sender) and receiver (as asserted in the contract logic), along with their respective channel locations. Our channel design also avoids non-deterministic variables like in-flight HTLCs or PTLCs, allowing the entire channel content to be derived from the calldata alone. The only additional overhead is the 8 vByte signature commitment s from the operator, given that the signature nonce R chosen by the operator is also deterministic. This is all there is!


Before delving into the channel specifics, let’s review the changes in the covenant setup.

The Default Tree— with 90 days-long expiry.

In contrast to the design described in my earlier announcement, Brollup v2 removes kdc.signers (top 64k accounts) from enforcing the covenant, thereby reducing interactivity. Now, only msg.senders and the operator enforce the covenant, and the tree expires in 90 days instead of one week.

As the covenant expires in 90 days, accounts must refresh their VTXOs by sending coins to themselves every 90 days; otherwise, their coins can be taken, in theory, by the operator.

When accounts refresh their coins, they send coins to themselves, thereby participating in the same covenant setup that they enforce. In this case, the covenant cannot be violated. It is entirely sufficient for msg.senders to enforce the covenant themselves; breaking a covenant involving their own coins would be self-defeating for an owner.

The Onboarding Tree — with 10 days-long expiry.

When an account initially onboards, they receive their VTXOs within an onboarding tree that expires in 10 days. In this case, the covenant enforcing these coins is bound by another sender. Therefore, the account must refresh these coins into the default tree, which they own and control.

channel:trigger -> channel:root

Brollup v2 makes it possible to establish a virtual channel from the VTXO. To enable this, a virtual UTXO is provided with two spending paths:

  1. The Channel path
    This is a 2-of-2 path used by both the operator and the owner to establish a virtual channel.
  2. The Claim path
    If the operator is uncooperative in setting up a channel, the owner can access coins from this path after the timeout.

Channel Design

Brollup channels are easy to reason about;

  • No revocation: Each new channel state overwrites the previous one with higher precedence.
  • No basepoints: It’s always the same key for to_self and to_operator. Keys are re-used without involving any point tweaking.
  • No assymetry: Channel state is symmetric, reproducible, and always descend from the channel root.
  • No middle-stages: No in-flight HTLCs or PTLCs. It is always about to_self and to_operator. Payments are linked through connectors.

Brollup channels operate as a 2-of-2 between to_self, which refers to the Brollup account itself, and to_operator. Both parties collaboratively sign state updates from the channel path to advance the channel state.

Unlike Lightning, Brollup channels do not use a revocation mechanism. Instead, each new channel state overwrites the previous one with higher precedence, rather than revoking it. This is similar to Eltoo; however, while Eltoo chains Bitcoin transactions together, we do not. A new channel state always descend from the channel root.

Brollup v2 utilizes a degrading relative timelock scheme to ensure that each new channel state has higher precedence than the previous one. By default, we use 64 degrading periods. The virtual channel output (channel:root) is a taptree with 64 leaves, where each tapleaf corresponds to a degrading period. Each period is a 2-of-2 between to_self and to_operator with a relative timelock, where the duration starts at 64 days and degrades by one with each subsequent period.

A user might choose to opt-in to more than 64 leaves, allowing the channel to accommodate more state updates throughout its lifetime. This comes with the tradeoff of increased waiting time in the event of unilateral closure, however, multiple layers of timelocks also serve as a means to provide everyone with a fair guarantee of unilateral exit in a mass-exit scenario, so this isn’t quite really a tradeoff. As for the on-chain footprint, the number of leaves scales logarithmically well for the control block.

A channel completes its lifetime either when 90 days have elapsed or 64 state transitions have occurred. The account then refreshes the virtual channel into a fresh, new tree. In the case where a channel has expired and not been refreshed, or the channel does not have enough liquidity, the account receives payments in the form of new VTXOs (within the onboarding tree).

Brollup v2 incorporates two type of payments:

  1. P2VTXO (Pay-to-vtxo)
    For making payments from a channel to a brand-new VTXO.
  2. P2SCOM (Pay-to-s-commitment)
    For making payments from a channel to another channel.

P2VTXO (Pay-to-vtxo)

P2VTXO — the sender pays the recipient 0.1 BTC in the form of a vtxo

P2VTXO (Pay-to-VTXO) involves making a payment from a channel to a VTXO. The sender swaps out their channel liquidity for a fresh new VTXO. The recipient receives a new VTXO within the onboarding tree, bound by the msg.sender. This occurs when the intended recipient is not yet onboarded or lacks sufficient inbound liquidity in their channels.

P2VTXO is a straightforward process:

  1. The operator creates a round transaction by allocating 0.1 BTC to the recipient and adding a connector output to the msg.sender’s channel.
  2. The msg.sender (to_self) and the operator (to_operator) sign a state update from the channel, pushing 0.1 BTC to the operator’s side in exchange for the atomic payment in the round transaction.

The connector output provided by the operator also commits to the calldata, ensuring the authenticity and atomicity of the contract execution.

P2SCOM (Pay-to-s-commitment)

P2SCOM — the sender (to_self) pays the recipient 0.1 BTC within their channel

P2SCOM (Pay-to-s-commitment) involves making a payment from a channel to another channel. The recipient receives their payment directly into their channel, rather than as a brand-new VTXO. This occurs when the intended recipient is already a user and has sufficient inbound liquidity in their channels.

In contrast to Lightning, the recipient can receive payments without needing to be online. The operator simply signs a channel update in favor of the recipient, pushing the value to the recipient’s side, and provides their version of the s commitment in the witness.

The operator, however, does not disclose the s value outright. Instead, the operator initially commits to the s value using a hashlock in the witness, proves with a zero-knowledge proof that the hashlock commitment is valid, and promises to reveal the actual s value afterward. This precaution is necessary to prevent the sender and recipient from colluding to steal funds from the operator by refusing to sign the channel update after obtaining the s value. Once the sender forfeits their channel liquidity by signing a state update, the operator reveals the s value directly in the witness.

As outlined in my earlier announcement, the calldata output is utilized as the change output for the operator, revealing the payload and now the s values in the subsequent transaction. With the new calldata output structure, the operator must now reveal the s values (in pushdata chunks) to access their change funds; otherwise, the output can be taken by the msg.senders :

Witness Elements:1. <operator signature>
2. <s values in single chunk>
3. <0x01> // True
--------------------------------------------------------------------Witness Script:OP_IF// Operator must reveal the s values to access their changeOP_HASH160
<s values commitment>
<operator key>
OP_ELSE// Or otherwise this change becomes spendable by msg.senders[]<24 hours>
<msg.senders[] aggregate key> // msg.senders pre-sign from this key
OP_ENDIF// Calldata is revealed regardlessOP_FALSE
<calldata> OP_ENDIF

Nonce Selection

Picking signature nonces deterministically from a well-known basepoint is not safe, as it can lead to private key recovery. However, using different keys for the same nonce is safe against private key recovery, as long as the nonce remains secret and keys are unlinked.

Brollup v2 employs a unique approach to save 32 bytes for the signature nonce R by pre-selecting 64,000 nonces hardcoded in the client software, and re-assigning the to_operator key from a random entropy in every state transition. This approach involves using identical nonces with varying keys, rather than using identical keys with varying nonces.

The pool of 64,000 hardcoded nonces (that is 2MB!) effectively supports the potential creation of up to 1,000 new virtual channels, with each capable of accommodating a maximum of 64 state updates in each state transition.

What’s changed in v2?

  1. No trusted setup
    State channel design eliminates the need for trusted setup.
  2. Efficient liquidity
    State channel design leads to a more efficient use of liquidity.
  3. Interactivity cut significantly
    Reduced interactivity due to the removal of kdc.signers from the set.
  4. Longer liveness
    Our use of state channel enables a longer expiration period of 90 days.
  5. Immediate finality
    Finality for payable executions no longer tied to block-production.
  6. 8 vByte overhead
    Reduced TPS for payable executions due to an 8 vByte overhead.

New TPS Projections

Due to the 8 vByte overhead in payable executions, TPS projections for token order place & fill and nft auction list & sell have been reduced to 147 and 148, respectively. TPS projections for non-payable transaction types such as token transfers and nft transfers remain unchanged.


Brollup v2 is a net improvement over the earlier design. It makes liquidity more efficient, increases liveness, enables higher liquidity velocity, and most importantly, removes the need for a trusted setup — all without requiring a protocol change to Bitcoin.

BVM vs. EVM comparsion

Brollup provides an order of magnitude better user experience than Ethereum, operating natively on Bitcoin with BTC as the native gas asset.

Interested in learning more? Join our TG community channel!