Introduction

This is the technical report for the Catalyst fund13 project “EUTxO L2 Interoperability”. It will be used to gather and introduce background information, but also as a delivery artifact for the various milestones.

The full list of milestones can be found here and the corresponding chapters in this document will contain documentation, instructions and links to other materials to reproduce or use our results in further work.

Background

Relevant research

Reading list

Hash Timelock Contracts (HTLC)

Setting up an HTLC allows the sender to lock an asset to be spent “accordingly” or it allows them to get back their funds after a timeout. Not much scripting is required for this construction, hence it is popularly used in Bitcoin Lightning to effectively forward payments between channels.

In Bitcoin Lightning, HTLCs are also used to swap into and out of lightning channels from the Bitcoin main chain. These atomic swaps are called Submarine Swaps and are fully trustless (no custody, no counterparty risk) because they share the same underlying chain / security model (= Bitcoin).

Adaptor signatures

Originating from ideas on Scriptless scripts where correct execution of scripts is captured by the validity of digital signatures (elliptic curve based schemes), so-called adaptor signature schemes can be used to reveal information through the actual signature. Verifiably Encrypted Signatures (VES) are a generalization of this concept onto both Schnorr and ECDSA signature schemes.

Related work about cross-chain atomic swaps between Bitcoin and Monero suggests that adaptor signatures can be used to realize unlocking on even very constrained target chains (Monero). We are in a much more comfortable position of very scriptable ledgers.

Quite low-level treatment on the signature schemes: https://medium.com/crypto-garage/adaptor-signature-schnorr-signature-and-ecdsa-da0663c2adc4

Milestone 1

Consists of two parts

  1. HTLC prototype of payment between two L2s
  2. Transaction design for ad-hoc ledgers

HTLC payment

Example workflow of a payment of some $USDM from Alice to Bob via one intermediary Ida using Hash-Time-Locked Contracts (HTLC).

The topology of the involved L2s is not further specified here, but could be for example two Hydra heads between Alice-Ida and Ida-Bob, or a two-party head beween Alice-Ida and both, Ida and Bob being participants of a Midgard optimistic rollup. Even multi-party heads where multiple intermediaries could share the collateral across multiple HTLC outputs are thinkable, but that would need further investigation how we can guarantee collateralization across multiple outputs.

HTLC Design

The HTLC is implemented as a single validator, with two possible redeemers, Claim and Refund. No validation is run during the Lock operation.

UTxOs Specification

HTLCUtxo

Address

  • Script address

Datum

  • hash: ByteString
  • timeout: PosixTime
  • sender: VerificationKeyHash
  • receiver: VerificationKeyHash

Value

  • min ADA
  • offered tokens

Transactions

Lock Funds

Creates an HTLCUtxo containing the offered tokens. The datum specifies the sender and receiver Verification keys for future authetication, as well as the timeout in posix time and the hash of the secret needed to claim the funds.

In step 1 of our example, Alice would execute this transaction and specify herself as the sender, Ida as the receiver, a timeout sufficiently in the future and the hash shared by Bob. In step 3, Ida would execute this transaction and specify themselves as the sender, Bob as the receiver, a timeout slightly lower than the one Alice specified and the same hash used in step 1.

The lower timeout is needed to avoid a situation where Bob claims the funds in Head B and Ida is unable to claim their share in Head A.

Lock funds into HTLC

Claim Funds

Consumes a HTLCUtxo with the Claim redeemer, providing the preimage of the stored hash. This transaction must be submited before the timeout and must be signed by the receiver.

In step 4, Bob uses the preimage that they generated in step 0 to claim the funds. In step 6, Ida uses the preimage that they learned from Bob’s transaction to unlock the funds locked by Alice.

Claim funds from HTLC

Refund

Consumes a HTLCUtxo with the Refund redeemer. This transaction must be submited after the timeout and be signed by the sender.

Refund funds from HTLC

Ad-hoc ledgers

The State Machines across Isomorphic Layer 2 Ledgers paper describes a solution for implementing atomic transactions performed across multiple L2 ledgers. By the paper, this is achieved by the verify→perform mechanism.

The verify→perform mechanism

Lets analize a simple example with just two Hydra heads as the L2s.

Let A, B be Hydra heads. An atomic transaction is a process involving a sequence of two transactions per head, named verifyX and performX for head X ∈ {A, B}. The goal would be to transfer assets from A to B, avoiding inconsistent and non-reversible states.

