-
Notifications
You must be signed in to change notification settings - Fork 492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Detecting and (avoid) Banning Wasabi coinjoins #11946
Detecting and (avoid) Banning Wasabi coinjoins #11946
Conversation
This is because the two mechanisms for detecting incoming coinjoin transactions are not enough in many cases and we were banning our own coinjoin inputs.
a89c9bb
to
da2095b
Compare
da2095b
to
f9f1f9d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, only nits
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/UtxoPrisonWardenTests.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only partial review
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/OffenderSerializationTests.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A question before submitting feedback: It looks like as an attacker I can create a tx that will pass IsWasabiCoinJoinLookingTx
and therefore be able to disrupt the rounds freely with the outputs of this transaction. Is this true? Is this a problem?
If yes to both, maybe we can make sure that an unused key belonging to coordinator's xpub is used as output
&& tx.Inputs.Count >= Config.MinInputCountByRound | ||
&& tx.Inputs.Count <= Config.MaxInputCountByRound | ||
&& tx.Outputs.All(x => Config.AllowedOutputTypes.Any(y => x.ScriptPubKey.IsScriptType(y))) | ||
&& tx.Outputs.Zip(tx.Outputs.Skip(1), (a, b) => (First: a.Value, Second: b.Value)).All(p => p.First >= p.Second); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these heuristics exactly the same than Dumplings @Szpoti ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is the logic in dumplings:
tx.Inputs.All(x => x.PrevOutput.ScriptPubKey.IsScriptType(ScriptType.P2WPKH) || x.PrevOutput.ScriptPubKey.IsScriptType(ScriptType.Taproot))
&& inputCount >= 50
&& inputValues.SequenceEqual(inputValues.OrderByDescending(x => x))
&& outputValues.SequenceEqual(outputValues.OrderByDescending(x => x))
&& outputValues.Count(x => Wasabi2Denominations.Contains(x.Satoshi)) > outputCount * 0.8;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take into account that dumplings, in general, knows less than wasabi. Dumplings assumes the inputCount
is greater than 50 because it doesn't know what the MinInputCountByRound
really is. It assumes all outputs are wpkh or tr because it doesn't know what the AllowedOutputTypes
really are.
OTOH, dumplings know the prevOutputs so, it knows the input values and then it can check the order of the inputs, wasabi cannot. For this same reason it could check that all the inputs are wpkh or tr.
The 80% of std denominations is just a bug waiting to be found. Where is that 80% comes from? If tomorrow we implement pay in coinjoins that would need to change.
Sure. You can create a huge wasabi coinjoin looking transaction to disrupt rounds but it is hard to imagine a more expensive way to attack.
There are cases where the coordinator cannot take any fee and in that case we risk to ban ourselves. |
5d18d43
to
a6859e7
Compare
You're right, I was under the false feeling that we could disrupt many rounds with one wabisabi's like cj, which is not the case as we can only disrupt the ongoing rounds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cACK and code LGTM
It would make sense to me to create a new offense DisruptedSeveralRoundsInSameTransaction
if a tx disrupts several rounds
Please consider it and feel free to either implement it in a follow up PR either don't implement it, both are fine for me.
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/CoordinatorTests.cs
Outdated
Show resolved
Hide resolved
Who do I have to kill to get this PR approved? |
CoinJoinIdStore.Contains(txId) || IsFinishedCoinJoin(txId) || IsWasabiCoinJoinLookingTx(tx); | ||
|
||
private bool IsFinishedCoinJoin(uint256 txId) => | ||
Arena.RoundStates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make sure: I don't see any RoundState.Phase == Phase.Ended
. Is it not necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No because if it is in signing state and matches the txid then it doesn't matter whether it already switched to Ended or not, it is one of our coinjoins.
In the first versions i tested the Phase but here we use RoundStates which is not updated immediately but after all the steps in the round have happen so, it only added problem
|
||
private static Transaction CreateTransaction(Money amount, OutPoint? outPoint = default) | ||
{ | ||
var tx = Network.RegTest.CreateTransaction(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be good to use Main
because that's closer to what is actually being done in the production then:
var tx = Network.RegTest.CreateTransaction(); | |
var tx = Network.Main.CreateTransaction(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NewMockRpcClient
below also relies on Main
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it can be. I saw in my mobile phone that the pr was approved and then i merged it immediately. I didn't see the comments, sorry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Me?
This PR fixes a few very important things in the process of detecting and banning round disruptions by spending coins participating in coinjoin rounds.
Arena.Rounds
instead ofArena.RoundStates
.Additionally to these problems this PR adds: