I’ve been thinking about the replays and aggregators and I think this is another option that is similar to anchors, but without anchors. The idea was described in this gist and below is a paste of its content:
Replay resistance through aggregators
One of the previous protections against replay attacks required the attacker to replay a sequence of payjoin transactions until the attacker was met with an impossible requirement of replaying a transaction that was impossible to replay due to a duplicate output (anchor solution) consensus rule violation.
This is an attempt to not introduce an absolute protection as the anchor solution does, but perhaps something that is for most practical concerns a good enough solution.
Main idea
Let’s assume we have a daily aggregator A
. Every transaction that gets published on the chain also sends a coinswap for each created output to A
.
Let’s reuse the idea of making every transaction a payjoin. We now have the same first step part of the attack protected in the same way which is that the attacker would need to replay a sequence of payjoin transactions. But we lack the initial condition which would make it impossible to replay the first transaction.
Let’s assume we get an output from a daily aggregator O1
. If a significant aggregation took place in A
when O1
was created, then we can assume that it is extremely hard to replay the aggregated transaction that created O1
. This is because all the outputs in the aggregated transactions need to be spent and the attacker would also need to know how to generate all the inputs of the aggregated transaction which seems almost impossible to do. The output O1
can thus play a similar role as an anchor, but can be spent.
All we have to do is know which outputs were ‘coinswapped’ and then use these as inputs for our payjoin transactions.
In order to be able to do simultaneous transactions, the wallet makes sure it has N
“safe” outputs available. We could label a coinswapped output as “safe” by using one of the zero bits in the bulletproof and setting it to 1.
Note: When doing a payjoin with a safe input B_I'
, then the output we create B_O
is also safe.
Wallet algorithm
Send
Alice (sender) has an input A_I
and a change output A_O
. After the transaction has been broadcasted, A_O'
is created with a bulletproof coinswap bit set to 1 and A_O -> A_O'
is sent to the daily aggregator.
Receive
Bob (receiver) contributes an input B_I'
(coinswapped) to the transaction, making a payjoin. Bob also has an output B_O
and similarly as in the case of Alice, after the transaction has been broadcasted, B_O'
is created with a bulletproof coinswap bit set to 1 and B_O -> B_O'
is sent to the daily aggregator.
First receive
It is impossible to contribute a coinswapped input when you don’t own any output. The first receive can be made safe if the received output is coinswapped in the aggregator before doing any other transaction.
Improvements
This is hard enough to replay as is, but can be made basically impossible if the daily aggregator contributes aggri-1 -> aggri to the daily aggregated transaction i
and then in i+1
adds aggri -> aggri+1 and so on. This would require the attacker to replay everything from all the daily aggregators which is practically impossible.