A Composable Unlinkability for Smart Contracts. Users commit data to one tumbling contract, then redeem an encrypted copy into any other on-chain application — with the link to the original commit removed.
1Visa Research · 2IMDEA Software Institute · 3MPI-SP · 4Texas A&M University · 5MIT
The linked PDF is arXiv v1 (2503.04260, March 2025). Table 2's Mobius and AMR comparison columns on this page come from the later AsiaCCS version and are not in that PDF.
In three numbers
Merkle tree of depth $20$ in every application (§7.1). Anonymous Zether's measured transfer uses a set of 8.
$\mathsf{C}_\mathsf{DTL} \rightarrow \mathsf{C}_\mathsf{Conf}$ (Table 3), against 7,306,703 for an Anonymous Zether transfer with 8 users.
Unlinkable withdraw (Table 3) on a 4-core i5-1137G7 laptop with 8 GB of memory. Groth16, Circom, SnarkJS.
The problem
Ledgers publish senders, receivers and amounts. The privacy add-ons that exist — unlinkable mixers like AMR, confidential payments like Zether, stealth addresses — are each built for one function, usually moving money. None of them can be plugged into other contracts. The paper asks:
How can we design privacy-enhancing solutions that can be composed with existing on-chain applications to enhance user privacy throughout the entire system?
User $u_i$ commits data $\mathsf{data}_i$ to the tumbling contract $\mathsf{C}_\mathsf{DTL}$. The contract adds a public key $\mathsf{cpk}$ to a Merkle tree.
Later, possibly from a fresh address, the user proves in zero knowledge that they own some leaf and receives $[\mathsf{data}_j]$, an encrypted copy of the data.
That copy flows straight into another contract: a payment, a confidential-balance contract (Zether), or a weighted vote. One layer, many applications.
Two constructions: $\mathtt{DTL}_\mathsf{fixed}$ when every user commits the same data (a fixed coin, an equal vote), and $\mathtt{DTL}_\mathsf{arb}$ for arbitrary data such as amounts. Both are proved correct, unlinkable, and secure against one-more redemption, theft and slander (Theorems 1 and 2).
Interactive 1 · the tumbler
Commit a few users into the tree, then redeem them to fresh addresses. The right-hand panel is everything the chain shows. Then try the three attacks. Each one is stopped by a specific line of the relation below.
Hex strings here are illustrative stand-ins produced by a toy hash, not Poseidon/Pedersen outputs. The relation rows follow Eq. 1 ($\mathtt{DTL}_\mathsf{fixed}$) and Eq. 2 ($\mathtt{DTL}_\mathsf{arb}$) in §5.
Interactive 2 · composed applications
Every application is a commit into $\mathsf{C}_\mathsf{DTL}$ followed by an unlinkable redeem into somewhere else. Pick a route. Segments are the measured per-transaction gas from Tables 2–4, and totals are sums of those entries.
Interactive 3 · against prior work
Mobius pays for its ring at withdrawal time, and Anonymous Zether pays for its anonymity set on every transfer. DTL's verification is a Groth16 check against a Merkle root, so its cost does not grow with the set. Prior-work numbers are the ones reported in those papers, as used in the paper's §7.
Interactive 4 · concurrency (Appendix, Theorem 3)
Every deposit changes the Merkle root, so the contract keeps the $k$ most recent roots. A withdrawal proves against one of them, say the root at position $i$. An attacker who floods deposits can push that root out of the list. Theorem 3 says this takes exactly $k-i+1$ deposits. With the paper's Ethereum figures (a block gas limit of about $30\text{M}$ and $767{,}565$ gas per deposit), at most $B = 39$ deposits fit in one block.
$B = \lfloor 30{,}000{,}000 / 767{,}565 \rfloor = 39$. The paper's worked example is $k = 1000$, $i = 1$: at least $26$ blocks (about $6.5$ minutes at $15$-second blocks) and $20$ ETH, which it prices at about \$36,000, to temporarily block one withdrawal. The honest user can just resubmit against a newer root. Block time, fee and gas limit are the paper's assumptions, not measurements.
Guarantees
| Property | Meaning (from §1) | $\mathtt{DTL}_\mathsf{fixed}$ | $\mathtt{DTL}_\mathsf{arb}$ |
|---|---|---|---|
| Correctness | A user who committed data can redeem the same data for use in other applications. | Thm 1 | Thm 2 |
| No one-more redemption | A user who commits $n$ data inputs cannot redeem more than $n$ outputs. | Thm 1 | Thm 2 |
| Theft prevention | An adversary cannot use data previously committed by an honest user. | Thm 1 | Thm 2 |
| Non-slanderability | An adversary cannot stop an honest user from redeeming their committed data. | Thm 1 | Thm 2 |
| Unlinkability | An adversary with the contract's state cannot link a user's commit to their redeem. For arbitrary data, it cannot tell whether a specific committed item is the one being redeemed. | Thm 1 | Thm 2 |
Assumptions: Theorem 1 assumes a secure zk-SNARK, Merkle tree and tagging scheme. Theorem 2 adds a hiding and binding commitment scheme and IND-CPA encryption. Proofs are in the full version (arXiv 2503.04260).
| Anonymity set | Confidential amount | Composability | Availability | Applications |
|---|
● yes ○ no ◐ partially provided, i.e. it composes with only a single application. Off-chain solutions rely on servers that can go offline or misbehave, which hurts availability.
Measured results
Groth16 over BN254 with Poseidon for the Merkle tree, Pedersen for tags and commitments, and ElGamal on Baby Jubjub for $\mathtt{DTL}_\mathsf{arb}$. The tree has depth $20$. Measured on a 4-core Intel i5-1137G7 with 8 GB of memory.
| DTL Deposit | DTL Withdraw | Mobius Deposit | Mobius Withdraw(8) | AMR Deposit | AMR Withdraw | |
|---|---|---|---|---|---|---|
| R1CS constraints | - | 8,146 | - | - | - | 28,275 |
| Proving time | - | 1.15s | - | 3.254ms | - | 8.325s |
| Gas cost | 767,565 | 233,375 | 105,346 | 2,685,712 | 1,036,580 | 325,051 |
| Transparent deposit addr → C_DTL | Confidential deposit C_Conf → C_DTL | Unlinkable withdraw C_DTL → C_Conf | AZether Transfer (8) | |
|---|---|---|---|---|
| R1CS constraints | - | 8,671 | 11,521 | - |
| Proving time | - | 1.16s | 1.32s | 1.9s |
| Gas cost | 767,565 | 1,051,112 | 258,467 | 7,306,703 |
| Registration addr_voter → C_DTL | Unlinkable vote C_DTL → C_Conf | Reveal addr_i → C_Conf | |
|---|---|---|---|
| R1CS constraints | - | 11,521 | 6,750 |
| Proving time | - | 1.19s | 1.03s |
| Gas cost | 767,565 | 258,467 | 291,151 |
Reference
@misc{le2025dtldatatumblinglayer,
title = {DTL: Data Tumbling Layer. A Composable Unlinkability for Smart Contracts},
author = {Mohsen Minaei and Pedro Moreno-Sanchez and Zhiyong Fang and
Srinivasan Raghuraman and Navid Alamati and Panagiotis Chatzigiannis and
Ranjit Kumaresan and Duc V. Le},
year = {2025},
eprint = {2503.04260},
archivePrefix = {arXiv},
primaryClass = {cs.CR},
url = {https://arxiv.org/abs/2503.04260}
}
Source code. The paper has no code or data availability statement, so this page links no implementation. The evaluation (§7) used Circom circuits, SnarkJS for proving and for generating the Solidity verifiers, and the Truffle toolchain on a test network.