The purpose of verifyX is to “simulate” the corresponding action to be performed in X. If verifyX succeeds for each X, it means that performX is safe to execute.

In simple terms, we first verify that the action to be taken in each head is doable (inputs could be spent, minting/burning validates successfully if any), and only then are the actions performed in each head. If performX for each X is successful, then the assets transfer from A to B is completed.

But, how to verify a future perform without executing it? In the verify step, the protocol does not directly produce the final outputs of the transfer. Instead:

  • The full body of the intended perform transaction (the “original transaction”) is embedded in the verify transaction’s somewhere (or maybe a hash of it).

  • verify ensures that its own inputs match those expected by the original transaction, and that all validation conditions (scripts, minting/burning policies) to produce the outputs (held in the embedded transaction) can be satisfied.

  • Because outputs are not yet created, irreversible actions like actual burning or final distribution do not happen at this stage.

  • Once verify has succeeded in both heads, the perform transaction does what the stored original body says, burns any temporary tokens, and creates the final outputs exactly as pre-agreed.

This mechanism implies that verify should be reversible. The paper includes situations where the verify step must be reversible, for example, transferring assets from A to B without an intermediary liquidity provider. This would involve burning them from A and minting them in B. If verifyA succeeds and verifyB doesn’t, we must be able to recover those assets in A. But if intermediaries provide the liquidity on the destinations ledgers, this might not be needed. Further investigation is needed to determine if this is the case.

In any case, NFTs are not considered in this mechanism. Only for ADA and fungible tokens. Extra policy engineering is needed to support NFTs.

In scenarios where one of the parties in charge of doing perform stalls the protocol flow by not doing it, a merge-transaction is needed to resolve disputed UTxOs, supported by other safety measures like collateralization.

The UTxOs subject to the verify→perform mechanism are called wrapped UTxOs, whose set defines the ad-hoc ledger Lₚ. Each head will contain a replica of the Lₚ. For the given use case of AB transfer

  • Replica R₀ in A contains Lₚ-wrapped UTxOs that include the actual asset being moved. These UTxOs are locked under the Lₚ validator.
  • Replica R₁ in B contains Lₚ-wrapped UTxOs that include the intermediary collateral. Locked under the same Lₚ validator.

Atomicity is enforced by making every Lₚ state change happen on both replicas (or none), so those two local views stay semantically equal even though the concrete UTxOs represent different things (assets to move on A vs collateral on B). In other words, both replicas UTxO set being semantically equivalent is the invariant that ensures atomicity. Divergent replicas states mean a liquidity trap.

The entities in charge of coordination of the verify→perform sequence on both heads is called intermediaries. They co-sign reversible verify transactions to confirm that inputs, witnesses, and policies are valid without committing to irreversible changes.

Intermediaries generate a pre-collected aggregate signature –a single signature assembled from all intermediaries’ keys– which will later authorize the irreversible perform transactions.

Intermediaries also post collateral, locked under the Lₚ validator at head B, equalling the value of the secured wrapped UTxOs at head A, needed for asset transfers. In a simple case of AB transfer with just one intermediary, the intermediary posts the collateral in R₁ replica and receives the same amount in R₀ replica.

How to verify a future perform without executing it?

The verify step stages a reversible transaction that proves the perform step can succeed. This is achieved by:

  • Collecting all relevant inputs: wrapped UTxOs from both replicas (assets in Head A, collateral in Head B).
  • Running all on-chain validation scripts: minting/burning, spending conditions, exactly as they would be in perform, but with outputs locked to an intermediate state rather than the final recipient.
  • Minting temporary proof tokens: these attest that the inputs passed validation and can be spent in perform.
  • No irreversible actions: assets are not actually moved to the destination or destroyed. Instead, they are locked in a way that can be undone if the other head’s verify fails.

This process guarantees that if both heads succeed in verify, the perform transactions can later be executed with no risk of failure, while still allowing reversibility if one side cannot verify.

Basic Use Case Specification

Transfer from Alce in Head A → Bob in Head B (with intermediaries set 𝙄 = {Ida})

Participants

  • Alice in Head A: sender of asset X
  • Bob in Head B: receiver of asset X
  • 𝙄 = {Ida}: intermediaries present in both heads; hold collateral; co-sign atomic steps (Ida is the only intermediary in this case)

Wrapped UTxO Datum Specification

  • owner (Address)
  • Kᵢ: aggregated public key of all intermediaries. For enforcing multisig control from the intermediary set.
  • nonce (Integer): random value generated at setup to uniquely bind the UTxO to a specific ad-hoc ledger instance.
  • perform tx body hash (Hash): hash of expected perform tx body to be executed after verify.

Step-by-Step Flow

  • Wrap assets to transfer + collateral

    • Head A: Alice locks asset X in Lₚ script → creates wrapped UTxO in replica R₀.
    • Head B: Ida locks their share of collateral in Lₚ script → creates wrapped UTxOs in replica R₁.
  • verifyA (Head A)

    • Consumes Alice’s wrapped UTxO, produces a staging UTxO (same assets, reversible, with proof of validity).
    • Ida’s signature is made.
  • verifyB (Head B)

    • Consumes collateral UTxOs, produces staging collateral UTxO (same assets, reversible, with proof of validity).
    • Ida’s signature is made.
  • Collect perform signatures

    • Ida agrees and signs both performA and performB tx bodies.
  • performA (Head A)

    • Finalizes transfer of assets from Alice to Ida in Head A.
  • performB (Head B)

    • Finalizes transfer of assets from Ida to Bob in Head B.

One-hop payment with ad-hoc ledgers

Continuing with the example use case of two Hydra heads A and B, with Alice in Head A and Bob in Head B, and Ida as the intermediary i.e. present in both heads, we will analyze a Lock operation of a one-hop payment with ad-hoc ledgers.

The Lock operation is the first step of the one-hop payment, akin to the HTLC Lock operation. It is the operation that locks the assets to be transferred from Alice to Bob via Ida.

Wrapping UTxOs

The first step for being “inside” of the corresponding replica of the ad-hoc ledger is to wrap the UTxOs that will be used to perform the atomic transaction (the Lock transaction in this case).

Each ledger (in this case, Head A and Head B) will contain a replica of the ad-hoc ledger Lₚ, named replica R₀ in Head A and replica R₁ in Head B. The replicas, as stated above, are defined by the set of wrapped UTxOs that are semantically equivalent between them.

Wrap UTxO

Verify the Lock transaction

The next step is to verify the Lock transaction. This is done by the verify step of the explained mechanism.

Verify Lock transaction

Perform the Lock transaction

The final step is to actually perform the Lock transaction. This is done by the perform step.

Perform Lock transaction

What’s the difference between using ad-hoc ledger or a simpler HTLC across L2s?

The main difference between using an ad-hoc ledger and a simpler HTLC is that the ad-hoc ledger allows for atomic transactions across multiple ledgers, while the simpler approach doesn’t.

Concretely, for the lock operation using just plain HTLC on two ledgers isn’t atomic. One of the parties could do the lock operation and then the other party don’t, and this would result in a liquidity trap until the HTLC expires. On the other hand, the ad-hoc ledger allows for more complex interactions via the verify→perform mechanism, where the verify step is reversible and the perform step is irreversible.

Also, the collateralization burden is distributed across the intermediaries, rather than being concentrated on one party. This makes the protocol more robust to failures and more flexible to different scenarios. By the paper, this makes the transfer between ledgers more capital efficient.

Further investigation about these (and more) differences will be done throughout the project.

Logbook that contains thinking, discussions, pains, joys, events, and experiences that happen while working on this project. It is supposed to be a kind of Stream of consciousness that can later be searched, linked to or reviewed. It may also be used as a very informal decision log.

2025-04-04

