[WabiSabi Protocol] Implement Moving to OutputRegistration
MODIFY
WalletWasabi.Tests/Helpers/WabiSabiFactory.cs
WalletWasabi.Tests/Helpers/WabiSabiFactory.cs
@@ -11,6 +11,7 @@ using WalletWasabi.Crypto.Randomness;
using WalletWasabi.Crypto.ZeroKnowledge;
using WalletWasabi.Tests.UnitTests;
using WalletWasabi.WabiSabi.Backend;
+using WalletWasabi.WabiSabi.Backend.Banning;
using WalletWasabi.WabiSabi.Backend.Models;
using WalletWasabi.WabiSabi.Backend.Rounds;
using WalletWasabi.WabiSabi.Crypto;
@@ -76,7 +77,7 @@ namespace WalletWasabi.Tests.Helpers
Blocks = target,
FeeRate = new FeeRate(10m)
});
- Arena arena = new(TimeSpan.FromSeconds(21), rounds.FirstOrDefault()?.Network ?? Network.Main, cfg ?? new WabiSabiConfig(), mockRpc);
+ Arena arena = new(TimeSpan.FromSeconds(21), rounds.FirstOrDefault()?.Network ?? Network.Main, cfg ?? new WabiSabiConfig(), mockRpc, new Prison());
foreach (var round in rounds)
{
arena.Rounds.Add(round.Id, round);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/AliceTimeoutTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/AliceTimeoutTests.cs
@@ -54,7 +54,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
// even though the deadline is reached.
WabiSabiConfig cfg = new();
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.ConnectionConfirmation;
+ round.SetPhase(Phase.ConnectionConfirmation);
var alice = WabiSabiFactory.CreateAlice();
round.Alices.Add(alice);
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/ConfirmConnectionTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/ConfirmConnectionTests.cs
@@ -39,6 +39,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
Assert.Null(resp.RealWeightCredentials);
Assert.NotEqual(preDeadline, alice.Deadline);
Assert.True(minAliceDeadline <= alice.Deadline);
+ Assert.False(alice.ConfirmedConnetion);
await arena.StopAsync(CancellationToken.None);
}
@@ -48,7 +49,8 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new();
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.ConnectionConfirmation;
+
+ round.SetPhase(Phase.ConnectionConfirmation);
var alice = WabiSabiFactory.CreateAlice();
var preDeadline = alice.Deadline;
round.Alices.Add(alice);
@@ -63,6 +65,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
Assert.NotNull(resp.RealAmountCredentials);
Assert.NotNull(resp.RealWeightCredentials);
Assert.Equal(preDeadline, alice.Deadline);
+ Assert.True(alice.ConfirmedConnetion);
await arena.StopAsync(CancellationToken.None);
}
@@ -94,13 +97,14 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
if (phase != Phase.InputRegistration && phase != Phase.ConnectionConfirmation)
{
- round.Phase = phase;
+ round.SetPhase(phase);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.ConfirmConnectionAsync(req));
Assert.Equal(WabiSabiProtocolErrorCode.WrongPhase, ex.ErrorCode);
}
}
Assert.Equal(preDeadline, alice.Deadline);
+ Assert.False(alice.ConfirmedConnetion);
await arena.StopAsync(CancellationToken.None);
}
@@ -125,7 +129,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new();
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.ConnectionConfirmation;
+ round.SetPhase(Phase.ConnectionConfirmation);
var alice = WabiSabiFactory.CreateAlice();
round.Alices.Add(alice);
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
@@ -141,6 +145,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.ConfirmConnectionAsync(req));
Assert.Equal(WabiSabiProtocolErrorCode.IncorrectRequestedWeightCredentials, ex.ErrorCode);
+ Assert.False(alice.ConfirmedConnetion);
await arena.StopAsync(CancellationToken.None);
}
@@ -150,7 +155,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new();
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.ConnectionConfirmation;
+ round.SetPhase(Phase.ConnectionConfirmation);
var alice = WabiSabiFactory.CreateAlice();
round.Alices.Add(alice);
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
@@ -166,6 +171,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.ConfirmConnectionAsync(req));
Assert.Equal(WabiSabiProtocolErrorCode.IncorrectRequestedAmountCredentials, ex.ErrorCode);
+ Assert.False(alice.ConfirmedConnetion);
await arena.StopAsync(CancellationToken.None);
}

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RegisterInputTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RegisterInputTests.cs
@@ -162,7 +162,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
if (phase != Phase.InputRegistration)
{
- round.Phase = phase;
+ round.SetPhase(phase);
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.RegisterInputAsync(req));
Assert.Equal(WabiSabiProtocolErrorCode.WrongPhase, ex.ErrorCode);
}
@@ -588,7 +588,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
// Make sure an Alice have already been registered with the same input.
var anotherAlice = WabiSabiFactory.CreateAlice(req.InputRoundSignaturePairs);
round.Alices.Add(anotherAlice);
- round.Phase = Phase.ConnectionConfirmation;
+ round.SetPhase(Phase.ConnectionConfirmation);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, rpc);
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.RegisterInputAsync(req));
@@ -620,7 +620,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
// Make sure an Alice have already been registered with the same input.
var preAlice = WabiSabiFactory.CreateAlice(req.InputRoundSignaturePairs);
anotherRound.Alices.Add(preAlice);
- anotherRound.Phase = Phase.ConnectionConfirmation;
+ anotherRound.SetPhase(Phase.ConnectionConfirmation);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, rpc);
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.RegisterInputAsync(req));

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RegisterOutputTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RegisterOutputTests.cs
@@ -23,7 +23,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new();
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.OutputRegistration;
+ round.SetPhase(Phase.OutputRegistration);
round.Alices.Add(WabiSabiFactory.CreateAlice());
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
@@ -56,7 +56,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new();
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.OutputRegistration;
+ round.SetPhase(Phase.OutputRegistration);
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
using Key key = new();
@@ -73,7 +73,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new() { MinRegistrableAmount = Money.Coins(2) };
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.OutputRegistration;
+ round.SetPhase(Phase.OutputRegistration);
round.Alices.Add(WabiSabiFactory.CreateAlice(value: Money.Coins(1)));
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
@@ -91,7 +91,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new() { MaxRegistrableAmount = Money.Coins(1.999m) };
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.OutputRegistration;
+ round.SetPhase(Phase.OutputRegistration);
round.Alices.Add(WabiSabiFactory.CreateAlice(value: Money.Coins(2)));
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
@@ -109,7 +109,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
WabiSabiConfig cfg = new();
var round = WabiSabiFactory.CreateRound(cfg);
- round.Phase = Phase.OutputRegistration;
+ round.SetPhase(Phase.OutputRegistration);
round.Alices.Add(WabiSabiFactory.CreateAlice());
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
@@ -136,7 +136,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
if (phase != Phase.OutputRegistration)
{
var req = WabiSabiFactory.CreateOutputRegistrationRequest(round);
- round.Phase = phase;
+ round.SetPhase(phase);
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.RegisterOutputAsync(req));
Assert.Equal(WabiSabiProtocolErrorCode.WrongPhase, ex.ErrorCode);
}

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RemoveInputTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RemoveInputTests.cs
@@ -64,7 +64,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
if (phase != Phase.InputRegistration)
{
- round.Phase = phase;
+ round.SetPhase(phase);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.RemoveInputAsync(req));
Assert.Equal(WabiSabiProtocolErrorCode.WrongPhase, ex.ErrorCode);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RoundCreationTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/RoundCreationTests.cs
@@ -7,6 +7,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.WabiSabi.Backend;
+using WalletWasabi.WabiSabi.Backend.Banning;
using WalletWasabi.WabiSabi.Backend.Rounds;
using Xunit;
@@ -26,7 +27,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
FeeRate = new FeeRate(10m)
});
- using Arena arena = new Arena(TimeSpan.FromSeconds(1), Network.Main, cfg, mockRpc);
+ using Arena arena = new Arena(TimeSpan.FromSeconds(1), Network.Main, cfg, mockRpc, new Prison());
Assert.Empty(arena.Rounds);
await arena.StartAsync(CancellationToken.None).ConfigureAwait(false);
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21)).ConfigureAwait(false);
@@ -47,13 +48,13 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
FeeRate = new FeeRate(10m)
});
- using Arena arena = new Arena(TimeSpan.FromSeconds(1), Network.Main, cfg, mockRpc);
+ using Arena arena = new Arena(TimeSpan.FromSeconds(1), Network.Main, cfg, mockRpc, new Prison());
Assert.Empty(arena.Rounds);
await arena.StartAsync(CancellationToken.None).ConfigureAwait(false);
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21)).ConfigureAwait(false);
- var round = Assert.Single(arena.Rounds);
+ var round = Assert.Single(arena.Rounds).Value;
- round.Value.Phase = Phase.ConnectionConfirmation;
+ round.SetPhase(Phase.ConnectionConfirmation);
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21)).ConfigureAwait(false);
Assert.Equal(2, arena.Rounds.Count);
@@ -72,14 +73,14 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
FeeRate = new FeeRate(10m)
});
- using Arena arena = new Arena(TimeSpan.FromSeconds(1), Network.Main, cfg, mockRpc);
+ using Arena arena = new Arena(TimeSpan.FromSeconds(1), Network.Main, cfg, mockRpc, new Prison());
Assert.Empty(arena.Rounds);
await arena.StartAsync(CancellationToken.None).ConfigureAwait(false);
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21)).ConfigureAwait(false);
- var round = Assert.Single(arena.Rounds);
+ var round = Assert.Single(arena.Rounds).Value;
- round.Value.Phase = Phase.ConnectionConfirmation;
- var blame = new Round(round.Value);
+ round.SetPhase(Phase.ConnectionConfirmation);
+ var blame = new Round(round);
Assert.Equal(Phase.InputRegistration, blame.Phase);
arena.Rounds.Add(blame.Id, blame);
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21)).ConfigureAwait(false);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/SignTransactionTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/SignTransactionTests.cs
@@ -28,7 +28,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
round.Alices.Add(alice);
var coinjoin = round.Coinjoin;
coinjoin.Inputs.Add(alice.Coins.First().Outpoint);
- round.Phase = Phase.TransactionSigning;
+ round.SetPhase(Phase.TransactionSigning);
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
var signedCoinJoin = coinjoin.Clone();
@@ -64,7 +64,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
{
if (phase != Phase.TransactionSigning)
{
- round.Phase = phase;
+ round.SetPhase(phase);
await using PostRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.SignTransactionAsync(req));
Assert.Equal(WabiSabiProtocolErrorCode.WrongPhase, ex.ErrorCode);
@@ -87,7 +87,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend
var coinjoin = round.Coinjoin;
coinjoin.Inputs.Add(alice1.Coins.First().Outpoint);
coinjoin.Inputs.Add(alice2.Coins.First().Outpoint);
- round.Phase = Phase.TransactionSigning;
+ round.SetPhase(Phase.TransactionSigning);
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, round);
// Submit the signature for the second alice to the first alice's input.

