Add basic dos protection
MODIFY
HiddenWallet.ChaumianTumbler/Controllers/TumblerController.cs
HiddenWallet.ChaumianTumbler/Controllers/TumblerController.cs
@@ -12,6 +12,7 @@ using NBitcoin.RPC;
using HiddenWallet.ChaumianTumbler.Store;
using HiddenWallet.ChaumianTumbler.Clients;
using Nito.AsyncEx;
+using HiddenWallet.ChaumianTumbler.Referee;
namespace HiddenWallet.ChaumianTumbler.Controllers
{
@@ -108,9 +109,12 @@ namespace HiddenWallet.ChaumianTumbler.Controllers
throw new ArgumentException("Input is already registered by another Alice");
}
- if (Global.UtxoReferee.Utxos.Any(x => x.Hash == op.Hash && x.N == op.N))
+ BannedUtxo banned = Global.UtxoReferee.Utxos.FirstOrDefault(x => x.Utxo.Hash == op.Hash && x.Utxo.N == op.N);
+ if (banned != default(BannedUtxo))
{
- throw new ArgumentException("Input is already registered by another Alice");
+ var maxBan = (int)TimeSpan.FromDays(30).TotalMinutes;
+ int banLeft = maxBan - (int)((DateTimeOffset.UtcNow - banned.TimeOfBan).TotalMinutes);
+ throw new ArgumentException($"Input is banned for {banLeft} minutes");
}
var txOutResponse = await Global.RpcClient.SendCommandAsync(RPCOperations.gettxout, op.Hash.ToString(), op.N, true);
@@ -362,19 +366,25 @@ namespace HiddenWallet.ChaumianTumbler.Controllers
if (Global.StateMachine.CoinJoin.Inputs.Count <= signatureModel.Index)
{
// round fails, ban alice
- throw new NotImplementedException();
+ await Global.UtxoReferee.BanAliceAsync(alice);
+ Global.StateMachine.FallBackRound = true;
+ Global.StateMachine.UpdatePhase(TumblerPhase.InputRegistration);
}
if(Global.StateMachine.CoinJoin.Inputs[signatureModel.Index].WitScript != default)
{
// round fails, ban alice
- throw new NotImplementedException();
+ await Global.UtxoReferee.BanAliceAsync(alice);
+ Global.StateMachine.FallBackRound = true;
+ Global.StateMachine.UpdatePhase(TumblerPhase.InputRegistration);
}
Global.StateMachine.CoinJoin.Inputs[signatureModel.Index].WitScript = witness;
var output = alice.Inputs.Single(x => x.OutPoint == Global.StateMachine.CoinJoin.Inputs[signatureModel.Index].PrevOut).Output;
if(!Script.VerifyScript(output.ScriptPubKey, Global.StateMachine.CoinJoin, signatureModel.Index, output.Value, ScriptVerify.Standard, SigHash.All))
{
// round fails, ban alice
- throw new NotImplementedException();
+ await Global.UtxoReferee.BanAliceAsync(alice);
+ Global.StateMachine.FallBackRound = true;
+ Global.StateMachine.UpdatePhase(TumblerPhase.InputRegistration);
}
}

MODIFY
HiddenWallet.ChaumianTumbler/Global.cs
HiddenWallet.ChaumianTumbler/Global.cs
@@ -22,6 +22,8 @@ namespace HiddenWallet.ChaumianTumbler
public static UtxoReferee UtxoReferee;
public static string UtxoRefereePath = Path.Combine(DataDir, "BannedUtxos.json");
+ public static Task UtxoRefereeJob;
+ public static CancellationTokenSource UtxoRefereeJobCancel;
public static RPCClient RpcClient;

MODIFY
HiddenWallet.ChaumianTumbler/Program.cs
HiddenWallet.ChaumianTumbler/Program.cs
@@ -69,6 +69,8 @@ namespace HiddenWallet.ChaumianTumbler
{
Global.UtxoReferee = new UtxoReferee();
}
+ Global.UtxoRefereeJobCancel = new CancellationTokenSource();
+ Global.UtxoRefereeJob = Global.UtxoReferee.StartAsync(Global.UtxoRefereeJobCancel.Token);
Global.StateMachine = new TumblerStateMachine();
Global.StateMachineJobCancel = new CancellationTokenSource();

Add basic dos protection