Progress fixing tests
MODIFY
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
@@ -106,7 +106,7 @@ namespace WalletWasabi.Backend.Controllers
public async Task<IActionResult> PostInputsAsync([FromBody, Required]InputsRequest request)
{
// Validate request.
- if (request.RoundId <= 0 || !ModelState.IsValid)
+ if (request.RoundId < 0 || !ModelState.IsValid)
{
return BadRequest("Invalid request.");
}
@@ -362,7 +362,7 @@ namespace WalletWasabi.Backend.Controllers
[ProducesResponseType(410)]
public async Task<IActionResult> PostConfirmationAsync([FromQuery, Required]string uniqueId, [FromQuery, Required]long roundId)
{
- if (roundId <= 0 || !ModelState.IsValid)
+ if (roundId < 0 || !ModelState.IsValid)
{
return BadRequest();
}
@@ -430,7 +430,7 @@ namespace WalletWasabi.Backend.Controllers
[ProducesResponseType(410)]
public IActionResult PostUnconfimation([FromQuery, Required]string uniqueId, [FromQuery, Required]long roundId)
{
- if (roundId <= 0 || !ModelState.IsValid)
+ if (roundId < 0 || !ModelState.IsValid)
{
return BadRequest();
}
@@ -579,7 +579,7 @@ namespace WalletWasabi.Backend.Controllers
[ProducesResponseType(410)]
public IActionResult GetCoinJoin([FromQuery, Required]string uniqueId, [FromQuery, Required]long roundId)
{
- if (roundId <= 0 || !ModelState.IsValid)
+ if (roundId < 0 || !ModelState.IsValid)
{
return BadRequest();
}
@@ -626,7 +626,7 @@ namespace WalletWasabi.Backend.Controllers
[ProducesResponseType(410)]
public async Task<IActionResult> PostSignaturesAsync([FromQuery, Required]string uniqueId, [FromQuery, Required]long roundId, [FromBody, Required]IDictionary<int, string> signatures)
{
- if (roundId <= 0
+ if (roundId < 0
|| !signatures.Any()
|| signatures.Any(x => x.Key < 0 || string.IsNullOrWhiteSpace(x.Value))
|| !ModelState.IsValid)

MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -1699,276 +1699,281 @@ namespace WalletWasabi.Tests
Logger.TurnOn();
}
- //[Fact]
- //public async Task CcjTestsAsync()
- //{
- // (string password, RPCClient rpc, Network network, CcjCoordinator coordinator, ServiceConfiguration serviceConfiguration) = await InitializeTestEnvironmentAsync(1);
+ [Fact]
+ public async Task CcjTestsAsync()
+ {
+ (string password, RPCClient rpc, Network network, CcjCoordinator coordinator, ServiceConfiguration serviceConfiguration) = await InitializeTestEnvironmentAsync(1);
- // Money denomination = Money.Coins(0.2m);
- // decimal coordinatorFeePercent = 0.2m;
- // int anonymitySet = 2;
- // int connectionConfirmationTimeout = 50;
- // var roundConfig = new CcjRoundConfig(denomination, 2, coordinatorFeePercent, anonymitySet, 100, connectionConfirmationTimeout, 50, 50, 2, 24, false, 11);
- // coordinator.UpdateRoundConfig(roundConfig);
- // coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
+ Money denomination = Money.Coins(0.2m);
+ decimal coordinatorFeePercent = 0.2m;
+ int anonymitySet = 2;
+ int connectionConfirmationTimeout = 50;
+ var roundConfig = new CcjRoundConfig(denomination, 2, coordinatorFeePercent, anonymitySet, 100, connectionConfirmationTimeout, 50, 50, 2, 24, false, 11);
+ coordinator.UpdateRoundConfig(roundConfig);
+ coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
- // Uri baseUri = new Uri(RegTestFixture.BackendEndPoint);
- // using (var torClient = new TorHttpClient(baseUri, SharedFixture.TorSocks5Endpoint))
- // using (var satoshiClient = new SatoshiClient(baseUri))
- // {
- // #region PostInputsGetStates
+ Uri baseUri = new Uri(RegTestFixture.BackendEndPoint);
+ using (var torClient = new TorHttpClient(baseUri, SharedFixture.TorSocks5Endpoint))
+ using (var satoshiClient = new SatoshiClient(baseUri))
+ {
+ #region PostInputsGetStates
+
+ // <-------------------------->
+ // POST INPUTS and GET STATES tests
+ // <-------------------------->
+
+ IEnumerable<CcjRunningRoundState> states = await satoshiClient.GetAllRoundStatesAsync();
+ Assert.Equal(2, states.Count());
+ foreach (CcjRunningRoundState rs in states)
+ {
+ // Never changes.
+ Assert.True(0 < rs.RoundId);
+ Assert.Equal(Money.Coins(0.00009648m), rs.FeePerInputs);
+ Assert.Equal(Money.Coins(0.00004752m), rs.FeePerOutputs);
+ Assert.Equal(7, rs.MaximumInputCountPerPeer);
+ // Changes per rounds.
+ Assert.Equal(denomination, rs.Denomination);
+ Assert.Equal(coordinatorFeePercent, rs.CoordinatorFeePercent);
+ Assert.Equal(anonymitySet, rs.RequiredPeerCount);
+ Assert.Equal(connectionConfirmationTimeout, rs.RegistrationTimeout);
+ // Changes per phases.
+ Assert.Equal(CcjRoundPhase.InputRegistration, rs.Phase);
+ Assert.Equal(0, rs.RegisteredPeerCount);
+ }
+
+ // Inputs request tests
+ var inputsRequest = new InputsRequest
+ {
+ BlindedOutputScripts = null,
+ ChangeOutputAddress = null,
+ Inputs = null,
+ };
- // // <-------------------------->
- // // POST INPUTS and GET STATES tests
- // // <-------------------------->
+ var round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
+ var roundId = round.RoundId;
+ var registeredAddresses = new BitcoinAddress[] { };
+ var schnorrPubKeys = round.MixingLevels.SchnorrPubKeys;
+ var requesters = new Requester[] { };
- // IEnumerable<CcjRunningRoundState> states = await satoshiClient.GetAllRoundStatesAsync();
- // Assert.Equal(2, states.Count());
- // foreach (CcjRunningRoundState rs in states)
- // {
- // // Never changes.
- // Assert.True(0 < rs.RoundId);
- // Assert.Equal(Money.Coins(0.00009648m), rs.FeePerInputs);
- // Assert.Equal(Money.Coins(0.00004752m), rs.FeePerOutputs);
- // Assert.Equal(7, rs.MaximumInputCountPerPeer);
- // // Changes per rounds.
- // Assert.Equal(denomination, rs.Denomination);
- // Assert.Equal(coordinatorFeePercent, rs.CoordinatorFeePercent);
- // Assert.Equal(anonymitySet, rs.RequiredPeerCount);
- // Assert.Equal(connectionConfirmationTimeout, rs.RegistrationTimeout);
- // // Changes per phases.
- // Assert.Equal(CcjRoundPhase.InputRegistration, rs.Phase);
- // Assert.Equal(0, rs.RegisteredPeerCount);
- // }
+ HttpRequestException httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nInvalid request.", httpRequestException.Message);
- // // Inputs request tests
- // var inputsRequest = new InputsRequest
- // {
- // BlindedOutputScripts = null,
- // ChangeOutputAddress = null,
- // Inputs = null,
- // };
-
- // HttpRequestException httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nInvalid request.", httpRequestException.Message);
-
- // byte[] dummySignature = new byte[65];
- // CcjRound round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
-
- // inputsRequest.BlindedOutputScripts = Enumerable.Range(0, round.MixingLevels.Count() + 1).Select(x => uint256.One);
- // inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(network);
- // inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nToo many blinded output was provided", httpRequestException.Message);
-
- // inputsRequest.BlindedOutputScripts = Enumerable.Range(0, round.MixingLevels.Count() - 2).Select(x => uint256.One);
- // inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(network);
- // inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nDuplicate blinded output found", httpRequestException.Message);
-
- // inputsRequest.BlindedOutputScripts = new[] { uint256.Zero };
- // inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(network);
- // inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is not unspent", httpRequestException.Message);
-
- // var addr = await rpc.GetNewAddressAsync();
- // var hash = await rpc.SendToAddressAsync(addr, Money.Coins(0.01m));
- // var tx = await rpc.GetRawTransactionAsync(hash);
- // var coin = tx.Outputs.GetCoins(addr.ScriptPubKey).Single();
+ byte[] dummySignature = new byte[65];
- // inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = dummySignature } };
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is neither confirmed, nor is from an unconfirmed coinjoin.", httpRequestException.Message);
+ inputsRequest.BlindedOutputScripts = Enumerable.Range(0, round.MixingLevels.Count() + 1).Select(x => uint256.One);
+ inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(network);
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nToo many blinded output was provided", httpRequestException.Message);
- // var blocks = await rpc.GenerateAsync(1);
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input must be witness_v0_keyhash.", httpRequestException.Message);
+ inputsRequest.BlindedOutputScripts = Enumerable.Range(0, round.MixingLevels.Count() - 2).Select(x => uint256.One);
+ inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(network);
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nDuplicate blinded output found", httpRequestException.Message);
- // var blockHash = blocks.Single();
- // var block = await rpc.GetBlockAsync(blockHash);
- // var coinbase = block.Transactions.First();
- // inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(coinbase.GetHash(), 0), Proof = dummySignature } };
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is immature.", httpRequestException.Message);
+ inputsRequest.BlindedOutputScripts = new[] { uint256.Zero };
+ inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(network);
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is not unspent", httpRequestException.Message);
- // var key = new Key();
- // var witnessAddress = key.PubKey.GetSegwitAddress(network);
- // hash = await rpc.SendToAddressAsync(witnessAddress, Money.Coins(0.01m));
- // await rpc.GenerateAsync(1);
- // tx = await rpc.GetRawTransactionAsync(hash);
- // coin = tx.Outputs.GetCoins(witnessAddress.ScriptPubKey).Single();
- // inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = dummySignature } };
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}", httpRequestException.Message);
+ var addr = await rpc.GetNewAddressAsync();
+ var hash = await rpc.SendToAddressAsync(addr, Money.Coins(0.01m));
+ var tx = await rpc.GetRawTransactionAsync(hash);
+ var coin = tx.Outputs.GetCoins(addr.ScriptPubKey).Single();
- // var proof = key.SignCompact(uint256.One);
- // inputsRequest.Inputs.First().Proof = proof;
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided proof is invalid.", httpRequestException.Message);
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = dummySignature } };
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is neither confirmed, nor is from an unconfirmed coinjoin.", httpRequestException.Message);
- // round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
- // var requester = new Requester();
- // uint256 msg = new uint256(Hashes.SHA256(network.Consensus.ConsensusFactory.CreateTransaction().ToBytes()));
- // uint256 blindedData = requester.BlindMessage(msg, round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey);
- // inputsRequest.BlindedOutputScripts = new[] { blindedData };
- // uint256 blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedData.ToBytes()));
+ var blocks = await rpc.GenerateAsync(1);
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input must be witness_v0_keyhash.", httpRequestException.Message);
- // proof = key.SignCompact(blindedOutputScriptsHash);
- // inputsRequest.Inputs.First().Proof = proof;
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nNot enough inputs are provided. Fee to pay:", httpRequestException.Message);
+ var blockHash = blocks.Single();
+ var block = await rpc.GetBlockAsync(blockHash);
+ var coinbase = block.Transactions.First();
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(coinbase.GetHash(), 0), Proof = dummySignature } };
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is immature.", httpRequestException.Message);
- // roundConfig.Denomination = Money.Coins(0.01m); // exactly the same as our output
- // coordinator.UpdateRoundConfig(roundConfig);
- // coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nNot enough inputs are provided. Fee to pay:", httpRequestException.Message);
+ var key = new Key();
+ var witnessAddress = key.PubKey.GetSegwitAddress(network);
+ hash = await rpc.SendToAddressAsync(witnessAddress, Money.Coins(0.01m));
+ await rpc.GenerateAsync(1);
+ tx = await rpc.GetRawTransactionAsync(hash);
+ coin = tx.Outputs.GetCoins(witnessAddress.ScriptPubKey).Single();
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = dummySignature } };
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}", httpRequestException.Message);
- // roundConfig.Denomination = Money.Coins(0.00999999m); // one satoshi less than our output
- // coordinator.UpdateRoundConfig(roundConfig);
- // coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nNot enough inputs are provided. Fee to pay:", httpRequestException.Message);
+ var proof = key.SignCompact(uint256.One);
+ inputsRequest.Inputs.First().Proof = proof;
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided proof is invalid.", httpRequestException.Message);
- // roundConfig.Denomination = Money.Coins(0.008m); // one satoshi less than our output
- // roundConfig.ConnectionConfirmationTimeout = 2;
- // coordinator.UpdateRoundConfig(roundConfig);
- // round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
- // requester = new Requester();
- // msg = network.Consensus.ConsensusFactory.CreateTransaction().GetHash();
- // blindedData = requester.BlindMessage(msg, round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey);
- // inputsRequest.BlindedOutputScripts = new[] { blindedData };
- // blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedData.ToBytes()));
- // proof = key.SignCompact(blindedOutputScriptsHash);
- // inputsRequest.Inputs.First().Proof = proof;
- // coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
- // using (var aliceClient = await AliceClient.CreateNewAsync(network, inputsRequest, baseUri))
- // {
- // // Test DelayedClientRoundRegistration logic.
- // ClientRoundRegistration first = null;
- // var second = new ClientRoundRegistration(aliceClient,
- // new[] { new SmartCoin(uint256.One, 1, Script.Empty, Money.Zero, new[] { new TxoRef(uint256.One, 1) }, Height.Unknown, true, 1) },
- // BitcoinAddress.Create("12Rty3c8j3QiZSwLVaBtch6XUMZaja3RC7", Network.Main));
- // first = second;
- // second = null;
- // Assert.NotNull(first);
- // Assert.Null(second);
+ round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
+ var requester = new Requester();
+ uint256 msg = new uint256(Hashes.SHA256(network.Consensus.ConsensusFactory.CreateTransaction().ToBytes()));
+ uint256 blindedData = requester.BlindMessage(msg, round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey);
+ inputsRequest.BlindedOutputScripts = new[] { blindedData };
+ uint256 blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedData.ToBytes()));
- // Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
- // Assert.True(aliceClient.RoundId > 0);
+ proof = key.SignCompact(blindedOutputScriptsHash);
+ inputsRequest.Inputs.First().Proof = proof;
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nNot enough inputs are provided. Fee to pay:", httpRequestException.Message);
- // CcjRunningRoundState roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
- // Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
- // Assert.Equal(1, roundState.RegisteredPeerCount);
+ roundConfig.Denomination = Money.Coins(0.01m); // exactly the same as our output
+ coordinator.UpdateRoundConfig(roundConfig);
+ coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nNot enough inputs are provided. Fee to pay:", httpRequestException.Message);
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nBlinded output has already been registered.", httpRequestException.Message);
+ roundConfig.Denomination = Money.Coins(0.00999999m); // one satoshi less than our output
+ coordinator.UpdateRoundConfig(roundConfig);
+ coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nNot enough inputs are provided. Fee to pay:", httpRequestException.Message);
- // roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
- // Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
- // Assert.Equal(1, roundState.RegisteredPeerCount);
+ roundConfig.Denomination = Money.Coins(0.008m); // one satoshi less than our output
+ roundConfig.ConnectionConfirmationTimeout = 2;
+ coordinator.UpdateRoundConfig(roundConfig);
+ round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
+ requester = new Requester();
+ msg = network.Consensus.ConsensusFactory.CreateTransaction().GetHash();
+ blindedData = requester.BlindMessage(msg, round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey);
+ inputsRequest.BlindedOutputScripts = new[] { blindedData };
+ blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedData.ToBytes()));
+ proof = key.SignCompact(blindedOutputScriptsHash);
+ inputsRequest.Inputs.First().Proof = proof;
+ coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
+ using (var aliceClient = await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri))
+ {
+ // Test DelayedClientRoundRegistration logic.
+ ClientRoundRegistration first = null;
+ var second = new ClientRoundRegistration(aliceClient,
+ new[] { new SmartCoin(uint256.One, 1, Script.Empty, Money.Zero, new[] { new TxoRef(uint256.One, 1) }, Height.Unknown, true, 1) },
+ BitcoinAddress.Create("12Rty3c8j3QiZSwLVaBtch6XUMZaja3RC7", Network.Main));
+ first = second;
+ second = null;
+ Assert.NotNull(first);
+ Assert.Null(second);
- // roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
- // Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
- // Assert.Equal(1, roundState.RegisteredPeerCount);
- // }
+ Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
+ Assert.True(aliceClient.RoundId > 0);
- // round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
- // requester = new Requester();
- // blindedData = requester.BlindScript(round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey.SignerPubKey, round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey.RpubKey, key.ScriptPubKey);
- // inputsRequest.BlindedOutputScripts = new[] { blindedData };
- // blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedData.ToBytes()));
- // proof = key.SignCompact(blindedOutputScriptsHash);
- // inputsRequest.Inputs.First().Proof = proof;
- // using (var aliceClient = await AliceClient.CreateNewAsync(network, inputsRequest, baseUri))
- // {
- // Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
- // Assert.True(aliceClient.RoundId > 0);
+ CcjRunningRoundState roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
+ Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
+ Assert.Equal(1, roundState.RegisteredPeerCount);
- // var roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
- // Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
- // Assert.Equal(1, roundState.RegisteredPeerCount);
- // }
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nBlinded output has already been registered.", httpRequestException.Message);
- // inputsRequest.BlindedOutputScripts = new[] { uint256.One };
- // blindedOutputScriptsHash = new uint256(Hashes.SHA256(uint256.One.ToBytes()));
- // proof = key.SignCompact(blindedOutputScriptsHash);
- // inputsRequest.Inputs.First().Proof = proof;
- // inputsRequest.Inputs = new List<InputProofModel> { inputsRequest.Inputs.First(), inputsRequest.Inputs.First() };
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nCannot register an input twice.", httpRequestException.Message);
+ roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
+ Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
+ Assert.Equal(1, roundState.RegisteredPeerCount);
- // var inputProofs = new List<InputProofModel>();
- // for (int j = 0; j < 8; j++)
- // {
- // key = new Key();
- // witnessAddress = key.PubKey.GetSegwitAddress(network);
- // hash = await rpc.SendToAddressAsync(witnessAddress, Money.Coins(0.01m));
- // await rpc.GenerateAsync(1);
- // tx = await rpc.GetRawTransactionAsync(hash);
- // coin = tx.Outputs.GetCoins(witnessAddress.ScriptPubKey).Single();
- // proof = key.SignCompact(blindedOutputScriptsHash);
- // inputProofs.Add(new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = proof });
- // }
- // await rpc.GenerateAsync(1);
+ roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
+ Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
+ Assert.Equal(1, roundState.RegisteredPeerCount);
+ }
- // inputsRequest.Inputs = inputProofs;
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nMaximum 7 inputs can be registered.", httpRequestException.Message);
- // inputProofs.RemoveLast();
- // inputsRequest.Inputs = inputProofs;
- // using (var aliceClient = await AliceClient.CreateNewAsync(network, inputsRequest, baseUri))
- // {
- // Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
- // Assert.True(aliceClient.RoundId > 0);
+ round = coordinator.GetCurrentInputRegisterableRoundOrDefault();
+ requester = new Requester();
+ blindedData = requester.BlindScript(round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey.SignerPubKey, round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey.RpubKey, key.ScriptPubKey);
+ inputsRequest.BlindedOutputScripts = new[] { blindedData };
+ blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedData.ToBytes()));
+ proof = key.SignCompact(blindedOutputScriptsHash);
+ inputsRequest.Inputs.First().Proof = proof;
+ using (var aliceClient = await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri))
+ {
+ Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
+ Assert.True(aliceClient.RoundId > 0);
+
+ var roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
+ Assert.Equal(CcjRoundPhase.InputRegistration, roundState.Phase);
+ Assert.Equal(1, roundState.RegisteredPeerCount);
+ }
+
+ inputsRequest.BlindedOutputScripts = new[] { uint256.One };
+ blindedOutputScriptsHash = new uint256(Hashes.SHA256(uint256.One.ToBytes()));
+ proof = key.SignCompact(blindedOutputScriptsHash);
+ inputsRequest.Inputs.First().Proof = proof;
+ inputsRequest.Inputs = new List<InputProofModel> { inputsRequest.Inputs.First(), inputsRequest.Inputs.First() };
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nCannot register an input twice.", httpRequestException.Message);
+
+ var inputProofs = new List<InputProofModel>();
+ for (int j = 0; j < 8; j++)
+ {
+ key = new Key();
+ witnessAddress = key.PubKey.GetSegwitAddress(network);
+ hash = await rpc.SendToAddressAsync(witnessAddress, Money.Coins(0.01m));
+ await rpc.GenerateAsync(1);
+ tx = await rpc.GetRawTransactionAsync(hash);
+ coin = tx.Outputs.GetCoins(witnessAddress.ScriptPubKey).Single();
+ proof = key.SignCompact(blindedOutputScriptsHash);
+ inputProofs.Add(new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = proof });
+ }
+ await rpc.GenerateAsync(1);
- // await Task.Delay(1000);
- // var roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
- // Assert.Equal(CcjRoundPhase.ConnectionConfirmation, roundState.Phase);
- // Assert.Equal(2, roundState.RegisteredPeerCount);
- // var inputRegistrableRoundState = await satoshiClient.GetRegistrableRoundStateAsync();
- // Assert.Equal(0, inputRegistrableRoundState.RegisteredPeerCount);
+ inputsRequest.Inputs = inputProofs;
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nMaximum 7 inputs can be registered.", httpRequestException.Message);
+ inputProofs.RemoveLast();
+ inputsRequest.Inputs = inputProofs;
+ using (var aliceClient = await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri))
+ {
+ Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
+ Assert.True(aliceClient.RoundId > 0);
- // roundConfig.ConnectionConfirmationTimeout = 1; // One second.
- // coordinator.UpdateRoundConfig(roundConfig);
- // coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
+ await Task.Delay(1000);
+ var roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
+ Assert.Equal(CcjRoundPhase.ConnectionConfirmation, roundState.Phase);
+ Assert.Equal(2, roundState.RegisteredPeerCount);
+ var inputRegistrableRoundState = await satoshiClient.GetRegistrableRoundStateAsync();
+ Assert.Equal(0, inputRegistrableRoundState.RegisteredPeerCount);
- // roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
- // Assert.Equal(CcjRoundPhase.ConnectionConfirmation, roundState.Phase);
- // Assert.Equal(2, roundState.RegisteredPeerCount);
- // }
+ roundConfig.ConnectionConfirmationTimeout = 1; // One second.
+ coordinator.UpdateRoundConfig(roundConfig);
+ coordinator.AbortAllRoundsInInputRegistration(nameof(RegTests), "");
+
+ roundState = await satoshiClient.GetRoundStateAsync(aliceClient.RoundId);
+ Assert.Equal(CcjRoundPhase.ConnectionConfirmation, roundState.Phase);
+ Assert.Equal(2, roundState.RegisteredPeerCount);
+ }
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nInput is already registered in another round.", httpRequestException.Message);
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nInput is already registered in another round.", httpRequestException.Message);
- // // Wait until input registration times out.
- // await Task.Delay(3000);
- // httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(network, inputsRequest, baseUri));
- // Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nInput is banned from participation for", httpRequestException.Message);
+ // Wait until input registration times out.
+ await Task.Delay(3000);
+ httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri));
+ Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nInput is banned from participation for", httpRequestException.Message);
- // var spendingTx = network.Consensus.ConsensusFactory.CreateTransaction();
- // var bannedCoin = inputsRequest.Inputs.First().Input;
- // var utxos = coordinator.UtxoReferee;
- // Assert.NotNull(await utxos.TryGetBannedAsync(bannedCoin.ToOutPoint(), false));
- // spendingTx.Inputs.Add(new TxIn(bannedCoin.ToOutPoint()));
- // spendingTx.Outputs.Add(new TxOut(Money.Coins(1), new Key().PubKey.GetSegwitAddress(network)));
- // var fakeBlockWithSpendingBannedCoins = network.Consensus.ConsensusFactory.CreateBlock();
- // fakeBlockWithSpendingBannedCoins.Transactions.Add(spendingTx);
+ var spendingTx = network.Consensus.ConsensusFactory.CreateTransaction();
+ var bannedCoin = inputsRequest.Inputs.First().Input;
+ var utxos = coordinator.UtxoReferee;
+ Assert.NotNull(await utxos.TryGetBannedAsync(bannedCoin.ToOutPoint(), false));
+ spendingTx.Inputs.Add(new TxIn(bannedCoin.ToOutPoint()));
+ spendingTx.Outputs.Add(new TxOut(Money.Coins(1), new Key().PubKey.GetSegwitAddress(network)));
+ var fakeBlockWithSpendingBannedCoins = network.Consensus.ConsensusFactory.CreateBlock();
+ fakeBlockWithSpendingBannedCoins.Transactions.Add(spendingTx);
- // await coordinator.ProcessBlockAsync(fakeBlockWithSpendingBannedCoins);
+ await coordinator.ProcessBlockAsync(fakeBlockWithSpendingBannedCoins);
- // Assert.NotNull(await utxos.TryGetBannedAsync(new OutPoint(spendingTx.GetHash(), 0), false));
- // Assert.Null(await utxos.TryGetBannedAsync(bannedCoin.ToOutPoint(), false));
+ Assert.NotNull(await utxos.TryGetBannedAsync(new OutPoint(spendingTx.GetHash(), 0), false));
+ Assert.Null(await utxos.TryGetBannedAsync(bannedCoin.ToOutPoint(), false));
- // states = await satoshiClient.GetAllRoundStatesAsync();
- // foreach (var rs in states.Where(x => x.Phase == CcjRoundPhase.InputRegistration))
- // {
- // Assert.Equal(0, rs.RegisteredPeerCount);
- // }
+ states = await satoshiClient.GetAllRoundStatesAsync();
+ foreach (var rs in states.Where(x => x.Phase == CcjRoundPhase.InputRegistration))
+ {
+ Assert.Equal(0, rs.RegisteredPeerCount);
+ }
- // #endregion PostInputsGetStates
+ #endregion PostInputsGetStates
//#region PostConfirmationPostUnconfirmation
@@ -2192,8 +2197,8 @@ namespace WalletWasabi.Tests
// #endregion PostSignatures
//}
- // }
- //}
+ }
+ }
//[Fact]
//public async Task CcjEqualInputTestsAsync()

