diff --git a/.gitignore b/.gitignore index 8dade17..11e0883 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ book/ result +.ipynb_checkpoints/ diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 0000000..6aacb5b --- /dev/null +++ b/.typos.toml @@ -0,0 +1,14 @@ +[default.extend-identifiers] +# Mermaid class for Alice's cluster in the intersection diagram. +aci = "aci" +# Author of The Byzantine Generals Problem. +Pease = "Pease" +# Author of Asymmetric Distributed Trust. +Cachin = "Cachin" +# Single-use reply blocks. +SURB = "SURB" +SURBs = "SURBs" + +[default.extend-words] +# Groth16, the proof system named after Jens Groth. +Groth = "Groth" diff --git a/README.md b/README.md index 38856fe..48ca09a 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,50 @@ # Fungi -This repository contains documents that describe a family collaborative Bitcoin transaction construction protocols. The protocols form a progression towards decentralized and market based privacy preserving transactions. +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](https://github.com/fungi-protocol/fungi). This repository contains the specifications and the analysis behind them. > [!NOTE] -> **Work in progress**: most chapters are still under review. See the [open pull requests](https://github.com/fungi-protocol/docs/pulls) for material being drafted. +> **Work in progress**: most chapters are drafts under review. See the [open pull requests](https://github.com/fungi-protocol/docs/pulls) for material being drafted. + +## 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. -## Fungi protocol suite +## Problem statement -### Honest setting +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. -The *honest* setting assumes all participants can be trusted in two ways: +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 $n-1$ deanonymization attack, where the adversary controls all of the other (apparent) participants, is a sufficient deterrent. -- not to disrupt the execution of the protocol -- with privacy, which means not revealing to the adversary, ideally forgetting, any information that may be revealed by participants in the course of the protocol's execution +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. -In this as well as subsequent protocol, trust never means giving up control over one's funds. Input signatures in transactions enforce this safety by letting each party ensure its , requiring unanimous consent by all parties. +The [problem definition](docs/collaborative_txn_privacy.md) chapter discusses these on-chain privacy leaks in depth, and describes a particular transaction graph structure that resists deanonymization more robustly. -### Semi-honest setting +## How Fungi works -In the *semi-honest* setting, also known as *honest-but-curious*, we no longer assume peers have to be trusted to keep a secret. Instead this relies on privacy preserving transports for the communication, that allow a peer to broadcast its messages anonymously to the other participants. Because Bitcoin transactions are transparent, privacy further demands a more careful approach to transaction construction, or the actions of a peer may be revealing even if not directly attributable. +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 semi-honest setting can provide some degree of confidentiality, especially against 3rd party observers, through the construction of net settlement transactions. But not anonymity. Transactions between peers that are somehow related have inherent privacy issues because such relationships constitute a social network, exhibiting community structure. +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. -### Byzantine fault tolerant setting +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. -Overcoming the community analysis concern requires a Sybil resistant, permissionless protocol where peers with no meaningful economic relationship can find each other. This involves an additional *coalition formation* protocol that sets up transaction construction using a market based mechanism. +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. -While it is beneficial for privacy, interacting with strangers in a permissionless protocol invites disruption or attempts at surveillance. For honest peers to be able to reliably transact, especially with the unanimity requirement, demands a byzantine fault tolerance from the transaction construction protocol. +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. -In the course of a BFT interaction with untrusted peers, a participant may still use the other variants of the protocol to coordinate activity with the subset of peers they do know or trust, for instance by performing net-settlement within a larger BFT CoinJoin. +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. -## Motivation +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. -Wallet clustering is the broad term for a variety of techniques that can be used to deanonymize on chain activity. Clustering involves linking particular coins to one another, attributing their ownership to the same entity. Over the course of Bitcoin's existence many papers have been published on this subject, also about related privacy issues issues, such as Lightning network, or the transport layer. +## Compared to JoinMarket -This body of work has, time and again, shown that misconceptions about privacy invariably err on the side of optimism. Moreover, depending on individual users' threat models, their adversary may have access to comprehensive auxiliary information. Such auxiliary information doesn't even need to be about the target user, information about other users may be useful for deanonymization of the target user. In cryptography, rotating long lived keys or favoring ephemeral ones can limit the scope of a compromise, but an individual's identity is who they are. +Fungi could be described as a spiritual successor to JoinMarket (as implemented by [JoinMarket](https://github.com/JoinMarket-Org/joinmarket-clientserver) and [JoinMarket-NG](https://github.com/joinmarket-ng/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. -The fungi protocol suite is designed to make arbitrary transactions possible between mutually consenting but distrusting peers. This means safety, liveness, and unlinkability of protocol messages. Within such a protocol peers are free to pursue whatever outcomes they desire. +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. -Privacy does not simply emerge naturally from collaborative transactions. Peers must actively optimize for that. Optimization involves the use of a cost function, an extension or generalization of the kind used for coin selection. This repository makes specific recommendations with which the protocols are designed to be compatible. The recommended privacy related terms address Sybil resistance, the transaction structure (for example how output values are chosen in relation to others' input values) and the graph structure. +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. diff --git a/book.toml b/book.toml index 0b88649..caff386 100644 --- a/book.toml +++ b/book.toml @@ -6,6 +6,11 @@ src = "src" [build] create-missing = false +[preprocessor.jupyter] +command = "python3 contrib/jupyter_nb.py" +after = ["links"] +before = ["graphviz", "mermaid", "katex"] + [preprocessor.graphviz] command = "mdbook-graphviz" after = ["links"] @@ -17,8 +22,11 @@ after = ["links", "graphviz"] [preprocessor.katex] command = "mdbook-katex" after = ["links"] +# mdbook-graphviz re-serializes the markdown, escaping the TeX source. +before = ["graphviz"] [output.html] additional-css = ["theme/diagrams.css"] git-repository-url = "https://github.com/fungi-protocol/docs" -site-url = "/docs/" +site-url = "/docs-draft/" +additional-js = ["theme/nb-table.js"] diff --git a/contrib/book.py b/contrib/book.py index 1cf9b79..952da45 100644 --- a/contrib/book.py +++ b/contrib/book.py @@ -4,14 +4,19 @@ docs/index.md, the bundle's OKF index, states the chapter order: its headings become the parts of SUMMARY.md and its entries the chapters, without their descriptions, so an entry must name a chapter, by a path -relative to docs/, and every chapter must have an entry. The README is -the introduction, and the index, with its descriptions, is the contents -page. Frontmatter is checked and then dropped, as mdbook would render it -as text. The bundle's other files are copied as they are. +relative to docs/, and every chapter must have an entry. An entry +indented two spaces more than the entry above it is a sub-chapter of +that entry. The README is the introduction, and the index, with its +descriptions, is the contents page. Frontmatter is checked and then +dropped, as mdbook would render it as text. Chapters are markdown pages +and Jupyter notebooks, whose frontmatter is a raw cell that opens them. +The bundle's other files are copied as they are, except for Jupyter's +autosaves. python3 book.py ROOT """ import argparse +import json import posixpath import re import shutil @@ -21,7 +26,7 @@ import yaml FRONTMATTER = re.compile(r"\A---\n(.*?)\n---[ \t]*(?:\n+|\Z)", re.DOTALL) -ENTRY = re.compile(r"\* \[([^\]]+)\]\(([^)\s]+)\)(?: - .*)?") +ENTRY = re.compile(r"( *)\* \[([^\]]+)\]\(([^)\s]+)\)(?: - .*)?") DOCS = "docs" # As set in book.toml. SRC = "src" @@ -29,12 +34,35 @@ GENERATED = ("README.md", "SUMMARY.md", CONTENTS) STATUSES = ("draft", "stable", "deprecated") RESERVED = ("index.md", "log.md") +NOTEBOOK = ".ipynb" +CHECKPOINTS = ".ipynb_checkpoints" +# A sub-chapter's entry is indented this much more than its chapter's. +INDENT = " " def strip_frontmatter(text): return FRONTMATTER.sub("", text, count=1) +def notebook_frontmatter(text): + """A notebook's frontmatter, as a markdown page would have it, if a + raw cell holding nothing else opens it, and the notebook without it.""" + nb = json.loads(text) + cells = nb.get("cells", []) + if cells and cells[0].get("cell_type") == "raw": + head = "".join(cells[0].get("source", [])) + if FRONTMATTER.fullmatch(head): + nb["cells"] = cells[1:] + return head, json.dumps(nb, indent=1, ensure_ascii=False) + "\n" + return "", text + + +def body(name, text): + if name.endswith(NOTEBOOK): + return notebook_frontmatter(text)[1] + return strip_frontmatter(text) + + def frontmatter(text): m = FRONTMATTER.match(text) fields = yaml.safe_load(m.group(1)) if m else None @@ -47,6 +75,8 @@ def check(name, text): has passed is not checked, so that a build does not depend on when it runs.""" try: + if name.endswith(NOTEBOOK): + text = notebook_frontmatter(text)[0] fields = frontmatter(text) except (yaml.YAMLError, ValueError) as e: raise ValueError(f"{name}: {e}") from e @@ -71,20 +101,35 @@ def check(name, text): def summary(index, pages): """SUMMARY.md from an OKF index: `# Part` headings and `* [Title](file.md) - description` entries, naming each of `pages`, - the paths in docs/ of the pages the book is given.""" + the paths in docs/ of the pages the book is given. Indented entries + are nested under the entry above them.""" out = ["# Summary", "", "[Introduction](README.md)", f"[Contents]({CONTENTS})"] listed = set() + # The depth of the entry above, or -1 at the start of a part, where + # there is none to nest under. + above = -1 for line in strip_frontmatter(index).splitlines(): if line.startswith("# "): out += ["", line, ""] + above = -1 elif m := ENTRY.fullmatch(line): - chapter = posixpath.normpath(m.group(2)) + depth, odd = divmod(len(m.group(1)), len(INDENT)) + if odd: + raise ValueError(f"index entry has odd indentation: {line!r}") + if depth > above + 1: + if above < 0: + raise ValueError(f"index entry has no entry above: {line!r}") + raise ValueError( + f"index entry is nested more than one level deeper: {line!r}" + ) + above = depth + chapter = posixpath.normpath(m.group(3)) if chapter not in pages: raise ValueError(f"index entry is not a chapter: {line!r}") if chapter in listed: raise ValueError(f"index entry repeats a chapter: {line!r}") listed.add(chapter) - out.append(f"- [{m.group(1)}]({chapter})") + out.append(f"{INDENT * depth}- [{m.group(2)}]({chapter})") elif line.strip(): raise ValueError(f"unexpected line in index: {line!r}") if unlisted := sorted(set(pages) - listed): @@ -103,8 +148,8 @@ def assemble(root): docs, out = root / DOCS, root / SRC index = (docs / "index.md").read_text() pages = {} - for page in sorted(docs.rglob("*.md")): - if page.name not in RESERVED: + for page in sorted([*docs.rglob("*.md"), *docs.rglob("*" + NOTEBOOK)]): + if page.name not in RESERVED and CHECKPOINTS not in page.parts: name = page.relative_to(docs).as_posix() pages[name] = page.read_text() check(name, pages[name]) @@ -136,14 +181,14 @@ def assemble(root): shutil.copytree( docs, out, - ignore=shutil.ignore_patterns("*.md", ".gitignore"), + ignore=shutil.ignore_patterns("*.md", "*" + NOTEBOOK, CHECKPOINTS, ".gitignore"), dirs_exist_ok=True, ) for name, text in generated.items(): (out / name).write_text(text) for name, text in pages.items(): (out / name).parent.mkdir(parents=True, exist_ok=True) - (out / name).write_text(strip_frontmatter(text)) + (out / name).write_text(body(name, text)) def main(argv=None): diff --git a/contrib/jupyter_nb.py b/contrib/jupyter_nb.py new file mode 100755 index 0000000..a10bfb7 --- /dev/null +++ b/contrib/jupyter_nb.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +"""mdbook preprocessor: render `.ipynb` chapters from their saved outputs. + +Any chapter whose source path ends in `.ipynb` is replaced with markdown +built from the notebook's cells. Nothing is executed: markdown cells pass +through verbatim and code-cell outputs (plots, tables, text) are emitted +from what the notebook already has saved, so the build needs no scientific +python stack. Images are inlined as data URIs, so no asset files are written. + +Input (code) cells are hidden by default -- the plotting boilerplate does +not aid understanding. Per-cell control follows the jupyter-book tag +convention via `metadata.tags`: + + remove-cell drop the cell entirely (no input, no output) + show-input force the source to be shown in a fenced block + remove-output drop the outputs + +Links to notebook chapters, `[text](notebook.ipynb#section)`, are pointed +at the chapter's `.md` path: mdbook rewrites `.md` links to the rendered +pages, on the print page too, but leaves `.ipynb` links as they are. + +Plots read on every mdbook theme when the notebook saves them transparent +with medium-lightness chrome (see the style cell in the notebook); a raster +cannot be recoloured by css the way inline svg can. +""" +import json +import posixpath +import re +import sys + +# The relative target of an inline link or a reference definition, if it +# ends in `.ipynb`, before any fragment. +NOTEBOOK_LINK = re.compile( + r"(\]\(\s*#?:]+)\.ipynb(?=[#>)\s]|$)", + re.M, +) + + +def cell_tags(cell): + return set(cell.get("metadata", {}).get("tags", [])) + + +def joined(value): + return "".join(value) if isinstance(value, list) else (value or "") + + +def fenced(code, lang=""): + return "\n```%s\n%s\n```\n" % (lang, code.rstrip("\n")) + + +def render_output(out): + kind = out.get("output_type") + if kind == "stream": + # stdout/stderr is noise (warnings, progress bars); drop it. + return "" + if kind == "error": + return fenced("\n".join(out.get("traceback", []))) + data = out.get("data", {}) + if "image/png" in data: + png = joined(data["image/png"]).replace("\n", "") + return '\n\n' % png + if "image/svg+xml" in data: + return '\n
\n%s\n
\n' % joined(data["image/svg+xml"]) + if "text/html" in data: + html = joined(data["text/html"]) + # Colab wraps tables in interactive widget markup (scripts, sort + # buttons) that is inert in a static book; keep just the table. + match = re.search(r"", html, re.S) + if match: + html = match.group(0) + return '\n
\n%s\n
\n' % html + if "text/plain" in data: + return fenced(joined(data["text/plain"])) + return "" + + +def render_notebook(nb): + parts = [] + for cell in nb.get("cells", []): + tags = cell_tags(cell) + if "remove-cell" in tags: + continue + kind = cell.get("cell_type") + if kind == "markdown": + parts.append(joined(cell.get("source"))) + elif kind == "code": + if "show-input" in tags: + parts.append(fenced(joined(cell.get("source")), "python")) + if "remove-output" not in tags: + for out in cell.get("outputs", []): + piece = render_output(out) + if piece: + parts.append(piece) + return "\n\n".join(p for p in parts if p.strip()) + + +def is_notebook(chapter): + for key in ("source_path", "path"): + p = chapter.get(key) + if isinstance(p, str) and p.endswith(".ipynb"): + return True + return False + + +def chapters(items): + # Separators are bare strings, part titles are `{"PartTitle": ...}`. + for item in items or []: + chapter = item.get("Chapter") if isinstance(item, dict) else None + if chapter: + yield chapter + yield from chapters(chapter.get("sub_items")) + + +def link_notebooks(chapter, notebooks): + """Point links that resolve to one of `notebooks` at its `.md` path.""" + here = posixpath.dirname(chapter.get("path") or "") + + def fix(m): + target = posixpath.normpath(posixpath.join(here, m.group(2) + ".ipynb")) + return m.group(1) + m.group(2) + ".md" if target in notebooks else m.group(0) + + chapter["content"] = NOTEBOOK_LINK.sub(fix, chapter.get("content", "")) + + +def main(): + if len(sys.argv) > 1 and sys.argv[1] == "supports": + sys.exit(0) + _context, book = json.load(sys.stdin) + # mdbook 0.5 renamed the top level key from `sections` to `items`. + items = book.get("items", book.get("sections")) + notebooks = set() + for chapter in chapters(items): + if is_notebook(chapter): + notebooks.add(posixpath.normpath(chapter.get("path") or chapter["source_path"])) + if chapter.get("content", "").strip(): + chapter["content"] = render_notebook(json.loads(chapter["content"])) + for chapter in chapters(items): + link_notebooks(chapter, notebooks) + json.dump(book, sys.stdout) + + +if __name__ == "__main__": + main() diff --git a/contrib/test_book.py b/contrib/test_book.py index 25f5c09..07f2c39 100644 --- a/contrib/test_book.py +++ b/contrib/test_book.py @@ -1,3 +1,4 @@ +import json import re import book @@ -13,6 +14,16 @@ * [Two](sub/two.md) - The second chapter. """ CHAPTERS = {"one.md", "sub/two.md"} +MARKDOWN_CELL = {"cell_type": "markdown", "metadata": {}, "source": ["# Three\n"]} + + +def notebook(*cells): + nb = {"cells": list(cells), "metadata": {}, "nbformat": 4, "nbformat_minor": 5} + return json.dumps(nb, indent=1, ensure_ascii=False) + "\n" + + +def raw_cell(text): + return {"cell_type": "raw", "metadata": {}, "source": text.splitlines(True)} def test_frontmatter_is_dropped_once(): @@ -44,6 +55,75 @@ def test_contents_keep_descriptions_under_one_title(): ) +NESTED = """# Part + +* [One](one.md) - The first chapter. + * [Two](sub/two.md) - Under the first. + * [Three](three.md) - Under the second. + + * [Four](four.md) - Under the first, after a blank line. +* [Five](five.md) - The last chapter. +""" +NESTED_CHAPTERS = {"one.md", "sub/two.md", "three.md", "four.md", "five.md"} + + +def test_summary_nests_indented_entries_under_the_entry_above(): + assert book.summary(NESTED, NESTED_CHAPTERS) == ( + "# Summary\n\n" + "[Introduction](README.md)\n" + "[Contents](contents.md)\n\n" + "# Part\n\n" + "- [One](one.md)\n" + " - [Two](sub/two.md)\n" + " - [Three](three.md)\n" + " - [Four](four.md)\n" + "- [Five](five.md)\n" + ) + + +def test_contents_keep_the_nesting(): + assert book.contents(NESTED) == ( + "# Contents\n\n" + "## Part\n\n" + "* [One](one.md) - The first chapter.\n" + " * [Two](sub/two.md) - Under the first.\n" + " * [Three](three.md) - Under the second.\n\n" + " * [Four](four.md) - Under the first, after a blank line.\n" + "* [Five](five.md) - The last chapter.\n" + ) + + +@pytest.mark.parametrize( + "index, error", + [ + ("# Part\n\n * [One](one.md)\n", "no entry above"), + (" * [One](one.md)\n", "no entry above"), + ("* [One](one.md)\n\n# Part\n\n * [Two](sub/two.md)\n", "no entry above"), + ("# Part\n\n* [One](one.md)\n * [Two](sub/two.md)\n", "more than one level"), + ("# Part\n\n* [One](one.md)\n * [Two](sub/two.md)\n", "odd indentation"), + ("# Part\n\n* [One](one.md)\n * [Two](sub/two.md)\n", "odd indentation"), + ("# Part\n\n* [One](one.md)\n\t* [Two](sub/two.md)\n", "unexpected line"), + ("# Part\n\n* [One](one.md)\n # Sub\n", "unexpected line"), + ], +) +def test_summary_rejects_entries_it_cannot_nest(index, error): + with pytest.raises(ValueError, match=error): + book.summary(index, CHAPTERS) + + +def test_summary_rejects_a_nested_chapter_listed_twice(): + with pytest.raises(ValueError, match="repeats a chapter"): + book.summary( + "# Part\n\n* [One](one.md)\n * [Two](sub/two.md)\n * [Again](one.md)\n", + CHAPTERS, + ) + + +def test_summary_rejects_a_nested_entry_that_is_not_a_chapter(): + with pytest.raises(ValueError, match="not a chapter"): + book.summary("# Part\n\n* [One](one.md)\n * [Gone](gone.md)\n", CHAPTERS) + + @pytest.mark.parametrize( "line, error", [ @@ -120,6 +200,31 @@ def test_check_rejects_a_page_without_a_type_status_or_stale_after(text, error): book.check("one.md", text) +def test_a_notebooks_frontmatter_is_the_raw_cell_that_opens_it(): + head = "---\ntype: Chapter\nstatus: stable\n---" + text = notebook(raw_cell(head), MARKDOWN_CELL) + assert book.notebook_frontmatter(text) == (head, notebook(MARKDOWN_CELL)) + book.check("three.ipynb", text) + + +@pytest.mark.parametrize( + "cells", + [ + [MARKDOWN_CELL], + [MARKDOWN_CELL, raw_cell("---\ntype: Chapter\nstatus: stable\n---")], + [raw_cell("---\ntype: Chapter\nstatus: stable\n---\n\nMore.\n"), MARKDOWN_CELL], + ], +) +def test_check_rejects_a_notebook_that_opens_without_frontmatter(cells): + with pytest.raises(ValueError, match="three.ipynb: no type"): + book.check("three.ipynb", notebook(*cells)) + + +def test_check_rejects_a_notebook_that_is_not_json(): + with pytest.raises(ValueError, match="three.ipynb: Expecting value"): + book.check("three.ipynb", "# Three\n") + + def test_assembly_skips_reserved_files_at_any_level(tmp_path): root, out = tmp_path / "root", tmp_path / "root" / "src" (root / "docs" / "sub").mkdir(parents=True) @@ -286,3 +391,19 @@ def fail(*args, **kwargs): with pytest.raises(OSError): book.assemble(root) assert (out / ".gitignore").read_text() == "*\n" + + +def test_assembly_makes_chapters_of_notebooks_without_their_frontmatter(tmp_path): + root, out = tmp_path / "root", tmp_path / "root" / "src" + (root / "docs" / ".ipynb_checkpoints").mkdir(parents=True) + (root / "README.md").write_text("# Intro\n") + (root / "docs" / "index.md").write_text("# Part\n\n* [Three](three.ipynb)\n") + head = "---\ntype: Chapter\nstatus: stable\n---" + (root / "docs" / "three.ipynb").write_text(notebook(raw_cell(head), MARKDOWN_CELL)) + # Jupyter's autosaves are neither chapters nor part of the book. + checkpoint = root / "docs" / ".ipynb_checkpoints" / "three-checkpoint.ipynb" + checkpoint.write_text(notebook(MARKDOWN_CELL)) + book.assemble(root) + assert (out / "three.ipynb").read_text() == notebook(MARKDOWN_CELL) + assert "- [Three](three.ipynb)\n" in (out / "SUMMARY.md").read_text() + assert not (out / ".ipynb_checkpoints").exists() diff --git a/contrib/test_jupyter_nb.py b/contrib/test_jupyter_nb.py new file mode 100644 index 0000000..002d171 --- /dev/null +++ b/contrib/test_jupyter_nb.py @@ -0,0 +1,33 @@ +import json + +import jupyter_nb + +NOTEBOOK = {"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# Nb\n"]}]} + + +def chapter(path, content, sub_items=()): + return {"Chapter": {"path": path, "source_path": path, "content": content, "sub_items": list(sub_items)}} + + +def test_chapters_skip_separators_and_part_titles(): + items = [ + {"PartTitle": "Part"}, + chapter("one.md", "", [chapter("sub/two.md", "")]), + "Separator", + chapter("three.md", ""), + ] + assert [c["path"] for c in jupyter_nb.chapters(items)] == ["one.md", "sub/two.md", "three.md"] + + +def test_links_to_notebook_chapters_point_at_their_md_path(monkeypatch, capsys): + items = [ + chapter("nb.ipynb", json.dumps(NOTEBOOK)), + "Separator", + chapter("sub/page.md", "[a](../nb.ipynb#x) [b](other.ipynb)\n\n[c]: ../nb.ipynb\n"), + ] + monkeypatch.setattr("sys.argv", ["jupyter_nb.py"]) + monkeypatch.setattr("sys.stdin", __import__("io").StringIO(json.dumps([{}, {"items": items}]))) + jupyter_nb.main() + out = json.loads(capsys.readouterr().out)["items"] + assert out[0]["Chapter"]["content"] == "# Nb\n" + assert out[2]["Chapter"]["content"] == "[a](../nb.md#x) [b](other.ipynb)\n\n[c]: ../nb.md\n" diff --git a/cspell.json b/cspell.json index c90a361..4032acd 100644 --- a/cspell.json +++ b/cspell.json @@ -20,10 +20,15 @@ "fonts", "python", "networking-terms", + "author-names", "bitcoin-privacy", "repo-tooling" ], "dictionaryDefinitions": [ + { + "name": "author-names", + "path": "./cspell/author-names.txt" + }, { "name": "bitcoin-privacy", "path": "./cspell/bitcoin-privacy.txt" diff --git a/cspell/author-names.txt b/cspell/author-names.txt new file mode 100644 index 0000000..a7c242d --- /dev/null +++ b/cspell/author-names.txt @@ -0,0 +1,62 @@ +# Author names +AdamISZ +Alpern +Androulaki +Capkun +Claessens +Danezis +Deligios +Dolev +Dorier +Dwork +Elkind +Eurocrypt +Falbesoner +Garay +Ghesmati +Gierlichs +Goldfeder +Haslhofer +Havar +josibake +Judmayer +Kalodner +Kappos +Karame +Keidar +Kelen +Klasovita +Kleppmann +Kogias +Kogman +Kokoris +Levchenko +Maurer +Meiklejohn +Möser +Naor +Neudecker +Paverd +Pomarole +Poupko +Preneel +Reisman +Roeschlin +Rollet +Sabouri +Serjantov +Seys +Shmatikov +Skoumios +Somsen +Stifter +Stockmeyer +Stütz +Syverson +Troncoso +Verbauwhede +Voelker +Weippl +Wuille +Yousaf +Zikas diff --git a/cspell/bitcoin-privacy.txt b/cspell/bitcoin-privacy.txt index 16c9b72..031467d 100644 --- a/cspell/bitcoin-privacy.txt +++ b/cspell/bitcoin-privacy.txt @@ -28,3 +28,83 @@ taptree unlinkability UTXO xpub +backout +feerates +locktimes +# Cited journals +Academiae +Scientiarum +Hungaricae +# Network science +assortativity +deanonymizes +multiroute +superconcentrator +# Cited authors +Chekuri +Idleman +Karrer +Kishimoto +Maurer +Neudecker +Orlin +multiset +satisfice +satisficing +sumset +coindays +precomputation +Blocklace +blocklace +CoinSwap +ECMH +fastcrypto +Merklized +permissioned +prevout +RIBLT +Samourai +sneakernet +unlinkable +contramap +vout +deanonymizing +Bustapay +CIOH +counterfactually +entropist +fingerprintable +multigraph +NSNR +payjoins +KVACs +minrelayfee +multisignature +standardness +unaddressable +vbytes +WabiSabi +wtxid +# Cryptography +HPKE +# Mathematics +elementwise +unioning +# Game theory +rivalrous + +# Concurrent PSBT construction +ANYONECANPAY +CRDT +globalseed +joinpsbts +keydata +kickstarter +nlocktime +psbtv +reserialization +txns +unioned +unrepresentable +unshuffled +valuedata diff --git a/cspell/tooling.txt b/cspell/tooling.txt index 4275994..32dd4a0 100644 --- a/cspell/tooling.txt +++ b/cspell/tooling.txt @@ -1,14 +1,22 @@ # Repository tools, identifiers, and upstream authors +ambs +atmd cacheprovider +capsys DejaVu devshell DNSSEC dontInstall dylanowen +encs fontconfig Graphviz +ipynb KaTeX +linkpred lzanini +mathit +mathrm mdBook mmdc NixOS @@ -17,5 +25,7 @@ pkgs pytest PyYAML stdenv +texttt toplevel +txni unfetched diff --git a/docs/Denominations_and_gap_size_distributions.ipynb b/docs/Denominations_and_gap_size_distributions.ipynb new file mode 100644 index 0000000..6cdc8fa --- /dev/null +++ b/docs/Denominations_and_gap_size_distributions.ipynb @@ -0,0 +1,1537 @@ +{ + "cells": [ + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "---\n", + "type: concept\n", + "title: Small Hamming Weight Denominations for CoinJoins\n", + "status: draft\n", + "stale_after: 2027-01-23T00:00:00Z\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Small Hamming Weight Denominations for CoinJoins\n", + "\n", + "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.\n", + "\n", + "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.\n", + "\n", + "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 $k$ such denominations. There are only $O(\\log n)$ such values up to $n$ sats.\n", + "\n", + "## Sub-transaction model and implications for privacy\n", + "\n", + "In the sub-transaction model ([1](https://m.flrn.cc/academic/2017_CoinJoin.pdf), [2](https://medium.com/@laurentmt/introducing-boltzmann-85930984a159)), for every repeated value with multiplicity $m$ in the inputs or the outputs of a sub-transaction mapping as a whole, $m!$ 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.\n", + "\n", + "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.\n", + "\n", + "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 $k$ distinct denominations, and each of which has multiplicity $m$ in the outputs of the sub-transaction mapping as a whole, then the number of equivalent mappings is $k \\times m!$. This counts permutations over sets of subsets of outputs, specifically when a subset of size $k$ is exchanged with a subset of size $1$.\n", + "\n", + "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.\n", + "\n", + "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.\n", + "\n", + "## Radix CoinJoin\n", + "\n", + "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.\n", + "\n", + "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.\n", + "\n", + "## Mixed bases and preferred values\n", + "\n", + "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](https://en.wikipedia.org/wiki/Preferred_number) can approximate values well with a smaller number of denominations.\n", + "\n", + "Currency conversions often result in excessively precise bitcoin amounts. In some base $b$, a value $v$ will have expected weight $\\frac{(b-1) \\log_b v}{b}$. 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).\n", + "\n", + "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.\n", + "\n", + "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.\n", + "\n", + "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." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parameters\n", + "\n", + "The minimal feerate can be controlled in order to vary the dust threshold." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# bitcoin network parameters\n", + "max_sats = 2099999997690000\n", + "dust_feerate = 3.0\n", + "expected_feerate = 10.0\n", + "min_vbytes = 98 # 294 sats @ 3 sat/vb for p2wpkh per https://bitcoin.stackexchange.com/a/41082\n", + "dust = int(min_vbytes * dust_feerate)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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 $c$ times `max_denom` needs more than $c$ terms, since no term exceeds `max_denom`, so it effectively has fewer than $k$ free terms and the sumset is sparse there." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# denomination parameters\n", + "min_denom = dust\n", + "max_denom = int(1e8) # reducing this reveals some interesting structure in the plots below\n", + "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.\n", + "max_combination_value = max_denom * 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# analysis parameters\n", + "min_diff = 2 # setting to dust hides small gaps, focusing on more significant ones\n", + "min_diff_ratio = 0 # 1e-4 is a basis point" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate denominations" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# import boilerplate\n", + "from math import comb, log, ceil\n", + "\n", + "from itertools import combinations_with_replacement, product\n", + "\n", + "import pandas as pd\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import numpy as np\n", + "\n", + "# theme-neutral plot style: reads on light and dark mdbook themes\n", + "plt.rcParams.update({\n", + " \"savefig.transparent\": True,\n", + " \"figure.facecolor\": \"none\",\n", + " \"axes.facecolor\": \"none\",\n", + " \"savefig.facecolor\": \"none\",\n", + " \"text.color\": \"#888888\",\n", + " \"axes.labelcolor\": \"#888888\",\n", + " \"axes.edgecolor\": \"#888888\",\n", + " \"axes.titlecolor\": \"#888888\",\n", + " \"xtick.color\": \"#888888\",\n", + " \"ytick.color\": \"#888888\",\n", + " \"grid.color\": \"#888888\",\n", + " \"legend.labelcolor\": \"#888888\",\n", + " \"axes.spines.top\": False,\n", + " \"axes.spines.right\": False,\n", + " \"legend.frameon\": False,\n", + "})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Denominations are based on [preferred value series](https://en.wikipedia.org/wiki/Preferred_number) in base 2, 3, and 10." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# helper functions\n", + "def powers(b: int) -> set[int]:\n", + " \"\"\"\n", + " Generates the powers of the given base up to the maximum denomination.\n", + " Smaller powers are kept, since a multiple of one may still be large enough.\n", + " \"\"\"\n", + " return { b**i for i in range(int(log(max_denom)/log(b))+1) }\n", + "\n", + "def multiples(vs: set[int], cs: set[int]) -> set[int]:\n", + " \"\"\"\n", + " Computes the products of pairs of values from two sets.\n", + " \"\"\"\n", + " return { c*v for (c,v) in product(cs,vs) if c*v in range(min_denom, max_denom+1) }" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# denominations of different bases\n", + "binary = multiples(powers(2), {1})\n", + "ternary = multiples(powers(3), {1,2})\n", + "decimal = multiples(powers(10), {1,2,5})" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# these additional Hamming weight 2 values plug the proportionally largest gaps\n", + "# between the denominations. this has some impact on the decomposition of smaller\n", + "# values (max_denom <= 1e6 or so) and so seem appropriate for a future with a\n", + "# lower dust feerate, but marginal benefit today\n", + "\n", + "#binary = binary | multiples({3}, { 2**i for i in [ 10, 13, 15, 18 ]})\n", + "\n", + "# the addition of 3 * 2^n arguably over-represents base 2 values\n", + "# https://en.wikipedia.org/wiki/Preferred_number#Computer_engineering\n", + "\n", + "#binary = multiples(powers(2), {1,3})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The combined set of denominations is just a union of these Hamming weight 1 values in these 3 useful bases." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# combined denomination set\n", + "combined = binary | ternary | decimal" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "dark" + }, + "output_type": "display_data" + } + ], + "source": [ + "# denomination values\n", + "palette = {'binary': '#0072B2', 'ternary': '#E69F00', 'decimal': '#009E73', 'combined': '#D55E00'}\n", + "origin = { v: 'binary' for v in binary } | { v: 'ternary' for v in ternary } | { v: 'decimal' for v in decimal }\n", + "\n", + "combined_index = {value: index for index, value in enumerate(sorted(combined))}\n", + "\n", + "plt.figure(figsize=(8,3))\n", + "sns.scatterplot(data=pd.DataFrame([{'value': v, 'index': combined_index[v], 'set': origin[v]} for v in sorted(combined) ]), x='index', y='value', hue='set', palette=palette)\n", + "\n", + "plt.yscale('log')\n", + "plt.ylabel('sats')\n", + "plt.title('Denomination values')\n", + "plt.grid(True, which='both', alpha=0.25)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "dark" + }, + "output_type": "display_data" + } + ], + "source": [ + "# denomination set sizes\n", + "data = {\n", + " 'set': ['binary', 'ternary', 'decimal', 'combined'],\n", + " 'size': [len(binary), len(ternary), len(decimal), len(combined)],\n", + " 'color': [palette['binary'], palette['ternary'], palette['decimal'], palette['combined']]\n", + "}\n", + "df_sets = pd.DataFrame(data)\n", + "\n", + "plt.figure(figsize=(8, 2))\n", + "ax = sns.barplot(x='set', y='size', hue='set', data=df_sets, palette=palette, legend=False)\n", + "plt.xlabel('Base')\n", + "plt.ylabel('Number of denominations')\n", + "plt.title(f'Sizes of denomination base sets for values ≤ {max_denom/1e8} BTC')\n", + "\n", + "for container in ax.containers:\n", + " ax.bar_label(container, fmt='%.0f', label_type='center', color='black')\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
setvaluebinary (little endian)popcountweight (base 3)weight (base 10)
0ternary0.00000486011001111613
1decimal0.00000500001011111641
2binary0.000005120000000001143
3ternary0.000007291001101101613
4decimal0.000010000001011111641
5binary0.0000102400000000001163
6ternary0.0000145801001101101614
7decimal0.0000200000001011111641
8binary0.00002048000000000001163
9ternary0.00002187110100010001514
10binary0.000040960000000000001173
11ternary0.000043740110100010001514
12decimal0.000050000001000111001561
13ternary0.000065611000010110011614
14binary0.0000819200000000000001154
15decimal0.0001000000001000111001571
16ternary0.0001312201000010110011615
17binary0.00016384000000000000001185
18ternary0.00019683110001110011001815
19decimal0.00020000000001000111001551
20binary0.0003276800000000000000011105
21ternary0.000393660110001110011001815
22decimal0.000500000000101011000011691
23ternary0.000590491001010101100111914
24binary0.0006553600000000000000001175
25decimal0.0010000000000101011000011671
26ternary0.0011809801001010101100111915
27binary0.00131072000000000000000001195
28ternary0.001771471101111111001101011316
29decimal0.00200000000000101011000011671
30binary0.002621440000000000000000001196
31ternary0.0035429401101111111001101011316
32decimal0.0050000000000100100001011117111
33binary0.0052428800000000000000000001196
34ternary0.00531441100011111101100000011016
35decimal0.0100000000000010010000101111791
36binary0.010485760000000000000000000011106
37ternary0.010628820100011111101100000011016
38ternary0.015943231100101111001010000111117
39decimal0.020000000000000100100001011117101
40binary0.0209715200000000000000000000011116
41ternary0.0318864601100101111001010000111117
42binary0.04194304000000000000000000000011116
43ternary0.04782969100111101101111100010011417
44decimal0.0500000000000010110100100011001871
45binary0.08388608000000000000000000000001186
46ternary0.095659380100111101101111100010011417
47decimal0.10000000000000010110100100011001891
48ternary0.143489071101011001001111010110111517
49binary0.167772160000000000000000000000001198
50decimal0.2000000000000000101101001000110018121
51ternary0.2869781401101011001001111010110111518
52binary0.3355443200000000000000000000000001178
53ternary0.43046721100000101110101100001001011117
54decimal0.500000000000000100001111010111110112111
55binary0.671088640000000000000000000000000011127
56ternary0.860934420100000101110101100001001011117
57decimal1.0000000000000000100001111010111110112131
\n", + "
" + ], + "text/plain": [ + " set value binary (little endian) popcount \\\n", + "0 ternary 0.00000486 011001111 6 \n", + "1 decimal 0.00000500 001011111 6 \n", + "2 binary 0.00000512 0000000001 1 \n", + "3 ternary 0.00000729 1001101101 6 \n", + "4 decimal 0.00001000 0001011111 6 \n", + "5 binary 0.00001024 00000000001 1 \n", + "6 ternary 0.00001458 01001101101 6 \n", + "7 decimal 0.00002000 00001011111 6 \n", + "8 binary 0.00002048 000000000001 1 \n", + "9 ternary 0.00002187 110100010001 5 \n", + "10 binary 0.00004096 0000000000001 1 \n", + "11 ternary 0.00004374 0110100010001 5 \n", + "12 decimal 0.00005000 0001000111001 5 \n", + "13 ternary 0.00006561 1000010110011 6 \n", + "14 binary 0.00008192 00000000000001 1 \n", + "15 decimal 0.00010000 00001000111001 5 \n", + "16 ternary 0.00013122 01000010110011 6 \n", + "17 binary 0.00016384 000000000000001 1 \n", + "18 ternary 0.00019683 110001110011001 8 \n", + "19 decimal 0.00020000 000001000111001 5 \n", + "20 binary 0.00032768 0000000000000001 1 \n", + "21 ternary 0.00039366 0110001110011001 8 \n", + "22 decimal 0.00050000 0000101011000011 6 \n", + "23 ternary 0.00059049 1001010101100111 9 \n", + "24 binary 0.00065536 00000000000000001 1 \n", + "25 decimal 0.00100000 00000101011000011 6 \n", + "26 ternary 0.00118098 01001010101100111 9 \n", + "27 binary 0.00131072 000000000000000001 1 \n", + "28 ternary 0.00177147 110111111100110101 13 \n", + "29 decimal 0.00200000 000000101011000011 6 \n", + "30 binary 0.00262144 0000000000000000001 1 \n", + "31 ternary 0.00354294 0110111111100110101 13 \n", + "32 decimal 0.00500000 0000010010000101111 7 \n", + "33 binary 0.00524288 00000000000000000001 1 \n", + "34 ternary 0.00531441 10001111110110000001 10 \n", + "35 decimal 0.01000000 00000010010000101111 7 \n", + "36 binary 0.01048576 000000000000000000001 1 \n", + "37 ternary 0.01062882 010001111110110000001 10 \n", + "38 ternary 0.01594323 110010111100101000011 11 \n", + "39 decimal 0.02000000 000000010010000101111 7 \n", + "40 binary 0.02097152 0000000000000000000001 1 \n", + "41 ternary 0.03188646 0110010111100101000011 11 \n", + "42 binary 0.04194304 00000000000000000000001 1 \n", + "43 ternary 0.04782969 10011110110111110001001 14 \n", + "44 decimal 0.05000000 00000010110100100011001 8 \n", + "45 binary 0.08388608 000000000000000000000001 1 \n", + "46 ternary 0.09565938 010011110110111110001001 14 \n", + "47 decimal 0.10000000 000000010110100100011001 8 \n", + "48 ternary 0.14348907 110101100100111101011011 15 \n", + "49 binary 0.16777216 0000000000000000000000001 1 \n", + "50 decimal 0.20000000 0000000010110100100011001 8 \n", + "51 ternary 0.28697814 0110101100100111101011011 15 \n", + "52 binary 0.33554432 00000000000000000000000001 1 \n", + "53 ternary 0.43046721 10000010111010110000100101 11 \n", + "54 decimal 0.50000000 00000001000011110101111101 12 \n", + "55 binary 0.67108864 000000000000000000000000001 1 \n", + "56 ternary 0.86093442 010000010111010110000100101 11 \n", + "57 decimal 1.00000000 000000001000011110101111101 12 \n", + "\n", + " weight (base 3) weight (base 10) \n", + "0 1 3 \n", + "1 4 1 \n", + "2 4 3 \n", + "3 1 3 \n", + "4 4 1 \n", + "5 6 3 \n", + "6 1 4 \n", + "7 4 1 \n", + "8 6 3 \n", + "9 1 4 \n", + "10 7 3 \n", + "11 1 4 \n", + "12 6 1 \n", + "13 1 4 \n", + "14 5 4 \n", + "15 7 1 \n", + "16 1 5 \n", + "17 8 5 \n", + "18 1 5 \n", + "19 5 1 \n", + "20 10 5 \n", + "21 1 5 \n", + "22 9 1 \n", + "23 1 4 \n", + "24 7 5 \n", + "25 7 1 \n", + "26 1 5 \n", + "27 9 5 \n", + "28 1 6 \n", + "29 7 1 \n", + "30 9 6 \n", + "31 1 6 \n", + "32 11 1 \n", + "33 9 6 \n", + "34 1 6 \n", + "35 9 1 \n", + "36 10 6 \n", + "37 1 6 \n", + "38 1 7 \n", + "39 10 1 \n", + "40 11 6 \n", + "41 1 7 \n", + "42 11 6 \n", + "43 1 7 \n", + "44 7 1 \n", + "45 8 6 \n", + "46 1 7 \n", + "47 9 1 \n", + "48 1 7 \n", + "49 9 8 \n", + "50 12 1 \n", + "51 1 8 \n", + "52 7 8 \n", + "53 1 7 \n", + "54 11 1 \n", + "55 12 7 \n", + "56 1 7 \n", + "57 13 1 " + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# denominations table\n", + "\n", + "def hamming_weight(n, base):\n", + " \"\"\"Calculates the Hamming weight of n in a given base.\"\"\"\n", + " if n == 0:\n", + " return 0\n", + " weight = 0\n", + " while n > 0:\n", + " weight += n % base != 0\n", + " n //= base\n", + " return weight\n", + "\n", + "pd.DataFrame([{\n", + " 'set': origin[x],\n", + " 'value': \"{0:.8f}\".format(x/1e8),\n", + " 'binary (little endian)': \"{0:b}\".format(x)[::-1],\n", + " 'popcount': bin(x).count('1'),\n", + " 'weight (base 3)': hamming_weight(x, 3),\n", + " 'weight (base 10)': hamming_weight(x, 10)\n", + " } for x in sorted(combined) ])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate sumsets\n", + "\n", + "`{0}` is unioned with the denominations in order to obtain the sumsets from combinations of size $\\leq k$ as opposed to $=k$." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# compute sumsets naively\n", + "\n", + "sumsets = []\n", + "for k in range(1, max_combination_size+1):\n", + " subsets = combinations_with_replacement({0} | combined, k)\n", + " sumset = { s for s in map(sum, subsets) if s in range(1,max_combination_value+1) }\n", + " sumsets.append(np.array(sorted(sumset)))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# (fail to) compute sumsets more efficiently\n", + "import numpy as np\n", + "from numpy.fft import fft, ifft\n", + "from math import log2\n", + "\n", + "def sumset_k_fft(nums, k):\n", + " \"\"\"\n", + " Compute sumset via FFT, same as above but supposedly faster\n", + " \"\"\"\n", + " nums = np.array(sorted(nums))\n", + " max_sum = np.max(nums) * k\n", + " poly = np.zeros(2**ceil(log2(max_sum)))\n", + " poly[nums] = 1\n", + " F = fft(poly)\n", + " Fk = F ** k\n", + " result = np.rint(ifft(Fk).real).astype(int)\n", + " sums = np.where(result > 0)[0]\n", + " sums = sums[(sums >= min_denom) & (sums <= max_combination_value)]\n", + " return sums\n", + "\n", + "# this is actually slower, so don't do it\n", + "#sumsets = [sumset_k_fft({0} | combined, k) for k in range(1, max_combination_size+1)]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "# compute gaps naively\n", + "# gaps = [np.array([ d for d in (b - a for a,b in zip(s, s[1:])) if min_diff <= d ]) for s in sumsets]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# compute gaps efficiently\n", + "gaps = []\n", + "for s in sumsets:\n", + " diffs = np.diff(s)\n", + " gaps.append(diffs[diffs >= min_diff])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# compute normalized gaps naively\n", + "#relative_gaps = [np.array([ p for d, p in ((b-a, (b-a)/b) for a,b in zip(s, s[1:])) if dust <= d and min_diff_ratio <= p ]) for s in sumsets]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "tags": [ + "show-input" + ] + }, + "outputs": [], + "source": [ + "# compute normalized gaps efficiently\n", + "\n", + "relative_gaps = []\n", + "for s in sumsets:\n", + " diffs = np.diff(s)\n", + " relative_diffs = diffs / s[1:]\n", + " mask = (diffs >= dust) & (relative_diffs >= min_diff_ratio)\n", + " relative_gaps.append(relative_diffs[mask])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plots" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "# dataframe boilerplate\n", + "\n", + "all_gaps_data = np.concatenate(gaps)\n", + "all_gaps_k_values = np.concatenate([np.full(len(g_arr), i + 1) for i, g_arr in enumerate(gaps)])\n", + "df_gaps = pd.DataFrame({'d': all_gaps_data, 'k': all_gaps_k_values})\n", + "\n", + "all_rel_gaps_data = np.concatenate(relative_gaps)\n", + "all_rel_gaps_k_values = np.concatenate([np.full(len(rg_arr), i + 1) for i, rg_arr in enumerate(relative_gaps)])\n", + "df_rel_gaps = pd.DataFrame({'r': all_rel_gaps_data, 'k': all_rel_gaps_k_values})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Gaps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Count and sizes\n", + "\n", + "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.\n", + "\n", + "Note that for $k \\in \\{1, 6\\}$ the scatterplots are a little misleading. For $k=1$ there aren't that many distinct values, so even though these values are smoothly distributed the quantile values aren't. For $k=6$ 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." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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VIthwNJYJmm8934b59wnYZA2Plye267bs2rAq865swC89+cAcWCyc+7ycNlfgKOAH2EBxFHAS865P+Z24L0/BPjEe7868DlwKPBr59wj4foGLGhpVy6zFvrQe386FjQeXbC8H/Ab59z74X4vAv60kN3+BnjbOXdyeP9t7/06wKkFx/2MBYO9C733OwN7Af8tWP4JljXMhvsJsGDt8naOvSLwd+fcW+H9d9trZGE3UO/9P7GAbaNw0b5YEHtYLnvnvT8YmI4FwA+3t99KpEBNRERERKqCc+5T7/025IOy8d77A4HrwvsfANu01S2ym7xW0JYW7/0UrDtkzqTw59Lhzw2Abb3337axr1WAQUB/YELBfqd6799eWCO899sCfwTGAEtg5/QDvfdDnHO5oiOzckFa6IuCdrVlDeD5omX/KzpuLRac7gP8ABgQ3ooLnTxX1M1xAnCS977WOdfSxrHPA64I38tHgduK2v493vsjsCB384LgbQNgVWCG975w84HY611V1PVRRERERKqGc+4TLDvyARacPcOCQdonPXj44u542cJlBcFJTcHPe7GuhIW31YAngUhnG+C9Xwmrgvg6sCcWnBwTru63iLYu7HiRcJviZYVOwjJjf8O6W66LdfdcrG6FzrkEsDaQCvc70Xu/e3vbh8H6hVgm8tWCVTVY18x1i26rAzcuThvLQRk1EREREakqYXfHA7EgLefAHg7SuuIlLJjKOOeai1d679/DAqpNgI/DZUtigcUT7exzQ+wc/iTnXGv4mL27oa1vAbu0caxCWwJ3O+euD49bgwWdbxZtt0kb999tJ5sGgHPuHeAd4Hzv/U1YsZS7irfz3q8K3IEVMbmzaPVLWLbvK+fcN+0dq1ooUBMRERGRqhKOSbuuaPF1uTFr5WhTOy4GDgdu8t7/HStEsio2lupw59y33vsrgb+H3SgnYQU8Wheyz/exc/jfeu/vBTbHxpctrkuBE731GbwSy0QdFK7LZdreA/b03m8GTANOBEbz/UBtBe/9eeE+1wd+i2Xjvsd7PwgrqHI78CFWIGQjLBhra9t7seIsl3nvR+fWOee+xIqSnAzc7b3/EzbWb0Wsoubfe7BLbI9Q10cRERERqRpFhUM+wAKVXDfI8cXVIMvJOfc51r5arIvg68A/sUInuWDsZKwb5D3Y+Kynse577e3zFSxAcuH+DgBO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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "dark" + }, + "output_type": "display_data" + } + ], + "source": [ + "gap_sizes = list(map(len, gaps))\n", + "gap_sizes_larger_than_dust = list(map(lambda x: max(len(x),1), [ [x for x in s if dust <= x] for s in gaps ]))\n", + "ks = list(range(1, max_combination_size + 1))\n", + "\n", + "fig, ax1 = plt.subplots(figsize=(8, 4))\n", + "\n", + "ax1.set_xlabel('Combination Size (k)')\n", + "ax1.tick_params(axis='y')\n", + "ax1.set_xticks(ks)\n", + "ax1.grid(axis='y', alpha=0.25)\n", + "ax1.set_yscale(\"log\")\n", + "\n", + "ax1.plot(ks, gap_sizes, label=\"# gaps\")\n", + "ax1.plot(ks, gap_sizes_larger_than_dust, label=f\"# gaps ≥ dust ({dust})\")\n", + "\n", + "mean_gap_sizes = df_gaps.groupby('k')['d'].mean()\n", + "median_gap_sizes = df_gaps.groupby('k')['d'].median()\n", + "num_quantiles = 20\n", + "quantiles = df_gaps.groupby('k')['d'].quantile([i/num_quantiles for i in range(1, num_quantiles)])\n", + "\n", + "ax1.plot(ks, mean_gap_sizes.values, label='mean gap size')\n", + "\n", + "ax1.scatter(ks, median_gap_sizes.values, color='#888888', marker='x', label='median gap size')\n", + "\n", + "for i in range(1, num_quantiles):\n", + " if i == num_quantiles // 2: # skip median, plotted separately above\n", + " continue\n", + " quantile_values = quantiles.loc[(slice(None), i/num_quantiles)].values\n", + " ax1.scatter(ks, quantile_values, marker='.', color='#888888', alpha=0.2, label=f'i×{100 // num_quantiles}-th percentile' if i == 1 else None)\n", + "\n", + "fig.suptitle('Gaps by Combination Size', y=1.05)\n", + "fig.legend(loc=\"lower left\", bbox_to_anchor=(1,1), bbox_transform=ax1.transAxes)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Gap sizes distribution\n", + "\n", + "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 $k>3$ are empty because the populated bins interspersing them correspond to successive integer values." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "bins = 300" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "dark" + }, + "output_type": "display_data" + } + ], + "source": [ + "min_gap = df_gaps['d'].min()\n", + "gap_bins = np.logspace(np.log10(min_gap), np.log10(df_gaps['d'].max()), bins)\n", + "g_abs_hist_binned = sns.FacetGrid(df_gaps, col='k', col_wrap=1, height=1.7, aspect=6)\n", + "g_abs_hist_binned.map(plt.hist, 'd', bins=gap_bins)\n", + "g_abs_hist_binned.set(xscale=\"log\", yscale=\"log\")\n", + "g_abs_hist_binned.fig.suptitle(f'Gap sizes ≥ {min_gap} sats', y=1.05)\n", + "for i, ax in enumerate(g_abs_hist_binned.axes.flat):\n", + " k = i+1\n", + " ax.grid(True, which='both', alpha=0.25)\n", + " if min_diff < dust:\n", + " ax.axvline(x=dust, color='#888888', linestyle='--', label=f'dust ({dust} sats = {min_vbytes} vB × {dust_feerate} sat/vB)')\n", + " ax.axvline(x=k*dust, color='orange', linestyle='--', label='k × dust')\n", + " ax.axvline(x=k*(expected_feerate * min_vbytes), color='red', linestyle='--', label=f'k × {min_vbytes} vB × {expected_feerate} sat/vB')\n", + " if i == 0:\n", + " ax.legend()\n", + " ax.secondary_xaxis('top').spines['top'].set_visible(False)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Relative gap size\n", + "\n", + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "dark" + }, + "output_type": "display_data" + } + ], + "source": [ + "ratio_bins = np.logspace(np.log10(df_rel_gaps['r'].min()), np.log10(df_rel_gaps['r'].max()), bins)\n", + "g_ratio_hist_binned = sns.FacetGrid(df_rel_gaps, col='k', col_wrap=1, height=1.5, aspect=7)\n", + "g_ratio_hist_binned.map(plt.hist, 'r', bins=ratio_bins)\n", + "g_ratio_hist_binned.set(xscale=\"log\", yscale=\"log\")\n", + "g_ratio_hist_binned.fig.suptitle(f'Relative gap sizes (b-a)/b ≥ {min_diff_ratio} for gaps (a,b) where (b-a) ≥ {dust}', y=1.05)\n", + "for i, ax in enumerate(g_ratio_hist_binned.axes.flat):\n", + " ax.grid(True, which='both', alpha=0.25)\n", + " ax.axvline(x=1e-4, color='#888888', linestyle='--', label='1‱')\n", + " ax.axvline(x=1e-2, color='red', linestyle='--', label='1%')\n", + " if i == 0:\n", + " ax.legend()\n", + " ax.secondary_xaxis('top').spines['top'].set_visible(False)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sums and combinations" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Density of distinct sums\n", + "\n", + "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).\n", + "\n", + "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).\n", + "\n", + "A density of 1 implies every possible integer value in the bin can be constructed exactly, and a density $\\geq\\mathrm{dust}^{-1}$ means every value can be approximated from below with error smaller than the dust threshold.\n", + "\n", + "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 $k$, smaller combinations are more efficient representations of a given value but concrete efficiency depends on the feerate, and at higher feerates." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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zj3I8+cemNgVBrGvR2ZPYJXa9JjiZNtNik/bnYquM60k65ogCBvDet6S/gfgL4AngApwF9FS+y8Abx2da8JGcPPNN8+88Y1v3PuhD31o8dWvfnXupg579+7tFU6hXvziF3PrbTfnCjz22GP69a9//d4//MM/PDU7Oyt7EgmCIEwYdVvmKysXY61GKztxk+attMJgWodUXL3jWKg1Dc+jVipRdm5D39pupbYbhq2QcV0Q1ks0vmXrPaGb9exDfxr4Z0EQfA/wAqK3/H/n+/6nRu2cMF5uuOGG2Xe84x27b7nlllNXX311z1vD3XffnRtOEYbh3qmpqam88845Xvva1+593etet3LllVeG999//9YJghQEQdghhM7DWs155z/GY4+eR+i8HTEJ3AhCrblv725WVuucqlTwQJa9j5CujOvWoaVthW1CenzL1ntCmnXHMfu+/1fAX43Ql7ESBMEs8I/AH/m+/x8225/N5tZbb62cPHlSf/KTnzx51VVX9f3Gdtlll+UGK1arVWeMoXPTgzV+93d/11teXna/8Ru/sbx+jwVBEISNYHpKviWOmji2+vyZBfbNau6vPk1iq0dInHE9DiVQxnDayWJAYXuQHN917fHI3JxsvSd0MNCEPggCDbwW+FGiPegd8CDwx8DNvu9P8t3zrcDdm+3EpHD06NHwnnvuKd90002zV1555ZLuE083zJL7z372s/rLX/6ynp+f78j+/5KXvOSsH/3RH61//OMfPzVwBQRBEARhizGtGlS0fAkfB8mM63aDJ/Oh1u3JllAMCY8YjPb4lpTSQgaFh0UQBAr4BPBK4KvA1wAFPAu4iWiS/6qRezgCgiA4AjwTuBU4usnuTASHDx9uXn/99UvHjh07eM0113DjjTcu9ZIfZsn9ddddF7797W9vJ8I7fvy496pXvWr/Rz/60ade9KIXra8CgiAIwoZTtyWqVrNsFNPaTlSMvSBsBvFWddZFL0bWdmCQxINZdIVHOIc34StVkrHrgjCJDPKc57XAS4Hv9X3/08kTrXj6PwuC4Kd93//9QRwIguClwK8BLwTOA37E9/0/S8lc05I5D/gH4E2+739uADPXt8pfNYhv251nPetZ5s477zx57Nixg294wxvc+9///tzs88Msub/wwgupVCrN+O+5uTkHcMkllzQvuOAC+cQTBEHYAtRtmb9fOcxK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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "dark" + }, + "output_type": "display_data" + } + ], + "source": [ + "min_sum = min_denom\n", + "max_sum = max_combination_value\n", + "\n", + "log_bins = np.logspace(np.log10(min_sum), np.log10(max_sum), bins)\n", + "\n", + "plt.figure(figsize=(12, 5))\n", + "\n", + "colors = plt.cm.plasma(np.linspace(0, 1, max_combination_size))[::-1]\n", + "\n", + "# similar to density=True except there's no division by the total entry count,\n", + "# which allows comparing the relative densities of different combination sizes\n", + "for i in range(max_combination_size -1 , -1, -1):\n", + " k = i + 1\n", + " if len(log_bins) > 1:\n", + " counts, bin_edges = np.histogram(sumsets[i], bins=log_bins)\n", + " bin_widths = np.diff(bin_edges)\n", + " density = counts / bin_widths\n", + " plt.bar(bin_edges[:-1], density, width=bin_widths, color=colors[i], label=f'k = {k}', align='edge')\n", + " plt.stairs(density, bin_edges, color='#888888', linewidth=1)\n", + "\n", + "plt.xscale('log')\n", + "plt.yscale('log')\n", + "plt.ylim(1e-5, 1)\n", + "plt.xlabel('Binned sums (sats)')\n", + "plt.ylabel('Density per bin (count / bin width)')\n", + "plt.title(f'Density of distinct sums by combination size (k)')\n", + "plt.axhline(y=1/dust, color='#888888', linestyle='--', label=f'dust⁻¹ ({dust}⁻¹)')\n", + "\n", + "plt.axhspan(ymin=0, ymax=1/dust, facecolor='lightgrey', alpha=0.5)\n", + "\n", + "plt.legend(loc='lower left', frameon=True, facecolor='white', labelcolor='black')\n", + "plt.grid(True, which='both', alpha=0.25)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Distinct combinations vs. distinct sums\n", + "\n", + "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." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "dark" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax1 = plt.subplots(figsize=(8, 5))\n", + "\n", + "ks = list(range(1, max_combination_size + 1))\n", + "# like the sumsets, count combinations of size <= k: multisets of size k drawn\n", + "# from the n denominations and 0, (n+k choose k), less the empty combination\n", + "num_combinations = [ comb(len(combined)+k, k) - 1 for k in ks ]\n", + "\n", + "\n", + "ax1.set_xlabel('Combination Size (k)', fontsize=11)\n", + "ax1.set_yscale(\"log\")\n", + "ax1.plot(ks, num_combinations, marker='.', label=f\"combinations of size ≤ k (({len(combined)}+k) choose k) − 1\")\n", + "ax1.plot(ks, list(map(len, sumsets)), marker='.', label=f\"distinct sums ≤ {max_combination_value/1e8} BTC\")\n", + "plt.axhline(y=max_combination_value, color='#888888', linestyle='--', label=f\"distinct integers ≤ {max_combination_value/1e8} BTC\")\n", + "ax1.legend()\n", + "for i, k in enumerate(ks):\n", + " ax1.text(k, num_combinations[i], f'{num_combinations[i]:,}', ha='right', va='bottom')\n", + " if k > 1:\n", + " ax1.text(k, len(sumsets[i]), f'{len(sumsets[i]):,}', ha='right', va='top')\n", + "\n", + "ax1.grid(True, which='both', alpha=0.25)\n", + "\n", + "\n", + "fig.suptitle(f'Combinations with replacement of denominations ≤ {max_denom/1e8} BTC')\n", + "\n", + "ax2 = ax1.twinx()\n", + "exponent = int(np.floor(np.log10(max_combination_value)))\n", + "mantissa = max_combination_value / (10**exponent)\n", + "def sup(n):\n", + " \"\"\"Converts an integer to a unicode superscript string.\"\"\"\n", + " superscript_map = {\n", + " '0': '⁰', '1': '¹', '2': '²', '3': '³', '4': '⁴', '5': '⁵', '6': '⁶',\n", + " '7': '⁷', '8': '⁸', '9': '⁹', '-': '⁻'\n", + " }\n", + " return ''.join(superscript_map.get(digit, digit) for digit in str(n))\n", + "ax2.set_ylabel(f'Density (y × ({mantissa:.1f} × 10{sup(exponent)}){sup(-1)})', fontsize=11)\n", + "ax2.set_yscale(\"log\")\n", + "# same scale as the left axis, divided by the size of the range\n", + "ax2.set_ylim(*(y / max_combination_value for y in ax1.get_ylim()))\n", + "\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.15" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/docs/bottom_up_construction.md b/docs/bottom_up_construction.md new file mode 100644 index 0000000..1b21708 --- /dev/null +++ b/docs/bottom_up_construction.md @@ -0,0 +1,82 @@ +--- +type: concept +title: Bottom-up construction +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# 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 {#1-seed-partitions-of-the-pending-action-queue} + +A partition $\pi$ of $Q$ 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 $n$ is small enough, add the whole partition-refinement lattice. The number of partitions is the Bell number $B_n$, 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 $n$ partitions provide $O(n)$ 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 {#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 {#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 $k$ acceptable decompositions selected uniformly at random when at least $k$ 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 [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md)). 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 {#6-bracket-and-back-up-values} + +Evaluate every leaf under currently available information. A leaf is a pure strategy. The [Optimization framework](optimization_framework.md) 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](cost_function_consolidation.md) 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](optimization_framework.md) 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. diff --git a/docs/channels.md b/docs/channels.md new file mode 100644 index 0000000..7376b16 --- /dev/null +++ b/docs/channels.md @@ -0,0 +1,184 @@ +--- +type: Specification +title: Peer and broadcast channels +description: Generic message interfaces, transport interactivity, privacy profiles and anonymous replies. +status: draft +stale_after: 2027-04-15T00:00:00Z +--- + + + +# 🤖 Peer and broadcast channels + +## Scope and status + +Channels deliver messages for the [protocol suite](overview.md). Peer channels carry payment negotiation and neighbor reconciliation; broadcast channels disseminate contributions to a group. This draft describes generic interfaces and their required characteristics. It leaves wire formats, concrete Rust trait signatures and transport selection open. + +The interfaces separate message direction, addressing, interactivity, delivery and privacy. A bidirectional channel need not be connection based; a broadcast channel need not identify its sender. An asynchronous programming interface alone establishes neither property. + +At the protocol boundary, Fungi consumes capabilities meeting those requirements. The application's [contact and identity integrations](contacts.md#capability-boundary-and-application-integration) handle preferred identifiers, discovery, authentication and revocation, and supply or withdraw usable capabilities. The protocol need not implement an identity system to use an authenticated channel. + +## Message interfaces and composition + +A send capability accepts a message of type `M`; a receive capability yields a message of type `M`. Each defines its own error type. A bidirectional interface combines send and receive capabilities, possibly with different message types in each direction. These operations suffice for both peer and broadcast communication; the endpoint's semantics determine which messages reach whom. + +The following notation describes capabilities, rather than prescribing Rust declarations: + +| Interface | Operation | Contract | +| --- | --- | --- | +| `SendChannel` | `send(M)` | Submit one message under the channel's declared delivery and privacy profile. | +| `RecvChannel` | `recv()` | Receive one message under that profile. | +| `Bidirectional` | Both operations | Receive `I` and send `O`; no requirement that either operation completes first. | +| `ChannelBuilder` | Build from configuration or addressing data | Produce a capability, performing setup interactions where required. | + +A successful send must specify what it acknowledges: acceptance into a local queue, storage at a relay, or receipt by the destination. These events do not establish application acceptance or inclusion in a completed transaction phase. Error types can describe transport-specific failures without requiring every transport to have a concept such as a broken connection or an unreachable peer. + +Adapters provide composition without imposing it on every implementation: + +* `Duplex` pairs independent send and receive capabilities. Two simplex mailbox sequences can provide a bidirectional channel this way; a Tor stream is already bidirectional. +* Splitting a native bidirectional implementation into independently driven halves is a separate adapter when supported. Splitting and shared ownership are not requirements of the message interfaces. +* A conversion `f: T -> U` adapts a sender of `U` into a sender of `T`, or a receiver of `T` into a receiver of `U`. Fallible conversions extend the error type. Encoding and decoding are instances of this composition; byte serialization stays at the transport boundary. + +Exclusive ownership of a send capability provides a natural place for mutable sequence state. Sharing it among concurrent writers is an additional policy. In particular, pairing two simplex channels does not authorize two writers to reuse one sequence of mailbox slots. + +## Peer addressing + +A peer channel targets one logical counterparty. Peer management associates the underlying capabilities with the expected peer identity, authentication evidence, trust policy and session lifetime. Possession of a transport address alone need not authenticate a payment counterparty. + +The message interfaces do not require a `peer_id()` operation. A peer wrapper can hold an identity together with the channel; a receive endpoint may instead accept messages from many senders without a separate accept operation. Nym raw messaging is an example of the latter shape. Demultiplexing and authentication then establish which logical exchange a message belongs to. + +A long-lived contact can have addresses on several transports. Its identity and trust relationship need not change when its transport changes. Contacts can represent the user's other devices, trusted collaborators or peers trusted only for liveness. These relationships differ from the coin-associated validator identities used in Byzantine construction; [peer introduction issue #60](https://github.com/fungi-protocol/fungi/issues/60) keeps them separate. + +Peer identity and anonymous initiation can coexist. An initiator may authenticate a payment recipient while withholding its own identity. A reply capability can let the recipient answer without learning a stable return address. Authentication in the reverse direction is a separate requirement and may deliberately be absent. + +Contact channels, introductions and payment negotiation build on peer channels, and are described in the [contacts chapter](contacts.md#long-lived-authenticated-contact-channels). + +## Broadcast addressing + +A broadcast channel targets a domain, such as a transaction-construction instance or an order-book topic. A sender submits a contribution to that domain; a receiver obtains contributions admitted by its subscription and protocol rules. Domains need explicit membership or subscription rules, namespace separation and retention policies. A secret topic can restrict discovery, but does not itself hide authorship or prevent members from sharing it. + +Broadcast can be implemented by gossip over peer channels or by a specialized dissemination service. Neither implementation inherently supplies Byzantine reliable broadcast, agreement, a total order, or evidence that every participant has received a message. Those properties require additional protocol rules and assumptions. The [block DAG](optimistic-track.md) provides causal evidence for construction and recovery; its interpretation remains separate from transport delivery. + +In the honest and semi-honest setting, a peer can initiate a session in its connected component and other peers decide whether to relay and participate. The initiation message binds the broadcast topic to a common construction context, including initial PSBT state and parameters; see [session initiation issue #61](https://github.com/fungi-protocol/fungi/issues/61). This transport-independent binding must survive bridging between different delivery mechanisms. + +A broadcast endpoint need not return the original author's identity. Anonymous contributions can be received without an attribution field, while validator blocks can authenticate the validator that acknowledges a set of contributions. The validator that relays or includes an output is not thereby its owner. + +### Gossip and reconciliation + +A minimal gossip exchange announces a content identifier, requests missing content and returns the requested object. [Peer set reconciliation](set-reconciliation.md) compares inventories to suppress redundant announcements and find missing identifiers; fetching preimages remains a separate operation. The same mechanism serves permissionless order-book gossip and permissioned construction. + +Anonymous submission also needs a way to inject a previously unannounced object. The existing peer-message notes propose unsolicited push, followed by forwarding to a randomly selected neighbor and announcements to other neighbors. This is a candidate dissemination policy, not an established anonymity guarantee. An announce-then-pull exchange with an identified origin can disclose who first held a contribution, even if later gossip hides its route. + +A peer channel authenticates an immediate neighbor where required. That authentication need not identify the author of a relayed contribution. Conversely, stripping the author field cannot undo attribution already revealed by the submission channel. + +## Channel characteristics + +Each usable channel profile answers the following questions. Direction and addressing are independent of the remaining properties. + +| Characteristic | Questions the profile must answer | +| --- | --- | +| Direction | Send only, receive only, or bidirectional? Are the two directions independently usable? | +| Addressing | One logical peer, one reply capability, or a broadcast domain? Can one receiver accept many senders? | +| Interactivity | Does setup or continued use require timely participation by the destination peer? What state expires if it pauses? | +| Delivery | What does send success mean? Can messages be lost, duplicated or reordered? What are retention and retry limits? | +| Authentication and confidentiality | Which endpoint or message author is authenticated? Who can read or modify a payload? | +| Unlinkability | Which messages or connections should an observer be unable to associate, and under what assumptions? | +| Metadata protection | Which observers can learn addresses, timing, sizes, volumes, topics or session associations? | +| Resource limits | What bounds message size, queued data, outstanding work and reply capacity? | + +### Interactivity relative to the data layer + +Here, **connection based** means that setup or continued delivery requires interactivity on a shorter timescale than the data layer's communication model permits peers to assume. A live stream can fail while a construction instance remains valid and is still waiting for delayed messages. This property concerns operational requirements; it does not impose synchrony on the transaction protocol. + +Tor onion-service streams require interactive introduction and rendezvous before stream use, and depend on live circuits.[^tor] A builder may therefore connect or accept, and the resulting channel can become unusable after connection loss. Rebuilding that transport need not restart construction or erase previously acknowledged inventory state. + +Nym's raw mixnet messaging API instead routes individual messages to an address without establishing a stream to the destination peer.[^nym-messaging] Local client registration, infrastructure connections, delivery retries and finite retention still have their own availability requirements. Connectionless peer messaging does not imply stateless implementation, unlimited offline delivery or a bounded delivery time. A stream adapter over a mixnet introduces additional session semantics and must be assessed separately. + +Linked store-and-forward mailboxes likewise separate a sender's submission from a recipient's retrieval. Both endpoints may interact with a storage service without being simultaneously available to each other. An initial key exchange can still require a reply before an established symmetric channel is usable; distinguish this handshake from each subsequent message delivery. + +| Delivery mechanism | Peer interaction | Native shape and lifetime | +| --- | --- | --- | +| Tor onion-service stream | Interactive setup; both endpoints participate in a live connection. | Bidirectional byte stream with message framing; rebuild after connection loss. | +| Nym raw mixnet messages | Addressed messages without a destination-peer stream handshake. | Message receive endpoint and addressed sends; replies can use SURBs. | +| Linked mailboxes over OHTTP | Independent submission and retrieval through infrastructure; any channel handshake is separate. | One writer and one reader per directional sequence; pair two sequences for bidirectional use. | +| Broadcast by gossip | Inherits each neighbor channel's interaction requirements. | A logical domain spanning multiple peer exchanges; it can outlive any one connection. | + +An `async fn` can wrap any of these mechanisms. Calling a transport "synchronous" would conflate its interactivity with the synchrony assumptions of the agreement protocol, so profiles state the actual setup, availability and expiry requirements. + +### Privacy and type separation + +**Connection unlinkability** concerns associations between separate connections. Messages on one connection can remain linkable to each other. **Message unlinkability** concerns associations between individual messages. Both require an observer and scope: privacy relative to a destination peer differs from privacy against relays or a network observer. + +An isolated Tor connection can hide the initiator's network address from the responder while exposing the association among messages sent on that stream. Opening a fresh stream for each contribution is insufficient to assert message unlinkability: circuit sharing, isolation configuration, timing, volume and application fingerprints also matter. A mixnet's message-oriented interface alone is likewise insufficient; its traffic model and the application's contents and reply identifiers affect the claim. + +Privacy tags on capabilities and builders can prevent structurally compatible channels from being used in the wrong role. A code path requiring anonymous output submission should require the corresponding declared message-unlinkability and metadata profile. Naming the property directly avoids an ambiguous "anonymous" tag that might mean only that no explicit sender identifier was attached. Such tags express assumptions and implementation obligations; they are not proofs that a transport deployment satisfies them. + +Adapters must preserve these obligations. A serialization adapter cannot manufacture unlinkability; adding a stable sender key, cookie or session tag can destroy it. Combining send and receive halves does not automatically give both directions the same privacy guarantees. + +## Single-use reply blocks + +A single-use reply block (SURB) gives the responder one anonymous return capability. The initiator prepares a protected return route and the material needed to construct a reply. The responder can use it without learning the initiator's destination address. Nym exposes this mechanism for anonymous replies.[^nym-surbs] + +At the interface boundary, a SURB can be modeled as a consumable send capability with bounded payload capacity. It supplies a return path without requiring a persistent bidirectional connection. The surrounding adapter can pool capabilities, fragment replies and request replenishment, but those operations have visible resource and latency costs. + +The reply contract must account for: + +* Single use: consumption must prevent accidental reuse. A failed or canceled send needs an explicit rule for whether the capability may already have been spent. +* Capacity: one logical reply may consume several SURBs. Reserve enough capacity for control traffic or define how exhaustion recovers. +* Validity: route availability, key changes and local storage policy can invalidate a reply capability. Profiles must specify expiry behavior without assuming a universal Nym lifetime. +* Replenishment: obtaining more capabilities introduces further communication. It must respect the data layer's tolerance for delay and must be bounded against resource exhaustion. +* Linkability: the request and reply are associated by the responding application. Nym sender tags can also group reply capabilities into a session. Hiding a return address does not make all messages in that session unlinkable. + +A SURB routes a reply; the application must separately establish any required counterparty authentication, confidentiality and integrity. Interactive payment delegation can use a reply path while keeping the initiator anonymous to the recipient. Public output submission should not acquire a stable session identifier merely because the transport supports replies. + +## Browser clients, mailboxes and bridging + +The [OHTTP priorities discussion](https://github.com/fungi-protocol/fungi/issues/73#issuecomment-5816227367) identifies browser and mobile web clients as an immediate target. Its minimal approach is a simplex peer channel with one writer and one reader, then ordinary epidemic gossip over those channels. A specialized multiparty broadcast service is a separate optimization path. Nym's browser messaging client is another candidate; browser deployment does not inherently require OHTTP. + +For the existing Payjoin directory path, compatibility is with directory infrastructure, rather than with BIP 77 payment clients. That path must preserve the directory's fixed-size opaque framing and write-once/read-once traffic profile. A Fungi logical message may need framing across several such payloads. Treating one mailbox as a contended multiparty broadcast destination changes its privacy and censorship properties; it is not a consequence of implementing the send and receive interfaces. + +A future service designed for multiple writers and readers can choose a different storage and dissemination model. Its profile must specify request and response size protection, key discovery and consistency, relay selection and retry policy, and confidentiality against stored-traffic decryption. The discussion calls for evaluating post-quantum protection at the payload, OHTTP and TLS layers. These are design requirements to evaluate, not claims that the existing directory path provides them. + +The [Tor/OHTTP bridge plan](https://github.com/fungi-protocol/fungi/issues/10) forwards logical messages across transports. Its [identity and deduplication rules](https://github.com/fungi-protocol/fungi/issues/8) belong to the message envelope and inventory layer. A bridge must preserve the construction namespace and content identity while evaluating what new metadata its operators can observe. Bridging transports neither transfers their privacy guarantees automatically nor establishes anonymity of the resulting broadcast path. + +## Applying the interfaces + +| Use | Addressing and capabilities | Additional requirements | +| --- | --- | --- | +| Initiation through a trusted contact | Long-lived authenticated contact channel over replaceable transport capabilities. | Initiate an honest or semi-honest session, potentially within a BFT session; persist the contact binding and safe messaging state. | +| Manual introduction and session initiation | Out-of-band descriptor or invitation over an existing contact channel, then peer and broadcast capabilities. | Initiate an honest or semi-honest session, potentially within a BFT session; verify its context and scope, with independent local acceptance. | +| Payment planning, coalition coordination and confirmation | Honest or semi-honest peer session over a contact channel or manual introduction. | Notify the payee, agree which coalition attempts to pursue, then confirm the DAG's message-set commitments, including proofs, before signing; the construction session may be BFT. | +| Anonymous transaction contributions | Send to the construction broadcast domain. | Message unlinkability and metadata protection appropriate to the fault model; dissemination must preserve required inclusion. | +| Inventory and content exchange | Neighbor send and receive. | Scope requests to advertised roots, validate contents, bound work and tolerate delayed or repeated messages. | +| Order-book dissemination | Broadcast subscriptions and neighbor exchanges. | Permissionless admission, retention and resource policies; relayed proofs remain independently verifiable. | + +Reconciliation exchanges name their immutable root and scope, so a delayed response remains interpretable after a newer advertisement or a transport rebuild. Retaining a peer's acknowledged baseline can avoid repeating work, provided the peer binding and evidence remain valid. A newly created channel to a different or anonymous counterparty must not inherit another peer's knowledge claims merely because it uses the same transport. + +Streaming reconciliation describes a sequence of messages, not a requirement for a live byte stream. A narrowing range reply stops further parent-scope transmission when processed; cells already in transit can arrive later and must remain distinguishable from child-scope cells. For store-and-forward or mixnet delivery, scheduling and outstanding-data limits must account for that delay. + +Neither a successful send, an exhausted receive queue nor an expired connection establishes reconciliation quiescence or phase completion. The consuming protocol interprets evidence of completion under its communication and fault assumptions. + +## Design provenance and open choices + +This draft develops the channel and gossip portions of the existing `peer-messages` draft (`onwloqro`, snapshot `1f68a962`). That branch also contains transaction, block and introduction notes; those remain separate. The newer DAG and reconciliation specifications supply the synchronization context here. + +Relevant feedback in the Fungi monorepo includes: + +* Cindy's [channel abstraction review](https://github.com/fungi-protocol/fungi/pull/17#discussion_r3994764107): builders can perform interactive connection setup or construct capabilities from an address; [typed adapters](https://github.com/fungi-protocol/fungi/pull/17#discussion_r4020203904) separate message conversion from transport. +* Cindy's [typed channel review](https://github.com/fungi-protocol/fungi/pull/32#pullrequestreview-5223909618): privacy tagging, interactivity and generic adapters are distinct concerns. Later feedback [names unlinkability directly](https://github.com/fungi-protocol/fungi/pull/32#discussion_r4106065317) and [places peer identity with peer management](https://github.com/fungi-protocol/fungi/pull/32#discussion_r4106122178). +* The [Cap'n Proto bridge review](https://github.com/fungi-protocol/fungi/pull/35#discussion_r4021384973), posted as `nothingmuch`: keep message and error types generic instead of assuming connection-specific failures at the RPC boundary. +* The [in-memory channel review](https://github.com/fungi-protocol/fungi/pull/34#pullrequestreview-5217326680): typed message channels, connection setup and store-and-forward simulation can be composed as separate layers. +* Cindy's [bidirectional adapter follow-up](https://github.com/fungi-protocol/fungi/pull/83#discussion_r4232570038): `Bidirectional` names the capability and `Duplex` names the pair adapter. +* 0xZaddyy's [linked mailbox review](https://github.com/fungi-protocol/fungi/pull/107#discussion_r4186249336): separate pure derivation, mutable sequence state and I/O. A [handshake can establish a subsequent symmetric channel](https://github.com/fungi-protocol/fungi/pull/107#discussion_r4186442342); this is design direction, not a specified cryptographic profile. +* 0xZaddyy's [simplex transport review](https://github.com/fungi-protocol/fungi/pull/111#pullrequestreview-5417305690): expose exclusive ownership of each simplex sequence, then pair opposite directions into a bidirectional channel. +* The [transport tracking issue #6](https://github.com/fungi-protocol/fungi/issues/6), [OHTTP discussion #73](https://github.com/fungi-protocol/fungi/issues/73#issuecomment-5816227367), and [naming follow-up #137](https://github.com/fungi-protocol/fungi/issues/137): anonymous broadcast over interoperating transports is the goal; simplex peer channels plus gossip provide the initial implementation path. + +Open choices include concrete trait signatures, representation of addressing and privacy tags, contact introduction and key-management profiles, persistence and resumption rules, builder roles, receive demultiplexing, delivery acknowledgements, reconnect policy, SURB budgets and a transport-specific threat model for each anonymous submission path. + +## References + +[^tor]: Tor Project. [Onion-service protocol overview](https://spec.torproject.org/rend-spec/protocol-overview.html), including interactive rendezvous and stream establishment. + +[^nym-messaging]: Nym. [Mixnet messaging module](https://nym.com/docs/developers/rust/mixnet), distinguishing individually routed messages from the stream interface. + +[^nym-surbs]: Nym. [Anonymous replies with SURBs](https://nym.com/docs/network/traffic/anonymous-replies), including sender tags, replenishment and deployment-dependent lifetimes. diff --git a/docs/coalition_formation.md b/docs/coalition_formation.md index 20ee11a..6d6ed09 100644 --- a/docs/coalition_formation.md +++ b/docs/coalition_formation.md @@ -1,10 +1,252 @@ --- -type: Stub -title: Market-based coalition formation for collaborative transaction construction +type: concept +title: Market-based coalition formation status: draft -stale_after: 2027-04-15T00:00:00Z +stale_after: 2027-01-23T00:00:00Z --- -# Market-based coalition formation for collaborative transaction construction +# Market-based coalition formation -This chapter is under review in [#18](https://github.com/fungi-protocol/docs/pull/18). Its draft is on [the pull request's branch](https://github.com/fungi-protocol/docs/blob/coalition-formation/coalition_formation.md). +## 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](https://en.wikipedia.org/wiki/Imputation_%28game_theory%29), 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 output a partition over $N$ 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 $n \leq N$ peers, $f$ of which are adversarial, liveness for transaction construction can be achieved (with privacy) by the honest subset of peers in $O(f)$ 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 $n-1$ 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 $A$, $B$, $C$, and $D$, respectively. Alice wants to CoinJoin with Bob and Carol. She creates a co-spend proposal with UTXOs $\{ A, B, C \}$. In this proposal, she adjusts her UTXO $A$ down by 100 sats, and adjusts $B$ and $C$, 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 $\{A, C\}$. + +Carol also wishes to CoinJoin with Alice and Dave. She creates a co-spend proposal with UTXOs $\{ A, C, D \}$, and adjusts $C$ down by 50 sats, $A$ up by 20, and $D$ 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 $\{ A, B, C, D \}$ as the UTXOs. + +Once all parties accept Dave's proposal, consensus has been bootstrapped. Everyone can derive the same total adjustments: $A - 80$, $B + 50$, $C + 0$, $D + 30$. In general, only the owner of each coin knows their final adjustment, but in this example, Carol knows that Dave obtained $+30$ because her proposal is the only one that applies to his coin, and likewise Alice knows Bob obtained $+50$. + +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 + +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 MTU (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 MTU 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 $n-1$ 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 $k$ 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 $c_1 + 2^{(c_2 d k)}$, where $d$ is the total duration of all proofs, and $c_i$ 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. + +### 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. 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. + +"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 $n$ UTXOs can have $1 \leq m \leq n$ linkable ring signatures by the associated online keys of the named UTXOs. + +While $m < n$, 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 $m=n$ 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 $n$ 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 $n$ 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, MTU, 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 $\lfloor\frac{v}{log_2(v)}\rfloor$, where $v$ 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 is added to the coalition formation proposal's adjustment vector, which covers all UTXOs. The coalition formation proposal's surplus must be positive and needs to cover the shared transaction fields at the set feerate, but otherwise, the aggregated surplus is at the discretion of the aggregator; it may be claimed as a coordination fee, redistributed among all parties arbitrarily, or included in the mining fees. + +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 + +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 as the coordinator between all named parties. MuSig2 signing should still be initiated concurrently, even when linkable ring signatures are used to minimize the number of round trips. + +### PayJoin-like payments in multiparty transactions + +Payments requests or intents may be encoded in the co-spend proposals using the value adjustment mechanism. Even if fully accepted, such proposals are merely signalling the intention to pay, because finality is contingent on successful collaborative transaction construction. + +The sender and receiver must arrange for proposals to transfer the payment amount. This can be achieved by the receiver extending the sender's proposal with additional UTXOs (potentially of unrelated parties, although at least one UTXO should be the receiver's in order to claim the adjustment, and multiple proposals may be required to represent the full payment amount due to the range proof width restriction). The sender and receiver must collaborate to produce a balance proof, as only one or the other knows the openings of some of the homomorphic value adjustments. + +With this approach, fallback transactions as in BIPs 79-7 are no longer as prudent, since the receiver's UTXOs are much more difficult to probe. Neither sender nor receiver needs to disclose any UTXOs to each other; only the payment amount is fully known to both. + +Although out of scope for this document, peers also negotiate the payment details out of band and arrange for valid registration of the receiver outputs during transaction construction. In this setting, the receiver doesn't need to contribute a UTXO at all and may still get privacy from the sender, since their output(s) may be ambiguous, and there are no limitations arising from the use of width limited range proofs. + +### 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 + +A transaction construction protocol can provide liveness, although in this setting, relying on KVACs would require one of the peers to serve as the coordinator, and it would be trusted. With modification, this coordinator could prove all transcript messages it accepted are valid, but may still arbitrarily censor certain operations, causing a UTXO to be unfairly blamed for failing to sign. + +Technically the coalition formation proposal can implement a coordination fee mechanism — for example, by making all adjustments slightly negative, apart from that of the coordinator (which may or may not be the aggregator). This provides the coordinator with an incentive to coordinate honestly on average. Unfortunately, this does little for any targeted censorship risk, so long as the payoff from censorship (of e.g. a specific TxOut) dominates over the expected loss of revenue from sabotaging a single attempt at transaction construction. It's likely that the majority of the revenue is still recoverable in a subsequent blame round, as the other participants have no indication that censorship has occurred. + +For a more robust mechanism, coalition formation outputs a set of online keys for a coalition, and among other things, these are intended to be used to implement byzantine fault tolerant state machine replication for transaction construction. The initial state, based on the coalition formation proposal, can be proven valid with respect to each UTXO's adjustment sum commitments, which enforces that the agreed to imputation is in effect. + +The state machine collects inputs and outputs of a transaction (or tree of transactions a la CoinJoinXT). Since state messages are self authenticating, authenticating using zero knowledge proofs (anonymous credentials or ring signatures), they can be posted anonymously, much like in a permissioned blockchain, where all peers act as validators. diff --git a/docs/collaborative_txn_privacy.md b/docs/collaborative_txn_privacy.md index 73367b7..06a318d 100644 --- a/docs/collaborative_txn_privacy.md +++ b/docs/collaborative_txn_privacy.md @@ -1,10 +1,1033 @@ --- -type: Stub +type: Problem Definition title: Collaborative transaction privacy +description: Challenges for privacy in multiparty transaction settings, from PayJoin to CoinJoin. status: draft -stale_after: 2027-04-15T00:00:00Z +stale_after: 2027-01-23T00:00:00Z --- # Collaborative transaction privacy -This chapter is under review in [#7](https://github.com/fungi-protocol/docs/pull/7). Its draft is on [the pull request's branch](https://github.com/fungi-protocol/docs/blob/problem-definition/collaborative_txn_privacy.md). +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.[^newman] 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.[^cioh-wp][^cioh-scroll] + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + a1("input 0.5"):::ac --> tx1["transaction 1"]:::txn + a2("input 0.3"):::ac --> tx1 + tx1 --> pay1("payment 0.6"):::bc + tx1 --> chg1("change 0.2"):::ac + chg1 --> tx2["transaction 2"]:::txn + a3("input 0.4"):::ac --> tx2 + tx2 --> pay2("payment 0.5"):::cc + tx2 --> chg2("change 0.1"):::ac +``` + +*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.[^reid-harrigan][^ron-shamir][^androulaki][^meiklejohn][^nick][^harrigan-fretter][^scroll-history] + +## 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.[^forms] 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. + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#5778a4,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#e49444,color:#111,rx:12,ry:12 + classDef payA fill:#da817d,stroke:#5778a4,stroke-width:3px,color:#111,rx:12,ry:12 + classDef payB fill:#9dc5c1,stroke:#e49444,stroke-width:3px,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + ai("Alice's input 0.9"):::ac --> tx["transaction"]:::txn + bi("Bob's input 0.3"):::bc --> tx + tx --> pa("payment 0.5"):::payA + tx --> cb("Bob's change 0.1"):::bc + tx --> pb("payment 0.2"):::payB + tx --> ca("Alice's change 0.4"):::ac + linkStyle 0,2,5 stroke:#5778a4,stroke-width:3px + linkStyle 1,3,4 stroke:#e49444,stroke-width:3px +``` + +*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.[^p2ep][^bip79][^bip78][^bip77] 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: + +```mermaid +flowchart LR + classDef alice fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bob fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + ai("Alice's input 0.9"):::alice + bi("Bob's input 0.6"):::bob + tx["transaction"]:::txn + pay("Bob's output 1.1"):::bob + chg("Alice's change 0.4"):::alice + ai --> tx + bi --> tx + tx --> pay + tx --> chg +``` + +*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.[^uih-adamisz][^uih-ghesmati] 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.[^payjoin-entropy] + +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.[^ns1r] 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: + +```mermaid +flowchart LR + classDef s1c fill:#7993b6,stroke:#000,color:#111 + classDef s2c fill:#e9a969,stroke:#000,color:#111 + classDef s3c fill:#da817d,stroke:#000,color:#111 + classDef rc fill:#9dc5c1,stroke:#000,color:#111 + ls1(["Alice"]):::s1c -- "0.2" --> lr(["Dave"]):::rc + ls2(["Bob"]):::s2c -- "0.3" --> lr + ls3(["Carol"]):::s3c -- "0.7" --> lr +``` + +*The payment graph, which isn't observable on-chain.* + +```mermaid +flowchart LR + classDef s1c fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef s2c fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef s3c fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef rc fill:#9dc5c1,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + r1("Dave's input 0.4"):::rc + s1("Alice's input 0.5"):::s1c + s2("Bob's input 0.6"):::s2c + s3("Carol's input 0.9"):::s3c + tx["transaction"]:::txn + pay("Dave's output 1.6"):::rc + c1("Alice's change 0.3"):::s1c + c2("Bob's change 0.3"):::s2c + c3("Carol's change 0.2"):::s3c + r1 --> tx + s1 --> tx + s2 --> tx + s3 --> tx + tx --> c2 + tx --> pay + tx --> c3 + tx --> c1 +``` + +*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,[^ns1r] 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.[^siblings] + +## Many senders, many receivers (NSNR) + +The two sides can instead be made symmetric. Let $n = 2m$ be the number of participants, half spending and half receiving. The transaction consists of $m$ payments between the $n$ sub-transactions, pairing sub-transactions uniquely. + +```mermaid +flowchart LR + classDef s1c fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef s2c fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef s3c fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef r1c fill:#9dc5c1,stroke:#000,color:#111,rx:12,ry:12 + classDef r2c fill:#88b279,stroke:#000,color:#111,rx:12,ry:12 + classDef r3c fill:#ecd580,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + s1("Alice's input 0.9"):::s1c --> tx["transaction"]:::txn + r3("Frank's input 0.15"):::r3c --> tx + s2("Bob's input 0.4"):::s2c --> tx + r1("Dave's input 0.3"):::r1c --> tx + s3("Carol's input 0.45"):::s3c --> tx + r2("Erin's input 0.35"):::r2c --> tx + tx --> p2("Erin's output 0.85"):::r2c + tx --> c3("Carol's change 0.25"):::s3c + tx --> p1("Dave's output 0.5"):::r1c + tx --> c1("Alice's change 0.4"):::s1c + tx --> p3("Frank's output 0.45"):::r3c + tx --> c2("Bob's change 0.1"):::s2c +``` + +*A multiparty PayJoin transaction with three payments between six participants, with one input and one output per party.* + +```mermaid +flowchart LR + classDef s1c fill:#7993b6,stroke:#000,color:#111 + classDef s2c fill:#e9a969,stroke:#000,color:#111 + classDef s3c fill:#da817d,stroke:#000,color:#111 + classDef r1c fill:#9dc5c1,stroke:#000,color:#111 + classDef r2c fill:#88b279,stroke:#000,color:#111 + classDef r3c fill:#ecd580,stroke:#000,color:#111 + ls1(["Alice"]):::s1c -- "0.5" --> lr2(["Erin"]):::r2c + ls2(["Bob"]):::s2c -- "0.3" --> lr3(["Frank"]):::r3c + ls3(["Carol"]):::s3c -- "0.2" --> lr1(["Dave"]):::r1c +``` + +*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: + +```mermaid +flowchart LR + classDef s1c fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef s2c fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef s3c fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef r1c fill:#9dc5c1,stroke:#000,color:#111,rx:12,ry:12 + classDef r2c fill:#88b279,stroke:#000,color:#111,rx:12,ry:12 + classDef r3c fill:#ecd580,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + s1("Alice's input 0.9"):::s1c --> tx["transaction"]:::txn + r3("Frank's input 0.15"):::r3c --> tx + s2("Bob's input 0.4"):::s2c --> tx + r1("Dave's input 0.3"):::r1c --> tx + s3("Carol's input 0.45"):::s3c --> tx + r2("Erin's input 0.35"):::r2c --> tx + tx --> c1("Alice's change 0.85"):::s1c + tx --> c3("Carol's change 0.25"):::s3c + tx --> p1("Dave's output 0.5"):::r1c + tx --> p2("Erin's output 0.4"):::r2c + tx --> p3("Frank's output 0.45"):::r3c + tx --> c2("Bob's change 0.1"):::s2c +``` + +*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.[^uih-adamisz][^uih-ghesmati] 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 $\frac{n}{2}$ payments among $n$ participants, net settlement allows odd $n$ and up to $\frac{n(n-1)}{2}$ 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 $n$ is in general not observable from the transaction (though in some cases it can be statistically or directly inferred from its structure). + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + ia("Alice's input 0.6"):::ac --> tx["transaction"]:::txn + ib("Bob's input 0.2"):::bc --> tx + ic("Carol's input 0.5"):::cc --> tx + tx --> oc("Carol's output 0.4"):::cc + tx --> oa("Alice's output 0.5"):::ac + tx --> ob("Bob's output 0.4"):::bc +``` + +*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.* + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111 + classDef bc fill:#e9a969,stroke:#000,color:#111 + classDef cc fill:#da817d,stroke:#000,color:#111 + A(["Alice"]):::ac -- "0.5" --> B(["Bob"]):::bc + B -- "0.3" --> C(["Carol"]):::cc + C -- "0.4" --> A +``` + +*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.[^ns-netflix][^ns-retro] + +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 generally[^moser-narayanan][^kappos], and also specifically in the context of PayJoin[^sabouri] — 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,[^ns-social] 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.[^ns-linkpred] + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111 + classDef bc fill:#e9a969,stroke:#000,color:#111 + classDef cc fill:#da817d,stroke:#000,color:#111 + classDef dc fill:#9dc5c1,stroke:#000,color:#111 + classDef enc fill:#88b279,stroke:#000,color:#111 + classDef acs fill:#7993b6,stroke:#ffe234,stroke-width:4px,color:#111 + classDef bcs fill:#e9a969,stroke:#ffe234,stroke-width:4px,color:#111 + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111 + classDef ambs fill:#fafafa,stroke:#ffe234,stroke-width:4px,color:#111 + subgraph aux["auxiliary graph"] + A(["Alice"]):::ac --- B(["Bob"]):::bc + A --- C(["Carol"]):::cc + B --- C + B --- D(["Dave"]):::dc + C --- E(["Erin"]):::enc + D --- E + end + subgraph anon["anonymized graph"] + v1(["Alice"]):::acs --- v2(["Bob"]):::bcs + v1 --- v3([" ? "]):::amb + v2 --- v3 + v2 --- v4([" ? "]):::amb + v3 --- v5([" ? "]):::amb + v4 --- v5 + v1 --- v6([" ? "]):::amb + end + A -.- v1 + B -.- v2 + style aux fill:none,stroke:#777 + style anon fill:none,stroke:#777 + linkStyle 13,14 stroke:#ffe234,stroke-width:3px +``` + +*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.* + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111 + classDef bc fill:#e9a969,stroke:#000,color:#111 + classDef cc fill:#da817d,stroke:#000,color:#111 + classDef dc fill:#9dc5c1,stroke:#000,color:#111 + classDef enc fill:#88b279,stroke:#000,color:#111 + classDef acs fill:#7993b6,stroke:#ffe234,stroke-width:4px,color:#111 + classDef bcs fill:#e9a969,stroke:#ffe234,stroke-width:4px,color:#111 + classDef ccs fill:#da817d,stroke:#ffe234,stroke-width:4px,color:#111 + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111 + classDef ambs fill:#fafafa,stroke:#ffe234,stroke-width:4px,color:#111 + subgraph aux["auxiliary graph"] + A(["Alice"]):::ac --- B(["Bob"]):::bc + A --- C(["Carol"]):::cc + B --- C + B --- D(["Dave"]):::dc + C --- E(["Erin"]):::enc + D --- E + end + subgraph anon["anonymized graph"] + v1(["Alice"]):::acs --- v2(["Bob"]):::bcs + v1 --- v3(["Carol"]):::ccs + v2 --- v3 + v2 --- v4([" ? "]):::amb + v3 --- v5([" ? "]):::amb + v4 --- v5 + v1 --- v6([" ? "]):::amb + end + A -.- v1 + B -.- v2 + C -. "1" .- v3 + style aux fill:none,stroke:#777 + style anon fill:none,stroke:#777 + linkStyle 13,14,15 stroke:#ffe234,stroke-width:3px +``` + +*The only unidentified vertex adjacent to both seeds must be Carol's, so it's matched first.* + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111 + classDef bc fill:#e9a969,stroke:#000,color:#111 + classDef cc fill:#da817d,stroke:#000,color:#111 + classDef dc fill:#9dc5c1,stroke:#000,color:#111 + classDef enc fill:#88b279,stroke:#000,color:#111 + classDef acs fill:#7993b6,stroke:#ffe234,stroke-width:4px,color:#111 + classDef bcs fill:#e9a969,stroke:#ffe234,stroke-width:4px,color:#111 + classDef ccs fill:#da817d,stroke:#ffe234,stroke-width:4px,color:#111 + classDef dcs fill:#9dc5c1,stroke:#ffe234,stroke-width:4px,color:#111 + classDef encs fill:#88b279,stroke:#ffe234,stroke-width:4px,color:#111 + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111 + classDef ambs fill:#fafafa,stroke:#ffe234,stroke-width:4px,color:#111 + subgraph aux["auxiliary graph"] + A(["Alice"]):::ac --- B(["Bob"]):::bc + A --- C(["Carol"]):::cc + B --- C + B --- D(["Dave"]):::dc + C --- E(["Erin"]):::enc + D --- E + end + subgraph anon["anonymized graph"] + v1(["Alice"]):::acs --- v2(["Bob"]):::bcs + v1 --- v3(["Carol"]):::ccs + v2 --- v3 + v2 --- v4(["Dave"]):::dcs + v3 --- v5(["Erin"]):::encs + v4 --- v5 + v1 --- v6([" ? "]):::amb + end + A -.- v1 + B -.- v2 + C -. "1" .- v3 + D -. "2" .- v4 + E -. "3" .- v5 + style aux fill:none,stroke:#777 + style anon fill:none,stroke:#777 + linkStyle 13,14,15,16,17 stroke:#ffe234,stroke-width:3px +``` + +*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 analogue[^minor-nitpick] 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 paper[^reid-harrigan], 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.[^multigraph-nitpick] 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.[^maxwell] 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. + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + a1("Alice's input 0.7"):::ac --> cj["CoinJoin"]:::txn + b1("Bob's input 0.25"):::bc --> cj + b2("Bob's input 0.15"):::bc --> cj + c1("Carol's input 0.55"):::cc --> cj + cj --> e1("output 0.3"):::amb + cj --> cb("Bob's change 0.1"):::bc + cj --> e2("output 0.3"):::amb + cj --> cc2("Carol's change 0.25"):::cc + cj --> e3("output 0.3"):::amb + cj --> ca("Alice's change 0.4"):::ac +``` + +*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.[^ns-social] 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.[^danezis][^troncoso] + +Unfortunately, linking inputs to one another is practically inherent in the equal-amount approach.[^tx0] 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: + +```mermaid +flowchart LR + classDef rc fill:#9dc5c1,stroke:#000,color:#111,rx:12,ry:12 + classDef r2c fill:#88b279,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + cj1["CoinJoin 1"]:::txn + cj1 --> m2("output 0.1"):::amb + cj1 --> m3("output 0.1"):::amb + cj1 --> m1("output 0.1"):::amb + cj2["CoinJoin 2"]:::txn + cj2 --> n1("output 0.1"):::amb + cj2 --> n2("output 0.1"):::amb + cj2 --> n3("output 0.1"):::amb + m1 --> tx1["transaction"]:::txn + tx1 --> p1("payment 0.03"):::rc + tx1 --> g1("change 0.07"):::amb + n1 --> tx2["transaction"]:::txn + tx2 --> g2("change 0.04"):::amb + tx2 --> p2("payment 0.06"):::r2c +``` + +*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: + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef rc fill:#9dc5c1,stroke:#000,color:#111,rx:12,ry:12 + classDef r2c fill:#88b279,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + classDef acg fill:#7993b6,stroke:#ffe234,stroke-width:5px,color:#111,rx:12,ry:12 + cj1["CoinJoin 1"]:::txn + cj1 --> m2("output 0.1"):::amb + cj1 --> m3("output 0.1"):::amb + cj1 --> m1("Alice's output 0.1"):::acg + cj2["CoinJoin 2"]:::txn + cj2 --> n1("Alice's output 0.1"):::acg + cj2 --> n2("output 0.1"):::amb + cj2 --> n3("output 0.1"):::amb + m1 --> tx1["transaction"]:::txn + tx1 --> p1("payment 0.03"):::rc + tx1 --> g1("Alice's change 0.07"):::acg + n1 --> tx2["transaction"]:::txn + tx2 --> g2("Alice's change 0.04"):::acg + tx2 --> p2("payment 0.06"):::r2c + g1 --> cj3["CoinJoin 3"]:::txn + g2 --> cj3 + b1("Bob's input 0.13"):::bc --> cj3 + cj3 --> q1("output 0.1"):::amb + cj3 --> q2("output 0.1"):::amb + cj3 --> q3("Alice's change 0.01"):::acg + cj3 --> q4("Bob's change 0.03"):::bc + linkStyle 6,8,9,10,12,13,17 stroke:#ffe234,stroke-width:4px +``` + +*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.[^sudoku] + +The Boltzmann link probability matrix[^boltzmann] and Maurer et al.'s sub-transaction model[^maurer] 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.[^diaz][^serjantov-danezis][^syverson][^scroll-intersection] + +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.[^radix] + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + b1("Bob's input 2"):::bc --> cj["Bad CoinJoin"]:::txn + a1("Alice's input 0.3"):::ac --> cj + b2("Bob's input 5"):::bc --> cj + a2("Alice's input 0.1"):::ac --> cj + cj --> o1("Alice's output 0.4"):::ac + cj --> o2("Bob's output 7"):::bc +``` + +*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.* + +```mermaid +flowchart LR + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + b1("input 0.1"):::amb --> cj["CoinJoin"]:::txn + a2("input 0.4"):::amb --> cj + b2("input 0.2"):::amb --> cj + b3("input 0.5"):::amb --> cj + a1("input 0.3"):::amb --> cj + cj --> o1("output 0.7"):::amb + cj --> o2("output 0.8"):::amb +``` + +*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.[^kelen-seres] 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 connected*[^flow], 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 attacks**[^goldfeder][^scroll-intersection] possible. In such attacks, we take the candidate origins of these now-linked coins and check for any overlaps. + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111 + classDef bc fill:#e9a969,stroke:#000,color:#111 + classDef cc fill:#da817d,stroke:#000,color:#111 + classDef dc fill:#9dc5c1,stroke:#000,color:#111 + classDef enc fill:#88b279,stroke:#000,color:#111 + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb1 fill:#fdf6ec,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + classDef amb2 fill:#edf5f5,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + B(["Bob's cluster"]):::bc --> cj1 + C(["Carol's cluster"]):::cc --> cj1 + A(["Alice's cluster"]):::ac --> cj1["CoinJoin 1"]:::txn + A --> cj2["CoinJoin 2"]:::txn + D(["Dave's cluster"]):::dc --> cj2 + E(["Erin's cluster"]):::enc --> cj2 + cj1 --> x1("Alice, Bob or Carol?"):::amb1 + cj1 --> x2("Alice, Bob or Carol?"):::amb1 + cj1 --> x3("Alice, Bob or Carol?"):::amb1 + cj2 --> y1("Alice, Dave or Erin?"):::amb2 + cj2 --> y2("Alice, Dave or Erin?"):::amb2 + cj2 --> y3("Alice, Dave or Erin?"):::amb2 +``` + +*The adversary's view while the CoinJoin outputs remain unspent: six outputs in two equivalence classes, each output ambiguous among its CoinJoin's participants.* + +```mermaid +flowchart LR + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + classDef aci fill:#7993b6,stroke:#e9a969,stroke-width:8px,color:#000,font-weight:bold + classDef bc1 fill:#e9a969,stroke:#ffe234,stroke-width:2px,color:#111 + classDef cc1 fill:#da817d,stroke:#ffe234,stroke-width:2px,color:#111 + classDef aco1 fill:#7993b6,stroke:#ffe234,stroke-width:3px,color:#111,rx:12,ry:12 + classDef dc2 fill:#9dc5c1,stroke:#ff7a76,stroke-width:2px,color:#111 + classDef enc2 fill:#88b279,stroke:#ff7a76,stroke-width:2px,color:#111 + classDef aco2 fill:#7993b6,stroke:#ff7a76,stroke-width:3px,color:#111,rx:12,ry:12 + B(["Bob's cluster"]):::bc1 --> cj1 + C(["Carol's cluster"]):::cc1 --> cj1 + A(["Alice's cluster"]):::aci --> cj1["CoinJoin 1"]:::txn + A --> cj2["CoinJoin 2"]:::txn + D(["Dave's cluster"]):::dc2 --> cj2 + E(["Erin's cluster"]):::enc2 --> cj2 + cj1 --> xo1("Bob or Carol?"):::amb + cj1 --> x("Alice's output"):::aco1 + cj1 --> xo2("Bob or Carol?"):::amb + cj2 --> y("Alice's output"):::aco2 + x --> sp["transaction"]:::txn + y --> sp + cj2 --> yo1("Dave or Erin?"):::amb + cj2 --> yo2("Dave or Erin?"):::amb + linkStyle 0,1 stroke:#ffe234,stroke-width:2px + linkStyle 2,7,10 stroke:#ffe234,stroke-width:5px + linkStyle 4,5 stroke:#ff7a76,stroke-width:2px + linkStyle 3,9,11 stroke:#ff7a76,stroke-width:5px +``` + +*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 $n$ candidates, a process of elimination that rules out one candidate at a time will take $O(n)$ time to narrow down a single candidate, but if intersections are used to eliminate them then $O(\log n)$ 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. + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef ec fill:#b996b2,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + atm(("ATM")):::ec -. "withdrawal" .-> a0("Alice's coin"):::ac + a0 --> cj["CoinJoin
Alice + Bob"]:::txn + b0("Bob's coin"):::bc --> cj + cj --> x1("Alice or Bob?"):::amb + cj --> x2("Alice or Bob?"):::amb + x1 --> deposit["deposit"]:::txn + deposit --> atmd("ATM's output"):::ec +``` + +*Taken in isolation, the deposited coin is ambiguous: It could be Alice's or Bob's.* + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef ec fill:#b996b2,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef acg fill:#7993b6,stroke:#ffe234,stroke-width:5px,color:#111,rx:12,ry:12 + atm(("ATM")):::ec -. "withdrawal" .-> a0("Alice's coin"):::acg + a0 --> cj["CoinJoin
Alice + Bob"]:::txn + b0("Bob's coin"):::bc --> cj + cj --> x1("Alice's output"):::acg + cj --> x2("Bob's output"):::bc + x1 --> deposit["deposit"]:::txn + deposit --> atmd("ATM's output"):::ec + linkStyle 0,1,3,5,6 stroke:#ffe234,stroke-width:4px +``` + +*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: + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef ec fill:#b996b2,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef acg fill:#7993b6,stroke:#ffe234,stroke-width:5px,color:#111,rx:12,ry:12 + atm(("ATM")):::ec -. "withdrawal" .-> a0("Alice's coin"):::acg + atm -. "withdrawal" .-> a0b("Alice's other coin"):::acg + b0("Bob's coin"):::bc --> cj1 + a0 --> cj1["CoinJoin 1
Alice + Bob"]:::txn + cj1 --> o2("Bob's output"):::bc + cj1 --> o1("Alice's output"):::acg + a0b --> cj2["CoinJoin 2
Alice + Carol"]:::txn + c0("Carol's coin"):::cc --> cj2 + cj2 --> o3("Alice's output"):::acg + cj2 --> o4("Carol's output"):::cc + o1 --> deposit["deposit"]:::txn + o3 --> deposit + deposit --> atmd("ATM's output"):::ec + linkStyle 0,1,3,5,6,8,10,11,12 stroke:#ffe234,stroke-width:4px +``` + +*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. + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef ec fill:#b996b2,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + atm(("ATM")):::ec -. "withdrawal" .-> a0("Alice's coin"):::ac + a0 --> cj1["CoinJoin 1
Alice + Bob"]:::txn + b0("Bob's coin"):::bc --> cj1 + cj1 --> a1("Alice's output"):::ac + cj1 --> b1("Bob's output"):::bc + b1 --> cj2["CoinJoin
Bob + Carol"]:::txn + c0("Carol's coin"):::cc --> cj2 + cj2 --> c1("Carol's output"):::cc + cj2 --> b2("Bob's output"):::bc + a1 --> cj3["CoinJoin 3
Carol + Alice"]:::txn + c1 --> cj3 + cj3 --> o1("Alice's output"):::ac + cj3 --> o2("Carol's output"):::cc + o2 --> deposit["deposit"]:::txn + deposit --> atmd("ATM's output"):::ec +``` + +*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.* + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef ec fill:#b996b2,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef amb fill:#fafafa,stroke:#777,stroke-dasharray:4 3,color:#111,rx:12,ry:12 + atm(("ATM")):::ec -. "withdrawal" .-> a0("Alice's coin"):::ac + a0 --> cj1["CoinJoin 1
Alice + Bob"]:::txn + b0("Bob's coin"):::bc --> cj1 + cj1 --> a1("Alice or Bob?"):::amb + cj1 --> b1("Alice or Bob?"):::amb + b1 --> cj2["CoinJoin
Bob + Carol"]:::txn + c0("Carol's coin"):::cc --> cj2 + cj2 --> c1("Alice, Bob or Carol?"):::amb + cj2 --> b2("Alice, Bob or Carol?"):::amb + a1 --> cj3["CoinJoin 3
Carol or Bob + Alice"]:::txn + c1 --> cj3 + cj3 --> o1("Alice, Bob or Carol?"):::amb + cj3 --> o2("Alice, Bob or Carol?"):::amb + o2 --> deposit["deposit"]:::txn + deposit --> atmd("ATM's output"):::ec +``` + +*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. + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef dc fill:#9dc5c1,stroke:#000,color:#111,rx:12,ry:12 + classDef enc fill:#88b279,stroke:#000,color:#111,rx:12,ry:12 + classDef fc fill:#ecd580,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef txni fill:#444,stroke:#5778a4,stroke-width:6px,color:#fff + classDef ai fill:#7993b6,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef bi fill:#e9a969,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef ci fill:#da817d,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef di fill:#9dc5c1,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + a0("Alice's coin"):::ac --> cj1["CoinJoin
Alice + Bob"]:::txni + b0("Bob's coin"):::bc --> cj1 + cj1 --> a1("Alice's output"):::ai + cj1 --> b1("Bob's output"):::bi + b1 --> cj2["CoinJoin
Bob + Carol"]:::txni + c0("Carol's coin"):::cc --> cj2 + cj2 --> b2("Bob's output"):::bi + cj2 --> c1("Carol's output"):::ci + d0("Dave's coin"):::dc --> cjx1["CoinJoin
Dave + Erin"]:::txn + e0("Erin's coin"):::enc --> cjx1 + cjx1 --> d1("Dave's output"):::dc + cjx1 --> e1("Erin's output"):::enc + c1 --> cj3["CoinJoin
Carol + Dave"]:::txni + d1 --> cj3 + cj3 --> c2("Carol's output"):::ci + cj3 --> d2("Dave's output"):::di + e1 --> cjx2["CoinJoin
Erin + Frank"]:::txn + f0("Frank's coin"):::fc --> cjx2 + cjx2 --> e2("Erin's output"):::enc + cjx2 --> f1("Frank's output"):::fc + linkStyle 0,2,3,4,6,7,12,14,15 stroke:#5778a4,stroke-width:3px +``` + +*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. + +```mermaid +flowchart LR + classDef ac fill:#7993b6,stroke:#000,color:#111,rx:12,ry:12 + classDef bc fill:#e9a969,stroke:#000,color:#111,rx:12,ry:12 + classDef cc fill:#da817d,stroke:#000,color:#111,rx:12,ry:12 + classDef dc fill:#9dc5c1,stroke:#000,color:#111,rx:12,ry:12 + classDef enc fill:#88b279,stroke:#000,color:#111,rx:12,ry:12 + classDef fc fill:#ecd580,stroke:#000,color:#111,rx:12,ry:12 + classDef gc fill:#b9a0d8,stroke:#000,color:#111,rx:12,ry:12 + classDef txn fill:#444,stroke:#000,color:#fff + classDef txni fill:#444,stroke:#5778a4,stroke-width:6px,color:#fff + classDef ai fill:#7993b6,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef bi fill:#e9a969,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef ci fill:#da817d,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef di fill:#9dc5c1,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef ei fill:#88b279,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef fi fill:#ecd580,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + classDef gi fill:#b9a0d8,stroke:#5778a4,stroke-width:6px,color:#111,rx:12,ry:12 + + a0("Alice"):::ac --> cj1[" "]:::txni + b0("Bob"):::bc --> cj1 + cj1 --> a1("Alice"):::ai + cj1 --> b1("Bob"):::bi + a1 --> cj6[" "]:::txni + + b1 --> cj2[" "]:::txni + c0("Carol"):::cc --> cj2 + cj2 --> c1("Carol"):::ci + cj2 --> b2("Bob"):::bi + d0("Dave"):::dc --> cjx1[" "]:::txn + e0("Erin"):::enc --> cjx1 + cjx1 --> d1("Dave"):::dc + cjx1 --> e1("Erin"):::enc + c1 --> cj3[" "]:::txni + d1 --> cj3 + cj3 --> d2("Dave"):::di + cj3 --> c2("Carol"):::ci + e1 --> cjx2[" "]:::txn + f0("Frank"):::fc --> cjx2 + cjx2 --> e2("Erin"):::enc + cjx2 --> f1("Frank"):::fc + + b2 --> cj4[" "]:::txni + e2 --> cj4 + cj4 --> b3("Bob"):::bi + cj4 --> e3("Erin"):::ei + + d2 --> cj5[" "]:::txni + f1 --> cj5 + cj5 --> d3("Dave"):::di + cj5 --> f2("Frank"):::fi + + b3 --> cj6 + d3 --> cj6 + g0("Grace"):::gc --> cj6 + cj6 --> a2("Alice"):::ai + cj6 --> b4("Bob"):::bi + cj6 --> d4("Dave"):::di + cj6 --> g1("Grace"):::gi + + linkStyle 0,2,3,4,5,7,8,13,15,16,21,23,24,25,27,28,29,30,32,33,34,35 stroke:#5778a4,stroke-width:4px +``` + +*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,[^proximity] 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.[^scam-exchanges] + +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. + +[^newman]: M. E. J. Newman, [*The Structure and Function of Complex Networks*](https://arxiv.org/abs/cond-mat/0303516) + +[^cioh-wp]: The common-input-ownership observation appears in passing in the Bitcoin whitepaper: S. Nakamoto, [*Bitcoin: A Peer-to-Peer Electronic Cash System*](https://bitcoin.org/bitcoin.pdf) + +[^cioh-scroll]: For an informal introduction to wallet clustering, see [The Scroll #2, Wallet Clustering Basics](https://spiralbtc.substack.com/p/the-scroll-2-wallet-clustering-basics) + +[^forms]: 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](https://spiralbtc.substack.com/p/the-scroll-5-the-many-faces-of-coinjoins) + +[^payjoin-entropy]: 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. + +[^reid-harrigan]: F. Reid and M. Harrigan, [*An Analysis of Anonymity in the Bitcoin System*](https://arxiv.org/abs/1107.4524) + +[^ron-shamir]: D. Ron and A. Shamir, [*Quantitative Analysis of the Full Bitcoin Transaction Graph*](https://eprint.iacr.org/2012/584) + +[^androulaki]: E. Androulaki, G. Karame, M. Roeschlin, T. Scherer, S. Capkun, [*Evaluating User Privacy in Bitcoin*](https://eprint.iacr.org/2012/596) + +[^meiklejohn]: 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*](https://cseweb.ucsd.edu/~smeiklejohn/files/imc13.pdf) + +[^nick]: J. Nick, [*Data-Driven De-Anonymization in Bitcoin*](https://jonasnick.github.io/papers/thesis.pdf) + +[^harrigan-fretter]: M. Harrigan and C. Fretter, [*The Unreasonable Effectiveness of Address Clustering*](https://arxiv.org/abs/1605.06369) + +[^moser-narayanan]: M. Möser and A. Narayanan, [*Resurrecting Address Clustering in Bitcoin*](https://arxiv.org/abs/2107.05749) +[^kappos]: G. Kappos, H. Yousaf, R. Stütz, S. Rollet, B. Haslhofer, S. Meiklejohn, [*How to Peel a Million: Validating and Expanding Bitcoin Clusters*](https://arxiv.org/abs/2205.13882) + +[^scroll-history]: For a narrative history of clustering techniques, see [The Scroll #3, A Brief History of Wallet Clustering](https://spiralbtc.substack.com/p/the-scroll-3-a-brief-history-of-wallet) + +[^p2ep]: [Pay-to-EndPoint (P2EP)](https://blockstream.com/2018/08/08/en-improving-privacy-using-pay-to-endpoint/) +[^bip79]: R. Havar, [BIP 79: *Bustapay :: a practical coinjoin protocol*](https://github.com/bitcoin/bips/blob/master/bip-0079.mediawiki) +[^bip78]: N. Dorier, [BIP 78: *A Simple Payjoin Proposal*](https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki) +[^bip77]: D. Gould and Y. Kogman, [BIP 77: *Async Payjoin*](https://github.com/bitcoin/bips/blob/master/bip-0077.md) + +[^uih-adamisz]: AdamISZ, [payjoin / unnecessary-input-heuristic writeup](https://gist.github.com/AdamISZ/4551b947789d3216bacfcb7af25e029e) + +[^uih-ghesmati]: S. Ghesmati, A. Kern, A. Judmayer, N. Stifter, and E. Weippl, [*Unnecessary Input Heuristics & PayJoin Transactions*](https://eprint.iacr.org/2022/589) + +[^boltzmann]: LaurentMT, [*Boltzmann*](https://gist.github.com/LaurentMT/d361bca6dc52868573a2), specifically the link-probability matrix. + +[^ns1r]: rust-payjoin, [PR #923 (removal of the experimental NS1R implementation, with status discussion)](https://github.com/payjoin/rust-payjoin/pull/923) + +[^siblings]: This concern is not entirely hypothetical; it applies to some CoinJoin capable wallets and Electrum's “multiple change addresses” mode. + +[^maxwell]: G. Maxwell, [*CoinJoin: Bitcoin privacy for the real world*](https://bitcointalk.org/index.php?topic=279249) + +[^maurer]: F. K. Maurer, T. Neudecker, M. Florian, [*Anonymous CoinJoin Transactions with Arbitrary Values*](https://www.comsys.rwth-aachen.de/publication/2017/2017_maurer_anonymous-coin-join-transactions-with/2017_maurer_anonymous-coin-join-transactions-with.pdf) + +[^ns-netflix]: A. Narayanan and V. Shmatikov, [*Robust De-anonymization of Large Sparse Datasets*](https://arxiv.org/abs/cs/0610105) (S&P 2008; the linked arXiv version is titled *How To Break Anonymity of the Netflix Prize Dataset*) + +[^ns-retro]: A. Narayanan and V. Shmatikov, [*Robust De-anonymization of Large Sparse Datasets: a Decade Later*](https://www.cs.princeton.edu/~arvindn/publications/de-anonymization-retrospective.pdf) + +[^ns-social]: A. Narayanan and V. Shmatikov, [*De-anonymizing Social Networks*](https://arxiv.org/abs/0903.3276) + +[^minor-nitpick]: 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. + +[^multigraph-nitpick]: 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. + +[^ns-linkpred]: A. Narayanan, E. Shi, B. I. P. Rubinstein, [*Link Prediction by De-anonymization*](https://arxiv.org/abs/1102.4374) + +[^sabouri]: A. Sabouri, [*How Wallet Fingerprints Damage Payjoin Privacy*](https://payjoin.org/blog/2026/03/25/wallet-fingerprints-payjoin-privacy/) + +[^goldfeder]: S. Goldfeder, H. Kalodner, D. Reisman, A. Narayanan, [*When the Cookie Meets the Blockchain*](https://arxiv.org/abs/1708.04748) + +[^danezis]: G. Danezis, [*Statistical Disclosure Attacks*](https://www.freehaven.net/anonbib/cache/statistical-disclosure.pdf) + +[^troncoso]: C. Troncoso, B. Gierlichs, B. Preneel, I. Verbauwhede, [*Perfect Matching Disclosure Attacks*](https://www.freehaven.net/anonbib/cache/troncoso-pet2008.pdf) + +[^scroll-intersection]: For an accessible treatment of entropy and intersection attacks on coinjoin anonymity sets, see [The Scroll #4, Intersection Attacks](https://spiralbtc.substack.com/p/the-scroll-4-intersection-attacks) + +[^kelen-seres]: D. M. Kelen and I. A. Seres, [*Towards Measuring the Traceability of Cryptocurrencies*](https://arxiv.org/abs/2211.04259) + +[^flow]: 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. + +[^diaz]: C. Diaz, S. Seys, J. Claessens, B. Preneel, [*Towards Measuring Anonymity*](https://www.freehaven.net/anonbib/cache/Diaz02.pdf) + +[^serjantov-danezis]: A. Serjantov and G. Danezis, [*Towards an Information Theoretic Metric for Anonymity*](https://bib.mixnetworks.org/pdf/serjantov2002towards.pdf) + +[^tx0]: 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. + +[^sudoku]: K. Atlas, [*Weak Privacy Guarantees for SharedCoin Mixing Service*](https://www.coinjoinsudoku.com/advisory/) (CoinJoin Sudoku) + +[^radix]: The [Radix CoinJoin Denominations](Denominations_and_gap_size_distributions.ipynb) chapter. + +[^syverson]: P. Syverson, [*Why I'm not an entropist*](https://www.freehaven.net/anonbib/cache/entropist.pdf) + +[^scam-exchanges]: 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. + +[^proximity]: 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. diff --git a/docs/contacts.md b/docs/contacts.md new file mode 100644 index 0000000..ad9a178 --- /dev/null +++ b/docs/contacts.md @@ -0,0 +1,261 @@ +--- +type: Specification +title: Contacts, devices and discovery +description: Introduction, TOFU, trust policy, revocation, application interoperability across transports, contact channels and payment negotiation. +status: draft +stale_after: 2027-04-15T00:00:00Z +--- + + + +# 🤖 Contacts, devices and discovery + +## Scope and identity model + +The goal is to authenticate a peer once, then maintain that relationship as its devices, addresses and supported transports change. A contact can initially be reachable over one transport and later advertise another without requiring the user to repeat the original identity check. Authentication of the update and of the new endpoint carries the established binding forward. + +This chapter describes application-level contact management above the [message channels](channels.md). It develops the transport-independent contact model in [peer introduction issue #60](https://github.com/fungi-protocol/fungi/issues/60). At the Fungi protocol boundary, the caller supplies a communication capability meeting the role's authentication, delivery and privacy requirements. The surrounding application and its identity integrations establish and maintain that capability. Owner-controlled keys, device authorization and a web of trust between connected peers can supply the bindings. There is no required external identity authority, registration service or globally trusted introducer. + +| Concept | Meaning | +| --- | --- | +| Contact ID | A local handle for the intended counterparty and its authentication history, devices and trust policy. It need not be a global public identifier or a transport address. | +| Contact authentication binding | Evidence accepted under local policy that associates credentials with this relationship, such as a contact-owner key or an introduction through connected peers. Authorized changes can preserve the local contact handle. | +| Device ID | An authenticated identity for one device or installation acting for the contact, with its own keys and permitted actions. | +| Transport peer ID or address | A transport-scoped identifier or delivery capability. Its namespace includes the transport and network; its binding records the device or contact authorized to use it. | +| Channel instance | A particular usable send/receive capability. Replacing it need not change the contact, device or transport identity. | + +A contact may have several devices, and each device may support several transport endpoints. Some transports combine addressing and authentication in one identifier; others require separate authentication material or offer only a consumable reply capability. The contact layer records the relevant binding rather than forcing every transport into a persistent `PeerId` API. Display names and user labels do not authenticate any of these identities. + +## Capability boundary and application integration + +Fungi uses the capability supplied to it. It need not resolve names, interpret identity records or implement device enrollment. The application chooses how to turn a preferred identifier and local trust policy into an appropriate capability. Contact management and identity backends can expose these integration operations: + +| Operation | Information supplied to the contact/channel layer | +| --- | --- | +| Resolve a contact | Devices and supported transport endpoints currently accepted for that contact. | +| Assess an introduction or update | The contact/device association, verification provenance, permitted actions and any unresolved conflict. | +| Authenticate a route | Evidence that the opened channel is bound to the expected contact and device under the accepted identity scheme. | +| Observe identity changes | Accepted endpoint additions, device changes, key transitions or revocations, with enough context to preserve continuity. | + +These are conceptual application-integration operations, not additional Fungi protocol requirements or fixed Rust signatures. A backend may authenticate an endpoint update using an owner key, a device authorized by the owner, or an introduction accepted through the local web of trust. The application selects the behavioral trust assumptions; cryptographic verification alone does not supply them. Record storage, key-management procedures and the evidence format remain behind the capability boundary. + +## Application interoperability and transport negotiation + +Applications need a more explicit common contract than the Fungi protocol itself. A versioned **contact exchange protocol** can specify how applications exchange transport support, authenticated endpoint information and lifecycle updates. An implementation can use its preferred identity backend internally, while a shared exchange profile gives another application enough information to interpret and authenticate its records. + +### Bootstrap requirements + +Peers must share at least one usable transport and a compatible way to establish an authenticated channel over it. Sharing a transport name alone is insufficient: framing, transport profile and authentication must also be compatible. The initial introduction or existing contact configuration supplies the candidate routes and authentication information needed to establish that first channel. Transport discovery after authentication cannot bootstrap a connection when no initial route exists. + +Once the channel is authenticated under the locally accepted contact binding, peers negotiate a contact-protocol version and exchange their supported transports. A bidirectional control exchange can use a native bidirectional channel, paired simplex channels or an authenticated reply mechanism. It need not require a continuously open stream or simultaneous availability. + +### Exchange semantics + +The following message roles form a draft interoperability contract. Their names describe semantics; canonical encoding remains to be specified. + +| Message role | Required information and effect | +| --- | --- | +| Capabilities | Supported contact-protocol versions, optional features, and transport/authentication profile identifiers and versions. Establish which profiles both peers understand. | +| Endpoint advertisement | Record identity, contact/device binding under a named identity profile, transport profile, peer ID or delivery address, and the authentication and update context required by that profile. Supplies a candidate additional route to the established contact. | +| State request | The desired scope and any previously accepted update checkpoint. Requests current endpoint/device information or missing updates after an offline period. | +| State response | An authenticated snapshot or update sequence with its scope and freshness context, including withdrawals needed to avoid reviving revoked bindings. | +| Withdrawal or revocation | The affected endpoint, device, credential or permission; authorizing evidence and update context under the named profile. Triggers the receiving application's revocation handling. | +| Update result | Which records were accepted, rejected, retained as unsupported or left unresolved. Distinguishes receipt from acceptance under local policy. | + +Each exchange is bound to its authenticated channel context and intended contact relationship. A profile must define how record issuers are authorized, how device bindings are verified and how updates are ordered or checked for replay. Authentication of the immediate channel alone does not authorize every claimed device enrollment or third-party introduction. + +An application can retain an authenticated advertisement for an unsupported transport without being able to use that transport yet. When both sides support the profile, it can construct another channel using the advertised information and verify the expected endpoint binding. Selecting that route preserves the established contact and assurance level. An update's receipt or a claimed privacy property does not by itself prove that the route satisfies a Fungi role's requirements. + +Transport support, endpoint availability and permission to use an endpoint are distinct. Peers can support the same transport but have no currently usable, authorized route over it. A withdrawn device or endpoint cannot be revived merely by retrying an old advertisement. If no shared usable route remains, the application reports the contact unavailable; a later compatible route can restore communication without discarding the contact history. + +### Specification boundary + +Cross-application interoperability requires a canonical envelope, message encoding, namespaced profile identifiers, version-negotiation rules and error/resource limits. Each supported identity/transport profile must specify the authentication evidence, address interpretation and revocation/freshness semantics its adapter uses. Unknown optional profiles should not prevent exchange over an already supported profile; unsupported required features must produce an explicit incompatibility result. + +These are application-level wire-protocol requirements. They allow distinct applications to exchange usable contact capabilities without standardizing their databases, UI, owner-key management or web-of-trust policy. The base encoding and concrete profiles remain specification work; this draft establishes their responsibilities rather than claiming byte-level interoperability already exists. + +## Preferred identifiers and identity integrations + +Users may prefer an existing identifier and its ecosystem rather than create a new Fungi-specific identity. An application can support several such choices while presenting the same channel capabilities to the protocol. Identifier kind, namespace and verification provenance remain attached to the contact record; translating to a local contact handle does not discard them. + +| Integration | Existing identity or discovery model | Application responsibility | +| --- | --- | --- | +| Owner-controlled key or direct introduction | A key or peer binding selected through local verification, TOFU or the web of trust. | Apply the owner's authorization and local introduction policy. | +| Matrix | Existing Matrix user and device identities, verification and cross-signing. | Preserve the distinction between account identifiers and verified cryptographic device/user bindings. | +| pkarr | Public-key-addressed, signed DNS records resolved through a DHT or relays. | Verify records under the accepted key and interpret their endpoint information under the selected profile. | +| Nostr | Public-key identities and signed events, with optional NIP-05 names. | Preserve the accepted key binding when resolving names or interpreting identity updates. | + +[Matrix cross-signing](https://spec.matrix.org/latest/client-server-api/#cross-signing) supports verification across a user's devices. Nunchuk's [earlier Matrix-based collaborative-wallet design](https://nunchuk.io/blog/group-wallet) is an example of reusing an existing communications ecosystem. [pkarr](https://github.com/pubky/pkarr) supplies signed resource-record discovery, while [Nostr NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) defines signed events. [NIP-05](https://github.com/nostr-protocol/nips/blob/master/05.md) explicitly says a changed name-to-key mapping must not silently replace a followed public key. + +Identity integration and message transport are independent choices. A user can prefer a Nostr identifier while reaching the contact over another authenticated transport. An accepted binding can associate identifiers from different systems with one contact, but matching names alone cannot establish that association. The protocol consumes the resulting capability without selecting Matrix, pkarr, Nostr or a new identity system for everyone. + +## Introduction, TOFU and trust + +An introduction supplies candidate authentication material and enough addressing information to begin communication. It can arrive through a manual exchange, an existing authenticated contact or a discovery mechanism. The record retains how the binding was established. + +With **trust on first use (TOFU)**, the application pins the authentication material accepted on first contact. Subsequent sessions must demonstrate continuity with that pin. TOFU does not independently establish that the first endpoint belonged to the person the user intended; it preserves the identity first accepted. Later fingerprint comparison or another independent verification procedure can strengthen the recorded assurance without creating a second contact. TOFU is one supported bootstrap policy; an existing owner-key binding or accepted introduction can provide another. + +Authentication status and behavioral trust are separate: + +| Dimension | Examples of recorded policy or evidence | +| --- | --- | +| Identity assurance | Discovered but unaccepted; TOFU-pinned; verified through an independent procedure; introduced by a named contact under local policy. | +| Privacy trust | Whether this contact or device may receive information whose disclosure would harm privacy. | +| Liveness trust | Whether the application assumes cooperation for the proposed honest or semi-honest session. | +| Permitted identity updates | Whether a credential or accepted introduction can advertise endpoints, enroll devices, rotate keys or introduce other contacts. | + +The existing peer-message draft distinguishes the user's own devices, peers trusted with privacy and liveness, peers trusted only with liveness, and stored-but-unused peer records. These are useful local policies, not a single authentication score. A successful handshake or an introduction does not automatically grant all of them. An introducer's permissions and any trust inherited through an introduction must be explicit; introducing another contact is distinct from announcing another endpoint for oneself. + +## Discovery and authenticated endpoint updates + +Discovery answers where a peer might be reachable and which capabilities it advertises. Authentication determines whether that information belongs to the established contact. Candidates can come from manual exchange, contact introductions or a chosen directory or rendezvous mechanism. A directory response, familiar display name or address match alone does not authorize merging a candidate into a contact. + +An established contact can announce new endpoints over its authenticated contact channel. Alternatively, it can supply an authenticated binding record that can be relayed or retrieved elsewhere. The backend interprets its issuer, permitted actions, device, transport namespace, peer ID or address, required authentication material, capabilities and update context under the chosen scheme. It checks the freshness and replacement information needed by that scheme. Unsupported transport records can be retained as authenticated information and used when local support becomes available. + +The desired flow is: + +1. Alice authenticates Bob through one supported channel, or records a TOFU pin, and stores the resulting contact binding. +2. Bob advertises another transport endpoint through credentials authorized by that binding. Alice verifies the update and records it under the existing contact and appropriate device. +3. When Alice can use that transport, she connects or exchanges messages with the endpoint and verifies the expected endpoint credentials or an authenticated exchange bound to this contact and channel context. +4. Alice exposes the resulting capability as another route to Bob. The original assurance and trust policy remain attached to the relationship; no fresh human identity check is needed for an authorized update. + +For example, a device first reached over Tor can later announce a Nym endpoint or paired mailbox setup over the existing authenticated relationship. The new transport need not carry a universal contact identifier publicly. Where the transport supports proof of endpoint-key possession, that proof is checked; otherwise the profile must specify an equivalent authenticated binding and exchange. Merely copying an advertised peer ID is insufficient. + +TOFU continuity extends through these authenticated updates, but its initial uncertainty also extends: learning another endpoint does not upgrade an unverified contact to independently verified. An unexplained key change remains a separate event requiring resolution, even if the previous transport has become unavailable. + +## Device enrollment, rotation and recovery + +An endpoint update for an existing device and enrollment of a new device are different operations. The identity backend decides whether the supplied evidence authorizes either operation under the owner's configuration and local trust policy. For an owner-key scheme, an owner can authorize device keys and their permitted actions. A web-of-trust scheme can instead express which connected peers' introductions are accepted for which purposes. Fungi consumes the resulting bindings without prescribing a device-enrollment hierarchy or introducing a trusted third party. + +Enrollment binds the new device's credentials and permitted actions to the established contact. Knowing one device's ID does not require sharing its private key with every other device. The contact record can retain per-device trust and capabilities, including whether a device may manage other devices or only communicate. + +The backend handles replay and conflicts within the chosen scheme and exposes unresolved identity changes to the application. Sequence numbers, epochs or explicit predecessor references are possible record-profile choices, not a required Fungi-wide identity log. A delayed record cannot silently undo an accepted revocation or replace a newer binding. Conflicting authenticated updates remain visible for resolution rather than choosing whichever arrived last. + +Routine key rotation can preserve continuity through an authorized transition. Loss of every trusted credential requires a recovery or renewed verification procedure; a replacement key learned solely through TOFU is not evidence of continuity with the old contact. Revocation changes which subsequent actions are accepted under the contact policy. Offline peers may learn it later, so a profile must define how it treats delayed messages and records. + +## Revocation and capability lifetime + +Revocation is a required lifecycle concern for the contact integration. Its scope must be explicit: withdrawing an endpoint, removing a device, invalidating a credential or withdrawing an introducer's permission are different events. Local removal of a privacy or liveness trust assumption is another reason to stop supplying a capability for a particular role, even if the peer's key remains valid. + +The application verifies revocation evidence according to the selected identity scheme, records the changed binding and invalidates affected cached routes and authorizations. A capability already handed to a running protocol must have a defined lifecycle response: its wrapper can stop further use and surface the loss of authorization, or the driver can withdraw and replace it. Merely deleting an address from future discovery results leaves existing channels and cached permissions unaddressed. + +Selecting another route must preserve the required authentication and privacy profile. Revoking one device must not silently authorize a newly discovered device, and losing an authenticated route must not silently trigger a weaker identity check. The contact handle can persist while particular devices and endpoints cease to be usable. + +An identity profile must describe how revocation is disseminated, what freshness can be established, and how offline or stale views are treated. Matrix, pkarr and Nostr integrations need not have identical mechanisms or guarantees. If current authorization cannot be established, the integration reports that uncertainty and local policy decides whether a capability may be supplied. Asynchronous discovery cannot promise instantaneous revocation knowledge everywhere. Handling already-received messages and an active session's commitments follows the relevant session rules. + +## Session and privacy boundaries + +Contact management supplies identity continuity for the [long-lived authenticated channel](#long-lived-authenticated-contact-channels) and the [manual introduction flow](#introductions-and-manual-session-initiation). Both can initiate honest or semi-honest sessions, including sessions operating within a broader BFT construction. Authentication of a counterparty does not confer trust in all participants of the enclosing session. + +The permissionless alternative is coalition formation with Byzantine strangers over privacy-preserving transports. That path can use its own coin-associated authentication and protocol admission rules without enrolling the strangers as persistent contacts or establishing a web-of-trust relationship. Contact discovery and permissionless coalition discovery therefore share channel machinery while retaining their distinct trust assumptions. + +Associating a contact's transport endpoints deliberately links them in the local contact record. Dissemination of that association is therefore a privacy decision. Endpoint updates should reach their intended audience under the chosen confidentiality policy; discovery does not require publishing a global contact-to-device-to-address directory. Pairwise contact credentials and scoped device identifiers are possible profiles. + +Anonymous contribution paths retain their own privacy requirements. They must not acquire contact IDs, device IDs or stable endpoint-update tags merely because the same application also manages authenticated contacts. A return capability such as a SURB can support an exchange without enrolling a persistent device or creating a long-lived contact. + +## Long-lived authenticated contact channels + +The contact-management layer separates contact and device identity from transport peer IDs. It records first-contact verification or TOFU, discovers candidate endpoints and authenticates later endpoint updates, so an established relationship can acquire new transport routes without repeating human authentication. + +Trusted contacts need a durable authenticated messaging relationship spanning multiple transaction-construction sessions. A **contact channel**, provisionally `ContactChannel`, supplies bidirectional typed messaging bound to an established contact identity. Its lifetime spans transport connections, address changes and periods when either party is offline. It can use Tor streams, paired mailboxes or another delivery mechanism underneath. + +An established contact channel provides a way to initiate an honest or semi-honest session with that contact. Manual introduction, described below, provides another. In either case, the resulting session can stand alone or operate within a broader Byzantine fault-tolerant (BFT) session. The inner session's trust assumptions apply to its participants and interactions; they do not require trusting every participant in the enclosing session. + +The abstraction separates three kinds of state: + +| State | Lifetime and responsibility | +| --- | --- | +| Contact record | Established identity, authentication keys, authorized transport addresses and local trust policy. Persists independently of any channel instance. | +| Authenticated messaging state | Binding to the contact, channel context, active key material and any sequence, replay or delivery bookkeeping required by the chosen profile. Can span multiple construction sessions and transport connections. | +| Transport capability | Current send/receive mechanism, connection or mailbox resources. Can fail or be replaced while the contact relationship persists. | + +Establishment binds the remote authentication key to the intended contact through an introduction or verification procedure. The normal trusted-contact profile authenticates both parties and protects message confidentiality and integrity. Authentication establishes who controls the accepted credentials; the local trust policy determines whether that contact is trusted with privacy, liveness or both. Neither property follows merely from successful authentication. + +The logical interface provides send and receive operations for that contact, together with lifecycle operations to establish or resume messaging, update authenticated addressing information, rotate keys and close the relationship's channel state. These operations need not perform a fresh handshake on every transport connection or message. Their concrete API and cryptographic protocol remain open. + +The contact-channel contract requires: + +* **Continuity:** resuming or switching transports preserves the authenticated counterparty binding. Pairing send and receive halves must bind both to the same intended contact and channel context. A newly observed address cannot replace that binding without authentication. +* **Durability:** persistence covers the key and sequence state needed for safe resumption. Reopening a channel must not reuse encryption nonces or mailbox slots. When safe resumption cannot be established, the profile specifies how to establish fresh messaging state. +* **Replay and delivery handling:** messages are bound to their channel context and, where applicable, construction session. Retries, duplicates and delayed messages across reconnects or transport changes have explicit handling; authentication alone supplies neither ordered nor exactly-once application delivery. +* **Key lifecycle:** the profile defines how authorized key rotation preserves contact continuity, how old in-flight messages are handled and when renewed contact verification is required. A long-lived relationship does not require one permanent traffic key; forward secrecy and recovery after compromise are separate profile choices. +* **Availability:** pending messages, retention, acknowledgements and expiry have defined bounds. An offline contact can delay progress without terminating the relationship or implying that a transaction phase has completed. + +Messages within this relationship are intentionally attributable to the contact at the receiving endpoint. Transport metadata protection can still hide network addresses and activity from other observers, but contact authentication does not provide message unlinkability relative to that contact. Anonymous transaction contributions therefore use a separate submission capability rather than inheriting the contact channel's identity or session tags. + +This extends the contact model in [peer introduction issue #60](https://github.com/fungi-protocol/fungi/issues/60). It also places [long-lived key rotation above the lower-level mailbox delivery abstraction](https://github.com/fungi-protocol/fungi/pull/107#discussion_r4186398006), allowing a finite construction session to use simpler messaging state while a persistent contact relationship manages renewal across sessions. + +## Introductions and manual session initiation + +[Contact introductions](#introduction-tofu-and-trust) establish identity and trust provenance; a session invitation binds a particular session's context. They can be exchanged together, but retain their distinct scopes. + +An **introduction** supplies the information needed to establish communication and verify the intended counterparty or session context. A user can exchange it manually, for example by scanning a QR code, following an invitation link or importing a shared file. An existing authenticated contact channel can carry the same logical information. The representation is independent of the transport used afterward. + +Both the established-contact path and the manual-introduction path initiate honest or semi-honest sessions. Such a session may itself be part of a BFT session: for example, payment counterparties can establish an inner session for delegation and confirmation while participating in broader BFT transaction construction. The invitation identifies the inner session's context and, when applicable, its relationship to the enclosing session. Accepting it establishes neither trust in all outer participants nor completion of the outer protocol's agreement conditions. + +Introductions have an explicit scope: establish a persistent contact, join one construction session, or both. Joining a session does not automatically save a trusted contact, and saving a contact does not authorize participation in future sessions. Contact introductions carry authentication material and transport addressing information; the user chooses the contact's local trust policy through the introduction procedure. + +A session invitation identifies a common construction context and supplies the capabilities needed to reach it: + +| Information | Purpose | +| --- | --- | +| Protocol version and session identifier | Distinguish this construction attempt from other attempts and interpret its parameters. | +| Initial construction state and parameters, or their verifiable commitment | Bind the initial PSBT, applicable constraints and any agreed deterministic-shuffling seed. | +| Broadcast namespace and access information | Establish the same logical domain across transports, including any secret topic material. | +| Bootstrap addressing and authentication or reply material | Reach an introducer or initial neighbors and verify the expected binding where authentication is required. | +| Scope and validity conditions | State whether the invitation is session-only, whether it also introduces a contact, and any use or expiry limits. | + +The descriptor binds these fields together so an accepted invitation cannot silently substitute a different session, topic or initial state. Encoding, commitment construction and invitation authentication remain profile choices. Manually transferring a descriptor does not itself authenticate its source; verification uses the established contact relationship or the verification procedure of the chosen out-of-band exchange. + +Manual initiation proceeds as follows: + +1. A user explicitly starts an honest or semi-honest session, either independently or within an enclosing BFT session. Their peer creates the initial context and an invitation for it, including broadcast and bootstrap information. +2. The user shares the invitation with selected peers, directly or through existing contact channels. Each recipient inspects the proposed context and independently accepts, declines or relays it under local policy. +3. An accepting peer verifies the descriptor's binding, establishes the required peer capabilities and joins the advertised broadcast domain. If only a commitment was supplied, it obtains and verifies the initial state before acting on it. +4. The peer enters the construction protocol for that context. Receiving an invitation, opening a channel and subscribing to a topic are distinct from accepting transaction terms or establishing phase agreement. The consuming protocol determines the evidence needed to proceed. + +This realizes the manual path in [session initiation issue #61](https://github.com/fungi-protocol/fungi/issues/61): any peer can initiate, while others choose whether to relay or participate. The introducer supplies a starting point; introducing peers does not confer a permanent coordinator role or transfer one peer's trust decisions to another. + +Repeated receipt of the same invitation identifies the same attempt rather than starting another construction automatically. A changed initial context requires a distinguishable descriptor and renewed acceptance where the change affects participation. Delayed, canceled and expired invitations need explicit handling in the initiation profile. Session access material is shared only with its intended recipients, and long-lived contact identifiers need not appear in anonymous contributions or public broadcast metadata. + +## Payment negotiation across the session lifecycle + +Payment negotiation uses the honest or semi-honest relationship established through a contact channel or manual introduction. It begins before transaction construction: counterparties first plan a payment and coordinate how to reach a suitable construction session, then exchange payment confirmations within that session. The construction session can use the BFT protocol while their bilateral negotiation retains its own trust assumptions. + +This is also a separation of state: counterparties maintain their private negotiation state, while the construction session synchronizes the shared contributions and proofs needed for its transaction. The [state-sharding discussion](optimistic-track.md#sharded-state-and-synchronization-scope) distinguishes that partitioning from replication and validation within each shared scope. + +### Notice and planning + +A payer tells the intended payee that it intends to pay them. They can negotiate the amount, timing and other payment terms. Advance notice lets the payee account for the expected incoming payment when planning its own payments, funding needs and participation in transaction construction. The negotiation records an expected payment; its later confirmation refers to a concrete transaction state. + +The relationship can therefore outlive any one coalition-formation attempt. A changed payment plan can be communicated before construction starts, and an unsuccessful attempt can lead to another agreed attempt without losing the payment context. + +### Coordinating coalition formation + +The peers agree which coalition-formation opportunities to pursue together. For example, Alice intends to pay Bob; they agree on a maker, then Alice and Bob each independently submit a co-spend proposal to that maker. Their proposals can be aggregated into a coalition that includes both of them, allowing the payment to be settled within its transaction. + +Their private agreement coordinates the target of the attempts. Each peer still evaluates and accepts the actual proposal terms under the coalition-formation protocol. Agreement to approach the same maker does not itself establish a coalition or start transaction construction. Once a coalition is formed and its session commences, the counterparties associate their payment negotiation with that session's context. + +This also connects manual initiation with permissionless discovery: the counterparties can establish their honest or semi-honest relationship first, then arrange to participate together in a broader BFT construction session with other peers. + +### Confirmation during construction + +Once construction is underway, the counterparties exchange payment confirmations tied to the [block DAG's Merkle set commitments](optimistic-track.md#payment-confirmation-commitments). A confirmation identifies the construction instance, phase and relevant committed message sets. These sets cover transaction contributions and applicable proof messages, allowing counterparties to confirm the protocol state on which the payment depends. They establish that the proposed construction satisfies the payment agreement before input signing; they are distinct from confirmation of a transaction on the Bitcoin chain. + +The [concurrent PSBT specification](https://github.com/fungi-protocol/docs/blob/concurrent-psbt/psbt-concurrent.md#confirmation-of-successful-payment-prior-to-signing) supplies the payment-graph dependency logic. Here its confirmation target is generalized from a PSBT unique ID to the DAG's committed message sets. Proofs can be committed as protocol messages alongside transaction data without first defining PSBT fields for those proofs. Deriving the same transaction data alone does not establish agreement on those proof messages. + +The confirmation dependencies follow the payment graph: + +* A receiver whose net balance is non-negative can confirm once the committed state includes all of its intended outputs and the relevant proof obligations have been checked under its accepted validation policy. +* A receiver that sends more than it receives waits for matching confirmations from all of its own payment receivers before confirming to its senders. +* Before signing, every sender obtains confirmation from every one of its receivers for the required committed sets in the same instance and phase, and checks that the confirmed state matches the state it accepts locally. + +If relevant transaction contributions or proof messages change the confirmation's committed scope, the counterparties reconcile their views and obtain confirmations for the updated scope before signing. Different DAG frontiers can represent the same confirmed message sets; acknowledgement-only blocks need not change the confirmation target. The exact selection and encoding of the required set commitments remain part of the confirmation profile. + +An earlier agreement on a payment or maker is not a substitute for these confirmations. The bilateral exchange remains scoped to the payment and the committed protocol state, while the enclosing construction protocol supplies its own validity and phase-agreement rules. + +## Open profile choices + +The application integration needs operations to import a candidate introduction, pin or verify an identity, resolve a contact to authorized devices and supported endpoints, authenticate a newly opened route, and apply authenticated updates or revocations. Trust policy and verification provenance persist alongside those records. The shared contact exchange needs its own versioned specification; Fungi receives the resulting capabilities and their lifecycle outcomes. + +Backend profiles can choose preferred identifier systems, owner-key schemes and pairwise identity support, introduction verification, device enrollment and recovery, binding-record encoding and freshness, discovery and update dissemination, conflict resolution and persistence across the user's own devices. They must expose the scope and practical limits of revocation and capability invalidation. The protocol leaves those mechanisms abstract while preserving the central rule: an authenticated route can teach us new authorized routes to the same contact without repeating human authentication, while discovery alone cannot change who that contact is. diff --git a/docs/cost_function_abstract.md b/docs/cost_function_abstract.md deleted file mode 100644 index cbac411..0000000 --- a/docs/cost_function_abstract.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: Stub -title: Cost function framework for Bitcoin wallets -status: draft -stale_after: 2027-04-15T00:00:00Z ---- - -# Cost function framework for Bitcoin wallets - -This chapter is under review in [#15](https://github.com/fungi-protocol/docs/pull/15). Its draft is on [the pull request's branch](https://github.com/fungi-protocol/docs/blob/cost-function-abstract/cost_function.md). diff --git a/docs/cost_function_concrete.md b/docs/cost_function_concrete.md new file mode 100644 index 0000000..62f7ed9 --- /dev/null +++ b/docs/cost_function_concrete.md @@ -0,0 +1,121 @@ +--- +type: concept +title: Privacy liability terms +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# Privacy liability terms + +🤖 The concrete terms of the [cost function](optimization_framework.md). Each term is specified in its own chapter. This one summarizes them. + +## Terms + +🤖 Objective costs, such as fees and blockspace, are concrete. The terms below are privacy liabilities and preferences. + +### 🤖 Randomization {#randomization} + +Two weak preferences, defined only on outpoints. $t$ is a block hash, used as a public randomness beacon, and $x_i = H(t, i)$ for each input outpoint $i$. Each preference is worth less than 1 sat, so it only breaks ties. + +- **Individual:** $x_i$, preferring "lucky" hashes. This is a total order on coins. +- **Pairwise:** $x_i \oplus x_j$, preferring pairs with a small XOR metric. + +Both are summed over the transaction's inputs, through a monotone scaling function. They bias co-spending through market choices. See the [Randomized selection and Sybil resistance](cost_function_randomized_selection.md) chapter. + +### 🤖 Sybil resistance {#sybil-resistance} + +The provenance term estimates the size of the order book at the time of a coin's funding transaction, from that transaction's input set. So it can be seen as a multiplier for the liquidity (coindays) and the transaction cost (fees) of the observed transaction. A discount rate reduces them to one cost. It can be repeated for ancestors, subject to data availability and computational limits. + +That's why it's conservative: the cost to the adversary can be reported as a minimum cost and a predicted maximum. The estimate can also be used for degree sequence estimation in the Karrer–Newman model of the [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) chapter. + +The Sybil resistance index $L$ is a lower bound on the number $N$ of candidates, computed from joint sums of spans: + +1. Sort the input hashes $x_i$ on a circle of $2^{64}$ points. +2. $T_{m,r}$ is the smallest total width of $r$ spans with disjoint interiors, each from a hash to its $m$-th successor, plus one grid unit per span. Let $\tau_{m,r} = T_{m,r} / 2^{64}$. +3. For a hypothetical pool of $M$ candidates: + $$ + q_{m,r}(M) = \min\left(1, \frac{M^{r(m+1)} \, \tau_{m,r}^{rm}}{r! \, (rm)!}\right) + $$ +4. The score is: + $$ + S(M) = \sum_{m,r} \frac{q_{m,r}(M)^{-1/2} - 1}{m(m+1)r(r+1)} + $$ +5. $L$ is the smallest $M$, at least the number of inputs, with $S(M) \lt 1/\delta$. + +Someone examining the transaction doesn't know $t$. So they take the largest $L$ over the $W$ candidate block hashes, each at $\delta / W$. + +Joint sums are used because the estimate: + +- **is symmetric:** rotating or reflecting the hashes doesn't change $L$; +- **uses all input values:** every input's hash enters through the spans; +- **can be bounded computationally:** caps on $m$ and $r$ keep the guarantees, and sums of single gaps screen each block hash; +- **is simple to understand how it's monotone:** adding an input splits a gap, so the sums only shrink and $L$ only grows; +- **has a controllable error:** $P(L \gt N) \le \delta$ for every selection strategy. + +See the [Randomized selection and Sybil resistance](cost_function_randomized_selection.md) chapter for the terms, and the [Sybil resistance index](sybil_resistance_index.md) chapter for the proofs and measurements. + +### 🤖 Subset sum ambiguity {#subset-sum-ambiguity} + +A liability $0 \le \ell(o) \le 1$ for each output $o$ of a proposed decomposition. + +- It scores how well subset sums of the other users' inputs' effective values cover the complete sumset of the decomposition from above, within a slop $\varepsilon$. +- The denser these subset sums, the more explanations, and the lower $\ell(o)$. +- Counting stops once there are enough explanations, and $\ell(o)$ only falls as inputs and outputs are learned. + +See the [Own inputs or outputs subset sum ambiguity](cost_function_subset_sum_ambiguity.md) chapter, and the [Others' inputs subset sum density](subset_sum_density.md) chapter for how density is estimated and optimized. + +### 🤖 Max flow based counterfactual path estimation {#max-flow-based-counterfactual-path-estimation} + +Disjoint flows: the number of counterfactual routes $\lfloor F / d \rfloor$ from a source coin to a set of sink coins. + +- $F$ is a max flow over the transaction graph, with every edge capped at the amount $d$. +- Each own coin gets a label $0 \le \iota(c) \le 1$ from the routes from its own origins. At $\iota(c) = 1$ it's impervious to intersection attacks. +- For coins spent together, the routes matrix, with the routes from each origin to each input, shows what an intersection can reveal. + +See the [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) chapter. + +### Consolidation + +🤖 Spending own coins together links them, and loss from intersection attacks compounds with each one. + +- 🤖 $\ell_c = (b^{\nu_0} - 1) \cdot (1 - p q)$, where $\nu_0$ is the number of inputs less one, and: + - $q = 1 - \nu / \nu_0$ measures the routes, where $\nu$ sums $1 - \iota$ over the inputs, less the largest one; + - $p$ measures the density of their subset sums. +- Normally the penalty can be larger than the budget, to avoid actions vulnerable to intersection attacks. +- 🤖 Routes and density each relieve it only in proportion to the other. +- With subset sums dense enough that the inputs can't easily be clustered, and with counterfactual routes, consolidation is tolerated freely. +- 🤖 $\ell_c = 0$ once the density reaches its threshold and every input but one is impervious. Density alone isn't enough, because comparing the ancestor sets of pairs of inputs narrows down an intersection attack efficiently, even in a large transaction. +- So the cost function compels a strategy. First CoinJoin with low fan-in while the subset sums on the inputs are dense. Once the counterfactual routes are built and the funds are well absorbed into the CoinJoin graph, consolidate their descendants, subject to the counterfactual superconcentrator condition: $K$ routes over the other users' edges only, from the earliest ancestor coins to the inputs under consideration. + +🤖 See the [Consolidation penalty](cost_function_consolidation.md) chapter. + +### 🤖 Sibling avoidance {#sibling-avoidance} + +Spending outputs of the same transaction together is penalized heavily. + +- $\ell_s = \sigma \sum_T \max(0, j_T - 1)$, where $j_T$ is the number of inputs created by transaction $T$, and $\sigma$ is large. +- Neither $\iota$ nor density reduces it. + +See the [Sibling output penalty](cost_function_siblings.md) chapter. + +### 🤖 UTXO pool diversity {#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} + +Other ad hoc terms, such as fingerprint avoidance, are yet to be specified. + +### 🤖 In the decision tree {#in-the-decision-tree} + +- **Subset sum ambiguity** can only fall as other users' inputs and outputs are learned. This gives the best and worst cases in [step 6 of *Bottom-up construction*](bottom_up_construction.md#6-bracket-and-back-up-values). +- **Labels** $\iota$, and the routes matrix entries for confirmed inputs, are fixed once a coin confirms, so they're cached per coin. Nothing other users add changes them. +- **Siblings and consolidation** are fixed when the inputs are chosen, except that $\ell_c$ can only fall as density rises. +- **Best cases** of the privacy liabilities are 0, used for pruning. +- **Randomization** changes during coalition formation, as candidates appear. The provenance term is fixed once a coin's funding transaction confirms. Both are events that trigger [re-evaluation](tactics.md#re-evaluation). diff --git a/docs/cost_function_consolidation.md b/docs/cost_function_consolidation.md new file mode 100644 index 0000000..817a1f3 --- /dev/null +++ b/docs/cost_function_consolidation.md @@ -0,0 +1,63 @@ +--- +type: concept +title: Consolidation penalty +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# 🤖 Consolidation penalty + +A privacy liability term of the [cost function](optimization_framework.md). Spending several own coins together links them, and loss from [intersection attacks](collaborative_txn_privacy.md) compounds with each one. It's tolerated freely only when the subset sums are very dense *and* the coins are already impervious to intersections. Both are required for any attenuation, and neither is sufficient alone. Each has a threshold, and the penalty is fully discharged once both meet theirs. + +- **Why unbounded.** Spending a whole wallet at once, e.g. in a hurry and without regard for privacy, would normally reveal its coins as one user's, and let all of its origin funds be traced. Under the right conditions, even such a transaction, with no other users' coins, can be safe. +- Density alone isn't enough. Comparing the ancestor sets of pairs of inputs narrows down an intersection efficiently, even in a large transaction. + +It's related to the term of the [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) chapter, which deals with the flows to the coins' ancestry. Its labels attenuate this penalty. + +## Definition + +- $I$: the own inputs of the transaction under consideration, each with a label $\iota(a) \in [0, 1]$, the degree to which $a$ is already impervious to intersections. + - The labels come from the [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) chapter, and are taken as given here. +- **Links.** $\nu_0 = |I| - 1$. +- **Linked count.** $\nu = \sum_{a \in I} (1 - \iota(a)) - \max_{a \in I} (1 - \iota(a))$. + - A single coin gives $\nu = 0$, and so does one coin that isn't impervious spent with ones that are. +- **Routes.** $q = 1 - \nu / \nu_0$, and $q = 1$ for a single coin. +- **Density.** $\eta = \min_{a \in I} f_a$. + - $f_a$ is the size-corrected fraction of steps 3–6 of the [subset sum ambiguity](cost_function_subset_sum_ambiguity.md#definition) term, with inputs and outputs swapped, as for [inputs absorbed into outputs](cost_function_subset_sum_ambiguity.md#after-confirmation). + - The targets are the non-empty $S \subseteq I$, with $r_S = \sum_{a \in S} e_a$, the sum of their effective values. The ways are the subsets of the other users' outputs summing into $[r_S - \varepsilon, r_S]$. + - $p = 1 - \text{clamp}(\log_2(\varphi_c / \eta) / \theta_c, 0, 1)$, with $\varphi_c$ well above that term's $\varphi$. +- **Liability.** $\ell_c = (b^{\nu_0} - 1) \cdot (1 - p q)$, with $b > 1$ the factor per intersection. + - **Thresholds.** $p = 1$ once $\eta \ge \varphi_c$. $q = 1$ once every input but one has $\iota = 1$, i.e. $K$ routes. + - It's 0 only when both meet their thresholds. + - The relief from each is proportional to the other: $\partial \ell_c / \partial p \propto -q$. With $q = 0$, density relieves nothing, and with $p = 0$, routes relieve nothing. + +## In the decision tree + +- It's a privacy-related term. +- The labels are fixed when the inputs are chosen. +- **Worst case:** $\eta$ counts only the other users' outputs known so far. Before any are known, $p = 0$ and the full penalty applies, whatever the routes. +- **Best case:** $\ell_c = 0$, which is used for pruning. +- $\ell_c \ge 0$ 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 + +- $\eta$ is computed from the complete sets. +- $\ell_c \ge 0$ stays unbounded, and isn't capped at 1 once the action is taken. + +## Evaluating the wallet state + +- The term can evaluate a wallet state too. Imagine a unilateral transaction spending all of its coins right after, and take that transaction's consolidation penalty. +- 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](#open-questions) about transactions with only the wallet's own coins. Until that's settled, $p = 0$ there, and every state with more than one coin gets the full penalty. + +## Monotonicity + +- $\ell_c$ can only fall as $\eta$ rises, or as the labels rise. + +## Open questions + +- Should siblings also count towards $\nu$? +- A transaction with only the wallet's own coins has no other users' outputs, so $p = 0$ and the penalty can't be discharged. Which density applies there? For example, the [output overlap](cost_function_subset_sum_ambiguity.md#sumset-overlap) $u_o$ of the transactions that created the inputs. +- How should $p$ and $q$ be scaled? +- Should $p$ use the [input overlap](cost_function_subset_sum_ambiguity.md#sumset-overlap) $u_a$, instead of or as well as $f_a$? It's known during coalition formation, and measures how easily the inputs can be clustered. diff --git a/docs/cost_function_counterfactual_paths.md b/docs/cost_function_counterfactual_paths.md new file mode 100644 index 0000000..09861e5 --- /dev/null +++ b/docs/cost_function_counterfactual_paths.md @@ -0,0 +1,274 @@ +--- +type: concept +title: Max flow based counterfactual path estimation +status: draft +stale_after: 2026-11-05T00:00:00Z +--- + +# 🤖 Max flow based counterfactual path estimation + +A privacy term of the [cost function](optimization_framework.md). 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](collaborative_txn_privacy.md)'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. + +Its main use is to label the wallet's own coins. A coin with enough counterfactual routes from its own origins is impervious to intersection attacks. The same counts tell when spending coins together is safe from them. + +## Network + +Built from the transaction graph alone, following Maurer et al.[^maurer] It knows nothing of clustering, and it's acyclic. + +- **Coin edges.** Each coin $c$ has two vertices: where it's created, and where it's spent. An edge joins them, with capacity $v(c)$. +- **Flow edges.** For each transaction, an edge from each spent coin to each created coin. + - Capacity: $P_{I,O}(i, o) \cdot \min(v(i), v(o))$. + - $P_{I,O}(i, o)$ is the probability that $i$ and $o$ are in the same sub-transaction. +- **Link edges.** These carry no flow. They only define the neighbourhoods below. + - Between the inputs of a transaction, with probability $P_{I,I}$. + - Between its outputs, with probability $P_{O,O}$. +- **Neighbourhoods.** The super-source of a coin $s$ connects to $s$ 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 $T$ 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 set to 0: + - 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 $s$ and sink coins $T$: + +1. **Amount.** $d = \min(v(s), v(T))$, where $v(T)$ is the sum of the sinks' values. +2. **Caps.** Every coin edge and every flow edge is capped at $d$. + - 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.** $F$ is the max flow from the super-source to the super-sink. +4. **Routes.** $k(s, T) = \lfloor F / d \rfloor$. + +For several sources, $k(S, T) = \min_{s \in S} k(s, T)$. + +- A single super-source over all of $S$ 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 $v$ in which no edge carries more than $v/k$ is a $k$-route flow.[^kishimoto][^aggarwal-orlin][^chekuri-idleman] + - That is, it's a sum of bundles. Each bundle is $k$ paths that share no edge, carrying equal amounts. +- **Guarantee.** With every capped edge at $d$ and $F \ge k d$, removing any $j \lt k$ capped edges still leaves a flow of at least $(k - j) d$. + - So no $k - 1$ capped edges cut the source off from the sinks. This is the problem definition's "no small cut". +- **Uncapped edges.** These behave like $k$ 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 $d/2$ each count as one route of $d$. + +The floor makes $k$ conservative. Three disjoint coins of $d/2$ give $k = 1$, yet any one of them can be removed and $d$ still gets through. + +### Max flow alone isn't enough + +- Without caps, a single large coin can carry all of $F$, so $F$ can't tell one route from several. +- Scaling the demand to $k d$ doesn't help, for the same reason. + +## Labels + +For each own coin $c$: + +- **Origins.** $O(c)$ is the set of coins by which the wallet received the funds $c$ descends from. +- **Routes.** $k_c = \min_{o \in O(c)} k(o, \{c\})$, with the wallet's own edges set to 0. +- **Label.** $\iota(c) \in [0, 1]$ rises with $k_c$ and reaches 1 at $K$, the number of routes at which a coin counts as impervious to intersections. For example, $\iota(c) = \min(1, k_c / K)$. +- **Use.** $\iota$ is the label the consolidation term, in the [Consolidation penalty](cost_function_consolidation.md) chapter, takes as given. At $\iota(c) = 1$, $c$ adds nothing to that term's linked count $\nu$. + +Everything $k_c$ depends on exists once $c$ confirms: the coins between its origins and $c$, the other coins in their transactions, and their link probabilities. So $k_c$ is fixed from then on, and labels are cached per coin. + +### Consolidation + +Spending own coins $I$ together links them. An intersection attack then intersects their candidate origins. + +- **Union.** $U = \bigcup_{i \in I} O(i)$: every coin by which the wallet received funds that any of them descends from. +- **Routes matrix.** $M_{i,u} = k(u, \{i\})$, for each $i \in I$ and $u \in U$. + - It's a bipartite graph from $U$ to $I$, 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: $k_c$ is the minimum of row $c$ over $O(c)$. +- **Reading it.** Row $i$ shows which origins $i$ has many counterfactual routes from. When every row is high in almost every column, each input's candidate origins cover almost all of $U$. The sets the adversary can intersect then have a small symmetric difference, so intersecting them reveals little. + - "Almost every" is read off $M$, not fixed in advance. For example, the columns where one row is at least $K$ and another isn't are what an intersection of those two inputs can reveal. +- **Attenuation.** The routes factor is the degree to which the consolidation penalty is attenuated. + - Without attenuation, the penalty can exceed the budget, so actions open to intersection attacks are avoided. + - Consolidation is tolerated freely only when both hold: the subset sums are dense enough that the inputs can't easily be clustered, and the counterfactual routes are in place. + - Both are required for any attenuation. Neither is sufficient on its own. + - Each has a threshold. When both meet their thresholds, the penalty is fully discharged. + - Dense subset sums aren't enough: even in a large transaction, comparing the ancestor sets of pairs of inputs efficiently narrows down an intersection attack. +- **Counterfactual superconcentrator.** The graph of other users' edges only, with the wallet's own edges set to 0. + - Sources: the earliest ancestor coins, $U$. + - Sinks: the inputs under consideration for consolidation, $I$. + - The aim is $K$ counterfactual routes across it, making it a superconcentrator: for every $j$, any $j$ sources and any $j$ sinks are joined by $j$ disjoint paths. + +## In the decision tree + +- **Fixed per coin.** Once a coin confirms, no later block adds to its ancestry. So $\iota$, and the entries of $M$ 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 $I$, and with them $U$ and the rows of $M$. Nothing other users add to the transaction changes them, so the best and worst cases are equal. +- **Outputs.** The transaction's own outputs get labels only after it confirms. +- **Order book coins.** The own inputs' coin edges are set to 0, 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 $\iota$ from $k^-$. Tightening $k^-$, with more walks or an exact $k$ on a pruned graph, can run between iterations of the decision loop in the [Mixed strategy](mixed_strategy.md) chapter. It can only raise $\iota$. +- **Score.** The routes factor attenuates the consolidation penalty. See [Consolidation](#consolidation). +- **Strategy.** Building the routes compels a strategy: + 1. While the subset sums on the inputs are dense, CoinJoin with low fan-in. + 2. Once the counterfactual routes exist and the funds are well absorbed into the CoinJoin graph, consolidate their descendants, subject to the counterfactual superconcentrator condition. + +## 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 $k$, since removing coins or edges can't raise a max flow. Some examples: + +- the last $n$ 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 $n$ inputs and $m$ outputs has $n m$ flow edges. + - Cache $P_{I,O}$ per transaction. It has a closed form for equal amounts, and needs subset sum enumeration otherwise. + - Leaving out edges with small $P_{I,O}$ gives a lower bound. +- A new block only adds coins and edges, so it never lowers $k$. + +## Approximation + +This avoids computing $k$ on the full graph. + +### 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](#pruning). +- If it can only fetch transactions adjacent to ones it knows, it uses the [bounds](#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 $d$, they set each coin's capacity. +3. **Links.** $P_{I,O}$, $P_{I,I}$ and $P_{O,O}$, 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 $p$, the fraction of unspent coins spent per block. +- Base the estimate on randomized selection, as in the [Randomized selection and Sybil resistance](cost_function_randomized_selection.md) 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.[^karrer-newman-acyclic][^karrer-newman-models] +- **Number of candidates $N$.** A larger $N$ gives a smaller $k$, so the conservative choice is an upper bound, such as the number of unspent coins. + - Randomized selection gives a lower bound $L \le N$. Using it in place of $N$ would overstate $k$. + - In the pool model below, doubling $N$ from 1000 to 2000 lowers $E[k]$ from 1.20 to 0.73 at $n = 4$, $R = 12$. + +### 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 $k$ is at most the smallest slice's capacity. +- In the prototype below, $k$ equals the smallest slice in 95% to 100% of runs. + +### Analytic estimate + +This covers the topology layer only: every coin's capacity is $d$, and every $P_{I,O}$ is 1. + +- **Growth.** $D_r$ is the number of unspent coins after block $r$ that descend from the source's neighbourhood. + - $D_{r+1} = (1 - p) D_r + \frac{p N \bar{o}}{\bar{\imath}} \left(1 - G(1 - D_r / N)\right)$. + - $\bar{\imath}$ and $\bar{o}$ are the mean numbers of inputs and outputs, and $G$ 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 $1 - G(1 - D_r / N)$, the probability that any of its inputs is a descendant. + - $A_r$, 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 $r$ is an ancestor of the sinks with probability $A_r / N$, 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. + - $X \sim \text{Binomial}(n_s, A_0 / N)$, where $n_s$ is the number of coins the source's neighbourhood first reaches. + - $Y \sim \text{Binomial}(n_T, D_{R-1} / N)$, where $n_T$ is the number of coins that first reach the sinks' neighbourhood, and $R$ is the number of blocks between them. + - $k \approx \min(X, Y)$, so $P(k \ge K) \approx P(X \ge K) \cdot P(Y \ge K)$. +- Using only the single narrowest slice, $\text{Binomial}(D_r, A_r / N)$, overestimates $k$. + +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 $k$ on each with the max flow, restricted to the coins between source and sink. +- Estimate $P(k \ge K)$ from the results. +- Unlike the analytic estimate, this covers every layer. + +**Prototype, analytic and Monte Carlo.** A pool of $N$ candidate coins of equal value. In each block, a fraction $p = 0.2$ of the pool is selected at random into transactions of $n$ inputs and $n$ outputs. The source's neighbourhood is the inputs of a transaction in the first block, and the sinks' is the outputs of one $R$ blocks later. Each Monte Carlo row is 30 to 40 runs. + +| $n$ | $N$ | $R$ | $E[k]$, Monte Carlo | $E[k]$, analytic | $P(k \ge n/2)$, Monte Carlo | $P(k \ge n/2)$, analytic | +|---|---|---|---|---|---|---| +| 4 | 1000 | 8 | 0.23 | 0.11 | 0.03 | 0.00 | +| 4 | 1000 | 12 | 1.20 | 0.97 | 0.30 | 0.23 | +| 4 | 1000 | 20 | 3.08 | 3.20 | 0.97 | 0.99 | +| 8 | 2000 | 6 | 1.43 | 1.04 | 0.03 | 0.00 | +| 8 | 2000 | 8 | 2.83 | 2.90 | 0.30 | 0.30 | +| 8 | 2000 | 12 | 5.33 | 5.58 | 0.93 | 0.97 | + +Counting only whether the first coins at each end are spent or created in time predicts $E[k] = 2.8$ at $n = 4$, $R = 8$. The graph between the ends is what limits $k$ there. + +### Bounds + +- **Upper bound.** For $k^+$, merge every coin $r$ transactions away from the source into the super-sink, and compute $k$. Do the same from the sink backwards, and take the smaller of the two. + - Keep $d$ as computed from $s$ and $T$. Merged coins raise the sink's value, and recomputing $d$ from it would break the bound. + - Merging only adds capacity, so each is an upper bound. + - The cost depends on $r$ and the local degrees, not on the chain. +- **Lower bound.** For $k^-$, take random walks forward from the source's neighbourhood and backward from the sink's. Follow $f$ randomly chosen edges per step, up to the other end's confirmation height. Compute $k$ on their union. + - The union is a subgraph, so its $k$ 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 and Sybil resistance](cost_function_randomized_selection.md) chapter, in the prototype below, this puts the smallest cut next to one of the ends, so $k = k^+$. 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 $k^-$ itself, as it approaches $k^+$. + +**Labels from bounds.** + +- $\iota$ uses $k^-$, so it's never overstated. +- If $k^- \ge K$, $c$ is impervious. +- If $k^+ \lt K$, it isn't, and more sampling won't change that. +- Otherwise, take more walks, or compute $k$ exactly on a pruned graph. + +**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 $k$ can be. +- **Random selection:** $k = k^+ = 8$ in every seed, so no route was lost in between. With 4 walks branching 2 ways per step, $k^- = 8$ in every seed. +- **Two halves that never transact with each other:** $k = 0$, while $k^+ = 8$. +- **Two halves, 10% of transactions mixed:** $k = 8$ 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 $P_{I,O} = 0$ 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](#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 $d$? +- 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 $\iota$, as the [consolidation term](cost_function_consolidation.md) 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 $M$ holds only single pairs. +- Should a privileged counterparty's own coins also be set to 0, since it knows where they went? +- Should $\iota$ ramp up to $K$, or switch from 0 to 1 at $K$? What should $K$ be? +- May $\iota$ use an estimate ($k^+$, the analytic estimate or Monte Carlo) when the randomization evidence is strong, or only $k^-$? +- **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 $n_s$ and $n_T$, 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? +- What label does an own input get before it confirms, such as change from a transaction still in flight? + +[^maurer]: F. K. Maurer, T. Neudecker, M. Florian, [*Anonymous CoinJoin Transactions with Arbitrary Values*](https://doi.org/10.1109/Trustcom/BigDataSE/ICESS.2017.280), TrustCom 2017. + +[^kishimoto]: W. Kishimoto, [*A method for obtaining the maximum multiroute flows in a network*](https://doi.org/10.1002/(SICI)1097-0037(199607)27:4%3C279::AID-NET3%3E3.0.CO;2-D), Networks 27(4), 1996. + +[^aggarwal-orlin]: C. C. Aggarwal, J. B. Orlin, [*On multiroute maximum flows in networks*](https://doi.org/10.1002/net.10008), Networks 39(1), 2002. + +[^chekuri-idleman]: C. Chekuri, M. Idleman, [*Congestion Minimization for Multipath Routing via Multiroute Flows*](https://doi.org/10.4230/OASIcs.SOSA.2018.3), SOSA 2018, Theorem 1. + +[^karrer-newman-acyclic]: B. Karrer, M. E. J. Newman, [*Random acyclic networks*](https://arxiv.org/abs/0902.4013), 2009. + +[^karrer-newman-models]: B. Karrer, M. E. J. Newman, [*Random graph models for directed acyclic networks*](https://arxiv.org/abs/0907.4346), 2009. diff --git a/docs/cost_function_randomized_selection.md b/docs/cost_function_randomized_selection.md new file mode 100644 index 0000000..cb8bf0e --- /dev/null +++ b/docs/cost_function_randomized_selection.md @@ -0,0 +1,124 @@ +--- +type: concept +title: Randomized selection and Sybil resistance +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# Randomized selection and Sybil resistance + + + +Three terms of the [cost function](optimization_framework.md). Two weak preferences randomize the choice of which UTXOs to co-spend with, using the blockchain as a randomness beacon. The provenance 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](https://en.wikipedia.org/wiki/Multistage_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](coalition_formation.md). The roles are used loosely: a single participant may perform both. + +## Inputs + +- $t$: a block hash, e.g. 144 blocks from the best known chain tip. +- $I$: the outpoints being considered for spending in a possible transaction, with $n = |I|$. +- $x_i = H(t, i)$ for each $i \in I$, where $H$ is a tagged hash. Hash outputs are interpreted as rational numbers in $[0, 1]$. +- $f_1, f_2$: monotone scaling functions, e.g. log or sqrt, possibly with a bias. + +## Per input term + +$$ +f_1\left( \sum_{i \in I} x_i \right) +$$ + +- 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 + +$$ +f_2\left( \sum_{i,j \in I} x_i \oplus x_j \right) +$$ + +- 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 $f_2$ 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 $x_i$, $x_i \oplus x_j$ is also uniform. Preferring small values also biases the $x_i$ themselves: a pair whose XOR has $b$ leading zero bits shares its $b$ most significant bits, so both lie in a random subinterval of size $2^{-b}$. This simplifies the density estimation. The Hamming distance or the arithmetic difference would change the distribution, and the scaling functions can simulate such effects. + +## 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 Sybil resistance index $L$, a lower bound on the number of candidate UTXOs $N$, computed from [joint sums](#joint-sums). +2. **Cost.** $L$ is a multiplier for the liquidity, in coindays, and the transaction cost, in fees, of the observed transaction. A discount rate reduces them to one cost. +3. **Ancestors.** Repeat for earlier transactions, subject to data availability and computational limits. + +The term rises with this cost: an inherited "luck" from previously lucky coins, or from coins that had a high affinity to each other at some previous point in time. + +- **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. +- **Conservative.** $L$ is a lower bound, so the cost to the adversary can be reported as a minimum cost and a predicted maximum. +- **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.[^bhatt] 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 [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) chapter. + +See also Belcher's analysis of fidelity bonds.[^belcher] + +### 🤖 Joint sums {#joint-sums} + +For the $n$ input hashes of the funding transaction and a confidence parameter $\delta$: + +1. **Spans.** Truncate the hashes to 64 bits, and sort them around a circle of $2^{64}$ points. An $m$-span runs from a hash to its $m$-th successor. Its width is the distance between them, plus one point. +2. **Sums.** For each $1 \le m \lt n$ and $1 \le r \le n/m$, $T_{m,r}$ is the smallest total width of $r$ spans with disjoint interiors. Spans may share endpoints. Let $\tau_{m,r} = T_{m,r} / 2^{64}$. + - For $m = 1$, this is the sum of the $r$ smallest spacings. + - Larger $m$ detects groups of nearby hashes. +3. **Tail bound.** For a hypothetical order book of $M$ candidates: + $$ + q_{m,r}(M) = \min\left(1, \frac{M^{r(m+1)} \, \tau_{m,r}^{rm}}{r! \, (rm)!}\right) + $$ +4. **Score.** + $$ + S(M) = \sum_{m,r} \frac{q_{m,r}(M)^{-1/2} - 1}{m(m+1)r(r+1)} + $$ +5. **Index.** $L$ is the smallest integer $M \ge n$ with $S(M) \lt 1/\delta$. + +Joint sums are used because they are: + +- **symmetric:** rotating or reflecting the hashes on the circle doesn't change $L$, so it doesn't matter which hashes count as lucky; +- **based on all input values:** every input's hash enters through the spans; +- **computationally bounded:** leaving out the terms above a fixed $m$ keeps the guarantees, and the $m = 1$ terms, which only need sorting, screen each candidate block hash; +- **simple to understand as monotone:** adding an input splits a spacing, so every $T_{m,r}$ can only shrink, $S$ can only grow, and $L$ can only grow; +- **of controllable error:** $P(L \gt N) \le \delta$ for every selection strategy. + +The [Sybil resistance index](sybil_resistance_index.md) chapter gives the proofs, the scan over block hashes, and measurements. + +## 🤖 In the decision tree {#in-the-decision-tree} + +- **Per input and pairwise terms** change during coalition formation, as candidates appear. +- **Provenance term** of a coin under consideration is fixed once its funding transaction confirms, so it's computed once per coin and cached. + +## After confirmation + +This is the analysis that contributes privacy gains, and that uses the budget. + +- All inputs are known, but $t$ isn't. It can be guessed from the confirmation time, or the nLockTime. +- 🤖 $L$ is the maximum over the candidate block hashes mined after the inputs confirmed, each at $\delta / W$ for $W$ candidates. See [Finding the block hash](sybil_resistance_index.md#finding-the-block-hash). +- 🤖 The provenance term of the transaction's outputs is then fixed. + +## 🤖 Open questions {#open-questions} + +- What should $\delta$ be? +- How are the minimum cost and the predicted maximum computed from $L$? +- How far back should the provenance term go, and how should the costs of several ancestors combine? The [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) chapter walks ancestors too. +- Can light clients estimate $L$ for transactions they only sample? + +[^belcher]: C. Belcher, [*Financial mathematics of JoinMarket fidelity bonds*](https://gist.github.com/chris-belcher/87ebbcbb639686057a389acb9ab3e25b#cost-of-sybil-attacks). + +[^bhatt]: S. N. Bhatt, [*On Concentration and Connection Networks*](https://hdl.handle.net/1721.1/149007), MIT, 1981. diff --git a/docs/cost_function_siblings.md b/docs/cost_function_siblings.md new file mode 100644 index 0000000..4986ecb --- /dev/null +++ b/docs/cost_function_siblings.md @@ -0,0 +1,34 @@ +--- +type: concept +title: Sibling output penalty +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# 🤖 Sibling output penalty + +A privacy liability term of the [cost function](optimization_framework.md). 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 + +- $I$: the own inputs of the transaction under consideration. +- For each earlier transaction $T$, $j_T$ is the number of its outputs in $I$. +- **Liability.** $\ell_s = \sigma \sum_T \max(0, j_T - 1)$, with $\sigma$ large. +- Neither the labels from the [Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) chapter nor [subset sum density](subset_sum_density.md) 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:** $\ell_s$ as defined. It depends only on the own inputs. +- **Best case:** $\ell_s = 0$, which is used for pruning. +- $\ell_s \ge 0$ 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 + +- $\ell_s$ is fixed once the inputs are chosen. +- Once the action is taken, the resulting coins' liability is capped at 1. + +## Open questions + +- Should $\ell_s$ extend to coins with a common ancestor further back? diff --git a/docs/cost_function_structure.md b/docs/cost_function_structure.md new file mode 100644 index 0000000..1a576cb --- /dev/null +++ b/docs/cost_function_structure.md @@ -0,0 +1,62 @@ +--- +type: concept +title: Cost function structure +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# 🤖 Cost function structure + +The evaluation of pure strategies is a family of cost functions, sharing the structure set out in the [Optimization framework](optimization_framework.md#preliminaries) 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](optimization_framework.md#global-privacy-budget), with its budget rate $p$ and remaining budget $B$, normalizes the privacy terms, so that all terms can be summed into a single amount in satoshis. + +Each coin has a *privacy liability* $\lambda$. 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. Coins received at external addresses start at the baseline $\lambda = 1$, since the wallet has no prior knowledge about them, and change outputs of unilateral payments are treated the same way. Their descendants may have a lower liability when they are produced by automated actions, reaching 0 when the coins are deemed fully private. $\lambda$ is stored per coin, but it is derived information. + +A coin's *subjective value* is its nominal value $x$ discounted by $\lambda p x$, effectively devaluing non-private wallet states. This is what turns abstract thresholds on privacy metrics into a penalty in satoshis. It simplifies the cost function so it only outputs a satoshi amount, allowing subjective and objective costs to be reduced to a single number, and therefore comparisons can be made between the wallet states predicted to result from taking one action vs. another. Since the discount depends only on the coin itself, this applies regardless of how many inputs and outputs a transaction has. + +A transaction spending coins with total discount $d_{in}$ and creating coins with total discount $d_{out}$ at an objective cost of $y$ changes the wallet's total subjective value by + +$$(d_{in} - d_{out}) - y,$$ + +so on privacy grounds alone, an action is only worth taking if the reduction in discounts dominates its 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 is not yet private, 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: + +| | nominal | $\lambda$ | discount | subjective value | change | +|---|---|---|---|---|---| +| before | 100,100 | 1 | 1,001 | 99,099 | | +| large improvement | 100,000 | 0.5 | 500 | 99,500 | +401 | +| small improvement | 100,000 | 0.8 | 800 | 99,200 | +101 | +| not worth it | 100,000 | 0.95 | 950 | 99,050 | −49 | + +Either of the first two outcomes is worth taking, and either leaves 901 sats in the remaining budget. The last reduces the discount 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: + +| | nominal | $\lambda$ | discount | subjective value | +|---|---|---|---|---| +| input | 100,100 | 1 | 1,001 | 99,099 | +| output A | 60,000 | 0.5 | 300 | 59,700 | +| output B | 40,000 | 0.9 | 360 | 39,640 | +| outputs total | 100,000 | | 660 | 99,340 | + +Discounts fall by 341, which dominates the fee, for a net change of +241. Consolidating two non-private coins of 60,000 and 40,100 sats (discounts of 600 and 401) into a single CoinJoin output of 100,000 sats with $\lambda = 0.5$ 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 $\lambda > 1$ 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 $\lambda = 1.2$, its discount is 1,200 and its subjective value 98,800, a change of −299 before any other terms. Such an increase counts against the action, which is only taken if other terms outweigh it, for example the utility of a payment with a hard deadline. Such states never materialize as the result of an automated action: once the action is taken, the resulting coins have their liability capped at the baseline of 1. The same applies if the user manually takes an action the wallet would not have taken: the loss it implies is written off 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 $x$ with total discount $d$ at a cost of $y$, results in coins whose subjective value is greater than $x - d$ and at most $x - y$ (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, providing perfect cover, 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. diff --git a/docs/cost_function_subset_sum_ambiguity.md b/docs/cost_function_subset_sum_ambiguity.md new file mode 100644 index 0000000..64cafb1 --- /dev/null +++ b/docs/cost_function_subset_sum_ambiguity.md @@ -0,0 +1,143 @@ +--- +type: concept +title: Own inputs or outputs subset sum ambiguity +status: draft +stale_after: 2026-11-05T00:00:00Z +--- + +# 🤖 Own inputs or outputs subset sum ambiguity + + + +A privacy liability term of the [cost function](optimization_framework.md). Given the wallet state and a transaction under consideration, it estimates how ambiguous a proposed output decomposition is, relative to the other users' coins known so far. It's cheap enough to evaluate for many decompositions. + +It implements [subset sum density](subset_sum_density.md) for the outputs: a bitmap or sparse convolution of the other users' inputs' effective values, with lookups for the complete sumset of the outputs, approximated from above. + +## Inputs + +- $f$: the feerate of the [coalition formation proposal](coalition_formation.md). Effective values are [fixed](subset_sum_density.md#effective-values) at $f$. +- $X$: effective values $a$ of the other users' inputs known so far, positive values only. +- $Y$: effective costs of the other users' outputs known so far. +- $I$: the own inputs, as effective values $e_a$. +- $O$: the proposed decomposition, as effective costs $c_o$, with $m = |O|$. +- $\beta$: the wallet's balance, as effective value. +- Parameters: + - $\varepsilon$: the slop; + - $A$: the number of explanations that counts as enough for one output; + - $\varphi$: the explained fraction at which the liability reaches 0; + - $\theta$: the width of the liability ramp, in bits. + +## Definition + +1. **Targets.** For each non-empty $S \subseteq O$: $s_S = \sum_{o \in S} c_o \le \beta$. +2. **Companions.** $C$ is the set of subset sums of $Y$, including 0. +3. **Ways.** $w(S, y)$, for $y \in C$, is the number of subsets of $X$ that sum into $[s_S + y, s_S + y + \varepsilon]$. + - Each one is a reading in which another user's inputs fund $S$ together with other users' outputs summing to $y$. +4. **Per-pair cap.** $\kappa = \lceil A / 2^{m-1} \rceil$. Each pair contributes at most $\kappa$ ways (satisficing). + - A large decomposition needs one explanation per combination. + - A single output needs $A$ ways for its only target. +5. **Count.** $n_o = \sum_{(S, y) : o \in S} \min(\kappa, w(S, y))$. +6. **Size correction.** $f_o = \min(1, n_o / (\kappa \cdot 2^{m-1}))$. + - Adding an output doesn't raise $f_o$ by itself. It has to pay for its blockspace through the objective cost. +7. **Liability.** $\ell(o) = \text{clamp}(\log_2(\varphi / f_o) / \theta, 0, 1)$. + - It's 0 once $n_o \ge \varphi \kappa 2^{m-1}$. + - It falls by $1/\theta$ per doubling of $n_o$. + +## Sumset overlap + +How well combinations of the user's coins match combinations of the other users' coins on the same side. Each match is a reading in which another user's coins take the place of the user's. + +- **Inputs, during coalition formation.** For each non-empty $S \subseteq I$, with $r_S = \sum_{a \in S} e_a$, $v(S)$ is the number of subsets of $X$ summing into $[r_S - \varepsilon, r_S + \varepsilon]$. + - These are lookups in $D$ or $T$, which already cover $X$. + - Steps 4–6 apply with $I$ in place of $O$ and $v$ in place of $w$, giving an overlap fraction $u_a$ per own input. +- **Outputs, in hindsight.** The same, with $O$ and the other users' outputs, once they're all known, giving $u_o$. + - The lookups are in $C$, or in a capped count table over $Y$ like $T$ when $\kappa > 1$. +- [Same side](#one-by-one) one by one matching is the case $|S| = 1$. + +## Implementation + +### Tables + +Built once per transaction and shared by all decompositions: + +- $D$: a bitmap with $D[i] = 1$ if some subset of $X$ sums into $[i, i + \varepsilon]$. It's used when $\kappa = 1$. + - Start with $D[-\varepsilon..0] = 1$. + - Then apply $D[i] \gets D[i] \lor D[i - a]$ per input, from the top down. + - Where the distinct sums are far fewer than the range, [Salas](https://arxiv.org/abs/2507.15511)'s enumerator can replace it. +- $T$: $\min(A, \text{number of subsets summing to } i)$, as u16. It's used when $\kappa > 1$. + - Apply $T[i] = \min(A, T[i] + T[i - a])$ per input, from the top down. + - Window sums stop at $\kappa$. +- $C$: a bitmap of companion sums. +- **Range:** $[-\varepsilon, \beta + y_{\max}]$, where $y_{\max}$ is the largest companion sum visited. Double it and rebuild if needed. Skip inputs that are too large to fit. + +### Updates + +- Each auxiliary input or concurrent output is one more pass over $D$, $T$ or $C$. The order doesn't matter. +- Deduplicate inputs by outpoint and outputs by output id. +- Removing a value needs uncapped counts, or a rebuild. + +### Per decomposition + +- For each $S$, add $\min(\kappa, w)$ to $n_o$ for each $o \in S$, for $y = 0$ first and then companions in increasing order. +- **Satisficing stops the work early:** + - a window, at $\kappa$; + - an output, once $\ell(o) = 0$; + - a decomposition, once all of its outputs have. + +### One by one + +Each own coin is matched against single coins of other users, using sorted arrays and binary search. + +- **Across sides:** a single input in $[c_o, c_o + \varepsilon]$, or a single output in $[e_i - \varepsilon, e_i]$. +- **Same side:** swaps within $\varepsilon$, and input and output swaps whose differences cancel. +- **Fast path:** these can satisfice an output before any table is built. + +### Radix denominations + +These are inputs with nominal value $c \cdot b^i$: + +- $b = 2$, $c = 1$; +- $b = 3$, $c \in \{1, 2\}$; +- $b = 10$, $c \in \{1, 2, 5\}$. + +They're grouped by effective value $v$, with multiplicity $m_v$. + +- **Multiplicity:** one pass per group, as a sliding window along each residue class mod $v$. +- **Contiguity:** sort the coins and keep a running sum $R$. Accept each next coin while it's $\le R + \varepsilon$, starting from a coin $\le \varepsilon$. + - Every target $\le R$ is then explained without the tables. + - Keeping $m_v - r$ coins per value gives robustness to $r$ removals per value. + +## In the decision tree + +- It's a privacy-related term. +- **Worst case:** only the coins known so far count. $X$ and $Y$ are lower bounds, and auxiliary inputs and outputs are learned later. Before any other user's outputs are known, $C = \{0\}$. +- **Best case:** $\ell(o) = 0$, which is used for pruning. +- Every participant, including the aggregator in that role, evaluates [co-spend proposals](subset_sum_density.md#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. +- $\ell(o) \in [0, 1]$. + +## After confirmation + +This is the analysis that contributes privacy gains, and that uses the budget. + +- All inputs and outputs are known. +- **Coalition formation proposal known:** evaluate at its $f$, 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. +- **Inputs absorbed into outputs:** the mirror image. + - Targets are subsets of the wallet's inputs. + - Subsets of the other users' outputs must sum into $[r_S - \varepsilon, r_S]$. + - In the decision tree, only the outputs known so far count, which before then means none. + +## Monotonicity + +- The decision tree's estimate is the same definition restricted to the lower bounds $X$ and $Y$. +- Learning inputs or outputs only adds ways and pairs, and the denominator depends only on $m$ and $A$. So $\ell(o)$ can only fall. +- This requires the same $f$, the same realized $O$, and the same parameters. + +## Open questions + +- Is $\varepsilon$ absolute, or relative to the target? Does it include adjustments? +- Should ways count input subsets, or distinct sums in the window? +- For one by one: across sides, same side, or both? +- How do $u_a$ and $u_o$ enter the liability: as their own term, or as extra ways in $n_o$? diff --git a/docs/index.md b/docs/index.md index 18aee53..aad5554 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,13 +2,41 @@ okf_version: "0.2" --- -# BIP Drafts +* [Collaborative transaction privacy](collaborative_txn_privacy.md) - Challenges for privacy in multiparty transaction settings, from PayJoin to CoinJoin. -* [PSBT Scrubber](bip-drafts/scrubber.md) - Which PSBT fields can be shared with trusted and untrusted parties such that privacy is preserved. +# Protocol Suite + +* [Overview](overview.md) - Collaborative transaction construction, privacy, fault tolerance and coalition formation. +* [🤖 Abstract transport interfaces](transport-interfaces.md) - Send and receive channels, privacy tags, and message unlinkable broadcast by gossip. +* [🤖 Peer and broadcast channels](channels.md) - Generic message interfaces, transport interactivity, privacy profiles and anonymous replies. +* [🤖 Peer set reconciliation](set-reconciliation.md) - Naive reconciliation, quiescence before block authoring, sparse Merkle sets, mutual knowledge, and range reconciliation and rateless streams as future optimizations. +* [🤖 Contacts, devices and discovery](contacts.md) - Introduction, TOFU, trust policy, revocation, application interoperability across transports, contact channels and payment negotiation. +* [Market-based coalition formation](coalition_formation.md) - Under review in #18. +* [🤖 Transaction construction](transaction-construction.md) - Content and state synchronization, the phases, the optimistic and recovery tracks, and the block DAG they share. + * [🤖 Optimistic track: blocks and phase states](optimistic-track.md) - Unanimity and phase closure on the optimistic track, phase by phase. + * [🤖 Recovery track](recovery-track.md) - How a stalled phase of the optimistic track turns into a recovery coalition formation proposal. Draft. + * [🤖 Validity proofs](validity-proofs.md) - Candidate design: proving outputs are covered by inputs through anonymous allocation registration. +* [🤖 Protocol messages](protocol-messages.md) - The messages peers exchange, who sends them, when, and what each requires of its channel. + +# Privacy Optimization Strategy -# In Review +* [Optimization framework for Bitcoin wallets](optimization_framework.md) - Under review in #15. +* [🤖 Pure Strategy Evaluation](pure_strategy_evaluation.md) - How the cost of a pure strategy is evaluated: the structure of the cost function, and its privacy liability terms. + * [🤖 Cost function structure](cost_function_structure.md) - The structure shared by the family of cost functions that evaluate pure strategies: time dependence, linear combination of terms and bracketing. + * [Privacy liability terms](cost_function_concrete.md) - The concrete terms of the cost function, and how each behaves in the decision tree. + * [Randomized selection and Sybil resistance](cost_function_randomized_selection.md) - Selection preferences that randomize which coins are co-spent, a Sybil resistance index measuring their effect, and a provenance term valuing coins by it. + * [🤖 Sybil resistance index](sybil_resistance_index.md) - A conservative 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. + * [🤖 Others' inputs subset sum density](subset_sum_density.md) - Outline of subset sum density, how it's estimated, and how co-spend proposals and the aggregator optimize it. + * [🤖 Own inputs or outputs subset sum ambiguity](cost_function_subset_sum_ambiguity.md) - Outline of a concrete cost function term for the subset sum ambiguity of output values. + * [🤖 Max flow based counterfactual path estimation](cost_function_counterfactual_paths.md) - Outline of a cost function term that estimates disjoint counterfactual paths with one max flow, and labels coins impervious to intersections. + * [🤖 Consolidation penalty](cost_function_consolidation.md) - 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](cost_function_siblings.md) - Outline of a concrete cost function term penalizing spending sibling outputs together. +* [Tactics](tactics.md) - Generating the decision tree bottom up, with coin selection and change decomposition, and when to re-evaluate it. + * [Bottom-up construction](bottom_up_construction.md) - 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](Denominations_and_gap_size_distributions.ipynb) - Why small Hamming weight denominations suit CoinJoin outputs, and how closely sums of a few of them approximate arbitrary amounts. +* [🤖 Mixed strategy](mixed_strategy.md) - How to compose a mixed strategy from the cost of pure strategies: randomization, time dependence, internalization and the decision loop. -* [Collaborative transaction privacy](collaborative_txn_privacy.md) - Under review in #7. -* [Cost function framework for Bitcoin wallets](cost_function_abstract.md) - Under review in #15. +# BIP Drafts + +* [PSBT Scrubber](bip-drafts/scrubber.md) - Which PSBT fields can be shared with trusted and untrusted parties such that privacy is preserved. * [Concurrent PSBT Construction](psbt-concurrent.md) - Under review in #16. -* [Market-based coalition formation for collaborative transaction construction](coalition_formation.md) - Under review in #18. diff --git a/docs/mixed_strategy.md b/docs/mixed_strategy.md new file mode 100644 index 0000000..a6a4931 --- /dev/null +++ b/docs/mixed_strategy.md @@ -0,0 +1,30 @@ +--- +type: concept +title: Mixed strategy +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# 🤖 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](optimization_framework.md) chapter, using the concrete monotone terms of the evaluation in the [Privacy liability terms](cost_function_concrete.md) chapter. + +## Randomization + +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*: it chooses uniformly at random among the $k$ best pure strategies that are sufficiently dissimilar, where $k$ is a parameter. This adds noise to the wallet's revealed preferences. The decision tree models the pure strategies explicitly, and the wallet randomizes over them. How to measure dissimilarity is still open. An alternative is to sample non-uniformly from a larger set, with lower probability for similar choices. + +## 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 $k$ 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. diff --git a/docs/optimistic-track.md b/docs/optimistic-track.md new file mode 100644 index 0000000..2e1c8b1 --- /dev/null +++ b/docs/optimistic-track.md @@ -0,0 +1,315 @@ +--- +type: Specification +title: "Optimistic track: blocks and phase states" +description: Unanimity and phase closure on the optimistic track, phase by phase. +status: draft +stale_after: 2027-04-15T00:00:00Z +--- + + + +# 🤖 Optimistic track: blocks and phase states + + + +## Scope and status + +This specification describes how Fungi transaction construction obtains consistency on the optimistic track, with threshold $t=n$. The [recovery track](recovery-track.md), with $t + +## 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 $n$ parties with non-trivial $n$ ($n > 2$) 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 $n-1$ 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 $n-1$ 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](https://gist.github.com/chris-belcher/87ebbcbb639686057a389acb9ab3e25b#cost-of-sybil-attacks). + +### 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](cost_function_structure.md#time-dependence) 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, then a payment that cannot be made privately should not be made at all. If it keeps rising, then at some point the utility of making the payment dominates any privacy liabilities, which is how a hard deadline is modeled. + +### 🤖 Global privacy budget {#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* $p$, a percentage chosen by the user, and the *remaining budget* $B$, an amount in satoshis. Only funds received at external addresses add to the remaining budget, which grows by $p$ times their value, and privacy-motivated expenses are deducted from it. + +This global budget limits overall spending for the purposes of privacy. The budget rate implies a lower bound for the expected harm from privacy leaks, since in setting it the user is indicating that the privacy improvements the wallet can provide are worth at least that much to them. This accounts for any downsides as well, such as the censorship risk or additional resources consumed. + +🤖 How the budget turns privacy metrics into amounts in satoshis, so that all terms can be summed, is described in the [Cost function structure](cost_function_structure.md#linear-combination) 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](coalition_formation.md). 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](collaborative_txn_privacy.md). 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](psbt-concurrent.md)). 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 {#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 $k$ acceptable leaves (see [Preliminaries](#preliminaries)), i.e. at least $k$ 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 $k$ 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 $k$ options for every retained action, not just at its root. diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..90c6e6f --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,245 @@ +--- +type: Overview +title: Fungi protocol overview +description: Collaborative transaction construction, privacy, fault tolerance and coalition formation. +status: draft +stale_after: 2026-10-31T00:00:00Z +--- + +# 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](./collaborative_txn_privacy.md) 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](./optimization_framework.md) 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](./coalition_formation.md) 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](https://bips.dev/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](https://bips.dev/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](./psbt-concurrent.md). 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.[^safety-liveness] + +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. + +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 [channel interfaces](channels.md) separate peer and broadcast addressing from transport interactivity, delivery and privacy. Bidirectional communication can use a live Tor stream, paired store-and-forward mailboxes or message delivery with anonymous reply capabilities. Each mechanism has different availability and lifetime requirements even when it presents the same send and receive operations. + +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. + +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](./psbt-concurrent.md#confirmation-of-successful-payment-prior-to-signing) for additional details. + +## Fault tolerance under different communication models + +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. + +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.[^dls] 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. + +## 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.[^honest-but-curious] + +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. + +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. + +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](./collaborative_txn_privacy.md) 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.[^byzantine-generals] 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. + +On the optimistic path, 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 path 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. + +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. + +### Consistency, liveness and termination in the presence of Byzantine faults + +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. + +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 $n = 3f+1$ where at most $f$ are faulty, a quorum of $2f+1$ peers will include at least $f+1$ 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 $f$ inputs owned by faulty peers honest parties should be able to successfully complete a run of the protocol after $O(f)$ 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 $f$ faults recovery is still possible but coordinating recovery attempts by identifying the subset of inputs eligible to participate in recovery requires additional assumptions. + +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. + +## Synchronizing protocol state + +The abstract state sharing requirements of the previous sections can be realized by a family of related constructions. + +### Byzantine eventual consistency + +The general starting point is Byzantine Eventual Consistency (BEC) by Martin Kleppmann and Heidi Howard.[^bec] In this model, messages, or transaction fragments as in our case, are committed to a [Merklized](https://en.wikipedia.org/wiki/Merkle_tree) 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 miners[^cordial-miners] is one of a family of so-called block DAG consensus protocols.[^dag-rider] 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 $n = 3f + 1$ validators, every block at height $h$ will have $t = n - f$ parent blocks with height $h - 1$. 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](https://en.wikipedia.org/wiki/Hash_consing) 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 $t = n$ 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 $t = 2f + 1$ lets responsive peers coordinate the recovery track. Note that in principle $t$ 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. + +### 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 $h$ with $t < n$ 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 $h$ to be produced with $t = n$ messages, the asynchronous base protocol can resume progress resulting in the diverging protocol states at height $h$. 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. + +### 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,[^trusted-coordinators] 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.[^asymmetric-trust] Flexible BFT provides a complementary precedent for interpreting a shared protocol transcript under different fault and timing assumptions.[^flexible-bft] 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. + +## 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](collaborative_txn_privacy.md) 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](./coalition_formation.md) protocol is designed to allow mutually distrusting strangers to bootstrap transaction construction using a market-based mechanism. 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.[^coinswap] 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.[^hedonic] 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. + +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. + +[^safety-liveness]: B. Alpern and F. B. Schneider, [*Defining Liveness*](https://www.cs.cornell.edu/fbs/publications/85-650.pdf) (1985). Formal definitions of safety and liveness, and their decomposition of system properties. + +[^dls]: C. Dwork, N. Lynch and L. Stockmeyer, [*Consensus in the Presence of Partial Synchrony*](https://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf) (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. + +[^honest-but-curious]: A. Paverd, A. Martin and I. Brown, [*Modelling and Automatically Analysing Privacy Properties for Honest-but-Curious Adversaries*](https://ajpaverd.org/publications/casper-privacy-report.pdf). 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. + +[^byzantine-generals]: L. Lamport, R. Shostak and M. Pease, [*The Byzantine Generals Problem*](https://lamport.azurewebsites.net/pubs/byz.pdf) (1982). The foundational treatment of agreement in the presence of arbitrary faults, including conflicting messages sent to different participants. + +[^bec]: M. Kleppmann and H. Howard, [*Byzantine Eventual Consistency and the Fundamental Limits of Peer-to-Peer Databases*](https://arxiv.org/abs/2012.00472) (2020). Byzantine causal broadcast and invariant-preserving replication; see §2.2–3 for the requirement that independently valid updates remain valid when merged. + +[^cordial-miners]: I. Keidar, O. Naor, O. Poupko and E. Shapiro, [*Cordial Miners: Fast and Efficient Consensus for Every Eventuality*](https://arxiv.org/abs/2205.09174) (2023). Blocklace dissemination, equivocation exclusion and ordering, with asynchronous and eventually synchronous variants. + +[^dag-rider]: I. Keidar, E. Kokoris-Kogias, O. Naor and A. Spiegelman, [*All You Need is DAG*](https://arxiv.org/abs/2102.08325) (2021). DAG-Rider separates construction of a communication DAG from local ordering of its proposals. + +[^trusted-coordinators]: Y. Kogman, [*Reiterating centralized coinjoin (Wasabi & Samourai) deanonymization attacks*](https://groups.google.com/g/bitcoindev/c/CbfbEGozG7c/m/w2B-RRdUCQAJ) + + + +[^asymmetric-trust]: O. Alpos, C. Cachin, B. Tackmann and L. Zanolini, [*Asymmetric Distributed Trust*](https://arxiv.org/abs/1906.09314) (2024). Subjective fault assumptions and asymmetric Byzantine quorum systems. + +[^flexible-bft]: D. Malkhi, K. Nayak and L. Ren, [*Flexible Byzantine Fault Tolerance*](https://arxiv.org/abs/1904.10067) (2019). Different clients interpret one protocol transcript using different fault and timing assumptions. + +[^coinswap]: For example [CoinSwap](https://openswap.live/) is such a protocol which relies on atomic swap contracts, designed with privacy in mind. + +[^hedonic]: D. Peters and E. Elkind, [*Simple Causes of Complexity in Hedonic Games*](https://arxiv.org/abs/1507.03474) (2015). Shows how modest expressiveness in preferences can make deciding the existence of stable outcomes computationally hard. diff --git a/docs/protocol-messages.md b/docs/protocol-messages.md new file mode 100644 index 0000000..54c4951 --- /dev/null +++ b/docs/protocol-messages.md @@ -0,0 +1,363 @@ +--- +type: Specification +title: Protocol messages +description: The messages peers exchange, who sends them, when, and what each requires of its channel. +status: draft +stale_after: 2027-04-22T00:00:00Z +--- + +# 🤖 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: + +| Group | Purpose | Settings | +| --- | --- | --- | +| [Peer introduction](#peer-introduction) | Learn and label peers out of band | honest, semi-honest | +| [Gossip](#gossip) | Disseminate objects within a namespace | all | +| [Sets](#sets) | Commit to, list and reconcile sets of objects | all | +| [Public gossip](#public-gossip) | Order book for coalition formation | Byzantine | +| [Negotiation](#negotiation) | Bilateral co-spend and coalition proposals | Byzantine | +| [Session initialization](#session-initialization) | Start a construction session | all | +| [Transaction construction](#transaction-construction) | Build the transaction | all | +| [Interactive payments](#interactive-payments) | Delegate and confirm payments | honest, semi-honest | +| [Blocks](#blocks) | Synchronize state and signal phase changes | semi-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. + +| Property | Values | Interface | +| --- | --- | --- | +| Direction | send, receive, or both | `SendChannel`, `RecvChannel`, `Bidirectional` | +| Delivery mode | one peer, or broadcast | `PeerChannel`, `BroadcastChannel` | +| Unlinkability | per channel, or per message | `UnlinkableMessageChannel` | +| Delivery guarantees | reliable or unreliable | | +| Timing | asynchronous or synchronous | | +| Metadata hiding | hides 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: + +| Messages | Direction | Delivery mode | Unlinkability | Delivery | Metadata hiding | Authentication | +| --- | --- | --- | --- | --- | --- | --- | +| [Transaction construction](#transaction-construction), semi-honest and Byzantine | send | broadcast | per message | reliable | required | — | +| [Interactive payments](#interactive-payments) | send and receive | peer | either | reliable | — | 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 level | Meaning | +| --- | --- | +| self | the user's own devices | +| trusted | trusted with privacy and liveness, e.g. in the same organization | +| semi-trusted | trusted with liveness | +| untrusted | the 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: + +| Message | Contents | Notes | +| --- | --- | --- | +| announce | object hash | throttled, or suppressed by [set reconciliation](#set-reconciliation) | +| pull | object hash | requests an announced object | +| push | object | solicited: answers a pull | + +### Unsolicited push + +The semi-honest and Byzantine settings add one message: + +| Message | Contents | Notes | +| --- | --- | --- | +| push (unsolicited) | object | used 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: + +| Set | Monotone | +| --- | --- | +| roots: the highest blocks, and the messages in no block | its closure is; the set itself is not | +| all blocks known to the peer | yes | +| blocks known to the peer at a given height | yes | +| all messages in blocks known to the peer | yes | + +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 + +| Message | Contents | Reply | +| --- | --- | --- | +| pull | Merkle root | its preimage | +| list | Merkle root | all 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](coalition_formation.md). + +| Object | Contents | Flood protection | +| --- | --- | --- | +| ownership proof | BIP 322 proof for a UTXO, committing to its online key, a validity interval and a block hash | proof hash below a threshold; replaces higher hashes for the same UTXO | +| UTXO directory entry | ownership proof, prevout or previous transaction, listen advertisements | — | +| listen advertisement | channel to reach the owner, constraints on proposals, willingness to be a validator, signed by the online key | signature hash, as for ownership proofs | +| co-spend proposal, unanimously accepted | see [negotiation](#negotiation) | one MuSig2 signature per proposal | +| co-spend proposal, partially accepted | opt-in only | time dependent key images | +| coalition proposal | see [negotiation](#negotiation) | signature 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. + +| Message | From | To | Contents | +| --- | --- | --- | --- | +| co-spend proposal | proposer | each named UTXO owner | outpoints, 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 | +| acceptance | each owner | involved peers | a linkable ring signature by its online key | +| MuSig2 nonces and partial signatures | each owner | involved peers | turn a unanimously accepted proposal into a fully accepted one | +| coalition proposal | aggregator | every implicated owner | fully accepted co-spend proposals, concrete parameters, adjustment vector, protocol version, committed listen advertisements naming the validators | +| coalition acceptance | each owner | involved peers | a signature by its online key | + +In the semi-honest setting the ring signatures can be skipped. Owners then +negotiate MuSig2 directly. + +## Session initialization + +| Setting | How a session starts | +| --- | --- | +| honest, semi-honest | a peer invites others to a random gossip topic | +| Byzantine | the 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. Each one is converted to +an unordered PSBT and joined into the local state, if it can be, as specified +in [concurrent PSBT construction](psbt-concurrent.md). + +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. + +| Message | Contents | Size | Settings | +| --- | --- | --- | --- | +| initialize | session parameters | — | all | +| add input | input with prevout data | hundreds of bytes | all | +| add output | output with its unique ID | hundreds of bytes | all | +| add fee contribution | explicit fee contribution | tens of bytes | all | +| issue from initial input | validity proof | several KiB | Byzantine | +| issue from auxiliary input | validity proof | several KiB | Byzantine | +| redeem | validity proof | several KiB | Byzantine | +| sign | signatures for one input | tens of bytes, more in the Byzantine setting | all | + +### Initialize + +Sets up the session parameters. The sort seed is the transcript hash: the +Merkle set commitment of the transaction construction messages the local peer +accepted. 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 map. Its `PSBT_OUT_UNIQUE_ID` identifies it, so adding it twice is +idempotent, while two equal outputs added separately stay distinct. + +### Add fee contribution + +A `PSBT_GLOBAL_EXPLICIT_FEE_CONTRIBUTION` entry: a 16 byte unique ID and an +amount. Fee contributions let peers account for fees exactly. + +### 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: + +| Signer | Behavior | +| --- | --- | +| hot key | signs automatically, any number of times | +| manual | the user approves each signature | +| limited | e.g. a hardware security module, or a virtual one | + +## Interactive payments + +Messages to a designated peer, the counterparty of a payment: + +| Message | From | To | Meaning | +| --- | --- | --- | --- | +| delegate | payer | payee | delegates n sats | +| confirm | payee | payer | the delegated funds were used | + +A peer must wait for its outgoing delegations to be confirmed before it +confirms delegations it received. The +[concurrent PSBT specification](psbt-concurrent.md) gives the full rule, +including how cycles are broken by net receivers. + +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. + +| Setting | Signing key | +| --- | --- | +| Byzantine | the UTXO's online key | +| semi-honest | an ephemeral key, for simplicity, though the model doesn't need it | + +### Phase change signals + +Blocks also signal phase changes: + +| Signal | Effect | +| --- | --- | +| inputs fixed | clears the inputs modifiable flag | +| overflow | acts as a single fee contribution with ID "" and amount `MAX_MONEY`, the top of the lattice | +| outputs fixed | clears the outputs modifiable flag and sorts the transaction | +| initial input issuance | issuance from initial inputs | +| auxiliary input issuance | issuance from auxiliary inputs | +| outputs proven | all 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? diff --git a/docs/psbt-concurrent.md b/docs/psbt-concurrent.md index 180e685..fd7c76c 100644 --- a/docs/psbt-concurrent.md +++ b/docs/psbt-concurrent.md @@ -1,5 +1,5 @@ --- -type: Stub +type: BIP Draft title: Concurrent PSBT Construction status: draft stale_after: 2027-04-15T00:00:00Z @@ -7,4 +7,277 @@ stale_after: 2027-04-15T00:00:00Z # Concurrent PSBT Construction -This chapter is under review in [#16](https://github.com/fungi-protocol/docs/pull/16). Its draft is on [the pull request's branch](https://github.com/fungi-protocol/docs/blob/concurrent-psbt/psbt-concurrent.md). +## 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 -> constructor (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 + +| Name | `keytype` | `keydata` | `keydata` Description | `valuedata` | `valuedata` Description | +| --- | --- | --- | --- | --- | --- | +| Transaction Unordered Flag | `PSBT_GLOBAL_TX_UNORDERED = TBD` | None | No key data | `<8-bit uint>` | If present, must be set to a value `0x03` to indicate inputs and outputs are unordered. | +| Sort Seed | `PSBT_GLOBAL_SORT_SEED = TBD` | None | No key data | `` | Random seed used to derive deterministic sort keys when explicit per-map sort keys are absent. | +| Deterministic Sort Flag | `PSBT_GLOBAL_SORT_DETERMINISTIC = TBD` | None | No 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 Input | `PSBT_GLOBAL_REMOVED_INPUT = TBD` | `` | `PSBT_IN_UNIQUE_ID` of an input removed from the logical input set. | None | No value data. | +| Removed Output | `PSBT_GLOBAL_REMOVED_OUTPUT = TBD` | `` | `PSBT_OUT_UNIQUE_ID` removed from the logical output set. | None | No value data. | + +### New per-input types + +| Name | `keytype` | `keydata` | `keydata` Description | `valuedata` | `valuedata` Description | +| --- | --- | --- | --- | --- | --- | +| Input Sort Key | `PSBT_IN_SORT_KEY = TBD` | None | No key data | `` | Arbitrary lexicographically comparable value used to order inputs. | +| Input Unique ID | `PSBT_IN_UNIQUE_ID = TBD` | None | No key data | `` | Optional unique suffix for outpoint identity, used for input removal extensions. | + +### New per-output types + +| Name | `keytype` | `keydata` | `keydata` Description | `valuedata` | `valuedata` Description | +| --- | --- | --- | --- | --- | --- | +| Output Unique ID | `PSBT_OUT_UNIQUE_ID = TBD` | None | No key data | `` | Universally unique identifier for output map identity under unordered output semantics. | +| Output Sort Key | `PSBT_OUT_SORT_KEY = TBD` | None | No key data | `` | 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](https://github.com/bitcoin/bips/blob/master/bip-0370.mediawiki#user-content-Unique_Identification) 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](#unique-identification-of-unordered-psbts). + +### 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](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#handling-duplicated-keys). 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 $A + A = A$). Attempting to join a PSBT more than once fails closed: if $B$ contains an input, and $A + B$ is defined, then $(A + B) + B$ 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 $B$ contains just an output, then $B + B$ 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 $(A + B) + C = A + (B + C)$ and that $A + B = B + A$. + +#### 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](#divergence-and-sighash-flags) 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](#ordering-inputs-and-outputs), 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 $n$ elements is $log_2(n!)$. For reference, $\log_2(35!) > 128$, $\log_2(25!) > 80$, and $\log_2(15!) > 40$. + +This can provides additional integrity to a collaborative transaction construction protocol, since [`SIGHASH_ALL`](#divergence-and-sighash-flags) 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](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type#2P-Set_(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](#divergence-and-sighash-flags), 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](#divergence-and-sighash-flags). + +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](https://en.wikipedia.org/wiki/Semilattice). + +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. diff --git a/docs/pure_strategy_evaluation.md b/docs/pure_strategy_evaluation.md new file mode 100644 index 0000000..784b40f --- /dev/null +++ b/docs/pure_strategy_evaluation.md @@ -0,0 +1,10 @@ +--- +type: concept +title: Pure Strategy Evaluation +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# 🤖 Pure Strategy Evaluation + +How the cost of a pure strategy is evaluated, in two parts. The [Cost function structure](cost_function_structure.md) chapter describes the structure shared by the family of cost functions: time dependence, the linear combination of terms, and bracketing. The [Privacy liability terms](cost_function_concrete.md) chapter summarizes the terms, each of which is specified in its own chapter. diff --git a/docs/recovery-track.md b/docs/recovery-track.md new file mode 100644 index 0000000..87425cd --- /dev/null +++ b/docs/recovery-track.md @@ -0,0 +1,507 @@ +--- +type: Specification +title: Recovery track +description: How a stalled phase of the optimistic track turns into a recovery coalition formation proposal. +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + + + +# 🤖 Recovery track + +A stalled phase ends in recovery track blocks, each signed by its validator and committing to what that validator is missing. Any participant can turn those lists into a recovery coalition formation proposal that anyone can check. Under synchrony, each successor instance excludes at least one faulty party and never an honest one. The exception is an honest payer whose payee stalled it, as in [counterparty stalls](#counterparty-stalls). + +This chapter describes the recovery track ($t \lt n$). The block structure, the per-track nonce commitments and the BIP-322 binding of validator keys to coins are described in [transaction construction](transaction-construction.md#block-dag). The closing of each phase is described in the [optimistic track](optimistic-track.md#phase-closure) chapter ($t = n$). Dissemination and set reconciliation are out of scope here. + +Several names in this chapter and in [phase closure](optimistic-track.md#phase-closure) are placeholders, chosen only so the rules can be stated: *per-input message*, *slot*, *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. + +## 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: $t=n$ for unanimous construction and $t3f$.[^acs] 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 $X_i$ is a validated fragment set, and $H_x$ is the set of honest proposers whose submitted sets contain fragment $x$. Since at most $f$ proposer slots are omitted, + +$$ +|H_x|>f\ \Longrightarrow\ Q\cap H_x\neq\varnothing +\ \Longrightarrow\ x\in\bigcup_{i\in Q}X_i. +$$ + +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. Replicated inclusion also does not preserve that participant's veto: recovery agreement can complete without its approval that its required data is present. This differs from the original optimistic branch's unanimity rule. Its authority to withhold signatures for its own inputs 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.[^choi] 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.[^dm] 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.[^sample-brb] 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 + +[^bip322]: K.-J. Alm, [*BIP 322: Generic Signed Message Format*](https://bips.dev/322/). Used for acceptance, proposals and validator key endorsement. + +[^bip340]: P. Wuille, J. Nick and T. Ruffing, [*BIP 340: Schnorr Signatures for secp256k1*](https://bips.dev/340/). The signature equation behind key exposure. + +[^bip352]: josibake, R. Somsen and S. Falbesoner, [*BIP 352: Silent Payments*](https://bips.dev/352/). Output derivation tweaked by the transaction's inputs. + +[^choi]: W. Choi, R. Cohen, J. Garay, N. Skoumios and V. Zikas, [*Byzantine Broadcast with Unknown Participants*](https://eprint.iacr.org/2025/2133) (2025). Defines active-parties set agreement. + +[^dolev-strong]: D. Dolev and H. R. Strong, [*Authenticated Algorithms for Byzantine Agreement*](https://doi.org/10.1137/0212045), SIAM Journal on Computing (1983). + +[^vigil]: J. Cheng, H. Sun, R. Zhou, J. Zhou and Z. Chen, [*Vigil: Accountable Liveness against Selective Silence*](https://arxiv.org/abs/2609.18778) (2026). + +[^deligios]: G. Deligios, I. Klasovita and C.-D. Liu-Zhang, [*Asymptotically Optimal Early Termination for Dishonest Majority Broadcast*](https://eprint.iacr.org/2024/1656), Eurocrypt 2025. The lower bound is cited there on p. 2. + +[^loss-nielsen]: J. Loss and J. B. Nielsen, [*Early Stopping for Any Number of Corruptions*](https://eprint.iacr.org/2023/1813), Eurocrypt 2024. + +[^cordial]: Idit Keidar, Oded Naor, Ouri Poupko and Ehud Shapiro. [Cordial Miners: Fast and Efficient Consensus for Every Eventuality](https://arxiv.org/abs/2205.09174). + +[^dual-track]: Minghang Li et al. [TockOwl: Asynchronous Consensus with Fault and Network Adaptability](https://eprint.iacr.org/2025/134) (USENIX Security 2025). TockOwl+ combines fast and slow tracks using hedging delays. + +[^crbb]: Ittai Abraham, Yuval Efron and Ling Ren. [The Latency Cost of Censorship Resistance](https://eprint.iacr.org/2025/2136). + +[^ic]: Panos Diamantopoulos, Stathis Maneas, Christos Patsonakis, Nikos Chondros and Mema Roussopoulos. [Interactive Consistency in practical, mostly-asynchronous systems](https://arxiv.org/abs/1410.7256). + +[^acs]: Andrew Miller, Yu Xia, Kyle Croman, Elaine Shi and Dawn Song. [The Honey Badger of BFT Protocols](https://eprint.iacr.org/2016/199). See also Sisi Duan, Michael K. Reiter and Haibin Zhang, [BEAT: Asynchronous BFT Made Practical, Section 5](https://reitermk.github.io/papers/2018/CCS.pdf), for the ACS properties. + +[^dm]: Danny Dolev and H. Raymond Strong. [Authenticated Algorithms for Byzantine Agreement](https://doi.org/10.1137/0212045). Ruomu Hou and Haifeng Yu. [Optimistic Execution in Byzantine Broadcast Protocols That Tolerate Malicious Majority](https://doi.org/10.1016/j.jpdc.2025.105203). + +[^sample-brb]: Rachid Guerraoui et al. [Scalable Byzantine Reliable Broadcast](https://arxiv.org/abs/1908.01738). diff --git a/docs/set-reconciliation.md b/docs/set-reconciliation.md new file mode 100644 index 0000000..c19c028 --- /dev/null +++ b/docs/set-reconciliation.md @@ -0,0 +1,143 @@ +--- +type: Specification +title: Peer set reconciliation +description: Naive reconciliation, quiescence before block authoring, sparse Merkle sets, mutual knowledge, and range reconciliation and rateless streams as future optimizations. +status: draft +stale_after: 2027-04-15T00:00:00Z +--- + + + +# 🤖 Peer set reconciliation + +## Scope and status + +This draft specifies a peer-layer mechanism for efficient dissemination of content-addressed messages. It operates on asymmetric knowledge of sets and a lower bound on mutual knowledge, expressed through sparse Merkle set commitments. + +The base functionality only needs the [naive reconciliation](#naive-reconciliation) of Byzantine Eventual Consistency (BEC), without its Bloom filter based optimization. Range-based set reconciliation (RBSR), and RBSR combined with rateless invertible Bloom lookup tables (RIBLT), are future optimization directions. We call their combination **hybrid recursive/rateless set reconciliation**: RBSR recursively controls the scope of the exchange; optional `rateless` and `rateless` streams can use available bandwidth while range replies are in flight. + +The mechanism serves both permissionless coalition formation and permissioned transaction construction. In the permissionless setting, peers reconcile coalition-formation order-book inventories, including listen advertisements, co-spend proposals, associated BIP-322 proofs and coin-associated fraud proofs. This exchange does not require a fixed validator set or a block DAG. The coalition-formation protocol determines which objects are valid, retained and eligible for negotiation. + +The [DAG's equivocation mechanism](transaction-construction.md#nonce-commitments-and-compact-equivocation-evidence) 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. + +In permissioned construction and recovery, the [block DAG](optimistic-track.md) uses the same mechanism to disseminate blocks and included messages, and supplies additional knowledge through causal references. Reconciliation is independent of block interpretation, validator thresholds and phase agreement. Both uses supply committed sets and evidence of shared knowledge; DAG ancestry is an additional source of that evidence, not a prerequisite. These algorithms target different device and network tradeoffs; an optimal switching policy has not yet been established. + +## Mutual and asymmetric knowledge + +Reconciliation uses the [generic peer-channel interface](channels.md), 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. + +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. + + +## 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. + +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.[^libra] 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. + +## Naive reconciliation + +The base functionality only needs the naive reconciliation algorithm of BEC.[^bec] Two peers exchange the hashes of their latest messages. A peer that receives a hash whose preimage it doesn't have requests it, and repeats this for the hashes that the obtained message refers to, until it reaches messages it already has. In the block DAG, these references 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 either. + +## Quiescence before block authoring + +Set reconciliation also informs when to author a block. Even when its cordial parent threshold is already met, as with $t=n$ in the optimistic track, a validator waits for its neighbors' Merkle sets to quiesce before authoring its next block. This reduces the total number of blocks, and helps make them more compressible on the wire. This heuristic applies whichever reconciliation algorithm is used. Local quiescence, its privacy motivation and the handling of stalled neighbors are described in the [optimistic track](optimistic-track.md#block-publication-and-quiescence) chapter. + +## Range reconciliation and streaming + +The first optimization direction is range-based set reconciliation in the style of Meyer and Scherer.[^rbsr] 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 $S$ and $T$ be the two sets being reconciled and let $K$ be a mutually identified subset of their intersection. Then + +$$ +(S\setminus K)\mathbin{\triangle}(T\setminus K)=S\mathbin{\triangle}T. +$$ + +Removing $K$ 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 $K$ 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` candidate uses an elliptic-curve multiset hash (ECMH) for its homomorphic cell checks, together with a channel-specific sampling schedule.[^riblt] The ECMH and adversarial-set adaptations are distinct from the published RIBLT construction and require their own analysis. + +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` + +A small difference spread throughout a large set can require many tree comparisons. PinSketch is a candidate for resolving such ranges directly. A capacity-$c$ sketch of $b$-bit nonzero field elements occupies $bc$ bits and can recover a symmetric difference of at most $c$ elements. Sketches combine by XOR.[^minisketch] + +Capacity depends on the difference size, while construction work also depends on the population being encoded. Straightforward construction over $N$ elements costs $O(Nc)$ field operations. Conventional decoding has quadratic scaling in the supported difference size. A shared-knowledge baseline reduces $N$ without reducing the required capacity for the same difference. + +Two extensions are under evaluation: + +| Variant | Operation | Tradeoff | +| --- | --- | --- | +| Additional syndromes | Extend the PinSketch for the same range without retransmitting earlier syndromes. | Increasing capacity increases computation; reuse of failed decoding work requires implementation support. | +| Small PinSketch cells | Use 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. + +## Relation to asynchronous data dissemination + +Asynchronous Data Dissemination (ADD) distributes a common message $M$ from at least $f+1$ honest holders to all honest nodes, with communication $O(n|M|+n^2)$ under $f + +How many ways subsets of a transaction's input values can fund a given amount. 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 density is estimated, and how co-spend proposals and the aggregator optimize it. The [subset sum ambiguity](cost_function_subset_sum_ambiguity.md) term implements it for the cost function. + +## Effective values + +Effective values are computed at the [coalition formation proposal](coalition_formation.md)'s feerate $f$, 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](https://arxiv.org/abs/cond-mat/0106125) estimate the number of subsets summing to a target. + - Their grand partition function, $\prod_j (1 + e^{\mu - \beta a_j})$, 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 $\beta$ and $\mu$ costs $O(n)$ per Newton step. + - It's only valid where the number of solutions is large. +- **Distinct sums.** [Salas](https://arxiv.org/abs/2507.15511) enumerates the $U$ distinct subset sums in $O(U n^2)$ time, or $O(U n)$ expected, independent of the range. It keeps one witness subset per sum, but gives no counts. +- **Bitmaps and counts.** Bellman's algorithm over a bounded range, as implemented by the [subset sum ambiguity](cost_function_subset_sum_ambiguity.md) 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. + - $\rho$, the interval width and a subset size cap $q_{\max}$ 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](https://github.com/fungi-protocol/docs/issues/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 $q_{\max}$, 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 $I = [c, c + w]$ for $\rho$ disjoint subsets of the inputs. If it fails, perturb the combination and rehash. + 1. **Bounds.** Give up if $\rho > \lfloor \sum a / c \rfloor$, or if $\rho > \lfloor n / q_{\min} \rfloor$, where $q_{\min}$ is the number of largest values needed to reach $c$. + 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 $q_{\max}$ and the last item. Extract a smallest subset, remove it, and repeat. + - Round values down to multiples of $\Delta$, and target $[c, c + w - q_{\max} \Delta]$, so exact sums stay in $I$. + 4. **Repair.** If stuck below $\rho$, move or swap coins between subsets and the unused pool. Stop at $\rho$. +- **Encoding.** One label per input in $\{0, \dots, \rho\}$, with 0 for unused. The subsets are disjoint by construction, and verification is $O(n)$. diff --git a/docs/sybil_resistance_index.md b/docs/sybil_resistance_index.md new file mode 100644 index 0000000..f32ca97 --- /dev/null +++ b/docs/sybil_resistance_index.md @@ -0,0 +1,147 @@ +--- +type: concept +title: Sybil resistance index +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# 🤖 Sybil resistance index + +A conservative lower bound $L$ on the number of candidate coins a transaction's inputs were selected from. It measures the effect of the selection preferences in the [randomized selection](cost_function_randomized_selection.md) chapter, whose provenance term uses it. + +## Candidates + +**Candidates** are the coins whose owners are active and offering them in the order book. $N$ is how many there are. It isn't directly observable. + +- Under the actual block hash $t$, 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 $N$ from below, much like estimating the hash rate from proofs of work. +- Candidates must be fixed before $t$ 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 + +- $x_i = H(t, i)$ for each input outpoint $i$. $H$ is a tagged hash, truncated to 64 bits and read as an integer modulo $Q = 2^{64}$, so the $x_i$ are points on a circle. +- Truncation keeps the guarantees below: the truncated hashes are uniform on the grid of $Q$ points, and the extra grid unit per span covers the rounding. + +## Pool size bound + +For the $n$ input hashes of a transaction and a confidence parameter $\delta$: + +1. **Spans.** Sort the hashes around the circle. An $m$-span runs from a hash to its $m$-th successor. Its width is the distance between them, plus one grid unit. +2. **Sums.** For each $1 \le m \lt n$ and $1 \le r \le n/m$, $T_{m,r}$ is the smallest total width of $r$ spans with disjoint interiors. Spans may share endpoints. Let $\tau_{m,r} = T_{m,r} / Q$. + - For $m = 1$, this is the sum of the $r$ smallest gaps. + - Larger $m$ detects groups of nearby hashes. +3. **Tail bound.** For a hypothetical pool of $M$ candidates: + $$ + q_{m,r}(M) = \min\left(1, \frac{M^{r(m+1)} \, \tau_{m,r}^{rm}}{r! \, (rm)!}\right) + $$ +4. **Score.** With weights that sum to 1 over all $m, r \ge 1$: + $$ + S(M) = \sum_{m,r} \frac{q_{m,r}(M)^{-1/2} - 1}{m(m+1)r(r+1)} + $$ +5. **Bound.** $L$ is the smallest integer $M \ge n$ with $S(M) \lt 1/\delta$. + +### Why it's conservative + +$P(L \gt N) \le \delta$ for every selection strategy. This includes choosing the inputs, and how many, after seeing the hashes, in order to maximize $L$. + +- **One placement.** In a uniform pool of $M$, the total of $r$ fixed disjoint blocks of $m$ gaps is $\text{Beta}(rm, M - rm)$. Its lower tail is at most $(M \tau)^{rm} / (rm)!$. +- **Every placement.** There are at most $M^r / r!$ ways to place the blocks. A union bound covers taking the minimum after seeing the pool. +- **Subsets.** Each selected $m$-span contains at least $m$ 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 $q$ is a conservative p-value, so $E[q^{-1/2} - 1] \le 1$. By Markov's inequality, $P(S(N) \ge 1/\delta) \le \delta$. The terms may be dependent. + +### Properties + +- **Monotone.** At a fixed beacon and $\delta$, adding inputs never lowers $L$. 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 $L$, so it doesn't matter which hashes count as lucky. +- **Integer arithmetic.** Each weighted term is rounded down to a multiple of $2^{-64}$, using integer square roots. Rounding only lowers the score, so it keeps both guarantees. +- **Caps.** Leaving out the terms above a fixed $m$ or $r$ keeps both guarantees: their weight goes unused. It costs power. +- **Cost.** $O(n^3)$ arithmetic operations over all $m$, on integers of $O(n (\log Q + \log M))$ 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 $L$ as the reference. + +## 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 $t$, at $\delta / W$ each for $W$ candidates, and take the largest $L$. + +- **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 $n$. So $L \gt n$ with probability at most $\delta / W$ for each such block hash, and at most $\delta$ for all of them. +- **Screen.** Only the $m = 1$ terms, sums of the smallest gaps, are evaluated for every block hash, once, at $M = n$. That is a sort and one score. The full bound is evaluated only when the screen gives $L \gt n$. The screen's threshold is fixed, so both guarantees hold. +- **Cost.** With $W = 1000$ 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, $\delta = 0.05$, 32 transactions per configuration, using the Python reference. + +- **No block hash used.** Inputs drawn uniformly. In all 96 transactions ($n$ = 16, 32, 80), no block hash gave $L \gt n$. At $\delta$ instead of $\delta / 1000$, 25 of them had one, up to $16 n$. +- **One block hash used**, by lowest hashes, XOR pairs or the tightest cluster, with $N$ = 1000 or 100,000. In all 576 transactions, it gave the largest $L$, no other gave $L \gt n$, and $n \lt L \le N$. +- **Cost of the split.** Median $L$ at $\delta / 1000$ is lower than at $\delta$ by about 2.6 times at $n = 16$, 1.7 at $n = 32$ and 1.3 at $n = 80$. + +### Caps + +Median $L / N$ of the used block hash with $N = 100{,}000$ and $n = 80$, at $\delta / 1000$: + +| Cap | Lowest hashes | XOR pairs | Cluster | +|---|---:|---:|---:| +| $m \le 1$ | 0.010 | 0.329 | 0.013 | +| $m \le 8$ | 0.108 | 0.329 | 0.167 | +| $m \le 16$ | 0.156 | 0.329 | 0.238 | +| $m \le 4$, $r \le 8$ | 0.051 | 0.106 | 0.075 | +| none | 0.225 | 0.329 | 0.350 | + +- **Don't cap $r$.** Pairs need many $m = 1$ terms. +- **Capping $m$** 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, $N = 1000$, $n = 16$). + +## Measurements + +From the prototype, with $\delta = 0.05$. Nine selection strategies are applied to the same candidate hashes in each trial. + +Median $L$ with $N = 1000$, over 32 trials: + +| $n$ | XOR pairs | Lowest hashes | Closest pairs | Uniform | +|---:|---:|---:|---:|---:| +| 4 | 57.5 | 11 | 66.5 | 4 | +| 16 | 227.5 | 116.5 | 265 | 16 | +| 32 | 346.5 | 225 | 378.5 | 32 | +| 100 | 400 | 327 | 457.5 | 100 | + +- With $N = 100{,}000$ and $n = 80$, median $L / N$ ranges from 0.28 (lowest hashes) to 0.47 (two clusters). +- **Uniform selection** gives $L = n$. A large pool shows nothing unless the selection is biased. +- **Overshoot.** $L \gt N$ in none of the 1,152 selected sets at $N = 100{,}000$, and none of the 2,304 at $N = 1000$. + - This doesn't prove coverage. The proof does. + - The guarantee bounds how often $L$ exceeds $N$, not by how much. + +### Tighter alternatives + +Overestimating $N$ 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 $\delta/3$ each. + - Median $L / N$ between 0.66 and 0.78 in the same comparison. + - $L \gt N$ 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 $1/r$ and power $9/10$. + +## Limitations + +- **Candidates, not owners.** $L$ 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 $L$ only if the selected coins' values are typical of the candidates. +- **Lower bound only.** $L$ isn't an estimate of $N$. There is no likelihood for the selected set given $N$. +- **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 $L$ by about 3%. + - Splitting $\delta$ over 1000 block hashes costs most at small $n$: about 2.6 times at $n = 16$. +- **Concealment.** A selection strategy can keep $L$ near $n$. Monotonicity only prevents raising $L$ by withholding coins. +- **Review.** The calibration argument hasn't been reviewed outside the prototype. + +## Open questions + +- Can $L$ 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 $M$ if any $q_{m,r} \le w_{m,r} \delta$, instead of the square root. This loses less to the split over block hashes. + - Tighter tails for $m = 1$. In a uniform pool, the gaps are exponential variables divided by their sum.[^renyi] Sums of the smallest gaps then have an exact law,[^holst] but it is impractical for large $n$ and small sums. A Chernoff bound on this form is practical, and gains about 1.3–1.6 times in $L$, only for large $r$. Nothing comparable is known for $m \gt 1$. + - Anchored ranks for the per-input preference, which are tighter for lowest hashes, at part of $\delta$. They treat the anchor specially, so symmetry is lost. + +[^renyi]: A. Rényi, "On the theory of order statistics", *Acta Mathematica Academiae Scientiarum Hungaricae* 4 (1953), 191–231, [doi:10.1007/BF02127580](https://doi.org/10.1007/BF02127580). + +[^holst]: 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](https://doi.org/10.2307/3212956). diff --git a/docs/tactics.md b/docs/tactics.md new file mode 100644 index 0000000..6723546 --- /dev/null +++ b/docs/tactics.md @@ -0,0 +1,30 @@ +--- +type: concept +title: Tactics +status: draft +stale_after: 2026-11-06T00:00:00Z +--- + +# Tactics + +🤖 A procedure for constructing the decision tree that the [cost function](optimization_framework.md) evaluates, using the terms in the [Privacy liability terms](cost_function_concrete.md) 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 {#inputs-and-output} + +The wallet state contains the spendable UTXO set, inflight transactions, current protocol observations and beliefs, policy parameters, and an ordered queue $Q=(q_1,\ldots,q_n)$ 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](optimization_framework.md) 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](bottom_up_construction.md) 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](mixed_strategy.md) 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. diff --git a/docs/transaction-construction.md b/docs/transaction-construction.md new file mode 100644 index 0000000..2e1e935 --- /dev/null +++ b/docs/transaction-construction.md @@ -0,0 +1,170 @@ +--- +type: Specification +title: Transaction construction +description: Content and state synchronization, the phases, the optimistic and recovery tracks, and the block DAG they share. +status: draft +stale_after: 2027-04-23T00:00:00Z +--- + + + +# 🤖 Transaction construction + +Transaction construction starts from an accepted coalition formation proposal and ends with a signed transaction. This chapter describes it in the abstract and defines the block DAG that its tracks share. The chapters that follow describe each track and the validity proofs. + +## 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](validity-proofs.md) 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](#nonce-commitments-and-compact-equivocation-evidence) that expose the key of a validator that equivocates. + +Transmitting either between peers is described in [peer set reconciliation](set-reconciliation.md). + +## Phases + +1. **Kickoff**: the validators acknowledge the coalition formation proposal, which lists the initial inputs. +2. **Auxiliary inputs** are added anonymously. +3. **Destination commitments**: knowing the complete input set, each input commits to its payments and outputs, keeping the balance fair. How output values are chosen is a matter of strategy, not of this protocol. +4. **Outputs** are added anonymously. +5. **Proven auxiliary inputs and proven outputs**, only if the outputs overspend. Missing auxiliary inputs and outputs are posted with proofs. +6. **Signatures** are collected, one per input. + +Each phase closes on a stable state before the next one starts. The [optimistic track](optimistic-track.md#phase-closure) says why. The [overview](overview.md) describes the honest, semi-honest and Byzantine settings these phases run in. + +## Tracks and validity proofs + +- [**Optimistic track**](optimistic-track.md), with threshold $t = n$. It is asynchronous, and phases advance by unanimous acknowledgement. On its own, it is sufficient in the honest and semi-honest settings. +- [**Recovery track**](recovery-track.md), with $t \lt n$. It is optional, and assumes synchrony or partial synchrony. It turns a stalled phase into a recovery coalition formation proposal. +- [**Validity proofs**](validity-proofs.md) 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. + +## Block DAG + +Both tracks use the block DAG defined here. + +### 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 + +$$ +b=(M_b, B_b, s_b, R_b^{\mathrm{opt}}, R_b^{\mathrm{rec}}, \kappa_b, \phi_b, E_b), +$$ + +with the following components: + +| Component | Meaning | +| --- | --- | +| $M_b$ | Set of included messages; may be empty for an acknowledgement block. | +| $B_b$ | Set of parent blocks. | +| $s_b$ | Optional self-parent block, from the same validator. | +| $R_b^{\mathrm{opt}}$ | Nonce point committed for signing the validator's next optimistic block. | +| $R_b^{\mathrm{rec}}$ | Nonce point committed for signing the validator's next recovery block. | +| $\kappa_b$ | Block type: optimistic ($t=n$) or pessimistic recovery ($t>: Send { + /// Privacy properties for this sender in relation to its destination peer. + type Privacy: Privacy; + type SendError: Error + Send + Sync + 'static; + fn send(&mut self, message: M) -> impl Future> + Send; +} + +pub trait RecvChannel>: Send { + type RecvError: Error + Send + Sync + 'static; + fn recv(&mut self) -> impl Future> + Send; +} + +pub trait Bidirectional, O = Vec>: RecvChannel + SendChannel {} +``` + +These match `crates/transport` in the Fungi repository at `5c0f08e`. + +* **One message per call.** `send` submits one message. `recv` yields one message. +* **Exclusive ownership.** Both operations take `&mut self`. Normally one consumer reads a channel and one writes it. If concurrent writes are ever needed, a layer on top wraps the channel in an `Arc` with interior mutability, such as a mutex. +* **Channel-defined errors.** Each channel defines its own error types. Failures such as "closed", "too large" or "unreachable" are specific to connection based channels, so the traits do not name them. +* **Typed messages.** The message type defaults to bytes. Transports provide byte channels at the boundary. Conversion adapters turn them into typed channels of the same shape. +* **Either direction alone.** An implementation may provide sending, receiving, or both. A consumer requires only the direction it uses. Adapters bridge the two shapes. +* **Many senders.** A receive channel need not belong to one sender. Some transports deliver every message for an address to a single receive interface. +* **Minimal `Bidirectional`.** It adds no methods. Its input and output message types may differ. + +## Privacy tags + +`Privacy` is a sealed trait. Its implementations are uninhabited types, used only as tags. + +| Tag | Messages linkable to each other | Messages linkable to a sender identifier | +| --- | --- | --- | +| `MessageUnlinkability` | No | No | +| `ConnectionUnlinkability` | Yes | No | +| `Unspecified` | Not declared | Not declared | + +* A tag describes the sending side. It states whether submitting a message on the channel leaks information to the destination peer. +* A missing sender field does not mean anonymity. Identity can still leak, or be inherent to the transport. For example, a connecting peer may authenticate to the accepting peer. Authenticated channels, and channels whose properties are not yet verified, are `Unspecified`. +* Code that writes messages that must be unlinkable requires a channel with the matching tag. The compiler checks the bound. This prevents privacy leaks that the structural types alone would allow. Concurrent PSBT construction tracks modifiability in types similarly. +* The tags name each property directly. The words "anonymous" and "pseudonymous" invite confusion: an unlinkable connection is easily read as anonymity of the connection, and a linkable one as pseudonymity of a long-term identity. +* Metadata hiding is always with respect to the initiator: the sender, or the connecting side of a stream. The responder is identified by its peer ID or address. +* `RecvChannel` carries no tag. + +More properties are not tags yet: + +* **Interactivity.** A connection based channel requires the peer to be available. The working adjective for this is "synchronous". It affects how channels are built and how long they live. It probably need not be a type, but may prove useful. +* **Destination.** A channel reaches either a single peer or many (multicast). See [open questions](#open-questions). +* **Reliability.** Whether delivery is reliable or unreliable. +* **Metadata hiding.** Whether the channel hides transport metadata from the responder. + +## Adapters + +Composition lives in adapters, not in the core traits. + +**`Duplex`** pairs a send channel and a receive channel into a `Bidirectional` channel. `into_parts` recovers them, so no borrowed halves are needed. The send destination and the receive source may differ. Its `Privacy` is that of `S`. Pairing is the right shape for talking to one particular peer, as net settlement requires. + +**Split** is the dual of `Duplex`. It is not implemented yet. A native bidirectional channel `T` moves into an `Arc`. Each half holds a clone and implements one direction. This assumes `T` is safe to share. Splitting consumes the channel. It is not a required trait method, since it may not be practical for some transports. + +**Conversion** changes the message type. Given `f: T -> S`: + +* a `SendChannel` becomes a `SendChannel` by applying `f` before each send (contramap); +* a `RecvChannel` becomes a `RecvChannel` by applying `f` to each received message (map); +* a bidirectional channel takes a pair of functions, one per direction. + +Conversion adapters are not implemented yet either. One adapter struct per underlying trait suffices. A fallible conversion extends the underlying channel's error type. Invalid data from a peer is then handled generically. Encoding and decoding are conversions. + +A paired codec type is deferred. When it is added, it should capture that round trips preserve information: `f ∘ g = id = g ∘ f`. + +A `Stream` adapter for receive channels is deferred until a consumer needs it. + +## Builders + +```rust +pub trait ChannelBuilder>: Send { + type Input: Send + Sync; + type Privacy: Privacy; + type Channel: SendChannel; + type BuildError: Error + Send + Sync + 'static; + fn build( + &mut self, + input: &Self::Input, + ) -> impl Future> + Send; +} +``` + +* A builder declares the `Privacy` of the channels it builds. +* Some builders interact. They open a connection. Their channels may become unusable when the connection drops. +* Other builders are stateless. They build a channel from an address alone. +* A connection based transport has two builders for the same channel type: one connects and one accepts. A connectionless transport needs only one builder per peer, if peers authenticate mutually. +* The main shared-secret builder derives a simplex channel and returns only one end. Both peers can use the same builder. Two writers on one simplex channel can only conflict, which harms privacy and censorship resistance. It is better to make that case impossible to construct. A bidirectional channel is a pair of simplex channels derived from the same secret, one per direction. + +## Message unlinkability from connection unlinkability + +A `ConnectionUnlinkability` channel is message unlinkable if it carries only one message. It may instead carry one set of inherently related messages, such as a transaction input and its signature. There are caveats: timing metadata can still leak, for example. + +A sketch, not from the reviews: an adapter could hold a builder whose `Privacy` is `ConnectionUnlinkability`, build a fresh channel for each message, and implement `SendChannel` with `Privacy = MessageUnlinkability`. + +## Broadcast channels from peer channels + +A broadcast channel is built out of peer channels. It implements the same two traits, so protocol code that broadcasts sees only `SendChannel` and `RecvChannel`. Tagging is about how a channel is used, and the destination is an [open question](#open-questions). + +* **Send.** `send` submits a message to the group. The caller does not choose which peers the gossip reaches. +* **Receive.** `recv` yields messages from the group. It need not authenticate or distinguish anonymous senders. + +Gossip always happens within a namespace or topic. Some namespaces are ephemeral, derived from a shared secret with a tagged hash. Others are well known, such as a public order book. If the namespace includes a block hash, message IDs can be short. + +A broadcast channel uses two kinds of peer channel: + +* **Neighbor channels** connect a peer to each of its gossip neighbors. They are bidirectional, and may have any tag, including authenticated ones. +* **Submission channels** carry the peer's own messages into the group anonymously. A builder tagged `MessageUnlinkability` builds them. + +### 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 `recv` 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. + +### 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. + +### Anonymous submission + +1. The sender pushes its message, unsolicited, to a group member over a submission channel. +2. That member handles it as any new unsolicited message. From then on it is an ordinary element of the synchronized set. A message that is not linked to its owner can be relayed even on a channel that is not anonymous. +3. The sender watches synchronization for its own message. It keeps submitting anonymously until it is satisfied that the message has been disseminated. + +So the broadcast send channel's unlinkability rests on the submission channels. It does not rest on the neighbor channels. + +### 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. + +**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 open broadcast (coalition formation) and closed 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**, or multicast. 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.** In the random telephone model, any peer may be reachable, and each round a peer shares new information with one neighbor. In the local model, each peer is connected to only part of the network. Fungi mainly targets the local model, with a limited number of connections per peer. + +Connection based channels limit a peer to a more or less static local topology. A transport that can send a message to any peer at any time behaves more like a low capacity clique, or the random telephone model. + +## Uses + +Each message type states which channel suits it. All these uses are message based. A stream transport becomes message based by framing. + +| Use | Direction | Sender | +| --- | --- | --- | +| Session initiation with known peers (honest and semi-honest settings) | Bidirectional | Authenticated | +| Interactive payments: notification and confirmation for net settlement | Bidirectional, reliable, to one peer | The 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 formation | Bidirectional | Sender anonymous | +| Anonymous broadcast within a session, such as transaction outputs in the semi-honest and Byzantine settings | Unidirectional, to the broadcast domain | Message unlinkable and metadata hiding | + +## Open questions + +From the reviews and issues: + +1. **Destination tag.** An associated type on `SendChannel` and `RecvChannel` could say whether a channel reaches a single peer or uses multicast, like `Privacy`. A builder cannot express a separate `PeerChannel` trait generically without trait objects. The lean is to keep peer identity in a wrapper type for connection management. `PeerChannel` is deferred to a later PR; the decision is still open. +2. **Interactivity.** A type tag, or only a concern of construction and lifetime. The lean is no tag. +3. **Broadcast topic.** Bind a session's messages to a common root without depending on the transport, perhaps with a hash tag. + +Added by this draft, not from the reviews: + +4. **Name.** The code says `ConnectionUnlinkability`. Should the spec say "channel unlinkability"? +5. **Tag order.** `MessageUnlinkability` implies `ConnectionUnlinkability`, but the sealed tags have no order. Should a bound that requires `ConnectionUnlinkability` also accept `MessageUnlinkability`? +6. **Related messages.** The one-message adapter above is a sketch. How does a caller group related messages onto one channel? +7. **Own messages in the synchronized set.** If a sender adds its own message to its set before submission, synchronization shows that it held the message first. Should a sender keep its own message out of its set until it arrives through synchronization? diff --git a/docs/validity-proofs.md b/docs/validity-proofs.md new file mode 100644 index 0000000..5452ae5 --- /dev/null +++ b/docs/validity-proofs.md @@ -0,0 +1,718 @@ +--- +type: Specification +title: Validity proofs by allocation registration +description: "Candidate design: proving outputs are covered by inputs through anonymous allocation registration." +status: draft +stale_after: 2027-04-17T00:00:00Z +--- + + + +# 🤖 Validity proofs by allocation registration + +> **Status: candidate, under evaluation (2026-10-17).** This is the best +> approach found so far. Evaluation continues until validity proofs are +> needed. The code will then be rewritten from scratch for Fungi, and this +> document finalized. Figures marked *measured* come from a proof of concept +> on a shared machine; parts marked *proposed* are not implemented yet. + +The [overview](overview.md#validity-proofs) 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. + +## Why this approach + +It balances the trade-offs better than the alternatives evaluated so far: + +1. **Production-quality Rust crates.** The proofs use the + [jellyfish](https://github.com/EspressoSystems/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 required proofs. The + optional completion proof needs 16,386 (8,194 for its variant). For example + [Perpetual Powers of Tau](https://github.com/privacy-scaling-explorations/perpetualpowersoftau) + or [Aztec Ignition](https://github.com/AztecProtocol/ignition-verification). +3. **Efficient for prover and verifier, even with payments.** Every proof is + 769 bytes. Each takes about 0.16–0.31 s to prove on one thread, and + about 40–50 µs to verify in a batch (*measured*). + +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. + +## Requirements + +| Requirement | Status | +|---|---| +| **Privacy.** No association among inputs and outputs beyond the public boundary and what counterparties know of their own payments. | Argued in [Privacy](#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](#two-trees-so-payer-and-payee-never-share-a-path) and the blinding $\beta$. | +| **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](#no-value-is-created). | +| **Flood protection.** Every admitted object spends a unit issued by an admitted input, so each phase admits a bounded number of statements. | Met: at most $D$ registrations per input, and each output claims a registered leaf. Duplicates count once and equivocation is removed ([Acceptance rules](#acceptance-rules)). | +| **Session binding.** No statement replays across sessions. | Met: every proof takes `session`, or a root agreed in the session, as a public input. | +| **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. | Met: tags are per slot, and a leaf is claimable only under its own binding. Output ids must stay private until the output phase. | +| **Attributable failure.** A run either completes, or names an input that recovery can exclude. | Met by per-input signatures and the [signing rules](#signing-and-failures). 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 $D$ and $K$. The private messages for net settlement are open. | + +## 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 $M$. 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. + +$M$ is the sum of one sparse matrix per participant, $M = \sum_j M_j$. A +participant's $M_j$ 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 $a$ from payer $j$ to payee $k$ through payment vertex $p$ +appears in two blocks: the edge into $p$ in $M_j$, and the edge out of $p$ +in $M_k$. Both edges stay in the sum. What cancels is the net flow at $p$: +$+a$ in from $M_j$, $-a$ out from $M_k$, so $p$ neither creates nor destroys +value. Contracting $p$ gives an entry of $a$ 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. + +```mermaid +flowchart LR + subgraph payer["payer's matrix M_j"] + I1["input i (value public)"] + end + subgraph payee["payee's matrix M_k"] + O2["output o (amount public)"] + end + I1 -->|"a_change"| O1["payer's change output"] + I1 -->|"a"| P(("payment vertex p")) + P -->|"a"| O2 + I2["payee's input"] -->|"b"| O2 +``` + +### 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 +$M$: + +| Vertex | Conservation | Checked by | +|---|---|---| +| input | its slot amounts plus a hidden excess equal its public value | input proof | +| payment vertex | the payee can claim at most what the payer registered | registration proof plus output proof, linked by the binding | +| output | its claimed leaves sum to its public amount | output proof | + +Anything registered but not claimed, or committed but not registered, becomes +fee. So the proofs give non-inflation, not that every payment arrives. That +each payment arrives is checked by the payer, through a receipt, 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. It +doesn't depend on the size of $M$. + +## Intuition + +### Slots, registration and outputs + +Three steps carry value from an input to an output: + +1. **Slots.** Each input splits its value into $D = 9$ slots. Each slot + names an amount and a destination. The input commits to its slots with an + input proof, posted under its name. +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 $K = 2$ 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. + +Interactive payments and [net settlement](overview.md#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. $D = 9$ and $K = 2$ 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 +$B$, 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 + +$$\mathit{tag}_i = H_\mathsf{RTAG}(\mathit{session}, s, i),\quad 0 \le i \lt D,$$ + +where $s$ is a secret the input committed to. The tag is deterministic in +$(s, i)$, so a second registration of the same slot repeats the tag and is +dropped. It is pseudorandom without $s$, so it doesn't reveal the input. This +is the idea behind periodic $n$-times anonymous authentication.[^clone-wars] +Here the bound is the number of slots, and the slot's position in the tree +supplies $i$. + +### Flood protection + +Every admitted object spends a unit issued by an admitted input: + +- a registration spends one of its input's $D$ slots, so there are at most + $9 \times 729$ registrations; +- an output must claim at least one registered leaf, and each leaf can be + claimed by only one output. + +### 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 $B$ before the payer's input proof. + +The payer hands its registration proof to the payee once $R_S$ 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 named. Before that, the payer can still withhold the proof itself +(see [Signing and failures](#signing-and-failures)). + +## Parameters + +| Symbol | Value | Meaning | +|---|---|---| +| curve | BN254 | proof system field and pairing | +| proof system | TurboPlonk, KZG, jellyfish | universal setup | +| $H$ | Poseidon, width 4, rate 3, $\alpha = 5$, 8 full and 56 partial rounds | all in-circuit hashing | +| arity | 3 | every Merkle tree | +| $D$ | 9 | slots per input (2 tree levels) | +| inputs | at most 729 | session tree, 6 levels | +| registrations | at most 6,561 | registration tree, 8 levels | +| $K$ | 2 | registered leaves per output | +| amount bits | 51 | $2^{51} > $ 21 million BTC in satoshis | +| excess bits | 32 | an 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 + +$H_\mathsf{dom}(x_1, \dots, x_m)$ is the Poseidon sponge with the capacity +element set to the domain constant $\mathsf{dom}$, absorbing three elements +per permutation. Each domain has a fixed input length. Tree nodes are one +permutation of $(\mathsf{NODE}, c_1, c_2, c_3)$. + +In the proof of concept: + +- The state is $(\mathsf{dom}, 0, 0, 0)$. 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: + + | Domain | Constant | Inputs | + |---|---|---| + | ALLOC | 7 | 3 | + | OUT | 8 | 4 (two permutations) | + | SLOT | 11 | 3 | + | RTAG | 12 | 3 | + | CLAIM | 13 | 3 | + | SID | 14 | 1 | + | NODE | $2^{32}$ | 3 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 $\mathit{pk}$. +- 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 a hash of the + [coalition formation](overview.md#coalition-formation) proposal. + +| Object | Definition | Known to | Public | +|---|---|---|---| +| $s$ | random, fresh per input and per attempt | the input's owner | no | +| $a_i$, $B_i$ | slot $i$'s amount and destination binding | the input's owner; the payee for its own slot | no | +| slot | $\mathit{slot}_i = H_\mathsf{SLOT}(a_i, B_i, s)$ | the input's owner | no | +| input root | 2-level tree over $\mathit{slot}_0 \dots \mathit{slot}_8$ | everyone | yes | +| $R_S$ | session root: 6-level tree over the agreed input roots, in the agreed input order | everyone | yes | +| tag | $\mathit{tag}_i = H_\mathsf{RTAG}(\mathit{session}, s, i)$ | everyone, after registration | yes | +| leaf | $\mathit{leaf}_i = H_\mathsf{ALLOC}(a_i, B_i, \mathit{tag}_i)$ | everyone, after registration | yes | +| $R_L$ | registration root: 8-level tree over the agreed leaves, sorted by value (*proposed*) | everyone | yes | +| $R_T$ | tag root: 8-level tree over the agreed registrations' tags; only for completion proofs | everyone | yes | +| $\mathit{pk}$ | fresh key per output and per attempt; not a spending key | the payee | after outputs | +| output id | $\mathrm{SHA256}(\mathit{pk})$, first 31 bytes | the payee; everyone once the output is posted | yes | +| binding | $B = H_\mathsf{OUT}(\mathit{session}, \mathit{amount}, \mathit{id}, \beta)$ with a random blinding $\beta$ | the payee; the payer sees only $B$ | no | +| claim commitment | $\mathit{cc} = H_\mathsf{CLAIM}(u_1 \mathit{leaf}_1, u_2 \mathit{leaf}_2, r)$ | everyone | yes | +| $R_C$ | claim root: 8-level tree over the agreed outputs' claim commitments | everyone | yes | + +The output id follows the [concurrent PSBT](overview.md#psbt-concurrency) +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. + +Never authorize by revealing $\beta$: the payer knows $B$, and could then +recompute it for each output and find the one it funded. + +## Proof sequence and data dependencies + +Each public phase ends with agreement on a common upper state (see the +[block DAG](optimistic-track.md#phase-agreement)). 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. + +```mermaid +flowchart TD + S["session"] --> IP["input proofs (named)"] + IP -->|"agreed input roots"| RS["R_S"] + RS --> RP["registration proofs (anonymous)"] + RP -->|"agreed leaves, dedup by tag"| RL["R_L"] + RL --> OP["output proofs (anonymous)"] + RP -.->|"agreed tags"| RT["R_T"] + RT -.-> CP["completion proofs (optional, named)"] + OP -->|"agreed outputs, dedup by output id"| RC["R_C"] + OP --> SA["script authorizations"] + RC --> RCP["receipts (private, payee to payer)"] + RCP --> SIG["signatures (named)"] + SA --> SIG +``` + +| Step | Phase | Posted | By | Proof | Public inputs | Produces | +|---|---|---|---|---|---|---| +| 0 | coalition formation | — | aggregator | — | — | `session`, initial inputs | +| 1 | initial and auxiliary inputs | named | input owners | — | — | agreed input set | +| 2 | destination commitments | named | each input | input proof | `session`, value, input root | $R_S$ | +| 3 | allocation registration | anonymous | payer, or the payee holding its proof | registration proof | `session`, $R_S$, tag, leaf | $R_L$ | +| 3b | optional | named | each input | completion proof | `session`, input root, $R_T$ | shows the input's non-zero slots are all registered | +| 4 | outputs | anonymous | each output's owner | output proof | `session`, $R_L$, amount, output id, cc | output set, $R_C$ | +| 5 | script authorization | anonymous | each output's owner | signature | output id, $\mathit{pk}$, script | final outputs | +| 6 | signing | named | each input | — | — | transaction | + +A repeat of auxiliary inputs with proofs changes $R_S$. Registrations and +output proofs are then made again. + +## Synchronization requirements + +### Public phases + +Every public phase is a set to agree on, not a sequence. Proofs within a +phase are independent of each other. They depend only on the previous phase's +root, so they can be made and posted in any order and verified in one batch. +A phase's boundary is a phase transition in the +[block DAG](overview.md#synchronizing-protocol-state). + +### Private messages between payer and payee + +Each payment adds three private messages. Each must arrive inside a window +between two public agreements: + +```mermaid +sequenceDiagram + participant Payee + participant Payer + participant DAG as Validators (block DAG) + Payee->>Payee: pick pk, id = SHA256(pk), blinding, amount + Payee->>Payer: binding B + Payer->>DAG: input proof (slot commits to amount and B) + DAG-->>Payer: agreed R_S + Payer->>Payee: registration proof + Payer-->>DAG: registration (or Payee submits it) + DAG-->>Payee: agreed R_L + Payee->>DAG: output proof + DAG-->>Payee: agreed output set and R_C + Payee->>DAG: script, signed under pk + Payee->>Payer: receipt + Payer->>DAG: signature, after checking the receipt +``` + +| Message | After | Before | +|---|---|---| +| payee → payer: binding $B$ | `session` known; output amount and id chosen | the payer's input proof | +| payer → payee: registration proof | $R_S$ agreed | registrations close | +| payee → payer: receipt | $R_C$ agreed | the payer signs | + +What this means for being online: + +- Payer and payee must both be online from the start of the session. That is + needed for transaction liveness anyway. +- The payee fixes its output's amount and id before the payer's input proof. + It fixes the script only after the 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](overview.md#fault-tolerance-via-branched-execution), not by the proofs. + +## Statements + +All circuits are TurboPlonk over BN254 with the parameters above. + +### Input proof + +*Purpose:* conservation at an input, and commitment to its slots. + +- **Public:** `session`, value (the input's amount), input root. +- **Witness:** $s$; for each slot, $a_i$ and $B_i$; the excess $e$. +- **Constraints:** + - $a_i \lt 2^{51}$ for every slot, and $e \lt 2^{32}$; + - $\sum_i a_i + e = \mathit{value}$; + - the input root is the tree over $\mathit{slot}_i = H_\mathsf{SLOT}(a_i, B_i, s)$. +- **Cost (*measured*):** 1,855 gates, domain $2^{11}$, 0.31 s to prove. + +The range checks stop a hidden slot of $p - x$ 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 $B_i$ +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`, $R_S$, tag, leaf. +- **Witness:** $s$, $a_i$, $B_i$, the 8-level path from $\mathit{slot}_i$ to + $R_S$. +- **Constraints:** + - the path proves $\mathit{slot}_i$ is in $R_S$. The two inner levels expose + the position as base-3 digits, which give $i$. The outer six hide which + input it is; + - $\mathit{tag} = H_\mathsf{RTAG}(\mathit{session}, s, i)$; + - $\mathit{leaf} = H_\mathsf{ALLOC}(a_i, B_i, \mathit{tag})$, with the same + $a_i$ and $B_i$ variables as the slot. +- **Cost (*measured*):** 1,017 gates, domain $2^{10}$, 0.16 s to prove. + +No range check is needed, because $a_i$ is the slot's range-checked amount. + +### Output proof + +*Purpose:* conservation at an output. + +- **Public:** `session`, $R_L$, amount, output id, cc. +- **Witness:** $\beta$; for $k \in \{1, 2\}$, $a_k$, $\mathit{tag}_k$ + and a path; $u_2$ (second source used); a filler value; $r$. $u_1$ is the + constant 1. An unused source's path starts from the filler instead of its + leaf, and is not checked against $R_L$, but the prover must still supply + one. +- **Constraints:** + - $B = H_\mathsf{OUT}(\mathit{session}, \mathit{amount}, \mathit{id}, \beta)$; + - for each used source, $H_\mathsf{ALLOC}(a_k, B, \mathit{tag}_k)$ is in $R_L$; + - $u_1 = 1$, 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; + - if both sources are used, their leaves differ; + - $\sum_k u_k a_k = \mathit{amount}$; + - $\mathit{cc} = H_\mathsf{CLAIM}(u_1 \mathit{leaf}_1, u_2 \mathit{leaf}_2, r)$. + An unused source enters as 0, so a receipt can open only on a leaf the + output actually spent. +- **Cost:** 1,935 gates, domain $2^{11}$ (*counted*). About 0.31 s to prove, + measured at 2,028 gates in the same domain, before the output id replaced + a script hash and an output tag. + +$K = 2$ covers one payment plus the payee's own slot. A payee paid by +several payers uses one output per payment, or a larger $K$. Larger $K$ is not +measured. $K = 4$ probably moves to domain $2^{12}$, about 0.6 s +(*estimate*). + +### Receipt (private) + +*Purpose:* show the payer its payment was claimed, without saying which +output claimed it. + +- **Public:** $R_C$, the payer's leaf. +- **Witness:** the output's claim commitment, its path to $R_C$, the other + claimed leaf, $r$, and which side the payer's leaf is on. +- **Constraints:** the commitment is in $R_C$ and opens to the payer's leaf on + one side. +- **Cost (*measured*):** 827 gates for an 8-level $R_C$, domain $2^{10}$, + 0.17 s to prove. A 6-level $R_C$ (729 outputs) is 645 gates (*counted*). + It is verified only by the payer. + +### Completion proof (optional) + +Not part of the baseline. 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. That is worth having only at marginal cost, and these +proofs don't look marginal. + +*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 named 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. + +- **Public:** `session`, input root, $R_T$. +- **Constraints:** for each slot, $a_i = 0$, or + $\mathit{tag}_i = H_\mathsf{RTAG}(\mathit{session}, s, i)$ is in $R_T$. +- **Cost:** 8,578 gates, domain $2^{14}$ (*counted*). 2.3 s to prove, + measured at 8,569 gates without destination bindings, in the same domain. + +A variant publishes $\mathit{sid} = H_\mathsf{SID}(s)$ in the input proof and +binds the completion proof to it, with the same $R_T$. That fits $2^{13}$ +(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 $R_L$, with no +$R_T$. That costs about 810 more gates, still in $2^{14}$ (*estimate*). The +sid 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. +- **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. Only the id's owner can + make both, unless the id leaked early. The output is removed, and its + leaves' value goes to the fee. +- **Trees:** each in an order that doesn't depend on arrival: + - $R_S$ over input roots in the agreed input order; + - $R_L$ over agreed leaves sorted by value (*proposed*; the proof of + concept uses arrival order); + - $R_C$ over exactly the kept outputs' claim commitments, sorted by output + id (*proposed*); + - $R_T$, if completion proofs are used, over the kept registrations' tags. +- **Script authorization.** After the output set is agreed, each output's + owner posts $(\mathit{pk}, \mathit{script}, \sigma)$, with $\mathit{pk}$ an + x-only secp256k1 key. It is accepted if the first 31 bytes of + $\mathrm{SHA256}(\mathit{pk})$ equal the output id, and $\sigma$ is a valid + BIP 340 signature under $\mathit{pk}$ over + $\mathrm{SHA256}(\mathit{session} \| \mathit{id} \| \mathit{script})$. + 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 $\sum \mathit{value} - \sum \mathit{amount}$. It is + public and must meet the session's terms. + +## Signing and failures + +The rules for signing: + +- **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 $R_C$; 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 $n - 2$ participants must be able to make +progress without them: + +- **A refusal is attributable.** Signatures are per input, so an input that + doesn't sign is named. 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 from the destination commitments without the named input.** The + retry is a new recovery proposal, so it has a new `session`, and keeps the + exclusions of earlier attempts. Everything from the input proofs on is + redone with fresh secrets, amounts, keys and output ids. That is about 1.1 s of proving per participant on one thread: an + input, two registrations, an output and a receipt (*derived*). +- **Not in place.** Continuing the same attempt without the named 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: + +| Failure | Who is named | Who loses | +|---|---|---| +| payer refuses to sign after a valid receipt | the payer's input | the payee's payment, until the retry | +| payee never claims | the payer's input (no receipt, so it won't sign) | the pair | +| payer never hands over its registration proof | the 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 it | the pair | +| anyone posts an invalid proof | nobody needs to be: it is rejected | nobody | + +A payee that never claims can get each payer who agreed to pay it named 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 $\sum \mathit{amount} \le \sum \mathit{registered} \le \sum \mathit{value}$. +The rest is fee. This is non-inflation only. That each payment arrives is a +separate check, by receipts before signing, and failures are attributed as in +[Signing and failures](#signing-and-failures). + +Non-inflation needs only the dedup by output id and the binding. Keeping the +output id private until the output phase protects liveness instead. To take +over an honest output's id, an attacker needs registered leaves bound to a +binding containing that id. Slots fix their bindings in the input proofs, so +that is impossible unless the payee leaks its id before then. In the proof of +concept even a leaked id can't be taken: an output is accepted only together +with a signature under the key the id hashes. With script authorization as a +separate phase, the output phase could carry such a signature too +(*proposed*). + +### Privacy + +- **The payee doesn't learn the paying input.** The payer's path is a + zero-knowledge witness. Tags are pseudorandom without $s$. +- **The payer doesn't learn the funded output.** It knows only $B$. The output + id becomes public when the output is posted, but the blinding never leaves + the payee, so the payer can't match $B$ to it. 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 $K$ 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. +- **Proofs are zero-knowledge as configured.** jellyfish masks the wire, + permutation and quotient polynomials when proving. + +### 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 $s$ (tags). +- $B$ and the claim commitment hide their contents, given their random + blindings $\beta$ and $r$. +- Anonymous submission of registrations and outputs. + +Attempting a transaction leaks information that no proof can hide. Fresh +amounts, keys and output ids on each attempt limit what recurs across +attempts. + +## Performance + +*Measured* with jellyfish on BN254, under load 3–6, medians of 3: + +| Proof | Gates | Domain | Prove, 1 / 10 threads | Verify, single | Batched, per proof | +|---|---|---|---|---|---| +| input | 1,855 | $2^{11}$ | 309 / 66 ms | 1.22 ms | 50 µs | +| registration | 1,017 | $2^{10}$ | 164 / 37 ms | 1.26 ms | 51 µs | +| output, with claim commitment | 1,935 | $2^{11}$ | 313 / 65 ms | 1.26 ms | 43 µs | +| receipt | 827 | $2^{10}$ | 165 / 36 ms | 1.24 ms | 43 µs | +| completion (optional) | 8,578 | $2^{14}$ | 2,261 / 440 ms[^value-mode] | 1.22 ms | 42 µ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. + +### Compared with other approaches + +For an output funded by two payers: + +| Approach | Setup | Bytes | Payee proving | +|---|---|---|---| +| this one | universal | 2,723 (two registrations and one output, with public inputs) | 0.31 s | +| split proving, Groth16 | per circuit | 1,176, with public inputs | not measured | +| recursion, Groth16 two-chain | per circuit | 484 | 6.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. +- Whether the output phase carries a signature under the output id's key. +- Tree padding. +- Measured cost of the output proof with the output id, and of $K > 2$. +- Whether to keep completion proofs at all, as an optional extension. +- Where allocation registration sits relative to the unproven output phase of + the optimistic branch. +- 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. + +[^value-mode]: Measured at 8,569 gates, without destination bindings. + +[^clone-wars]: J. Camenisch, S. Hohenberger, M. Kohlweiss, A. Lysyanskaya and M. Meyerovich, [*How to Win the Clone Wars: Efficient Periodic n-Times Anonymous Authentication*](https://eprint.iacr.org/2006/454) (2006). diff --git a/flake.lock b/flake.lock index 1ffe3ad..421d9fb 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1788450739, - "narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=", + "lastModified": 1790898470, + "narHash": "sha256-zTwuwezD0w3hpga6a6P8emidzAZFyWqlNeRBlpWOOl8=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993", + "rev": "024633cd702b10285db5cb19b40ad48d2399ba60", "type": "github" }, "original": { @@ -36,11 +36,11 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1788057806, - "narHash": "sha256-DTQSMxzDWmT0zhguthvegnVkn7CFqGCv4IHCzk5ZUpM=", + "lastModified": 1790477367, + "narHash": "sha256-oujbxmVKDhci2E4EM3KyAbRUgp5/IsCoiA/LfEF7OOk=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "596e2e3940e09b2abbeb03f75fa1828c57fcd72c", + "rev": "f7cd230690d9fc982d06129f9189b101fddcfa3b", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index c0e75f6..5443704 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,7 @@ ./nix/preprocessors.nix ./nix/site.nix ./nix/devshell.nix + ./nix/notebook.nix ./nix/spellcheck.nix ./nix/apps/validate-commits ]; diff --git a/nix/notebook.nix b/nix/notebook.nix new file mode 100644 index 0000000..0b9f140 --- /dev/null +++ b/nix/notebook.nix @@ -0,0 +1,36 @@ +{ ... }: +{ + perSystem = + { pkgs, ... }: + let + # Every dependency of the notebook is packaged in nixpkgs. + notebookDeps = + p: with p; [ + ipykernel + matplotlib + nbconvert + numpy + pandas + seaborn + ]; + in + { + # The notebook, re-executed. Execution is deterministic and records no + # timing metadata, so an up to date notebook is byte-identical to the + # build output. + packages.notebook = + pkgs.runCommand "Denominations_and_gap_size_distributions.ipynb" + { nativeBuildInputs = [ (pkgs.python3.withPackages notebookDeps) ]; } + '' + export HOME=$(mktemp -d) + install -m 644 ${../docs/Denominations_and_gap_size_distributions.ipynb} notebook.ipynb + jupyter nbconvert --execute --inplace --to notebook \ + --ExecutePreprocessor.record_timing=False notebook.ipynb + cp notebook.ipynb $out + ''; + + devShells.notebook = pkgs.mkShell { + packages = [ (pkgs.python3.withPackages (p: notebookDeps p ++ [ p.jupyterlab ])) ]; + }; + }; +} diff --git a/nix/site.nix b/nix/site.nix index 0490dcd..54f09de 100644 --- a/nix/site.nix +++ b/nix/site.nix @@ -41,12 +41,12 @@ ''; # lychee loads CA certificates to build its HTTP client even with --offline. links = pkgs.runCommand "links" { nativeBuildInputs = [ pkgs.lychee pkgs.cacert ]; } '' - # The site is served from /docs/, so a link from the root leaves it. - mkdir root && ln -s ${site} root/docs - # The 404 page needs for browsers to find its assets. + # The site is served from /docs-draft/, so a link from the root leaves it. + mkdir root && ln -s ${site} root/docs-draft + # The 404 page needs for browsers to find its assets. # Lychee does not check this, so verify it separately. - grep -qF '' root/docs/404.html - lychee --offline --include-fragments --no-progress --root-dir $PWD/root root/docs + grep -qF '' root/docs-draft/404.html + lychee --offline --include-fragments --no-progress --root-dir $PWD/root root/docs-draft touch $out ''; }; diff --git a/theme/nb-table.js b/theme/nb-table.js new file mode 100644 index 0000000..22e1235 --- /dev/null +++ b/theme/nb-table.js @@ -0,0 +1,67 @@ +// Paginate long notebook tables. The Colab `data_table` widget is interactive +// JS that cannot run in a static book, so its rendered fallback is one long +// table; this restores page-through navigation client-side, no dependencies. +(function () { + var PAGE = 20; + + var style = document.createElement("style"); + style.textContent = + ".nb-pagination{display:flex;gap:.25rem;flex-wrap:wrap;margin:.5rem 0 1rem}" + + ".nb-pagination button{font:inherit;padding:.15rem .5rem;cursor:pointer;" + + "border:1px solid var(--sidebar-active,#4183c4);border-radius:4px;" + + "background:transparent;color:inherit;opacity:.7}" + + ".nb-pagination button.active{opacity:1;background:var(--sidebar-active,#4183c4);" + + "color:var(--sidebar-bg,#fff);border-color:transparent}" + + // print shows every row, so shrink the table to keep its widest rows on the page + "@media print{.nb-output tbody tr{display:table-row!important}" + + ".nb-output table{font-size:.85em}.nb-output th,.nb-output td{padding:3px 8px}" + + ".nb-pagination{display:none}}"; + document.head.appendChild(style); + + function paginate(table) { + var body = table.tBodies[0]; + if (!body) return; + var rows = Array.prototype.slice.call(body.rows); + if (rows.length <= PAGE) return; + + var pages = Math.ceil(rows.length / PAGE); + var nav = document.createElement("div"); + nav.className = "nb-pagination"; + var buttons = []; + + function show(p) { + rows.forEach(function (r, i) { + r.style.display = i >= p * PAGE && i < (p + 1) * PAGE ? "" : "none"; + }); + buttons.forEach(function (b, i) { + b.classList.toggle("active", i === p); + }); + } + + for (var p = 0; p < pages; p++) { + (function (p) { + var b = document.createElement("button"); + b.type = "button"; + b.textContent = String(p + 1); + b.addEventListener("click", function () { + show(p); + }); + nav.appendChild(b); + buttons.push(b); + })(p); + } + + table.parentNode.insertBefore(nav, table.nextSibling); + show(0); + } + + function run() { + document.querySelectorAll(".nb-output table").forEach(paginate); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", run); + } else { + run(); + } +})();