Problem
Payjoin transactions improves sender privacy by hiding change, recipient amount and breaking common input ownership heuristic. It also provides an opportunity to consolidate UTXOs for the recipient. This requires coordination or interaction between sender and recipient.
Recipient needs to trust the sender while sharing UTXOs hence it affects privacy if done with untrusted people. Example: Using payjoin for donations
Research
Users can avoid payjoin with untrusted users if receiving payments but this does not remove the coordination required and limits payjoin usage.
Do 2 person coinjoin however you share UTXO with a random user in this case.
I was brainstorming about
SIGHASH_RING
to emulate ring signatures and decoy inputs used in monero transactions. This consensus change does not look possible.
Solution
Tx: b3fb5df0230353ece5491a8fa79398f17576318a9bcab72fa253ca3b58cf9e00
This is a monero transaction in which 16 ring size is used for the input hence you cannot determine which input is signed by the user out of 16. The amounts are hidden and stealth addresses are used for outputs.
Can we achieve something similar in a bitcoin transaction without any interactions between sender and recipient? It wouldn’t be the same because Ring CT is not possible on bitcoin.
Goals
- Use inputs with history linked to others
- Hide payment amount
- Use silent payment address
What if you could have multiple inputs in transaction that other users own? Yes, this is possible if you do coinswap on-chain or swap using statechains or buy statecoin from a seller using Lightning Latch or do submarine swaps using boltz.
So user will have multiple inputs in a transaction, one of them with history beloging to other user. Remaining will have different on-chain footprint. It will not be possible for an on-chain analyst to know if they all belong to the same user. This does not require the level of interaction involved in a coinjoin transaction which has inputs from different users. Inputs required for a transaction are prepared by the user and swaps can be automated or abstracted away from user.
What will the user need apart from some inputs swapped off-chain? They will need silent payment address for recipient and create a transaction with multiple outputs. One of these outputs could even be the change address. So, change amount and script type will be chosen accordingly.
Implementation
Users should label some UTXOs as “octojoin” so that they can be used in octojoin transactions. Ideally these UTXOs are the ones swapped with others and linked with someone else’s transaction history. An algorithm which needs some values from user to create the transaction or notify the user about missing inputs will be implemented by different wallets:
Payment amount
Number of inputs (default:3)
Number of outputs (default:2)
Equal amounts in inputs (default:false)
Proof of Concept
I have used mercury layer in this PoC, however you can do submarine swaps or regular on-chain swaps as well.
Alice swaps 2 UTXOs with Bob and Carol using mercury layer. These are the steps you need to follow for swapping coins (example):
$ cargo run list-statecoins test1
{
"coin.address": "tml1qqpy3pfer35yt7yduytrcxzjtjrr84cd0ymuwqktxn5006mrm0zq88srsuuuln2wmxc8jdyqj32qw0rkvajaettxzseysegu9d2p833uwfhsuj8thu",
"coin.aggregated_address": "tb1p3pyd0h8j67mp37fk575v64f8ags9u02u6ycvq7jqquzwnd9ujx3qfjprq5",
"coin.amount": 1000000,
"coin.locktime": 303828,
"coin.statechain_id": "27f0aeef853d4035a4504643e4b2007b",
"coin.status": "CONFIRMED",
"coin.user_pubkey": "024885391c6845f88de1163c18525c8633d70d7937c702cb34e8f7eb63dbc4039e"
}
$ cargo run list-statecoins test2
{
"coin.address": "tml1qqpgj4yez9dp0mqrld8g8hda33aa6wr26umktlaezween54gtj2dzsgz4460y3hhm5qh3gv7tu9wu9lrw3sanc7nuffxgh6hmaj77gdghpssmsjmvn",
"coin.aggregated_address": "tb1pq8eujf64svdlpk6hu98hze4a4cc6rkhsr2c0qcpz8vl9nn2tqj3szd0wwu",
"coin.amount": 1000000,
"coin.locktime": 300306,
"coin.statechain_id": "63bb92e80af64cadbd1355557298e23d",
"coin.status": "CONFIRMED",
"coin.user_pubkey": "02895499115a17ec03fb4e83ddbd8c7bdd386ad73765ffb913b399d2a85c94d141"
}
$ cargo run new-transfer-address test2 -b
{
"batch_id": "b998441c-4ce2-474e-8dc8-4fea42cc76ec",
"new_transfer_address:": "tml1qqp9jjshh7txvery5xddf07src8v6mhxkdm0nasjj9h72mqhg5dajucrlqtlx8e5ct4gdslgsn5dp9as00n3cq5cf4lnts5t83ehcts2ujhspv9rr5"
}
$ cargo run transfer-send test1 27f0aeef853d4035a4504643e4b2007b tml1qqp9jjshh7txvery5xddf07src8v6mhxkdm0nasjj9h72mqhg5dajucrlqtlx8e5ct4gdslgsn5dp9as00n3cq5cf4lnts5t83ehcts2ujhspv9rr5 b998441c-4ce2-474e-8dc8-4fea42cc76ec
{
"Transfer": "sent"
}
$ cargo run new-transfer-address test1
{
"new_transfer_address:": "tml1qqpy9z5gazc8yw6c0awkglt796src0m7hsxed5fpf4r088vddnrljegrl6m75k7wu52rp793cp468fezawqg73dfedx9fqfnrrt0zfgsku4swrnmze"
}
$ cargo run transfer-send test2 63bb92e80af64cadbd1355557298e23d tml1qqpy9z5gazc8yw6c0awkglt796src0m7hsxed5fpf4r088vddnrljegrl6m75k7wu52rp793cp468fezawqg73dfedx9fqfnrrt0zfgsku4swrnmze b998441c-4ce2-474e-8dc8-4fea42cc76ec
{
"Transfer": "sent"
}
$ cargo run transfer-receive test1
$ cargo run transfer-receive test2
If PSBT is supported for withdrawals in mercury layer we wont need to add the extra step of moving swapped coins to our address before using for payments. However, it can be ignored for the proof of concept.
Assume Alice now has 1 input that existed in the wallet and 2 swapped from Bob and Carol. She will create a transaction with these 3 inputs to pay Dave in a octojoin transaction:
https://mempool.space/signet/tx/5447f526c64d4f00171f024aae38a1c347ad00e7a295247f9c6acfca21ed2655
Dave shared his silent payment address with Alice which was used to generate 2 addresses used as outputs. Multiple interpretation are possible in this transaction with enough anonset and it is difficult to find that Dave was paid ~0.03 BTC.
Pseudocode
We will need a market of sellers and buyers for UTXO of different denominations. 2 bounties exist to improve the usage of mercury layer that you may find interesting: https://invincible-privacy.github.io/donate/projects/
Best practices
Outputs from octojoin tx should not be spent together
Avoid mixed input types
Spoof wallet fingerprints
Octojoin does not replace coinjoin, payjoin etc. but provide an alternative option to improve privacy in bitcoin transactions.
Credits
Chris Belcher
Dan Gould
Nicholas Gregory
Tom Trevethan
Ruben Somsen