Add more checks
MODIFY
HiddenWallet.ChaumianTumbler/Configuration/Config.cs
HiddenWallet.ChaumianTumbler/Configuration/Config.cs
@@ -58,6 +58,9 @@ namespace HiddenWallet.ChaumianTumbler.Configuration
[JsonProperty(PropertyName = "SigningPhaseTimeoutInSeconds")]
public int? SigningPhaseTimeoutInSeconds { get; private set; }
+ [JsonProperty(PropertyName = "MaximumInputsPerAlices")]
+ public int? MaximumInputsPerAlices { get; private set; }
+
public Config()
{
@@ -91,6 +94,7 @@ namespace HiddenWallet.ChaumianTumbler.Configuration
InputConfirmationPhaseTimeoutInSeconds = 60;
OutputRegistrationPhaseTimeoutInSeconds = 60;
SigningPhaseTimeoutInSeconds = 60;
+ MaximumInputsPerAlices = 7;
if (!File.Exists(path))
{
@@ -114,6 +118,7 @@ namespace HiddenWallet.ChaumianTumbler.Configuration
InputConfirmationPhaseTimeoutInSeconds = config.InputConfirmationPhaseTimeoutInSeconds ?? InputConfirmationPhaseTimeoutInSeconds;
OutputRegistrationPhaseTimeoutInSeconds = config.OutputRegistrationPhaseTimeoutInSeconds ?? OutputRegistrationPhaseTimeoutInSeconds;
SigningPhaseTimeoutInSeconds = config.SigningPhaseTimeoutInSeconds ?? SigningPhaseTimeoutInSeconds;
+ MaximumInputsPerAlices = config.MaximumInputsPerAlices ?? MaximumInputsPerAlices;
}
await ToFileAsync(path, cancel);

MODIFY
HiddenWallet.ChaumianTumbler/Controllers/TumblerController.cs
HiddenWallet.ChaumianTumbler/Controllers/TumblerController.cs
@@ -8,6 +8,7 @@ using HiddenWallet.ChaumianTumbler.Models;
using HiddenWallet.ChaumianCoinJoin;
using Org.BouncyCastle.Utilities.Encoders;
using NBitcoin;
+using NBitcoin.RPC;
namespace HiddenWallet.ChaumianTumbler.Controllers
{
@@ -53,7 +54,8 @@ namespace HiddenWallet.ChaumianTumbler.Controllers
Phase = Global.StateMachine.Phase.ToString(),
Denomination = Global.StateMachine.Denomination.ToString(fplus: false, trimExcessZero: true),
AnonymitySet = Global.StateMachine.AnonymitySet,
- TimeSpentInInputRegistrationInSeconds = (int)Global.StateMachine.TimeSpentInInputRegistration.TotalSeconds
+ TimeSpentInInputRegistrationInSeconds = (int)Global.StateMachine.TimeSpentInInputRegistration.TotalSeconds,
+ MaximumInputsPerAlices = (int)Global.Config.MaximumInputsPerAlices
});
}
catch (Exception ex)
@@ -64,29 +66,49 @@ namespace HiddenWallet.ChaumianTumbler.Controllers
[Route("inputs")]
[HttpPost]
- public IActionResult Inputs(InputsRequest request)
+ public async Task<IActionResult> InputsAsync(InputsRequest request)
{
try
{
+ // Check not nulls
if (request.BlindedOutput == null) return new BadRequestResult();
if (request.ChangeOutput == null) return new BadRequestResult();
if (request.Inputs == null || request.Inputs.Count() == 0) return new BadRequestResult();
- byte[] blindedOutut = HexHelpers.GetBytes(request.BlindedOutput);
+
+ // Check format (parse everyting))
+ byte[] blindedOutput = HexHelpers.GetBytes(request.BlindedOutput);
var changeOutput = new BitcoinWitPubKeyAddress(request.ChangeOutput, expectedNetwork: Global.Config.Network);
- var inputs = new HashSet<OutPoint>();
- foreach (var input in request.Inputs)
+ if (request.Inputs.Count() > Global.Config.MaximumInputsPerAlices) throw new NotSupportedException("Too many inputs provided");
+ var inputs = new HashSet<TxOut>();
+ foreach (InputProofModel input in request.Inputs)
{
- OutPoint op = new OutPoint();
+ var op = new OutPoint();
op.FromHex(input.Input);
- inputs.Add(op);
+ var txOutResponse = await Global.RpcClient.SendCommandAsync(RPCOperations.gettxout, op.Hash.ToString(), op.N, true);
+ // Check if inputs are unspent
+ if (txOutResponse.Result == null)
+ {
+ throw new ArgumentException("Provided input is not unspent");
+ }
+ if(txOutResponse.Result.Value<int>("confirmations") <= 0)
+ {
+ throw new ArgumentException("Provided input is not confirmed");
}
-
- // Check format (parse everyting))
// Check if inputs are native segwit
+ if (txOutResponse.Result["scriptPubKey"].Value<string>("type") != "witness_v0_keyhash")
+ {
+ throw new ArgumentException("Provided input is not witness_v0_keyhash");
+ }
+ var value = txOutResponse.Result.Value<decimal>("value");
+ var scriptPubKey = new Script(txOutResponse.Result["scriptPubKey"].Value<string>("asm"));
+ var txout = new TxOut(new Money(value, MoneyUnit.BTC), scriptPubKey);
+ inputs.Add(txout);
+ }
+
// Check if proofs are valid
// Check if inputs have enough coins
- // Check if inputs are unspent
// Check if inputs are confirmed or part of previous CoinJoin
+ // only enable requests in specific phases
throw new NotImplementedException();
}

MODIFY
HiddenWallet.ChaumianTumbler/Models/StatusResponse.cs
HiddenWallet.ChaumianTumbler/Models/StatusResponse.cs
@@ -13,5 +13,6 @@ namespace HiddenWallet.ChaumianTumbler.Models
public string Denomination { get; set; }
public int AnonymitySet { get; set; }
public int TimeSpentInInputRegistrationInSeconds { get; set; }
+ public int MaximumInputsPerAlices { get; internal set; }
}
}

Add more checks