By @ch1bo and @SwiftlyUnmoving

  • Discussing our take-aways from the paper
  • Glances over the fact that script spending does not generalize easily
  • Collateralization and fee structure is handwavy and could be problematic
  • How to make NFTs minting policy compatible with L2s
    • Case on script context and have values for Hydra, Hydrozoa, Midgard, …?
    • Equivalent of a spending validator agreeing to be committed into L2
    • But we would need to delegate trust to Hydra, Midgard etc. when minting happens later on L1
    • On L1 we can identify that we are minting in e.g. a Hydra fanout and can green-light this if the validator set is enough
  • Interfacing spending validators with L2s (on committing) is equivalent to using them for atomic transactions across L2
  • Atomic transactions across L2s is kind of equal to establishing an L3 (and that same interfacing problem when going L2 -> L3)
  • Spending and minting needs to be compatible with the cross ledger protocol (i.e. the wrap-perform transaction)
  • Collaterizing NFTs is an issue for any cross-ledger protocol!
    • While in the L2 case, there may be a chance to avoid duplication as we share the same L1 and a dispute protocol can exist
    • However that would still mean that one party will only be refundend the collateral instead of the NFT
    • Also: What’s sufficient collateral for one NFT, who decides?
    • Too high collateral limits liquidity / reach of such an NFT (each intermediary set would need to be liquid enough)
    • Even harder to estimate for state thread tokens (which ensure contract continuity)
      • Consolidation of smart contract state is going to be hard.
  • How does the ad-hoc ledger concept scale?
    • For example in doing multiple hops and routing
    • In principle, collateral should be sharable across inermediaries (per hop)
    • We should model this to see wheather the whole feasible the concept is
    • Timing within payment channel networks is adding up, is this the case here too?
  • Difficulty levels of “asset under interop”
    • Easiest: one currency value (UTxO = Bitcoin)
    • Easy: multiple, fungible assets (UTxO-ma, only FT)
    • Medium: non-fungible tokens (UTxO-ma, also NFTs)
    • Hardest: fully scriptable spending and minting (EUTxO)
  • Liquidity across the path
    • Lightning already has the complexity of direction in liquidity
    • In a full UTxO ledger, it is even more difficult as the assets might not be owned by the validator
    • Need to know how much collateral is available for route finding
  • Do we even benefit from UTxO ledger model over an account model?
    • Maybe not?
    • Would simplify collateral allocation
    • Indidividual state channel interactions might benefit from it, but for bridging / routing funds across ledgers not so much?
    • One account for each interop protocol intermediary (= collateral available = liquidity available)
  • What if liveness of L2 breaks down?
    • Wrapped UTxOs must be recoverable or performable on L1
    • We should “front load” as much work as possible in the wrapping (aka verify) transaction so that perform or dispute can always fit on L1 even
  • We also mentioned in passing that the only way we could do full script verification (with simulated script context) for verify would be by side-stepping the L2 ledger and build support into Hydra/Midgard
  • Also: is there a timeout before a dispute can be made? Otherwise we would race between signing perform and doing a dispute -> or is this not an issue?

2025-04-01

By @ch1bo

  • Want to establish a logbook to put notes for this project
  • Rendering into the mdbook like I started doing for cardano-blueprint seems useful too
  • Hower, using the Github wiki as a logbook is producing less noisy commits on the main repository
  • The github wiki is also a repository we can add as a submodule, i.e.
    git submodule add wiki git@github.com:cardano-scaling/eutxo-l2-interop.wiki.git
    
  • Then, symlinking the the logbook.md into book/ and adding it to SUMMARY.md does the trick
  • Now, only nix is choking on submodules (as always)
  • Found the idea of tracking the submodule as a flake input online in this thread https://discourse.nixos.org/t/get-nix-flake-to-include-git-submodule/30324/16
  • Now, we track the submodule commit also in the flake.lock, but at least the nix build works as-is.

2025-03-25

By @ch1bo

  • Re-read the research paper and started a summary in the technical report
  • Approach is quite “ad-hoc” indeed and borrows on generalization of HTLCs being similar “two-step commit schemes”
  • Relevant other paper SoK: Communication Across Distributed Ledgers which focuses on cross chain communication, but establishes as generic model: “A generic CCC protocol consists of three main phases: commit (on X), verify (and commit on Y ), and an optional abort”
  • Could improve some terminology around “utxo addresses” which seem to be rather “output references”
  • Wrap + perform is basically a two stage commit similar to the above
  • Script continuity of verify-perform? What if L2 closes? Need intermediaries ensure continuity somehow “on top” of running the L2 ledger?
  • UTxO and UTxOma should be “embeddable” into EUTxO protocol for ad-hoc ledgers - as they do not require general scriptability
  • Verifying the transaction on “wrap” sounds like side-stepping the EUTxO ledger? i.e. simulate a script context with outputs as they would on perform
  • Mint tokens on wrapping -> why not on perform? to avoid burning in case of dispute
  • Setting a dispute flag on the wrapped UTxO would rather be another state of the protocol!?
  • What if liveness of L2s break?
  • The biggest open questions remain:
    • How to collateralize NFTs?
    • How to generically wrap script UTxOs without side-stepping EUTxO ledger?
    • How to ensure script continuity of wrap + perform steps (without minting tokens ourselves; what if L2 closes)?

Demo

Diagrams & Maths

We can use mermaid diagrams (live editor):

graph LR;
    A-->B-->D;
    A-->C;

and maths using katex:

Alerts

warning

We can use the github flavored callouts, documented here

note

A friendly note in github. How about code blocks?

cargo install mdbook-alerts

Footnotes

Additional information that would complicate the read-flow can be put into footnotes 1.

1

Example footnote