MODIFY
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/AliceClient.cs
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/AliceClient.cs
@@ -62,6 +62,18 @@ namespace WalletWasabi.WebClients.Wasabi.ChaumianCoinJoin
AliceClient client = new AliceClient(roundId, registeredAddresses, schnorrPubKeys, requesters, network, baseUri, torSocks5EndPoint);
try
{
+ // Correct it if forgot to set.
+ if (request.RoundId != roundId)
+ {
+ if (request.RoundId == 0)
+ {
+ request.RoundId = roundId;
+ }
+ else
+ {
+ throw new NotSupportedException($"InputRequest roundId doesn't match to the provided roundId: {request.RoundId} != {roundId}.");
+ }
+ }
using (HttpResponseMessage response = await client.TorClient.SendAsync(HttpMethod.Post, $"/api/v{Helpers.Constants.BackendMajorVersion}/btc/chaumiancoinjoin/inputs/", request.ToHttpStringContent()))
{
if (response.StatusCode != HttpStatusCode.OK)

MODIFY
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/BobClient.cs
WalletWasabi/WebClients/Wasabi/ChaumianCoinJoin/BobClient.cs
@@ -20,7 +20,7 @@ namespace WalletWasabi.WebClients.Wasabi.ChaumianCoinJoin
/// <returns>If the phase is still in OutputRegistration.</returns>
public async Task<bool> PostOutputAsync(long roundId, BitcoinAddress activeOutputAddress, UnblindedSignature unblindedSignature, int level)
{
- Guard.MinimumAndNotNull(nameof(roundId), roundId, 1);
+ Guard.MinimumAndNotNull(nameof(roundId), roundId, 0);
Guard.NotNull(nameof(activeOutputAddress), activeOutputAddress);
Guard.NotNull(nameof(unblindedSignature), unblindedSignature);
Guard.MinimumAndNotNull(nameof(level), level, 0);

Progress fixing tests