Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Fungi

Fungi is a protocol for collaborative transactions designed to make using Bitcoin more private. Participants can also pay each other interactively in these transactions, which helps not just privacy but also blockspace efficiency.

A software development kit (SDK) is in development. This repository contains the specifications and the analysis behind them.

Note

Work in progress: most chapters are drafts under review. See the open pull requests for material being drafted.

Chapters, sections or paragraphs marked with 🤖 are LLM output. They have been partly verified but have not yet been edited or rewritten as necessary, and should be considered a working draft.

Background

Censorship resistance and fungibility are among Bitcoin’s foundational properties. Without privacy, both can be undermined largely outside the protocol’s rules, whether by targeting specific individuals or through chilling effects.

Bitcoin transactions are public data, and they are connected in a graph structure. Chain analysis is the application of heuristics to this graph to infer which coins share an owner. While no heuristic is perfect, their effectiveness has been shown in numerous studies. Several heuristics can be combined for a more accurate analysis. Analysis might also draw on auxiliary information not recorded on the blockchain, such as which coins an exchange sent to which customer.

CoinJoin transactions seek to undermine some of the heuristics used to cluster coins across the transaction graph. They combine several users’ inputs and outputs in one transaction in order to obscure ownership links within it. Several CoinJoin implementations exist with different approaches to their transaction structure.

Problem statement

Unfortunately, CoinJoin privacy is often stated in terms of the number of indistinguishable outputs in a transaction. This tacitly ignores the fact that those coins will go on to be spent. The information revealed by the spending transactions, which are themselves related to other transactions, can dramatically affect privacy, in some cases making the CoinJoin inputs linkable to the outputs.

Recurring relationships give rise to patterns too. Transacting with the same employers, shops and friends leaves a structure in the transaction graph, even if techniques like PayJoin might hide the individual amounts and confound some of the clustering heuristics. Obscuring this structure necessitates transacting with unrelated users, chosen at random, so users who don’t know or trust each other need a way to find each other and agree on a transaction. Random selection must additionally be Sybil resistant, so that the cost of an deanonymization attack, where the adversary controls all of the other (apparent) participants, is a sufficient deterrent.

In general, deanonymizing a single user always makes it easier to deanonymize the other users. But sometimes the adversary might progress not just by process of elimination, but more like divide and conquer. This happens when deanonymizing that one user splits the problem of deanonymizing the rest into several smaller problems, as opposed to merely making it incrementally smaller.

The problem definition chapter discusses these on-chain privacy leaks in depth, and describes a particular transaction graph structure that resists deanonymization more robustly.

How Fungi works

A user first tells their wallet which payments they intend to make, and the wallet keeps these in a queue. Intents can vary in their time, privacy or cost sensitivity. Making a payment quickly, cheaply and privately is a balancing act, and improving one usually means compromising on another. The wallet’s job is to construct transactions that make the queued payments, balancing these goals in line with the user’s preferences.

The wallet schedules and batches payments, negotiating with other participants to find terms that suit the user’s priorities. The more flexible a payment’s timing, the more cost-effective it can be, because there is more time for compatible proposals to be combined, so that its cost can be shared with more participants. The protocol and the strategy are designed together, and the SDK implements both.

Avoiding links between coins is central to the strategy. The input and output amounts can imply such links if there aren’t enough possibilities for how to group inputs and outputs so their totals match. But as mentioned above, a partition of a transaction’s coins can also be evaluated based on the surrounding context in the transaction graph, not just the amounts associated with that transaction. So the strategy must consider not just whether the transaction’s internal structure is sufficiently ambiguous, but also how a transaction sits in the wider transaction graph.

In Fungi, a co-spend proposal sets out the terms for spending a set of coins together. Proposals are made automatically according to the privacy optimization strategy. The transaction-wide terms of a co-spend proposal are public, constraining things like the range of acceptable feerates or whether or not non-SegWit inputs can be used. Proposals can also include fees, which are kept confidential. A proposal involving three or more parties additionally hides which of them made the proposal. Once accepted by all parties, co-spend proposals are publicly broadcast.

Any participant can collect fully accepted co-spend proposals from multiple parties, and then make a coalition formation proposal which aggregates them together, so long as the terms are compatible. If everyone accepts the coalition formation proposal, then a coalition has been formed, and the parties can proceed with collaborative transaction construction. Privacy is brittle in small transactions. A critical mass of participants is therefore necessary for privacy to be robust and cost-effective, and coalition formation is designed to facilitate such a critical mass forming.

During collaborative transaction construction, participants add their intended inputs and outputs anonymously. This preserves the unlinkability of inputs and outputs so long as it isn’t undermined in some other way (for example by reusing an output address). Interactive payments additionally provide privacy against the payment counterparty. In addition to hiding the payment amount from third parties, the sender and receiver do not learn about each other’s coins. Since many interactive payments can be settled in one collaborative transaction, this creates the opportunity for blockspace savings.

In order to ensure funds are secure throughout, every participant retains control at all times and therefore signs their own inputs. Unfortunately, this means that as the number of participants grows, reliability will necessarily degrade. Even if the probability of any one participant causing a fault is low, that compounds when considering the probability that none of them will. Transaction construction is designed to be fault-tolerant, so that even when a valid transaction has not successfully been produced, participants have a basis to refine the coalition structure. Fault tolerance includes malicious disruption.

Compared to JoinMarket

Fungi could be described as a spiritual successor to JoinMarket (as implemented by JoinMarket and JoinMarket-NG). Like JoinMarket, it is peer-to-peer and market-based, with no centralized coordinator, but differs substantially in how it approaches the order book mechanism as well as transaction construction.

JoinMarket distinguishes two roles: in each transaction, a user in the role of the taker selects several makers from the order book. Makers advertise their willingness to participate in CoinJoin transactions. Generally, the taker will pay the on-chain fees as well as any maker fees. The taker learns which coins belong to the makers it pays, so makers get no privacy from the taker. And because there is a single taker, a transaction can only include as many participants as one taker is willing to pay for.

Fungi makes no distinction between the taker and maker roles. Instead, a participant can both send and accept proposals, and proposals involving multiple users can be aggregated, allowing a single transaction to be negotiated more as a group buy of blockspace. As the number of participants grows, the privacy benefits compound for everyone, which means each individual user needs to pay for proportionately less blockspace in order to meet their individual privacy requirements. Finally, the proposed transaction structure aims to address several deanonymization attacks that were not yet understood at the time JoinMarket’s design was put in place.

Contents

Problem Statement

Protocol Suite

  • Overview - Collaborative transaction construction, privacy, fault tolerance and coalition formation.
  • Abstract transport interfaces - Send, receive and bidirectional channels, the kinds of messaging the protocol needs, and broadcast built from peer to peer channels.
  • 🤖 Peer and broadcast channels - Broadcast to a group or to the world, built by gossip over peer to peer channels.
  • Contacts and payment messaging - What interactive payments need from peer to peer messaging between payer and payee.
  • Market-based coalition formation - Bilateral negotiation and aggregation of co-spend proposals into a unanimously accepted coalition formation proposal.
  • Transaction construction - Content and state synchronization, the phases, the optimistic and recovery tracks, and what the validity proofs enforce.
    • Block DAG - The validator blocks both tracks share, with their objects, nonce commitments and equivocation evidence, genesis, causal order and frontiers.
    • 🤖 Optimistic track: blocks and phase states - Unanimity and phase closure on the optimistic track, phase by phase.
    • Recovery track - How a stalled phase of the optimistic track turns into a recovery coalition formation proposal. Draft.
  • 🤖 Peer set reconciliation - Requesting hash preimages, naive reconciliation, unordered sets, and range and rateless reconciliation as optimizations.
  • 🤖 Protocol messages - The messages peers exchange, who sends them, when, and what each requires of its channel.
  • 🤖 Validity proofs - Selected design: proving outputs are covered by inputs through anonymous allocation registration.

Privacy Optimization Strategy

  • Optimization framework for Bitcoin wallets - Objective costs, privacy liabilities and payment utility as the basis for automated wallet decisions.
  • 🤖 Pure Strategy Evaluation - How the cost of a pure strategy is evaluated: the structure of the cost function, its privacy liability terms, and the privacy metrics they take as input.
    • 🤖 Cost function structure - The structure shared by the family of cost functions that evaluate pure strategies: time dependence, linear combination of terms and bracketing.
    • 🤖 Privacy liability terms - The privacy objectives assessed by each liability term and how the terms interact.
      • Randomized selection - Selection preferences that randomize which coins are co-spent, and a lower bound on the size of the order book they were selected from.
      • 🤖 Sybil resistance - Observed resource requirements and sampled cost estimates assessed against the user’s threat model.
      • 🤖 Subset sum ambiguity - Outline of a concrete cost function term for the subset sum ambiguity of input and output values.
      • 🤖 Consolidation penalty - Outline of a concrete cost function term penalizing consolidation unless the subset sums are very dense and the coins are impervious to intersections.
      • 🤖 Sibling output penalty - Outline of a concrete cost function term penalizing spending sibling outputs together.
    • 🤖 Privacy metrics - Measures computed from public data that the privacy liability terms take as input.
      • 🤖 Order book size estimation - A relatively conservative estimate of a lower bound on the number of candidate coins a transaction’s inputs were selected from, and how to find the block hash they were selected with.
      • 🤖 Subset sum density - How many subsets of a multiset of effective values sum into a target interval, a quantity the subset sum ambiguity and consolidation terms reuse, how it’s estimated, and how co-spend proposals and the aggregator optimize it.
      • 🤖 Counterfactual paths - Outline of how to count disjoint counterfactual paths with one max flow, and how to estimate the count.
  • 🤖 Mixed strategy - How to compose a mixed strategy from the cost of pure strategies: randomization, time dependence, internalization and the decision loop.
  • Tactics - Generating the decision tree bottom up, with coin selection and change decomposition, and when to re-evaluate it.
    • Bottom-up construction - Building the decision tree from the leaves: partitions of the intent queue, coin selection, change construction, order book coins, action sequences, and bracketing.
    • Radix CoinJoin Denominations - Why small Hamming weight denominations suit CoinJoin outputs, and how closely sums of a few of them approximate arbitrary amounts.

BIP Drafts

  • PSBT Scrubber - Which PSBT fields can be shared with trusted and untrusted parties such that privacy is preserved.
  • Concurrent PSBT Construction - PSBT fields and rules for combining partial transactions and terminating concurrent construction.

Collaborative transaction privacy

This document examines some challenges for privacy in a variety of multiparty transaction settings, from PayJoin to CoinJoin.

The Bitcoin transaction graph

The Bitcoin transaction graph is a trace of the movement of funds between different users.

The flows themselves can also be modeled as a graph where vertices represent users, and edges represent the relationships between the users, that is to say the edges describe how funds tend to flow between the users. Borrowing from the first study to describe this, we’ll refer to it as the user network, and define it more precisely below. Deanonymization of Bitcoin transactions roughly corresponds to recovering (parts of) this underlying structure from the transaction graph recorded on-chain.

Neither the user network nor the transaction graph is random. But they both have some randomness in them. The user network is a kind of social graph, specifically an economic network. An extensive literature on complex networks characterizes such graphs.1 These networks behave very differently from random graphs, certain properties of these graphs can be predicted reliably. In the transaction graph, some of the details are obscured, primarily due to Bitcoin’s reliance on the UTXO model (rather than say the account model) for transfers. However, because the transaction graph is a trace of transfers through the user network, and because the user network is highly structured, so is the transaction graph. And while the user network is not directly observable, it is one of the defining properties of Bitcoin that the complete transaction graph is observable by anyone.

For the transaction graph to be privacy preserving, it must robustly obscure patterns originating from the user network. This is challenging because the user network constrains how the transaction graph is constructed. There are different ways of accomplishing this goal, but the approach assumed here is that of an overtly ambiguous graph, where the individual users’ actions are sufficiently and randomly intertwined, necessitating additional information to disentangle. The central claim made here is that such a graph must be carefully and deliberately constructed. It does not emerge spontaneously, nor by naive attempts. But it can be constructed, even efficiently, and the guarantees it provides are relatively straightforward to understand and even to quantify.

Unfortunately, common misconceptions about how on-chain privacy works and what attackers are capable of paint a much rosier picture than what the published literature has shown is actually possible. None of the attacks described here are novel, but some of the cited results of the privacy literature originated in a different setting than Bitcoin privacy.

This document isn’t concerned with providing empirical proof of the viability of different attacks, partly because some of the structures whose weaknesses are examined are still hypothetical, but mostly because of the lack of novelty; the cited works are generally supported by evidence and most are peer reviewed. It is on proponents of privacy to show why their technology can resist such attacks, rather than on critics to demonstrate how it can be broken for the same reasons as in cryptography but even more so because many of these attacks are substantially amplified by an adversary’s access to auxiliary information such as labeling originating from KYC processes.

Unlike in cryptography, where the burden of proof is both high and generally belongs to those making claims of security, in Bitcoin privacy various apologists and interested parties often promote the notion that the burden of proof is reversed, or that addressing these problems is trivial. That framing is misleading in minimizing the consequences. Misinformed users are needlessly exposed to risks to which they might not have given informed consent.

This document is concerned with defining specific failure modes. Vendors of privacy-enhancing technologies, as is the norm in other industries, should be expected to address these widely understood attacks and argue for how their product maintains privacy in the face of adversaries that aren’t assumed to be unreasonably weak. Specifically this document defines the problems that the Fungi protocol suite aims to address. And by extension a minimum bar for evaluating any claims about the on-chain privacy guarantees it tries to provide.

In other words, the problem is that due to the economic network at the heart of Bitcoin, not only is it unreasonable to expect privacy or fungibility automatically, but the privacy guarantees that are currently available themselves often rely on unreasonable assumptions. By understanding these challenges we can describe the properties a transaction graph requires so that its resistance to analysis does not rest on fragile or unrealistic assumptions.

Unilateral transaction privacy

Unilateral transactions are highly susceptible to deanonymization using clustering techniques. After address reuse, the most obvious way to cluster, or link a user’s coins, is the common-input-ownership heuristic (CIOH): A transaction that spends several inputs is evidence that one entity owns all of them, since at the protocol level signing for all of them normally requires all of their keys.2 3

input 0.5

transaction 1

input 0.3

payment 0.6

change 0.2

transaction 2

input 0.4

payment 0.5

change 0.1

input 0.5

transaction 1

input 0.3

payment 0.6

change 0.2

transaction 2

input 0.4

payment 0.5

change 0.1

CIOH links the inputs of each transaction, and change identification links the two transactions: All five blue coins merge into a single cluster.

Practical clustering combines heuristics beyond CIOH to build a wallet cluster: a set of addresses and coins inferred to share one owner.4 5 6 7 8 9 10

Collaborative transactions

A transaction that spends inputs owned by more than one user falsifies CIOH by construction. Starting with just two parties, the observable structure can have (at least) two forms.11 The on-chain transaction must be compatible with the actual allocation of inputs, outputs, and payments among the participants, but it might not reveal that allocation in its entirety.

The first two-party form is a batched transaction, or a CoinJoin: two independent sub-transactions, both of which are balanced, aggregated into a single transaction.

Here, a sub-transaction means some, but not all, of a transaction’s inputs and outputs attributed to one participant’s action. A more precise, probabilistic notion will be discussed below. Informally, a balanced sub-transaction is one whose balance, the difference of the sum of input values and the sum of the output values, is approximately zero.

Alice's input 0.9

transaction

Bob's input 0.3

payment 0.5

Bob's change 0.1

payment 0.2

Alice's change 0.4

Alice's input 0.9

transaction

Bob's input 0.3

payment 0.5

Bob's change 0.1

payment 0.2

Alice's change 0.4

A batch: two independent spends aggregated, SharedCoin style. Each sub-transaction balances on its own (0.9 = 0.5 + 0.4 and 0.3 = 0.2 + 0.1).

In the example above, although CIOH is falsified, the amounts strongly suggest one way of partitioning the transaction, and CIOH still applies within each sub-transaction separately. We’ll return to this form of collaborative transaction and its variations, as well as how the sub-transaction model generalizes CIOH, in later sections.

Two-party PayJoin

The other main form a two-party transaction can take is a PayJoin.12 13 14 15 Unlike the independent, balanced sub-transactions in the preceding example, the sender’s sub-transaction has a positive balance (a surplus) that covers the receiver’s negative balance (a deficit). This imbalance between the two sub-transactions is the payment.

The following illustrates a single payment from Alice to Bob, but Bob also contributes one of his own inputs alongside Alice’s:

Alice's input 0.9

Bob's input 0.6

transaction

Bob's output 1.1

Alice's change 0.4

Alice's input 0.9

Bob's input 0.6

transaction

Bob's output 1.1

Alice's change 0.4

Here, Alice pays Bob 0.5: Bob’s 0.6 input grows into a 1.1 output. The payment amount appears nowhere on-chain, and the ownership coloring is of course not part of the on-chain data either.

For privacy, a somewhat teleological but more general definition of PayJoin is a collaborative transaction that should be indistinguishable from an ordinary single-party transaction. The unnecessary-input heuristics flag an input when the remaining inputs could already fund the outputs and fees; such an input may reveal that another participant contributed it.16 17 If collaborative transactions were sufficiently common, naive application of CIOH would quickly lead to cluster collapse, forcing a more nuanced approach to clustering.

CIOH, seeing two inputs, would wrongly attribute them to a single owner. There’s no single unambiguous interpretation: Looking at a transaction like the example in isolation, an analyst cannot be sure which inputs are Alice’s, which output is the real payment, or even that a PayJoin occurred at all rather than an ordinary two-input spend.

With only two parties, there are only a few interpretations, namely the different ways of assigning inputs and outputs to sub-transactions attributed to Alice and Bob separately. The typical uncertainty is therefore on the order of a few bits to an external observer, even when looking only at the transaction in isolation and ignoring its context.18

The next few sections discuss extensions to two-party PayJoin, but bear in mind that as they’re more difficult to analyze, the same concerns apply even more to the two-party case. Additionally, a two-party PayJoin inherently cannot provide privacy from the counterparty. Each participant can eliminate their own inputs and outputs from consideration, which entails that everything else is attributable to the only other party. Privacy within a transaction requires three or more parties.

Many senders, one receiver (NS1R)

A natural generalization is from one sender to many.19 Several senders each contribute inputs to a single transaction that pays one common receiver, so it resembles an ordinary batched payout the receiver might have made by consolidating funds:

0.2

0.3

0.7

Alice

Dave

Bob

Carol

0.2

0.3

0.7

Alice

Dave

Bob

Carol

The payment graph, which isn’t observable on-chain.

Dave's input 0.4

Alice's input 0.5

Bob's input 0.6

Carol's input 0.9

transaction

Dave's output 1.6

Alice's change 0.3

Bob's change 0.3

Carol's change 0.2

Dave's input 0.4

Alice's input 0.5

Bob's input 0.6

Carol's input 0.9

transaction

Dave's output 1.6

Alice's change 0.3

Bob's change 0.3

Carol's change 0.2

Alice, Bob and Carol pay 0.2, 0.3 and 0.7 respectively; Dave consolidates the payments with a 0.4 input of his own. None of the payment amounts appear on-chain.

This allows more payments to be consolidated into a single receiver output, so it’s cheaper than paying separately.

Counterparty privacy depends on how the transaction is constructed. In the experimental NS1R implementation,19 each sender supplied a pre-signed transaction to the receiver, revealing which inputs and change outputs belonged to that sender. If transaction construction conceals attribution, the receiver can still use its knowledge of each sender’s payment amount to test possible input and change-output assignments. This can narrow the possibilities, and may identify a sender’s change output, but does not by itself guarantee a unique assignment.

This structure can’t really hide much more than that: The change outputs will likely still link, and as the number of senders grows, the receiver must consolidate more aggressively to leverage the savings — which is itself a detectable fingerprint. Avoiding it means forgoing the fee savings and splitting the received funds into several outputs of a smaller magnitude to better match the distribution of the change outputs. Splitting the receiver’s funds creates another hazard: Later spending those sibling outputs together, even in a multiparty transaction, is wasteful and potentially more indicative of common ownership than spending non-sibling outputs together. Two independent users participating in one transaction and then independently spending their respective outputs in the same subsequent transaction would arguably require more coincidences.20

Many senders, many receivers (NSNR)

The two sides can instead be made symmetric. Let be the number of participants, half spending and half receiving. The transaction consists of payments between the sub-transactions, pairing sub-transactions uniquely.

Alice's input 0.9

transaction

Frank's input 0.15

Bob's input 0.4

Dave's input 0.3

Carol's input 0.45

Erin's input 0.35

Erin's output 0.85

Carol's change 0.25

Dave's output 0.5

Alice's change 0.4

Frank's output 0.45

Bob's change 0.1

Alice's input 0.9

transaction

Frank's input 0.15

Bob's input 0.4

Dave's input 0.3

Carol's input 0.45

Erin's input 0.35

Erin's output 0.85

Carol's change 0.25

Dave's output 0.5

Alice's change 0.4

Frank's output 0.45

Bob's change 0.1

A multiparty PayJoin transaction with three payments between six participants, with one input and one output per party.

0.5

0.3

0.2

Alice

Erin

Bob

Frank

Carol

Dave

0.5

0.3

0.2

Alice

Erin

Bob

Frank

Carol

Dave

The underlying payment graph, which isn’t observable on-chain.

A different interpretation of the same transaction might swap the candidate ownership of Alice’s 0.4 change and Erin’s 0.85 output:

Alice's input 0.9

transaction

Frank's input 0.15

Bob's input 0.4

Dave's input 0.3

Carol's input 0.45

Erin's input 0.35

Alice's change 0.85

Carol's change 0.25

Dave's output 0.5

Erin's output 0.4

Frank's output 0.45

Bob's change 0.1

Alice's input 0.9

transaction

Frank's input 0.15

Bob's input 0.4

Dave's input 0.3

Carol's input 0.45

Erin's input 0.35

Alice's change 0.85

Carol's change 0.25

Dave's output 0.5

Erin's output 0.4

Frank's output 0.45

Bob's change 0.1

Under this alternative assignment, Alice’s 0.9 input leaves 0.85 in change, implying a payment of only 0.05 to Erin.

Because each participant only participates in exactly one payment, each hidden sub-transaction is related to only one payment of one amount. The amounts therefore still carry information. In the example above, the alternative 0.05 payment may seem less plausible than the original 0.5 payment if its magnitude is atypical relative to prior on-chain payments and auxiliary context such as exchange rates, timing, fees, and wallet fingerprints. This is essentially the same logic as the unnecessary input heuristics.16 17 And if the adversary happens to know that Alice’s cluster contains a smaller UTXO than the 0.9 one which still suffices for a payment of 0.05, that would be rather strong evidence in favor of the payment amount being 0.5.

Net settlement with cycles

Net settlement is the most general form of multiparty PayJoin. Where NSNR fixed payments among participants, net settlement allows odd and up to net payments to be aggregated: Any participant may pay any other.

Participants settle an arbitrary set of mutual obligations in a single transaction, including cycles (e.g. Alice pays Bob, Bob pays Carol, Carol pays Alice). A participant may both pay and receive payments in the same settlement. The number of participants is in general not observable from the transaction (though in some cases it can be statistically or directly inferred from its structure).

Alice's input 0.6

transaction

Bob's input 0.2

Carol's input 0.5

Carol's output 0.4

Alice's output 0.5

Bob's output 0.4

Alice's input 0.6

transaction

Bob's input 0.2

Carol's input 0.5

Carol's output 0.4

Alice's output 0.5

Bob's output 0.4

A single settlement transaction. Under the ownership assignment shown, the balances are Alice +0.1, Bob −0.2, and Carol +0.1: inputs minus outputs, including fees. None of the individual obligation amounts appear on-chain.

0.5

0.3

0.4

Alice

Bob

Carol

0.5

0.3

0.4

Alice

Bob

Carol

Three mutual obligations, including a cycle.

Once cycles are allowed, a participant’s inferred balance can combine several payments sent and received, as well as their miner fee contribution. It is still a single amount, but its magnitude need not resemble that of any individual payment: Large payments in opposite directions can leave a small balance, including near zero. This weakens the amount-based analysis used in the preceding NSNR example. A small balance is no longer evidence of an implausibly small payment, because it may instead reflect the settlement of several larger obligations.

Since net settlement is strictly more general, if it’s supported in implementations, then every multiparty batch could in principle be a net settlement transaction, even if that’s not actually the case. Conversely, if the only thing actually deployed is the restricted NSNR above, users are forced back into that weaker regime where amounts still leak. The strength of the defense depends on the general form being the norm, not the exception.

Unfortunately, this isn’t enough for privacy, because the resulting graph still has community structure. The adversary doesn’t see only a single transaction; it sees the transaction graph and some clustering of it (which may be based just on the graph structure, or be based on blockchain-external information too). A settlement among counterparties is a slice of an economic network, and economic networks aren’t featureless: They have recurring relationships, and the behaviors can often follow predictable patterns.

Sparse datasets

Deanonymization of networks with exactly this kind of structure is a well studied problem. In 2008, Narayanan and Shmatikov showed that real-world high dimensional datasets are typically sparse — most records have no close neighbors in the feature space — and this sparseness makes deanonymization feasible with only a little auxiliary information, even when that information is noisy.21 22

Any observable pattern in a cluster is potentially useful for such an analysis. These divide into statistical features (fee-rate habits, activity timing and time zone, value distributions) and topological features (the shape a cluster carves through the graph and its links to other clusters). “Topological” is used to refer to the graph structure in order to distinguish it from the structure of transactions, which are more to do with wallet fingerprints.

Wallet (software) fingerprints are a special case of the statistical kind: Signature grinding, fee-rate selection, script and address types, and nSequence and nLockTime conventions each vary from one wallet implementation to the next. While some wallets randomize these, and specific entities may use more than one piece of software, fingerprint-based clustering — both more generally23 24, and also specifically in the context of PayJoin25 — has thus far proven to be extremely powerful. This problem is pretty widespread. In principle, it can be mitigated by the Sisyphean task of making all wallets draw their observable behavior from similar enough distributions to render them indistinguishable. Note that these distributions need not be uniform, nor must every transaction look identical.

Fortunately wallet fingerprints on their own do not have high enough dimensionality to satisfy the sparseness condition: while the software used to create certain transactions might be determined even with low uncertainty, that on its own does not distinguish one user of the software from another. It can nevertheless narrow the population within which other statistical and topological features distinguish a cluster.

Unfortunately, that doesn’t invalidate the general approach. And while minimizing fingerprint leaks is necessary for clustering resistance in a diverse wallet ecosystem, even if it comprehensively fixed that would not be sufficient for addressing these concerns they currently raise, since wallet fingerprints aren’t the only dimensions along which clusters can be compared, and they remain useful when considering a model where sparseness does hold.

Social graphs

Turning to the topological features, in subsequent work,26 the same authors showed that the vertices of two social graphs can be matched iteratively, starting from a relatively small seed matching, which matches some of the vertices of one graph with those of the other.

This builds on the sparseness assumption exploited by the previous work. Here, a “dimension” can be thought of roughly as whether some target vertex is related to some other specific vertex. In a social graph, most nodes will be readily identifiable based on the identities of their neighbors. The actual result in the paper is significantly stronger, requiring only a seed of relatively few matched nodes to iteratively propagate the matching along the graphs. Later work by Narayanan et al. generalized this further to link prediction on incomplete graphs.27

anonymized graph

auxiliary graph

Alice

Bob

Carol

Dave

Erin

Alice

Bob

 ? 

 ? 

 ? 

 ? 

anonymized graph

auxiliary graph

Alice

Bob

Carol

Dave

Erin

Alice

Bob

 ? 

 ? 

 ? 

 ? 

The adversary holds two overlapping social graphs — one identified, one anonymized. The yellow correspondence edges mark the seed of confidently matched pairs, identifying their anonymous endpoints.

anonymized graph

auxiliary graph

1

Alice

Bob

Carol

Dave

Erin

Alice

Bob

Carol

 ? 

 ? 

 ? 

anonymized graph

auxiliary graph

1

Alice

Bob

Carol

Dave

Erin

Alice

Bob

Carol

 ? 

 ? 

 ? 

The only unidentified vertex adjacent to both seeds must be Carol’s, so it’s matched first.

anonymized graph

auxiliary graph

1

2

3

Alice

Bob

Carol

Dave

Erin

Alice

Bob

Carol

Dave

Erin

 ? 

anonymized graph

auxiliary graph

1

2

3

Alice

Bob

Carol

Dave

Erin

Alice

Bob

Carol

Dave

Erin

 ? 

Each match extends the frontier: Dave’s vertex is the remaining neighbor of Bob’s, and Erin’s is the remaining neighbor of Carol’s. The graphs don’t need to agree exactly — the vertex with no counterpart in the auxiliary graph simply remains unmatched.

Suppose the adversary starts with an incomplete clustering of Bitcoin transaction outputs. While the clusters do link together some outputs, because it’s incomplete, there may be several clusters per actual user. So long as the adversary still hasn’t collected enough evidence to conclude that several clusters belong to the same user, that user still enjoys pseudonymity.

This adversary doesn’t just apply CIOH blindly. When it’s first observed, a transaction suspected to be a PayJoin, for example, will have four or more related clusters. Each entity will be represented by at least one input-side cluster and at least one output-side cluster. Naive CIOH would compel merging of all of the input clusters, and change identification may additionally link it to one of the outputs. Subsequent transactions will in turn link to those. The ensuing cluster collapse will of course be avoided by any competent adversary.

Starting with the transaction graph, where coins are vertices, let clusters be represented by undirected edges connecting the linked coins. By edge contraction on these edges, a graph minor analogue28 can be obtained from a given clustering, where all of the coins of a particular cluster are fused into just one vertex representing the cluster itself. The residual edges of this multigraph correspond to transfers of Bitcoin between clusters, so those relationships remain available for analysis.

Reid and Harrigan’s paper4, in its discussion of clustering, introduced the notion of a user network, where vertices are users and edges represent the flows of Bitcoin between them. If the clustering is complete, and each user can be identified with just one node on the contracted graph, that is the user network. Otherwise, when the clustering is incomplete, this cluster graph is better thought of as a pseudonym graph rather than a user network. This is a social network per Shmatikov and Narayanan’s definition.29 The statistical feature distributions of clusters reduce to attributes on the vertices, and both those and the topological features can inform the edge attributes used in their algorithm.

Narayanan and Shmatikov’s propagation algorithm starts with two graph views and a seed correspondence between some of their vertices. Contracting the entire coin graph gives us only one view. To obtain several, we could first partition the cluster-annotated coin graph, for example into epochs, and then contract each subgraph separately. Each resulting graph minor analogue would then present a view of the pseudonym graph over a different period.

Existing clustering supplies the seed correspondence. If a coin in one epoch is already linked to a coin in another, their cluster vertices form a seed pair. Address reuse, heuristics applied to boundary transactions, or auxiliary information can supply such links.

The more active a user is, the more data they expose. Consistent economic relationships can also make their neighborhood recognizable across epochs. Where the views preserve enough of this structure and the adversary has suitable seeds, Shmatikov and Narayanan’s graph matching algorithm can propagate clustering information beyond local heuristics. A proliferation of pseudonyms may limit any one run of the propagation algorithm, but high-confidence matches can still inform other clustering heuristics, and the outputs of other clustering heuristics can be used as inputs to this algorithm.

Epochs are also only one way to partition the coin graph. Another approach would place the boundaries at high-ambiguity regions, where many clusters seemingly connect to many others, as CoinJoins tend to produce. Excluding those densely connected regions can leave components in which each cluster has relatively few neighbors. The adversary can then compare components from different partitions.

As a crude analogy, this is the “opposite” of expander decomposition, a technique that partitions a graph by making sparse cuts in order to decompose a graph into several components, while retaining strong connectivity within each component. Here, the adversary instead decomposes the graph along dense, high-ambiguity regions in order to obtain sparse components whose relationships are easier to match to one another.

Some clustering must already have been produced by another technique for this to work, hence the starting assumption that the clustering is partial. It both supplies the annotations that make contraction possible in the first place and provides the seed correspondence from which graph matching can propagate.

So, even when net settlements call amount-based analysis into question, and the number of parties complicates things further, the nature of social networks and of the transaction graph is that over time, a lot of structure will inevitably be revealed. There’s an expression that illustrates this; I think it goes something like “show [the adversary] who your friends are, and [the adversary] will [successfully deanonymize you].”

Equal amount CoinJoin among arbitrary peers

Every construction so far required its participants to be doing business with one another: a payment, a batch of payments, a settlement of mutual obligations.

A CoinJoin doesn’t have this limitation.30 The participants of an equal amount CoinJoin transaction spend their inputs to produce outputs of the same amount and script type. Traditionally parties are assumed to not be related except in that they are participating in the same transaction, which implies there are no payments settled between them apart from any fees related to the transaction itself, which tend to be low.

Alice's input 0.7

CoinJoin

Bob's input 0.25

Bob's input 0.15

Carol's input 0.55

output 0.3

Bob's change 0.1

output 0.3

Carol's change 0.25

output 0.3

Alice's change 0.4

Alice's input 0.7

CoinJoin

Bob's input 0.25

Bob's input 0.15

Carol's input 0.55

output 0.3

Bob's change 0.1

output 0.3

Carol's change 0.25

output 0.3

Alice's change 0.4

The equal outputs are interchangeable, but the change outputs remain linked to the inputs by their amounts, and Bob’s two inputs are linked to each other by the consolidation forced by a minimum denomination requirement.

PayJoin transactions are made when one party intends to pay another, but in CoinJoin transactions no such relationship between the parties needs to exist. This means they can be chosen randomly from a broader population rather than be constrained by the structure of the real world user network and its economic relationships. While it may seem that this already confounds social-graph analysis, this type of CoinJoin is readily identifiable. A cautious adversary can decline to apply CIOH within it, leaving additional cluster pseudonyms, while still matching the implied user graphs on either side.26 Observable flows between apparent clusters elsewhere in the graph can still expose recurring economic relationships and therefore community structure.

What it can do is introduce uncertainty about the origins of a coin, limiting the ability to perform input-side clustering for any subsequent transactions as well. This slows the rate at which certainty can be gained about clustering structures, but it isn’t a comprehensive or robust defense, and over time, such structures will generally be revealed.31 32

Unfortunately, linking inputs to one another is practically inherent in the equal-amount approach.33 Users generally cannot choose incoming payment amounts or outgoing-payment change to match a CoinJoin denomination, so reaching that denomination often requires combining inputs and almost always produces change. This change is also relatively easy to link to the input clusters, as discussed in the next section.

Turning to the equal amount outputs, their order is presumed to be meaningless, so as long as they’re unspent, they’re interchangeable. But this doesn’t last indefinitely. Any spending transactions of these outputs will reveal more information about an output’s ownership through its timing, fingerprints, and other information that can be incorporated into the adversary’s clustering model.

Furthermore, even though such a transaction only spends a single output, any change left from the payment will, in general, not be of a specific denomination either. To avoid harming the privacy of the payment transaction, this change shouldn’t be linkable to the spender’s other on-chain activity, but even if spent into a CoinJoin, the equal amount approach necessitates consolidating multiple such coins together, which potentially links many “anonymous” transactions to each other, and to subsequent transactions via the change from the CoinJoin.

For example, suppose Alice obtains two seemingly anonymous coins from two independent CoinJoins of the same denomination and spends each in its own payment:

CoinJoin 1

output 0.1

output 0.1

output 0.1

CoinJoin 2

output 0.1

output 0.1

output 0.1

transaction

payment 0.03

change 0.07

transaction

change 0.04

payment 0.06

CoinJoin 1

output 0.1

output 0.1

output 0.1

CoinJoin 2

output 0.1

output 0.1

output 0.1

transaction

payment 0.03

change 0.07

transaction

change 0.04

payment 0.06

Two mixed coins spent independently: Each payment is ambiguous, and nothing links the payments to the same user.

Later, wanting to CoinJoin again, she consolidates the two leftover change outputs:

CoinJoin 1

output 0.1

output 0.1

Alice's output 0.1

CoinJoin 2

Alice's output 0.1

output 0.1

output 0.1

transaction

payment 0.03

Alice's change 0.07

transaction

Alice's change 0.04

payment 0.06

CoinJoin 3

Bob's input 0.13

output 0.1

output 0.1

Alice's change 0.01

Bob's change 0.03

CoinJoin 1

output 0.1

output 0.1

Alice's output 0.1

CoinJoin 2

Alice's output 0.1

output 0.1

output 0.1

transaction

payment 0.03

Alice's change 0.07

transaction

Alice's change 0.04

payment 0.06

CoinJoin 3

Bob's input 0.13

output 0.1

output 0.1

Alice's change 0.01

Bob's change 0.03

The consolidating CoinJoin links the two change outputs, which links the two payments and retroactively identifies Alice’s outputs in both of the original CoinJoins.

In other words, attempting to CoinJoin to recover the change and make it usable for private payments not only fails to achieve that goal, but also undoes the privacy of the previous transactions.

Arbitrary amount CoinJoin

So strict adherence to the equal amount approach leaks information about linkage after the fact. Naive batching, which we glossed over, does too, even without considering the wider context of the graph.34

The Boltzmann link probability matrix35 and Maurer et al.’s sub-transaction model36 are two similar models. They employ a combinatorial approach: Count all the ways the transaction could be partitioned, grouping together subsets of the inputs and outputs into sub-transactions, which are assumed to be the actions of a single party in a multiparty transaction.

What exactly makes a partition a valid sub-transaction mapping is whether or not the sub-transaction is deemed plausible. In Maurer et al., the values of the inputs and the outputs must exactly cancel out, which isn’t sufficiently general for real-world analyses. Boltzmann casts a wider net by allowing these to vary somewhat, accounting for fees (including JoinMarket maker fees).

A large number of possible partitions does not by itself imply much privacy: Most of the probability may be concentrated on just a few of them. Entropy quantifies the uncertainty in this distribution, measured in bits.37 38 39 40

When a sub-transaction mapping is underdetermined, more than one assignment of inputs and outputs to separate sub-transactions remains possible. If several assignments have comparable probabilities, the adversary needs further information to distinguish them. The entropy of the distribution implies a lower bound on how much additional information is required. Output values can be deliberately chosen to create many possible assignments.41

Bob's input 2

Bad CoinJoin

Alice's input 0.3

Bob's input 5

Alice's input 0.1

Alice's output 0.4

Bob's output 7

Bob's input 2

Bad CoinJoin

Alice's input 0.3

Bob's input 5

Alice's input 0.1

Alice's output 0.4

Bob's output 7

Carelessly chosen values are no better than a naive batch: The only sub-transaction mapping consistent with the amounts is 0.1 + 0.3 = 0.4 and 2 + 5 = 7, so a subset sum analysis fully partitions the transaction.

input 0.1

CoinJoin

input 0.4

input 0.2

input 0.5

input 0.3

output 0.7

output 0.8

input 0.1

CoinJoin

input 0.4

input 0.2

input 0.5

input 0.3

output 0.7

output 0.8

With values chosen to be underdetermined, three distinct mappings balance: The 0.7 output can be funded by 0.3 + 0.4, by 0.2 + 0.5, or by 0.1 + 0.2 + 0.4, with the remaining inputs funding the 0.8 output. Across these readings — and the single-owner one — no input is linked to either output.

Alternatively, the assumption that each participant’s sub-transaction is balanced (allowing for fees), can be invalidated. As discussed above, net settlement allows one participant’s surplus to cover another’s deficit while the transaction as a whole still balances. There’s no technical reason why economically related users couldn’t settle within a protocol that also admits strangers to the same transaction. This will also conceal their business relationships better than a purely net settlement transaction structure.

The adversary can also incorporate statistical features, topological features of the surrounding graph, and auxiliary information into its sub-transaction analysis. These can change the plausibility of a mapping which only accounts for the amounts. Neither variant of the model, as originally described, incorporates these additional observables. For this reason, neither net settlement nor overtly ambiguous CoinJoins can offer a comprehensive solution to these problems.

Taking provenance into account

Enumerating the possible points of origin of the funds of a particular coin is fairly intuitive based on the graph structure.42 The entropy of the probability distribution of this candidate set can grow fairly quickly by CoinJoining, especially if an effort is made to diversify peer selection.

However, it can also decay rather quickly. Suppose the adversary successfully deanonymizes some auxiliary user. This can have two very different outcomes:

  • The coins of that user are eliminated as linking candidates when attempting to deanonymize the target user. This is an additive decay of privacy.
  • In addition, the eliminated coins form the boundary between regions of the transaction graph, fracturing it. This is a multiplicative decay of privacy, and the adversary can make progress at an exponential rate when this is the case.

An entropy estimate based on on-chain observations measures uncertainty under the information available to that particular observer. It cannot represent the uncertainty remaining for an adversary with additional information, nor how quickly that uncertainty could shrink.

For example, a chain analysis vendor with KYC information may already be able to separate regions of a graph that still appears highly ambiguous to an outside observer. Users therefore need a safety margin chosen for the auxiliary information their threat model allows the adversary to have.

Robust connectivity

If the CoinJoin graph is robustly connected43, then no small cut separates any output from the mass of its candidate origin coins. Stated differently, every output is connected to its candidate origins by multiple disjoint paths.

This redundancy forestalls the cliff of exponential decay, where privacy becomes much more brittle, extending the duration of the linear decay regime by requiring the adversary to deanonymize a much larger proportion of users before divide-and-conquer tactics start coming into play.

But when two post-CoinJoin outputs are linked, on-chain or otherwise, this makes intersection attacks44 40 possible. In such attacks, we take the candidate origins of these now-linked coins and check for any overlaps.

Bob's cluster

CoinJoin 1

Carol's cluster

Alice's cluster

CoinJoin 2

Dave's cluster

Erin's cluster

Alice, Bob or Carol?

Alice, Bob or Carol?

Alice, Bob or Carol?

Alice, Dave or Erin?

Alice, Dave or Erin?

Alice, Dave or Erin?

Bob's cluster

CoinJoin 1

Carol's cluster

Alice's cluster

CoinJoin 2

Dave's cluster

Erin's cluster

Alice, Bob or Carol?

Alice, Bob or Carol?

Alice, Bob or Carol?

Alice, Dave or Erin?

Alice, Dave or Erin?

Alice, Dave or Erin?

The adversary’s view while the CoinJoin outputs remain unspent: six outputs in two equivalence classes, each output ambiguous among its CoinJoin’s participants.

Bob's cluster

CoinJoin 1

Carol's cluster

Alice's cluster

CoinJoin 2

Dave's cluster

Erin's cluster

Bob or Carol?

Alice's output

Bob or Carol?

Alice's output

transaction

Dave or Erin?

Dave or Erin?

Bob's cluster

CoinJoin 1

Carol's cluster

Alice's cluster

CoinJoin 2

Dave's cluster

Erin's cluster

Bob or Carol?

Alice's output

Bob or Carol?

Alice's output

transaction

Dave or Erin?

Dave or Erin?

Alice’s spend links one output from each class. Tracing each input back — from spent output, through its creating CoinJoin, and to the pre-CoinJoin input clusters — gives the two antecessor sets, highlighted in yellow and red. These overlap only at Alice’s cluster, highlighted as the one node belonging to both: The intersection identifies her, and by elimination also narrows the remaining outputs’ candidate sets: CoinJoin 1’s to Bob or Carol, CoinJoin 2’s to Dave or Erin.

If each additional intersection reduces the remaining candidate set by a constant factor, its size falls exponentially with the number of observations. Starting from candidates, a process of elimination that rules out one candidate at a time will take time to narrow down a single candidate, but if intersections are used to eliminate them then observations may suffice for successful deanonymization.

This holds unless the size of the symmetric difference between antecessor sets is bounded by a constant — i.e. the antecessor sets of linked coins are very similar — because then the size of the intersection is similar to the size of the intersected sets. This attack is powerful because that similarity is rare in practice: The intersection will usually be significantly smaller than the sets themselves.

It’s also important to bear in mind that the candidate origins aren’t coins, but rather clusters, so the objects being intersected needn’t be connected on the transaction graph for the adversary to notice an overlap. This is particularly concerning because the clusters being intersected are the pre-CoinJoin ones, where — presumably — privacy is inherently weak. It’s also worth emphasizing that the change outputs of equal amount CoinJoins are part of these clusters as well.

Next, consider an adversary who is also a counterparty — for example, an ATM in some remote location that sells coins to a user in exchange for cash, and later receives funds from descendants of those coins. Such a counterparty knows, from its own records, exactly which coins it paid out and can observe when descendants of those coins are sold back to it. Connectivity to a crowd of strangers over the internet does little against this, because none of those strangers are likely to have transacted with the ATM, and the CoinJoin doesn’t sever the link from a coin to its past. By the same logic of intersection attacks, privacy loss arising from consolidation of more than one input doesn’t just add up; it compounds. This is known as the Eve-Alice-Eve threat model.

Own-origin robustness

The privileged counterparty knows one endpoint because it is the origin, so the property is stated relative to that origin. It demands that a coin have many plausible, counterfactual paths back to the user’s own antecedent coins.

Suppose Alice withdraws from that ATM, and that is her only means of obtaining Bitcoin. She then CoinJoins with Bob. If one of those coins is then returned to the ATM, its operator can conclude that it is likely Alice.

withdrawal

ATM

Alice's coin

CoinJoin
Alice + Bob

Bob's coin

Alice or Bob?

Alice or Bob?

deposit

ATM's output

withdrawal

ATM

Alice's coin

CoinJoin
Alice + Bob

Bob's coin

Alice or Bob?

Alice or Bob?

deposit

ATM's output

Taken in isolation, the deposited coin is ambiguous: It could be Alice’s or Bob’s.

withdrawal

ATM

Alice's coin

CoinJoin
Alice + Bob

Bob's coin

Alice's output

Bob's output

deposit

ATM's output

withdrawal

ATM

Alice's coin

CoinJoin
Alice + Bob

Bob's coin

Alice's output

Bob's output

deposit

ATM's output

But in this minimal example, the ambiguity is thin. The ATM can conclude with reasonable certainty that the deposit is Alice’s, because it’s much more likely to get repeated business from her than it is for her to randomly interact with Bob just before Bob happens to use the ATM.

Consolidation makes the ATM’s job easier still. Suppose Alice withdraws two coins, mixes each once with a different peer, and then spends the two mixed outputs together:

withdrawal

withdrawal

ATM

Alice's coin

Alice's other coin

Bob's coin

CoinJoin 1
Alice + Bob

Bob's output

Alice's output

CoinJoin 2
Alice + Carol

Carol's coin

Alice's output

Carol's output

deposit

ATM's output

withdrawal

withdrawal

ATM

Alice's coin

Alice's other coin

Bob's coin

CoinJoin 1
Alice + Bob

Bob's output

Alice's output

CoinJoin 2
Alice + Carol

Carol's coin

Alice's output

Carol's output

deposit

ATM's output

Each CoinJoin output on its own is ambiguous, but only Alice is consistent with both inputs of the consolidation, so the deposit identifies her. Additional inputs amplify the ATM’s observing power exponentially.

Suppose instead that Bob CoinJoins with another user, Carol, and then Carol CoinJoins with Alice.

If Carol were to use the ATM at that point, her coin would have inherited Alice’s provenance, which may cause the ATM to incorrectly conclude that it is Alice who is using it. By symmetry, if it were Alice who did that, she gets some degree of plausible deniability.

withdrawal

ATM

Alice's coin

CoinJoin 1
Alice + Bob

Bob's coin

Alice's output

Bob's output

CoinJoin
Bob + Carol

Carol's coin

Carol's output

Bob's output

CoinJoin 3
Carol + Alice

Alice's output

Carol's output

deposit

ATM's output

withdrawal

ATM

Alice's coin

CoinJoin 1
Alice + Bob

Bob's coin

Alice's output

Bob's output

CoinJoin
Bob + Carol

Carol's coin

Carol's output

Bob's output

CoinJoin 3
Carol + Alice

Alice's output

Carol's output

deposit

ATM's output

In this scenario, it is actually Carol who deposits, and the funds were never in Alice’s possession, but their history is interwoven with Alice’s through the CoinJoins, which, by the same logic, would cause the adversary to mistakenly conclude that it is Alice.

withdrawal

ATM

Alice's coin

CoinJoin 1
Alice + Bob

Bob's coin

Alice or Bob?

Alice or Bob?

CoinJoin
Bob + Carol

Carol's coin

Alice, Bob or Carol?

Alice, Bob or Carol?

CoinJoin 3
Carol or Bob + Alice

Alice, Bob or Carol?

Alice, Bob or Carol?

deposit

ATM's output

withdrawal

ATM

Alice's coin

CoinJoin 1
Alice + Bob

Bob's coin

Alice or Bob?

Alice or Bob?

CoinJoin
Bob + Carol

Carol's coin

Alice, Bob or Carol?

Alice, Bob or Carol?

CoinJoin 3
Carol or Bob + Alice

Alice, Bob or Carol?

Alice, Bob or Carol?

deposit

ATM's output

The same transactions from the ATM’s point of view: After CoinJoin 3, the two outputs are equivalent — whichever one is deposited has plausible paths back to the dispensed coin, directly through CoinJoin 3 or via Bob through CoinJoins 1 and 2 — so the ATM cannot tell Alice returning from either Bob or Carol.

Repeated CoinJoins can spread Alice’s coins’ provenance-related features to other users’ coins while spreading their features to hers. This allows her to build up to a quantifiable anonymity set.

Alice's coin

CoinJoin
Alice + Bob

Bob's coin

Alice's output

Bob's output

CoinJoin
Bob + Carol

Carol's coin

Bob's output

Carol's output

Dave's coin

CoinJoin
Dave + Erin

Erin's coin

Dave's output

Erin's output

CoinJoin
Carol + Dave

Carol's output

Dave's output

CoinJoin
Erin + Frank

Frank's coin

Erin's output

Frank's output

Alice's coin

CoinJoin
Alice + Bob

Bob's coin

Alice's output

Bob's output

CoinJoin
Bob + Carol

Carol's coin

Bob's output

Carol's output

Dave's coin

CoinJoin
Dave + Erin

Erin's coin

Dave's output

Erin's output

CoinJoin
Carol + Dave

Carol's output

Dave's output

CoinJoin
Erin + Frank

Frank's coin

Erin's output

Frank's output

Coins are colored by their true owner; a thick blue border marks the coins descending from Alice’s. Dave’s coin picks up the fingerprint when mixing with Carol, for example.

As this set grows, Alice’s chances of CoinJoining her actual funds with such a coin increase with time. If Alice participates in enough CoinJoins so that eventually inputs to the next CoinJoin are already descendants of her prior coin and many such counterfactual paths exist, that can provide privacy even against an adversarial counterparty, which by finding its own coins in the intersection is able to cluster much more reliably than a third-party observer relying on heuristics.

Alice

Bob

Alice

Bob

Carol

Carol

Bob

Dave

Erin

Dave

Erin

Dave

Carol

Frank

Erin

Frank

Bob

Erin

Dave

Frank

Grace

Alice

Bob

Dave

Grace

Alice

Bob

Alice

Bob

Carol

Carol

Bob

Dave

Erin

Dave

Erin

Dave

Carol

Frank

Erin

Frank

Bob

Erin

Dave

Frank

Grace

Alice

Bob

Dave

Grace

Continuing the preceding graph, Bob and Dave spend marked outputs along separate branches. As more marked outputs circulate, more branches can spread Alice’s provenance features. In Alice’s next four-input CoinJoin, Bob’s and Dave’s inputs also descend from her original coin; only Grace’s does not.

When spending more than one coin, the similarity of these provenance features matters because it determines how much their antecessor sets overlap.

To quantify an anonymity set size, Alice can count the inputs belonging to other users that already share her coins’ provenance features,45 i.e. inputs that counterfactually trace back to her origin coins. Many such counterfactual paths imply that intersected candidate sets shrink only at a linear rate, because Alice’s coins would also be in the intersections arising from post CoinJoin linking of coins that have nothing to do with her.

This is the most conservative notion of on-chain privacy described in this document. CoinJoin transactions that have the topological properties discussed — where peers are chosen so as to satisfy these robustness properties — are required to frustrate a real-world deanonymization adversary. Without them, the information required to deanonymize is often revealed in the transaction graph itself, which is already very harmful for privacy, fungibility, and censorship resistance. And this is compounded — perhaps catastrophically — by many other privacy loss vectors outside the graph, such as blockchain indexing services for light clients, KYC information, leaks from data breaches, and transport level information like IP addresses.

Note, however, that this still requires that the other ATM users also CoinJoin; otherwise, Alice’s history will still be unique. Even if she tries to obscure this using “normal looking” transactions, the ATM could still distinguish Alice based on the fact that these transactions descend from the CoinJoin subgraph, simply because those of the other users do not. Determining whether she is the only such user is something that can be judged based on evidence like temporal patterns (correlations or periodic activity). Such patterns are more easily discernible when there are clearly delineated CoinJoin-using and non-CoinJoin-using populations in the transaction graph as a whole.

The adversary can combine amount-based analysis, wallet fingerprints and other statistical features, graph matching, link prediction, intersection attacks, and auxiliary information. A link inferred from one source can change the interpretation of another. These analyses need not run as separate stages, and the auxiliary information may come from public observations, the adversary’s own transactions, or private records.

Censorship resistance vs. privacy tradeoffs and complementarity

The constructions discussed here form a spectrum: unilateral transactions, two-party PayJoins, many senders and receivers, net settlement, and market-based CoinJoin among strangers, constructed with increasing degrees of connectivity robustness.

One end offers censorship resistance and generally weak privacy; the other offers stronger privacy guarantees at the cost of an overt fingerprint.

Note that this doesn’t refer to on-chain censorship resistance specifically; we must take for granted that at least some miners will include CoinJoin transactions for any of this to work. The relevant risk is censorship by businesses — an exchange or custodian that refuses, freezes, or discounts coins by their history, particularly if that history contains privacy-enhanced transactions.46

This isn’t zero sum. The two ends then reinforce each other. The censorship-resistant end gains fungibility and can better resist clustering from being interwoven with the well-connected structure. The robust anonymity end gains censorship resistance by not being an insular sub-economy that rarely touches ordinary transactions.

Multiparty transactions that don’t overtly optimize for an underdetermined sub-transaction mapping can still provide ambiguity, with their susceptibility to censorship based on public information largely reduced to their proximity to the overtly privacy-enhancing ones.

If this spectrum of transaction forms and topological properties is realized on-chain, the distribution of provenance features labeling a user’s output has a better chance of matching the provenance feature distributions of more superficially similar but unrelated coins. Superficially similar coins are those with which it shares statistical features (like value distribution or wallet software fingerprints) or transaction layout features (e.g. size of the containing transaction).

Recall that sparseness is a requirement for Narayanan and Shmatikov’s results. In today’s transaction graph, cluster features — both statistical, and more importantly, topological — are very likely to be unique because there doesn’t exist any wallet software that deliberately blends the topological features. Wallet fingerprints and other statistical features of clusters might not be sparse on their own. But if the social network structure is recoverable from the transaction graph, that will be enough for the adversary to deanonymize most of the graph. Auxiliary information like KYC data might be the basis of such a seed, but just high degree nodes on the social graph, such as well-known mining pools, exchanges, and payment processors may suffice.

Sufficiently ambiguous collaborative transactions would produce coins that share the sum of their inputs’ provenance feature vectors, blending together their fingerprints. This undermines sparseness by construction. The more widely these sums spread, the less sparse the feature vectors of all coins become. For the transaction graph structure to actually be connected in this way requires deliberate effort, but there’s no fundamental barrier to this occurring.

This suggests that some of today’s widely held — but often misleading — beliefs or intuitions about on-chain privacy and fungibility would be more accurate under two conditions: if such mixing of provenance features were pervasive, and if the boundary between such transactions and “normal” transactions were obscured by a network of covert transactions, none of them completely disconnected from the CoinJoin graph.

In other words, imagine a world where some users CoinJoin and construct transaction graphs with sufficiently many disjoint counterfactual paths, as discussed above, and other users engage in net settlement transactions or two-party PayJoins. Crucially, all of these subgraphs are intertwined. In that world, the combinatorial explosion of graph-based features, which today can reveal a lot of information to the adversary, would be rendered mostly inert. By construction, such a transaction graph will not satisfy the sparseness conditions which are required for applying Shmatikov and Narayanan’s approach.

Until such time, be skeptical of claims that PayJoin or even CoinJoin provide privacy against a competent adversary — especially if it’s well funded and is widely known to have access to a trove of high-quality auxiliary information. And even if this does become a reality, please remember that it wouldn’t address the auxiliary information concern, nor thwart any as-of-yet undiscovered analyses that perhaps exploit some subtler leaks. And bear in mind that this depends not just on software, but a critical mass of adoption and assimilation of such privacy enhanced transaction graph structures into the rest of the Bitcoin ecosystem in order to have a meaningful impact on fungibility.


  1. M. E. J. Newman, The Structure and Function of Complex Networks ↩

  2. The common-input-ownership observation appears in passing in the Bitcoin whitepaper: S. Nakamoto, Bitcoin: A Peer-to-Peer Electronic Cash System ↩

  3. For an informal introduction to wallet clustering, see The Scroll #2, Wallet Clustering Basics ↩

  4. F. Reid and M. Harrigan, An Analysis of Anonymity in the Bitcoin System ↩ ↩2

  5. D. Ron and A. Shamir, Quantitative Analysis of the Full Bitcoin Transaction Graph ↩

  6. E. Androulaki, G. Karame, M. Roeschlin, T. Scherer, S. Capkun, Evaluating User Privacy in Bitcoin ↩

  7. S. Meiklejohn, M. Pomarole, G. Jordan, K. Levchenko, D. McCoy, G. M. Voelker, S. Savage, A Fistful of Bitcoins: Characterizing Payments Among Men with No Names ↩

  8. J. Nick, Data-Driven De-Anonymization in Bitcoin ↩

  9. M. Harrigan and C. Fretter, The Unreasonable Effectiveness of Address Clustering ↩

  10. For a narrative history of clustering techniques, see The Scroll #3, A Brief History of Wallet Clustering ↩

  11. The two-party case isn’t exhaustive; the space of collaborative transaction forms is larger; in particular, lightning is probably the most widespread type of two-party transaction. See The Scroll #5, The Many Faces of CoinJoins ↩

  12. Pay-to-EndPoint (P2EP) ↩

  13. R. Havar, BIP 79: Bustapay :: a practical coinjoin protocol ↩

  14. N. Dorier, BIP 78: A Simple Payjoin Proposal ↩

  15. D. Gould and Y. Kogman, BIP 77: Async Payjoin ↩

  16. AdamISZ, payjoin / unnecessary-input-heuristic writeup ↩ ↩2

  17. S. Ghesmati, A. Kern, A. Judmayer, N. Stifter, and E. Weippl, Unnecessary Input Heuristics & PayJoin Transactions ↩ ↩2

  18. Roughly 1.58 bits is the best possible case for a two-input, two-output transaction, which is a rather typical shape. Counterintuitively, while additional inputs seem to suggest linear growth in entropy because of the combinatorics, input consolidation may result in a linear reduction in entropy due to consolidation as a function of the in-degree of the consolidation sub-transaction. See the discussion about intersection attacks below. ↩

  19. rust-payjoin, PR #923 (removal of the experimental NS1R implementation, with status discussion) ↩ ↩2

  20. This concern is not entirely hypothetical; it applies to some CoinJoin capable wallets and Electrum’s “multiple change addresses” mode. ↩

  21. A. Narayanan and V. Shmatikov, Robust De-anonymization of Large Sparse Datasets (S&P 2008; the linked arXiv version is titled How To Break Anonymity of the Netflix Prize Dataset) ↩

  22. A. Narayanan and V. Shmatikov, Robust De-anonymization of Large Sparse Datasets: a Decade Later ↩

  23. M. Möser and A. Narayanan, Resurrecting Address Clustering in Bitcoin ↩

  24. G. Kappos, H. Yousaf, R. Stütz, S. Rollet, B. Haslhofer, S. Meiklejohn, How to Peel a Million: Validating and Expanding Bitcoin Clusters ↩

  25. A. Sabouri, How Wallet Fingerprints Damage Payjoin Privacy ↩

  26. A. Narayanan and V. Shmatikov, De-anonymizing Social Networks ↩ ↩2

  27. A. Narayanan, E. Shi, B. I. P. Rubinstein, Link Prediction by De-anonymization ↩

  28. This isn’t really a graph minor since there are directed edges. In fact, it’s not really a graph because it has both directed and undirected edges. ↩

  29. Strictly speaking, their model involves a directed graph, not a multigraph, but edges are labeled with arbitrary attributes so the information about the various payments can be collected into a rich set of attributes on a single edge representing the relationship between two clusters. ↩

  30. G. Maxwell, CoinJoin: Bitcoin privacy for the real world ↩

  31. G. Danezis, Statistical Disclosure Attacks ↩

  32. C. Troncoso, B. Gierlichs, B. Preneel, I. Verbauwhede, Perfect Matching Disclosure Attacks ↩

  33. This gets worse if coins of a specific denomination are prepared before the CoinJoin, because that setup transaction is highly fingerprintable as a unilateral transaction. ↩

  34. K. Atlas, Weak Privacy Guarantees for SharedCoin Mixing Service (CoinJoin Sudoku) ↩

  35. LaurentMT, Boltzmann, specifically the link-probability matrix. ↩

  36. F. K. Maurer, T. Neudecker, M. Florian, Anonymous CoinJoin Transactions with Arbitrary Values ↩

  37. C. Diaz, S. Seys, J. Claessens, B. Preneel, Towards Measuring Anonymity ↩

  38. A. Serjantov and G. Danezis, Towards an Information Theoretic Metric for Anonymity ↩

  39. P. Syverson, Why I’m not an entropist ↩

  40. For an accessible treatment of entropy and intersection attacks on coinjoin anonymity sets, see The Scroll #4, Intersection Attacks ↩ ↩2

  41. The Radix CoinJoin Denominations chapter. ↩

  42. D. M. Kelen and I. A. Seres, Towards Measuring the Traceability of Cryptocurrencies ↩

  43. Note that being connected doesn’t just mean a path can be traced along the graph, but that the flow of funds along that path appears plausible. ↩

  44. S. Goldfeder, H. Kalodner, D. Reisman, A. Narayanan, When the Cookie Meets the Blockchain ↩

  45. Not exactly the same, since both temporal patterns and the number of hops make a difference. This can be addressed by ensuring the length of the actual path taken is consistent with the distribution of lengths of the counterfactual paths. ↩

  46. Unsurprisingly, the most aggressive compliance posturing has historically often come from businesses that later collapsed, namely FTX, whose executives were convicted of fraud, and BlockFi, which settled SEC charges that included materially false statements before going under in FTX’s wake. ↩

Fungi protocol overview

Fungi is a suite of protocols for collaborative Bitcoin transactions. Its goal is to support interactive payments and net settlement with counterparties, as well as decentralized, market-based CoinJoins with untrusted parties.

While the protocols themselves support arbitrary transaction structures, obtaining privacy outcomes is a matter of participants acting in their own self-interest and cooperating with others to achieve the desired results. The problem definition describes conditions for a transaction graph to preserve privacy on chain. These conditions are specified in terms of properties of the graph, both the transactions that form it and its overall structure. The repository also discusses the definition of a cost function for optimizing for this outcome. That said, the protocols for collaborative transactions summarized in this document are agnostic to the details of such a cost function.

Depending on whether peers must be considered adversarial, and the underlying transport mechanisms, different variations of transaction construction are defined. These are the honest, semi-honest (also known as honest-but-curious) and Byzantine settings.

In the honest setting, we assume peers can be trusted to follow the protocol and never leak any information apart from the final transaction (deliberately or otherwise). In the semi-honest setting we no longer trust peers with privacy; privacy-preserving transports are used to hide the attribution of different transaction fragments. In the Byzantine setting fault tolerance means tolerating arbitrary and potentially malicious behavior from peers, to the extent possible.

These protocols are designed to allow interactive payments with net settlement. While net settlement on its own is beneficial for privacy in some ways, it does not adequately obscure the community structure that is inherent in real-world economic networks. Randomizing peer selection is one of the requirements for building CoinJoin graphs with the desired privacy enhancing properties.

In order to randomize peer selection, the last component needed is the coalition formation protocol. It provides a market-based mechanism to allow mutually distrusting strangers to anonymously start an instance of the Byzantine fault tolerant (BFT) transaction construction protocol.

PSBT concurrency

BIP 174 defines Partially Signed Bitcoin Transactions (PSBTs), which allow a device with UTXO data to prepare a transaction for signing on a separate signing device. Signatures can be collected in any order, so multiple signing devices can be used, with a well-defined procedure for how to assemble everything into a signed transaction that can be broadcast.

While BIP 174 has been used in several collaborative transaction protocols, as specified it can only represent a fully formed unsigned transaction. BIP 370 extends the format to explicitly allow the input and output lists to be modifiable. The fact that these lists are ordered presents a challenge for concurrent transaction construction.

The first component of the Fungi protocol suite is the proposed Concurrent PSBT specification. It treats these collections as unordered sets rather than lists, allowing fragments to be combined regardless of arrival order, not just when collecting signatures but also when authoring the transaction. A consistent ordering is established before signing.

In the “sneakernet” setting participants can pass around a single PSBT file, editing it in turn before handing it to the next party, but with concurrent PSBTs they can also concurrently modify different copies and merge them as well. And anything in between. Because divergent copies can be merged into one coherent transaction, the details of communication don’t need to be specified; it could be a shared directory on a server, or one or more USB sticks, perhaps files shared over email, or some combination of the above.

Consistency, safety and liveness

Consistency has to do not just with peers synchronizing their states, but also detecting when they have been successfully synchronized. Two properties of distributed systems related to this are safety and liveness: safety excludes unacceptable outcomes; liveness concerns whether the protocol eventually completes.1

Because transactions are subject to the safety guarantees of the Bitcoin protocol, collaborative transaction construction can more or less take it for granted. In all transaction construction variants the consistency requirement is agreeing on the exact unsigned transaction. We assume SIGHASH_ALL, which means that a signature by an input only authorizes that exact transaction, with its full list of inputs and outputs. In order to combine the signatures and obtain a fully valid transaction, all of the signatures must be made against the same transaction data.

Because even in the honest setting spending authority is never delegated and signing is unanimous, safety violations (sending money to an unintended destination) are precluded. The unfortunate cost of such unconditional theft resistance is that any input owner can effectively veto a transaction, disrupting the liveness property even if all the other parties agree to proceed with it.

As a result, liveness is inherently brittle. Consistency is a liveness requirement, not a safety requirement, and all of the mechanisms described here are primarily concerned with enhancing liveness without breaking the privacy assurances made to honest participants.

Interactive transaction construction in the honest setting

All of the protocols described here, starting with this one, assume interactivity. The PSBT concurrency spec describes how to merge states without specifying how peers communicate, whereas the protocols prescribe specific messages to be exchanged between peers. Some of these messages correspond to unordered PSBT fragments, and can merged according the concurrent PSBT specification.

An honest participant is one that complies with the protocol. Faulty peers may deviate from the protocol, by being unresponsive or potentially with arbitrary, possibly malicious behavior. In the honest setting we assume that the only kind of fault is being unresponsive. Not only that, peers are additionally expected to keep confidential all of the information pertaining to the protocol’s execution.

🤖 Peers exchange payment details with their counterparties, and send transaction contributions to the group as a whole. The abstract transport interfaces describe this communication as messages on send and receive channels, independently of the transport: authenticated peer to peer channels, and broadcast to the group built from them by gossip.

The honest setting accommodates geographically separated co-signers within a multisig wallet, coordination between separately managed funds within an organization, collaborative batching, and interactive payments. Before signing, every participant checks this transaction, ensuring their funds end up in the destinations they intended. Although the model assumes no malicious edits to the transaction, performing these checks is what enforces safety. Doing this ensures that if the assumption does not hold, the system still fails closed, and any faults that aren’t explicitly accounted for in the model will only lead to denial of service, not loss of funds. Needless to say, this check also applies to the more adversarial settings described below.

Net settlement

One of the motivating use cases for interactive transaction construction is more efficient and private on-chain payments. Several parties can batch arbitrarily many payments into one transaction. Each participant’s inputs and outputs express only the net difference. Individual payment amounts need not appear on chain.

Net settlement adds both safety and liveness considerations. Before signing, a participant must know that its funds reach the intended destinations. It can check outputs returning funds to itself directly; for a payment, it needs the payee to confirm that the transaction satisfies their agreement. This can add sequential dependencies between peers. Within each payment cycle at least one party will receive as much as it sends or more, and can therefore safely initiate a cascade of confirmations. See the concurrent PSBT specification for additional details.

Fault tolerance

Because of the unanimity condition, a peer which is offline and not able to sign its inputs essentially vetoes the transaction even if not intentionally. Transaction construction therefore naturally has two tracks: the optimistic track, which requires unanimity, and the recovery track, which facilitates restarting transaction construction with a subset of participants. Recovery is a permissioned instance of the coalition formation protocol described in more detail in the last section of this overview.

🤖 Liveness is therefore inherently brittle and sensitive to delays. Deciding when a peer is unresponsive depends on what can be assumed about message delivery. The recovery track describes the asynchronous, synchronous and partially synchronous communication models, and what each allows.

Transaction construction in the semi-honest setting

In the semi-honest setting, participants are still assumed to cooperate, but are no longer trusted with privacy. Instead we assume the adversary can see their observations, regardless of whether this information is leaked accidentally or deliberately shared.2

🤖 Preserving privacy therefore requires anonymous broadcast to the group, while payment messages need only authenticate the receiver. The abstract transport interfaces and contacts chapters describe these requirements.

The privacy objective is to avoid revealing anything more than what is inherent in the transaction data to the world, and the minimal payment details to counterparties. Anonymous communication is a necessary but insufficient requirement for this; it does not prevent inference from amounts or transaction structure, nor from the wider transaction graph. The on-chain limitations described in the problem definition still apply.

This setting is inherently more brittle, because when disruptive messages are shared anonymously not only is it unclear how to recover, in general it isn’t possible to tell apart the disruptive messages from the honest ones without some additional mechanism.

Byzantine fault tolerant transaction construction

The semi-honest setting assumes that participants claim only what they are entitled to in outputs, and cooperate until the transaction is successfully constructed and signed. While crash faults can be detected depending on the communication model, there are of course many other ways participants can be disruptive, especially if they have malicious goals like preventing the other parties from transacting.3 A Byzantine fault tolerant (BFT) protocol is one that is resilient to such disruption.

Participation is voluntary, and no party can be compelled to sign. The protocol therefore operates in the non-cooperative game-theoretic setting: any agreement to transact or sign cannot be binding, and must be self-enforcing through incentives in order to have any bearing. We therefore additionally define an honest participant as one which intends to complete the protocol and sign, regardless of which permitted actions the other honest participants choose to take. The agreed conditions must preserve that incentive throughout construction; the coalition formation protocol, discussed at the end of this overview, provides a mechanism for negotiating those conditions and aligning incentives for cooperation. For now we will simply assume that the honest users’ incentives are already aligned when transaction construction commences.

Under the rules of the semi-honest setting a malicious participant might attempt to overspend, causing the combined transaction to be invalid even if signatures are given for all inputs. A malicious peer might also equivocate: give conflicting accounts of its actions to different peers. Or it might simply withhold a signature, causing delays. In the Byzantine setting the honest peers must be resilient to such disruption. This means ensuring flood protection and fairness.

Optimistic transaction construction

The first problem is to establish that transaction fragments are valid without attributing them to specific participants. Validity means that the cost of an output is covered by input funds without double spending. Validity can be proven using zero-knowledge proofs, but this is costly, so we would like to avoid it where possible.

Due to the unanimity condition even in the Byzantine setting, successful termination requires that all participants in a particular transaction construction session comply with the protocol, which includes being responsive. When this happens to be the case, the optimistic approach is to let everything proceed exactly as in the semi-honest setting: Participants anonymously add their fragment, and once everyone acknowledges the same balanced transaction they can simply sign. The Byzantine fault-tolerant variant of Fungi is therefore designed to recover liveness by identifying at least one input controlled by a faulty peer, and then attempting transaction construction again with the faulty inputs excluded. Once all faulty participants have been excluded the honest participants will be able to successfully carry out transaction construction.

Validity proofs

The purpose of validity proofs is to restore the possibility of completion by preventing the same funds from being claimed more than once. The proofs establish that outputs and fee contributions are covered by input funds, including any funds that originate from payments between participants. They must accomplish this without sacrificing privacy, which is why they must be zero-knowledge proofs. They do not replace each participant’s final approval, nor can they compel any participant into providing the remaining proofs or signatures. They ensure that honest, responsive participants can successfully add all of their intended inputs and outputs to the shared state without obstruction.

A widely circulated misconception is that validity proofs in such protocols, due to the use of zero knowledge somehow themselves are a source of privacy. This is false. All they can do is enforce validity, and if done correctly, they can enforce this without requiring privacy to be destroyed.

🤖 Transaction construction describes when proving is required in the optimistic phase, and why the proofs remove any reason for honest participants to withhold their signatures.

Consistency, liveness and termination in the presence of Byzantine faults

🤖 Byzantine faults take different forms, and each is handled differently. An invalid transaction output, one that overspends, is excluded by validity proofs, which reduce it to an omission fault. An equivocated block, two conflicting blocks signed by one validator, exposes that validator’s key, which serves as compact evidence against its coin. Together, these leave delay as the effective attack on liveness: withholding messages, and above all withholding a signature at the end, which is maximally disruptive.

🤖 Since successful termination requires unanimity, a majority agreeing is not enough. Instead, peers agree on the available evidence, such as which inputs’ signatures are missing, and recover by excluding those inputs in another attempt. The recovery track describes this reasoning, and branched execution how recovery attempts proceed alongside the original one.

Synchronizing protocol state

🤖 Peers synchronize protocol state using a block DAG. It is a special case of Byzantine eventual consistency, narrowed in steps: validator blocks with cordial parent requirements, a threshold for each track, one validator taking on the collection work, and optional TEE attestations. The same structure therefore accommodates several communication models and trust assumptions, to suit a variety of client capabilities and circumstances.

🤖 Two things distinguish this from typical DAG consensus, including protocols that switch between modes or tracks. First, the optimistic track requires unanimity, not a quorum. Second, the optimistic and recovery tracks may race, and different sessions may attempt to spend the same inputs. This can’t be prevented in a permissionless setting, and it is useful for replace-by-fee (RBF). Racing is not a safety violation, because Bitcoin itself resolves conflicts between competing transactions. In consensus protocols, by contrast, every mode or track must agree on a single log.

Coalition formation

Until now we have assumed an initial set of participants, some of which will be removed in new branches of the protocol as these are spun off in response to failures. We have not discussed how this initial set of participants is formed. The honest and semi-honest settings imply some degree of trust, which means such groups can form out of band.

The Byzantine setting, on the other hand, is designed to facilitate transacting with potentially malicious, ideally randomly selected peers, because as discussed in the problem definition document, such randomness is required for privacy guarantees to be robust, but this still depends on the initial set of participants being defined. For this purpose we define a coalition formation protocol, and that comes with its own set of challenges, first among which is that it operates in the permissionless setting.

The coalition formation protocol is designed to allow mutually distrusting strangers to bootstrap transaction construction using a market-based mechanism.

🤖 Agreements between strangers can’t be binding without a confirmed transaction, so it operates in the non-cooperative setting, and aligns incentives by redistributing the surplus from collaboration as sats. The background explains why.

This is exactly the mechanism that the coalition formation protocol attempts to build: co-spend proposals are anonymous and confidential proposals, each of which is a bundle of bilateral agreements between the proposer and the owners of the other UTXOs listed in the proposal. The distinguishing feature of co-spend proposals is that they can be aggregated together, which generalizes a JoinMarket-like fee mechanism: it allows multiple “takers” to pay a single “maker” as a kind of group buy, as well as multiple independent “makers”, all in the same transaction. This generality means that the distinction between taker and maker is removed; any participant can play both roles in a single transaction, depending on the co-spend proposals it makes or accepts.

Coalition formation proposals bundle together a collection of co-spend proposals, each of which has been unanimously accepted. Unanimous acceptance of a coalition formation proposal by the owners of all inputs named in all proposals kicks off the permissioned transaction construction with an initial set of inputs, and the terms of the aggregated co-spend proposals in effect. The aggregator role is undertaken by peers proposing coalition formation proposals.


  1. B. Alpern and F. B. Schneider, Defining Liveness (1985). Formal definitions of safety and liveness, and their decomposition of system properties. ↩

  2. A. Paverd, A. Martin and I. Brown, Modelling and Automatically Analysing Privacy Properties for Honest-but-Curious Adversaries. Section II-A defines an honest-but-curious participant as following the protocol while attempting to infer all possible information from legitimately received messages; the paper studies undetectability and unlinkability. ↩

  3. L. Lamport, R. Shostak and M. Pease, The Byzantine Generals Problem (1982). The foundational treatment of agreement in the presence of arbitrary faults, including conflicting messages sent to different participants. ↩

Abstract transport interfaces

🤖 These interfaces give the protocol an abstract syntax for messages. Every part of the protocol is described in terms of messages: who sends them, who receives them, and what a message reveals about its sender. How a message travels is up to the transport.

🤖 Delivering messages is the transport’s job. Its non-malicious delivery faults and delays constrain the timing model the layers above can assume. Agreeing on what was delivered belongs to those layers. Protocol timeouts need not match transport timeouts; see the communication models. Wire encodings are out of scope.

🤖 Channels

  • A send channel accepts messages, one per send.
  • A receive channel yields messages, one at a time.
  • A bidirectional channel is both. Its two directions may carry different message types.

A channel may offer only one direction, and a participant needs only the direction it uses. A receive channel need not belong to one sender: some transports deliver every message for an address to one receive channel.

The protocol should make progress even if a channel delivers only one message at a time. In the asynchronous and partially synchronous models, the network adversary can already impose this.

Kinds of messaging

With some well-defined way to transmit messages from one peer to another, we can start to reason about how synchronization between peers can happen by using interactivity. Communication serves two purposes: peers exchange payment details directly with their counterparties, and send transaction contributions to the group as a whole.

In order to realize peer-to-peer channels, any transport that provides authentication, integrity and confidentiality may be used. This allows peers to send messages to each other directly, for initiating as well as carrying out transaction construction.

🤖 The protocol needs three kinds of messaging:

KindSender
Peer to peerAuthenticated
Peer to groupAnonymous
Peer to worldAnonymous

🤖 Peer to group and peer to world are both broadcast. In line with the literature on reliable broadcast, this specification uses “broadcast” for both. They differ in the broadcast domain:

  • a group is the participants of one session, such as a transaction construction session. Peer to group is also called multicast.
  • the world is open to anyone, such as the readers of a public order book.

🤖 Some uses:

UseDirectionSender
Session initiation with known peers (honest and semi-honest settings)BidirectionalAuthenticated
Interactive payments: notification and confirmation for net settlementBidirectional, reliable, to one peerThe receiver is authenticated and can reply. The sender need not be authenticated, and game theory suggests it shouldn’t be.
Offering co-spend proposals in coalition formationBidirectionalSender anonymous
Anonymous broadcast within a session, such as transaction outputs in the semi-honest and Byzantine settingsTo the groupMessage unlinkable and metadata hiding

Unlinkability

An authenticated channel may identify the sender of a message, which would be problematic for this notion of privacy. Even if the sender isn’t authenticated, transport-related metadata such as IP addresses can leak information about the sender. If transaction fragments are exchanged this way, this can indicate links between inputs and outputs that belong to the same user, even when the final transaction would leave those relationships ambiguous to an outside observer. This is an undesirable trust assumption.

Preserving privacy requires anonymous broadcast to the group. Overlay networks such as Tor can be used to anonymously send messages to peers for relaying. The privacy guarantees of the underlying transport form the basis of message unlinkability, and once a message is not linked to its owner it can be relayed even on a non-anonymous channel. While this can also be achieved without external dependencies, for example using DC-nets, this approach does not scale to large numbers of participants, and is hard to make fault tolerant in addition to still revealing transport-related metadata.

🤖 Two properties describe what a send channel reveals to the peer that receives its messages:

PropertyMessages linkable to each otherMessages linkable to the sender
Message unlinkabilityNoNo
Connection unlinkabilityYesNo
  • Leaving out a sender field does not make a channel anonymous. Identity can still leak through the transport, or be part of it, as when a connecting peer authenticates.
  • Metadata hiding is always with respect to the initiator: the sender, or the side that connects. The responder is identified by its address.
  • A connection unlinkable channel that carries only one message is message unlinkable. The same holds for one set of inherently related messages, such as a transaction input and its signature. Timing metadata can still link messages.

Broadcast from peer channels

Group communication can be built out of peer-to-peer channels; this is known as gossip or rumor-spreading. Alternatively, a specialized broadcast channel implementation can be used. So long as each peer eventually receives all messages sent by every other peer, they will converge on the same transaction fragments, and combine them in the same way to obtain a consistent view of the unsigned transaction.

🤖 Peer to group and peer to world are built by gossip over peer to peer channels that are sender anonymous and message unlinkable.

🤖 A sender submits its message to a member of the broadcast domain over such a channel. From then on, peers relay it like any other message, over channels that need not be anonymous. The anonymity of a broadcast therefore rests on the channel it was submitted on, not on the channels between gossip neighbors.

🤖 Peer and broadcast channels describes the gossip.

🤖 Peer and broadcast channels

Peer to group and peer to world messages are broadcast. Both are built by gossip over peer to peer channels, using the send and receive channels of the abstract transport interfaces. A broadcast channel is itself a send channel and a receive channel, so protocol code that broadcasts sees only those two.

  • Send submits a message to the broadcast domain. The sender does not choose which peers the gossip reaches.
  • Receive yields messages from the broadcast domain. It need not authenticate or distinguish anonymous senders.

Broadcast domains

Gossip always happens within a namespace or topic, which names the broadcast domain.

  • A group namespace is ephemeral. It is derived from a shared secret with a tagged hash, as for a transaction construction session. A secret namespace restricts discovery, but it does not hide authorship, and it does not stop members from sharing it.
  • A world namespace is well known, such as a public order book.

If the namespace includes a block hash, message IDs can be short.

A session’s initiation message binds its namespace to the construction context, including the initial PSBT state and parameters. See session initiation issue #61.

Gossip by itself does not provide reliable broadcast, agreement, a total order, or evidence that every participant has received a message. Those need protocol rules on top. For transaction construction, the block DAG provides them.

Peer to world broadcast

Setup: BIP 322 gossip, online key enrollment

Every spendable coin could potentially be spent in a multiparty transaction (although not all coins can be co-spent). To facilitate this, we require a gossip mechanism for BIP-322 ownership proofs, with a replacement and expiration mechanism for flood protection, committing to a public key referred to as the online key for the coin.

The purpose of this online key is to authenticate the owner of the UTXO without requiring them to access the spending keys for communication. Anonymous authentication requires the use of ring signatures (and are therefore less likely to be supported by a HWW than BIP-322 proofs), and also simplify the mapping to just a single public key per UTXO, regardless of the complexity the scriptPubKey might have (complex multisig or ambiguity from multiple spend paths).

Ownership proofs are also used to estimate input weights. For P2TR outputs, this indicates the spend path intended to be used in any collaborative transactions. Note, however, that this isn’t enforceable.

Each proof’s endorsement of the online key has a validity interval specified in terms of Bitcoin block height or MTP (valid-after and valid-until). When multiple proofs by the same UTXO are nominally in effect, the one with the latest expiry time takes precedence. Ownership proofs commit to a block hash whose height or MTP is within some set interval of the valid-after field.

Flood protection

Online keys may need to be rotated. A rate limiting mechanism is needed for ownership proofs, and more generally for other protocol messages.

Ownership proofs are tied to UTXOs that provides some degree of Sybil protection, since creating UTXOs incurs a cost. However, this is insufficient for flood protection, since there is no restriction on how many ownership proofs can be created.

Note that Sybil resistance for flood protection is a separate concern from Sybil resistance in the context of CoinJoin deanonymization attacks on CoinJoins. The latter is assumed to be encoded of the cost function, and therefore out of scope for this protocol.

To be accepted (and propagated through gossip) by a peer, any newly made proof associated with a coin must have a hash value (e.g. wtxid of the BIP 322 to_sign virtual transaction) numerically smaller than all the other proofs already associated with that output which are known to the peer.

Because ownership proofs may be valid at disjoint time intervals, a peer should store up to proofs (in total, not per validity time interval) in its gossip set for each candidate UTXO, so long as the hashes of all of these are numerically smaller than , where is the total duration of all proofs, and are dynamically set policy values (similar to minrelayfee, based on local resource limits).

Precedence ordering

In addition to rudimentary flood protection for the ownership proof gossip, this defines a clear precedence order. This is so that with respect to a specific block tip, even without global consensus on the set of all ownership proofs, it’s possible to efficiently arrive at the unambiguous mapping from a particular set of UTXOs to the same set of online keys by sharing with peers any relevant proofs they might be missing.

If the online keys are generated by hash chain (similar to LN revocation keys), revealing the key can revoke a previous ownership proof, forcing a linear sequence of key updates, and providing a mechanism for efficient revocation. However, it’s unclear at the time of writing whether revocation is required at all, and the proof of work approach to flood protection seems sufficient.

Similarly, rate limiting could be done by restricting the rate of broadcast on the basis of the committed block hash, but on its own, this wouldn’t establish a precedence order, and in the absence of consensus on the set of ownership proofs, it may result in ambiguities about which online key to use.

Listen advertisements

Peers should only gossip listen advertisements for currently active or soon-to-be-active online keys. The hash of the signature is used as a flood protection mechanism, similar to ownership proofs.

Flood protection for partially accepted proposals

Partially accepted proposals can be communicated directly only between involved peers or gossipped to third parties. Gossip of partial proposals enables a single proposer to make many nuisance offers involving different sets of keys. Normally linkable ring signatures will protect their identity, which means that other nodes can only use a statistical approach to detect the culprit and may mistakenly penalize the UTXOs the attacker names, without their owners contributing to this flooding attack. “Normally” means the key image generator point is just be a hash to curve of the proposal data itself, allowing a practically unlimited number of ring signatures per UTXO (exponential in the size of the candidate UTXO set).

To limit this behavior, the linkable ring signature key image base point can be time dependent (e.g. making use of a sufficiently buried block’s hash as a randomness beacon) and include a truncated hash of the proposal when choosing the generator (by hashing to the curve). Truncating to 10 bits, for example, would allow up to 1,024 unrelated proposals to be accepted or made by a single UTXO equivocation per timestep, allowing flooding to be prevented. Note, however, that honest users may be restricted from accepting some honest proposals due to the birthday bound, but honest proposers with knowledge of other proposals can grind the proposal data to avoid collisions, and we of course assume attackers can do this without restriction).

Additionally, it’s possible to make use of a verifiable encryption scheme for the openings of the commitments, allowing verification of the proposal during gossip, but this doesn’t prevent the broadcast of nuisance proposals that wouldn’t be accepted despite being formally valid.

In contrast, in a semi-honest setting, and if acceptors don’t mind revealing whether they accept to the proposer, the linkable ring signatures can be shortcut entirely and MuSig2 negotiated directly, with the proposer collecting the nonces and partial signatures of all named parties. MuSig2 signing should still be initiated concurrently, even when linkable ring signatures are used to minimize the number of round trips.

Peer channels

A broadcast channel uses two kinds of peer to peer channel:

  • Neighbor channels connect a peer to each of its gossip neighbors. They are bidirectional, and may be authenticated. A neighbor’s authentication identifies the neighbor, not the author of a message it relays.
  • Submission channels carry the peer’s own messages into the broadcast domain. They are sender anonymous and message unlinkable.

Gossip messages

These travel over neighbor channels. The minimal set suffices for the honest setting:

  • announce a message by its hash;
  • pull a message by its hash;
  • push a message that a neighbor pulled.

The semi-honest and Byzantine settings add unsolicited push, used for anonymous broadcast. A peer that receives a new unsolicited message pushes it to one randomly selected neighbor, and announces it to its other neighbors. This is a candidate policy, not an established anonymity guarantee.

🤖 Anonymous submission introduces a message into the broadcast domain. Once received, the message is disseminated by gossip or set reconciliation. The submission mechanism and the subsequent dissemination serve different purposes.

Anonymous submission

  1. The sender pushes its message, unsolicited, to a member of the broadcast domain over a submission channel.
  2. That member handles it as any new unsolicited message. From then on it is an ordinary message in the synchronized set. A message that is not linked to its author can be relayed even on a channel that is not anonymous.
  3. The sender keeps its own message out of its synchronized set until it receives the message through synchronization. It then processes and relays the message by the same rules as any other received message, without using its knowledge of authorship. Until it is satisfied that the message has been disseminated, it continues submitting anonymously.

The broadcast’s anonymity therefore rests on the submission channels, not on the neighbor channels. Removing an author field later cannot undo what the submission channel revealed. If a message is first announced by an identified peer, and then pulled from it, that peer is revealed as the first to hold it, even if later gossip hides the route.

Synchronization

Convergence is the point of a transaction construction session. Each peer therefore synchronizes the set of all session messages with each of its neighbors. Order does not matter: the result is the union of the sets. This includes the blocklace, the session’s block DAG. A peer’s broadcast receive channel yields each message when it first enters the peer’s set.

Every message carries a state commitment: the Merkle roots of the sender’s sets, with height and set sizes. Fetching an ever-growing set of sets is a resource exhaustion risk. Blocks are necessary for progress, and cordiality rate limits them.

Honest peers should converge on the messages to include before producing blocks. A peer should be eager to gossip, but not too eager to produce blocks.

The goal is that all participants, even those with asymmetric capabilities such as limited bandwidth, arrive at the same set of messages. This repeats over multiple epochs.

Dissemination methods

Epidemic gossip is the minimal approach: announce new messages to neighbors, which pull the ones they lack. It works over simplex peer channels. It avoids write contention and multiple readers per destination, and the potential censorship these allow. It will likely win on latency. But announcements are sent for every message to every neighbor, and a peer may hear of the same message many times.

Set reconciliation is a later improvement of blocklace dissemination efficiency. Two neighbors compare their sets and learn which messages each is missing. It throttles or suppresses announcements. Communication then grows with the difference between the sets, not with their size. It will likely win on communication complexity. Range based reconciliation and rateless invertible Bloom lookup tables (RIBLT) are candidates. Multiparty set reconciliation has not been studied as far as we know; recent work covers two parties. A peer can still reconcile with each neighbor in turn. See peer set reconciliation.

Network coding, such as algebraic gossip on top of the same structure, offers a whole spectrum of further possibilities, with some additional complications.

The same building blocks may not suit both peer to world broadcast (coalition formation) and peer to group broadcast (transaction construction). Message counts and sizes also vary: small messages on the happy path, larger ones for validity proofs.

Topology

  • Hub and spoke. Some peers are better connected, and many others connect to them.

  • Clique. Every peer is connected to every other peer, with no distinction between them. A transport that can send to any peer at any time, without a connection, behaves like this.

  • Gossip. Two models apply, both described by Weaver (Unknown Participants, Changing Topologies, and Faulty Devices, PhD dissertation, Georgetown University, 2023, p. 69 and p. 155):

    • In the random phone call model, also called the gossip model, each round a peer exchanges a bounded amount of information with one neighbor, picked at random. The graph is often assumed to be connected (Karp et al. 2000, Boyd et al. 2006).
    • In the LOCAL model, each round a peer exchanges messages with all of its neighbors, and the topology has bounded degree (Luby 1985, Alon, Babai and Itai 1986). Fungi targets both models.

Connection based channels limit a peer to a more or less static local topology, so a connection oriented transport scales well only in the LOCAL model. A transport that is connectionless end to end can send a message to any peer at any time. It matches the random phone call model, or a low capacity clique.

Candidate transports

The specification relies only on the channel properties above. These candidate transports are not part of it. Gossip over any of them provides group and world broadcast. The table says what each provides directly.

TransportDeliveryBroadcast domainSender anonymityTopology
BIP 77 mailboxStore and forwardNone, peer to peerMessage unlinkable towards the directory, if the OHTTP relay and the directory do not collude. Messages to one mailbox are linkable to each other by its ID.Random phone call model: connectionless end to end, so a peer can reach any mailbox. The directory is a hub.
OHTTP pubsubStore and forward, by topicGroup (secret topic) and world (well known topic)As for the BIP 77 mailbox, for each publish and each read.Independent servers, connected to each other or not, like nostr relays. Peers bridge between them.
Nostr with gift wrappingStore and forward, by subscriptionWorldEach event is signed by a one-time key, so it does not name its author. The relay connection still identifies the client, and links the events sent on it.Independent relays, connected to each other or not. Peers bridge between them.
TorConnection oriented, low latencyNone, peer to peerConnection unlinkable. With connection isolation, one message per connection is message unlinkable.LOCAL model: connection oriented, so it scales well only with a bounded number of connections per peer.
NymMessage based mixnetNone, peer to peerMessage unlinkable. Mixing delays and cover traffic resist timing correlation.Random phone call model: connectionless end to end, so a peer can send to any peer at any time.
  • BIP 77 mailbox. BIP 77 payjoin already uses it, with directories reached through OHTTP relays. It suits interactive payments and session initiation with a known peer: the receiver is identified by its mailbox, and the sender need not be.
  • OHTTP pubsub. A specialized service, with topics in place of mailboxes. It would serve group broadcast, and global gossip as well. It runs on a set of independent servers, much like nostr relays. A broadcast domain can span several servers, or be sharded across them, as long as some peers bridge between the servers and keep the network connected. None exists yet.
  • Nostr with gift wrapping. Gift wrapping hides the author in the event, not in the connection. Open gossip that is message unlinkable therefore needs one relay connection per message, over an anonymous channel.
  • Tor.
    • It has by far the most adoption, compared with Nym or OHTTP mailboxes. Anonymity loves company, so Tor is likely the better privacy choice, even though its guarantees are weaker than Nym’s.
    • Its guarantees are stronger than OHTTP’s, with three hops instead of two. Neither resists a global passive adversary doing traffic analysis.
    • It is not usable from a web app or progressive web app (PWA).
    • Being connection oriented, it suits neighbor channels, and submission channels that carry one message per connection, using stream isolation.
    • A cold start is slow, because building circuits takes many round trips. Once circuits are built, a new connection costs about the circuit’s end to end latency, plus the exit node’s connection to the server.
    • A phone waking up pays the cold start. This is the main reason to also support OHTTP: a request takes only a few round trips, because the OHTTP relay keeps its connection to the gateway open. Being request and response oriented, OHTTP also keeps a client’s requests unlinked at the server, without a separate connection for each.
  • Nym. Nym sends to any peer without a connection, so it suits the random phone call model. Mixing adds latency.

Contacts and payment messaging

🤖 Interactive payments need the payer and the payee to message each other. This chapter states what the protocol requires of that messaging. How an application manages contacts, identities and devices, and how it obtains a suitable channel, is up to the application. The protocol only uses the channel it is given, so it need not implement an identity system.

Requirements

  1. 🤖 Reach the counterparty’s device. A peer can send authenticated peer to peer messages to a device acting for its counterparty.
  2. 🤖 Invite it into a collaborative transaction. A payment is made by inviting the counterparty into a transaction construction session. The invitation binds the session’s identity, its initial state and its broadcast namespace. An accepted invitation therefore cannot silently substitute a different session. Receiving an invitation is distinct from accepting the transaction’s terms.
  3. 🤖 Message it during the critical section. After output finalization and before input signing, the counterparties exchange payment confirmations. The messaging must remain available for this.

🤖 The payment relationship can be honest or semi-honest, even when the construction session uses the Byzantine fault tolerant protocol. The confirmations below are how the counterparties check that the shared session satisfies their payment.

Payment communication has different requirements, which also must be provided by the underlying transport. A sender must authenticate its receiver and obtain confirmation that the proposed transaction satisfies their agreement. However, this authentication can rely on a one-time code or pseudonym. The receiver doesn’t need to authenticate the sender in order to be paid securely. Both counterparties know their payment amount, but need not disclose that relationship to the group or identify their transaction inputs and outputs to one another.

🤖 Confirmation during construction

Before signing its inputs, the payer needs the payee to confirm that the output set it will sign is consistent with the payee’s claim that the funds reach their ultimate destination. The confirmation is with respect to the construction state, including payments settled through other participants. It is distinct from confirmation of a transaction on the Bitcoin chain.

The concurrent PSBT specification defines who confirms to whom, in what order, and how cycles in the payment graph are broken. The confirmed construction state is bound to the protocol transcript’s Merkle-set commitment, which is used as the deterministic sort seed. The transcript includes the applicable proofs as well as transaction contributions, so this commitment also binds those proofs.

Counterparties exchange these confirmations after output finalization and before input signing, with respect to that finalized state. An earlier agreement on a payment or maker is not a substitute for this check. Each participant also checks the applicable proof obligations, while the construction protocol supplies its validity and phase-agreement rules.

Market-based coalition formation

Problem definition

In several existing market-based decentralized protocols involving collaborative transactions, a single party initiates and typically bears the costs — for example, JoinMarket or liquidity ads.

Transactions meeting the demand of more than one “taker” can be more efficient, depending on their desired outcomes. CoinJoin privacy in particular is a non-rivalrous positive externality obtained by each participant from the other participants, and as such, it’s an inherently positive sum.

The following protocol aims to generalize the type of order matching JoinMarket supports, allowing multiple users’ intents to be aggregated together.

Overview of proposed solution

This document describes a permissionless, peer-to-peer protocol for negotiating the initiation of a collaborative transaction construction. This takes place over two primary phases: bilateral negotiation, followed by aggregation. Successful execution of the protocol results in a coalition of UTXO owners unanimously agreeing to build a transaction together.

This isn’t a transaction construction protocol, but a precursor to such a protocol. This protocol bootstraps a compatible transaction construction protocol by finding consensus on an initial set of UTXOs whose (honest) owners intend to spend them in a collaborative transaction. Refer to the last section for a brief discussion of such a protocol and how it composes with this one.

Bilateral negotiation

A proposer, the owner of one or more UTXOs, selects UTXOs belonging to others from an “order book”. The proposer initiates peer-to-peer bilateral negotiations with the owners of these coins by sending them a message that includes a co-spend proposal. This expresses an intent to cooperate to spend this set of coins together in a single Bitcoin transaction.

Co-spend proposals are publicly verifiable, confidential adjustments to the effective values of the specified coins. These adjustments can represent arbitrary payoff structures. Whether a proposal takes effect (i.e. the adjustment is applied) is contingent on the constraints specified in the proposal being satisfied in a transaction construction session intended on spending the specified UTXOs. For example, a proposal may require that non-SegWit inputs be excluded for TxID stability, or that the feerate be within an acceptable range, among other constraints.

Co-spend proposals rely on cryptography to keep each coin’s adjustment hidden, except for that coin’s owner and the proposer. The proposer’s UTXO is indistinguishable from the other UTXOs. Before a proposal is unanimously accepted, it isn’t known which UTXO owners have accepted the proposal.

Aggregation

Co-spend proposals aren’t exclusive. Many proposals can be aggregated together before collaboratively constructing a transaction in which the combination of all the aggregated proposals is in effect. The UTXOs specified in proposals that are aggregated together may overlap but don’t need to; the main requirement is for the constraints to be compatible.

Fully accepted proposals can be broadcast and then aggregated with other compatible proposals. Aggregation makes it possible for multiple participants to simultaneously optimize for their desired outcome according to their individual preferences. When they value privacy, or any other kind of positive sum interaction, aggregation generates surplus from which all participants may benefit.

To aggregate, several proposals are bundled together with a coalition formation proposal that all parties must agree to. Unanimous acceptance of such a coalition formation proposal signals that everyone is ready to construct a transaction.

Because transactions are only valid if all inputs are signed, multiparty transactions require unanimous agreement. A precondition for denial of service protection in privacy preserving multiparty transaction construction protocols is incentive compatibility for the honest participants. No honest participant should have a reason to withhold their signature.

The primary purpose of this protocol is to construct an imputation, which is a payoff distribution over the inputs. This aligns incentives for successful transaction construction while maintaining confidentiality of the individual payoffs.

Background

Hedonic games and games with transferable utility

Coalition formation games, in game theory, typically refer to the cooperative game theory setting, where agreements are binding and can be enforced by some kind of mechanism. While Bitcoin can provide such a construct, analogously to the function of the court system, the current consensus rules require some kind of contract to be anchored in a confirmed transaction, i.e. binding agreements require creating new transactions and waiting for them to confirm.1 In order to build transactions without having already built transactions, we must therefore assume the non-cooperative setting. Coalition formation in the non-cooperative setting can only rely on incentives.

When preferences over the coalition structure are in play (the cost function), in so-called hedonic games, it is often very hard (also in an algorithmic sense) to find stable coalition structures, as the preferences of the participants may conflict. In their most general form, such game descriptions are enormous as the preferences are defined over a large combinatorial object. Even when many assumptions are made, like constraining the kinds of preferences the participants may have, it is still generally hard to find stable equilibria.2 Complicating matters further, sharing the preferences would itself be a privacy leak, so we would prefer to limit that as much as possible, and certainly we cannot assume a mechanism that optimizes outcomes by just being able to read these preferences.

Fortunately, some of these difficulties of hedonic games can be bypassed with the introduction of a transferable utility, and assigning the coalition itself a payoff, which can be redistributed. In our use case this payoff originates from any blockspace savings from net settlement, and the privacy benefits from collaboration. This surplus is not observable, it is the sum of subjective payoffs depending on individual participants’ preferences (which in turn depend on their circumstances, privacy threat model, etc). While this does not guarantee stability, if a stable coalition structure exists, a transferable utility can make the process of finding one much easier by iterated bilateral negotiation. However much these benefits are worth to participants, if this surplus exists, then it can be voluntarily redistributed as sats among the participants (i.e. via a fee mechanism) aligning incentives for collaborative transaction construction, so that all coalition members stand to gain from participating.

Coalition formation games output a partition over peers. Finding stable equilibria in such games is generally difficult. Depending on the structures in the preferences of the peers, many special cases described in the hedonic games literature are still hard. In the byzantine setting appropriate for Bitcoin protocols, no such structure can be assumed, which makes finding stable partitions intractable.

Since the participants in the protocol unilaterally control independent UTXOs during the execution of this protocol, we’re constrained to the non-cooperative setting, where agreements are non-binding and can’t be enforced. Additionally, for privacy, the cost functions should remain hidden so that no mechanism can access the peers’ preferences and globally optimize. Note that due to the nature of revealed preferences, the cost function can’t be fully hidden.

Fortunately, the introduction of a transferable utility greatly simplifies finding stable coalition structures, even under these assumptions. Bitcoin can approximate such a transferable utility. This makes it possible to simply assign payoffs to the coalitions and allow them to be distributed among the peers through bilateral negotiation. If Alice prefers not to co-spend with Bob, but Carol strongly favors both Alice’s and Bob’s participation, Carol is able to compensate Alice, so that as long as the coalition generates some surplus, all parties will be able to obtain a positive payoff.

Transaction construction liveness assumptions

For a coalition of peers, of which are adversarial, liveness for transaction construction can be achieved (with privacy) by the honest subset of peers in time. Any defection requires transaction construction to start over. Due to random network disruptions, necessarily some rate of (apparent) defection must be tolerated.

Because exclusivity of spending attempts by inputs can’t be enforced without global consensus, and because transaction replacement is desirable for fee market efficiency, we assume inputs are allowed to participate in concurrent sessions, which will result in conflicting transactions. Opt-in signalling can be used and obeyed as a courtesy, but this ultimately reduces to the same liveness model as transaction construction, potentially requiring additional attempts to recreate the transaction.

Cost functions

This protocol is mostly agnostic to the cost function that describes the peers’ preferences.

Much like in the problem of coin selection (which this work aims to generalize), the cost function is denominated in sats, and it’s the combination of objective terms (i.e. the fee cost) and subjective ones (any positive utility obtained from transacting, which by definition must dominate over the objective costs for a self-interested, not necessarily honest peer to agree to sign the transaction).

Although out of scope for this specific document, privacy-related terms are assumed to quantify things like how much cover other peers’ coins provide in Maurer et al’s sub-transaction model, or an estimate of the cost to an adversary of an deanonymization attack (for instance, an adversary using older coins incurs a higher cost to do such an attack, as that liquidity must effectively be locked up to become old).

A precondition for liveness is that any such cost function is monotonically decreasing in new information revealed during transaction construction.

Concretely, this means that whenever the action of some peer is revealed (i.e. when an input or output is added), at worst, other peers should be indifferent to this, but they may also obtain positive utility. If this isn’t the case, parties may rationally choose to defect. The purpose of the constraints in proposals is to allow the honest subset peers to avoid such non-malicious conflicts a priori. Since monotonicity is required for liveness, a peer that engages in the protocol without adhering to this restriction and refuses to sign is deviating from the protocol, and therefore by definition not a member of the honest subset.

Simplified example

Note that this example omits many details discussed below.

Alice, Bob, Carol, and Dave are owners of UTXOs , , , and , respectively. Alice wants to CoinJoin with Bob and Carol. She creates a co-spend proposal with UTXOs . In this proposal, she adjusts her UTXO down by 100 sats, and adjusts and , perhaps up by 50 sats each, providing an incentive for Bob and Carol to accept. She sends this to Bob and Carol, who accept, after which the proposal is fully accepted and broadcast.

For all Bob knows, either Carol or Alice made the proposal, and the same goes for Carol, not knowing if it was Alice or Bob. Bob only learns that he was offered 50 sats; he doesn’t learn how much Carol (or whomever) was offered. All Bob knows is that the 50 sats, which he would receive if a transaction was constructed with this proposal in effect, would be paid for by one of the UTXOs .

Carol also wishes to CoinJoin with Alice and Dave. She creates a co-spend proposal with UTXOs , and adjusts down by 50 sats, up by 20, and up by 30. This too is unanimously accepted and broadcast.

Dave then notices both proposals are compatible, and chooses to aggregate them together. He produces a coalition formation proposal, which depends on these two proposals. The coalition formation proposal chooses a specific feerate, among other things, combining the constraints of both previous proposals. It names as the UTXOs.

Once all parties accept Dave’s proposal, consensus has been bootstrapped. Everyone can derive the same total adjustments: , , , . In general, only the owner of each coin knows their final adjustment, but in this example, Carol knows that Dave obtained because her proposal is the only one that applies to his coin, and likewise Alice knows Bob obtained .

All peers can then proceed to transaction construction, where each party is entitled to add up to their adjusted value’s worth in outputs. They may add additional inputs and arbitrary outputs, so long as for each peer, the sum of the outputs’ effective cost doesn’t exceed the sum of the adjusted effective values of that peer’s inputs.

Technical details

Setup: BIP 322 gossip, online key enrollment

🤖 Ownership proofs and online keys are specified under peer to world broadcast, together with the gossip, flood protection and precedence ordering rules for them and for listen advertisements.

Negotiation: Listen advertisements and/or gossip of partially accepted proposals

Short-lived listen advertisements may be signed by “makers” using their online keys to indicate that the owner of a UTXO is soliciting proposals pertaining to its spending over the named communication channel.

“Takers” evaluate listening coins and can construct proposals (defined in the next section) over the specified communication channels.

Alternatively, negotiation with listening but unaddressable UTXO owners can be made possible using an opt-in gossip layer. On this layer, it’s permitted to broadcast partially accepted proposals. See below for a discussion of flood protection considerations in this setting.

Listen advertisements can specify constraints for proposals being entertained, indicating that proposals outside of the constrained subspace (see coalition formation proposal details below for specifics) are unacceptable at any price.

Finally, listen advertisements also indicate the owner’s willingness to serve as a validator node in transaction construction, as either demanding to be a one, opting in at the aggregator’s discretion, or declining. The aggregator has an incentive be a validator (and to do so honestly), but is not required to.

Co-Spend proposals

Co-spend proposals specify a set of outpoints of coins intended to be spent together. Fully accepted proposals take effect contingent on the conditions they specify, such as the range of feerates the offer is valid under, nLocktime ranges, or whether or not txid stability is required (i.e. only SegWit inputs). The effect of a proposal is some confidential redistribution of the input funds, e.g. fees negotiated between the transacting parties.

Making and ratifying co-spend proposals

A proposal specifying UTXOs can have linkable ring signatures by the associated online keys of the named UTXOs.

While , a proposal is only partially accepted. Which of the peers have accepted a partial proposal is kept hidden by the ring signatures. This includes keeping the proposer anonymous within this set of signers; technically, the proposer is just the first to accept, and at least one peer needs to accept for anti-Sybil flood protection reasons.

If linkable ring signatures with distinct key images have been collected, then a proposal has been unanimously accepted.

Finally, for a proposal to be fully accepted, the linkable ring signatures are replaced with a single Schnorr signature made by the MuSig2 aggregate key formed from the set of associated online keys of the UTXOs. This reduces the size, as well as the computational cost of verifying proposals. Because all parties have accepted, no single party can deny having signed. This makes a joint multisignature semantically equivalent to the individual linkable ring signatures. The deniability of linkable ring signatures only makes a difference during negotiations before all parties have accepted.

Fully accepted proposals can then be broadcast for aggregation. A fully accepted proposal indicates that all owners of the specified UTXOs have some interest in this proposal being in effect.

Individual proposals commit to a specific set of BIP 322 ownership proofs so that the signatures on them are verifiable. Proposals that refer to expired ownership proofs are still considered valid, and more generally, proposals that commit to different ownership proofs are potentially valid as long there is a non-expired ownership proof associated with the UTXO, which is also used for input weight estimations. See the coalition formation proposal section below for details.

Co-spend proposals aren’t updatable or revocable once fully accepted, but they do have an expiry (specified in block height, MTP, or UTC time). More than one signature on the same proposal should be considered a flooding attack by all participants, and honest parties should only sign (MuSig2) a proposal once. Again, see below for discussion of flood protection with respect to partially accepted proposals.

However, co-spend proposals are able to explicitly include conflict hints for other proposals, indicating that (at least) the proposer of the conflicting proposal wouldn’t accept a coalition formation proposal that depends on the excluded proposals.

Effective value adjustments

Proposals verifiably redistribute sats among the UTXOs by adjusting their effective values. Corresponding to each UTXO, a homomorphic value commitment to an adjustment term is included. This adjustment can implement fee payments between peers, and it may be positive or negative for every UTXO.

The sum of all the adjustment value commitments in a proposal is a commitment to the sum of the adjustments. This value, the surplus of a proposal, is included in cleartext, and the sum commitment is proven to commit to it in a balance proof. This too may be positive or negative.

When communicating a partial proposal, the proposer shares with each recipient the opening of the commitment associated with their UTXO. This payoff is denominated in sats, and it can be positive or negative.

Each adjustment value commitment is also covered by a range proof certifying that the adjustment is a small positive or negative integer. Small means at least , where is the minimal effective value among all specified UTXOs. This minimum value is computed by taking the highest acceptable feerate in the proposal conditions and multiplying that by the input weights estimated from the ownership proofs.

The sum of the adjustment commitments, when tweaked by the effective value of the UTXO according to the final feerate of the UTXO, must be a commitment to a positive number of sats. This is ensured by accounting for the maximum values in the range proofs, and by ensuring it doesn’t overflow the effective value.

Imposing a minimal range width size imposes a limit on how many proposals can be aggregated together, roughly logarithmic in the total value to be spent. Proposals can use wider range proofs than the minimum, which limits their ability to be aggregated and leaks information about the size of the adjustments.

Proposal aggregation and condition details

A coalition formation proposal is a special kind of co-spend proposal that aggregates together a bundle of non-conflicting, fully accepted co-spend proposals. The coalition formation proposal is made by one of the peers, the aggregator, to all other peers implicated in the aggregation. The aggregator must also set specific values for any constrained parameters (e.g. a concrete feerate and not just a range).

Making and ratifying coalition formation proposals

Any peer may attempt to construct a coalition formation proposal by aggregating unanimously accepted co-spend proposals together, so long as it controls at least one of the online keys implicated in the aggregation. For rate limiting, the aggregator’s key is made explicit, and the hash of this signature is used for flood control when gossipping the partially signed coalition formation proposal, much like the hash of ownership proofs.

Unlike co-spend proposals, coalition formation proposals are accepted with a regular signature by the online key. This makes them tractable for aggregators to make coalition formation proposals that revise the payoff or omit peers who didn’t accept. As discussed above, coalition formation proposals aren’t mutually exclusive. If a peer rejects a coalition formation proposal due to the inclusion of a specific proposal, it may broadcast a counter final proposal of its own, so there’s no mechanism for explicit rejection.

A coalition formation proposal also specifies a concrete transaction construction protocol version, and commits to a specific set of listen advertisements associated with the specified UTXOs, which have either demanded or opted into serving as validators. These peers agree to allow other peers to connect to them and facilitate in gossip. Depending on the liveness requirements of byzantine agreement for the subsequent transaction construction protocol, the aggregator may specify validators at their discretion and named parties may accept or decline.

Bootstrapping consensus for transaction construction

Once a coalition formation proposal is fully accepted, a coalition has been formed, complete with a payoff imputation. The online keys are then used to initiate a consensus protocol to construct the full transaction.

Since the coalition formation proposal addresses every UTXO, its ownership proof set commitment is authoritative. This determines the canonical online key set for the coalition, allowing a consensus protocol to be initialized. The aggregator should use precedence ordering for symmetry breaking to minimize additional gossip and improve the chances of the coalition formation proposal being unanimously accepted, but there’s no consensus state for this data at the time the coalition formation proposal is being authored. The purpose of coalition formation proposals is to bootstrap both the consensus protocol and incentive compatibility to make use of it.

Coalition formation proposal structure

🤖 The surplus of all included co-spend proposals belongs to the coalition. The aggregator proposes adjustments for each UTXO and an amount to allocate to mining fees. Some or all of the surplus may be allocated to mining fees, which must cover the shared transaction fields at the agreed feerate. These allocations take effect only if the coalition formation proposal is unanimously accepted.

The logical conjunction of co-spend proposals implies the union of their adjusted UTXOs and the intersection of their conditions is in effect. The per-UTXO adjustments are collected for each outpoint. The total adjustment for each UTXO may not overflow its effective value, based on the range proof widths.

Co-spend proposals therefore form a commutative semi-group, unioning the sets of UTXOs and summing the adjustments component wise. It’s only a semi-group because proposals can’t always be aggregated together. One reason for this is that the conditions might be mutually exclusive. Another is consensus rules (e.g. OP_CLTV making conflicting assertions).

Conditions are intersected elementwise. The intersection of mutually exclusive conditions — for example, a time-based vs. a height-based nLocktime — is empty, precluding the combination of such proposals.

The following are all numerical intervals under intersection:

  • Transaction consensus fields
    • version
    • individual flag bits (top is {0,1} then {0}, {1}, bottom is {})
    • nIns
    • not included: nOuts, (min cannot be enforced and so can’t be included, max is enforced indirectly by vbytes allocation see below)
    • nSequence (constrains all nSequence fields)
    • nLocktime
  • Non-consensus parameters
    • feerate
    • max total vbytes per tx (divide by nIns and round down for allocation per input, nIns must be set accordingly to pass standardness or consensus limits)

The following are sets under intersection:

  • Allowed input types (catchall “unknown” or “arbitrary” as one of the variants, variants for standard or well known output types)
  • Allowed output types

Flood protection for partially accepted proposals

🤖 Gossip of partially accepted proposals, and its flood protection, is specified under peer to world broadcast.

Post quantum security and privacy

Apart from the BIP-322 ownership proofs, which are related to spending keys, the signatures used throughout don’t require PQ security for privacy (assuming perfectly hiding commitments) or safety, but only for liveness.

However, for privacy, it’s important that any proofs of knowledge of openings of the commitments don’t compromise the unconditional hiding of commitments, so as to avoid “harvest now, decrypt later” attacks on anonymity (although out of the scope of this document, this is also required for transaction construction).

Secondly, in addition to the secp256k1 online key, a PQ key for end-to-end encrypted communication (e.g. the encrypted openings of commitments included in a proposal) can also be used. HPKE is an obvious choice for secp256k1-based encryption, and hybrid HPKE is specified using ML-KEM, which makes it a relatively simpler change. However, neither of these is verifiable without general purpose ZK, which is often costly for the prover or in proof size. Lattice-based schemes (without a symmetric cipher) seem potentially amenable to such verifiable encryption, but I have yet to look into that. Verifiable encryption is necessary for partial proposal gossip, as otherwise there’s no guarantee that the proposal can even be accepted, as some parties may not learn the opening of the value commitments associated with their UTXOs.

Finally, PQ privacy must of course also assume that metadata privacy at the transport layer is also preserved.

Transaction construction protocol

🤖 The accepted coalition formation proposal specifies the initial inputs, their online keys, the negotiated adjustments and the parameters for transaction construction. It is the genesis of the construction instance. The initial state can be proven valid with respect to each UTXO’s adjustment sum commitments, which enforces that the agreed imputation is in effect. When construction stalls, the recovery track turns the stall into a new coalition formation proposal among the responsive subset.

🤖 Any participant can act as an aggregator. Assembling a proposal gives that participant no additional privileges during transaction construction.


  1. For example CoinSwap is such a protocol which relies on atomic swap contracts, designed with privacy in mind. ↩

  2. D. Peters and E. Elkind, Simple Causes of Complexity in Hedonic Games (2015). Shows how modest expressiveness in preferences can make deciding the existence of stable outcomes computationally hard. ↩

Transaction construction

🤖 Transaction construction starts from an accepted coalition formation proposal and ends with a signed transaction. This chapter describes it in the abstract. Its sub-chapters define the block DAG that the tracks share, and describe each track.

🤖 Content and state

Construction synchronizes two different things:

  • Content: the transaction-level messages, such as inputs, outputs, fee contributions and their proofs. The validity proofs constrain which content is valid.
  • State: which admitted content is in the agreed state of each phase. State synchronization uses agreement-level messages, the validator blocks. Validity proofs do not cover blocks. Blocks have their own mechanisms, such as the nonce commitments that expose the key of a validator that equivocates.

Transmitting either between peers is described in peer set reconciliation.

🤖 Phases

🤖 The initial inputs are already fixed by the accepted coalition formation proposal. The optimistic phases add content without validity proofs. They concern transaction data, and are not to be confused with the optimistic track, which concerns agreement. The optimistic phases are the semi-honest construction, including when it is used in the Byzantine setting.

🤖 Every message is keyed: it relates to one input, one output or one fee contribution. Phases differ in whether their keys are listed when the phase opens or arrive anonymously.

PhaseKeysContentNext
1. Kickofflisted: initial inputsacknowledgement of the proposal2
2. Optimistic auxiliary inputsanonymousauxiliary inputs, without proofs3
3. Optimistic outputs and fee contributionsanonymousoutputs and fee contributions, without destination commitments or proofsbalance zero: 8; overflow: 4
4. Initial-input proofslisted: initial inputscommitments to allocations of funds and vbytes5
5. Auxiliary-input proofsanonymousproofs authenticated by each auxiliary input’s own online key, consuming initial inputs’ vbyte allocations6
6. Allocation registrationanonymousproofs of allocations against the session root7
7. Output proofsanonymousproofs of coverage against the registered-leaf root8
8. Signatureslisted: final inputsinput signaturesdone

🤖 Phases 4 to 7 are the proven phases. They run only if the optimistic outputs and fee contributions overflow the available balance. The optimistic outputs are then discarded, and the proven phases use fresh, unguessable output ids. Once phase 5 closes, both input-proof sets determine the session root; the closed registration set determines the registered-leaf root. Output scripts are authorized as specified by the validity proofs. On the optimistic track, only a balance of zero continues to signatures. Unclaimed balances are possible only on the recovery track, which is a different termination path. How output values are chosen is a matter of strategy, not of this protocol.

Each phase closes on a stable state before the next one starts. The optimistic track says why, and gives the acknowledgement rule for each kind of phase. The overview describes the honest, semi-honest and Byzantine settings these phases run in.

🤖 Tracks

Both tracks use the block DAG.

  • Optimistic track, with threshold . It is asynchronous, and phases advance by unanimous acknowledgement. On its own, it is sufficient in the honest and semi-honest settings.
  • Recovery track, with . It is optional, and assumes synchrony or partial synchrony. It turns a stalled phase into a recovery coalition formation proposal.

Validity proofs

🤖 Validity proofs are needed only once overspending is detected. They reduce the validity of transaction-level messages to omission faults: a participant can still withhold a message, but cannot get an invalid one accepted. They enforce:

  • No inflation. Amounts are non-negative, and the outputs sum to at most the value of the inputs. What no output claims is fee.
  • 🤖 Flood protection. In the proven phases, auxiliary inputs consume initial inputs’ vbyte allocations, registrations consume input slots, and each output claims a registered leaf. In the optimistic outputs phase, every output or fee contribution accounts for at least 1 sat, so the available input balance bounds contributions before overflow. An overflow signal can trigger proving, but the phase still closes under its normal agreement rule. These are contribution bounds, not bounds on all network traffic.
  • Session binding. No statement can be replayed in another session.

🤖 They enforce this without revealing how a participant splits its inputs’ value among its outputs and payments. Payment satisfaction is checked by counterparty confirmation before signing, as the concurrent PSBT specification defines. In the proven phases, a receipt additionally proves that the payment allocation was claimed; it does not replace confirmation.

In the optimistic phase, no proofs are needed if every participant can verify that all of its funds are accounted for in its outputs and fees contributions, and no overspending has occurred, and everyone acknowledges that exact state. Overspending triggers proving so that contentious outputs and fee contributions can be validated. An anonymous, oversized fee contribution permits any participant to abort the optimistic phase and force validity proofs to be required.

Only valid transactions have consequences for the owners of the inputs, because an invalid transaction cannot actually spend any coins, even if fully signed. The sense in which the fragments themselves must be valid according to the proofs is that when combined they would result in a valid transaction if it were fully signed. Taken together with the incentive compatibility assumption, the lack of obstruction removes any reason for honest participants to withhold their signatures: by following the protocol their funds will be sent to the destination they intended, and since this applies to all participants, this removes any valid reason for honest participants to withhold their input signatures.

Block DAG

🤖 Both tracks use the block DAG defined here.

Synchronizing protocol state

The abstract state sharing requirements of transaction construction can be realized by a family of related constructions.

🤖 These constructions form a ladder of increasingly narrow special cases. Each step restricts the one before it, so every structure further down is still an instance of those above it:

  1. Byzantine eventual consistency: a hash-linked causal log of authenticated messages.
  2. A block DAG with cordiality: a fixed set of validators, each block referring to blocks of the previous height.
  3. A threshold per track: on the optimistic track, on the recovery track.
  4. One validator collecting: the others acknowledge its blocks. This splits the workload within the same model, on either track.
  5. TEE attestations: an optional extension to all blocks, which certain clients can choose to trust, even when they act as validators.

Byzantine eventual consistency

The general starting point is Byzantine Eventual Consistency (BEC) by Martin Kleppmann and Heidi Howard.1 In this model, messages, or transaction fragments as in our case, are committed to a Merklized causal log. For example, if Alice is adding an output, the output itself would be the payload of her message, and the envelope would contain references to Alice’s last message, as well as the messages of other peers, referenced by hash.

In the naive version of their protocol (they describe a more optimized version), whenever a message is received, if the receiving peer does not know what a hash in its references commits to, it will request the preimage from the peer which sent this message, and after a finite number of such recursive queries and round trips it will eventually reach a message it has already seen. Signatures on the messages authenticate their authorship, allowing messages to be relayed via intermediate peers, and for any equivocations to be detectable. If the payloads are subject to validity constraints and merging independently accepted updates preserves these constraints, as Kleppmann and Howard show, this is sufficient for Byzantine eventual consistency: loosely speaking, even in the presence of Byzantine nodes, honest peers will eventually converge on the same set of messages.

For privacy-preserving transaction construction, the payload should be a list of transaction fragments delivered anonymously to the peer which constructs the message. In the general BEC construction, these messages form a directed acyclic graph (DAG), with each honest peer’s messages forming a linked list which also links into the linked lists of other peers. BEC itself does not require the depths of these lists to be synchronized or bounded; the block DAG specializations below impose additional structure.

Because in our setting they collect several state-related messages submitted by other participants, we’ll call these messages blocks, in line with conventions in similar protocols.

Cordial miners inspired invariants

Cordial miners2 is one of a family of so-called block DAG consensus protocols.3 In these protocols, a fixed set of participants, usually called validators, produce blocks that, similarly to BEC, refer to other validators’ blocks, and the consensus protocol involves defining a deterministic function that produces a consistent priority order when blocks conflict, that all honest validators will agree on. The cordiality requirement is that for validators, every block at height will have parent blocks with height . In addition to setting up the required thresholds for Byzantine fault-tolerant consistency, this also serves as a flood protection mechanism.

By waiting to reconcile the set of fragments with neighboring peers before building a block, peers can adhere to the cordiality while minimizing the number of blocks sent overall, which is more appropriate for the goal of coming to consensus over a finite sequence of sets with minimal end-to-end latency, as opposed to maximizing throughput and minimizing confirmation latency, which is the more typical design goal for DAG consensus algorithms.

Note that these restrictions on the structure still consist of a special case of Kleppmann and Howard’s hash-consed DAG; every block DAG structure is also a valid Byzantine eventual consistency causal log structure. Because of the validity proofs on transaction fragments, and the concurrent PSBT semantics we do not need an ordering but only a set union.

In the optimistic track, borrowing the cordial structure and setting to fulfill the unanimity requirement means that under asynchrony eventual consistency is the best guarantee we could make. Under synchrony or partial synchrony, the more standard lets responsive peers coordinate the recovery track. Note that in principle could be lowered further, for partition tolerance or recovery in the presence of a dishonest majority, but this is a substantial qualitative difference in guarantees and so it has not yet been explored.

Centralization spectrum and optional TEE-based liveness

All participants can submit their transaction fragments to a designated validator, with all other validators’ blocks simply acknowledging the designated validator’s blocks. These acknowledgements can have empty payloads, concentrating collection and validation work on one peer.

In principle, it is possible to decouple the validator role from the participant role, with one validator serving many transaction participants. That validator’s blocks form a linked list. This instantiates a version of the protocol based on a trusted coordinator. Note that “trust” here is meant only with regard to liveness, not to privacy. If a coordinator is trusted with privacy, which is the norm for such services,4 validity proofs and anonymous broadcast are little more than privacy theater. A centralized protocol where the server simply does not keep a permanent record would be strictly better because users would be informed and computational and bandwidth resources would not be pointlessly wasted, degrading reliability (which is itself a privacy concern).

Note that centralizing the bulk of this communication and coordination work on one node does not require decoupling the validator and participant roles, nor does it confer any special privileges to this de-facto leader; on the DAG model participants which only acknowledge the blocks of a single peer, can make those acknowledgement in the form of blocks that echo the content bearing blocks with minimal communication complexity. No protocol modifications so long as this validator is still a participant in the transaction, and only the introduction of a validator that is not a participant would require these roles to be decoupled.

Going further, a trusted execution environment (TEE) can shift trust assumptions from a participant to the hardware vendor on which the participant is running the protocol. Such a participant can produce attestations about exactly what code is being executed in the TEE enclave, which the other participants can verify. Clients could therefore accept its validation of the protocol state without trusting the operator to execute that code faithfully, instead trusting the vendor’s hardware isolation and attestation guarantees.

The reason such an additional trust assumption may be desired in some circumstances is that it improves liveness and consistency under weaker quorum assumptions, while reducing clients’ validation work further. This does not relax the requirement for unanimous transaction signing, nor is the TEE trusted with protecting privacy; private allocations and spending authority remain with the participants and their messages must remain unlinkable. This provides an alternative path to liveness when clients are too constrained for scalable Byzantine fault tolerance, or when the conditions for Byzantine fault tolerance don’t hold (for example a dishonest majority of validators).

🤖 Peers need not make identical trust assumptions: one may accept a vendor’s attestations while another validates independently. This is related to asymmetric distributed trust, which models each participant’s assumptions about which combinations of peers may fail.5 Flexible BFT provides a complementary precedent for interpreting a shared protocol transcript under different fault and timing assumptions.6 These are relevant frameworks rather than proofs of this TEE construction; its guarantees depend on the chosen acceptance rules and trust assumptions.

In other words, using essentially the same unmodified block DAG structure we can accommodate multiple communication models and trust assumptions, to accommodate a variety of client capabilities and circumstances.

🤖 Objects

A construction instance identifies a fixed validator set and its permitted inputs. A phase identifies the interpretation and admission rules for contributions within that instance. Recovery proposals can establish successor instances with different membership.

A contribution is an application message, such as a transaction fragment, proof, acknowledgement or coalition proposal. Anonymous submission prevents a validator’s inclusion of a contribution from identifying its author.

A block is a product type

with the following components:

ComponentMeaning
Set of included messages; may be empty for an acknowledgement block.
Set of parent blocks.
Optional self-parent block, from the same validator.
Nonce point committed for signing the validator’s next optimistic block.
Nonce point committed for signing the validator’s next recovery block.
Block type: optimistic () or pessimistic recovery ().
Phase within that type’s protocol.
Optional extensions encoded as type-length-value (TLV) fields.

Type and phase may be implicit in the protocol context rather than separately encoded. The optional self-parent is a distinct component from the parent set. Causal ancestry follows both the parent-set references and the self-parent, when present. The block is authenticated by its validator; the signature encoding remains to be specified. Every validator block commits separate nonce points for its next optimistic and recovery signatures.

Optimistic blocks coordinate transaction construction. Recovery blocks coordinate fault-tolerant, permissioned coalition formation so that a new transaction construction instance can start. The recovery type describes the fault model being accommodated, not evidence that a particular participant is faulty.

🤖 Optional block extensions

Blocks carry optional protocol extensions as type-length-value (TLV) fields. A reader can skip an unknown field using its length. Ignoring an extension leaves the core block interpretation unchanged; an extension cannot silently redefine parent references, messages, thresholds or phase-transition rules. Extensions can supply additional evidence that a peer elects to use under its own validation policy.

One extension carries a trusted execution environment (TEE) attestation. It binds the claimed validation result to the relevant block contents, parent-set commitment, instance and phase, and identifies the executed validation code. A peer may rely on that evidence under its hardware-vendor and attestation trust assumptions, while another peer ignores it and validates independently. The attested statement must exclude the attestation bytes themselves to avoid a circular commitment. TLV identifiers, canonical encoding and the precise attested statement remain to be specified.

🤖 Optional attested validation and acknowledgement relay

🤖 As in the centralization spectrum, a validator can leave message collection to other validators. Its own blocks then have empty message sets, , and serve as acknowledgements of the blocks they reference.

Peers can follow a trusted node’s validation, or use attestations from a validator with a TEE. In either case, each retains its validator key and produces its own acknowledgement blocks. Configuring the peers to follow one trusted node provides the single-server arrangement without introducing a separate protocol.

The attested validator supplies the parent set needed for a peer to issue its acknowledgement of the preceding block. After checking the attestation and its context, the peer can use those parent commitments in its own acknowledgement block, retaining its self-parent and nonce commitments. Thus constrained peers need not reconstruct the parent set by independently processing every relayed contribution and acknowledgement.

The exchange is interleaved:

  1. A TEE-backed validator publishes an attested block containing the parent-set evidence needed to acknowledge the preceding block.
  2. Other validators issue their individual acknowledgement blocks using that evidence; their message sets can be empty.
  3. The next TEE-backed block references the preceding TEE-backed block and the other validators’ acknowledgements, relaying them and supplying the evidence for the next acknowledgements.

The validator relays acknowledgements rather than signing on behalf of their authors. Support still counts the distinct validators whose acknowledgements are represented. Peers can independently validate the same DAG, and multiple validators may provide attestations; the profile does not create a privileged protocol leader.

The attestation can certify validation and satisfaction of the applicable agreement predicate. It does not authorize a change to that predicate: unanimous phases still require all required acknowledgements, and transaction signing still requires the input owners. Private allocation information and spending keys are not supplied to the TEE. Peers retain local checks needed to bind their own contributions, proofs and signatures to the intended instance and privacy context. The optional trust assumption reduces validation work and can support stronger liveness under the selected recovery policy.

Nonce commitments and compact equivocation evidence

Valid fragments can do nothing to establish the consistency property nor do they preclude equivocation itself; they can only force it to be detectable when attempted. A malicious peer can send two independently valid but conflicting fragments to different honest peers. In order to detect such equivocations, the honest nodes must observe the conflict, allowing both to be removed and maintaining the invariant that the unsigned transaction must be valid if signed.

To know when they can sign, peers need to communicate not only the fragments themselves, but also which fragments they have seen and whether they agree to proceed at the end of a particular phase. Misbehaving peers might then attempt to prevent progress by disrupting convergence by the honest peers.

🤖 Let be validator ’s public signing key in a group of prime order . Each block commits two independently generated nonce points, and . A successor signature must use the point committed for its track in the preceding signing block. The two commitments allow an optimistic successor and a recovery successor without treating that permitted branching as equivocation. Each individual commitment may authorize only one distinct signed block.

🤖 For a Schnorr signature with committed nonce , response and challenge , verification checks

🤖 The challenge binds the public key, nonce point and complete signed block context, including the instance, track and predecessor commitment.7 If the validator signs two distinct blocks using the same committed nonce, yielding distinct challenges , their responses reveal

🤖 Anyone who obtains both signatures can extract this scalar. Other peers need only receive and check ; they do not need to obtain the equivocated blocks. The validator private key therefore serves as compact, independently verifiable equivocation evidence. Repeating an identical signature is not equivocation, and using the two distinct track commitments as intended does not expose the key.

🤖 Strictly, the scalar proves that the validator key is exposed: deliberate disclosure or compromise produces the same evidence. The protocol treats this as sufficient to disqualify the key without requiring attribution to a particular pair of conflicting blocks. Once exposed, signatures under that key cannot establish who produced subsequent messages. Validator keys must be separate from Bitcoin spending keys and other secrets whose exposure would violate theft resistance or privacy.

🤖 The validator key is the online key endorsed by the coin owner’s BIP-322 proof during coalition formation. The revealed scalar, together with that endorsement or a reference to it, forms a coin-associated fraud proof. A recipient checks both and the endorsement binding to the coin. The recipient need not obtain the conflicting blocks or participate in the construction instance where the key was exposed.

🤖 This fraud proof can be gossiped through the permissionless coalition-formation order book using the same peer reconciliation mechanism as advertisements and proposals. Peers that validate it can ban the endorsed coin from subsequent coalition formation. Replacing the online key does not remove evidence against that coin. This is a protocol admission decision, not a restriction on spending the coin under Bitcoin consensus. The endorsement scope determines which coin or coins the evidence applies to.

🤖 The encoding must unambiguously identify the predecessor nonce commitment consumed by each signature, including the first signature on each track and transitions to successor instances. Nonce normalization and challenge construction must preserve the extraction equation. These details remain part of the signature profile.

🤖 Genesis

The coalition formation proposal serves as the instance’s genesis, denoted by . In the honest and semi-honest settings, an equivalent initiation message serves the same role. It establishes the construction context, including the initial inputs and validator membership , with . Every initial-input owner participates as a validator through its enrolled online key. Genesis is the common root within this instance; its representation need not be identical to an ordinary validator block.

🤖 Optimistic and recovery tracks

Genesis and the two acknowledgement layers of kickoff have instance-local heights 0, 1 and 2. From height 3 onward, progress has two branches: the optimistic or unanimous branch with , and a pessimistic recovery branch with and improved liveness under its chosen recovery assumptions. This does not require producing two blocks for every step. Until a reduced-threshold block is published, the recovery overlay contains no blocks; publication of such blocks activates it. The recovery track is described in the recovery track chapter.

🤖 This differs from typical DAG consensus, including protocols that switch between modes or tracks. There, every mode or track must agree on a single log. Here, the optimistic track requires unanimity, and the two tracks may race: different sessions may attempt to spend the same inputs. That can’t be prevented in a permissionless setting, and it is useful for replace-by-fee (RBF). Racing is not a safety violation, because Bitcoin itself resolves conflicts between competing transactions.

Recovery can establish a successor coalition through a new coalition formation proposal. That proposal serves as the successor instance’s genesis and references blocks in the preceding instance’s recovery DAG as parents. The new construction context therefore retains the causal history of the recovery evidence.

🤖 Causal order and block properties

Write when or is reachable from through parent-set or self-parent references. Define

is the block’s inclusive causal history. For independent validation, a block is causally delivered only after its required contents and ancestors have been obtained and validated. Receiving a root or block hash is not causal delivery. The optional attested-validation profile permits peers to accept certified validation of that history without independently retrieving and checking all of it; this does not assert that they locally possess the history. The following properties are derived from authenticated block data and its causal history:

PropertyDefinition
Author Validator authenticating the block.
Instance-local height Zero for this instance’s genesis; otherwise one plus the maximum height of its parent-set and self-parent references within the instance. Cross-instance recovery ancestry remains part of causal history.
ContextConstruction instance, block type and phase , whether explicit or inferred.
Observed messages Union of included messages throughout .
Phase state Application interpretation of the messages for phase and the construction instance in . Ancestors from predecessor instances provide recovery evidence, not new contributions to this instance.
SupportDistinct validators whose qualifying acknowledgements occur in , for a specified state and predicate.

Height measures causal depth; it is not elapsed time or by itself a threshold logical clock. Support counts validators, not blocks. Producing additional blocks cannot multiply a validator’s weight.

The analogue of Cordial Miners’ is a deterministic interpretation function

which derives the phase state, supporting evidence and permitted transitions. Cordial Miners uses to extract a total order while excluding equivocations.2 Here the interpretation is set-valued: compatible admitted contributions are joined without assigning them a total order. The phase rules determine how invalid or conflicting evidence affects admission. Observation of a message and acceptance into application state remain distinct.

For the compatible admitted contributions of a phase, extending causal history preserves inclusion. Block authentication identifies the validator, not the authors of anonymous payloads. Incompatible self-parent histories by the same validator within the same branch provide equivocation evidence. Explicitly separate recovery branches are different contexts, not automatically equivocations. Evidence is retained rather than resolved by choosing whichever block arrived first.

🤖 Frontiers

A finite causally closed block set has frontier

The frontier is the antichain of its maximal blocks. It represents the entire causal cut because

For a frontier , write and . Frontier extension is ordered by iff . The join of two compatible causal views is represented by .

A frontier is not a selection of one block per validator. It can omit a validator whose blocks are ancestors of another frontier block, or contain several incomparable blocks by an equivocating validator. A local current frontier represents all causally delivered blocks in its scope. A historical frontier represents a specific earlier cut and must be identified as such.

Different frontiers may contain exactly the same phase contributions. Phase agreement therefore compares interpreted phase states, not equality of block hashes or frontier sets. Acknowledgement-only blocks can advance the frontier without changing the transaction state.

References


  1. M. Kleppmann and H. Howard, Byzantine Eventual Consistency and the Fundamental Limits of Peer-to-Peer Databases (2020). Byzantine causal broadcast and invariant-preserving replication; see §2.2–3 for the requirement that independently valid updates remain valid when merged. ↩

  2. Idit Keidar, Oded Naor, Ouri Poupko and Ehud Shapiro. Cordial Miners: Fast and Efficient Consensus for Every Eventuality. ↩ ↩2

  3. I. Keidar, E. Kokoris-Kogias, O. Naor and A. Spiegelman, All You Need is DAG (2021). DAG-Rider separates construction of a communication DAG from local ordering of its proposals. ↩

  4. Y. Kogman, Reiterating centralized coinjoin (Wasabi & Samourai) deanonymization attacks ↩

  5. O. Alpos, C. Cachin, B. Tackmann and L. Zanolini, Asymmetric Distributed Trust (2024). Subjective fault assumptions and asymmetric Byzantine quorum systems. ↩

  6. D. Malkhi, K. Nayak and L. Ren, Flexible Byzantine Fault Tolerance (2019). Different clients interpret one protocol transcript using different fault and timing assumptions. ↩

  7. Pieter Wuille, Jonas Nick and Tim Ruffing. BIP 340: Schnorr Signatures for secp256k1. Reference for the Schnorr verification equation and key-prefixed challenges; the predecessor nonce commitments and equivocation-evidence policy are part of this protocol. ↩

🤖 Optimistic track: blocks and phase states

Scope and status

This specification describes how Fungi transaction construction obtains consistency on the optimistic track, with threshold . The recovery track, with , is described separately. It uses the block DAG. Transmitting that history between peers is described in the peer set reconciliation chapter.

This is a draft technical specification. The data model and reconciliation rules below describe the intended construction. Exact encodings, cryptographic parameters, quiescence scheduling and phase-specific agreement predicates remain to be specified.

The construction retains the causal delivery and validation semantics of Byzantine Eventual Consistency (BEC).1 Discovering missing data only needs BEC’s naive reconciliation; more efficient algorithms are future optimizations. It does not introduce a total order on transaction fragments. Compatible fragments combine by set union; arbitrary PSBT updates are not assumed to form a join semilattice. The transaction protocol determines admission, compatibility and the interpretation of its state.

Design objectives

The unit of progress is a completed transaction-construction phase, not a newly produced block. Unlike a blockchain processing a continuing transaction stream, this protocol coordinates a finite set of contributions toward a stable phase boundary. Its principal performance objectives are end-to-end phase latency, lightweight validation and low communication cost. Faster block production has no independent value.

For a given phase latency and agreement guarantee, fewer blocks are preferable. They reduce authentication, validation, storage and dissemination overhead, and expose fewer intermediate causal views from which an observer could infer propagation order or network topology. Block count is therefore both a resource metric and a privacy consideration, although it is not itself a measure of privacy leakage. Batching must be evaluated against the delay it adds to completing the phase.

The relevant latency measurements are time to reconciliation quiescence, time to a stable common phase state, and time until the evidence permits the next phase. The optimistic target is to reach stability in approximately two communication round trips once the phase’s contributions and local prerequisites are available. This is a design target, not an established bound: the precise exchanges, starting condition and completion predicate remain to be derived from the phase rules. DAG depth alone does not count round trips, and communication rounds have no fixed wall-clock duration under asynchrony.

Evaluation therefore measures blocks and bytes per completed phase, per-peer validation work, and the communication needed to establish and disseminate closing evidence. Block throughput and time to the next block do not substitute for these measurements.

Phase closure

🤖 The optimistic track is defined for the asynchronous communication model. Every phase closes by two rounds of unanimous acknowledgement of the same contribution set. Cooperative participants advance as soon as they hold the evidence; a silent participant can stall progress. The recovery track handles missing per-input messages and stalled validator participation.

Finalizing each phase’s contribution set keeps it stable for the next. This matters most for the input set, which must be stable before outputs:

  • Validity proofs and their privacy. Proving an output before a late input arrives would need a more complicated proof statement and would harm privacy, so it is not supported.
  • The balance condition. With only some of the inputs and some of the outputs, the two could sum to the same amount, and the balance would reach zero too early.
  • Choosing output values. Most importantly, output values are chosen on the basis of the input set, including the auxiliary inputs. This is a privacy requirement.

State acknowledgement and unanimity

Set finalization uses two rounds of acknowledgements carried implicitly by ordinary DAG blocks. In the first round, each validator acknowledges its phase state with nothing further to add. In the second, each validator acknowledges that all validators’ first-round acknowledgements refer to the same set. These are roles of blocks in the construction phase, not separate block types or payload messages.

Let be the fixed validator set and the contribution set represented by block for construction phase . For first-round acknowledgement blocks , synchronization requires a common set :

A second-round acknowledgement has causal evidence of first-round acknowledgements from every validator for that same , and still represents itself. A participant finalizes the set once it has the second-round acknowledgements from every validator. The blocks need not have equal heights or identical parents; the contribution sets they acknowledge must agree.

Receiving one block from every validator is therefore insufficient if those blocks represent different sets. Taking their union does not establish that the first-round acknowledgements were synchronized. Reconciliation must continue until the common-set condition is met. 🤖 When a validator may give its first-round acknowledgement depends on whether the phase’s keys are listed or anonymous.

Phase transitions

🤖 A validator enters phase once it has the second-round acknowledgements from all of finalizing the same set for . Kickoff is entered on holding the genesis. Validation of an individual contribution does not itself establish a phase’s completion.

A participant advances when the relevant evidence becomes available; others catch up through causal delivery. Local phase changes need not be simultaneous.

The exact successor phase is a deterministic function of the completed state and the transaction protocol’s rules. A late message cannot silently amend an already closed phase: its treatment must follow those rules or belong to a new attempt. A claimed transition without the required evidence is not accepted as a valid transition.

No phase transition can infer readiness solely from local quiescence. Conversely, obtaining a closing certificate does not require proving that no further network traffic exists. The finite agreement is on and its readiness conditions. Reconciliation completion, quiescence and phase completion are distinct events.

🤖 Keyed messages

🤖 Every transaction-level message is keyed: it relates to one input, one output or one fee contribution. In the optimistic phases, fee contributions are explicit and keyed for idempotence. In the proven phases, explicit fee contributions are no longer required, because nobody can claim more than they can prove. Whatever no output claims is fee. A key can have more than one message. The block DAG witnesses every message it includes, so all validators see duplicates under the same key. Two valid input proofs from one input with different allocation commitments are evidence against that input, as described under per-input messages.

🤖 Ideally every kind of equivocation would expose the online key, as conflicting validator blocks expose the validator key through nonce commitments. For anonymously published messages, this could use double-authentication-preventing (DAPS) ring signatures, which could also rate-limit messages per key. This remains to be specified.

🤖 An initial input publishes its messages through its validator. Auxiliary inputs and outputs are published by connection-oriented anonymous broadcast. It can relay several messages for the same key, as long as each connection carries only one auxiliary input or one output.

🤖 Phases differ only in when a validator gives its first-round acknowledgement:

  • Listed keys: kickoff, initial-input proofs and signatures. The keys are fixed when the phase opens. A validator acknowledges once its view holds a valid message for every key.
  • Anonymous keys: auxiliary inputs, outputs and fee contributions, proven auxiliary inputs, allocation registrations and proven outputs. A validator acknowledges under the anonymous-phase publication rule.

Hashes and identifiers

  • , the tagged hash of BIP 340.2 Tags begin with fungi/.
  • Instance id: .
  • Outpoint: = txid (32 bytes, internal byte order) followed by vout (u32, little-endian).
  • Validator: its index in , in genesis order.

Input lists

🤖 The initial inputs are listed in the genesis. Every initial-input owner participates as a validator, validating and acknowledging the construction state. The aggregator owns an initial input and is therefore a validator too. Each input acts through the online key enrolled by its ownership proof; its spending authority is used for transaction signing. Auxiliary inputs are submitted anonymously, first without proofs and, only after overflow, with the required proofs.

🤖 Optimistic auxiliary inputs, optimistic outputs and fee contributions, auxiliary-input proofs, allocation registrations and output proofs are submitted anonymously. Input proofs and final signatures identify the input by outpoint; anonymous submission does not make the transaction’s outpoints private. The optimistic phases, which add content without validity proofs, concern transaction data; they are distinct from the optimistic track this chapter describes, which concerns agreement.

Per-input messages

A per-input message is signed by, or bound to, one input. These are the only messages that can blame an input. 🤖 Each list of listed keys is sorted by outpoint bytes, ascending.

PhaseList MessageValid if
kickoffthe initial inputs signature by the online key of over
initial-input proofs, only after overflowthe initial inputs input proof of verifies under the validity proofs and is authenticated by the online key of , bound to and
signaturesthe inputs of the final unsigned transactionsignature of a valid witness for over the final unsigned transaction

An invalid message counts as absent.

🤖 Validators take the union of the per-input messages they receive, each identified by its input’s outpoint. An input commits to one input proof. If it posts two valid input proofs for the same with different allocation commitments, the DAG reveals both. Their online-key authentication binds them to that input, so, as in Cordial Miners,3 the pair is evidence of malfeasance by that specific input. As the block DAG requires, both are removed from the phase state. Recovery additionally excludes the input. Two different valid signatures over the same transaction, or two valid ACCEPT messages, are not equivocation; either one serves.

Blocks and acknowledgements

🤖 Validators publish blocks in the shared block-DAG format. A block’s payload holds received messages not yet in its causal history. Anonymous submissions become eligible for inclusion once received through synchronization, without distinguishing the validator’s own submissions from those of other participants. A block with no new messages can acknowledge the state established by its causal history.

The acknowledgement rounds use optimistic-track blocks. Recovery-track blocks use the separate recovery nonce commitment, as described in the block format. The permitted branching between tracks is not equivocation.

Successive blocks by one validator are not equivocation merely because they belong to the same construction phase. Equivocation evidence follows the predecessor and nonce-commitment rules of the block DAG.

🤖 A validator can leave message collection to other validators, or follow a trusted or TEE-attested validator, while still producing its own acknowledgement blocks. The block DAG describes this under optional attested validation and acknowledgement relay.

Phases

Each phase below admits its content, then closes by the rules above. The phases run in the order given in transaction construction.

Kickoff

🤖 Kickoff is the validators’ acknowledgement of the coalition formation proposal, the genesis. It is keyed by the initial inputs, each acknowledging with an message. Its two acknowledgement rounds are the first two layers of the block DAG. Once a peer holds second-round acknowledgements from all validators, kickoff is complete for it, and it can begin anonymously disseminating auxiliary inputs.

A missing acknowledgement can stall kickoff. The recovery overlay begins after the genesis acknowledgement layers; this rule does not itself provide a recovery mechanism for incomplete kickoff.

Anonymous-phase publication

🤖 In each anonymous phase, a validator waits for reconciliation quiescence and at least the phase’s minimum waiting period before its first-round acknowledgement. Inclusion of its own anonymous contributions is not a condition for either acknowledgement round. The same rule applies to auxiliary inputs, outputs and fee contributions, allocation registrations, and proven outputs. The waiting periods and reconciliation scope remain to be specified. Quiescence permits publication under this rule; phase closure still requires both rounds of unanimous acknowledgements described above.

🤖 Conditioning an identified validator’s block on receipt or inclusion of its own anonymous registration or output would let adversarial peers test the association by selectively withholding that contribution. A participant therefore continues validating and acknowledging the construction even if every other validator omits its contributions. If the resulting transaction does not satisfy its output or payment requirements, it refuses transaction signing instead. A missing signature identifies an input, but does not by itself identify the omitted anonymous contribution or establish why the participant refused to sign.

Auxiliary inputs

🤖 Auxiliary inputs are admitted anonymously. Omitted auxiliary inputs are not part of this transaction.

Outputs

🤖 Outputs and fee contributions are admitted anonymously without validity proofs. This is the same content protocol as in the semi-honest setting. The initial inputs are already known, and the optimistic auxiliary-input set has been agreed. No mandatory destination-commitment phase precedes these contributions.

🤖 Every optimistic output or fee contribution accounts for at least 1 sat. The balance in a validator’s view is the total of minus the outputs and fee contributions in that view. A participant may post the overflow signal, equivalent to a fee contribution of MAX_MONEY, to make that balance negative. This starts the need for proving; it does not bypass the anonymous-phase waiting rule or the phase-closing acknowledgements.

The balance of the finalized set determines the next phase:

  • Balanced. At a balance of zero, the phase continues to signatures. 🤖 This is the only outcome that terminates on the optimistic track. Agreement on this balance does not establish that every participant’s outputs are present or that its payment requirements are satisfied; participants check those conditions before signing.
  • Overspent. If the balance is negative, at least one output or fee contribution is not covered. The phase continues with the proven phases, as the validity proofs require. In the Byzantine setting anyone can force this. For example, a faulty party posts an output for exactly the remaining amount before an honest output arrives; the honest output then makes the balance negative.
  • 🤖 Underspent. A positive balance does not terminate the optimistic track. Unclaimed balances are possible only on the recovery track, which is a different termination path.

Initial-input proofs

🤖 The proven phases run only after overflow in the optimistic outputs phase. Optimistic outputs are discarded. Participants choose fresh, unguessable output ids for the proven phases. This phase is keyed by the initial inputs: each posts its proof, identified by outpoint and authenticated by its online key. The proof commits to its allocations of funds and vbytes. The finalized initial-input-proof set supplies the allocations used for auxiliary admission.

Proven auxiliary inputs

🤖 Auxiliary inputs are submitted anonymously with their proofs. Each proof message is authenticated by that input’s own online key, enrolled by its BIP-322 ownership proof, and bound to the session. Each admission consumes a vbyte allocation committed by an initial input. Only once the proven auxiliary-input set is finalized is the session root derived from the accepted initial and auxiliary input allocations. The validity proofs describe the dependency; the current PoC does not implement the vbyte-allocation admission relation.

Allocation registration and proven outputs

🤖 Output proving has two anonymous phases. First, allocation registrations are submitted against the final session root. Their finalized set determines the registered-leaf root. Then outputs are submitted with proofs against that root. The proofs enforce coverage. As in the outputs phase, only a balance of zero terminates the optimistic track. Script authorization follows the validity proofs.

Signatures

🤖 Signatures are keyed by the inputs of the final unsigned transaction. Once every validator holds every signature, the transaction is complete.

Payment confirmation commitments

🤖 A payment confirmation states that a particular construction state satisfies the payment agreement: the payee confirms delivery of the funds to their ultimate destination, including any onward payments. Counterparties exchange confirmations after output finalization and before input signing. The payer checks that the output set committed to by its input signature is consistent with that confirmation. This check does not require the payer to learn which output belongs to the payee. The concurrent PSBT specification defines the dependencies between counterparties’ confirmations.

🤖 The confirmed construction state is bound by the protocol transcript’s Merkle-set commitment. That transcript includes the transaction contributions and required proofs, and its commitment is used as the deterministic sort seed for constructing the unsigned transaction. The payer checks that the payee’s confirmation names the same transcript commitment that it uses to construct the output set it signs. Acknowledgement-only blocks can change a DAG frontier without changing this construction state.

🤖 In the Byzantine setting, the wire objects are specified protocol messages. Their accepted state projects into the PSBT data used to construct and sign the transaction. Honest and semi-honest construction can use PSBT extensions; the Byzantine construction requires specified protocol extensions rather than accepting arbitrary PSBT extensions as protocol messages.

Block publication and quiescence

🤖 Quiescence minimizes the number of block DAG waves per phase. Convergence on a phase’s contributions happens by gossip; the block DAG exists to verify that convergence did occur. Waiting for convergence among its neighbors before authoring a block therefore avoids needless waves. This applies even when the cordial parent threshold is already met, as with . Fewer blocks are also more compressible on the wire. Peer set reconciliation is an input to this rule, whichever reconciliation algorithm is used.

Reconciliation between neighbors precedes the release of a new cordial block. The objective is to publish a consolidated view rather than a sequence of intermediate views that exposes the order in which contributions reached the validator. This reduces observable correlations between the block contents and the network’s propagation topology.

For a fixed reconciliation scope, local quiescence means that its advertised sets have been reconciled and there is no outstanding reconciliation work for that scope. It is a local condition: it neither proves that no further message exists nor closes admission to a phase. A newly advertised root can create more work.

A publication rule must specify which neighbors and advertised roots belong to the scope, how concurrent advertisements affect it, and how stalled neighbors are handled. Those choices are not yet fixed. Waiting for all future advertisements is not a finite condition; waiting for every neighbor can indefinitely delay publication. Any cutoff or recovery policy must be evaluated together with the intended privacy and liveness properties.

Cordial parent-inclusion rules additionally limit block production according to progress by other validators.3 Quiescence batches the available contributions before a permitted block is released; it does not replace the parent threshold. On a hub-and-spoke topology, a well-connected validator can assemble most payloads while others acknowledge them. This is workload concentration, without requiring a privileged leader.

The privacy objective is to avoid additional attribution beyond the transaction, authorized counterparty knowledge and the transport’s guarantees. Channel-randomized transfer schedules reduce redundant traffic; quiescent publication reduces intermediate public views. Neither alone establishes a topology-hiding theorem. The remaining leakage includes publication timing, neighbor failures and the selected quiescence policy.

Dissemination interface

🤖 Blocks and their messages are disseminated by peer set reconciliation. Its naive reconciliation, which requests the preimages of unknown hashes until it reaches known blocks, is sufficient for causal delivery; the other algorithms there are optimizations. Reconciliation supplies contents and completion status. It does not decide block validity, unanimity or phase transitions. Beluga’s block synchronizer is a reference for this boundary and for evaluating recovery traffic.4

Resource bounds and validation

🤖 Bounds on neighbor exchanges, speculative decoder work and unresolved roots are given in peer set reconciliation. The transaction protocol bounds admitted contributions; the DAG rules must additionally bound block production and recovery proposals. Invalid contributions do not enter validated application state, and reconciliation cannot force a withholding participant to sign.

Open specification choices

The remaining choices are:

  • Canonical block encodings and the interface to peer-layer committed sets.
  • Quiescence scope and publication scheduling, including handling of continuing traffic and stalled neighbors.
  • Exact interpretation of the two acknowledgement rounds in the block DAG, admission boundaries, and their interaction with late contributions and recovery.
  • Bounds on block production and branch proliferation.
  • 🤖 Equivocation evidence that exposes the online key for every kind of keyed message, for example using DAPS ring signatures, and its use for rate limiting.

The DAG interpretation and phase rules are independent of the peer layer’s choice of reconciliation algorithm.

References


  1. Martin Kleppmann and Heidi Howard. Byzantine Eventual Consistency and the Fundamental Limits of Peer-to-Peer Databases. ↩

  2. Pieter Wuille, Jonas Nick and Tim Ruffing. BIP 340: Schnorr Signatures for secp256k1. Reference for the Schnorr verification equation and key-prefixed challenges; the predecessor nonce commitments and equivocation-evidence policy are part of this protocol. ↩

  3. Idit Keidar, Oded Naor, Ouri Poupko and Ehud Shapiro. Cordial Miners: Fast and Efficient Consensus for Every Eventuality. ↩ ↩2

  4. Tasos Kichidis et al. Beluga: Block Synchronization for BFT Consensus Protocols. ↩

Recovery track

🤖 A stalled phase can produce recovery observations in validator blocks, each signed by its validator and committing to what that validator is missing. Any participant can turn those observations into a recovery coalition formation proposal that anyone can check. The intended synchrony properties are exclusion of a faulty party without excluding an honest one, apart from the counterparty-stall exception. Claims below that depend on identifying missing first- or second-round acknowledgements remain unresolved under the two-round finalization rule.

🤖 This chapter describes the recovery track (). The block structure and the per-track nonce commitments are described in the block DAG chapter. The closing of each phase is described in the optimistic track chapter (). Dissemination and set reconciliation are out of scope here.

🤖 Several names in this chapter and in phase closure are placeholders, chosen only so the rules can be stated: per-input message, quorum mode, own-view mode, deny list, late pass, coin binding, evidence-only proposal, boundary split and light participant. A light participant is one that does not see the DAG.

Fault tolerance via branched execution

Somewhat surprisingly, the optimistic track and the recovery track can both proceed more or less independently.

Under asynchrony and in the presence of (Byzantine) faults, due to the unanimity requirement the best consistency guarantee that can be made for the optimistic track is eventual consistency. No liveness guarantee is possible in the presence of faults for a particular run of the transaction construction protocol.

Recall that when multiple transactions attempt to spend some of the same coins, it is up to miners to determine which one (if any) will be confirmed in a block. Miners are assumed to follow their incentives, maximizing fee revenues. Even if transaction replacement wasn’t useful or desirable, there is no mechanism that can enforce that unspent outputs are exclusively bound to one transaction construction session over another without global consensus.

As we have seen, the success path always reaches termination, and can only reach it by observing unanimous agreement, and when that is possible progress requires only eventual consistency. Validity proofs reduce Byzantine faults to omission faults, so recovering liveness in the presence of failure requires partial synchrony assumptions at the very least.

Since input exclusivity is neither desirable nor enforceable, we can embrace its absence and reframe liveness in a simpler way by treating all failure recovery as branching off another instance of the protocol with a subset of the participants precisely when that subset of the participants can agree among themselves that a failure condition has been detected. Such agreement inherently requires synchrony or partial synchrony, and so explains why this is needed for fault tolerance. In this case the blocks at some height with parent blocks will be produced as part of the recovery synchronization protocol on top of which a new transaction construction session will commence. If messages are delivered allowing a block at height to be produced with messages, the asynchronous base protocol can resume progress resulting in the diverging protocol states at height . This special case has the same structure as all-to-all broadcast.

Since recovery is just permissioned coalition formation, any participant may act as an aggregator and make a coalition formation proposal based on its local view; the proposed participants must all accept before it starts. Membership changes can alter anonymity or payment terms, so participants may renegotiate or decline. Recovery also has a privacy cost: excluding an input links it to the outputs that drop out with it, even if its owner was merely unresponsive.

The reason this framing is simpler is that recovery attempts do not need to terminate the run of the protocol that they are trying to recover. In the case that both branches eventually succeed, Bitcoin itself will adjudicate the conflicting transactions. We can treat failure recovery as a (more) synchronous layer building on a fundamentally asynchronous optimistic base protocol with BEC semantics.

🤖 Recovery overlay

Each optimistic session is monotone and append-only. Its optimistic and recovery tracks are interleaved within the same block DAG, distinguished by the threshold used for progress: for unanimous construction and for recovery. The recovery DAG is the logical overlay formed by the reduced-threshold blocks and their causal references, not a separately synchronized history or a rollback of construction. Publishing a recovery block does not disable subsequent optimistic progress. The overlay provides robust dissemination and synchronization of the observations used by aggregators to propose recovery coalitions. The original session can continue receiving contributions and completing phases while the overlay progresses.

This resembles dual-track consensus, which combines an optimistic path with a more robust alternative; TockOwl+ is an example using concurrent fast and slow tracks with hedging delays.1 Here the tracks share the DAG substrate and are differentiated by , rather than requiring a global switch between protocols. Their purposes also differ: the optimistic track completes the existing construction, while recovery supports proposals for successor coalitions. The citation provides a design comparison, not a proof of this composition.

🤖 Unlike those tracks, the optimistic track here requires unanimity, and the tracks may race without violating safety: different sessions may attempt to spend the same inputs, and Bitcoin resolves conflicts between competing transactions.

An aggregator may propose a successor when its recovery view is sufficient under its chosen policy. Let represent that view’s frontier. The recovery coalition formation proposal references the blocks in as parents, thereby committing to their causal history. The proposal is the genesis of a new optimistic session, with its own first and second unanimous acknowledgement rounds at kickoff. Multiple aggregators can propose different successors from different views; there is no requirement to first agree globally on one recovery view.

Let denote the active set derived from the recovery evidence and policy at . A recovery proposal may use only co-spend proposals involving members of . Restricting eligibility does not rewrite the terms or membership of an existing co-spend proposal. The successor coalition still requires acceptance of its own terms and satisfaction of its kickoff conditions. The precise activity and view-sufficiency predicates remain parameters to be specified.

For recovery blocks, a threshold predicate may authorize progress in permissioned coalition formation without satisfying unanimous set finalization for the original membership. Such progress does not close the original construction phase. Successful negotiation establishes a new instance, whose membership and kickoff conditions are checked against the accepted proposal. Threshold selection and the recovery predicates are independent parameters of the interpretation function.

The parallel recovery overlay uses to coordinate fault-tolerant, permissioned coalition formation; its purpose is to improve the robustness of aggregators’ recovery proposals. Wall-clock policies, threshold logical clocks or BEC proposal exchange can support different recovery modes. Anyone can aggregate a proposal from a local view. Other participants can counterpropose; no globally agreed recovery view is required before negotiation.

An accepted proposal fixes a successor’s initial inputs and validators as a subset of the parent session’s, and fixes its allowed auxiliary inputs. Kickoff requires the proposal’s required signatures and anonymity conditions. The successor then runs its own optimistic construction with . The original and competing recovery instances may remain active concurrently.

Lower thresholds permit smaller groups to pursue recovery, down to two-party collaboration. They do not automatically preserve quorum-intersection or censorship-resistance guarantees of larger groups. Censorship-Resistant Byzantine Broadcast (CRBB) couples agreement on a set with inclusion of timely honest submissions, and studies the latency cost of that guarantee; replacing its timing assumptions with threshold-clock evidence requires a separate argument.2 The DAG retains proposals, contributions and evidence needed for those arguments without requiring global agreement between distinct successor instances.

Consistency, liveness and termination in the presence of Byzantine faults

In typical definitions of Byzantine fault-tolerant distributed consensus or agreement protocols, once a majority of honest peers has settled on a certain state, any lagging honest peers will only ever accept updates that progress towards that state when they are able to catch up. Unfortunately for our purposes this isn’t enough for fault-tolerant transaction construction, since successful termination of the protocol requires unanimity.

If a majority of the honest users can agree on a set of inputs and outputs, but one of the honest participants not in this majority still hasn’t submitted all of their outputs, then it would rightfully withhold its signatures even if it does come back online. When assuming the asynchronous communication model, this can delay termination indefinitely, and achieving a majority is not sufficient for termination.

Contributing signatures to a transaction that may become valid when fully signed is both an honest signal and a signal of honesty. In the signalling-theory sense, it is not costless, since the transaction may have consequences such as mining fees if the other parties also sign. Contributing signatures also signals honesty in the sense defined above: validity proofs make it safe for honest participants to sign regardless of the actions of other users, so they have no reason to withhold their signatures. A which deviates or defects from transaction construction can veto the transaction but at the cost of withholding a signature on at least one of their inputs.

In lieu of agreement about a transaction, agreement on the available evidence can still support liveness by allowing recovery from a fault. This boils down identifying inputs for which signatures have not yet been received. A missing signature may still eventually arrive, completing the transaction, but to avoid waiting indefinitely, participants can negotiate another transaction construction attempt while continuing to listen for progress in the original one.

Under synchrony or partial synchrony (specifically the eventual synchrony variant), if a sufficient threshold of peers can all agree it has been too long, then they can initiate such a recovery session. A threshold of peers agreeing implies a majority of honest peers agreeing. Note that agreement by a majority of honest participants requires a supermajority threshold. A quorum is a set of peers meeting the required agreement threshold. Given where at most are faulty, a quorum of peers will include at least honest peers, a majority within any such quorum.

So long as the notion of “too long” is well defined (consistent with the communication model) and agreed to by such a quorum, whenever there are up to inputs owned by faulty peers honest parties should be able to successfully complete a run of the protocol after attempts by simply excluding those inputs as it becomes apparent that they are disruptive or unresponsive. Even in the worst case this process ensures at least one input can always be excluded.

If there are more than faults recovery is still possible but coordinating recovery attempts by identifying the subset of inputs eligible to participate in recovery requires additional assumptions.

Fault tolerance under different communication models

If a subset of participants can all agree that some other peers are faulty, they could recover by restarting transaction construction without those peers’ inputs, allowing them to produce a valid transaction without those peers. Deciding when a peer is unresponsive, the only kind of fault that is tolerated in the honest threat model, largely depends on how messages are transmitted. Depending on what can be assumed about message delivery, different guarantees about liveness or fault tolerance can be made.

The distributed systems literature typically divides this into three communication models: asynchrony, synchrony, and partial synchrony.3 Each demands a different approach to fault tolerance. These models also apply in the more adversarial settings.

Asynchrony

In the asynchronous communication model, messages may be arbitrarily delayed, so when an expected message fails to arrive, we cannot conclude the sender is faulty because when that happens isn’t well defined. This setting is the simplest in which correct behavior can be reasoned about, because it makes the weakest guarantees. If we assume all peers are honest, the only recourse is to keep waiting.

Synchrony

Intuitively, a peer that has been unresponsive for too long can be considered faulty. By adding timeouts, we can recover liveness by simply giving up coordinating with such peers.

The synchronous communication model is typically in play whenever a protocol relies on specific timeout values, i.e. defining how long is “too long”. This model assumes that the participants can agree on what time it is, and that all sent messages will arrive no later than some maximal delay. If a message that is expected to arrive fails to do so before the timeout elapses, the peer which was supposed to send is said to experience a crash fault, rendering it unresponsive for the remainder of the protocol, or an omission fault if it was temporarily unavailable and some of its messages were not delivered.

Note that such delays may be arbitrarily long, provided their bound is well defined, even if the underlying transport requires interactivity on a shorter time scale. For example, we might use TCP/IP with timeouts on the order of tens of seconds to interact with a store-and-forward service that allows peers to send each other messages with timeouts on the order of hours or days. The model assumed by the underlying transport or its parameters need not agree with the model assumed for transaction construction.

Partial synchrony

Partial synchrony lies in between. Like the synchronous model, it assumes message delivery is timely, but unlike the synchronous model, the bound on the delay either isn’t known or may not always apply, so simply waiting for a timeout duration will not suffice to obtain liveness. Typically this requires acknowledgement from some threshold fraction of participants in order for progress to be made.

🤖 Model

Parties

  • Initial inputs are listed in the genesis. Each input is represented by the online key enrolled by its ownership proof, as specified in coalition formation.
  • Auxiliary inputs are admitted anonymously in the auxiliary input phase.
  • Validators , with . A validator uses the online key of an initial input to sign its blocks with the precommitted nonce. The ownership proof selected by the accepted coalition formation proposal binds that key to the input’s outpoint. Exposure of the key disqualifies the validator; exposure alone does not establish whether its owner equivocated, disclosed the key or was compromised.
  • Participants own inputs. Every initial-input owner participates as a validator through its enrolled online key and supplies the required acknowledgements. Following another node does not remove this role.
  • Aggregator: whoever submits a recovery proposal. It has no other role.

Faults

  • Byzantine faults, which include crashes and omissions.
  • Quorum mode: at most of the validators are faulty, with . Any number of input owners may be faulty.
  • Own-view mode: any number of validators and owners may be faulty. This is the dishonest majority setting.
  • A validator’s faults are attributed to its initial input, and that input’s faults to its validator.

Synchrony

Under synchrony there is a known bound : a message an honest party sends at its local time is held by an honest recipient by the recipient’s local time . covers delivery, fetching missing causal history and clock skew.

Honest validators relay every valid message and block they hold to every validator, and to the participants connected to them. So whatever one honest validator holds, every honest validator holds within more.

Under partial synchrony the bound holds only after an unknown time, or for an unknown . See Timing.

Transport properties

  • Validator-to-validator channels are authenticated.
  • Anonymous contributions use a sender-anonymous transport. Each copy goes over its own connection, unless the transport provides unlinkability between messages.
  • In quorum mode, an honest participant sends each message to at least validators and receives from at least . In own-view mode it sends to and receives from every validator.

🤖 Objects

🤖 Hashes and identifiers, input lists, per-input messages, keyed messages and the interpretation of ordinary DAG blocks are defined with phase closure in the optimistic track chapter.

Evidence that excludes at once

EvidenceContentExcludes
exposed keya validator scalar with that validator
per-input equivocationtwo conflicting valid input proofs of input

A key is exposed when a validator signs two different blocks with the same committed nonce: the two responses give .4

An invalid block is not evidence. It is ignored, and its author is treated as unresponsive, so honest validators may mark it missing. One example is a recovery track block that marks as missing something in its own causal history. The exception is equivocation: if an invalid block reuses a committed nonce, the author’s key is still recovered from it as a fraud proof. So the nonce commitment check applies to every signed block, valid or not.

🤖 Recovery track

Acknowledgement evidence

🤖 Set finalization uses ordinary blocks in two acknowledgement rounds. In the first round, each peer implicitly acknowledges that it has nothing to add to the candidate set. In the second, every peer acknowledges that the first-round acknowledgements were synchronized: the same set is represented in all those blocks. The union of different first-round states is not a finalized state.

🤖 These rounds describe how blocks are interpreted, not separate block types. The recovery rules must identify which block and state satisfy each round before absence of that acknowledgement can support an exclusion. Two ordinary blocks with different contents are not, by that fact alone, nonce reuse or evidence of equivocation. The nonce-consumption and conflicting-acknowledgement rules needed for that inference remain to be specified.

Deadlines

The recovery track adds deadlines to the optimistic track. is the local time at which a validator enters phase , and the deadline is , with one of the parameters.

🤖 A deadline does not close a phase or force an acknowledgement. Anonymous-phase publication still waits for reconciliation quiescence and the minimum waiting period, independently of the validator’s own anonymous contributions. Finalization still requires the two acknowledgement rounds over the same set. The deadline supplies the reference time for the proposed recovery schedule below; its compatibility with those publication conditions remains to be established.

Recovery track blocks

On the optimistic track a phase advances only with blocks from all validators, . In terms of Cordial Miners, this is the most cordial a validator can be, at the cost of liveness: one silent validator stalls the phase.5 A recovery track block has a reduced threshold, . A validator sends one when it thinks it has waited too long, subject to the usual cordiality requirement on its parents.

A validator in phase publishes a recovery track block for at if it has not entered . For the signatures phase, “entered ” means it holds every signature.

It stops once it holds a successor of whose kickoff has closed, or once reaches . It keeps relaying ’s messages after that, so a late signature can still complete .

Parents. In quorum mode, blocks of from at least distinct validators. In own-view mode, at least ’s own latest block. It should also reference every block of that holds and that is not already below one of its parents. A validator in a minority partition cannot gather parents, so in quorum mode it publishes nothing.

Payload. Every received phase message holds that is not yet in its causal history, as on the optimistic track. Anonymous submissions become eligible for inclusion once received through synchronization, without distinguishing the validator’s own submissions from those of other participants. This relays late messages.

Contents. Besides the payload, the block holds , , , any evidence objects, and what is missing: inputs of , none for anonymous phases, and validators.

The block commits unambiguously to what is missing, explicitly or implicitly. Whether it lists the missing items or they follow from its parents and causal history is a wire-level encoding choice, and so is a bitmap versus a list of validator indices. They are left to the protocol messages. An explicit list is expected to be simpler: in quorum mode , so fewer items are generally missing than present.

A block that marks as missing something in its own causal history contradicts itself. It is invalid, and its author is treated as unresponsive.

What is missing. An honest validator marks a missing input if its view holds no valid message keyed by in phase .

🤖 Missing-validator marks remain unresolved. The earlier proposed timing rule used absence of a first-round acknowledgement, or of a second-round acknowledgement after publishing the corresponding local acknowledgement, with a relay margin. Applying such a rule requires identifying the relevant ordinary block, round and candidate state. It must also account for reconciliation quiescence, minimum waiting periods and differing first-round states. No bound showing that every honest peer can issue the required acknowledgement within has been established for these conditions. The exclusion rules below therefore do not yet establish no framing for missing-validator marks.

Exclusion

Exclusion is a function of the evidence in the proposal alone, so anyone can recompute it. Its inputs are , a set of recovery track blocks for one by distinct validators, and , a set of evidence objects.

Quorum mode requires :

may hold more than blocks. The mark threshold remains ; the intended no-framing argument for validator marks still requires the missing-acknowledgement rules.

Own-view mode takes to be one block, by the proposer’s validator. and are what that block marks. Honest participants protect themselves with the veto in acceptance.

Evidence, in both modes, adds its signer or author to or . It needs no recovery track block, so a proposal may be built from evidence alone, at any time.

Coin binding is applied once, at the end: each excluded validator’s coin joins , and the validator of each coin in joins .

Empty result. If both sets are empty, no proposal is valid. The instance continues, and the next round’s deadline applies. This is a late pass.

Recovery proposal

A recovery proposal is a coalition formation proposal. It carries evidence, and the successor’s genesis is derived from that evidence.

#FieldContent
1versionu8 = 1
2kindu8 = recovery
3parent (32), (u8), (u16); = 0xFFFF for an evidence-only proposal
4evidence blockshashes of the blocks in
5evidence objectsone type-length-value object each
6excluded inputs, sorted outpoints
7excluded validators, sorted indices into the parent’s
8proposeran outpoint in
9signatureby the proposer’s online key over

Every recipient derives the successor’s genesis:

FieldDerivation
deny list, where is the parent’s deny list (empty for a first instance)
initial inputs
validators, in parent order, each with its outpoint
co-spend proposalsthose of the parent that name no outpoint in
parametersas in Parameters

The successor id is . It depends on and , not on , the evidence objects or the proposer. Two proposals with the same result therefore name the same successor.

Excluded inputs’ co-spend proposals must be dropped, so new co-spend proposals may be required.

Validators of every descendant instance reject a denied outpoint as an auxiliary input. An excluded auxiliary input is never an initial input, so only the deny list keeps it out.

Validation. A proposal is valid if and only if:

  1. the parent instance and are known;
  2. each block in is a validly signed recovery track block for , and the authors are distinct validators of ;
  3. in quorum mode , and each block of has parents from distinct validators; in own-view mode is one block, by the proposer’s validator;
  4. each evidence object is valid for ;
  5. and equal the output of exclusion;
  6. is not empty;
  7. the proposer is in and the signature verifies;
  8. the successor’s parameters pass the participant checks in Parameters.

Checks 2 and 3 are skipped for evidence-only proposals.

Dissemination and flood bound. A proposal counts only when it is in the payload of a validator block, and its evidence blocks are in that block’s causal history. Honest validators relay blocks, so within every honest party holds what one honest validator holds. Each proposal is signed by an initial input, which is the input-issued unit it spends. Validators carry at most one proposal per proposer per , and at most one per .

Acceptance

A participant owning accepts a proposal only if:

  1. is valid;
  2. 🤖 veto, if the participant sees the DAG: no input excluded by marks has a valid per-input message in its view. A validator exclusion must be checked against the first- or second-round acknowledgement it was marked for, interpreted from ordinary DAG blocks; this part of the veto remains unresolved until the acknowledgement-identification rule is specified (required in own-view mode, recommended in quorum mode);
  3. its own policy accepts the new terms: anonymity, fees and payments.

A participant may accept competing successors of the same phase, in the same round or in later rounds. Like the parent and its successor, they run concurrently, and Bitcoin decides which one confirms.

Choosing. At by its own clock, with , it considers the proposals held in validator blocks by then, plus evidence-only proposals for . An evidence-only proposal competes at the next cutoff. Among those that pass the checks:

  • in quorum mode it picks the one with the most exclusions;
  • in own-view mode it picks the one with the fewest;
  • ties go to the lowest .

🤖 Conditional on the intended no-framing property in quorum mode, a larger exclusion set is preferable, and a faulty aggregator can only offer a subset of what an honest one finds unless it adds more faulty parties. In own-view mode a single block decides, and a faulty one can frame. A participant that cannot veto therefore prefers the smaller set.

Accepting. It sends for to every validator in . This is the successor’s first per-input message. Validators enter the successor’s kickoff on holding its genesis, and kickoff closes like any other phase. A participant in that never accepts stalls that kickoff. Kickoff has no recovery, so the successor does not exclude that input. Its other participants can accept a competing successor instead.

The parent keeps running. Validators keep processing , and participants keep their obligations in it, including signing if it gets that far. If both instances are signed, Bitcoin decides which one confirms. Either pays every honest participant as intended.

Timing

  • Honest validators enter a phase within of each other.
  • Submission margin: an honest initial-input owner sends each phase message by by its own clock. Then every honest validator holds it by its own deadline. The three are delivery to some honest validator, relay to the rest, and entry skew.

🤖 The following is the proposed recovery schedule. Its acknowledgement-completion times are targets, not established bounds for the two-round set-finalization rule:

Local timeEvent
enters
proposed last submission by an honest initial-input owner
proposed deadline; first-round acknowledgement still depends on its publication conditions
proposed availability of honest first-round acknowledgements; unresolved
proposed availability of honest second-round acknowledgements; scheduled round-0 recovery observation if it has not entered
every honest party holds every honest round-0 recovery track block; aggregators build proposals
cutoff : participants choose a successor and send ACCEPT

🤖 Conditional on the recovery blocks being published and relayed at the proposed times, the cutoff calculation is as follows. This does not establish the preceding acknowledgement deadlines. Measured from the earliest honest validator’s , call it : every honest recovery track block is held by ; an honest aggregator, which entered by , builds by ; an honest validator holds the proposal and carries it by ; every honest participant holds it by . Each participant’s own is at least , so its cutoff is late enough.

Partial synchrony. Set , so the round spacing doubles each round, and successors inherit and every duration multiplied by . Before stabilization an honest message can miss a deadline, and an honest input can then be excluded in quorum mode. The veto still protects it while some honest participant in with a view holds its message. A successor’s exceeding the real delivery bound supplies the timing assumption; it does not resolve acknowledgement identification or prove the missing-validator rule. The cutoff, proposed relay margins and submission margins all grow with it.

Parameters

All parameters are fixed in the genesis.

NameMeaningSuggested
modequorum or own-viewquorum when
fault bound in quorum mode for a first instance
timing boundset by the aggregator
duration from entry to deadline, per phaseat least
spacing between recovery rounds
backoff factor1 under synchrony, 2 under partial synchrony
acceptance cutoff after
last recovery round per phaseset by the aggregator

Successors. and each duration are multiplied by for the stalled round . The fault bound is carried, not recomputed: , where counts the validators excluded by proven fault. Those are marks in quorum mode, an exposed key, or coin binding from an input excluded by marks or by equivocation. The successor runs in quorum mode if , and in own-view mode otherwise.

For example, with and , two faulty validators stay and three honest ones leave. Then and , so the successor runs in own-view mode, since . Recomputing from would give , and the two faulty validators alone could then exclude anyone.

Participant checks. The genesis comes from whoever started the instance, and an aggregator that sets too small breaks synchrony for everyone. A participant accepts a genesis or a successor only if is at least its own estimate of the transport bound, every , , and the mode and follow the rules above.

🤖 Counterparty stalls

A faulty payee can stall its honest payer at no cost to itself. For example, it never claims its payment after the payer’s input proof. The payer gets no receipt, so it does not sign, and its input is named. Recovery then excludes the payer, not the payee.

Payer and payee trust each other for liveness: the payer chose its payee and takes the risk that it stalls. So either way of handling this is acceptable. This draft specifies option A and describes option B.

Option A: blame the payer only

This is the rule above, and it matches the failure table in the validity proofs draft (validity-proofs.md).

  • Bound: a faulty payee can get each honest payer that chose it named once. The successors it forces for free are at most the number of honest payers paying faulty payees.
  • Who pays: the payer loses this attempt. Third parties pay one retry each time, with fresh secrets and a new session, and one more attempt that retry unlinkability must cover.
  • Privacy: no payment is published. The named input is public, as it is for any failure.

Option B: blame the pair

  • Gain: every stall costs the adversary a coin, so each successor costs a coin holds, except for payees with no input in the instance.
  • The payee must be provably the payee. A payer that could name any input would get third parties excluded, which is ruled out. So the payer needs a statement the payee signed, for example a signature by the payee’s online key over the payment terms. The payer would post it as an evidence object, and exclusion would add the payee’s input to the payer’s.
  • That statement proves the payment to anyone. The payer can publish it at any time. Publishing it for blame shows everyone which two inputs a payment links. Both leave the instance, but the link stays attached to those coins.
  • The payer learns the payee’s input. The validity proofs draft requires that the payee not learn the paying input and the payer not learn the funded output. It says nothing about this direction, so option B needs that decided. A stall already weakens the first requirement in both options, as below.
  • A payee with no input in the instance cannot be blamed. Option B then falls back to option A.
  • Who failed stays unknown. The statement shows that the pair did not complete, not which one failed. A lying payer can get its honest payee excluded, but the payer is also excluded.

In both options

A faulty payee learns the paying input when that input is named after its own stall. Payer anonymity with respect to the payee therefore holds only for payees that complete. The retry restarts from the destination commitments with fresh secrets, not in place.

🤖 Properties

🤖 The intended properties assume synchrony and the submission margins in Timing. Missing-validator exclusion and the properties that depend on it remain conditional on the unresolved acknowledgement-identification and timing rules.

Honest messages arrive in time

An honest participant that respects its margin has its message held by every honest validator by that validator’s own deadline.

No framing

🤖 The intended quorum-mode property is that no valid proposal excludes an honest input or validator, except a payer whose payee stalled it and that payer’s validator. The argument is incomplete for missing-validator marks:

  1. No honest validator marks an honest input, since its message arrived in time and a received message is never withdrawn.
  2. 🤖 The proposed rule does not yet establish that an honest validator cannot be marked missing. Finalization requires synchronized first-round acknowledgements of the same set; differing first-round blocks do not by themselves prove equivocation or expose a signing key. The earlier argument based on a unique first-round block therefore does not apply.
  3. Faulty validators supply at most marks, and exclusion needs .
  4. Honest validators’ keys are not exposed, their blocks are valid, and honest parties do not equivocate.
  5. Coin binding links an honest coin only to an honest validator. So it excludes an honest validator only together with its coin, which happens only after a counterparty stall.

Late passes are bounded

🤖 The previous late-pass bound counted one first-round acknowledgement and one second-round acknowledgement per validator per phase, plus a per-input message where applicable. Ordinary DAG blocks do not supply that fixed item count without an acknowledgement-identification rule. The claimed one-late-pass bound per item, and the derived totals of 13 rounds () or 17 rounds (), are therefore unresolved. The current phase sequence also needs to be included when any such count is derived again.

Successors are bounded

🤖 Conditional on the intended no-framing property, a chain of started successors has length at most the number of faulty inputs plus faulty validators, plus the number of honest payers paying faulty payees. Each valid proposal excludes at least one party, every excluded party is faulty apart from those payers, excluded inputs stay on the deny list, and excluded validators are never added again. If at most inputs are faulty as well, as above, that is the attempts described there, plus the payer term.

An honest participant that declines a successor’s terms does not send ACCEPT, so that successor’s kickoff stalls. Kickoff has no recovery, so the input is not excluded there, and the other participants can accept a competing successor.

Each successor costs a coin

🤖 Conditional on the intended no-framing property, every exclusion by marks or proven fault removes a faulty coin, directly or through coin binding. Under option A the exception is a faulty payee stalling its payer, as above. Retries are then limited by the adversary’s coins, plus the number of honest payers paying faulty payees.

Own-view mode

  • A successor that names an honest participant with a view never excludes an honest input by marks: that participant vetoes, and the successor needs every ACCEPT.
  • An honest aggregator whose result is empty holds every item and relays it, which is a late pass. A vetoing participant holds the item and relays it too, so the next round has it.
  • A light participant cannot veto. If every participant with a view named in a successor is faulty, a framed exclusion can start.

Boundary splits

A proposal that reaches an honest validator just before the cutoff reaches some participants in time and others too late. In quorum mode it wins only if it excludes more, and under synchrony those extra exclusions are faulty parties. The two groups accept different successors. Each stalls at kickoff while the parent keeps running, and neither excludes the other group, since kickoff has no recovery. Either group can also accept the other’s successor.

Without agreement on the set of proposals, this cannot be ruled out. Applying the relay rule of the next section to proposals gives that agreement, at a cost of .

🤖 Dishonest majority

The block DAG leaves this setting unexplored, so this section is exploratory. Open coalition formation resembles Byzantine agreement with unknown participants. Recovery resembles the active-set setting instead: the universe is known, and which members are active is not. Choi et al. define active-parties set agreement for this.6 Its validity conditions map onto recovery:

Active-parties set agreementRecovery
includes every party active from the start that stays honestintended no framing; validator-mark rule unresolved
excludes parties not activated by terminationa missing per-input message supports an input mark; missing-validator marks need a specified acknowledgement rule
may include faulty partiesa spared faulty party costs one more round

Recovery needs less than active-parties set agreement. Different aggregators may build different successors, and unanimous acceptance takes the place of agreement.

Own-view mode is the dishonest majority mode. Per-input messages are signed by their inputs and blocks by their validators, so relaying needs no threshold. 🤖 The intended no-framing argument uses synchrony, signatures and the veto; for validator marks it still depends on identifying the required acknowledgement and its state. What own-view mode lacks is agreement: two honest views can differ at a deadline, and the cost is one more round per vetoed proposal. See what the literature gives.

Relay signatures

This optional rule adds agreement on exclusions among honest parties, as in Dolev and Strong’s authenticated broadcast.7 For a per-input message of a phase with deadline by the party’s own clock:

  • a party counts as on time if it holds by with signatures from distinct validators other than the submitter;
  • an honest validator that first counts as on time with signatures adds its own and relays to every validator;
  • with the assumed number of faulty validators, up to , a party marks missing only at ;
  • 🤖 Extending the rule to first- and second-round acknowledgements requires identifying their ordinary DAG blocks and relevant states. Using the same phase deadline for both rounds is not yet justified.

Each hop needs , not , because honest deadlines differ by up to . If relays at its own , then , whose , holds the message by , which is on time with signatures. If one honest party counts as on time, every honest party does, so honest marks agree and an honest aggregator’s proposal passes every honest veto. The cost is up to before marking: for at .

What the literature gives

  • The threshold is tight. Vigil proves that a node silent toward at most honest nodes cannot be identified (Theorem 2), so the threshold of marks is tight.8 Silence toward fewer nodes can only be repaired by relaying. Vigil also shows that accountability is impossible under partial synchrony with an unknown stabilization time (Proposition 2). That is why framing before stabilization remains.
  • A polarizer can replace the relay chain. A polarizer is a broadcast step after which every honest party holds the message with a proof, or a proof that the sender sent nothing. In the send-transferable-message protocol of Deligios, Klasovita and Liu-Zhang, every honest party ends with the message and a proof, or with a proof that the sender did not send it. This holds for any , and all honest parties stop within rounds, at most one round apart, with the number of parties actually corrupted, the corruption bound and (Lemma 10).9 That is what own-view mode needs: a transferable missing mark that never names an honest sender. It builds on the polarizer of Loss and Nielsen.10
  • The agreement lower bound may not apply. Deterministic broadcast needs rounds.9 Recovery does not need agreement, and no bound is known for the task without it.
  • A veto alone wastes an attempt. A held message shows that its sender sent it, not that it arrived in time. So a vetoed proposal excludes no one, and progress then needs an event that can be proven. This is open.

Which mode to use

SettingMode
can be assumedquorum mode, with the veto as a second check
no honest supermajorityown-view mode
own-view mode, and vetoes cost too many roundsown-view mode with relay signatures, or a polarizer

Privacy

🤖 What the recovery track reveals:

  • which inputs and validators were late in which phase; both are already public within the instance;
  • nothing about anonymous contributions, since recovery track blocks mark only per-input messages and validator blocks.

🤖 Retries:

  • each started successor costs the adversary at least one coin, apart from option A’s counterparty exception;
  • a late pass starts nothing, so it creates no new attempt;
  • a participant accepts at most one successor per stalled phase;
  • excluding an input links it to the outputs that drop out, which is inherent, and is why a retry restarts with fresh secrets rather than in place.

🤖 Change scripts. BIP 352 change derivation is tweaked by the input set.11 Every valid proposal removes at least one coin, through coin binding if it excludes only a validator, so the successor’s input set always differs and its change scripts differ too. Without coin binding, a validator-only exclusion would keep the input set and repeat the scripts. Then the tweak would have to include .

🤖 The following protections are intended; those relying on missing-validator exclusion remain conditional on the unresolved rules above:

  • censoring anonymous contributions, by sending each one to validators, or to all in own-view mode;
  • lying aggregators, since anyone recomputes the exclusion from signed evidence, and the veto checks it against the participant’s own view;
  • withdrawing presence, since a received message is never withdrawn and the DAG witnesses duplicates;
  • 🤖 Differing first-round states are not finalized by union. A second-round acknowledgement must establish that the first-round acknowledgements were synchronized over the same set. How conflicting acknowledgement evidence affects recovery remains unresolved.

🤖 What remains: framing before stabilization under partial synchrony, framing of light participants in own-view mode, boundary splits, honest payers named after a counterparty stall.

Note that synchronization has consequences for privacy as well, when operating outside of the design parameters. A majority of malicious validators, for example, could disrupt gossip and inclusion of certain messages in order to deanonymize them. In this scenario, the participant which unsuccessfully attempted to anonymously broadcast that message but failed can choose to include it, which would potentially implicate it as the author, or defect from validation in order to avoid acknowledging a state which does not include the message. However, in such a circumstance it would be better to allow outputs to be omitted and to withhold signing with one of the inputs in order to reveal as little as possible.

🤖 Cost

🤖 Set finalization requires two acknowledgement rounds using ordinary DAG blocks. This does not establish a cost of exactly two blocks per validator per phase: ordinary publication may produce additional blocks, and acknowledgement identification is not yet specified. The earlier fixed block-count claim is withdrawn. Timers themselves do not add network messages before firing.

One recovery round:

ItemSize
recovery track block parentsat least hashes of 32 bytes
missing inputs, as a bitmap bytes; 92 at 729 inputs
missing validators, as a bitmap bytes
signature64 bytes

With and , one block is about 2.3 KB, and one round about 230 KB across all validators. A proposal with five exclusions is about 2.5 KB, mostly the 67 block hashes, since the successor’s lists are derived rather than sent. A light participant fetches the blocks of , about 150 KB, and the blocks they name as parents, so that it can check signatures, parent authors and marks. It needs no deeper causal history. A participant with the history also checks that no block marks as missing something in its own causal history.

Participants send ACCEPT for the successor at about . The successor’s kickoff then closes like any phase.

🤖 Worked example

Quorum mode, with validators A, B, C and D: , , , and exclusion needs 2 marks. D is faulty. A, B, C and D use the online keys of initial inputs , , and . The auxiliary inputs are and , and the signature for is withheld. The phase is signatures.

🤖 No validator holds a message from . The example illustrates input-omission marks only; it assumes that honest validators make no missing-validator marks while that input message is pending. The general rule for such marks is unresolved. At :

Blockmissing inputsmissing validators
Anone
Bnone
Cnone
D (false)A

With , has 3 marks and is excluded, while and A have one each and are not. So , , and no coin binding applies. The successor has , , and .

If D’s coin later withholds its signature, the next round excludes , and validator D with it. If ’s signature is in the causal history of D’s block, that block contradicts itself. It is invalid and ignored, and D is treated as unresponsive.

🤖 Open questions

  • Counterparty stalls: whether to adopt option B, and if so, whether the payer may learn the payee’s input.
  • Boundary splits: accept them, or pay for agreement on proposals with relay signatures or a polarizer.
  • Whether a veto in own-view mode can lead to an exclusion that can be proven, rather than a wasted attempt.
  • Whether successors may reuse input proofs from the parent, rather than restarting at kickoff.
  • 🤖 How an input that never sends ACCEPT for a successor is excluded, since kickoff has no recovery.
  • 🤖 How the new co-spend proposals that replace dropped ones are made.
  • 🤖 Identification of first- and second-round acknowledgements in ordinary DAG blocks, including their state references, nonce consumption, conflicting-acknowledgement evidence and the timing needed for missing-validator marks.
  • Exact encodings of blocks, signatures and nonce commitments, which are shared with the optimistic track and defined in the block DAG chapter.
  • Recovery activity and view-sufficiency predicates, including how the active set constrains eligible co-spend proposals.

🤖 Appendix: Comparison with agreement building blocks

The DAG records causal evidence; it does not prescribe one agreement primitive for every phase or recovery mode. The following comparison distinguishes dissemination, agreement and inclusion. Applications to Fungi are candidate compositions, not guarantees inherited merely by representing a protocol’s messages as blocks.

The comparison uses the design objectives of the optimistic track. A construction optimized for sustained blockchain throughput or rapid block confirmation may introduce unnecessary work and observable intermediate states in a finite phase. The relevant question is how cheaply and quickly it establishes a stable phase boundary, including the cost of disseminating its agreement evidence.

Building blockGuarantee relevant hereRelationship to this specification
Byzantine Eventual ConsistencyEventual convergence of valid, mergeable updates under its delivery and application assumptions.Supports dissemination of contributions and concurrent recovery proposals. Convergence alone does not identify a finite closing boundary.
Byzantine reliable broadcastAn honest sender’s value is delivered; if one honest peer delivers, all honest peers eventually deliver the same value.Can establish consistent availability of a block or proposal. It need not terminate for a silent faulty sender, and does not establish completeness of a phase.
Interactive consistencyHonest peers decide an identical indexed vector containing every honest participant’s submitted value.A comparison for collecting views. Taking their union does not implement Fungi’s two acknowledgement rounds, which finalize only when the first-round blocks represent the same set.
Asynchronous common subsetAgreement on a sufficiently large subset of indexed proposals, possibly omitting some honest proposals.Can establish a common recovery view without a wall-clock deadline. It does not by itself establish full phase inclusion or require the selected proposers to become successor members.
Lattice agreementDecided states are comparable, with validity relating them to proposed states.Comparable causal views can still differ. A phase requiring one exact common state needs a stronger agreement condition.
Censorship-Resistant Byzantine BroadcastSet agreement with inclusion guarantees for timely honest submissions.Supplies a reference for phase-specific inclusion. The meaning of timely submission must be established for each recovery mode.

Completeness and asynchronous selection

Interactive consistency exposes the collection problem directly. The mostly-asynchronous construction of Diamantopoulos et al. uses a synchrony boundary for collecting inputs, followed by agreement on the result.12 Thus agreement on the vector and knowing which inputs it must contain are separate obligations.

In the standard asynchronous common subset (ACS) formulation, the selected proposer set has , including at least honest proposals. HoneyBadger constructs ACS from reliable broadcast and randomized binary agreement under .13 These are guarantees within a fixed instance; they do not imply global agreement between separate recovery branches.

Overlapping proposals provide a useful inclusion condition. Suppose each proposal is a validated fragment set, and is the set of honest proposers whose submitted sets contain fragment . Since at most proposals are omitted,

🤖 This counting argument protects a sufficiently replicated fragment even when its original observer’s proposal is omitted. It concerns the submitted sets, not information learned after submission. Causal ancestry can witness this inclusion without identifying the anonymous author of the fragment. ACS alone gives no corresponding guarantee for a fragment present in only one honest proposal. This inclusion calculation is not a phase-finalization rule: the union of selected differing views is not the synchronized first-round set required by the second acknowledgement round. A participant continues validator duties independently of inclusion of its own anonymous contributions; its authority to withhold transaction signatures remains separate.

Membership, resilience and recovery

Active-parties set agreement (APSA) establishes a common set of participant identities without knowing their number in advance. Its validity condition includes every participant active from the start that remains honest until termination, excludes identities not activated by termination, and permits inclusion of faulty participants. The construction uses synchronous rounds, signatures and a certificate-authority setup; it does not identify exactly the honest or currently responsive participants.6 This is relevant to the recovery overlay: the parent session has known membership, but the subset available for a successor is not fixed in advance. An aggregator’s view-derived active set need not be globally agreed; APSA supplies a stronger comparison in which eligible honest participants agree on one set. Once a successor coalition proposal is accepted, its construction instance has fixed membership. Agreement on an active set is not a substitute for acceptance of that proposal’s terms or for future signing cooperation.

Authenticated synchronous broadcast admits dishonest-majority constructions. Dolev–Strong is the classical example; FlintBB adds an optimistic execution path when actual faults are lower than the configured bound.14 Their timing assumptions cannot be replaced by DAG height alone. Conversely, allowing separate successor instances weakens the global agreement objective without proving any particular broadcast or inclusion guarantee within those instances.

Sample-based reliable broadcast addresses a different dimension: reducing communication and computation with probabilistic guarantees.15 Its uniform sampling and hidden-communication assumptions require examination before exposing its evidence in validator blocks. It is a dissemination alternative, not a replacement for unanimous acceptance.

The specification does not yet select one of these constructions as the recovery agreement mechanism.

References


  1. Minghang Li et al. TockOwl: Asynchronous Consensus with Fault and Network Adaptability (USENIX Security 2025). TockOwl+ combines fast and slow tracks using hedging delays. ↩

  2. Ittai Abraham, Yuval Efron and Ling Ren. The Latency Cost of Censorship Resistance. ↩

  3. C. Dwork, N. Lynch and L. Stockmeyer, Consensus in the Presence of Partial Synchrony (1988). The introduction contrasts synchronous and asynchronous models and defines the two forms of partial synchrony used here: an unknown timing bound, or a bound that holds only eventually. ↩

  4. P. Wuille, J. Nick and T. Ruffing, BIP 340: Schnorr Signatures for secp256k1. The signature equation behind key exposure. ↩

  5. Idit Keidar, Oded Naor, Ouri Poupko and Ehud Shapiro. Cordial Miners: Fast and Efficient Consensus for Every Eventuality. ↩

  6. W. Choi, R. Cohen, J. Garay, N. Skoumios and V. Zikas, Byzantine Broadcast with Unknown Participants (2025). Defines active-parties set agreement. ↩ ↩2

  7. D. Dolev and H. R. Strong, Authenticated Algorithms for Byzantine Agreement, SIAM Journal on Computing (1983). ↩

  8. J. Cheng, H. Sun, R. Zhou, J. Zhou and Z. Chen, Vigil: Accountable Liveness against Selective Silence (2026). ↩

  9. G. Deligios, I. Klasovita and C.-D. Liu-Zhang, Asymptotically Optimal Early Termination for Dishonest Majority Broadcast, Eurocrypt 2025. The lower bound is cited there on p. 2. ↩ ↩2

  10. J. Loss and J. B. Nielsen, Early Stopping for Any Number of Corruptions, Eurocrypt 2024. ↩

  11. josibake, R. Somsen and S. Falbesoner, BIP 352: Silent Payments. Output derivation tweaked by the transaction’s inputs. ↩

  12. Panos Diamantopoulos, Stathis Maneas, Christos Patsonakis, Nikos Chondros and Mema Roussopoulos. Interactive Consistency in practical, mostly-asynchronous systems. ↩

  13. Andrew Miller, Yu Xia, Kyle Croman, Elaine Shi and Dawn Song. The Honey Badger of BFT Protocols. See also Sisi Duan, Michael K. Reiter and Haibin Zhang, BEAT: Asynchronous BFT Made Practical, Section 5, for the ACS properties. ↩

  14. Danny Dolev and H. Raymond Strong. Authenticated Algorithms for Byzantine Agreement. Ruomu Hou and Haifeng Yu. Optimistic Execution in Byzantine Broadcast Protocols That Tolerate Malicious Majority. ↩

  15. Rachid Guerraoui et al. Scalable Byzantine Reliable Broadcast. ↩

🤖 Peer set reconciliation

Push gossip

Epidemic gossip disseminates data by pushing it: a peer that learns of a new message passes it on to its neighbors, and they pass it on in turn. Every peer eventually receives every message, assuming the required connectivity and delivery. A peer can also request missing messages by hash or reconcile its set with another peer’s set, as described below.

🤖 Small messages are pushed eagerly to neighbors. A block is pushed as just its header, expecting the receiver to already know its Merkle tree.

Requesting hash preimages

A block refers to its parents and to the messages it includes by hash, and a set of messages is committed to by a Merkle root. A peer can therefore hold a root without knowing the leaves it commits to. Such a peer wants to pull the missing leaves, not wait for someone to push them.

Naive reconciliation

Pulling works because honest peers follow two rules:

  • An honest peer never sends a message containing hashes for which it has not validated the preimages.
  • An honest peer responds to a pull for a hash with its preimage.

This is analogous to getdata in Bitcoin’s peer to peer protocol. A peer that receives a hash can pull its preimage from the sender. It repeats this for the hashes in the obtained message, until it reaches messages it already has. This is enough for the naive reconciliation of Byzantine Eventual Consistency (BEC).1 In the block DAG, the hashes are a block’s parents and included messages. The number of round trips can be up to the length of the longest path of missing messages. Kleppmann and Howard reduce it using Bloom filters; that optimization is not needed.

Reconciliation uses peer to peer channels, independently of whether delivery uses a live connection or store-and-forward messages. Exchanges identify their root and scope so delayed replies remain interpretable after a newer advertisement or transport rebuild. A reconciliation stream is a sequence of messages, not a requirement for a connection-based byte stream. Neighbor identity and acknowledged knowledge belong to peer management; they need not expire with the transport connection.

Sparse Merkle sets

Sets are represented by sparse Merkle trees keyed by the cryptographic hash of each referenced object. The key is its set identity; repeated insertion is idempotent. The tree commits to an unordered set, independently of arrival order or the peer that supplied an element.

The DAG does not order messages, so its message sets are unordered. Where an order is wanted, for example if a block’s parents are committed to in an arbitrary order, the commitment is to a list instead: a Merkle tree over positions, like the Merkle tree of a Bitcoin block, which commits to an ordered list of transactions. Ordered versus unordered is the distinction between a list and a set. Whether a set is included in the block DAG determines its consistency guarantees, not its order.

Empty subtrees have a canonical representation. A singleton subtree is represented by its leaf rather than a chain of otherwise empty internal nodes, following the compression described for Libra’s sparse Merkle trees.2 Leaf, internal-node and empty-node encodings must be unambiguous and domain separated. The exact encoding and hash function are pending choices.

Every message sent to a neighbor carries the relevant set root. An advertised root adds that set to the reconciliation allow-list for that neighbor. Reconciliation requests are scoped to such an advertised set, or to a subtree established during its reconciliation. Advertising a root authorizes reconciliation; it does not establish that the contents are valid or available.

Immutable sets coexist with changing inventory sets. For example, a block DAG can advertise its current frontier, unincorporated contributions or all known blocks; the frontier can change while its causal closure grows monotonically. An inventory advertisement identifies the kind of set as well as its current root; the retention policy for superseded inventory roots remains to be specified.

An exchange identifies an immutable root. Later advertisements can introduce newer roots without changing the meaning of an exchange already in flight. Obtained messages are shared across exchanges and neighbors through the local content-addressed inventory.

Sets outside the block DAG

The same mechanism can exchange the Merkle set roots of messages that are not in any block. These sets are ephemeral and have no protocol consistency guarantees; they are just used to trigger set reconciliation.

  • In the peer to group context, this is analogous to a mempool: contributions to a transaction construction session that no block includes yet.
  • In the peer to world context, this is the order book of coalition formation: listen advertisements, co-spend proposals, and their ownership proofs.

Peer to world does not rely on BEC or on blocks. Peers just exchange Merkle trees with adjacent peers. The coalition formation protocol decides which objects are valid, which are kept, and which are eligible for negotiation.

The DAG’s equivocation mechanism exposes a validator’s BIP-322-endorsed online private key. Gossiping this scalar and its endorsement evidence lets other peers verify the fraud proof and ban the associated coin from coalition formation without obtaining the equivocated blocks. Reconciliation disseminates the evidence; the consuming protocol validates it and applies the admission policy.

Quiescence before block authoring

🤖 Set reconciliation is an input to block publication: a validator waits for its neighbors’ sets to converge before authoring its next block, whichever reconciliation algorithm is used. The rule and its purpose, avoiding needless block DAG waves, are described under block publication and quiescence in the optimistic track.

Optimizations

Range-based set reconciliation (RBSR), and RBSR combined with rateless invertible Bloom lookup tables (RIBLT), come naturally from the same mechanism. Instead of exchanging a root and pulling every leaf, two peers compare subtrees, and pull only where their sets differ. We call the combination hybrid recursive/rateless set reconciliation: RBSR recursively controls the scope of the exchange; optional rateless<iblt> and rateless<pinsketch> streams can use available bandwidth while range replies are in flight. These algorithms target different device and network tradeoffs; an optimal switching policy has not yet been established.

Mutual and asymmetric knowledge

Each peer has a local inventory and neighbor-specific evidence about the neighbor’s inventory. A root identifies a set without establishing that the receiver possesses its elements. The receiver may know only the commitment, some leaves, or the complete set. Missing identifiers and missing message preimages are distinct: learning a leaf hash can identify a subsequent content request.

Mutual knowledge here means an operationally established shared subset, not epistemic common knowledge. A jointly identified baseline can be omitted from both sides of a reconciliation exchange. Asymmetric knowledge also helps: a peer can request particular missing objects or avoid resending acknowledged objects without first establishing identical inventories. Mere absence from an advertisement need not establish that the neighbor lacks an object.

Range reconciliation and streaming

The first optimization direction is range-based set reconciliation in the style of Meyer and Scherer.3 It is not needed for the base functionality. A sparse-tree prefix identifies a key range. Equal subtree commitments require no further exchange; unequal ranges are subdivided or resolved by transmitting leaves.

A subtree advertisement includes its key prefix as well as its root. The receiver can compare it directly with the corresponding position in its local tree, without first requesting every intervening level. The sender may skip levels and stream intermediate subtrees of comparable population, reducing sequential round trips. Population estimates used for scheduling are not substitutes for checking the committed set.

Each channel independently randomizes the order of streamed subtrees, for example using an ephemeral channel secret. If several neighbors possess the same set, their different schedules tend to expose different missing ranges first. Recovered objects immediately update the common inventory and can satisfy work pending on other channels. This reduces duplicate transfers in expectation; it does not guarantee disjoint work.

Restricting comparisons to sparse-tree prefixes is a specialization of the range approach. It does not automatically inherit bounds for arbitrary equal-population range partitions; the cost of representing such partitions by multiple prefixes requires evaluation.

The range protocol remains usable without a homomorphic fingerprint. Rateless reconciliation, described below, has additional requirements.

Shared-knowledge baselines

Acknowledged set commitments provide evidence of data already shared with a neighbor. Application-level references can compactly supply further evidence; a block DAG is one such application. Let and be the two sets being reconciled and let be a mutually identified subset of their intersection. Then

Removing reduces the number of elements to encode without changing the difference to recover. This is useful even when the residual elements are widely scattered across the key space.

In either setting, acknowledged inventory roots and object receipts can establish shared knowledge. In the DAG setting, additional neighbor-specific information is available:

  • A neighbor’s validated blocks identify payloads and causal ancestors that the local node has also obtained.
  • Blocks from that neighbor which build upon local blocks acknowledge the corresponding causal closure.
  • The local transmission log identifies objects already sent to that neighbor. Until receipt is established, this is speculative knowledge rather than an acknowledged common baseline.

Baseline references must determine the same at both endpoints. A local belief about a neighbor’s inventory is insufficient. A baseline can be named by agreed DAG frontiers; its use is restricted to elements common to the sets in the current exchange. Knowing an object does not imply that it belongs to every advertised block payload. For cumulative causal inventories, a shared ancestral frontier supplies this subset directly.

The original root remains the target commitment. Residual reconciliation need not create a separate authenticated tree for each neighbor. PinSketch subtraction, for example, can remove a common baseline algebraically, whereas range traversal can skip established shared subtrees or account for known leaves.

A Byzantine neighbor may acknowledge data it does not possess. Such an acknowledgement does not permit either endpoint to accept unchecked contents. Missing data can still be requested, and the exchange can fall back to a smaller baseline or none. Baseline agreement and fallback messages remain to be encoded.

Hybrid recursive/rateless set reconciliation

The second optimization direction combines range reconciliation with rateless streams.

An advertised root may be followed immediately by a rateless reconciliation stream for that set. This uses the time before a range-based reply arrives. The rateless<iblt> candidate uses an elliptic-curve multiset hash (ECMH) for its homomorphic cell checks, together with a channel-specific sampling schedule.4 The ECMH and adversarial-set adaptations are distinct from the published RIBLT construction and require their own analysis.5

A range reply narrowing the work to subsets is an unconditional stop signal for the parent stream. Stopping does not depend on whether its decoder has completed. Further optional streams are scoped to the unresolved subsets. The exchange identifies the root, prefix and stream parameters so that delayed parent cells cannot be mistaken for child cells.

Streams with different sampling parameters have separate decoder state. Recovered objects can be shared across decoders; differently parameterized cells cannot be pooled as one sketch. Previously received cells may be retained locally, but stopping a stream ends further transmission for that scope.

The relevant robustness target includes honest peers reconciling sets whose elements were chosen adversarially by third parties. Channel-specific schedule randomness and ECMH checks address different concerns: deliberate concentration in the sampling schedule and false cell recovery, respectively. Neither compels a malicious neighbor to send data. Parameter selection and bounds on decoding work remain open.

Sparse differences and rateless<pinsketch>

A small difference spread throughout a large set can require many tree comparisons. PinSketch is a candidate for resolving such ranges directly. A capacity- sketch of -bit nonzero field elements occupies bits and can recover a symmetric difference of at most elements. Sketches combine by XOR.6

Capacity depends on the difference size, while construction work also depends on the population being encoded. Straightforward construction over elements costs field operations. Conventional decoding has quadratic scaling in the supported difference size. A shared-knowledge baseline reduces without reducing the required capacity for the same difference.

Two extensions are under evaluation:

VariantOperationTradeoff
Additional syndromesExtend the PinSketch for the same range without retransmitting earlier syndromes.Increasing capacity increases computation; reuse of failed decoding work requires implementation support.
Small PinSketch cellsUse small-capacity sketches with a rateless sampling sequence, allowing a cell to recover several residual elements.Bounds local decoding work, but changes the peeling algorithm and requires new performance and robustness analysis.

In either case, a narrowing range reply stops transmission for the parent scope. Computational budgets can trigger subdivision rather than further sketch expansion. Small fixed-capacity sketches cached at selected tree nodes can reduce repeated encoding work, at a storage and update cost. Channel-dependent sampling limits reuse of cached sampled sketches.

Decoding beyond capacity can return a false candidate rather than an explicit failure. Sketch results are provisional until checked against the committed data. A sampled-cell construction must account for false recovery before propagating it through peeling; checking only the final root detects failure but does not bound wasted decoding work. Mapping message hashes into smaller field elements also requires collision handling. These details remain part of the sketch profile, not changes to the DAG semantics.

Resource bounds and validation

Outstanding neighbor exchanges, speculative decoder work and retained unresolved roots require explicit bounds. An advertised root scopes requests but does not establish that its set is small or admissible. Duplicate data does not earn repeated processing rights. Retrieved contents are checked against commitments; application validity is checked by the consuming protocol.

Open specification choices

Remaining choices include canonical tree encodings; advertisement scopes and retention; baseline references and fallback; range scheduling; rateless parameters and ECMH checks; field-element mapping and sketch validation; and computational and bandwidth budgets. Measurements should vary set population, symmetric difference, latency, device capability and number of neighbors independently.

The reconciliation mechanism reports completion for a specified scope. Whether that completion permits publishing a block or advancing a phase belongs to the consuming protocol.

References


  1. Martin Kleppmann and Heidi Howard. Byzantine Eventual Consistency and the Fundamental Limits of Peer-to-Peer Databases, §5. ↩

  2. Zachary Amsden et al. The Libra Blockchain, sparse Merkle tree discussion. ↩

  3. Aljoscha Meyer and Konstantin Scherer. Range-Based Set Reconciliation Without Homomorphic Hashing. ↩

  4. Lei Yang, Yossi Gilad and Mohammad Alizadeh. Practical Rateless Set Reconciliation. ↩

  5. Ephemeral ECMH, on whether small elliptic curves can serve as the checksum in rateless set reconciliation, against adversarially chosen items, with a public beacon instead of a shared secret. ↩

  6. Minisketch: an optimized library for BCH-based set reconciliation, including its mathematical explanation and incremental-decoding discussion. ↩

🤖 Protocol messages

Scope and status

This chapter lists the messages peers exchange in the Fungi protocol suite. For each message it says who sends it, to whom, in which setting, what it carries, and what the channel carrying it must provide.

It is a draft. Wire encodings, field sizes and signature profiles are not specified yet. Sizes below are orders of magnitude. Each section ends with its open questions.

The messages fall into these groups:

GroupPurposeSettings
Peer introductionLearn and label peers out of bandhonest, semi-honest
GossipDisseminate objects within a namespaceall
SetsCommit to, list and reconcile sets of objectsall
Public gossipOrder book for coalition formationByzantine
NegotiationBilateral co-spend and coalition proposalsByzantine
Session initializationStart a construction sessionall
Transaction constructionBuild the transactionall
Interactive paymentsGrant funds and confirm paymentshonest, semi-honest
BlocksSynchronize state and signal phase changessemi-honest, Byzantine

Channel requirements

Channels are described by their properties, not by a transport. Choosing a transport that has these properties belongs to another layer.

PropertyValuesInterface
Directionsend, receive, or bothSendChannel, RecvChannel, Bidirectional
Delivery modeone peer, or broadcastPeerChannel, BroadcastChannel
Unlinkabilityper channel, or per messageUnlinkableMessageChannel
Delivery guaranteesreliable or unreliable
Timingasynchronous or synchronous
Metadata hidinghides metadata, or not

Delivery guarantees, timing and metadata hiding are tags: properties declared about a channel.

Metadata hiding is always with respect to the initiator: the sender, or the side that connects on a stream. The responder is always identified, by its peer ID or its address.

An unlinkable channel used for one message at a time yields unlinkable messages, with caveats. For example, an implementation that reuses circuits can leak timing metadata.

Every message type states explicitly which channels are appropriate for it. Two are specified so far:

MessagesDirectionDelivery modeUnlinkabilityDeliveryMetadata hidingAuthentication
Transaction construction, semi-honest and Byzantinesendbroadcastper messagereliablerequired—
Interactive paymentssend and receivepeereitherreliable—the payer authenticates the payee; the payee may or may not authenticate the payer

Open questions:

  • What do gossip, set and public gossip messages require of their channels?
  • What do transaction construction messages require in the honest setting?

Peer introduction

Honest and semi-honest settings only.

A user adds a peer ID out of band, with one of four trust levels:

Trust levelMeaning
selfthe user’s own devices
trustedtrusted with privacy and liveness, e.g. in the same organization
semi-trustedtrusted with liveness
untrustedthe peer ID is stored and labeled, but not used

Open questions:

  • Should there be an introducer role, for self, trusted and semi-trusted peers, that may add peers at or below its own trust level?

Gossip

Gossip always happens within a namespace, also called a topic.

Some namespaces are ephemeral. Their name is derived from a shared secret using a tagged hash. Some are well known, such as the version 1 public order book. Co-spend proposals are namespaced by a Bitcoin block hash. If an object’s ID is derived from a namespace that includes a block hash, the ID can be short.

Minimal gossip

These three messages suffice in the honest setting:

MessageContentsNotes
announceobject hashthrottled, or suppressed by set reconciliation
pullobject hashrequests an announced object
pushobjectsolicited: answers a pull

🤖 Small messages are pushed eagerly to neighbors. A block is pushed as just its header, expecting the receiver to already know its Merkle tree.

🤖 After an anonymous submission enters the broadcast domain, peers disseminate it by gossip or set reconciliation. Anonymous submission does not replace dissemination.

Unsolicited push

The semi-honest and Byzantine settings add one message:

MessageContentsNotes
push (unsolicited)objectused for anonymous broadcast

A peer receiving a new object by unsolicited push forwards it by push to one randomly selected peer, and announces it to its other peers.

Open questions:

  • How to scope ephemeral namespaces: by shard, by time, or by number of messages.

Sets

Every message carries a state commitment. It includes the Merkle roots of the sender’s mutable sets, its height and its set sizes.

Immutable sets

An immutable set is referenced by its Merkle root. Sets are sparse Merkle trees, in the style of Libra’s. A block commits to two immutable sets: its parents and its messages.

Mutable sets

A mutable set is tracked as a sequence of Merkle roots. A peer has these:

SetMonotone
roots: the highest blocks, and the messages in no blockits closure is; the set itself is not
all blocks known to the peeryes
blocks known to the peer at a given heightyes
all messages in blocks known to the peeryes

Fetching an ever-growing collection of sets is a resource exhaustion risk. Blocks are needed for progress, and are rate limited by cordiality. A dishonest majority can still flood.

Set listing

MessageContentsReply
pullMerkle rootits preimage
listMerkle rootall of its leaves

Leaves here are hashes, not preimages. Listing all leaves lets the receiver recompute the root.

Set reconciliation

Two methods are candidates:

  • Range based. List to a given depth, with clamping.
  • RIBLT. A stream of rateless coded symbols for a set.

For mutable sets, randomize the hash and restart the stream on each new item. Reply to a range based request with the children, then stream RIBLT data.

The RIBLT cells need a multiset hash. Elliptic curve multiset hash (ECMH) candidates are:

  • GLS254;
  • a GLS254 analogue with m = 61 or m = 67, where complete formulae should hold;
  • the curve25519 ECMH in fastcrypto;
  • secp256k1.

Open questions:

  • Can only the latest root of each mutable set be queried?
  • Should listing to a given depth return the intermediate nodes?
  • Should a range based reply jump ahead, up to some listing size, instead of returning only the children? How does range based reconciliation apply to mutable sets?
  • Is range based reconciliation only for immutable sets, or throttled for mutable ones?
  • Should immutable sets use a hybrid, interspersing RIBLT with range based reconciliation?
  • Can reconciliation data be carried in padding and in announce messages?

Public gossip

Public gossip uses a well known namespace. These objects form the order book for coalition formation.

ObjectContentsFlood protection
ownership proofBIP 322 proof for a UTXO, committing to its online key, a validity interval and a block hashproof hash below a threshold; replaces higher hashes for the same UTXO
UTXO directory entryownership proof, prevout or previous transaction, listen advertisements—
listen advertisementchannel to reach the owner, constraints on proposals, willingness to be a validator, signed by the online keysignature hash, as for ownership proofs
co-spend proposal, unanimously acceptedsee negotiationone MuSig2 signature per proposal
co-spend proposal, partially acceptedopt-in onlytime dependent key images
coalition proposalsee negotiationsignature hash of the aggregator’s key

Willingness to be a validator is one of: demands it, opts in at the aggregator’s discretion, or declines.

Negotiation

Byzantine setting. These messages go over the channel named in the recipient’s listen advertisement, or are gossiped as partial proposals where peers opt in.

MessageFromToContents
co-spend proposalproposereach named UTXO owneroutpoints, conditions, ownership proof commitments, one adjustment commitment per UTXO with range proofs, surplus and balance proof, expiry, optional conflict hints, the opening of the recipient’s adjustment
acceptanceeach ownerinvolved peersa linkable ring signature by its online key
MuSig2 nonces and partial signatureseach ownerinvolved peersturn a unanimously accepted proposal into a fully accepted one
coalition proposalaggregatorevery implicated ownerfully accepted co-spend proposals, concrete parameters, adjustment vector, protocol version, committed listen advertisements naming the validators
coalition acceptanceeach ownerinvolved peersa signature by its online key

In the semi-honest setting the ring signatures can be skipped. Owners then negotiate MuSig2 directly.

Session initialization

SettingHow a session starts
honest, semi-honesta peer invites others to a random gossip topic
Byzantinethe gossip topic is the hash of the coalition formation proposal, including secret data encrypted to all participants

Transaction construction

These messages are gossiped to the session’s topic. Transaction contributions project into unordered PSBT state and combine according to concurrent PSBT construction. In the Byzantine setting, the wire format consists of specified protocol messages, rather than arbitrary PSBTs. Honest and semi-honest construction can tolerate PSBT extensions; extensions in the Byzantine setting must be specified as protocol extensions.

In the semi-honest and Byzantine settings they need a send channel with unlinkable messages, reliable delivery and broadcast addressing. Outputs in particular must always be message-unlinkable and hide metadata.

MessageContentsSizeSettings
initializesession parameters—all
add inputinput with prevout datahundreds of bytesall
add outputoutput with its unique IDhundreds of bytesall
add fee contributionexplicit fee contributiontens of bytesall
issue from initial inputvalidity proofseveral KiBByzantine
issue from auxiliary inputvalidity proofseveral KiBByzantine
redeemvalidity proofseveral KiBByzantine
signsignatures for one inputtens of bytes, more in the Byzantine settingall

Initialize

Sets up the session parameters. The sort seed is the transcript hash: the Merkle set commitment of the accepted construction messages at the agreed state before signing, including the applicable proofs. Later input signatures and acknowledgement-only blocks do not change this seed. Concurrent PSBT construction allows this by setting PSBT_GLOBAL_SORT_DETERMINISTIC and leaving PSBT_GLOBAL_SORT_SEED unset, so each replica supplies the seed when it orders the transaction.

Add input

An input map with its prevout data. In the Byzantine setting, initial inputs are named by the coalition formation proposal, so only auxiliary inputs carry prevout data. The message also carries:

  • an ownership proof committing to an online key;
  • a signature by that online key on the message, committing to the session ID or gossip topic.

Add output

An output contribution, which projects into a PSBT output map. Its unique ID becomes PSBT_OUT_UNIQUE_ID, so adding it twice is idempotent, while two equal outputs added separately stay distinct.

🤖 In the optimistic phases, each admitted output has an amount of at least 1 sat, as required by the construction rules.

Add fee contribution

A 16 byte unique ID and an amount, which project into a PSBT_GLOBAL_EXPLICIT_FEE_CONTRIBUTION entry. Fee contributions let peers account for fees exactly.

🤖 In the optimistic phases, each admitted fee contribution accounts for at least 1 sat. The overflow signal has the separate meaning described below.

Issue and redeem

Byzantine setting only. These messages carry validity proofs. Issuance is from initial inputs or from auxiliary inputs. Their contents depend on the validity proof construction, which is specified separately.

Sign

The signer first converts the PSBT to an ordered one, then signs with SIGHASH_ALL. A signature is tens of bytes. In the Byzantine setting the message can be larger, bounded by the size of the input’s ownership proof.

Signers differ in how they can be used:

SignerBehavior
hot keysigns automatically, any number of times
manualthe user approves each signature
limitede.g. a hardware security module, or a virtual one

Interactive payments

Messages to a designated peer, the counterparty of a payment:

MessageFromToMeaning
grantpayerpayeegrants n sats of the payer’s funds to the payee
confirmpayeepayerconfirms the committed state the payer’s signature depends on

The concurrent PSBT specification defines what is confirmed and in what order, including how cycles are broken by net receivers. It is concerned with state only. These messages carry that state between the counterparties.

These messages need send and receive channels with reliable delivery and peer addressing. They may be linkable or unlinkable. The payer must authenticate the payee. Whether the payee authenticates the payer depends on the payment; game theory suggests it shouldn’t.

Interactive payments belong to the honest or semi-honest threat model, not the Byzantine one. They can still take place within a broader Byzantine session.

Blocks

Blocks provide consistency and synchronization, in the style of a blocklace. They are used in the semi-honest and Byzantine settings.

A block contains:

  • the Merkle set commitment of its parent blocks;
  • the Merkle set commitment of the gossiped transaction construction messages it includes;
  • its parent block by the same node;
  • the nonce point R its successor will be signed with.

A block is signed with the nonce point committed in its own-node parent.

SettingSigning key
Byzantinethe UTXO’s online key
semi-honestan ephemeral key, for simplicity, though the model doesn’t need it

Phase change signals

Blocks also signal phase changes:

SignalEffect
inputs fixedclears the inputs modifiable flag
overflowacts as a single fee contribution with ID “” and amount MAX_MONEY, the top of the lattice
outputs fixedclears the outputs modifiable flag and sorts the transaction
initial input issuanceissuance from initial inputs
auxiliary input issuanceissuance from auxiliary inputs
outputs provenall outputs are proven, and invalid outputs pruned

Open questions:

  • In the semi-honest setting, can additional validators just join? If not, how is initialization synchronized?

🤖 Validity proofs by allocation registration

🤖 Status: selected (2026-10-25). Allocation registration was chosen because the payee doesn’t learn the paying input, at the cost of a separate registration phase between the input and output proofs; see Compared with other approaches. The code is being rewritten from scratch for Fungi. Figures marked measured come from a proof of concept on a shared machine; parts marked proposed are not implemented yet. The open questions list what is not specified yet.

The overview explains when validity proofs are needed: once overspending has been detected, outputs and fee contributions must prove they are covered by input funds, without revealing how each participant allocates its funds. This document specifies one way to do that.

🤖 Proofs are needed only in the proven phases, phases 4 to 7 of transaction construction. They run only after overflow in the optimistic outputs phase. The optimistic phases before them carry no proofs.

🤖 In outline: each input commits to how its value is split, with an input proof. Each part is then registered anonymously, and each output proves anonymously that registered parts cover its amount. The intuition below explains how, and Statements specifies each proof.

Intuition

Slots, registration and outputs

Three steps carry value from an input to an output:

  1. 🤖 Slots. Each input splits its value into slots. Each slot specifies an amount and a destination. The input commits to its slots with an input proof. Initial inputs prove first, identified by outpoint; auxiliary inputs are submitted anonymously with their proofs afterward.
  2. Registration. Each non-zero slot is turned into a registered leaf by a registration proof, posted anonymously. The proof shows the slot belongs to some admitted input without saying which.
  3. Outputs. An output proves that up to registered leaves name it as their destination, and that their amounts sum to its amount. It is posted anonymously.

A payment is just a slot whose destination is someone else’s output. The payer registers it; the payee claims it.

Payments need no proof about the payment from the payer to the payee, no recursion and no multi-party computation. The payer only hands the payee its registration proof early, which is a public object anyway.

Interactive payments and net settlement are in scope. The circuits check only the endpoint allocation: slots from inputs, registered, and claimed by outputs. They have no payment variables. Payment obligations, including net settlement (a participant without inputs that receives from A and pays C, or a cycle of payments), are mapped onto slots, and confirmed with counterparties, by private messages around the proofs. This document specifies those messages for a direct payment from an input to an output; the rest is open. and bound the endpoint allocation, not the number of payments.

Two trees, so payer and payee never share a path

Each proof proves membership in a tree that everyone builds from public, agreed data:

  • the session tree over the inputs’ slot commitments, used by registrations;
  • the registration tree over registered leaves, used by outputs.

The payer’s path, from slot to input, lives only inside its zero-knowledge registration proof. The payee’s path, from leaf to the registration tree’s root, is computed from public data. No input membership path crosses from payer to payee, so the payee can’t learn the paying input, and the payer can’t learn the funded output. What does pass between them is the binding , the registration proof and the receipt.

A tag per slot limits each input to D registrations

Registration is anonymous, so something has to stop an input registering the same slot twice. Each registration publishes a tag

where is a secret the input committed to. The tag is deterministic in , so a second registration of the same slot repeats the tag and is dropped. It is pseudorandom without , so it doesn’t reveal the input. This is the idea behind periodic -times anonymous authentication.1 Here the bound is the number of slots, and the slot’s position in the tree supplies .

Flood protection

🤖 These bounds apply to the proven phases:

  • Auxiliary inputs consume vbyte allocations committed by initial inputs.
  • A registration spends one of an admitted input’s slots, so there are at most registrations under the input capacity in Parameters.
  • A proven output must claim at least one registered leaf, and each leaf can be claimed by only one output.

🤖 Before overflow, each optimistic output or fee contribution accounts for at least 1 sat, so the input balance bounds them. These contribution bounds do not bound all network traffic.

Destination fixed at commitment

A slot commits to its destination’s binding when the input proves (destination mode). So the registered leaf is fully determined by the slot, and any valid registration of a slot is identical. This is why the payee must give the payer its binding before the payer’s input proof.

The payer hands its registration proof to the payee once is agreed, and either one can submit it. After the payee has it, the payer can’t renege by withholding its registration. It can only refuse to sign, and then its input is identified by outpoint. Before that, the payer can still withhold the proof itself (see Signing and failures).

The flow graph

A transaction moves value from inputs to outputs. Each participant decides how its own inputs’ value is split. Some of that value goes to its own outputs, and some to payments to other participants.

As a matrix

Write the flows as a matrix . Rows are sources and columns are sinks. There are four kinds of vertex:

  • inputs, whose values are public;
  • outputs, whose amounts are public;
  • the fee, a public sink: each input’s hidden excess, or fee pseudo-outputs;
  • payment vertices, one per payment. Each is shared by exactly one payer and one payee, and is not labelled publicly.

is the sum of one sparse matrix per participant, . A participant’s has non-zero entries only on edges at its own vertices, or at payment vertices it shares:

  • from its inputs to its own outputs;
  • from its inputs to a payment vertex, if it is a payer;
  • from a payment vertex to its outputs, if it is a payee.

A payment of from payer to payee through payment vertex appears in two blocks: the edge into in , and the edge out of in . Both edges stay in the sum. What cancels is the net flow at : in from , out from , so neither creates nor destroys value. Contracting gives an entry of from the payer’s input to the payee’s output.

Contracting every payment vertex leaves a bipartite allocation from inputs to outputs and the fee. Payments are structure inside its edges, and don’t change its row and column sums. Those sums are public; its entries are not.

payee's matrix M_k

payer's matrix M_j

a_change

a

a

b

input i (value public)

output o (amount public)

payer's change output

payment vertex p

payee's input

payee's matrix M_k

payer's matrix M_j

a_change

a

a

b

input i (value public)

output o (amount public)

payer's change output

payment vertex p

payee's input

What is observable

  • The boundary is public. Row sums over input rows are the input values. Column sums over output columns are the output amounts. These are exactly the public inputs of the proofs below.
  • Each block is private to its participant. The proofs reveal nothing about how a participant splits its inputs beyond the boundary.
  • Each payment entry is known to its payer and payee. The payer knows its input and the amount. The payee knows the amount and its output. The proofs reveal neither side to the other.
  • No one is shown the full matrix. In particular, the proofs don’t reveal the entry from a payer’s input to a payee’s output.

These hold under the stated leakage: the public boundary, what counterparties know of their own payments, and anonymous submission. Amounts, small anonymity sets and colluding counterparties can still reveal more.

How the proofs enforce it

The proofs check that no vertex creates value, without anyone assembling :

VertexConservationChecked by
inputits slot amounts plus a hidden excess equal its public valueinput proof
payment vertexthe payee can claim at most what the payer registeredregistration proof plus output proof, linked by the binding
outputits claimed leaves sum to its public amountoutput proof

🤖 Anything registered but not claimed, or committed but not registered, becomes fee. The proofs establish non-inflation. Counterparty confirmation establishes that the committed construction satisfies the payment agreement. In the proven phases, the payer also checks a receipt showing that its allocation was claimed before signing.

The cost of each proof depends on one participant’s block, a fixed small number of slots, and on the tree depths fixed by the session’s capacity.

Requirements

RequirementStatus
Privacy. No association among inputs and outputs beyond the public boundary and what counterparties know of their own payments.Argued in Privacy, not formalized. Relies on anonymous submission.
Counterparty privacy, both ways. The payee doesn’t learn the paying input; the payer doesn’t learn the funded output.Met by the two trees and one blinding per source.
No inflation. Amounts are non-negative, each registered leaf funds at most one output, and outputs sum to at most the inputs.Met; see No value is created.
🤖 Flood protection in the proven phases. Auxiliary inputs consume initial inputs’ vbyte allocations; registrations and outputs consume allocations from admitted inputs.Registrations are bounded by per admitted input, and each output must claim a registered leaf. Duplicates count once and equivocation is removed (Acceptance rules). vbyte admission is not in the proof of concept.
🤖 Session binding. No statement replays across sessions.Enforced by the acceptance rules: validators build each root from statements accepted for that session and verify dependent proofs against the expected root. This is not in the proof of concept.
🤖 Honest allocations can’t be blocked. Other participants can’t consume or block an honest allocation, apart from the dependency between a payer and its payee.Tags are per slot, and a leaf is claimable only under its own binding. Proven outputs use fresh output ids.
Attributable failure. A run either completes, or names an input that recovery can exclude.Met by per-input signatures and the signing rules. Completion proofs are optional.
Interactive payments and net settlement, including recipients without inputs, intermediaries and cycles.In scope. The circuits check any endpoint allocation within and . The private messages for net settlement are open.

Phases and data dependencies

Each public phase ends with agreement on its contribution set (see phase closure). Everyone then computes the phase’s root from the agreed set. Proofs in the next phase use that root, alongside their own public inputs. No proof depends on another party’s private proof. A phase’s boundary is a phase transition in the block DAG.

🤖 Every public phase is a set to agree on, not a sequence. Proofs within a phase can be made and posted in any order, and are verified against the phase’s fixed public inputs and roots.

🤖 Initial-input proofs are identified by outpoint and authenticated by their enrolled online keys. They commit to allocations of funds and vbytes. Their agreed set supplies the vbyte allocations that auxiliary-input proofs consume. Once both input-proof sets are fixed, everyone derives the final from the accepted initial and auxiliary input roots. Output proving then has two stages: anonymous allocation registration against , followed by anonymous output proofs against the resulting .

balance zero

overflow

agreed initial allocations, including vbytes

accepted initial and auxiliary input roots

agreed leaves, dedup by tag

agreed tags

agreed outputs, dedup by output id

session and initial inputs

optimistic auxiliary inputs

optimistic outputs and fee contributions

signatures by outpoint

initial-input proofs by outpoint

auxiliary-input proofs, submitted anonymously

R_S

allocation registration, anonymous

R_L

output proofs, anonymous

R_T

completion proofs, optional, by outpoint

R_C

script authorizations

receipts, private, payee to payer

balance zero

overflow

agreed initial allocations, including vbytes

accepted initial and auxiliary input roots

agreed leaves, dedup by tag

agreed tags

agreed outputs, dedup by output id

session and initial inputs

optimistic auxiliary inputs

optimistic outputs and fee contributions

signatures by outpoint

initial-input proofs by outpoint

auxiliary-input proofs, submitted anonymously

R_S

allocation registration, anonymous

R_L

output proofs, anonymous

R_T

completion proofs, optional, by outpoint

R_C

script authorizations

receipts, private, payee to payer

🤖 The proven phases have the following dependencies, numbered as in transaction construction. Payment confirmation is required before signing on both paths; receipts are additional checks in the proven phases.

PhaseSubmissionDepends onProduces
4. Initial-input proofsby outpointsession, fixed initial inputsagreed initial-input allocations, including vbytes
5. Auxiliary-input proofsanonymousagreed initial vbyte allocationsaccepted auxiliary-input allocations; final
6. Allocation registrationanonymoussession, registered-leaf root ; tag root if needed
completion proofs, optionalby outpointinput root, evidence that an input’s non-zero slots were registered
7. Output proofsanonymoussession, proven output set, claim root
script authorizationanonymousoutput id, output key, scriptauthorized final outputs
8. Signaturesby outpointfinal transaction, payment confirmations and applicable receiptstransaction

Private messages between payer and payee

🤖 In the proven phases, each direct payment adds the following three private proof messages. They are exchanged only when proving is needed, within the windows shown below. The ordinary payment-confirmation exchange remains required as well.

Validators (block DAG)PayerPayeeValidators (block DAG)PayerPayeediscard optimistic outputs, choose fresh pk and id, prepare amount and bindingbinding B_kinput proof by outpoint, in the applicable input-proof phasefinal R_S after initial and auxiliary input proofsregistration proofregistration (or Payee submits it)agreed R_Loutput proofagreed output set and R_Cscript, signed under pkreceiptsignature after receipt, script and payment-confirmation checks
Validators (block DAG)PayerPayeeValidators (block DAG)PayerPayeediscard optimistic outputs, choose fresh pk and id, prepare amount and bindingbinding B_kinput proof by outpoint, in the applicable input-proof phasefinal R_S after initial and auxiliary input proofsregistration proofregistration (or Payee submits it)agreed R_Loutput proofagreed output set and R_Cscript, signed under pkreceiptsignature after receipt, script and payment-confirmation checks
MessageAfterBefore
payee → payer: binding session known; output amount and id chosenthe payer’s input proof
payer → payee: registration proof agreedregistrations close
payee → payer: receipt agreedthe payer signs

What this means for being online:

  • 🤖 Payer and payee must be available for payment confirmation after output finalization and before input signing, and, if proving becomes necessary, for these proof messages.
  • 🤖 The payee chooses fresh output ids, and supplies the binding before the applicable input proof. Script authorization follows the proven output set.
  • Third parties never see a pair’s private messages. But a party waiting on one may delay its part in a public agreement, so third parties can wait on them indirectly. A stalled agreement is resolved by recovery, not by the proofs.

Parameters

SymbolValueMeaning
curveBN254proof system field and pairing
proof systemTurboPlonk, KZG, jellyfishuniversal setup
Poseidon, width 4, rate 3, , 8 full and 56 partial roundsall in-circuit hashing
arity3every Merkle tree
9slots per input (2 tree levels)
inputsat most 729session tree, 6 levels
registrationsat most 6,561registration tree, 8 levels
2registered leaves per output
amount bits51 21 million BTC in satoshis
excess bits32an input’s hidden fee share

Placeholder constants: the proof of concept generates Poseidon constants with arkworks’ Grain generator. They are not the reference constants. Production must load the reference constants.

Hashes and objects

is the Poseidon sponge with the capacity element set to the domain constant , absorbing three elements per permutation. Each domain has a fixed input length. Tree nodes are one permutation of .

In the proof of concept:

  • The state is . Each block of up to three inputs is added to elements 1–3, then the state is permuted. The hash is element 1 of the final state, and so is a tree node.

  • Domain constants and input lengths:

    DomainConstantInputs
    ALLOC73
    OUT83
    SLOT113
    RTAG123
    CLAIM133
    SID141
    NODE3 children
  • Amounts and slot indices enter as field elements of their integer value.

  • The output id is the first 31 bytes of the SHA-256 digest read as a little-endian integer. SHA-256 is taken over the 32-byte x-only serialization of .

  • In the script authorization message, session and the id are 32-byte little-endian field encodings, followed by the raw script.

  • Padding for trees smaller than their capacity is not defined yet. The jellyfish tests use random siblings. The Groth16 reference pads with a hash of a separate EMPTY domain, but under a different Poseidon instance.

  • 🤖 session is the instance id of the optimistic track, a hash of the coalition formation proposal, as a field element. The mapping is not fixed yet; the first 31 bytes as a little-endian integer, as for the output id, would do (proposed). The proof of concept takes session as a field element directly.

ObjectDefinitionKnown toPublic
random, fresh per input and per attemptthe input’s ownerno
, slot ’s amount and destination bindingthe input’s owner; the payee for its own slotno
slotthe input’s ownerno
input root2-level tree over everyoneyes
session root: 6-level tree over the agreed input roots, in the agreed input ordereveryoneyes
tageveryone, after registrationyes
leafeveryone, after registrationyes
registration root: 8-level tree over the agreed leaves, sorted by leaf hash (proposed)everyoneyes
tag root: 8-level tree over the agreed registrations’ tags; only for completion proofseveryoneyes
fresh key per proven output; not a spending keythe payeeafter proven outputs
output id, first 31 bytesthe payee until the output-proof phase; then everyoneyes, when posted
binding, one random blinding per source the payee; payer sees only no
claim commitmenteveryoneyes
claim root: 8-level tree over the agreed outputs’ claim commitmentseveryoneyes

The output id follows the concurrent PSBT requirement that each output has a unique identifier. A scriptPubKey can’t serve, because it may not be stable until after the output set is. Taking the id as the hash of a fresh key lets the payee later authorize the output’s script.

🤖 Fresh output ids. Optimistic outputs are discarded when the proven phases start, and their ids are not reused. For each proven output, the payee chooses a fresh key , distinct from its optimistic outputs and earlier attempts, so the output id is unguessable. The payee keeps the id private until the output-proof phase, after the input allocations and registrations are fixed. Until then, payers see only their bindings .

🤖 A slot’s binding is the binding that the payee gave for that source: indexes the payer’s slots, and the output’s sources.

🤖 The payee keeps each blinding private. Revealing it to payer would let that payer test its binding against the public output amounts and ids.

🤖 Each source uses an independently sampled blinding. With a shared binding, a payer could combine its known allocation amount with a candidate public output amount to guess the other source’s amount, then test that guess against the public registration leaves and tags. Independent bindings prevent this test because the payer does not know the other source’s binding.

🤖 The binding doesn’t repeat session. An output proof is verified against the registration root of its own session, and that root is built only from registrations verified in that session, so a leaf is claimable only where it was registered. See Acceptance rules.

Statements

All circuits are TurboPlonk over BN254 with the parameters above.

Input proof

Purpose: conservation at an input, and commitment to its slots.

🤖 The statement below covers the allocation of value. Initial-input proofs also commit to vbyte allocations, which auxiliary-input proofs consume; that part is not in the proof of concept. Input-proof messages identify their input by outpoint and bind the statement to the session. Both initial and auxiliary input-proof messages are authenticated by the input’s own online key, enrolled by its BIP-322 ownership proof. Auxiliary-input messages are still submitted anonymously.

  • Public: session, value (the input’s amount), input root.
  • Witness: ; for each slot, and ; the excess .
  • Constraints:
    • for every slot, and ;
    • ;
    • the input root is the tree over .
  • Cost (measured): 1,855 gates, domain , 0.31 s to prove.

The range checks stop a hidden slot of cancelling an oversized slot. Nine 51-bit slots and a 32-bit excess can’t wrap the field. The excess is this input’s share of the fee. Fee pseudo-outputs, which spend a slot like an output, are an alternative. A zero slot needs no destination; any will do. A self-transfer is a slot whose binding is the participant’s own output.

Registration proof

Purpose: turn a committed slot into an anonymous registered leaf, at most once.

  • Public: session, , tag, leaf.
  • Witness: , , , the 8-level path from to .
  • Constraints:
    • the path proves is in . The two inner levels expose the position as base-3 digits, which give . The outer six hide which input it is;
    • ;
    • , with the same and variables as the slot.
  • Cost (measured): 1,017 gates, domain , 0.16 s to prove.

No range check is needed, because is the slot’s range-checked amount.

Output proof

Purpose: conservation at an output.

  • Public: session, , amount, output id, cc.
  • Witness: for , , , and a path; (second source used); a filler value; . is the constant 1. An unused source’s path starts from the filler instead of its leaf, and is not checked against , but the prover must still supply one.
  • Constraints:
    • for each source;
    • for each used source, is in ;
    • , so every output claims at least one leaf. Without this, an output with no sources and amount 0 would verify, and outputs would be ungated;
    • 🤖 , so the second source is used whole or not at all. Without this, could be any field element;
    • if both sources are used, their leaves differ;
    • ;
    • . An unused source enters as 0, so a receipt can open only on a leaf the output actually spent.
  • Cost (measured): 1,931 gates, domain , 0.32 s to prove.

covers one payment plus the payee’s own slot. A payee paid by several payers uses one output per payment, or a larger . Larger is not measured. probably moves to domain , about 0.6 s (estimate).

Receipt (private)

Purpose: show the payer its payment was claimed, without saying which output claimed it.

🤖 A receipt is distinct from payment confirmation. It proves that the payment allocation was claimed in the proven state. Confirmation tells the payer that the committed construction satisfies the payment agreement, as the concurrent PSBT specification defines. The proven phases require both checks before signing.

  • Public: , the payer’s leaf.
  • Witness: the output’s claim commitment, its path to , the other claimed leaf, , and which side the payer’s leaf is on.
  • Constraints: the commitment is in and opens to the payer’s leaf on one side.
  • Cost (measured): 827 gates for an 8-level , domain , 0.17 s to prove. A 6-level (729 outputs) is 645 gates (counted). It is verified only by the payer.

Completion proof (optional)

Purpose: show that every non-zero slot of an input was registered. Where the session requires it, an input that doesn’t give one is identified by outpoint as incomplete or unresponsive. That doesn’t show who failed: the payer may not have handed over its registration proof, or the payee may have received it and not posted it.

No other rule needs it: an omitted registration only removes value from what can be claimed, and that value goes to the fee. It can’t inflate funds or consume another participant’s allocation. A counterparty that doesn’t complete can make its partner withhold a signature, which recovery already handles. The completion proof only adds attribution within the pair: without it, a payer that reneges can make its payee appear faulty.

🤖 The measured completion proof takes about 2.3 s on one thread, compared with 0.16–0.33 s for the other proof types.

  • Public: session, input root, .
  • Constraints: for each slot, , or is in .
  • Cost: 8,578 gates, domain (counted). 2.3 s to prove, measured at 8,569 gates without destination bindings, in the same domain.

A variant publishes an input identifier in the input proof and binds the completion proof to it, with the same . That fits (1.1 s). But it loses the zero-slot exemption: every input then registers all nine slots, with dummies.

The root-bound proof could instead prove its leaves are in , with no . That costs about 810 more gates, still in (estimate). The variant can’t, because it has no amounts or bindings.

Acceptance rules

Every validator applies the same deterministic rules to the agreed sets:

  • Verification. Each proof verifies against its circuit’s fixed verifying key and the agreed root it names. A phase’s proofs can be checked in one batch_verify, which accepts a mix of circuits.

  • Duplicates and equivocation. These are validator rules, not part of the proofs; the proofs make them possible by exposing the tag and the output id as public keys. Proofs of the same statement are duplicates, even if their bytes differ, and are counted once. Different valid statements under one key are equivocation, and only identify which output every validator removes. An agreed set has no order, so no rule may depend on which arrived first. The proof of concept keeps the first in list order instead.

  • 🤖 Inputs: keyed by outpoint. An input proof is posted by its outpoint and authenticated by the input’s online key, bound to session; two different input proofs for one outpoint are per-input equivocation, as defined in the optimistic track, and remove the input.

  • Registrations: keyed by tag. The slot fixes the leaf, so every registration of a slot has the same statement, and equivocation can’t happen.

  • 🤖 Outputs: keyed by output id. Two statements for one id can differ in the claim commitment or in which leaves they spend. Conflicting statements remove that output, and its leaves’ value goes to the fee. Because proven output ids are fresh, other participants cannot prepare their own allocation to an honest output id; see No value is created.

  • Trees: each in an order that doesn’t depend on arrival:

    • over input roots in the agreed input order;
    • over agreed leaves sorted by leaf hash (proposed; the proof of concept uses arrival order);
    • over exactly the kept outputs’ claim commitments, sorted by output id (proposed);
    • , if completion proofs are used, over the kept registrations’ tags. 🤖 Each tree is built only from statements that verified with this session’s session as a public input, and each proof is verified against its own session’s root. The bindings don’t carry session; this rule is what stops a leaf being claimed in another session. Validators must enforce this association when constructing roots and accepting dependent proofs.
  • Script authorization. After the output set is agreed, each output’s owner posts , with an x-only secp256k1 key. It is accepted if the first 31 bytes of equal the output id, and is a valid BIP 340 signature under over . Conflicting authorizations for one id are equivocation, and remove the output. This matters only for consistency, not for incentives. Removal is simpler than any other way to break the tie. The proof of concept checks the output proof, key hash and signature together, as one posted output. The spec separates them because the script may only be stable after the output set is.

  • Balance. The fee is . It is public and must meet the session’s terms.

Signing and failures

🤖 These signing rules apply after the proven phases. Every sender also obtains the payment confirmations required by the concurrent PSBT specification.

  • A payer signs only after verifying a receipt for each of its payments, and only the complete transaction with every output’s script authorized. Otherwise it risks its funds going to the fee. A receipt shows the payment was claimed in ; it doesn’t show the script or the settlement.
  • A payee signs its own inputs only if its output is in the transaction with the agreed amount and script.

If either fails, the other participants must be able to make progress without them:

  • 🤖 A refusal is attributable. Signatures are identified by outpoint, so an input that doesn’t sign is identified by that outpoint. Blame may fall on the pair, payer or payee or both, because they trust each other for liveness. They don’t trust third parties for it.
  • 🤖 Retry without the excluded outpoint. The retry is a new recovery proposal, so it has a new session and keeps the exclusions of earlier attempts. It follows the same phase order, including the optimistic phases; any subsequent proving uses fresh secrets, amounts, keys and output ids. The measured value-allocation proof work is about 1.1 s per participant on one thread: an input, two registrations, an output and a receipt (derived). This excludes vbyte admission.
  • Not in place. Continuing the same attempt without the excluded input would show which outputs drop out. Those are exactly that input’s payees, so the link would leak for whichever member of the pair was honest.

What each failure costs:

FailureWho is identified by outpointWho loses
payer refuses to sign after a valid receiptthe payer’s inputthe payee’s payment, until the retry
payee never claimsthe payer’s input (no receipt, so it won’t sign)the pair
payer never hands over its registration proofthe payer’s input, if it follows the signing rule (no receipt); the payee’s inputs, if it has any and refuses to sign; with completion proofs required, an input that can’t give one, which is the same if the payee received the proof and didn’t post itthe pair
anyone posts an invalid proofnobody needs to be: it is rejectednobody

🤖 A payee that never claims can get each payer who agreed to pay it identified by outpoint once. That stays within the trust the pair placed in each other. A missing completion proof shows that an input didn’t meet its obligations, under the session’s rules. It doesn’t show whether that was malice or failure.

Security sketch

No value is created

  1. Input: the hidden slots plus the excess equal the public value, and none can be negative.
  2. Registration: each slot registers at most once, because its tag is unique. A leaf carries the slot’s own amount and binding.
  3. One output: its used leaves are distinct, and they sum to its amount.
  4. Across outputs: a leaf names one binding, which contains one output id. Outputs are deduplicated by output id, so no leaf is claimed twice.

So . 🤖 The rest is fee. This proves non-inflation. Payment satisfaction is checked by counterparty confirmation, with an additional receipt check in the proven phases, before signing. Failures are attributed as in Signing and failures.

🤖 Non-inflation uses deduplication by output id and the destination binding. Liveness additionally relies on fresh output ids. An attacker that learns an id when it is posted cannot change its committed allocations to fund a conflicting statement under that id. This argument does not cover ids disclosed before those commitments are fixed.

🤖 The PoC also checks the output-id key and a signature over the session, id and script together with the output proof. That signature authorizes the script; it does not bind the amount, allocation sources or claim commitment. The liveness argument above relies on the ordering and secrecy of the fresh id, rather than treating that signature as authentication of the whole funding statement. Script authorization may remain separate from output proving.

Privacy

  • The payee doesn’t learn the paying input. The payer’s path is a zero-knowledge witness. Tags are pseudorandom without .

  • The payer doesn’t learn the funded output. It knows only . The output id becomes public when the output is posted, but the blinding never leaves the payee, so the payer can’t match to it. Each source has its own blinding, so the payer can’t test the other sources’ leaves either. The receipt hides which commitment it opens.

  • Registrations are unlinkable to inputs. This assumes anonymous submission, and tree orders that don’t depend on arrival. Peers submit over a sender-anonymous transport. If the transport doesn’t provide message unlinkability, each connection carries only one message. The sender checks through gossip that its message reached the peers.

  • Payments per output are hidden. Every output proof has source positions, whether the second is used is a witness, and the claim commitment hides which leaves it spent.

  • The payment count depends on the session’s terms. The number of registrations is public. If the terms fix the number of registrations per input, with zero slots registered as dummies to fill it, the count reveals nothing about payments. The numbers of inputs and outputs are inherently public.

    The fixed number should make enough payments plausible that actual payments could change the analysis significantly. A handful of plausible payments in a large transaction is a strong constraint, suggesting the sub-transaction model may apply. No proof enforces the number; an input that registers fewer only weakens it.

  • Proof blinding. jellyfish randomizes the wire, permutation and quotient polynomials. The privacy argument assumes zero knowledge for the proof system and transcript used here.

Assumptions

  • KZG and TurboPlonk on BN254 in the algebraic group model, with a ceremony that had at least one honest contributor.
  • BN254’s security is about 100 bits, not 128.
  • Poseidon is collision resistant, and pseudorandom when keyed by (tags).
  • and the claim commitment hide their contents, given their random blindings and .
  • Anonymous submission of registrations and outputs.

🤖 The non-inflation argument relies on proof soundness and the binding properties of the hashes. If either fails, the allocation proofs no longer establish funding coverage. A forged conflicting statement under an honest output id can also cause that output to be removed, disrupting completion without identifying the forger. Failure of anonymous submission instead exposes links between messages and their senders.

🤖 The setup must produce an SRS whose trapdoor is unknown to every participant, including the aggregator. An existing compatible ceremony can supply this SRS; initiating a session does not require generating a new setup.

Attempting a transaction leaks information that no proof can hide. Fresh amounts, keys and output ids on each attempt limit what recurs across attempts.

Implementation and performance

  1. Rust implementation. The proofs use the jellyfish implementation of TurboPlonk with KZG commitments.
  2. Universal setup. No per-circuit ceremony. Any BN254 powers-of-tau ceremony of degree at least 2,050 works for the input, registration, output and receipt proofs. The optional completion proof needs 16,386 (8,194 for its variant). For example Perpetual Powers of Tau or Aztec Ignition.

Measured with jellyfish on BN254, under load 3–6, medians of 3:

ProofGatesDomainProve, 1 / 10 threadsVerify, singleBatched, per proof
input1,855309 / 66 ms1.22 ms50 µs
registration1,017164 / 37 ms1.26 ms51 µs
output, with claim commitment1,931324 / 63 ms1.32 ms56 µs
receipt827165 / 36 ms1.24 ms43 µs
completion (optional)8,5782,261 / 440 ms21.22 ms42 µs

Every proof is 769 bytes, and each verifying key is 1,146 bytes.

A session with 500 inputs, 1,000 registrations and 500 outputs has 2,000 proofs, 1.79 MB including public inputs. It verifies in one batch in 90 ms on one thread, or 21 ms on ten. Each participant proves in about 1 s on one thread: one input, two registrations and one output. 🤖 500 inputs is an example below the 729-input capacity.

🤖 Not in the proof of concept

  • vbyte admission. The proof of concept treats initial and auxiliary inputs as one input type. Initial-input vbyte allocations, and their consumption by auxiliary inputs, are protocol requirements it doesn’t implement. Its measurements don’t include their cost.
  • Per-session roots. It checks single proofs and doesn’t build the trees, so it doesn’t implement the acceptance rule that builds each root from statements accepted for that session.

Compared with other approaches

🤖 jellyfish was chosen over these alternatives:

  • Groth16.3 It needs a trusted setup for each circuit, which is problematic for privacy. The setup’s second phase is specific to the circuit, and its participants contribute one after another,4 which doesn’t work well here. A universal setup reuses an existing ceremony instead.
  • Sigma protocols and STARKs. They need no trusted setup, but their verifier complexity is too high.
  • Curve Forests.5 Its verifier cost is logarithmic in the set size, but for our range of set sizes its overhead dominates over a Triptych sigma protocol,6 whose verifier cost is linear.
  • Anonymous credentials. With roughly 500 validators, credential issuance and its proof work may cost each validator too much, depending on the scheme, the threshold and the number of contributions. This needs measuring.

🤖 Payment negotiation state stays with the two counterparties. Their payment confirmations bind to the proof messages in the DAG; the negotiation transcript does not become shared validator state.

🤖 The table below also compares two ways of proving payments directly, without a registration phase:

  • Split proving. The payer proves its own allocation with a commit-carrying Groth16 proof, which the payee re-randomizes for its output proof.
  • Recursion. The payee’s output proof verifies the payer’s proof, one level deep: inner proofs on BLS12-377, the outer proof on BW6-761.

For an output funded by two payers:

ApproachSetupBytesPayee proving
this oneuniversal2,723 (two registrations and one output, with public inputs)0.32 s
split proving, Groth16per circuit1,176, with public inputsnot measured
recursion, Groth16 two-chainper circuit4846.0 s

Open questions

  • Sorting the registration tree.
  • The private messages for net settlement: payments through participants without inputs, and cycles, mapped to slots bound to final outputs.
  • Tree padding.
  • Measured cost of .
  • 🤖 Whether registrations can be posted anonymously, or in the same phase as the input proofs, under an auxiliary rate-limiting mechanism. That would merge the registration phase into the input phase.
  • Whether to keep completion proofs at all, as an optional extension.
  • Whether the concurrent PSBT specification already authenticates a late script for an output id, so script authorization can reuse it.
  • Reference Poseidon constants, and the choice of ceremony.
  • The number of registrations per input to fix in the session’s terms, and its cost: 0.16 s and 769 B per dummy registration.

  1. J. Camenisch, S. Hohenberger, M. Kohlweiss, A. Lysyanskaya and M. Meyerovich, How to Win the Clone Wars: Efficient Periodic n-Times Anonymous Authentication (2006). ↩

  2. Measured at 8,569 gates, without destination bindings. ↩

  3. J. Groth, On the Size of Pairing-based Non-interactive Arguments (2016). ↩

  4. S. Bowe, A. Gabizon and I. Miers, Scalable Multi-party Computation for zk-SNARK Parameters in the Random Beacon Model (2017). ↩

  5. M. Campanelli, M. Hall-Andersen and S. H. Kamp, Curve Forests: Transparent Zero-Knowledge Set Membership with Batching and Strong Security (2024). ↩

  6. S. Noether and B. Goodell, Triptych: Logarithmic-sized Linkable Ring Signatures with Applications (2020). ↩

Optimization framework for Bitcoin wallets

This document describes how to score the outcomes of transacting on Bitcoin, in particular privacy outcomes. This is the basis for automating various decisions delegated by the user to the wallet.

🤖 It sets out the general approach to implementing the wallet’s strategy, which is to generate decisions and evaluate them, and the requirements this places on the cost function. Unlike the protocols, which are normative, the strategy is a recommendation, and can’t be enforced.

🤖 Preliminaries

Automating the decisions delegated to a wallet is an optimization problem, and every optimization problem has a cost function.

A pure strategy is a complete plan: a sequence of actions leading from the current wallet state to one specific outcome, i.e. one path down the decision tree. The cost function, the one this document defines, evaluates pure strategies. It is a sum of terms of three kinds:

  • objective costs, such as fees
  • privacy liabilities
  • payoffs from completing goals, such as making a payment

Every term is a piecewise linear function of time, and is known to be either privacy related or not. A pure strategy is evaluated at a point in time by evaluating each of its terms at that time and taking their sum.

The strategy is implemented by generating decisions and evaluating them. Tactics generate the decision tree from the wallet state. The evaluation is mostly defined in terms of pure strategies, because these are easier to make transparent: a sum of terms, each labelled as privacy related or not, and each a piecewise linear function of time. Pruning and the decision loop then turn these evaluations into the wallet’s mixed strategy.

The wallet doesn’t simply follow the best pure strategy. If it did, an adversary able to predict the wallet’s state could also predict its choices. Instead it plays a mixed strategy, a random choice among pure strategies. The Mixed strategy chapter recommends how to compose one.

A cost function for the mixed strategy exists, but it is a more complicated mathematical object, which this document doesn’t define or study. It only describes how the mixed strategy is played.

🤖 Wallet states and actions

The input domain of the cost function is wallet states. A wallet state includes the wallet’s confirmed and unconfirmed transactions, current observations and beliefs, policy parameters, and a queue of intents.

Technically partial wallet states are permitted, since incomplete information about future transactions must still be evaluated. This is done under the assumption that the available information is a lower bound on the outcome. For example a co-spend proposal has a lower bound on the set of inputs in any transaction where it may be in effect.

Intents can be on chain payments, i.e. a TxOut to be created, or more generally any unordered PSBT fragment.

Decision tree structure

A wallet constructs a decision tree whose root is the current wallet state. Each edge is an available action, and each node is the predicted wallet state produced by the sequence of actions leading up to it from the root.

Leaves are mutually exclusive outcomes under consideration. An action may create or modify a collaborative transaction, advance a coalition formation negotiation, or fall back to a unilateral transaction. When a transaction is confirmed the corresponding intents are removed from the queue.

Actions include announcements and negotiation, not just the steps of transaction construction. For example:

  • broadcasting an ownership proof for a coin
  • updating a coin’s listen advertisement to solicit co-spend proposals
  • making a co-spend proposal naming specific coins, and choosing the payoff for each
  • making a co-spend proposal naming a single coin, with a surplus and a subset sum density requirement, leaving the search over the order book to an aggregator
  • accepting a co-spend proposal, or a coalition formation proposal
  • adding auxiliary inputs and outputs to a committed transaction, and signing it

How the tree is built is part of the strategy, and is described in the Tactics chapter.

How the wallet chooses among the pure strategies in the tree, and when it acts, is described in the Mixed strategy chapter.

Coin selection with objective costs

The coin selection problem in Bitcoin is that of deciding which of the unspent transaction outputs available to a wallet should be used when constructing a new transaction. Coin selection is constrained by the desired outcomes of constructing a transaction. The simplest example of such an outcome is when the user is intending to make an on-chain payment: a transaction which includes an output whose value is the payment amount, and whose scriptPubKey is determined by the receiver. The most basic constraint then is that the payment output is included, giving control over those funds to the receiver.

Because confirmation is needed for payment finality, the feerate of a transaction is also constrained. For a transaction to be valid, the value of the new outputs must be covered by the value of the spent outputs, and the fees paid by a transaction consist of the difference between these sums. The feerate is a transaction’s fees divided by its size. For timely confirmation the feerate must provide a strong enough incentive for miners to include the given transaction in their block templates, as compared to alternative transactions they might wish to include instead.

With respect to some given feerate, the effective value of an unspent transaction output is its nominal value, minus the cost of the blockspace consumed by the input which spends it. Similarly, the effective cost of an output accounts not just for its nominal value, but also the cost of the block space required to create it.

Sometimes it’s possible to closely approximate the effective cost of a payment output as the sum of the effective values of a subset of the spendable coins. However, typically the smallest sum of effective values that is larger than the sum of the effective costs will be significantly larger. A change output with an effective cost equal to the excess balance is then created instead of overpaying in fees.

Framed as an optimization problem, coin selection aims to minimize transaction costs while still achieving the desired outcomes (e.g. making payments). Since the decision space scales exponentially in the number of available UTXOs, a brute force search will in general be intractable, requiring an approach such as branch and bound.

Expectation and bracketing

Internalizing future costs

The immediate costs of some action may not represent its long term consequences. Internalizing expectations of the future into the cost of an action makes optimization simpler, since decisions can be evaluated one step at a time.

🤖 Abstractly, one might recursively consider all actions that may follow any particular state. An expected cost can be derived by first assigning a cost to each terminal state, then weighting it according to a probability distribution. Adding these costs to the cost of the actions which immediately precede the terminal states internalizes future expected costs, and this can be propagated all the way back to the immediately available actions.

Unfortunately, enumerating every contingency like this, even if the depth is restricted, is not only intractable, but often hard to define. Assigning probabilities can also be tricky. Due to these challenges, in practice simplified models are instead used to internalize such future costs into the cost of the immediately available actions. Although this might not account for everything that may eventually happen, that isn’t really a goal worth pursuing so long as relative comparisons between alternatives are made possible.

🤖 Bracketed evaluation under incomplete information

During decision-making, states are evaluated with incomplete information, as a bracket between a best case and a worst case, described in the Cost function structure chapter. An automated action is taken only when the cost-function evaluation predicts an improvement, accounting for the wallet’s subjective balance, objective costs and the utility of completing payments. As information about other users’ coins becomes available, the lower bound can improve. Once the transaction is fully constructed, the same cost function evaluates the complete state, including the other users’ output values. The completed evaluation determines the liabilities and the accounting for privacy-budget expenditure.

Future cost of spending (Bitcoin Core’s waste metric)

At the time an output is created, the size of the input that will eventually spend it is already known (or an expected size in the case of P2TR outputs). This size is independent of whatever else happens in that transaction. Reliably predicting a feerate, on the other hand, is not possible, as that is a market prediction problem.

While specific future feerates are inherently unpredictable, if at some point in time it’s clear that a low feerate is sufficient for timely confirmation, then it is possible to reliably predict that at any point in the future the feerate is likely to be higher. When this is the case it makes sense to spend a larger set of potentially smaller outputs, consolidating their values, because although the total blockspace required to spend a set of outputs is fixed regardless of when each output is spent, the cost can be minimized if more of this blockspace is consumed at lower feerates.

Optimizing these costs is the underlying motivation for the waste metric used in Bitcoin Core’s coin selection. This term in the cost function which governs coin selection internalizes an expected cost of spending a coin to the evaluation of the cost of its output. When the target feerate is lower than this predicted future feerate, this makes the evaluation of spending an input right now lower than this predicted future cost.

A simplified version of the waste metric (omitting some terms) is to consider some expected future feerate as effectively the zero point, by subtracting it from the target feerate at the time of coin selection. When the target feerate is lower, this will be negative, which makes larger transactions seem cheaper than smaller ones. The rationale for rewarding larger transactions is that the total blockspace that will eventually be consumed spending all of the coins available in a wallet is essentially fixed, but what matters is simply when that blockspace is consumed, and at what feerate. During times of low demand for blockspace (and therefore low target feerates), coin selection will therefore tend to consolidate a fragmented wallet. When demand rises again, if coin selection must be done at the higher target feerate, since there would be fewer, higher value coins available on average, the expected transaction size at these higher target feerates will be lower, which in turn will result in lower overall spending on fees. The waste metric is only one of the terms of the cost function, and is included in the evaluation of every automated transaction. Spending coins together may also affect other terms, such as privacy liabilities, so whether such consolidation happens depends on how the waste metric weighs against these and against the urgency of any payments.

Cost of CPFP transactions

Child-pays-for-parent (CPFP) transactions spend one or more outputs of transactions that have not yet been confirmed, and at a higher feerate than the unconfirmed transactions’ average feerate. This gives miners an incentive to include the parent(s), as the more lucrative child transaction can only be confirmed after the parent(s).

From the point of view of a wallet, spending unconfirmed outputs is therefore more costly in expectation, because to do so at a higher feerate requires paying for the parent transaction(s)’ blockspace as well.

Arguably this is already accounted for by the waste metric future feerate parameter, but a qualitative distinction is being made here because there is more uncertainty in predicting the payments a wallet is expected to make at any point in the indefinite future, as opposed to only what is due before some inflight transaction is expected to confirm.

Utility of payments

For the purposes of this document a payment will mean a net transfer of funds between two parties. Transactions are a way of realizing payments, but a single transaction can perform multiple payments or even net settlement for multiparty transactions.

An intent is a concrete representation of the goal of creating some output (or input, in which case the goal is the destruction of some unspent output) before some deadline. The deadline can refer to the transmission of a signed transaction to the recipient out of band, broadcasting the transaction, or its confirmation in a block. For simplicity, and without loss of generality, output creation intents will be assumed to correspond to payments but that isn’t necessarily the case (for example funding a lightning channel). We will assume intents are made known to the wallet some time in advance of the deadline.

🤖 The change in the balance of a wallet resulting from a transaction, negated, is its objective cost: positive when the balance decreases, and negative when it increases, for example when receiving a payment. In contrast, the utility obtained from a transaction confirming may include subjective terms as well. Subjective costs inherently depend on beliefs or preferences, and are the basis for any surplus created from transactions as any redistribution of on chain funds is necessarily zero sum.

Reliably confirming transactions at the lowest possible feerate before the deadline of any payments it realizes is not feasible, because predicting future feerates is a market prediction problem. Attempting to confirm as close to the deadline as possible can incur additional costs due to the variability of fees, or risk missing the deadline. If payment deadlines are missed, the utility obtained from making the payments may be diminished. Some risk of missing the deadline or overpaying fees is always inherent.

This perspective suggests that the same action performed at different times is in fact not the same action, but two different ones, which will have different costs. However, to keep things simple we will not consider actions-at-a-point-in-time separately, but rather each action’s cost evaluation will output not just a single numerical value, but a function of time, and different actions can be compared across all of time.

Payment batching

Confirming transactions at the earliest possible time (well in advance of the deadline) is sub-optimal as it precludes any possibilities of batching payments. However, before confirmation it is possible to replace transactions by double spending at least one of their spent outputs in a transaction which is more attractive to miners (which also diminishes the importance of introducing any CPFP liability). This is known as replace-by-fee (RBF), and multiple policies for allowing this, some defunct, have existed over the years.

A reasonable strategy that utilizes RBF for batching is to simply broadcast a transaction which underpays fees as soon as a payment becomes known, and then replace the transaction with progressively higher feerate transactions, growing the batch of payments with each such replacement. This conserves blockspace: the blockspace increase of another payment is primarily just the cost of an additional output. If some subsequent transaction is much more urgent than inflight ones, then it of course can also be realized in a separate, higher feerate transaction, in order to avoid paying for the entire batch at the higher feerate.

This batching strategy can reduce costs, minimizing the opportunity costs of the eager but naive strategy (successfully confirming before the deadline precludes RBF based batching) or the risk of missing deadlines in the lazier one. Unfortunately this RBF-eager strategy also leaks a lot more information about the payments made and the wallet making them than simply posting the full batch as late as possible (for example as discussed in this paper). A lazy strategy will make the same batching possible without such leaks, at the cost of forgoing any low fee opportunities that may be available well in advance of the earliest deadline.

Privacy Liabilities

Whether or not one should broadcast eagerly and then bump fees, or wait in order to limit how much information is revealed by fee bumping depends on whether the harms from the loss of privacy outweigh the expected savings from broadcasting earlier.

Unilaterally spending more than one output reveals to the adversary, based on the common input ownership or multi-input heuristic, that they are likely to be owned by the same entity. More broadly, all transactions necessarily reveal which coins they spend, the total amount involved, the values of the inputs and outputs, script types used, and a number of wallet fingerprints such as the value of nLockTime or details of signature encoding. This information is useful for wallet clustering (1, 2, 3), a cornerstone of Bitcoin chain analysis and deanonymization.

The adversary is anyone who might be attempting to deanonymize the user. This can be a third party or a counterparty. In some cases information linking several coins may already be known to the adversary. For example, suppose a customer makes one payment to a merchant in an on-chain transaction, creating a change output, and then eventually spends that change output to make another payment to the same merchant. If these payments are already linkable, for example because they are both associated with the same email address, then no further information is revealed to the merchant by spending a coin that it already knows belongs to that customer.

On the other hand it may be the case that two payments are made by the same customer to the same merchant, but no information with which the merchant could link these payments is available. In such cases the appropriate behavior might be to deliberately avoid any coins linked to the previous payment when making the later one.

The worst case for this kind of leakage, in terms of how much information is revealed in a single transaction, is when the entire wallet’s balance is spent in a single transaction. This is problematic not just because it links all coins together but also because it reveals the wallet’s total balance, potentially aiding in additional analysis (such as correlating this amount to past transactions that aren’t unambiguously linked to it).

Let’s momentarily ignore both the severity of the harm of such privacy leaks (assume it’s just some fixed penalty), as well as the risk, i.e. the probability that liquidating the entire wallet is necessary (for example when under duress, in response to a security incident, or when needing to make an urgent payment for an amount close to the available balance). What then determines the cost is how much information is leaked. Considering this potential contingency after every wallet state, and then internalizing the cost into the cost of the transaction which results in that state encodes the implicit goal of privacy enhancing transactions, which is to leave the wallet in a state where the harm of any such liquidation is reduced, because the information leaks are minimized.

Censorship risk

On-chain privacy techniques in Bitcoin come in two flavors: overt or covert. Overt techniques add ambiguity in a way that is apparent, and therefore can be identified as privacy enhanced transactions (e.g. CoinJoin). Contrast this with covert techniques (e.g. CoinSwap), which aren’t easily identifiable.

Both overt and covert techniques carry censorship risk. For overt techniques this is inherent, as the use of the technique is self-evident, and exchanges that may regard this as a compliance risk (which incidentally is more often the case for fraudulent exchanges) are more likely to reject or even confiscate deposits that are linkable to such techniques. For covert techniques, although the technique itself doesn’t flag a deposit, it may result in counterfactual linking of the deposit funds to coins that are deemed tainted.

Parameterizing the cost function according to user preferences

The design space of a cost function for privacy has three main axes: improving privacy, minimizing delays, and economizing on cost, all of which trade off against each other. When considering each transaction independently, although there are 3 dimensions for optimization, there are only two degrees of freedom. Meaningfully improving privacy on Bitcoin requires interaction with others, which can inherently introduce delays, or it can require improving the ambiguity of the transaction structure with the goal of frustrating analysis, and this often requires utilizing more blockspace. The sooner this is needed, the higher the fees incurred.

Privacy sensitivity

To quantify privacy, wallet software must include some kind of privacy metric. Metrics make it possible to measure progress, and to define stopping conditions for any privacy optimizations (which aren’t costless). For example, an estimate of an anonymity set size of a coin might be one such metric. Developer provided default thresholds can allow non-expert users to choose a threshold appropriate for their threat model, on a per intent basis (distinguishing between sensitive payments and those that only require opportunistic privacy).

The metrics discussed here will attempt to ascertain how well the payments of the user blend in with those of others. Due to the limitations of Bitcoin’s consensus layer (cleartext amounts, overt spend graph), multiparty transactions are necessary in order to meaningfully resist clustering. Multiparty transactions are those which involve the actions of more than one user. Although there are other aspects to Bitcoin privacy, this framework is primarily concerned with on chain notions, which can be defined in terms of wallet clustering.

Sybil resistance

Complicating matters, since Bitcoin is permissionless it’s not directly observable whether a transaction involves parties with non-trivial () or not. Since only coins have identity, and there is no notion of accounts or users in the protocol, all an honest user knows definitively is which coins are under its own control vs. those that aren’t. It’s not possible, in general, to determine whether or not the coins that an honest user does not control are all controlled by a single entity or multiple separate ones.

A sybil attack on a network or distributed system involves a single entity controlling many apparent identities, the closest analog of which are coins. As a component of a deanonymization attack, a sybil attack can be used to isolate the honest parties. If all actions other than those of the victim are visible to the adversary, a scenario known as an deanonymization attack, then the adversary is able to observe the victim’s actions with full transparency. Unfortunately the only recourse for this kind of attack is to impose or at least account for the cost of such an attack.

When any privacy metrics are interpreted, the implied cost to the adversary of doing an deanonymization attack, i.e. the cost of controlling the inputs to the metrics (note: not inputs as in spent coins, but in the sense of all information that is fed into an analysis being under adversarial control), should be factored into the weight of the interpretation of the metric.

We might turn cluster analysis on its head, and as the defender attempt to detect such attacks heuristically. However, evading this only adds some overhead for the adversary, and this overhead may be very low in the case of covert techniques.

Ideally whatever the cost is, it should exceed the value to the adversary obtained by deanonymization, deterring such attacks through incentives. However, in reality the economics for targeted vs. dragnet surveillance will vary, and costs, even liquidity costs, may be far from equilibrium, so it is very hard to say what level of cost will suffice. The value of surveillance for, say, advertising may be more or less limited by the victim’s disposable income, whereas for targets like political dissidents, significant resources might be allocated by the attacker. Ultimately this is very subjective and depends on the threat model.

What is possible to say is that this cost can be quantified concretely by accounting for the fees incurred by others in the construction of transactions which seem attractive and are used to support the analysis of some metric. With a discount rate, the age of a spent coin can be used to estimate a liquidity cost for the adversary, as in fidelity bonds.

Payment urgency

As described in abstract terms above, a per intent deadline or confirmation target similar to the standard user experience for determining feerates can be used to control the time sensitivity of specific actions.

🤖 More generally, every term of the cost function may depend on time. How this is modeled is described in the Cost function structure chapter.

The privacy sensitivity of a transaction determines whether the preferred behavior is to execute a payment even if privacy is sacrificed as the deadline approaches, or whether it’s better to miss the deadline or even forgo the transaction entirely if the payment cannot be made privately.

🤖 This is determined by the shape of the intent’s utility curve. If it plateaus or turns downwards before outweighing the privacy liabilities, the wallet may miss the deadline or forgo the payment. A curve that keeps rising can model a hard deadline by eventually outweighing those liabilities.

🤖 Global privacy budget

Finally, a global (i.e. per wallet, not per intent or transaction) budget is used to normalize all metrics so that the costs of actions with different privacy outcomes are directly comparable. The budget has two parts: the budget rate , a percentage chosen by the user, and the remaining budget , an amount in satoshis. Only funds received at external addresses add to the remaining budget, which grows by times their value, and privacy-motivated expenses are deducted from it.

This global budget limits overall spending for the purposes of privacy. The user consents to the wallet’s behavior for discharging privacy liabilities and is willing to spend up to this budget to obtain it. This implies that the expected subjective harm of leaving those liabilities undischarged is at least as great as the subjective cost of spending the budget, accounting for downsides such as censorship risk or additional resources consumed. Accordingly, all privacy liabilities collectively reduce a new privacy-problematic coin’s subjective value by the budget fraction of its nominal value. Each term evaluates a defined problem; evidence that the problem has been removed discharges the corresponding liability to 0. These are subjective valuations under the specified criteria, rather than guarantees of privacy.

🤖 How the budget turns privacy metrics into amounts in satoshis, so that all terms can be summed, is described in the Cost function structure chapter.

Use in multiparty protocols

In the context of a multiparty transaction construction, a fixed overhead of 10.5-12.5 vB per transaction incurs a cost that can be shared with others. Since this is substantially smaller than a typical input, the savings are arguably negligible. If a cross input signature aggregation soft fork is enabled then instead of a fixed overhead, a per input overhead can additionally be shared among participants, providing a much stronger incentive than the fast diminishing fixed overhead’s savings. Such savings are limited, ultimately by consensus block size limits, and practically by policy, which limits transactions to 100KvB (though this limit can be overcome by use of multisig and pre-signed transaction trees).

Subjective benefits, in particular those related to privacy metrics, can be more strongly positive sum. Since terms derived from privacy metrics are often concerned with data controlled by the other parties, this can be strongly positive sum as the actions of each user individually may benefit every other user, not just themselves, a quadratic number of opportunities to create a surplus.

Unless parties wish to censor each other, they should at the very least be indifferent to the actions of the other users. This is important for liveness, since secure transactions generally require unanimous consent which presents an inherent challenge for liveness. Therefore it makes sense to have prior agreement to avoid any actions which may result in negative utility.

For instance, suppose Alice stands to benefit from funding a lightning channel. In order to do this she needs to add the appropriate output, no different than a regular output, but on its own this is insufficient to be as valuable as a unilaterally controlled output: lightning channels require backout transactions signed by the other party to the channel, and secure presigned transactions require stable transaction IDs (no malleability). For this reason if some other party to the transaction chooses to add a non-SegWit input, this suddenly devalues Alice’s proposed output, and she has a rational reason to avoid signing the resulting transaction.

For this reason we require that any such requirements are specified upfront, and that all parties agree to them before accepting the coalition formation proposal. This must cover technical restrictions, such as the nLockTime required by inputs encumbered with OP_CLTV, since height-based and time-based locktimes are mutually exclusive, but also constraints on things like the feerate, the script types of inputs and outputs (and/or spend types for P2TR outputs), and the values of inputs, whether nominal values, for example to require some multiplicity of standard denominations, or effective values, which determine subset sum densities. This agreement must also distribute the net allocation of virtual bytes or weight units in the transaction to the parties involved, ensuring that the total size does not overflow.

With such a setup, it is reasonable to define honest parties as being indifferent to others’ arbitrary actions. For this to be incentive compatible we must also demand that the cost function which governs the decisions made during the protocol execution is indeed monotonically decreasing in new information. Since the input domain of the cost function includes partial wallet states, lower bounds on the information contained within the transactions, such as a subset of the inputs or the outputs (unordered), can be evaluated as well. Monotonicity ensures that the subjective costs can only decrease as additional transaction data is revealed from the other parties, allowing decisions to be made with access to partial information.

Note that this does allow the evaluation to change. For example, if one party’s choice of inputs is already committed, and they then learn of the inputs of the other parties, this may change their evaluation of which set of outputs to add in the next stage of the protocol. Monotonicity ensures that this evaluation can only improve in the critical section of the protocol.

🤖 This is a substantive restriction. Many sensible cost functions don’t satisfy it, for example one that is averse to a certain kind of counterparty, and such cost functions aren’t compatible with these protocols. It is required because transactions are signed with SIGHASH_ALL: if any party defects, all other parties need to renegotiate and retry transaction construction, which is costly, and defections can cascade. Monotonicity is therefore required for liveness guarantees to be incentive compatible. Byzantine parties may not respect it at all.

🤖 Accepting a coalition formation proposal means agreeing to all compatible actions by all parties, effectively declaring that the wallet’s cost function is monotone with respect to anything outside of the restrictions agreed to upfront. The protocols also exploit this to make the transaction construction state a join semilattice (see concurrent PSBT construction). Both the state and the game theory are needed for transaction construction to succeed: safety is inherent in SIGHASH_ALL, but liveness is fragile to crash and byzantine faults.

🤖 Commitment

Co-spend proposals may be made or accepted in anticipation of a good outcome, but accepting a coalition formation proposal is binding: defecting has reputational costs, since other peers may discount the UTXOs of a party that fails to sign. Accepting a coalition formation proposal therefore commits the wallet to the sub-tree it belongs to, and requires that this sub-tree has at least acceptable leaves (see Preliminaries), i.e. at least contingencies to select from for that transaction. These must remain acceptable for long enough that a run of the protocol can be expected to complete. If they are only briefly acceptable, then as that window closes, a payment whose deadline is about to be missed may have to be made unilaterally instead, which may in turn leave the remaining intents without any urgency, so that it’s better to wait.

Full RBF means that inputs can be double spent at will, so the inputs named in an accepted coalition formation proposal are bound to its transaction construction session, but not exclusively: the commitment is only to see the session through.

The committed sub-tree typically has a fixed set of output intents, but some may be dropped, for example if a payment becomes urgent and the feerate of the CoinJoin is too low. Even if some outputs or auxiliary inputs are omitted, there should be at least options for decomposing the committed outputs, with different denominations under consideration. Change decomposition is the observable that an adversary able to predict the wallet’s state could otherwise predict, if the cost function had no noise and simply optimized. This amounts to a recursive invariant of the committed sub-tree: at least options for every retained action, not just at its root.

🤖 Pure Strategy Evaluation

How the cost of a pure strategy is evaluated, in three parts. The Cost function structure chapter describes the structure shared by the family of cost functions: time dependence, the linear combination of terms, and bracketing. The Privacy liability terms chapter summarizes the terms, each of which is specified in its own chapter. The Privacy metrics chapter describes the measures the terms take as input.

🤖 Cost function structure

The evaluation of pure strategies is a family of cost functions, sharing the structure set out in the Optimization framework chapter: a linear combination of terms, each labelled as privacy related or not, and each a piecewise linear function of time. This chapter describes that structure: how terms depend on time, how they are combined into a single amount in satoshis, and how incomplete information is handled by bracketing. The chapters that follow define the concrete terms.

Time dependence

Every term of the cost function and every intent in the queue may depend on time, and how it does may depend on what is being evaluated. This time dependence is modeled as piecewise linear offsets to values computed independently of time, so the cost function returns a family of piecewise linear functions of time, one per term. Evaluating them at a given time is just a matter of indexing them and taking a sum, but treating them explicitly as piecewise linear functions makes it possible to solve for intercepts.

Linear combination

The global privacy budget, with its budget rate and remaining budget , normalizes the privacy terms, so that all terms can be summed into a single amount in satoshis.

Each coin has a privacy liability . Concrete privacy terms each start from their own notions, for example quantifying the entropy of a coin’s anonymity set and how close it is to some threshold, potentially non-linearly, and are normalized into a single ensemble liability. All privacy liabilities collectively give a new privacy-problematic coin the baseline ; each term does not impose a separate baseline reduction. Coins received at external addresses start at this baseline, since the wallet has no prior knowledge about them. Change outputs of unilateral payments and privacy-problematic outputs of manual consolidations also start at the baseline. Evidence that the problems specified by the terms’ definitions have been removed discharges the corresponding liabilities, reaching 0 when all have been discharged. This expresses the model’s assessment of those problems, rather than a general privacy guarantee. is stored per coin, but it is derived information.

A coin’s subjective value is its nominal value reduced by . At the baseline, the collective reduction in subjective value is therefore the budget fraction of the coin’s nominal value. This turns abstract thresholds on privacy metrics into a penalty in satoshis, allowing subjective and objective costs to be summed and the wallet states predicted to result from different actions to be compared. Since the reduction in subjective value is computed per coin, this applies regardless of how many inputs and outputs a transaction has.

A transaction spending coins with a total reduction in subjective value of and creating coins with a total reduction of at an objective cost of changes the wallet’s total subjective value by

so on privacy grounds alone, an action is only worth taking if the decrease in liability costs dominates its objective cost. Privacy-motivated costs must also fit within the remaining budget. Other terms, such as the waste metric or the utility of completing a payment, also drive the decision. However, the utility of a payment is not part of the subjective value of the resulting state: a payment’s utility rising over time doesn’t mean that waiting longer to make it would leave the wallet with a higher subjective balance.

For example, suppose Alice sets her budget rate to 1% and receives a coin of 100,100 sats, adding 1,001 sats to her remaining budget. The coin starts at the baseline, so its subjective value is 99,099 sats. The wallet considers CoinJoin transactions costing 100 sats in fees, each replacing it with a coin of 100,000 sats:

nominalreduction in subjective valuesubjective valuechange
before100,10011,00199,099
large improvement100,0000.550099,500+401
small improvement100,0000.880099,200+101
not worth it100,0000.9595099,050−49

Either of the first two outcomes is worth taking, and either leaves 901 sats in the remaining budget. The last reduces the liability cost by only 51 sats while costing 100, so the wallet would not make it.

The same accounting applies when coins are split or consolidated. Splitting the same coin into two outputs whose liabilities improve by different amounts:

nominalreduction in subjective valuesubjective value
input100,10011,00199,099
output A60,0000.530059,700
output B40,0000.936039,640
outputs total100,00066099,340

The total reduction in subjective value falls by 341, which dominates the fee, for a net change of +241. Consolidating two coins of 60,000 and 40,100 sats, both at the baseline (reductions in subjective value of 600 and 401) into a single CoinJoin output of 100,000 sats with gives exactly the same result as the single coin, +401, since only the totals on each side matter.

When evaluating a candidate action, the cost function may assign to the resulting coins. For example, if the privacy metrics assess the output of consolidating the same two coins without a CoinJoin, at the same fee, at , its reduction in subjective value is 1,200 and its subjective value 98,800, a change of −299 before any other terms. Such an increase counts against the candidate in the full cost-function evaluation. An automated action is taken only when the cost-function evaluation predicts an improvement. This evaluation accounts for changes in the wallet’s subjective balance, objective costs, the waste metric, and the utility of completing a payment.

During decision-making, the cost function evaluates partial states with incomplete information. Once the transaction is fully constructed, the same function evaluates the complete state, including the other users’ output values. This determines the liabilities and the accounting for privacy-budget expenditure. An explicit manual override resets the liability accounting for the resulting privacy-problematic coins to the baseline. This writes off the loss as an external adjustment authorized by the user, reflecting a valuation the cost function fails to capture.

In general, a transaction which is worth taking on privacy grounds alone, spending coins of nominal value with a total reduction in subjective value of at a cost of , results in coins whose subjective value is greater than and at most (when no liability remains).

Bracketing

We model privacy liabilities as terms that only reduce the evaluation of a particular state, and can only be reduced as more information is revealed. This means that for every state we can derive a best case and worst case cost. The worst case is based on the information already available: it assumes that no other party contributes anything of value to the wallet, apart from the adjustments of any co-spend proposals in effect, which are guaranteed if the leaf materializes. The best case assumes they act optimally for the wallet, discharging all modeled privacy liabilities, and is obtained by simply omitting any privacy related penalties from the sum. Its use is pruning: a leaf whose best case is still unacceptable can be discarded, as in branch and bound.

The most likely outcome lies in between, with other parties behaving the way they typically behave. An expected value for each leaf could in principle be estimated empirically, by comparing how a coalition was evaluated when the wallet committed to it with the actual wallet state, and the reduction in liabilities it generated, once it was finalized in a block. However, peers that consistently behave well could push the wallet towards optimism, and then exploit it in a coalition where they don’t. How much risk to accept is up to the user, but this document only describes the pessimistic version, in which a leaf’s expected value is its worst case. An expected value can always be introduced later as another term.

During the critical section of transaction construction, i.e. after the inputs are revealed and before signatures are posted, knowledge of the other users’ inputs may improve the worst case bracket. Preparing the decision tree ahead of time and computing these brackets makes it possible to respond to this new information efficiently, finalizing the decision of which outputs to add to the transaction in order to obtain better outcomes.

🤖 Privacy liability terms

Privacy liabilities represent subjective losses of utility associated with outcomes that do not meet the user’s privacy objectives. Each term evaluates a specified measure or proxy; evidence that the defined problem has been removed discharges the corresponding liability. The cost function combines these liabilities with objective costs and the utility of completing payments to guide the wallet’s automated decisions.

The liabilities collectively reduce a new privacy-problematic coin’s subjective value by the budget fraction of its nominal value. The Optimization framework explains this valuation, and Cost function structure defines the accounting. The measures and their thresholds express objectives chosen for the user’s threat model. Meeting them does not establish that the resulting outcome satisfies that threat model in every respect. This chapter describes the purpose and interactions of the terms; their definitions and justifications appear in the linked chapters. The measures computed from public data that the terms take as input are described in the Privacy metrics chapter.

Randomized selection

An adversary who controls many of the coins a user co-spends with learns the user’s coins by elimination. Randomizing which coins are co-spent makes that costly.

  • Per input and pairwise preferences. They randomize which coins are co-spent, with block hashes as a public randomness beacon. They only break ties, so they don’t compete with the other terms.
  • Cardinality. Everyone uses the same randomness, so the bias it leaves in a transaction’s inputs can be observed afterwards, and bounds the size of the order book the inputs were selected from.

Randomization also promotes a robustly connected transaction graph, which the counterfactual paths term measures. See the Randomized selection chapter for the terms, and the Order book size estimation chapter for the lower bound on the number of candidates.

🤖 Sybil resistance

The Sybil resistance term evaluates the cost of an adversary supplying the coins in a coin’s history and the candidates from which they were selected. Observed resource requirements and estimates derived from selection bias are assessed against the user’s threat model. The liability is zero when the attack cost is judged prohibitive under that model; otherwise, it represents a subjective loss scaled by the user’s privacy budget. See the Sybil resistance chapter.

Subset sum ambiguity

Amounts are the most direct way to link a transaction’s inputs to its outputs, and the inputs to each other. This term measures how well the other users’ coins explain the user’s amounts.

  • The more combinations of the user’s outputs the subset sums of the other users’ inputs cover, the more readings of the transaction remain, and the lower the liability.
  • It measures the same for the user’s own inputs.
  • Once the transaction has been fully built, both are also checked against the subset sums of the other users’ outputs.

See the Subset sum ambiguity chapter. The Subset sum density chapter covers the density it relies on, and how co-spend proposals and the aggregator raise it.

Counterfactual paths

Intersection attacks compare the histories of coins across transactions, and what those histories have in common reveals the link. This term counts the disjoint routes a coin’s amount could have taken from its origins.

  • Its main use is a label for each of the wallet’s own coins, indicating how closely it meets the objective for counterfactual routes.
  • The consolidation penalty uses these labels, together with subset-sum density, to evaluate spending coins together.

See the Counterfactual paths chapter.

Consolidation

The consolidation penalty accounts for the additional exposure to intersection attacks introduced by spending multiple wallet-owned inputs together. Its liability is deliberately unbounded: consolidation may leave the wallet worse off than its baseline, and the corresponding subjective loss may exceed the remaining privacy budget. An automated action is taken only when the cost-function evaluation predicts an improvement. Fees, batching, and reduced fragmentation may make more aggressive consolidation attractive in the best case, while the available evidence must support the decision.

The penalty is attenuated jointly by subset-sum density and counterfactual routes, with the contribution of each depending on the other. Dense subset sums alone are insufficient, because comparing the ancestry of pairs of inputs narrows down an intersection efficiently. The route analysis considers each input against the combined set of coins through which the inputs’ funds first entered the wallet. These pairwise flow measurements would contribute to a graded measure of absorption, whose aggregation and use in the liability remain to be specified. The consolidation chapter defines these quantities and their thresholds. The same penalty contributes to the evaluation of a wallet state by considering a hypothetical transaction spending all of its coins together, so that the wallet can arrange its state to minimize privacy damage if an emergency requires the user to spend those funds at short notice.

See the Consolidation penalty chapter.

Siblings

Spending outputs of the same transaction together is wasteful, and a strong sign of common ownership. Amounts can explain the values, but not two users spending outputs of one transaction together, so neither subset sums nor counterfactual routes relieve it. It’s penalized heavily.

See the Sibling output penalty chapter.

UTXO pool diversity

A wallet also values the diversity of its own UTXO pool:

  1. some radix denominations;
  2. some coins with high Hamming weight;
  3. a good size distribution, possibly adapted to the wallet’s payment distribution.

How to represent this mathematically is an open question.

Other ad hoc terms

Other ad hoc terms, such as fingerprint avoidance, are yet to be specified.

In the decision tree

Each liability either only falls as other users’ coins are learned, or is fixed once the inputs are chosen or a coin confirms. That’s what lets bottom-up construction bracket every leaf between a best case and a worst case, cache what’s fixed per coin, and re-evaluate only when something changes. Once the transaction is fully constructed, the same cost function evaluates the complete state and determines the liabilities and privacy-budget accounting. Each term’s chapter says how it behaves in the decision tree.

Randomized selection

Two terms of the cost function: weak preferences that randomize the choice of which UTXOs to co-spend with, using the blockchain as a randomness beacon. The Sybil resistance term values coins by how well that randomization can be observed in their history.

Together they:

  • make Sybil attacks more costly;
  • promote a robustly connected transaction graph, with similarities to interconnection networks;
  • establish a Schelling point among takers with regards to which makers to interact with;
  • reduce temporal fingerprinting of makers’ UTXOs’ availability;
  • provide useful information to light clients with limited access to the blockchain.

They compose with arbitrary other terms. The setting is non-cooperative, so they are a component of a strategy, not a mechanism. If widely adopted by those paying for CoinJoin blockspace, privacy related payoffs are more strongly positive sum.

Makers announce UTXOs in an order book, and takers propose to spend them in CoinJoin transactions, as in coalition formation. The roles are used loosely: a single participant may perform both.

Inputs

  • : a block hash, e.g. 144 blocks from the best known chain tip.
  • : the outpoints being considered for spending in a possible transaction, with .
  • for each , where is a tagged hash. Hash outputs are interpreted as rational numbers in .
  • : monotone scaling functions, e.g. log or sqrt, possibly with a bias.

Per input term

  • How “lucky” a maker’s coin is at a point in time, with many leading 1’s in the hash output being considered lucky. This is a total ordering over inputs.
  • A weak preference: more than 0 but less than 1 sat, so it only breaks ties.
  • It lets takers converge on the same makers’ coins, especially when the number of active takers is small enough that a grand coalition can construct a single transaction. All else being equal, takers concentrate on the same subset of makers, reducing their shared costs.

Pairwise term

  • An affinity between inputs, using the XOR metric. Valuing it promotes randomized assortativity between inputs.
  • A weak preference, like the per input term. It scales quadratically in the number of inputs, which must account for.
  • Tipping point. Due to the CoinJoin liveness model, success probability is roughly exponential in the number of inputs. This limits how far the total order of the per input term can be optimized. Where these interactivity costs dominate, this term dominates over the first, avoiding more rivalrous competition for lucky coins to all be spent in the same transaction.
  • Partitions. When the candidate UTXO set is larger than the feasible transaction size, this term promotes partitioning of the candidate UTXO set, with each part being a reasonable estimator for its size.
  • Why XOR. For uniform , is also uniform. Preferring small values also biases the themselves: a pair whose XOR has leading zero bits shares its most significant bits, so both lie in a random subinterval of size . This simplifies the density estimation. The Hamming distance or the arithmetic difference would change the distribution, and the scaling functions can simulate such effects.

🤖 Order book size estimation

The Order book size estimation chapter gives a lower bound on the number of candidate coins the inputs were selected from, using the joint sums of the input hashes, with for every selection strategy. It also gives the proofs, the scan over block hashes, and measurements.

🤖 In the decision tree

  • Per input and pairwise terms change during coalition formation, as candidates appear.

After confirmation

This is the analysis that contributes privacy gains, and that uses the budget.

  • All inputs are known, but isn’t. It can be guessed from the confirmation time, or the nLockTime.
  • 🤖 is the maximum over the candidate block hashes mined after the inputs confirmed, each at for candidates. See Finding the block hash.
  • 🤖 The Sybil resistance term of the transaction’s outputs is then fixed.

🤖 Open questions

  • What should be?
  • Can light clients estimate for transactions they only sample?

🤖 Sybil resistance

The Sybil resistance liability depends on the cost of an adversary supplying the coins in the history of the coin under consideration, and the candidates from which they were selected. The assessment assumes that all candidate UTXOs in the relevant order books, and the transactions that created them, were controlled by one adversary. Observed resource requirements and estimates of unobserved costs are evaluated against the user’s threat model.

Provenance term

For a coin under consideration, a fidelity bond like analysis of the transaction that created it, its funding transaction:

  1. Order book size. Estimate the size of the order book at the time of the funding transaction, from its input set. This is the lower bound on the number of candidate UTXOs from the Order book size estimation chapter.
  2. Cost. Account for the liquidity, holding times and fees visible in the observed graph. Use and the sampled paths to estimate additional costs, subject to assumptions about the unobserved candidates. A discount rate expresses the time value of capital held over those intervals. This opportunity cost can be combined with fees.
  3. Ancestors. Repeat for earlier transactions, subject to data availability and computational limits.

Selection bias is a property of past selection events. Those events confer Sybil resistance relevant to the assessment of later coins; the bias itself is not inherited.

  • Why it’s a cost. For a single adversary to construct a transaction exhibiting such a bias, it must control the entire set of candidate UTXOs, not just the coins that end up being selected. Then takers would have to select the outputs of this transaction.
  • Bounds and estimates. is a lower confidence bound on candidate count. Converting it into an estimate of unobserved costs requires assumptions about candidate values and holding times. This estimate is distinct from resource bounds established directly by the observed graph.
  • Only with the preferences. The term can only be optimized in the presence of a market preference like the per input and pairwise terms, or no bias would be detectable.
  • Costless for honest users. Assuming takers and makers weakly prefer the bias, it’s costless, at least on average. With market demand for it, makers can be profitable. This promotes a wider CoinJoin graph, with less temporal assortativity.
  • Waiting. The longer a UTXO is unspent, the more chances it has of being lucky.
  • Intersection attacks. Randomization promotes a high number of paths between coins, even for bounded degree graphs, as in superconcentrator graphs.1 It doesn’t guarantee them: it draws from the non-random set of available candidate UTXOs at a point in time. The estimate can also be used for degree sequence estimation in the Karrer–Newman model of the Counterfactual paths chapter.

See also Belcher’s analysis of fidelity bonds.2

🤖 Observed resource requirements

The observed transaction graph provides lower bounds on the resources required under the hypothesis that they were controlled by one adversary:

  • Liquidity. Coins known to have been unspent concurrently require at least their combined value in liquidity. This bound depends on their total value, regardless of how that value is divided among coins.
  • Capital held over time. While coins remain unspent, their value cannot also be spent in concurrent CoinJoins. Spending them ends their holding intervals. Maintaining this capital also incurs an opportunity cost due to the time value of money, which is the principal connection to the fidelity bond analysis. Coin values multiplied by their holding durations give capital-time quantities, expressed in coindays; a discount rate is used to evaluate the associated opportunity cost.
  • Fees. The observed transactions record the fees paid to create and spend those coins. Treating these as costs to the adversary assumes that it controls only a limited share of mining hash rate.

A fetched subgraph can already establish these bounds. It is not necessary to reconstruct the entire ancestry.

🤖 Estimation from sampled paths

The randomized subgraph is the portion of the transaction graph corresponding to biased input selections. In the bipartite representation with transaction and coin vertices, prune the coin vertices that do not appear to have been randomly selected and take the induced subgraph on the remaining vertices. The randomization is verifiable because the selection uses a cryptographic public randomness beacon.

A path is found by traversing backwards from a UTXO in the order book until reaching CoinJoins already known to the wallet, such as descendants of CoinJoins it participated in. This establishes a flow route. The traversal is repeated several times, bounded to a particular block range.

The observed paths are tallied as in observed resource requirements: at a given discount rate, the total cost of their coindays and their transaction fees. This is the base Sybil resistance.

Even if only a small number of paths are found, the order book size estimate extends the tally to a cost for the randomized subgraph concurrent with the observed paths: a total cost to the adversary, assuming the observed paths are representative. The representativeness is supported by observable selection bias in the inputs of the traversed transactions.

The estimate is restricted to this randomized subgraph. Only quantities estimated from the subset of inputs exhibiting the selection bias are scaled; other inputs encountered in the fetched history are excluded from that extrapolation. The order book size estimate supplies , a lower confidence bound on candidate count, to estimate the width of the randomized subgraph.

From the observed paths, estimate the candidate-value and holding-time distributions and their means as functions of time, retaining the number of observations supporting each estimate. Scale the estimated means by to estimate the corresponding aggregate quantities for the randomized subgraph concurrent with the observed paths. Resource estimates derived this way depend on the representativeness assumption, unlike bounds established directly from the observed graph.

Concurrent transactions with similar selection bias provide additional observations of the same candidate population. Combining comparable path samples refines the estimated distributions and their means; it does not add separate population sizes. With two comparable paths, the quantity scaled by is their mean, rather than their sum. The same applies to more paths: the number of observations supports the estimate and is not an additional width multiplier.

🤖 Subjective liability

The observed lower bound and estimated cost are assessed against the user’s threat model. There is no universal threshold for sufficient adversarial cost. The cost judged prohibitive depends on the severity of the user’s real-world threat model; more severe threats require a higher threshold.

The liability is zero when the attack cost is judged prohibitive under that model. Otherwise, it represents a subjective loss scaled by the user’s privacy budget. This valuation guides the combined decision framework; it does not establish that the chosen privacy measures cover every threat to the user.

🤖 In the decision tree

The term of a coin under consideration is fixed once its funding transaction confirms, so it’s computed once per coin and cached. The transaction’s own outputs get theirs after confirmation, as the randomized selection chapter describes.


  1. S. N. Bhatt, On Concentration and Connection Networks, MIT, 1981. ↩

  2. C. Belcher, Financial mathematics of JoinMarket fidelity bonds. ↩

🤖 Subset sum ambiguity

A privacy liability term of the cost function. It applies the techniques of the subset sum density chapter to the user’s own coins, for two measures:

  • Inputs. How well the sumset of the other users’ inputs covers the sumset of the user’s inputs.
  • Outputs. How well the sumset of the other users’ inputs covers the sumset of the user’s outputs.

Once the transaction has been fully built, both are also checked against the sumset of the other users’ outputs. If both are well covered for every combination, the sub-transaction model is underdetermined.

Given the wallet state and a transaction under consideration, it checks both for a proposed output decomposition, relative to the other users’ inputs known so far. The other users’ sumsets are bounded in degree, so they stay small, and the user’s own are complete. It’s cheap enough to evaluate for many decompositions.

Sub-transaction ambiguity

A sub-transaction mapping, as in the models of Maurer et al. and LaurentMT described in Collaborative transaction privacy, partitions a transaction’s inputs and outputs into sub-transactions that each balance. Given one valid mapping, others can be reached by transformations that preserve that invariant. Ordered by generality, they break counting the mappings into a hierarchy of complexity:

  • 1:1 exchange. If an output denomination has multiplicity , the permutations of the equal outputs all preserve the mapping. With one copy of the denomination per sub-transaction, quotienting by these permutations is trivial.
  • n:m exchange. Substitute a set of inputs or outputs for another. With effective values and costs at an estimated feerate, this preserves the invariant in a model that admits non-zero fees.
  • Merge and re-partition. The most general transformation that’s still constructive. Merge some of the mapping’s sub-transactions and partition them again, or make exchanges that break the invariant temporarily. It’s a walk through the space of partitions and back into the sub-space of sub-transaction mappings.
  • Enumeration. As in Maurer et al., the space can be enumerated by brute force.

Multiplicity makes 1:1 exchange trivial, but that isn’t enough for privacy. This term climbs only as high as n:m exchange, which reduces to subset sum. Subset sum density makes n:m exchange underdetermined as well, without the generality or the computational cost of the last two. The coverage checks below concern n:m exchange of the sums only the wallet knows: its own inputs and outputs. If those are sufficiently underdetermined, they give a lower bound on the number of sub-transaction mappings relevant to the wallet, and on the entropy of Maurer et al.’s link probabilities , and .

Notation

For a multiset of values:

  • is the set of its subset sums, over non-empty subsets.
  • is the set of sums of at most of its elements.
  • : every has some with .
  • : every has some with .
  • A single such is covered.

Inputs

  • : the feerate of the coalition formation proposal. Effective values are fixed at .
  • : effective values of the other users’ inputs known so far, positive values only.
  • : effective costs of the other users’ outputs. They’re only known once the transaction has been fully built, though not necessarily signed. By then is fixed. While decisions are evaluated, is empty.
  • : the own inputs, as effective values.
  • : the user’s outputs, as effective costs.
    • In the decision tree, a proposed decomposition.
    • Once the transaction has been fully built, the complete multiset of the user’s outputs.
  • Parameters:
    • : the degree bound for the other users’ sumsets, e.g. 2 or 3 for large transactions;
    • : the slop;
    • : the covered fraction at which the liability reaches 0;
    • : the number of doublings of over which the liability falls from 1 to 0.

Definition

  1. Other users’ sumsets. , and once is known. Either can be a bitmap, or count the subsets per sum.
    • Whether coverage should require more than one subset per sum depends on the threat model, the computational resources and the value range.
  2. Own sumsets. , and once is proposed.
  3. Coverage. Effective values are at least effective costs, so each check is one-sided.
    • While decisions are evaluated, check and . The other users’ inputs can plausibly combine to the same balance as the user’s coins, or slightly more.
    • After the fact, also check . Sums of are total effective costs, so they’re at most the sums of .
    • And . A sum of is a combination of the other users’ outputs that could be interchanged with the user’s outputs of that sum, so it’s at most their actual sum.
  4. Covered fraction. For each own coin in or , is the fraction of the subsets of its side that contain and whose sums are covered.
  5. Liability. .
    • It’s 0 once .
    • It falls by per doubling of .

Implementation

Tables

Built once per transaction and shared by all decompositions:

  • : for each sum up to the range, the smallest number of elements of that reach it, if at most .
    • Apply per input , from the top down.
    • Counting per sum works the same way, with one layer per subset size.
    • has at most elements. Where that’s far fewer than the range, enumerate it explicitly, or use a sparse convolution, and look sums up by binary search.
  • : the same over , once it’s known.
  • : enumerated once per transaction. : enumerated per decomposition. Both are small.
  • Lookups: a prefix count over the table answers whether the window holds a sum, or against .
  • Rounding: the windows tolerate rounding, e.g. to multiples of 128 sats. Round in the direction that counts no implausible substitution.
    • Against , round the values of down and the own sums up.
    • Against , round the values of up and the own sums down.
    • The window then widens by at most rounding units.
  • Range: from 0 to the largest own sum plus . Double it and rebuild if needed. Skip inputs that are too large to fit.

Updates

  • Each auxiliary input is one more pass over . Once the transaction has been fully built, each of the other users’ outputs is one more pass over . The order doesn’t matter.
  • Deduplicate inputs by outpoint and outputs by output id.
  • Removing a value needs counts, or a rebuild.

Per decomposition

  • Look up each sum of . The results for are shared by all decompositions.
  • Satisficing stops the work early:
    • a coin, once ;
    • a decomposition, once all of its outputs have.

Radix denominations

These are inputs with nominal value :

  • , ;
  • , ;
  • , .

They’re grouped by effective value , with multiplicity .

  • Multiplicity: one pass per group, as a sliding window along each residue class mod .
  • Contiguity: sort the coins and keep a running sum . Accept each next coin while it’s , starting from a coin .
    • Every sum is then covered without the tables.
    • It may use any number of coins, so it only applies when is at least the number of coins accepted.
    • Keeping coins per value gives robustness to removals per value.

In the decision tree

  • It’s a privacy-related term.
  • Worst case: only the inputs known so far count. is a lower bound, and auxiliary inputs are learned later. The other users’ outputs aren’t known until the transaction has been fully built, so only is checked.
  • Best case: , which is used for pruning.
  • Every participant, including the aggregator in that role, evaluates co-spend proposals with this term, deciding whether to propose a generated one or to accept an incoming one.
    • A generated proposal can carry density challenges, with a reward in the surplus.
    • Perturbing a proposal adds values to the tables, one pass each.
  • .

After confirmation

This is the analysis that contributes privacy gains, and that uses the budget.

  • All inputs and outputs are known, so the checks against apply.
  • Coalition formation proposal known: evaluate at its , which continues the decision tree’s chain. Also evaluate at the final feerate, which is a second scenario.
  • Recovery from seed: evaluate at the final feerate only.

Monotonicity

  • The decision tree’s estimate is the same definition restricted to the lower bound , with empty.
  • Learning inputs or outputs only adds sums to and , so covered sums stay covered and can only fall.
  • This requires the same , the same realized , and the same parameters.

Open questions

  • Is absolute, or relative to the target? Does it include adjustments?
  • After the fact, is a sum covered if either or covers it, or are the two fractions separate?

🤖 Consolidation penalty

A privacy liability term of the cost function. Spending several own coins together adds exposure to intersection attacks, which the term models as compounding with each additional coin. Subset-sum density and counterfactual routes jointly attenuate the penalty: the contribution of each depends on the other. The penalty is fully discharged when both meet their thresholds.

  • Why unbounded. Consolidation may leave the wallet worse off than its baseline, so the liability can exceed 1 and its associated reduction in subjective value can exceed the remaining privacy budget. Other terms may still outweigh this cost; the penalty does not categorically prohibit consolidation.
  • Density alone isn’t enough. Comparing the ancestor sets of pairs of inputs narrows down an intersection efficiently, even in a large transaction.

Consolidation exposes the inputs’ histories to comparison, so the route analysis considers their combined ancestry. Its measurements describe counterfactual connectivity between each input and the coins through which any of the consolidated funds first entered the wallet. Combining these measurements into a scalar would quantify how thoroughly the inputs’ histories have become connected through other users’ transactions. This measure of absorption would inform the consolidation liability alongside subset-sum density. The aggregation rule remains to be specified.

The routes factor uses the route counts of the Counterfactual paths to label the wallet’s coins, and the combined ancestry of the inputs.

Definition

The following parameterization uses per-coin route labels. Incorporating a joint measure of absorption into this parameterization remains an open question.

  • : the own inputs of the transaction under consideration, each with a label , the degree to which meets the counterfactual-route objective.
    • The labels are defined in Labels.
  • Links. .
  • Linked count. .
    • A single coin gives , and so does one coin below the route threshold spent with coins that meet it.
  • Routes. , and for a single coin.
  • Density. .
    • is the covered fraction of the subset sum ambiguity term for own input .
    • While decisions are evaluated, it checks against , the other users’ inputs known so far. After the fact, it also checks it against , the other users’ outputs.
    • , with well above that term’s .
      • : the number of doublings of over which rises from 0 to 1.
  • Liability. , with the factor per intersection.
    • Thresholds. once . once every input but one has , i.e. routes.
    • For more than one own input, it’s 0 only when both meet their thresholds.
    • The relief from each is proportional to the other: . With , density relieves nothing, and with , routes relieve nothing.

Labels

For each own coin :

  • Origins. is the set of coins by which the wallet received the funds descends from.
  • Routes. , with the wallet’s own edges omitted.
  • Label. rises with and reaches 1 at , the chosen route threshold. For example, .
  • Use. At , adds nothing to the linked count .

Everything depends on exists once confirms: the coins between its origins and , the other coins in their transactions, and their link probabilities. So is fixed from then on, and labels are cached per coin.

From bounds

With the bounds and :

  • uses , so it’s never overstated.
  • If , is impervious.
  • If , it isn’t, and more sampling won’t change that.
  • Otherwise, take more walks, or compute exactly on a pruned graph.

Combined ancestry

Spending own coins together links them. An intersection attack then intersects their candidate origins.

  • Union. : every coin by which the wallet received funds that any of them descends from.
  • Routes matrix. , for each and .
    • It’s a bipartite graph from to , with each edge labelled by its routes, written as a matrix.
    • Each entry is one max flow. Entries already computed for a coin’s own origins carry over: is the minimum of row over .
  • Reading it. Row shows which origins has many counterfactual routes from. When every row is high in almost every column, each input’s candidate origins cover almost all of . The sets the adversary can intersect then have a small symmetric difference, so intersecting them reveals little.
    • “Almost every” is read off , not fixed in advance. For example, the columns where one row is at least and another isn’t are what an intersection of those two inputs can reveal.
  • Aggregation. A candidate absorption index aggregates shortfalls in pairwise connectivity. Its parameters and its mapping to the consolidation liability remain to be determined.
  • Counterfactual superconcentrator. The graph of other users’ edges only.
    • Sources: the earliest ancestor coins, .
    • Sinks: the inputs under consideration for consolidation, .
    • The aim is counterfactual routes across it, making it a superconcentrator: for every , any sources and any sinks are joined by disjoint paths.

Candidate absorption index

One candidate aggregates the shortfall of each input–origin pair from a connectivity objective. For this purpose, use the unrounded flow ratio , retaining fractional values rather than the integer route count . Let be the objective and the degree to which a pair meets it. Saturation prevents additional flow for an already sufficient pair from providing further compensation for weak connectivity elsewhere.

For nonnegative weights summing to 1 over the input–origin pairs, define

At , this is one minus the root-mean-square shortfall. Larger gives weak pairs more influence; as tends to infinity, approaches the weakest score with positive weight. Finite permits strong coverage to compensate for incomplete coverage, while each improvement below saturation increases the index for a pair with positive weight. If a fraction of the weight has score 0 and the rest has score 1, then .

The weights must represent the exposure being evaluated, rather than the number of sampled paths. Their choice remains open, including how to prevent splitting funds or repeating observations from manufacturing credit. The index is a connectivity measure, not an attack-cost estimate. Incorporating Sybil resistance along the supporting paths remains to be specified: an adversary may create apparent alternatives through prior CoinJoins, and the expenditure supporting several pairs cannot be counted as a separate expenditure for each pair.

A possible extension first computes a coverage score for each input across origins, and for each origin across inputs, using a power mean with exponent . It then takes a power mean of those profiles’ shortfalls, with exponent , and subtracts it from 1. This distinguishes missing connections concentrated around one input or origin from missing connections spread across them, which the single mean does not. It adds a parameter and requires weights at both levels. Neither formulation by itself establishes that a high score makes a targeted intersection attack prohibitively expensive.

In the decision tree

  • It’s a privacy-related term.
  • Fixed per coin. Once a coin confirms, no later block adds to its ancestry. So , and the entries of for confirmed inputs, are computed once and reused in every leaf. Over time, they’re constant.
  • A leaf’s inputs. A leaf fixes the own inputs , and with them and the rows of . Nothing other users add to the transaction changes them, so the best and worst cases of the labels and are equal.
  • Outputs. The transaction’s own outputs get labels only after it confirms.
  • Order book coins. The own inputs’ coin edges are omitted, so routes from their origins into the transaction’s own outputs enter only through other users’ inputs.
    • An order book coin that descends from those origins adds routes, so selecting it is valuable.
    • A co-spend proposal from an own input that names such a coin links the two, unless such proposals are already common. An outcome may still prefer the selection, but the cost function should penalize proposals that leak the link this way.
  • Bounds. Leaves use from , the lower bound. Tightening , with more walks or an exact on a pruned graph, can run between iterations of the decision loop in the Mixed strategy chapter. It can only raise .
  • Worst case: checks only the other users’ inputs known so far. Their outputs aren’t known until the transaction has been fully built.
  • Best case: , which is used for pruning.
  • is unbounded, so its associated reduction in subjective value can exceed the remaining budget. An automated action requires a predicted improvement under the full cost-function evaluation. Consolidation-heavy branches are pruned when that evaluation cannot justify them; evidence that improves the lower bound can reduce the penalty and change the decision.
  • More aggressive consolidation can nevertheless have a better best-case evaluation because of feerates, batching opportunities, or reduced fragmentation. That best case alone does not justify execution under the current lower bound.
  • It applies to every own output of the transaction. The reduction in subjective value scales with their total value, independently of the number of outputs.

After construction

  • Once the transaction is fully constructed, is computed from the complete sets and the same cost function is evaluated with that information. This determines the liabilities and the accounting for privacy-budget expenditure, as described in Cost function structure. An explicit manual override resets liability accounting to the baseline.

Evaluating the wallet state

  • The term can evaluate a wallet state too. Imagine that an emergency forces the user to spend all of its coins rapidly in one unilateral transaction, and take that transaction’s consolidation penalty. This favors arranging the wallet state to minimize the privacy damage if such a liquidation becomes necessary.
  • That transaction’s cost includes its objective costs, e.g. the fees for each coin, so this also prices a wallet split over many coins.
  • It depends on the open question about transactions with only the wallet’s own coins. Until that’s settled, there, and every state with more than one coin gets the full penalty.

Monotonicity

  • can only fall as rises, or as the labels rise.

Open questions

  • How should the absorption index determine the route factor? The candidate shortfall mean and its grouped extension describe possible aggregation rules; their weights, parameters and resistance to manipulation remain to be evaluated.

  • Should siblings also count towards ?

  • A transaction with only the wallet’s own coins has no other users’ coins, so and the penalty can’t be discharged. Which density applies there? For example, the covered fraction of the outputs that became the inputs, in the transactions that created them.

  • How should and be scaled?

  • What link probabilities apply to the transaction under construction? They must hold in every completion.

  • Which term penalizes a co-spend proposal that leaks a link to an order book coin that adds routes, and how is “already common” measured?

  • How is the routes factor computed: from each input’s , as the definition does now, or from the counterfactual superconcentrator condition?

  • How is the counterfactual superconcentrator condition checked? It ranges over sets of sources and sinks of equal size, while holds only single pairs.

  • Should ramp up to , or switch from 0 to 1 at ? What should be?

  • May use an estimate (, the analytic estimate or Monte Carlo) when the randomization evidence is strong, or only ?

  • What label does an own input get before it confirms, such as change from a transaction still in flight?

🤖 Sibling output penalty

A privacy liability term of the cost function. Spending outputs of the same transaction together is wasteful, and more indicative of common ownership than spending unrelated coins together. It’s penalized heavily.

Definition

  • : the own inputs of the transaction under consideration.
  • For each earlier transaction , is the number of its outputs in .
  • Liability. , with large.
  • Neither the labels from the Consolidation penalty chapter nor subset sum density reduce it. Amounts can explain the values, but not two users spending outputs of one transaction together.

In the decision tree

  • It’s a privacy-related term.
  • Worst case: as defined. It depends only on the own inputs.
  • Best case: , which is used for pruning.
  • is unbounded, so it can exceed the remaining budget. The action is then taken only if other terms, e.g. a payment deadline, outweigh it.
  • It applies to every own output of the transaction. The discount scales with value, not with the number of outputs.

After confirmation

  • is fixed once the inputs are chosen.
  • Once the action is taken, the resulting coins’ liability is capped at 1.

Open questions

  • Should extend to coins with a common ancestor further back?

🤖 Privacy metrics

Measures computed from public data, which the privacy liability terms take as input. Unlike the terms, they don’t depend on the wallet’s threat model or preferences.

  • Order book size estimation: how many candidate coins a transaction’s inputs were selected from.
  • Subset sum density: how many subsets of a multiset of values sum into a target interval.
  • Counterfactual paths: how many times an amount could have travelled from a source coin to sink coins, along disjoint counterfactual paths.

🤖 Order book size estimation

A relatively conservative estimate of a lower bound on the number of candidate coins a transaction’s inputs were selected from, and a median estimate of that number. Both measure the effect of the selection preferences in the randomized selection chapter. The Sybil resistance term uses , and the Counterfactual paths chapter uses for its degree sequence.

Candidates

Candidates are the coins whose owners are active and offering them in the order book. is how many there are. It isn’t directly observable.

  • Under the actual block hash , the candidates’ hashes are uniform. The selected inputs are a subset. If the selection depends on the hashes, the subset deviates from uniform, which bounds from below, much like estimating the hash rate from proofs of work.
  • Candidates must be fixed before is known.
  • Each candidate is one draw. Spending the same coin twice isn’t a second draw.
  • To exhibit the deviation, an adversary must control all the candidates, not just the selected coins.

Hashes

  • for each input outpoint . is a tagged hash, truncated to 64 bits and read as an integer modulo , so the are points on a circle.
  • Truncation keeps the guarantees below: the truncated hashes are uniform on the grid of points, and the extra grid unit per span covers the rounding.

Pool size bound

For the input hashes of a transaction and a confidence parameter :

  1. Spans. Sort the hashes around the circle. An -span runs from a hash to its -th successor. Its width is the distance between them, plus one grid unit.
  2. Sums. For each and , is the smallest total width of spans with disjoint interiors. Spans may share endpoints. Let .
    • For , this is the sum of the smallest gaps.
    • Larger detects groups of nearby hashes.
  3. Tail bound. For a hypothetical pool of candidates:
  4. Score. With weights that sum to 1 over all :
  5. Bound. is the smallest integer with .

Why it’s conservative

for every selection strategy. This includes choosing the inputs, and how many, after seeing the hashes, in order to maximize .

  • One placement. In a uniform pool of , the total of fixed disjoint blocks of gaps is . Its lower tail is at most .
  • Every placement. There are at most ways to place the blocks. A union bound covers taking the minimum after seeing the pool.
  • Subsets. Each selected -span contains at least gaps of the full pool. So no subset has smaller totals than the pool itself. The extra grid unit per span covers rounding hashes to integers.
  • Combining. Each is a conservative p-value, so . By Markov’s inequality, . The terms may be dependent.

Properties

  • Monotone. At a fixed beacon and , adding inputs never lowers . So withholding coins from a fixed pool can’t raise it.
  • Symmetric. No position on the circle is special. Rotating or reflecting the hashes doesn’t change , so it doesn’t matter which hashes count as lucky.
  • All inputs. Every input’s hash enters through the spans.
  • Integer arithmetic. Each weighted term is rounded down to a multiple of , using integer square roots. Rounding only lowers the score, so it keeps both guarantees.
  • Caps. Leaving out the terms above a fixed or keeps both guarantees: their weight goes unused. It costs power.
  • Cost. arithmetic operations over all , on integers of bits.
    • A Python reference implementation takes a median of 25 ms for 64 inputs and 92 ms for 100.
    • A Rust implementation takes 0.01–2.5 ms for up to 100 inputs, and 17 ms for 200, on an Apple M4. It decides in floating point, and falls back to the exact integer score near the threshold, so it returns the same as the reference.

🤖 Median estimate

inverts the joint sums at their median instead of at . For a chosen and , it is the smallest at which the observed is at least the median of the same quantity for a uniform pool of candidates.

  • Same construction as . The spans and sums are those of the pool size bound, with in place of . For , the quantity is the sum of the smallest gaps, whose exact law is known.1
  • Median-unbiased only for the pool’s own spans. reads correctly in the median only when the observed spans are spans of the full pool, as when the whole pool is observed.
  • Reads low under weaker selection. As in Why it’s conservative, no selected set has smaller joint sums than the pool itself, so is lower.
  • Reads high on small pools. It spends no , so nothing bounds how often it exceeds .
  • Not the largest over and . Taking the largest over all and reads high.
  • No lowest error estimate. Without a probability law for the selection, no estimator has lowest error. The tails are heavy, so estimators are compared by quantiles rather than by mean squared error.

Measured in the prototype for a related statistic, the median inversion of the -th smallest gap:

  • With clustering and , it reads about . At and , the median reading is .
  • At , it overshoots in 28% of runs, and in 22 of 40 runs at .

Finding the block hash

Someone examining a transaction doesn’t know which block hash the selection used. They can guess it from the confirmation time, or from the nLockTime, but not exactly. So they evaluate every candidate , at each for candidates, and take the largest .

  • Candidate block hashes. 1000 or more for every transaction that looks like a CoinJoin, all mined after its inputs confirmed.
  • No false beacon. Under a block hash the selection didn’t use, the input hashes are independent and uniform: a fully observed pool of . So with probability at most for each such block hash, and at most for all of them.
  • Screen. Only the terms, sums of the smallest gaps, are evaluated for every block hash, once, at . That is a sort and one score. The full bound is evaluated only when the screen gives . The screen’s threshold is fixed, so both guarantees hold.
  • Cost. With and up to 100 inputs, 2–9 ms per transaction in Rust, mostly hashing (about 75 ns per hash) and the screen (1–4 µs per block hash). Hashes may be cached per outpoint and block hash.

Simulation

1000 random block hashes per transaction, , 32 transactions per configuration, using the Python reference.

  • No block hash used. Inputs drawn uniformly. In all 96 transactions ( = 16, 32, 80), no block hash gave . At instead of , 25 of them had one, up to .
  • One block hash used, by lowest hashes, XOR pairs or the tightest cluster, with = 1000 or 100,000. In all 576 transactions, it gave the largest , no other gave , and .
  • Cost of the split. Median at is lower than at by about 2.6 times at , 1.7 at and 1.3 at .

Caps

Median of the used block hash with and , at :

CapLowest hashesXOR pairsCluster
0.0100.3290.013
0.1080.3290.167
0.1560.3290.238
, 0.0510.1060.075
none0.2250.3290.350
  • Don’t cap . Pairs need many terms.
  • Capping loses clusters and lowest hashes. The full bound runs on about one block hash per transaction, so it can stay uncapped up to about 100 inputs.
  • The screen missed the used block hash in 1 of 32 transactions (lowest hashes, , ).

Measurements

From the prototype, with . Nine selection strategies are applied to the same candidate hashes in each trial.

Median with , over 32 trials:

XOR pairsLowest hashesClosest pairsUniform
457.51166.54
16227.5116.526516
32346.5225378.532
100400327457.5100
  • With and , median ranges from 0.28 (lowest hashes) to 0.47 (two clusters).
  • Uniform selection gives . A large pool shows nothing unless the selection is biased.
  • Overshoot. in none of the 1,152 selected sets at , and none of the 2,304 at .
    • This doesn’t prove coverage. The proof does.
    • The guarantee bounds how often exceeds , not by how much.

Tighter alternatives

Overestimating awards credit for Sybil resistance that isn’t there. That is worse than underestimating it, so the bound above is preferred over tighter ones.

  • Density profile. Anchored ranks, Beta spans and Rényi gap ranks, at each.
    • Median between 0.66 and 0.78 in the same comparison.
    • in 5 of the 1,152 sets, by up to 1.30 times, and in 11 of the 2,304.
    • Its returned bound has only been tested to be monotone, not proved. It also treats fixed positions on the circle specially.
  • Gap curve. Accumulates the evidence of every ordered gap, with fixed weights and power .

Limitations

  • Candidates, not owners. bounds the number of candidate coins, not the number of users. One owner with many coins is many candidates.
  • Values. The adversary’s cost is proportional to only if the selected coins’ values are typical of the candidates.
  • Lower bound only. isn’t an estimate of . There is no likelihood for the selected set given .
  • Power. The fixed weights, the union bound and the square root lose power.
    • The minimum totals discard some of where the hashes are.
    • In a fixed example with one dense cluster, adding a second cluster at half the density raised by about 3%.
    • Splitting over 1000 block hashes costs most at small : about 2.6 times at .
  • Concealment. A selection strategy can keep near . Monotonicity only prevents raising by withholding coins.
  • Review. The calibration argument hasn’t been reviewed outside the prototype.

Open questions

  • Which and should use, or how should they be combined?
  • How should the median be computed for , and for large ?
  • Can be updated as inputs are added? A wallet compares many candidate transactions.
  • More power. Options next to the bound above:
    • Combine the terms by a weighted minimum, rejecting if any , instead of the square root. This loses less to the split over block hashes.
    • Tighter tails for . In a uniform pool, the gaps are exponential variables divided by their sum.2 Sums of the smallest gaps then have an exact law,1 but it is impractical for large and small sums. A Chernoff bound on this form is practical, and gains about 1.3–1.6 times in , only for large . Nothing comparable is known for .
    • Anchored ranks for the per-input preference, which are tighter for lowest hashes, at part of . They treat the anchor specially, so symmetry is lost.

  1. L. Holst, “On the lengths of the pieces of a stick broken at random”, Journal of Applied Probability 17(3) (1980), 623–634, doi:10.2307/3212956. ↩ ↩2

  2. A. Rényi, “On the theory of order statistics”, Acta Mathematica Academiae Scientiarum Hungaricae 4 (1953), 191–231, doi:10.1007/BF02127580. ↩

🤖 Subset sum density

How many subsets of a multiset of effective values sum into a target interval. It’s a quantity that cost function terms reuse, not a term on its own:

  • The subset sum ambiguity term checks how well the sumsets of the other users’ inputs, and after the fact their outputs, cover the sumsets of the user’s inputs and outputs.
  • The consolidation penalty uses the same coverage for the user’s inputs.

Dense subset sums give many readings of which inputs funded which outputs. Where the subset sums of different users’ coins on the same side overlap, they also give readings of which coins belong to which user. This chapter covers how the index is estimated, and how co-spend proposals and the aggregator optimize it.

Effective values

Effective values are computed at the coalition formation proposal’s feerate , with no adjustments. They form the multiset whose subset sums are counted.

  • This isn’t a perfect model, but it’s one of the plausible scenarios the adversary must consider.
  • For all the adversary knows, the feerate was the coalition formation’s and every adjustment was 0. So any reading found under it is one the adversary can’t rule out.

Estimates and enumerators

  • Saddle point estimate. Sasamoto, Toyoizumi and Nishimori estimate the number of subsets summing to a target.
    • Their grand partition function, , counts subsets by size as well as by sum.
    • It’s a product over inputs, so adding or removing coins changes only their factors. Re-solving and costs per Newton step.
    • It’s only valid where the number of solutions is large.
  • Distinct sums. Salas enumerates the distinct subset sums in time, or expected, independent of the range. It keeps one witness subset per sum, but gives no counts.
  • Sparse convolution. Bringmann, Fischer and Nakos convolve nonnegative vectors in time near-linear in the number of nonzero entries of the output, with a Monte Carlo algorithm, and deterministically or Las Vegas.
    • Convolving the count vectors of groups of coins gives the explicit sumset with its counts, not only which sums are reachable.
    • Where the distinct sums are far fewer than the range, this is cheaper than a table over the whole range.
  • Bitmaps and counts. Bellman’s algorithm over a bounded range, as implemented by the subset sum ambiguity term.

Co-spend proposals

  • Challenges. A co-spend proposal can require density with challenges, and attach a reward for them in the surplus. Aggregators aren’t guaranteed a payout.
    • , the interval width and a subset size cap are difficulty parameters. Co-spend proposals challenge whatever they like.
    • A simple client can send a single-UTXO proposal with a high density requirement and a large surplus, delegating the search over the order book to the aggregator.
  • Perturbation (fungi-protocol/docs#75). Given the convolution implied by a co-spend proposal, add desired values, e.g. standard denominations, and check whether the set becomes dense enough.
    • Simulated annealing makes the same moves, adding or removing a coin. It can generate co-spend proposals for the decision tree, and optimize coin selection.
    • Unlike branch and bound, it needs no bounds on the cost function.

Aggregator

The aggregator searches over combinations of co-spend proposals, for ones whose inputs solve each other’s challenges easily.

  • Terms. A combination’s terms must intersect. The aggregator determines the feerate and the other concrete parameters from the intersection, and the feerate fixes the effective values.
  • Score. The interval is only known once the coalition formation proposal is hashed. So a challenge is easy if density is high across its whole range of interval positions, by the saddle point estimate.
    • It respects , since it counts by size.
    • It doesn’t check disjointness. The prover does.
  • Moves. Add or remove a co-spend proposal, as in simulated annealing.
    • Seed with proposals that offer large surpluses.
    • Prefer additions that raise the score in the most challenge ranges per unit of weight. Proposals whose challenge ranges overlap reinforce each other.
    • Each addition brings its own challenges, which must be easy too.
    • Accept a combination once every challenge is easy. Among those, prefer larger rewards within the weight limit.
  • Grinding. Rehashing for an easier interval is acceptable. Finding better coins to aggregate with is easier.
  • Prover. Once the combination is fixed and hashed, solve each challenge interval for disjoint subsets of the inputs. If it fails, perturb the combination and rehash.
    1. Bounds. Give up if , or if , where is the number of largest values needed to reach .
    2. Singletons by binary search. Pairs by two pointers, then a maximum matching.
    3. Larger subsets. Run Bellman’s algorithm over the unused coins, storing per cell the smallest subset size up to and the last item. Extract a smallest subset, remove it, and repeat.
      • Round values down to multiples of , and target , so exact sums stay in .
    4. Repair. If stuck below , move or swap coins between subsets and the unused pool. Stop at .
  • Encoding. One label per input in , with 0 for unused. The subsets are disjoint by construction, and verification is .

🤖 Counterfactual paths

A counterfactual-connectivity measurement used by the cost function. It counts how many times the sink’s amount could have travelled from a source coin to the sink coins, along disjoint counterfactual paths. This is the problem definition’s robust connectivity, measured with one max flow.

The paths start at any coin linked to the source within its transactions, and end at any coin linked to the sinks. These links are what make more than one route possible. A source and a sink with nothing linked to them give at most one.

The Consolidation penalty chapter uses it to label the wallet’s coins, and to estimate when spending them together is safe from intersection attacks.

Network

The transaction graph, with details that don’t matter here, such as scripts, left out. Transactions are vertices and coins are edges, which works because an unspent coin can’t carry flow along the DAG. Each max flow is from one source to its sinks, and every edge is labelled with its capacity for that pair.

Edges follow the funds, from the transaction that creates a coin to the one that spends it. The source is the earlier coin, such as an origin of the wallet’s coins, and the sinks are later coins, such as the wallet’s own. Bitcoin’s references point the other way, from each input to the coin it spends. Either direction gives the same result. Reversing every edge and swapping the source with the sinks turns each cut between them into a cut with the same capacity, so the max flow, and with it , is unchanged.

  • Coin edges. Each coin is an edge from the transaction that creates it to the transaction that spends it, with capacity .
  • Flow edges. The model is refined by replacing each transaction with a bipartite graph: an edge from each spent coin to each created coin.
    • Capacity: .
    • is the probability that and are in the same sub-transaction.
    • Max flow works the same way on the refined graph, so the model with one vertex per transaction is without loss of generality.
  • Link edges. These carry no flow. They only define the neighbourhoods below.
    • Between the inputs of a transaction, with probability .
    • Between its outputs, with probability .
  • Neighbourhoods. The super-source of a coin connects to and to every coin linked to it on either side, with capacity equal to the link probability times that coin’s value. The super-sink of the sink coins is built the same way.
  • Own edges. When source and sink are both the wallet’s coins, only counterfactual paths should remain. Two kinds of edges are omitted from the graph:
    • flow edges between two of the wallet’s coins in the same transaction;
    • coin edges of the wallet’s coins on the way from the source to the sink.

Definition

For a single source coin and sink coins :

  1. Amount. , where is the sum of the sinks’ values.
  2. Caps. Every coin edge and every flow edge is capped at .
    • Uncapped: the coin edges of the source and the sinks, and the super-source and super-sink edges.
    • Coins linked to the source or the sinks are capped like any other, so each carries at most one route.
  3. Flow. is the max flow from the super-source to the super-sink.
  4. Routes. .

For several sources, .

  • A single super-source over all of would add up the routes of different sources. Two linked coins with one route each would score 2, hiding the intersection.

Why this counts routes

  • Theorem. An acyclic flow of value in which no edge carries more than is a -route flow.1 2 3
    • That is, it’s a sum of bundles. Each bundle is paths that share no edge, carrying equal amounts.
  • Guarantee. With every capped edge at and , removing any capped edges still leaves a flow of at least .
    • So no capped edges cut the source off from the sinks. This is the problem definition’s “no small cut”.
  • Uncapped edges. These behave like parallel copies, so routes may share them.

Split routes

A route may be spread over several smaller coins, as long as no two routes share a capped edge. For example, two disjoint coins of each count as one route of .

The floor makes conservative. Three disjoint coins of give , yet any one of them can be removed and still gets through.

Max flow alone isn’t enough

  • Without caps, a single large coin can carry all of , so can’t tell one route from several.
  • Scaling the demand to doesn’t help, for the same reason.

Scope

For one source and one sink, only the coins that descend from the source’s neighbourhood and are ancestors of the sink’s neighbourhood matter. These lie between the two confirmations. One pair never needs the full chain.

Pruning

Any restriction of the transaction graph gives a lower bound on , since removing coins or edges can’t raise a max flow. Some examples:

  • the last blocks;
  • only CoinJoins meeting some conditions;
  • only the flow edges of specific coins in them, such as equal amount outputs.

A lower bound is safe for labels: a coin is never labelled impervious when it isn’t.

Restricting to CoinJoins undercounts, though: payments and PayJoins intertwined with CoinJoins also carry counterfactual routes.

Cost

  • One max flow per source. Sources are independent, so they parallelize.
  • A transaction with inputs and outputs has flow edges.
    • Cache per transaction. It has a closed form for equal amounts, and needs subset sum enumeration otherwise.
    • Leaving out edges with small gives a lower bound.
  • A new block only adds coins and edges, so it never lowers .

Approximation

This avoids computing on the full graph.

The approximation can’t be strictly monotone. Bounding the resources spent on decision making is a client implementation decision. As long as a light client doesn’t defect, i.e. it behaves as if its evaluation is monotone, it is still incentive compatible.

Data access

How much of the chain a wallet sees depends on its constraints:

  • With limited bandwidth, it samples blocks.
  • With limited storage, it fetches every block in a range, but keeps only a subgraph in a compact encoding. See Pruning.
  • If it can only fetch transactions adjacent to ones it knows, it uses the bounds.

Layers

The approximation estimates each layer of the network separately. Each layer depends only on the ones before it.

  1. Topology. Transactions, their numbers of inputs and outputs, and how long coins stay unspent.
  2. Amounts. Coin values. Relative to , they set each coin’s capacity.
  3. Links. , and , computed from the amounts within each transaction. They set the flow edges and the neighbourhoods.
  4. Knowledge. The wallet’s own edges.

Sampled blocks

  • Sample blocks, and estimate each layer’s distributions from their transactions, separately.
    • For the topology: the numbers of inputs and outputs per transaction, and the spend rate , the fraction of unspent coins spent per block.
  • Base the estimate on randomized selection, as in the Randomized selection chapter. When coins are selected at random from the candidates, the transaction graph can be treated as a random acyclic network with those degree distributions.4 5
  • Observed paths. Traversing backwards from a coin in the order book until reaching CoinJoins the wallet already knows, such as descendants of ones it participated in, establishes a flow route. This can be repeated several times, bounded to a block range. Even if only a few paths are found, they estimate the degree sequence of the random acyclic network, together with the order book size estimation.
    • The paths give the distributions of the numbers of inputs and outputs, from the transactions they pass through.
    • The order book size estimation gives a median estimate of the number of candidates.
  • Number of candidates .
    • The order book size estimation gives , a relatively conservative estimate of a lower bound on . It scales the Sybil cost.
    • The degree sequence uses , a median estimate of .
    • In the pool model below, no coins enter or leave the CoinJoin graph. There, doubling from 1000 to 2000 lowers from 1.20 to 0.73 at , .

Time slices

Every route crosses each block boundary on a coin that’s unspent at that boundary.

  • A slice is the set of coins unspent at a boundary that descend from the source’s neighbourhood and are ancestors of the sinks’ neighbourhood, excluding the neighbourhoods themselves.
  • Each slice is a cut, so is at most the smallest slice’s capacity.
  • In the prototype below, equals the smallest slice in 95% to 100% of runs.

Analytic estimate

This covers the topology layer only: every coin’s capacity is , and every is 1.

  • Growth. is the number of unspent coins after block that descend from the source’s neighbourhood.
    • .
    • and are the mean numbers of inputs and outputs, and is the generating function of the number of inputs. The two numbers are assumed independent.
    • Under random selection, a transaction joins the descendants with probability , the probability that any of its inputs is a descendant.
    • , the ancestors of the sinks’ neighbourhood, grows the same way backwards from the sink, with inputs and outputs swapped.
  • Slices. Under random selection, an unspent coin after block is an ancestor of the sinks with probability , independently of whether it descends from the source.
  • Ends. The slices next to the source and the sinks are the narrowest, and nearly independent of each other.
    • , where is the number of coins the source’s neighbourhood first reaches.
    • , where is the number of coins that first reach the sinks’ neighbourhood, and is the number of blocks between them.
    • , so .
  • Using only the single narrowest slice, , overestimates .

The estimate is neither a lower nor an upper bound.

Monte Carlo

  • Generate transaction graphs from the estimated layers, in order: topology, amounts, links, knowledge.
  • Compute on each with the max flow, restricted to the coins between source and sink.
  • Estimate from the results.
  • Unlike the analytic estimate, this covers every layer.

Prototype, analytic and Monte Carlo. A pool of candidate coins of equal value. In each block, a fraction of the pool is selected at random into transactions of inputs and outputs. The source’s neighbourhood is the inputs of a transaction in the first block, and the sinks’ is the outputs of one blocks later. Each Monte Carlo row is 30 to 40 runs.

, Monte Carlo, analytic, Monte Carlo, analytic
4100080.230.110.030.00
41000121.200.970.300.23
41000203.083.200.970.99
8200061.431.040.030.00
8200082.832.900.300.30
82000125.335.580.930.97

Counting only whether the first coins at each end are spent or created in time predicts at , . The graph between the ends is what limits there.

Bounds

  • Upper bound. For , merge every coin transactions away from the source into the super-sink, and compute . Do the same from the sink backwards, and take the smaller of the two.
    • Keep as computed from and . Merged coins raise the sink’s value, and recomputing from it would break the bound.
    • Merging only adds capacity, so each is an upper bound.
    • The cost depends on and the local degrees, not on the chain.
  • Lower bound. For , take random walks forward from the source’s neighbourhood and backward from the sink’s. Follow randomly chosen edges per step, up to the other end’s confirmation height. Compute on their union.
    • The union is a subgraph, so its is a lower bound.
    • Walks that cross share edges, and the max flow counts a shared edge once. Overlapping paths aren’t double counted.

Randomization. With randomized selection, as in the Randomized selection chapter, in the prototype below, this puts the smallest cut next to one of the ends, so . That isn’t guaranteed in general.

  • The selection bias bounds the number of candidates from below. It doesn’t show that both ends draw from the same candidates: two groups that never transact with each other can each select at random.
  • The evidence that the ends are connected is itself, as it approaches .

Prototype, bounds. A layered model: 7 layers of 256 coins of equal value, joined by 6 rounds of transactions with 8 inputs and 8 outputs, 6 seeds each.

  • The source’s neighbourhood is the 8 inputs of its transaction, and the sink’s is the 8 outputs of its transaction. So 8 is the most can be.
  • Random selection: in every seed, so no route was lost in between. With 4 walks branching 2 ways per step, in every seed.
  • Two halves that never transact with each other: , while .
  • Two halves, 10% of transactions mixed: in 5 seeds, and 7 in the other.

Limitations

  • Sub-transactions. Flow relaxes sub-transaction mappings: it can split across them in ways no single mapping allows.
  • Unknown link probabilities. Taking when it’s unknown is conservative.
  • Independent transactions. Each transaction’s probabilities are computed on their own. Intersections across transactions enter only through the minimum over sources and the consolidation condition.
  • What the adversary removes. Routes are counted as disjoint in coins and flow edges, while an adversary deanonymizes users, removing all of a user’s coins at once.
  • Timing and hops. Route length and timing aren’t modelled.

Open questions

  • With several sink coins, should each sink get its own share of ?
  • Should a privileged counterparty’s own coins also be omitted, since it knows where they went?
  • Known transactions. The wallet already has the transactions next to its own coins. Should the estimates use those as they are, such as the actual and , and model only the transactions it hasn’t fetched?
  • Amounts and links in the analytic estimate. Can they enter as expected capacities per coin, or only through Monte Carlo?
  • How should competing spends of one coin be handled?
  • Entries and exits. A smaller also means fewer vertices. Two counts depend on it: coins entering from transactions without randomized inputs, and outputs leaving the CoinJoin graph. Which way this moves , and so whether or is more conservative here, isn’t known.

  1. W. Kishimoto, A method for obtaining the maximum multiroute flows in a network, Networks 27(4), 1996. ↩

  2. C. C. Aggarwal, J. B. Orlin, On multiroute maximum flows in networks, Networks 39(1), 2002. ↩

  3. C. Chekuri, M. Idleman, Congestion Minimization for Multipath Routing via Multiroute Flows, SOSA 2018, Theorem 1. ↩

  4. B. Karrer, M. E. J. Newman, Random acyclic networks, 2009. ↩

  5. B. Karrer, M. E. J. Newman, Random graph models for directed acyclic networks, 2009. ↩

🤖 Mixed strategy

This chapter recommends how to compose a mixed strategy out of the cost of pure strategies, as set out in the Optimization framework chapter, using the concrete monotone terms of the evaluation in the Privacy liability terms chapter.

Randomization

An adversary that knows the wallet’s state and pure strategy can predict its next action. A mixed strategy randomizes over pure strategies, but its effect depends on how the observable outcomes differ.

Uniform selection among distinct leaves has bits of entropy over leaf identity. However, similarities between their outcomes can reduce the uncertainty over the distinctions relevant to an adversary. Sampling should give less weight to similar alternatives so that the resulting distribution is approximately uniform over materially different choices. How to measure similarity and construct this sampling distribution remains open.

Time dependence

Every term of the cost of a pure strategy is a piecewise linear function of time, so the cost is too. The cost is a transparent sum of such terms partly so that crossing times can be solved for, and the brackets derived efficiently at predicted future times. Since the predicted times are themselves uncertain, the cost brackets can also be augmented with time brackets, i.e. bounds on those predicted times.

Internalization

The solver searches for sequences that lead to states with greater valuation. It values the leaves first, then propagates their brackets and the tree level expectation toward the root. The tree level expectation internalizes the optionality of the leaves into their parent: it is the mean of the worst cases of the least worst leaves below that parent, since the mixed strategy chooses uniformly among them. This ignores that leaves aren’t independent, as they may share actions. This reduces a plan involving many contingent future actions to comparisons among the actions available now.

Internalizing the expectations about a node’s children into the node gives the node its own piecewise linear curve. Solving it for the time at which the next child is expected to have positive utility determines when to take that branch, unless new information invalidates the decision in the meantime.

Decision loop

The wallet acts in a decision loop. Internalization is what allows this loop to be run as a greedy search, going one level down the tree per iteration: since each node already accounts for what may follow it, a look ahead of depth 1 is sufficient. Internalizing takes one pass over the tree, and doesn’t need to be repeated on every iteration of the loop.

From the current state, the wallet finds the next action, i.e. the child of the root, that will become attractive soonest, waits for it to do so, and takes it. It then prunes that action’s siblings, committing to the sub-tree below it. There can be multiple paths to the same outcome, for example through repeated actions or states that converge, so an implementation may share sub-trees and represent the tree as a DAG.

Tactics

🤖 A procedure for constructing the decision tree that the cost function evaluates, using the terms in the Privacy liability terms chapter. The input is the current wallet state. The output is a tree whose edges are actions and whose nodes are successor wallet states.

🤖 Inputs and output

The wallet state contains the spendable UTXO set, inflight transactions, current protocol observations and beliefs, policy parameters, and an ordered queue of pending actions. An entry may be a PSBT fragment, a lone TxOut for an intended payment, or an arbitrary transaction fragment. This procedure calls every such entry an intent without assuming that it already defines a complete transaction.

The edges of the tree are the actions listed in the Optimization framework chapter, together with constructing, signing, broadcasting, or replacing a unilateral transaction, and deferring or skipping an intent.

Each path must be executable from the current wallet state. Each leaf denotes the resulting wallet state after a mutually exclusive plan, including its remaining queue and unilateral fallbacks.

🤖 The Bottom-up construction chapter builds the tree from the leaves toward the root: it partitions the queue of intents, selects coins, constructs change, extends outcomes with order book coins, expands leaves into action sequences, and brackets and backs up their values.

Re-evaluation

Each path down the tree is a plan, i.e. a pure strategy. Since announcements and co-spend proposals are actions like any other, they are planned as well. New alternatives can be added to the tree, or a whole new tree can be computed from any state and combined with the current one as further alternatives.

Because the tree is potentially large and costly to generate and evaluate, most of it is generated up front. It is then updated as co-spend proposals, coalition formation proposals, and the auxiliary inputs of committed transactions are learned.

🤖 The decision loop is specified in the Mixed strategy chapter. The tree is extended or rebuilt within the available compute budget, and re-evaluated with current brackets and action-duration estimates, whenever the pending-action queue changes or other new information arrives.

🤖 Relevant events include new co-spend proposals, changes to randomization terms during coalition formation, fee or time updates, and observing additional inputs before committing to particular output choices. Event-driven re-evaluation allows the wallet to exploit new information without requiring exhaustive precomputation of the partition lattice.

Bottom-up construction

The tree is built bottom up, starting with complete outcomes and working back towards the immediate actions that would lead to them:

  1. Partition the queue of intents heuristically. Each partition is an outcome: a set of batches to execute.
  2. For each outcome, select coins batch by batch, possibly shuffling. Coin selection may optimize or be fully randomized, and interactive incoming payments can be treated as pseudo-inputs. This ensures that the outcome has a positive surplus and can be executed.
  3. Decompose each surplus into radix denominations, enumerating the possibilities by brute force.
  4. Extend outcomes by selecting coins from the order book.

This generates many independent outcomes, each complete and balanced, each made up of disjoint batches. Typically there will be one greedy batch, or one small batch for a unilateral fallback if an intent becomes urgent.

🤖 Construct the tree from the leaves toward the root. First enumerate candidate outcomes: complete allocations of queued intents to transaction batches or unilateral fallbacks, together with concrete inputs, outputs, change structures, and protocol contingencies. Then derive action sequences that realize those outcomes from the current wallet state. While working upward, merge reverse paths whenever they share the same predecessor action. Equivalently, factor common prefixes of the root-to-leaf action sequences so that shared, less-committal actions appear closer to the root.

🤖 1. Seed partitions of the pending-action queue

A partition of groups intents that the wallet plans to realize together. Each part is one batch; distinct parts are separate transactions or sessions. The partition-refinement order captures every way the same intents may be realized together or separately. Its bottom element is the discrete partition of singleton batches, and its top element is the indiscrete partition containing the entire queue in one batch.

Time-dependent payoff curves constrain this lattice. If an intent is elapsing and its expected multiparty delay would make it irrational, move it to an executable unilateral fallback or skip it. The residue remains eligible for batching. This avoids the false dichotomy between doing the whole queue unilaterally and putting the whole queue into one multiparty transaction: one leaf may contain several multiparty batches, several unilateral actions, and deferred intents.

Seed candidate partitions as follows:

  1. Always add the bottom and top elements after applying feasibility and time filters.
  2. If is small enough, add the whole partition-refinement lattice. The number of partitions is the Bell number , so exhaustive enumeration is reserved for small queues.
  3. Otherwise, seed at least one maximal path from bottom to top. Starting at the bottom, repeatedly merge the pair of parts with the greatest priority according to objective cost reduction, coin-selection feasibility, and time constraints. Never backtrack along this path. Its partitions provide partition seeds and a linear-space baseline for this stage. Later coin-selection and change alternatives may expand each seed into several outcomes and leaves.
  4. Prefer several paths when resources allow. Vary priority order or retain several near-best merges at selected levels so the seed is a tree rather than only a list.
  5. Spend remaining precomputation budget on additional partitions. Simulated annealing, randomized merge and split moves, beam search, or another combinatorial search may sample the omitted lattice. During a live protocol session, repeat this search with newly revealed information and score the sampled partitions directly.

🤖 2. Allocate coin selections within each partition

For every seeded partition, allocate inputs jointly across all of its batches. A simple implementation processes the batches successively with an ordinary coin-selection algorithm while removing each selected UTXO from the set available to later batches. The order is part of the candidate. No UTXO may appear in two batches of the same partition.

Repeat allocation with different batch orders, coin-selection randomization, or near-optimal solutions so that each batch can have several candidate coin selections. Reject an allocation unless every batch is balanced: its selected input value must exceed the effective cost of its intended outputs and other mandatory transaction fields.

Positive balance establishes feasibility, not rationality. Before expanding an allocation, reject any batch whose excess implies an unreasonable feerate or whose objective cost can never be offset by its payoff curve. Also reject any choice that the internalized privacy model marks as prohibited, encoded as an infinite privacy liability: by construction such a choice is never rational, regardless of nominal fee savings. Finite privacy harms remain priced terms in the wallet-state valuation and may trade off against other costs.

🤖 3. Recover surplus with change construction

Coin selection generally leaves a positive balance that would otherwise be overpaid in fees. Change construction recovers that value and therefore minimizes the batch’s objective cost.

In the Radix CoinJoin setting, expand each batch into a decision tree of Radix CoinJoin decompositions. Keep at least acceptable decompositions selected uniformly at random when at least exist. A partial decomposition may also be retained when later information is needed to finish it.

In a net-settlement setting, the residual balance may require only an ordinary self-spend output. That produces a degenerate decision tree with one choice and no decomposition decision.

4. Extend outcomes with order book coins

Order book coins that would increase the number of counterfactual paths into the wallet’s new outputs are especially valuable (see Counterfactual paths). However, a co-spend proposal made from the wallet’s input that the paths are added to, naming such a coin, links the two, unless such proposals are already common. An outcome may still prefer such a selection, but the cost function should penalize co-spend proposals that leak the link in this way.

🤖 Such a coin adds paths as a co-input when it descends from the origins of the wallet’s own inputs.

5. Expand leaves into action sequences

🤖 For each surviving outcome, construct one or more sequences of atomic actions that lead from the current wallet state to that leaf. A multiparty batch may require initiating a session, sending co-spend proposals, adding inputs, observing other participants’ inputs, and adding outputs. A fallback batch may instead require constructing and broadcasting a unilateral transaction. Attach the estimated duration and information revealed by each edge.

🤖 When several leaves share an action, factor that action into a common ancestor. Choose the factoring and edge order to preserve options: given each leaf’s bracket, put the least committal and least revealing common actions nearest the root. For example, if one or two coins appear in almost every partition, using them in co-spend proposals can leave more of the generated forest addressable than revealing outputs or committing rarer inputs first.

The coins these outcomes share then guide the structure of the tree, as does each coin’s luck, both now and at the next block, since the randomness beacon can be a block hash at some depth below the tip rather than the tip itself. Actions are scheduled least committal first, so the actions shared by the most outcomes end up nearest the root.

Within a batch, inputs are added before outputs, and signatures come last. Inputs named in co-spend proposals are scheduled early, in particular those compatible with the most favorable outcomes. Auxiliary inputs, which aren’t named in any co-spend proposal, are added using the weight unit credits of these initial inputs. Whether to include them can be decided after observing the other users’ initial inputs, i.e. the full list of UTXOs in the coalition formation proposal.

The expected durations of steps can be annotated along each path. This takes the time dependence of the leaves into account, so that actions are scheduled early enough.

🤖 Time-dependent payoff curves participate in this construction. An action sequence is admissible only if its cumulative estimated duration leaves every dependent branch rational at the time it would be taken. A branch may end in a unilateral fallback when coalition formation outlives an intent’s multiparty window.

🤖 6. Bracket and back up values

Evaluate every leaf under currently available information. A leaf is a pure strategy. The Optimization framework chapter scores it as a family of piecewise linear time-dependent curves, one per term, each flagged as privacy-related or not, evaluated at a point and summed. Objective costs, including blockspace, fees, and change, are normally concrete. A leaf’s wallet state can itself be valued by imagining a unilateral transaction spending all of its coins right after, and taking that transaction’s consolidation penalty and objective costs, as in the Consolidation penalty chapter.

Terms that depend on other participants’ future input or output choices are bracketed:

  • Worst case: no other party contributes value, apart from co-spend adjustments in effect.
  • Best case: every privacy liability is 0. It’s used for pruning.

Back the leaf values up through each action, shifting successor payoff curves by the action’s estimated duration, and adding the immediate action cost at each edge. These backups internalize future consequences, so the action at the root isn’t myopic. Each parent is valued by its tree level expectation, as in the Optimization framework chapter.

Once the wallet commits an action, prune its incompatible siblings. Every action discards parts of the forest, so early actions that preserve many acceptable descendants are preferred.

Small Hamming Weight Denominations for CoinJoins

Standardizing on a small set of denominations has advantages, among other use cases, for privacy in CoinJoin transactions. Instead of creating a single output for an arbitrary amount, a wallet can approximate the amount from below by a sum of standard denominations, and create one output for each denomination in the sum. Each of these outputs is less linkable to the input cluster that funded it.

The fewer denominations there are to choose from, the more likely it is that more than one user chooses any given denomination, which improves privacy. The cost is that more outputs are needed to represent a given balance.

With too few denominations, the approximations also get worse. This notebook quantifies that trade-off. It takes denominations with Hamming weight 1, meaning values with a single nonzero digit in some base, such as powers of 2. It then measures the gaps between consecutive sums of up to such denominations. There are only such values up to sats.

Sub-transaction model and implications for privacy

In the sub-transaction model (1, 2), for every repeated value with multiplicity in the inputs or the outputs of a sub-transaction mapping as a whole, equivalent mappings can be obtained by permutation. Permuting coins of equal value does not change the sum of any sub-transaction, so it preserves the defining property of a sub-transaction: that its inputs minus its outputs sum to (approximately) zero. Permutations within a single sub-transaction do not change which sub-transaction any coin is assigned to, so they yield no new mappings.

In base 2, a value with multiplicity 2 within a single sub-transaction is exchangeable with the next denomination up from some other sub-transaction. Base 3 and 10 have somewhat more complex arithmetic relationships which imply yet more permutations of subsets of coins.

If an arbitrary output value (i.e. with large Hamming weight) can be constructed – or more generally than in Maurer et al, approximated – by summing together distinct denominations, and each of which has multiplicity in the outputs of the sub-transaction mapping as a whole, then the number of equivalent mappings is . This counts permutations over sets of subsets of outputs, specifically when a subset of size is exchanged with a subset of size .

Although this preserves the nominal sum of the sub-transaction, its weight, and therefore its implied fee rate, will differ. A high variance in the implied fee rates of sub-transactions is less likely, so unlike 1:1 exchanges, k:1 exchanges are not perfectly symmetric. Here a sub-transaction’s implied fee rate is the nominal sum of its inputs minus that of its outputs, divided by the weight of the sub-transaction. Users who attempt to recover every last sat are more susceptible to such analysis.

A partition of the inputs and outputs is only a valid sub-transaction mapping if each part’s outputs balance its inputs. When the coins form a dense subset sum instance, almost any group of inputs can be balanced by many groups of outputs, and vice versa. With multiplicities high enough that no single sub-transaction uses every copy of a denomination, the remaining coins stay dense after any one sub-transaction is set aside, so the same holds for the rest of the transaction. Every input and output therefore appears in many distinct sub-transactions across all non-derived mappings.

Radix CoinJoin

It follows that a logarithmic (in the range of values) number of small Hamming weight values with non-trivial multiplicity, taken from a geometric progression, can provide cover for any number of arbitrary valued inputs and outputs. Larger Hamming weight values with multiplicity 1 can of course contribute to subset sum density, but a geometric progression with high multiplicity is much more robust and trivial to analyze.

Ignoring any hypothetical UTXO sharing, the anonymity set size of a CoinJoin transaction is constrained by the number of inputs or the number of outputs (the smaller of the two). Even if the estimated number of distinct sub-transactions in which a coin appears is very large, this only means that the sub-transaction mappings will not be the limiting constraint on anonymity set size for this coin. Therefore even loose lower bounds on this value are sufficient in practice.

Mixed bases and preferred values

If using only a single base, when a small fee cost is subtracted from a single denomination this will result in a remaining balance with a large Hamming weight in that base. To get around this to some extent, values from multiple bases can be used. Additionally, not all Hamming weight 1 values are required, a preferred value series can approximate values well with a smaller number of denominations.

Currency conversions often result in excessively precise bitcoin amounts. In some base , a value will have expected weight . Values which have a small weight in one base usually have a large weight in another, in particular bases 2 and 3. The result of subtracting a value with weight 1 in base 3 from a value with a large weight in base 2 can often have a weight that is smaller by more than 1 (but it may also be higher).

Concretely, the 1-2-5 series in base 10 is useful for representing values with a decimal bias. Base 2 and 3 are suitable for decomposing arbitrary values with a high decimal Hamming weight. They are also complementary to each other: the 1-2 series in base 3 has a high Hamming weight in base 2 and powers of 2 have a high Hamming weight in base 3. These additional values also improve the overall density, reducing the sizes of combinations required for good approximations. Beyond this, additional denominations provide diminishing returns.

As we will see in detail, allowing more outputs improves the density of representable values. Coverage is denser in the interior of the range and becomes sparser towards the upper end, where combinations are limited by the largest available denomination. Raising this denomination limit can improve coverage in the upper region, but does not fill existing gaps between smaller values. With the parameters used here, some gaps still exceed the dust threshold even with six outputs.

This python implementation is optimized for simplicity, not performance or memory use, and the nature of this problem lends itself to precomputation. In an optimized implementation it’s possible to exhaustively enumerate all possibilities even as part of an online computation. This is worth noting because for privacy choosing uniformly at random between an unbiased selection of acceptable choices is better than always picking the best choice according to the cost function. A black box optimization approach may introduce such a bias depending on the cost function.

Parameters

The minimal feerate can be controlled in order to vary the dust threshold.

# bitcoin network parameters
max_sats = 2099999997690000
dust_feerate = 3.0
expected_feerate = 10.0
min_vbytes = 98 # 294 sats @ 3 sat/vb for p2wpkh per https://bitcoin.stackexchange.com/a/41082
dust = int(min_vbytes * dust_feerate)

We will generate denominations from the dust threshold to some maximum value. Setting a large max_denom smooths the gap distribution and emphasizes the gaps between the larger magnitude values, which tend to have smaller relative differences. max_combination_value cuts the sums off at a multiple of max_denom, because larger sums are less informative. A sum above times max_denom needs more than terms, since no term exceeds max_denom, so it effectively has fewer than free terms and the sumset is sparse there.

# denomination parameters
min_denom = dust
max_denom = int(1e8) # reducing this reveals some interesting structure in the plots below
max_combination_size = 6 # 7 is slow but doable, and consumes lots of ram for larger values of max_denom with this naive implementation. results are not very interesting, median gap size is 1 sat.
max_combination_value = max_denom * 2

The final parameters set a cutoff for the smallest gaps. The smallest possible gap is of size 1. Setting a higher cutoff omits negligible gaps (e.g. below dust) improving readability of the individual histograms with regard to larger gaps. Low values aid in comparing between sumset degrees.

# analysis parameters
min_diff = 2 # setting to dust hides small gaps, focusing on more significant ones
min_diff_ratio = 0 # 1e-4 is a basis point

Generate denominations

Denominations are based on preferred value series in base 2, 3, and 10.

# helper functions
def powers(b: int) -> set[int]:
  """
  Generates the powers of the given base up to the maximum denomination.
  Smaller powers are kept, since a multiple of one may still be large enough.
  """
  return { b**i for i in range(int(log(max_denom)/log(b))+1) }

def multiples(vs: set[int], cs: set[int]) -> set[int]:
  """
  Computes the products of pairs of values from two sets.
  """
  return { c*v for (c,v) in product(cs,vs) if c*v in range(min_denom, max_denom+1) }
# denominations of different bases
binary  = multiples(powers(2),  {1})
ternary = multiples(powers(3),  {1,2})
decimal = multiples(powers(10), {1,2,5})
# these additional Hamming weight 2 values plug the proportionally largest gaps
# between the denominations. this has some impact on the decomposition of smaller
# values (max_denom <= 1e6 or so) and so seem appropriate for a future with a
# lower dust feerate, but marginal benefit today

#binary = binary | multiples({3}, { 2**i for i in [ 10, 13, 15, 18 ]})

# the addition of 3 * 2^n arguably over-represents base 2 values
# https://en.wikipedia.org/wiki/Preferred_number#Computer_engineering

#binary  = multiples(powers(2), {1,3})

The combined set of denominations is just a union of these Hamming weight 1 values in these 3 useful bases.

# combined denomination set
combined = binary | ternary | decimal
set value binary (little endian) popcount weight (base 3) weight (base 10)
0 ternary 0.00000486 011001111 6 1 3
1 decimal 0.00000500 001011111 6 4 1
2 binary 0.00000512 0000000001 1 4 3
3 ternary 0.00000729 1001101101 6 1 3
4 decimal 0.00001000 0001011111 6 4 1
5 binary 0.00001024 00000000001 1 6 3
6 ternary 0.00001458 01001101101 6 1 4
7 decimal 0.00002000 00001011111 6 4 1
8 binary 0.00002048 000000000001 1 6 3
9 ternary 0.00002187 110100010001 5 1 4
10 binary 0.00004096 0000000000001 1 7 3
11 ternary 0.00004374 0110100010001 5 1 4
12 decimal 0.00005000 0001000111001 5 6 1
13 ternary 0.00006561 1000010110011 6 1 4
14 binary 0.00008192 00000000000001 1 5 4
15 decimal 0.00010000 00001000111001 5 7 1
16 ternary 0.00013122 01000010110011 6 1 5
17 binary 0.00016384 000000000000001 1 8 5
18 ternary 0.00019683 110001110011001 8 1 5
19 decimal 0.00020000 000001000111001 5 5 1
20 binary 0.00032768 0000000000000001 1 10 5
21 ternary 0.00039366 0110001110011001 8 1 5
22 decimal 0.00050000 0000101011000011 6 9 1
23 ternary 0.00059049 1001010101100111 9 1 4
24 binary 0.00065536 00000000000000001 1 7 5
25 decimal 0.00100000 00000101011000011 6 7 1
26 ternary 0.00118098 01001010101100111 9 1 5
27 binary 0.00131072 000000000000000001 1 9 5
28 ternary 0.00177147 110111111100110101 13 1 6
29 decimal 0.00200000 000000101011000011 6 7 1
30 binary 0.00262144 0000000000000000001 1 9 6
31 ternary 0.00354294 0110111111100110101 13 1 6
32 decimal 0.00500000 0000010010000101111 7 11 1
33 binary 0.00524288 00000000000000000001 1 9 6
34 ternary 0.00531441 10001111110110000001 10 1 6
35 decimal 0.01000000 00000010010000101111 7 9 1
36 binary 0.01048576 000000000000000000001 1 10 6
37 ternary 0.01062882 010001111110110000001 10 1 6
38 ternary 0.01594323 110010111100101000011 11 1 7
39 decimal 0.02000000 000000010010000101111 7 10 1
40 binary 0.02097152 0000000000000000000001 1 11 6
41 ternary 0.03188646 0110010111100101000011 11 1 7
42 binary 0.04194304 00000000000000000000001 1 11 6
43 ternary 0.04782969 10011110110111110001001 14 1 7
44 decimal 0.05000000 00000010110100100011001 8 7 1
45 binary 0.08388608 000000000000000000000001 1 8 6
46 ternary 0.09565938 010011110110111110001001 14 1 7
47 decimal 0.10000000 000000010110100100011001 8 9 1
48 ternary 0.14348907 110101100100111101011011 15 1 7
49 binary 0.16777216 0000000000000000000000001 1 9 8
50 decimal 0.20000000 0000000010110100100011001 8 12 1
51 ternary 0.28697814 0110101100100111101011011 15 1 8
52 binary 0.33554432 00000000000000000000000001 1 7 8
53 ternary 0.43046721 10000010111010110000100101 11 1 7
54 decimal 0.50000000 00000001000011110101111101 12 11 1
55 binary 0.67108864 000000000000000000000000001 1 12 7
56 ternary 0.86093442 010000010111010110000100101 11 1 7
57 decimal 1.00000000 000000001000011110101111101 12 13 1

Generate sumsets

{0} is unioned with the denominations in order to obtain the sumsets from combinations of size as opposed to .

# compute sumsets naively

sumsets = []
for k in range(1, max_combination_size+1):
  subsets = combinations_with_replacement({0} | combined, k)
  sumset = { s for s in map(sum, subsets) if s in range(1,max_combination_value+1) }
  sumsets.append(np.array(sorted(sumset)))
# compute gaps efficiently
gaps = []
for s in sumsets:
  diffs = np.diff(s)
  gaps.append(diffs[diffs >= min_diff])

For the relative gap size, omit gaps below the dust threshold. These gaps are negligible and unrecoverable (since an additional output has a cost), and are therefore noise. To improve clarity of the plots they are filtered out of the relative differences.

# compute normalized gaps efficiently

relative_gaps = []
for s in sumsets:
    diffs = np.diff(s)
    relative_diffs = diffs / s[1:]
    mask = (diffs >= dust) & (relative_diffs >= min_diff_ratio)
    relative_gaps.append(relative_diffs[mask])

Plots

Gaps

Count and sizes

Here we compare the gaps (ignoring gaps of size 1) of the sumsets of different degrees. As larger combinations are permitted the number of distinct sums grows and with them the number of gaps between these sums. Because these values are all in a fixed range, the sizes of the more numerous gaps of sumsets of higher degrees are of course smaller.

Note that for the scatterplots are a little misleading. For there aren’t that many distinct values, so even though these values are smoothly distributed the quantile values aren’t. For several quantiles of the sumset are entirely gaps of size 1. The plot omits those gaps, so its lowest several quantiles are 2 and the next several are 3. The spacings of these in the scatter plot are a visual artifact arising from plotting integer values.

Gap sizes distribution

The next two plots show the gaps in more detail, both their sizes and their sizes in relation to the next larger value. When decomposing into low Hamming weight values, the total balance being decomposed may fall in one of these gaps. The distribution of their sizes bounds the loss from the decomposition. Here too small integer values create visual artifacts, the empty bins for are empty because the populated bins interspersing them correspond to successive integer values.

Relative gap size

The next plot displays gaps larger than the dust threshold as a fraction of the larger value. No quantization artifacts arise in this plot, but there is a cutoff imposed by dividing by values no larger than the maximum combination value.

Sums and combinations

Density of distinct sums

The next plot shows the density of distinct sums in the integers. The previous plots show the gap sizes over the entire range, but not all balances decompose as readily, and towards the end of the range the density tapers off (see max_combination_value parameter). The initial ramp up is determined by the size of the smallest denomination (see also dust_feerate parameter).

This plot gives a clearer indication of the expected loss as a function of the balance being decomposed into a sum of standard values. The distinct constructible sums are assigned into bins (ranges of natural numbers). To plot each bin, this number of distinct values is divided by the size of the bin (number of distinct values, or difference between smallest and largest values).

A density of 1 implies every possible integer value in the bin can be constructed exactly, and a density means every value can be approximated from below with error smaller than the dust threshold.

More intuitively, anything above the dashed line means values can be well approximated often enough that the loss is on average negligible (the cost of an additional output will be higher even at the minimum relay fee). The difference in costs will be linear in , smaller combinations are more efficient representations of a given value but concrete efficiency depends on the feerate, and at higher feerates.

Distinct combinations vs. distinct sums

The following plot displays the possible combinations (as opposed to the distinct sums of the previous plot), which gives an indication for how many ways of constructing a possible sum there are as the combination size increases.

BIP: XXX Privacy PSBT

Abstract

PSBT creation, construction, updating, and signing may all add privacy-sensitive information to PSBTs.

When exchanging (modifiable) PSBTs during construction (BIP 370 or otherwise) or signing with untrusted counterparties, only some fields are necessary to share, and privacy can be harmed significantly if certain fields required for a signing device, for example, are leaked to an untrusted party.

This document specifies what fields can be shared with trusted and untrusted parties such that privacy is preserved.

Rationale

Historically, PSBTs were exchanged only with trusted peers. For example, one owner, one organization, or mutually trusting cosigners. Interactive protocols now pass PSBTs across trust boundaries (payjoin, coordinator-less coinjoin, external combiners). Some protocols, such as BIP 77, explicitly mention what fields should be removed. However, other interactive transaction-construction BIPs either always assume a trusted environment or tacitly assume that clients will remove sensitive information. Without proper specification clients will diverge.

Trust scope

Model the trust scope as a single authorization boundary: every PSBT role inside it may observe the full PSBT, including signing material and wallet-internal metadata. You rely on those parties not to relay that data outside the scope. When a PSBT leaves the scope, hand off only the entries the external role needs for its next step. Scrub every privacy-sensitive field listed below at each trust-boundary crossing unless policy explicitly documents an exception.

If a PSBT re-enters the trust scope, it may regain the fields that were stripped.

Motivating examples

BIP 77/78 example: Payjoin requires the sender to strip derivation fields before responding to their counterparty. The counterparty adds their inputs and outputs, updates with information necessary to sign the PSBT and then strips that information again before responding to the sender. Either party only learns the information needed to complete the protocol.

Multisig example (2-of-3) with a central coordinator and mutually untrusting independent signers: PSBT gets created, coins are selected and outputs are created. The change output includes enough information such that each signer can verify the change is created correctly. The updater creates 3 different PSBTs with signing fields specific to a signer. Signers strip signing fields before distributing back to combiner – they only include a partial signature. Signers do not learn each other’s derivation paths. In case a signer is replaced, they will not be able to identify the wallet’s future outputs based on on-chain information.

BIP 174 manual coinjoin workflow: This is an example of interactive transaction construction between three mutually untrusting wallets. Alice creates the PSBT and adds her inputs; at this point the PSBT should only contain public fields. Bob does the same. Carol adds inputs and signs them. This is not explicitly noted, but signing fields may have been present. Carol (and the other signers) must strip signing fields before returning the PSBT.

Specification

Scrubber Role

Run the scrubber at the trust boundary on the sending side. It reads the in-scope PSBT, copies only the non-sensitive fields defined below into a fresh outbound PSBT, and drops everything else before handoff. The scrubber must sit inside the wallet trust scope: it needs the full PSBT to scrub correctly, and only the scrubbed copy crosses the trust scope.

Fields

We categorize PSBT fields from the BIP 174 type registry by privacy sensitivity. Each table lists the registry name, key type, minimum PSBT version, and the BIP that introduces the field.

Insensitive Fields

These include public fields that the final transaction reveals on-chain.

Some of these fields will always be available on-chain. Others are conditional based on the output type and/or the wallet policy. Those that are optional should not be shared with other signing parties or the combiner. If they are non-optional, they can be shared unconditionally. If a field is non-optional but may not end up on-chain (for example, when witness data exists for multiple spending conditions), the peer before the trust boundary must commit to a spending path and remove witness fields that are unlikely to appear on-chain before handoff. Otherwise a signer may leak additional information about spending conditions that would otherwise be hidden (e.g taptree structure when key-path spending is used).

Global

<keytype>PSBT versionBIP
PSBT_GLOBAL_UNSIGNED_TX = 0x000174
PSBT_GLOBAL_TX_VERSION = 0x022370
PSBT_GLOBAL_FALLBACK_LOCKTIME = 0x032370
PSBT_GLOBAL_INPUT_COUNT = 0x042370
PSBT_GLOBAL_OUTPUT_COUNT = 0x052370

Input

<keytype>PSBT versionBIP
PSBT_IN_NON_WITNESS_UTXO = 0x000, 2174
PSBT_IN_WITNESS_UTXO = 0x010, 2174
PSBT_IN_SIGHASH_TYPE = 0x030, 2174
PSBT_IN_REDEEM_SCRIPT = 0x040, 2174
PSBT_IN_WITNESS_SCRIPT = 0x050, 2174
PSBT_IN_FINAL_SCRIPTSIG = 0x070, 2174
PSBT_IN_FINAL_SCRIPTWITNESS = 0x080, 2174
PSBT_IN_PREVIOUS_TXID = 0x0e2370
PSBT_IN_OUTPUT_INDEX = 0x0f2370
PSBT_IN_SEQUENCE = 0x102370
PSBT_IN_REQUIRED_TIME_LOCKTIME = 0x112370
PSBT_IN_REQUIRED_HEIGHT_LOCKTIME = 0x122370
PSBT_IN_TAP_KEY_SIG = 0x132371
PSBT_IN_TAP_SCRIPT_SIG = 0x142371
PSBT_IN_TAP_LEAF_SCRIPT = 0x152371

Output

<keytype>PSBT versionBIP
PSBT_OUT_AMOUNT = 0x032370
PSBT_OUT_SCRIPT = 0x042370, 375

Internal PSBT Fields

These fields govern internal PSBT logic and can be shared without loss of privacy.

<keytype>PSBT versionBIP
PSBT_GLOBAL_TX_MODIFIABLE = 0x062370
PSBT_GLOBAL_VERSION = 0xFB0, 2174

Sensitive Fields

These include signing fields and metadata a signing party needs to derive keys, identify wallet-controlled outputs, verify wallet policy, or verify protocol-specific rules.

Air-gapped cold signing parties need these fields explicitly because they may not maintain wallet state or derive the required context from another source.

Partial Signatures

The primary privacy concern is revealing which keys have signed and any public keys not already present in script fields; combiners require the signature values to merge.

<keytype>PSBT versionBIP
PSBT_IN_PARTIAL_SIG = 0x020, 2174

Derivation Fields

Untrusted parties that learn an xpub and derivation path can derive previous and future (unhardened) addresses.

<keytype>PSBT versionBIP
PSBT_GLOBAL_XPUB = 0x010, 2174
PSBT_IN_BIP32_DERIVATION = 0x060, 2174
PSBT_OUT_BIP32_DERIVATION = 0x020, 2174
PSBT_IN_TAP_BIP32_DERIVATION = 0x162371
PSBT_OUT_TAP_BIP32_DERIVATION = 0x072371
PSBT_IN_SP_SPEND_BIP32_DERIVATION = 0x1f2376

Proprietary and Unknown Fields

Global, input, and output proprietary and unknown fields are application-defined: their meaning is not specified by the PSBT standards, so a scrubber cannot classify them as safe to retain. By default, remove them before any handoff to an untrusted party.

<keytype>PSBT versionBIP
PSBT_GLOBAL_PROPRIETARY = 0xFC0, 2174
PSBT_IN_PROPRIETARY = 0xFC0, 2174
PSBT_OUT_PROPRIETARY = 0xFC0, 2174
(any unregistered keytype)0, 2—

Pre-images

These fields supply preimages for hash-lock conditions in scripts (HTLCs). TODO: expand rationale.

<keytype>PSBT versionBIP
PSBT_IN_RIPEMD160 = 0x0a0, 2174
PSBT_IN_SHA256 = 0x0b0, 2174
PSBT_IN_HASH160 = 0x0c0, 2174
PSBT_IN_HASH256 = 0x0d0, 2174

Taptree Fields

Taproot hides optional script paths from untrusted parties. Internal key and related fields reveal whether script paths exist.

<keytype>PSBT versionBIP
PSBT_IN_TAP_INTERNAL_KEY = 0x172371
PSBT_IN_TAP_MERKLE_ROOT = 0x182371
PSBT_OUT_TAP_INTERNAL_KEY = 0x052371
PSBT_OUT_TAP_TREE = 0x062371

Output Redeem Script / Witness Script

This data may eventually appear on-chain; revealing it early leaks the spending condition prematurely.

<keytype>PSBT versionBIP
PSBT_OUT_REDEEM_SCRIPT = 0x000, 2174
PSBT_OUT_WITNESS_SCRIPT = 0x010, 2174

MuSig Fields

MuSig2 signing parties necessarily sit in the same trust scope. An untrusted party that learns the other signing parties’ keys can correlate them with the aggregate key and weaken MuSig’s single-key-spend obfuscation.

<keytype>PSBT versionBIP
PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS = 0x1a2373
PSBT_IN_MUSIG2_PUB_NONCE = 0x1b2373
PSBT_IN_MUSIG2_PARTIAL_SIG = 0x1c2373
PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS = 0x082373

Silent Payment Fields

Silent payment fields are sensitive because they reveal that an output is a silent payments output which is meant to be indistinguishable on-chain from a plain P2TR output. Reveal silent-payment fields only across a trust boundary when the protocol requires it.

<keytype>PSBT versionBIP
PSBT_GLOBAL_SP_ECDH_SHARE = 0x072375
PSBT_GLOBAL_SP_DLEQ = 0x082375
PSBT_IN_SP_ECDH_SHARE = 0x1d2375
PSBT_IN_SP_DLEQ = 0x1e2375
PSBT_IN_SP_TWEAK = 0x202376
PSBT_OUT_SP_V0_INFO = 0x092375
PSBT_OUT_SP_V0_LABEL = 0x0a2375

Misc

<keytype>PSBT versionBIP
PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE = 0x092322
PSBT_IN_POR_COMMITMENT = 0x090, 2127
PSBT_OUT_DNSSEC_PROOF = 0x352353

PSBT_GLOBAL_GENERIC_SIGNED_MESSAGE falls into a similar category as proprietary and unknown fields. Depending on the message contents, sharing with untrusted parties may be appropriate, but by default it should be removed.

PSBT_IN_POR_COMMITMENT is meant to be shared only with trusted parties. Signing parties must share their commitment only with trusted parties.

PSBT_OUT_DNSSEC_PROOF creates an identity-to-output mapping and should be shared only with trusted parties.

Modifiable Flag Note

If the inputs- or outputs-modifiable flags are set, the scrubber can still remove individual fields.

Updater: multi-signer case

In cases where multiple untrusting signers are participating in the signing process, the updater must build a separate PSBT per signer and attach only that signer’s required signing fields on each copy.

Sorting

If signers use different libraries with different serialization implementations, an untrusting party can identify the signer by the order in which they encode fields. To prevent this, the scrubber must sort each map lexicographically by key after it removes sensitive fields.

Field transfer sequence

Example: wallet trust scope versus an external combiner. The Creator through Scrubber roles sit in one scope and may handle signing metadata under your internal policy. Scrubber to Combiner is the trust-boundary crossing: the scrubber builds the outbound PSBT copy that keeps only what merge needs (typically the public transaction skeleton plus that signing party’s partial witness material) and drops every other privacy-sensitive field listed below.

External to wallet trust scopeWallet trust scopeExtractorFinalizerCombinerScrubberSignerUpdaterConstructorCreatorExtractorFinalizerCombinerScrubberSignerUpdaterConstructorCreatorScrubber stays inside the wallet trust scope and may read the full PSBT.Trust boundary. Outbound copy omits sensitive fields.Extract broadcast-ready transactionEmpty PSBTPublic transaction fieldsPublic transaction fieldsSigning fields scoped to this signerPSBT with signing metadata and partial witnessPublic transaction fieldsPartial witness fields for mergePublic transaction fieldsCombined partial witness fieldsFinalization fields
External to wallet trust scopeWallet trust scopeExtractorFinalizerCombinerScrubberSignerUpdaterConstructorCreatorExtractorFinalizerCombinerScrubberSignerUpdaterConstructorCreatorScrubber stays inside the wallet trust scope and may read the full PSBT.Trust boundary. Outbound copy omits sensitive fields.Extract broadcast-ready transactionEmpty PSBTPublic transaction fieldsPublic transaction fieldsSigning fields scoped to this signerPSBT with signing metadata and partial witnessPublic transaction fieldsPartial witness fields for mergePublic transaction fieldsCombined partial witness fieldsFinalization fields

Example: 2-of-3 with two co-owner signing parties in the wallet trust scope and a third recovery signing party outside it, as in BIP 89 chain-code delegation. Co-owners receive full signing metadata inside the scope. The recovery party acts as delegator and must not receive other parties’ derivation paths, public keys, or partial signatures. The updater builds a separate PSBT copy per signing party.

BIP 89 delegator outside scopeWallet trust scopeSignerCCombinerScrubberSignerBSignerAUpdaterConstructorCreatorSignerCCombinerScrubberSignerBSignerAUpdaterConstructorCreatorCo-owners stay in scope. One party may act as BIP 89 delegatee.Omit other signing parties' derivations and partial signatures.Trust boundary. Delegator sees only per-spend signing context.Combiner is trusted. Co-owners need not scrub for merge.Empty PSBTPublic transaction fieldsPSBT copy, public fields and signing metadataPSBT copy, public fields and signing metadataPSBT copy scoped to SignerCScrubbed PSBT and CCD tweak bundlePartial witness from SignerCPartial witness from SignerAPartial witness from SignerBMerge partial witnesses
BIP 89 delegator outside scopeWallet trust scopeSignerCCombinerScrubberSignerBSignerAUpdaterConstructorCreatorSignerCCombinerScrubberSignerBSignerAUpdaterConstructorCreatorCo-owners stay in scope. One party may act as BIP 89 delegatee.Omit other signing parties' derivations and partial signatures.Trust boundary. Delegator sees only per-spend signing context.Combiner is trusted. Co-owners need not scrub for merge.Empty PSBTPublic transaction fieldsPSBT copy, public fields and signing metadataPSBT copy, public fields and signing metadataPSBT copy scoped to SignerCScrubbed PSBT and CCD tweak bundlePartial witness from SignerCPartial witness from SignerAPartial witness from SignerBMerge partial witnesses

Reference Implementation

https://github.com/arminsabouri/rust-psbt/tree/scrubber-role

Test Vectors

A collection of test vectors is provided. Each test vector contains an input PSBT and an expected PSBT after the scrubber role has run. Both PSBTs are in base64 format.

Concurrent PSBT Construction

Abstract

New fields and rules for combining PSBTs in a distributed setting. This provides an alternative to the BIP 370 constructor role that is less sensitive to order of operations and therefore more amenable to concurrency, which reduces the coordination required for collaborative transaction construction.

Motivation

BIP 174 defines Combiner functionality. Its purpose is to integrate information add by either the Updater or Signer roles to divergent copies of a PSBT. According to the specification the combiner is intended for for PSBTs whose underlying unsigned transactions are identical, i.e. it is restricted to the Updater and Signer roles.

BIP 370 introduced a Constructor role, which allows signalling that the inputs or outputs of a PSBT are modifiable. Arbitrary mutation of the inputs and outputs is then allowed, but this assumes such state updates are done sequentially. The combiner role is mostly unchanged in BIP 370, and is restricted to only allow combining fields of PSBTs which spend and create the same outputs, and in the same order. This facilitates aggregating signatures from multiple parties in any order, but has limited usefulness during the construction of the PSBT.

In a distributed system it is easier to deliver messages without guaranteeing the order of delivery is consistent across nodes. Agreement on the set of outputs to spend and a set of outputs to create is sufficient for constructing a transaction, it isn’t necessary to agree on the order in which they were added. This document defines an order insensitive merging procedure which generalizes the Combiner role to non-identical modifiable PSBTs which may still overlap in some of their data. To terminate concurrent transaction construction, a consistent ordering procedure is also defined for producing a a consistent PSBT which can subsequently be manipulated using the normal BIP 174 roles.

Specification

TODO diagram for the combined state machine, indicate when downconversion (to v2 or v0) can happen

creator -> constructor<modifiable, unordered> -> constructor<modifiable> (bip 370) -> updater -> signer -> combiner -> finalizer -> extractor

TODO discuss scrubbing after signer and before combiner

The new field types for distributed PSBT construction are as follows:

New global types

Namekeytypekeydatakeydata Descriptionvaluedatavaluedata Description
Transaction Unordered FlagPSBT_GLOBAL_TX_UNORDERED = TBDNoneNo key data<8-bit uint>If present, must be set to a value 0x03 to indicate inputs and outputs are unordered.
Sort SeedPSBT_GLOBAL_SORT_SEED = TBDNoneNo key data<bytes globalseed>Random seed used to derive deterministic sort keys when explicit per-map sort keys are absent.
Deterministic Sort FlagPSBT_GLOBAL_SORT_DETERMINISTIC = TBDNoneNo key data<8-bit uint>A value of 0x01 indicates sort keys must be deterministically derived and explicit PSBT_IN_SORT_KEY / PSBT_OUT_SORT_KEY fields are disallowed. A value of 0x00 indicates sort keys are required and PSBT_GLOBAL_SORT_SEED is disallowed.
Removed InputPSBT_GLOBAL_REMOVED_INPUT = TBD<bytes input unique id>PSBT_IN_UNIQUE_ID of an input removed from the logical input set.NoneNo value data.
Removed OutputPSBT_GLOBAL_REMOVED_OUTPUT = TBD<bytes output unique id>PSBT_OUT_UNIQUE_ID removed from the logical output set.NoneNo value data.

New per-input types

Namekeytypekeydatakeydata Descriptionvaluedatavaluedata Description
Input Sort KeyPSBT_IN_SORT_KEY = TBDNoneNo key data<bytes sort key>Arbitrary lexicographically comparable value used to order inputs.
Input Unique IDPSBT_IN_UNIQUE_ID = TBDNoneNo key data<bytes unique id>Optional unique suffix for outpoint identity, used for input removal extensions.

New per-output types

Namekeytypekeydatakeydata Descriptionvaluedatavaluedata Description
Output Unique IDPSBT_OUT_UNIQUE_ID = TBDNoneNo key data<bytes unique id>Universally unique identifier for output map identity under unordered output semantics.
Output Sort KeyPSBT_OUT_SORT_KEY = TBDNoneNo key data<bytes sort key>Arbitrary lexicographically comparable value used to order outputs when transitioning from unordered to ordered mode.

PSBT identity and transaction effects

The BIP 174 Combiner role specifies how to merge diverging copies of the same PSBT. PSBTs are considered “the same”, by identifying them based on the unsigned transaction. Two PSBTs with the same unsigned transaction but potentially different key value pairs are considered two versions of the same PSBT.

BIP 370 introduces the notion of a unique ID which is computed as a hash that commits to UTXOs being spent and the new outputs being created, thereby ensuring PSBTs with the same ID have the same structure, but abstracting away some details of the transaction, thereby introducing a notion of equivalence that is a bit more general.

The effects of a transaction on the distribution of money are determined by its effects the UTXO set: which outputs does it spend and create. However, with regards to money changing hands, we would like to treat equivalent outputs as interchangeable by disregarding the specific outpoints by which specific coins are identified.

Both notions of identity ensure that PSBTs with the same ID have the same effects, but it is not true that PSBTs with the same effects will have the same ID, since depends on the specific order of the inputs and outputs, among other things. By abstracting over these details we obtain a more general notion of PSBT identity than in BIP 370. The details of how to compute this ID are provided below.

Combiner role and transaction effects

The BIP 174 Combiner role requires that the PSBTs have the same identity. In order to relax this constraint and allow the Combiner role to be used in conjunction with (a more general notion of) the Constructor role, the Combiner role has to be made more conservative in other regards.

BIP 174 specifies that fields with duplicate keys and more than one distinct value may be combined by picking one of the values arbitrarily. This is safe within the scope of BIP 174 because any inconsistency will only affect the validity of a transaction. In other words, when choosing one value over another for a duplicate field, although signing may fail to produce a valid signature, no money will be lost because if the IDs are the same, the the effects are identical.

This notion of safety can be extend beyond just combining signing related data, so that effects of a transaction formed by combining PSBTs do not depend in any way on the order in which the PSBTs were combined, nor even on combination being done sequentially. Note that this does not require that the effects of the constituent PSBT be identical, only that all of them are combined at some point. More formally, in order to be safe, combining should be monotone in the transaction effects.

Unfortunately choosing between conflicting values arbitrarily does not preserve this notion of safety when merging PSBTs where the inputs or outputs of one PSBT don’t correspond to the inputs or outputs which occupy the same positions in the second PSBT. For example, if the first inputs of two PSBTs spend different coins, and one PSBT takes precedence, the input in the other transaction will be omitted. If the PSBT_IN_PREVIOUS_TXID field of one PSBT overrides the other but this precedence is reversed for PSBT_IN_OUTPUT_INDEX, the one remaining input will be corrupted.

joinpsbts vs. the Combiner role

Bitcoin Core additionally implements a joinpsbts RPC command which does allow merging PSBTs with different identities, so long as their spent output sets are disjoint.

joinpsbts is not idempotent with respect to inputs (writing it as , idempotence would mean that ). Attempting to join a PSBT more than once fails closed: if contains an input, and is defined, then will fail, because a transaction cannot spend the same coin twice.

joinpsbts is also not idempotent with respect to the outputs, but unfortunately also does not fail closed, potentially leading to overspending: if contains just an output, then will contain two copies of that output.

Although not strictly associative or commutative, due to use of shuffling, in regards to transaction effects it does hold that and that .

Strict Combiner

In order for combination being deterministic, idempotent and commutative and associative in regards to transaction effects, when either bits 0 or 1 of PSBT_GLOBAL_TX_MODIFIABLE are set, indicating the transaction is modifiable, instead of choosing arbitrarily the strict Combiner MUST fail whenever duplicate fields have conflicting (unequal) values.

Exceptions to this are detailed in the next sections, preserving idempotence, commutativity and associativity.

This establishes a more conservative foundation for ensuring that the effects of a transaction formed by combining a set of PSBTs will always be the same regardless how these PSBTs were combined to obtain a complete transaction.

Unordered input and output sets

Since transaction effects are invariant under permutations of the inputs or outputs, treating the inputs and outputs as unordered sets as opposed to order lists allows safe combining to be defined for PSBTs that are not identical.

To represent this we define a global field PSBT_GLOBAL_TX_UNORDERED, indicating whether the order of inputs and outputs should be ignored. The value is an unsigned 8 bit integer and if present must be set to 0x03, indicating the transaction in unordered.

Rationale: Since there is no known use case that requires input or output to be marked unordered or ordered separately from each other, that is omitted from the spec. The value 0x03 simplifies forward compatibility with any specification that might amend this by allowing either bit to be set independently, so long as it overlaps with this specification when both are set.

If set, the Has SIGHASH_SINGLE flag of PSBT_GLOBAL_TX_MODIFIABLE must not be set. SIGHASH_SINGLE inputs MUST not be used in unordered transactions.

Unordered PSBTs MUST be shuffled prior to reserialization. This is easily accomplished by storing them in randomized hashmaps, keyed by their unique identifiers as defined below. If all inputs and outputs have sort keys, the key based ordering may be used instead of shuffling.

[fn:Join is implicitly defined on equivalence class of all permutations of inputs/outputs, but the PSBT contents is a random representative.

Rationale: Not shuffling presents a privacy hazard, leaking information about the sequence of actions leading to a transaction’s construction. When a transaction is unordered, shuffling by definition doesn’t change its meaning, but ensures the incidental order can’t accidentally be relied upon.

Combining PSBTs with different identities

When PSBT_GLOBAL_TX_UNORDERED is set, the input or output maps are no longer distinguished by their index, but instead by a unique identifier defined for each input or output.

Inputs or outputs with identical unique IDs (those which are present in both PSBTs) are merged by combining their key-value pairs with the stricter, idempotent combination defined above.

These sets of combined inputs and outputs are then unioned with any inputs or outputs from that have distinct unique identifiers (i.e. are only present in one of the PSBTs, and therefore aren’t combined with a counterparts). Distinct identifiers are only allowed if the corresponding PSBT_GLOBAL_TX_MODIFIABLE flag is set, because such combinations represent additions of inputs or outputs. If this is not the case but a distinct input or output is present, then combining must fail.

Unique identifiers for inputs

Inputs are identified by their outpoint, i.e. the tuple of their PSBT_IN_PREVIOUS_TXID and PSBT_IN_OUTPUT_INDEX, both of which must be set.

Unique identifiers for outputs

Outputs are identified by a new PSBT_OUT_UNIQUE_ID field, which must be universally unique (e.g. 16 bytes of randomness).

This ensures that repeated addition of the same output is idempotent, but that if two different distributed constructors both attempt to add an identical output (same PSBT_OUT_VALUE and PSBT_OUT_SCRIPT), that will still result in two copies of the output as intended. This is important because a transaction with only a single copy will appear correct but end up losing the value of all missing copies to mining fees.

Outputs with an identical PSBT_OUT_SCRIPT can be merged, and their values summed together after PSBT_GLOBAL_TX_UNORDERED is cleared and an order is determined, using BIP 370 construction rules. See the next section on ordering.

Ordering inputs and outputs

  • TODO: unique ID can be derived by sorting even if sort key is empty, but txn finalization must not be unless all sort keys are provided explicitly (regardless of DETERMINISTIC)
  • add section for unique ID derivation a la BIP 370

Clearing the PSBT_GLOBAL_TX_UNORDERED field indicates the order of the inputs and outputs. Due to the shuffling requirement, the given order will in general not be consistent across replicas if this is done without determining an order, resulting in diverging unsigned transactions.

For consistent ordering we define PSBT_IN_SORT_KEY and PSBT_OUT_SORT_KEY fields for inputs and outputs respectively, that may include up to 32 bytes of arbitrary data, used as a sort key for lexicographical sorting.

If the global field PSBT_GLOBAL_SORT_DETERMINISTIC is set (unsigned 8 bit integer) to 0x01, then sort keys MUST NOT be set, and PSBT_GLOBAL_SORT_SEED MUST be set and contain at least 128 bits of randomness.

If PSBT_GLOBAL_SORT_DETERMINISTIC is set to 0x00, explicit sort keys are required to be set and used prior to clearing the PSBT_GLOBAL_TX_UNORDERED field and fixing the transaction order.

If any PSBT_IN_SORT_KEY and PSBT_OUT_SORT_KEY are omitted, the global PSBT_GLOBAL_SORT_SEED field is set, and PSBT_GLOBAL_SORT_DETERMINISTIC is either omitted or set to 0x01, the sort keys are derived deterministically. A missing PSBT_IN_SORT_KEY is derived as H(PSBT_GLOBAL_SORT_SEED || PSBT_IN_PREVIOUS_TXID || PSBT_IN_OUTPUT_INDEX) and PSBT_OUT_SORT_KEY as H(PSBT_GLOBAL_SORT_SEED || PSBT_OUT_UNIQUE_ID), where H_s is a BIP 341 style tagged hash, with the tag preimage being BIP ???? deterministic ordering (TODO pick a real domain separator).

If any sort key is missing, ordering can only proceed after PSBT_GLOBAL_SORT_SEED is set.

A Creator creating an unordered transaction SHOULD set PSBT_GLOBAL_SORT_DETERMINISTIC to ensure consistent ordering rules are enforced.

For sufficiently large transactions the ordering itself (and therefore the per input signatures) is a cryptographically binding commitment to the PSBT_GLOBAL_SORT_SEED value. This is because the entropy of the ordering of elements is . For reference, , , and .

This can provides additional integrity to a collaborative transaction construction protocol, since SIGHASH_ALL signatures must agree on the ordering.

In applications where this is desirable, the Creator should only set PSBT_GLOBAL_SORT_DETERMINISTIC to 0x01, and leave PSBT_GLOBAL_SORT_SEED unset. Each replica will locally provide a value for PSBT_GLOBAL_SORT_SEED just in time, as a commitment to protocol transcript (e.g. the root hash of a Merkle set of protocol messages).

If that is not the case, the Creator should initialize PSBT_GLOBAL_SORT_SEED with sufficient randomness thereby ensure some order can always be determined, or set PSBT_GLOBAL_SORT_DETERMINISTIC to 0x00 to indicate explicit sort keys are required..

TODO global sort seed || hash of fee contributions or expect application to commit to that in transcript if appropriate?

TODO: Rationale for allowing explicit sort key: lightning interactive-tx serial_id field. should always use odd parity form, encoded in network order so that lexicographical sorting works the same as the interactive-tx sorting rule.

Unique identification of unordered PSBTs

In order to derive unique IDs as in BIP 370 for unordered transactions, the PSBT_GLOBAL_SORT_SEED and PSBT_IN_SORT_KEY and PSBT_OUT_SORT_KEY fields are cleared, and then the ordering procedure of the previous section is used without the restriction of a non-empty PSBT_GLOBAL_SORT_SEED (sorting with an empty seed).

TODO: domain separation from PSBT v2, it doesn’t make sense to treat an ordered BIP 370 PSBT as the same PSBT even if it agrees on its content when it doesn’t agree that the order is meaningless. how to do this? hashing output unique IDs of outputs is insufficient for domain separation of input only partially constructed PSBTs, but maybe that’s OK.

Divergence and SIGHASH flags

Signers MUST sign only using SIGHASH_ALL.

If SIGHASH_ANYONECANPAY or SIGHASH_NONE is used by a signer, the signature is valid for an (ill defined) equivalence class of transactions, with non-equivalent transaction effects.

At minimum any such signature could lead to txid malleability, and so is not composable with any protocol that requires pre-signed descendant transactions.

Furthermore, members of this equivalence class of transactions may differ substantially in their effects, potentially leading to loss of funds, not only due to byzantine faults but even omission faults. To ensure undesired transactions are not inadvertently authorized, the full output list should always be committed to using SIGHASH_ALL.

Rationale: No known use cases for such flags in true multiparty transactions (i.e. three or more parties). If necessary, a carve out can be specified in a separate document (e.g. for kickstarter-style crowdfunding with SIGHASH_ANYONECANPAY|SIGHASH_ALL signing).

Confirmation of successful payment prior to signing

Parties which neither send nor receive payments within a transaction can safely sign so long as all of their intended outputs are covered by the input signature. This may require signing more than once if some messages are delayed, but TODO see also termination via explicit fee contributions.

If there is any net transfer between the parties, it is insufficient for a sender (any party that makes an outgoing payment to another party within the transaction regardless of their net send/receive balance) to rely only on the signature committing to the outputs they added, because some of their funds will be used by other parties and their actions need to have been registered as well.

Before signing, every sender must wait until it has positive confirmation of the PSBT’s unique ID (which commits to the full output set) from every one of its receivers, and that in every case the confirmed ID matches the one they derive locally.

Every receiver whose net balance is non-negative (they may be a sender too but they receive at least as much as they send) can confirm the unique PSBT ID to their respective senders output set contains all of their added outputs.

Every receiver whose balance is net negative (they send more than they receive) must wait for confirmation from all receivers for whom it is a sender before it confirms the unique ID to the senders for whom it is a receiver.

If there is a cyclic payment graph, for example Alice pays Bob, Bob pays Carol, and Carol pays Alice, net positive receivers can safely initiate confirmations, breaking the circular dependency, because senders will sign will only occur after all receivers have confirmed and if all net positive receivers have confirmed then all funds are accounted for. At least one such node must exist in every cyclic payment structure, since the sum of the payments along a cycle will be 0.

If there is any mismatch in the confirmations, either the receiver or the sender has not yet received the full message set. If a receiver learns of an additional input or output after previously confirming, they must confirm the new unique ID which incorporates this additional data. If a sender learns of an additional input or output, they can derive a new unique ID, and stop waiting if this matches all of their receivers’ confirmations.

Such a confirmation mechanism does not require an agreement or consensus mechanism, only eventual consistency. If messages are guaranteed to be delivered eventually then every receiver will eventually confirm a consistent least upper bound.

TODO sender/receiver examples, including an example with a receiver that contributes no inputs, only outputs

TODO net-sender, net-receiver, explain in terms of breaking cyclic graph to a tree with net-receivers at the leaves, propagate confirmation up the chain.

Input or output removal (optional)

As in BIP 174, the combination of several PSBTs must contain all the key-value pairs from each of the input PSBTs.

If support for removal of inputs and outputs is needed, two global fields PSBT_GLOBAL_REMOVED_INPUT and PSBT_GLOBAL_REMOVED_OUTPUT can be used to represent a two phase set by specifying the inputs or outputs to be removed in the keydata. Inputs or outputs whose unique IDs are specified must be pruned from the input or output.

Because inputs are identified by outpoint, an input spending the same coin as an input whose outpoint is in the set of removed inputs can’t normally be added. Therefore we introduce an optional PSBT_IN_UNIQUE_ID field, whose value (if provided) is appended to the outpoint.

Support for removal is entirely optional. Implementations may explicitly fail when combining with a PSBT that sets either PSBT_GLOBAL_REMOVED_INPUT or PSBT_GLOBAL_REMOVED_OUTPUT, but completely ignoring these fields is fail safe.

Assuming SIGHASH_ALL is used, it’s sufficient to simply rely on the signature hashing. If an output was removed, a peer which does not implement removal it will diverge from those that do, and therefore produce a signature that will not be valid for the transaction supporting peers will produce and subsequently sign, and vice versa, ensuring that neither transaction is valid.

This optionality extends the PSBT_IN_UNIQUE_ID field, a removal and re-insertion with incompatible data will either cause combination to fail due to a mismatch or succeed by ignoring the removal and treating the insertion as idempotent, but otherwise diverge.

While this would allow limited interoperability among clients, that is not recommended, and is described as an argument for the safety of omitting any removal related functionality. Implementations which omit removal functionality SHOULD fail or at least warn if combining a PSBT that signals removal.

TODO: while combine is monotone of data / PSBT fields including removals, it is no longer monotone in transaction effects. This does not present a safety issue if only SIGHASH_ALL is used.

Rationale for optionality: not implementing is safe, couldn’t find usage of tx_remove_{input,output}, non-monotonic state makes termination / limits trickier.

TODO for interactive-tx, set PSBT_IN_UNIQUE_ID to odd parity serial_id. this makes it possible to support tx_remove_{input,output} operations.

PSBT CRDT (optional)

In some circumstances a conflict free replicated data type (CRDT) can be defined as a subtype of (unordered) PSBTs. In a CRDT, in addition to being idempotent, commutative and associative, combination is additionally guaranteed to succeed.

Success here means producing a useful output, which ideally would guarantee a transaction that would be valid if fully signed, which also conforms to standardness policy. This can only be guaranteed under assumptions that must be realized by some additional protocol, beyond the scope of this document.

Mutually exclusive inputs

Two OP_CLTV encumbered coins, one with a height based and one with a time based nLocktime constraint will impose mutually exclusive validity requirements on their spending transactions, and therefore cannot be spent together in the same transaction.

In order to ensure the least upper bound of any two inputs under consideration not only can be defined, but will correspond to a valid transaction, the Creator role can restrict the domain of spendable inputs before inputs are added.

TODO PSBT_GLOBAL_{REQUIRED,MAXIMUM}_{HEIGHT,TIME}_LOCKTIME height and time separately or just integer range? separately is consistent with other PSBT specs. a single nlocktime interval field with two unsigned integers, required and max-required would make many invalid states unrepresentable, but is more fiddly and unfamiliar.

Size Limits

advisory fields: MAX_WEIGHT_PER_PARTICIPANT, MAX_TRANSACTION_WEIGHT (default 400000?) - determines max number of participants while also signalling size limit is enforced

if every participant effectively restricts the domain by respecting the limit the least upper bound is guaranteed not to exceed the limit making the join valid.

assumes the number of participants can be restricted via some external mechanism.

Termination

knowing when to proceed to signing

  • global fee contribution
    • PSBT_GLOBAL_EXPLICIT_FEE_CONTRIBUTION
    • keydata = 16 byte uuid
    • value = u64 amount of funds explicitly contributed as fees
    • needs PSBT_IN_NON_WITNESS_UTXO or PSBT_IN_WITNESS_UTXO for nominal value
    • effective values/costs would a specific feerate and input size estimation, instead all such fee contributions should also be added (but can be computed deterministically in case this is known)

inputs before outputs? only rely on payment ACKs

Rationale

Backwards Compatibility

Reference Implementation


TODO

  • new PSBT version?

    • con: new PSBT version pro: deserializing unordered txns in psbtv2 will error instead of potentially leaking unshuffled input/output order
  • Move inline rationales to their own section

  • BIP 174 describes how to aggregate signatures via combiner. example includes a manual coinjoin flow, joining of PSBTs not defined in the spec. technically this involves two different PSBTs. discuss what happens when not sequential, as well as conceptual issues.


  • discuss liveness. safety WRT transaction effects is nice but we also want to minimize irrecoverable failures. discuss both generally and in CRDT section.