One way to prevent a coinswap server from learning individual input-output links is to perform the service as a Multi Party Computation (MPC).
The CoinSwap service shall be provided by n >= 2 servers CS_1…CS_n, each with a known TOR address, that are assumed to not all be colluding.
Suppose I want to self-spend my output C to C’ = C + x*G - fee*H.
The fee can be assumed to be fixed, e.g. to (1+21+r) * accept_fee_base, where r accounts for the swap service reward.
I will send one of the servers the following info
- an offset x_0
- C’
- a BP range proof for C’
and the remaining n-1 servers will each receive
- a commitment to x_0
- a random offset x_i
where x_0 is chosen as x - Sum x_i.
At the end of each day, an MPC takes all these self-spend shares submitted throughout the day, and recombines them based on the x_0 commitment of each. Then the MPC computes C from C’ and the total offset, verifies each one (balance and input must be in UTXO while output is not), and aggregates all valid ones together into one big transaction, with an additional kernel and swap reward output.
Even n-1 colluding servers should be unable to link C and C’ together from this MPC output.
A DOS attack could submit many invalid tx shares, prompting a necessary MPC to filters them out. This MPC could turn out to be too expensive to deal effectively with the attack. That is the biggest weakness of this scheme.
It would require the MPC overhead to be relatively modest.
PS: Note that we can simply set n=1 to get a non-MPC scheme with minimal messages.
PPS: We can also start out with an n>1 service that starts out as non-MPC (e.g. each day the n servers pick a random leader to do the aggregation) but that aims to migrate to MPC in future with no change in interface.