MODIFY
WalletWasabi/WabiSabi/Backend/Banning/Prison.cs
WalletWasabi/WabiSabi/Backend/Banning/Prison.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using WalletWasabi.WabiSabi.Backend.Models;
namespace WalletWasabi.WabiSabi.Backend.Banning
{
@@ -36,6 +37,14 @@ namespace WalletWasabi.WabiSabi.Backend.Banning
}
}
+ public void Note(Alice alice, Guid lastDisruptedRoundId)
+ {
+ foreach (var input in alice.Coins.Select(x => x.Outpoint))
+ {
+ Punish(input, Punishment.Noted, lastDisruptedRoundId);
+ }
+ }
+
public void Punish(OutPoint utxo, Punishment punishment, Guid lastDisruptedRoundId)
=> Punish(new Inmate(utxo, punishment, DateTimeOffset.UtcNow, lastDisruptedRoundId));

MODIFY
WalletWasabi/WabiSabi/Backend/Models/Alice.cs
WalletWasabi/WabiSabi/Backend/Models/Alice.cs
@@ -23,6 +23,8 @@ namespace WalletWasabi.WabiSabi.Backend.Models
public long TotalInputWeight => TotalInputVsize * 4;
public int TotalInputVsize => Coins.Sum(x => x.ScriptPubKey.EstimateInputVsize());
+ public bool ConfirmedConnetion { get; set; } = false;
+
public long CalculateRemainingWeightCredentials(uint maxRegistrableWeight) => maxRegistrableWeight - TotalInputWeight;
public Money CalculateRemainingAmountCredentials(FeeRate feeRate) => TotalInputAmount - feeRate.GetFee(TotalInputVsize);

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
@@ -12,6 +12,7 @@ using WalletWasabi.Bases;
using WalletWasabi.BitcoinCore.Rpc;
using WalletWasabi.Crypto.Randomness;
using WalletWasabi.Logging;
+using WalletWasabi.WabiSabi.Backend.Banning;
using WalletWasabi.WabiSabi.Backend.Models;
using WalletWasabi.WabiSabi.Backend.PostRequests;
using WalletWasabi.WabiSabi.Crypto.CredentialRequesting;
@@ -21,11 +22,12 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
{
public class Arena : PeriodicRunner
{
- public Arena(TimeSpan period, Network network, WabiSabiConfig config, IRPCClient rpc) : base(period)
+ public Arena(TimeSpan period, Network network, WabiSabiConfig config, IRPCClient rpc, Prison prison) : base(period)
{
Network = network;
Config = config;
Rpc = rpc;
+ Prison = prison;
Random = new SecureRandom();
}
@@ -34,6 +36,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
public Network Network { get; }
public WabiSabiConfig Config { get; }
public IRPCClient Rpc { get; }
+ public Prison Prison { get; }
public SecureRandom Random { get; }
protected override async Task ActionAsync(CancellationToken cancel)
@@ -43,6 +46,8 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
// Remove timed out alices.
TimeoutAlices();
+ StepConnectionConfirmationPhase();
+
StepInputRegistrationPhase();
// Ensure there's at least one non-blame round in input registration.
@@ -62,7 +67,36 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
}
else
{
- round.Phase = Phase.ConnectionConfirmation;
+ round.SetPhase(Phase.ConnectionConfirmation);
+ }
+ }
+ }
+
+ private void StepConnectionConfirmationPhase()
+ {
+ foreach (var round in Rounds.Values.Where(x => x.Phase == Phase.ConnectionConfirmation))
+ {
+ if (round.Alices.All(x => x.ConfirmedConnetion))
+ {
+ round.SetPhase(Phase.OutputRegistration);
+ }
+ else if (round.ConnectionConfirmationStart + Config.ConnectionConfirmationTimeout < DateTimeOffset.UtcNow)
+ {
+ var alicesDidntConfirm = round.Alices.Where(x => !x.ConfirmedConnetion).ToArray();
+ foreach (var alice in alicesDidntConfirm)
+ {
+ Prison.Note(alice, round.Id);
+ }
+ round.RemoveAlices(x => alicesDidntConfirm.Contains(x));
+
+ if (round.InputCount < Config.MinInputCountByRound)
+ {
+ Rounds.Remove(round.Id);
+ }
+ else
+ {
+ round.SetPhase(Phase.OutputRegistration);
+ }
}
}
}
@@ -164,6 +198,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
{
var amountRealCredentialResponse = round.AmountCredentialIssuer.HandleRequest(realAmountCredentialRequests);
var weightRealCredentialResponse = round.WeightCredentialIssuer.HandleRequest(realWeightCredentialRequests);
+ alice.ConfirmedConnetion = true;
return new(
amountZeroCredentialResponse,

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Round.cs
WalletWasabi/WabiSabi/Backend/Rounds/Round.cs
@@ -30,8 +30,6 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
Coinjoin = Transaction.Create(Network);
- CreationTime = DateTimeOffset.UtcNow;
-
Hash = new(HashHelpers.GenerateSha256Hash($"{Id}{MaxInputCountByAlice}{MinRegistrableAmount}{MaxRegistrableAmount}{RegistrableWeightCredentials}{AmountCredentialIssuerParameters}{WeightCredentialIssuerParameters}{FeeRate.SatoshiPerByte}"));
}
@@ -61,7 +59,6 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
public CredentialIssuerParameters AmountCredentialIssuerParameters { get; }
public CredentialIssuerParameters WeightCredentialIssuerParameters { get; }
public Guid Id { get; } = Guid.NewGuid();
- public Phase Phase { get; set; } = Phase.InputRegistration;
public List<Alice> Alices { get; } = new();
public int InputCount => Alices.Sum(x => x.Coins.Count());
public List<Bob> Bobs { get; } = new();
@@ -70,8 +67,30 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
public ISet<OutPoint> BlameWhitelist { get; } = new HashSet<OutPoint>();
public byte[] UnsignedTxSecret { get; }
public Transaction Coinjoin { get; }
- public DateTimeOffset CreationTime { get; }
private RoundParameters RoundParameters { get; }
+ public Phase Phase { get; private set; } = Phase.InputRegistration;
+ public DateTimeOffset InputRegistrationStart { get; } = DateTimeOffset.UtcNow;
+ public DateTimeOffset ConnectionConfirmationStart { get; private set; }
+ public DateTimeOffset OutputRegistrationStart { get; private set; }
+ public DateTimeOffset TransactionSigningStart { get; private set; }
+
+ public void SetPhase(Phase phase)
+ {
+ Phase = phase;
+
+ if (phase == Phase.ConnectionConfirmation)
+ {
+ ConnectionConfirmationStart = DateTimeOffset.UtcNow;
+ }
+ else if (phase == Phase.OutputRegistration)
+ {
+ OutputRegistrationStart = DateTimeOffset.UtcNow;
+ }
+ else if (phase == Phase.TransactionSigning)
+ {
+ TransactionSigningStart = DateTimeOffset.UtcNow;
+ }
+ }
public int RemoveAlices(Predicate<Alice> match)
{
@@ -84,7 +103,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
public bool IsInputRegistrationEnded(uint maxInputCount, TimeSpan inputRegistrationTimeout)
{
- if (Phase != Phase.InputRegistration)
+ if (Phase > Phase.InputRegistration)
{
return true;
}
@@ -94,7 +113,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
return true;
}
- if (CreationTime + inputRegistrationTimeout < DateTimeOffset.UtcNow)
+ if (InputRegistrationStart + inputRegistrationTimeout < DateTimeOffset.UtcNow)
{
return true;
}

MODIFY
WalletWasabi/WabiSabi/WabiSabiCoordinator.cs
WalletWasabi/WabiSabi/WabiSabiCoordinator.cs
@@ -26,7 +26,7 @@ namespace WalletWasabi.WabiSabi
Warden = new(parameters.UtxoWardenPeriod, parameters.PrisonFilePath, Config);
ConfigWatcher = new(parameters.ConfigChangeMonitoringPeriod, Config, () => Logger.LogInfo("WabiSabi configuration has changed."));
- Arena = new(parameters.RoundProgressSteppingPeriod, rpc.Network, Config, rpc);
+ Arena = new(parameters.RoundProgressSteppingPeriod, rpc.Network, Config, rpc, Prison);
Postman = new(Config, Prison, Arena, Rpc);
}

[WabiSabi Protocol] Implement Moving to OutputRegistration