Make AliceId secret again (but nullable for now)
MODIFY
WalletWasabi.Tests/Helpers/WabiSabiFactory.cs
WalletWasabi.Tests/Helpers/WabiSabiFactory.cs
@@ -111,7 +111,7 @@ namespace WalletWasabi.Tests.Helpers
}
public static Alice CreateAlice(Coin coin, OwnershipProof ownershipProof, Round round)
- => new(coin, ownershipProof, round) { Deadline = DateTimeOffset.UtcNow + TimeSpan.FromHours(1) };
+ => new(coin, ownershipProof, round, Guid.NewGuid()) { Deadline = DateTimeOffset.UtcNow + TimeSpan.FromHours(1) };
public static Alice CreateAlice(Key key, Money amount, Round round)
=> CreateAlice(CreateCoin(key, amount), CreateOwnershipProof(key), round);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PostRequests/RegisterInputSuccessTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PostRequests/RegisterInputSuccessTests.cs
@@ -13,7 +13,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend.PostRequests
{
public class RegisterInputSuccessTests
{
- private static void AssertSingleAliceSuccessfullyRegistered(Round round, DateTimeOffset minAliceDeadline, ArenaResponse<uint256> resp)
+ private static void AssertSingleAliceSuccessfullyRegistered(Round round, DateTimeOffset minAliceDeadline, ArenaResponse<Guid> resp)
{
var alice = Assert.Single(round.Alices);
Assert.NotNull(resp);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PostRequests/RemoveInputTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Backend/PostRequests/RemoveInputTests.cs
@@ -33,7 +33,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend.PostRequests
await using ArenaRequestHandler handler = new(cfg, new Prison(), arena, new MockRpcClient());
// There's no such alice yet, so success.
- var req = new InputsRemovalRequest(round.Id, BitcoinFactory.CreateUint256());
+ var req = new InputsRemovalRequest(round.Id, Guid.NewGuid());
await handler.RemoveInputAsync(req, CancellationToken.None);
// There was the alice we want to remove so success.
@@ -53,7 +53,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend.PostRequests
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync();
await using ArenaRequestHandler handler = new(new WabiSabiConfig(), new Prison(), arena, new MockRpcClient());
- var req = new InputsRemovalRequest(uint256.Zero, BitcoinFactory.CreateUint256());
+ var req = new InputsRemovalRequest(uint256.Zero, Guid.NewGuid());
var ex = await Assert.ThrowsAsync<WabiSabiProtocolException>(async () => await handler.RemoveInputAsync(req, CancellationToken.None));
Assert.Equal(WabiSabiProtocolErrorCode.RoundNotFound, ex.ErrorCode);
@@ -68,7 +68,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Backend.PostRequests
await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));
var round = arena.Rounds.First();
- var req = new InputsRemovalRequest(round.Id, BitcoinFactory.CreateUint256());
+ var req = new InputsRemovalRequest(round.Id, Guid.NewGuid());
foreach (Phase phase in Enum.GetValues(typeof(Phase)))
{
if (phase != Phase.InputRegistration)

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Client/ArenaClientTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Client/ArenaClientTests.cs
@@ -171,7 +171,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Client
round.SetPhase(Phase.ConnectionConfirmation);
var fundingTx = BitcoinFactory.CreateSmartTransaction(ownOutputCount: 1);
var coin = fundingTx.WalletOutputs.First().Coin;
- var alice = new Alice(coin, new OwnershipProof(), round);
+ var alice = new Alice(coin, new OwnershipProof(), round, Guid.NewGuid());
round.Alices.Add(alice);
using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(config, round);

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Integration/WabiSabiHttpApiIntegrationTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Integration/WabiSabiHttpApiIntegrationTests.cs
@@ -343,7 +343,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Integration
var response = await apiClient.RegisterInputAsync(round.Id, coinToRegister.Outpoint, signingKey, CancellationToken.None);
- Assert.NotEqual(uint256.Zero, response.Value);
+ Assert.NotEqual(Guid.Empty, response.Value);
}
[Fact]
@@ -374,9 +374,9 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Integration
RoundState[] rounds = await apiClient.GetStatusAsync(CancellationToken.None);
RoundState round = rounds.First(x => x.CoinjoinState is ConstructionState);
- ArenaResponse<uint256> response = await apiClient.RegisterInputAsync(round.Id, coinToRegister.Outpoint, signingKey, CancellationToken.None);
+ ArenaResponse<Guid> response = await apiClient.RegisterInputAsync(round.Id, coinToRegister.Outpoint, signingKey, CancellationToken.None);
- Assert.NotEqual(uint256.Zero, response.Value);
+ Assert.NotEqual(Guid.Empty, response.Value);
}
private class StuttererHttpClient : HttpClientWrapper

MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Models/SerializationTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Models/SerializationTests.cs
@@ -41,7 +41,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Models
public void InputRegistrationResponseMessageSerialization()
{
var message = new InputRegistrationResponse(
- BitcoinFactory.CreateUint256(),
+ Guid.NewGuid(),
CreateCredentialsResponse(),
CreateCredentialsResponse());
@@ -53,7 +53,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Models
{
var message = new ConnectionConfirmationRequest(
BitcoinFactory.CreateUint256(),
- BitcoinFactory.CreateUint256(),
+ Guid.NewGuid(),
CreateZeroCredentialsRequest(),
CreateRealCredentialsRequest(),
CreateZeroCredentialsRequest(),
@@ -116,7 +116,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Models
{
var message = new InputsRemovalRequest(
BitcoinFactory.CreateUint256(),
- BitcoinFactory.CreateUint256());
+ Guid.NewGuid());
AssertSerialization(message);
}

MODIFY
WalletWasabi/WabiSabi/Backend/Models/Alice.cs
WalletWasabi/WabiSabi/Backend/Models/Alice.cs
@@ -8,17 +8,17 @@ namespace WalletWasabi.WabiSabi.Backend.Models
{
public class Alice
{
- public Alice(Coin coin, OwnershipProof ownershipProof, Round round)
+ public Alice(Coin coin, OwnershipProof ownershipProof, Round round, Guid id)
{
// TODO init syntax?
Round = round;
Coin = coin;
OwnershipProof = ownershipProof;
- Id = CalculateHash();
+ Id = id;
}
public Round Round { get; }
- public uint256 Id { get; }
+ public Guid Id { get; }
public DateTimeOffset Deadline { get; set; } = DateTimeOffset.UtcNow;
public Coin Coin { get; }
public OwnershipProof OwnershipProof { get; }
@@ -37,14 +37,5 @@ namespace WalletWasabi.WabiSabi.Backend.Models
// Have alice timeouts a bit sooner than the timeout of connection confirmation phase.
Deadline = DateTimeOffset.UtcNow + (connectionConfirmationTimeout * 0.9);
}
-
- private uint256 CalculateHash() => CalculateHash(Coin, OwnershipProof);
-
- public static uint256 CalculateHash(Coin coin, OwnershipProof ownershipProof)
- => StrobeHasher.Create(ProtocolConstants.AliceStrobeDomain)
- .Append(ProtocolConstants.AliceCoinTxOutStrobeLabel, coin.TxOut)
- .Append(ProtocolConstants.AliceCoinOutpointStrobeLabel, coin.Outpoint)
- .Append(ProtocolConstants.AliceOwnershipProofStrobeLabel, ownershipProof)
- .GetHash();
}
}

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
WalletWasabi/WabiSabi/Backend/Rounds/Arena.cs
@@ -346,7 +346,12 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.WrongOwnershipProof);
}
- var alice = new Alice(coin, request.OwnershipProof, round);
+ // Generate a new Guid with the secure random source, to be sure
+ // that it is not guessable (Guid.NewGuid() documentation does
+ // not say anything about GUID version or randomness source,
+ // only that the probability of duplicates is very low).
+ var id = new Guid(Random.GetBytes(16));
+ var alice = new Alice(coin, request.OwnershipProof, round, id);
if (alice.TotalInputAmount < round.MinRegistrableAmount)
{

MODIFY
WalletWasabi/WabiSabi/Client/AliceClient.cs
WalletWasabi/WabiSabi/Client/AliceClient.cs
@@ -17,7 +17,6 @@ namespace WalletWasabi.WabiSabi.Client
{
public AliceClient(RoundState roundState, ArenaClient arenaClient, Coin coin, BitcoinSecret bitcoinSecret)
{
- AliceId = CalculateHash(coin, bitcoinSecret, roundState.Id);
RoundId = roundState.Id;
ArenaClient = arenaClient;
Coin = coin;
@@ -29,7 +28,7 @@ namespace WalletWasabi.WabiSabi.Client
ConfirmationTimeout = roundState.ConnectionConfirmationTimeout / 2;
}
- public uint256 AliceId { get; }
+ public Guid? AliceId { get; private set; }
public uint256 RoundId { get; }
private ArenaClient ArenaClient { get; }
public Coin Coin { get; }
@@ -43,11 +42,8 @@ namespace WalletWasabi.WabiSabi.Client
public async Task RegisterAndConfirmInputAsync(RoundStateUpdater roundStatusUpdater, CancellationToken cancellationToken)
{
var response = await ArenaClient.RegisterInputAsync(RoundId, Coin.Outpoint, BitcoinSecret.PrivateKey, cancellationToken).ConfigureAwait(false);
- var remoteAliceId = response.Value;
- if (AliceId != remoteAliceId)
- {
- throw new InvalidOperationException($"Round ({RoundId}), Local Alice ({AliceId}) was computed as {remoteAliceId}");
- }
+ AliceId = response.Value;
+
IssuedAmountCredentials = response.IssuedAmountCredentials;
IssuedVsizeCredentials = response.IssuedVsizeCredentials;
Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Registered an input.");
@@ -93,7 +89,7 @@ namespace WalletWasabi.WabiSabi.Client
var response = await ArenaClient
.ConfirmConnectionAsync(
RoundId,
- AliceId,
+ (Guid)AliceId,
amountsToRequest,
vsizesToRequest,
IssuedAmountCredentials,
@@ -110,7 +106,7 @@ namespace WalletWasabi.WabiSabi.Client
public async Task RemoveInputAsync(CancellationToken cancellationToken)
{
- await ArenaClient.RemoveInputAsync(RoundId, AliceId, cancellationToken).ConfigureAwait(false);
+ await ArenaClient.RemoveInputAsync(RoundId, (Guid)AliceId, cancellationToken).ConfigureAwait(false);
Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Inputs removed.");
}
@@ -123,17 +119,8 @@ namespace WalletWasabi.WabiSabi.Client
public async Task ReadyToSignAsync(CancellationToken cancellationToken)
{
- await ArenaClient.ReadyToSignAsync(RoundId, AliceId, BitcoinSecret.PrivateKey, cancellationToken).ConfigureAwait(false);
+ await ArenaClient.ReadyToSignAsync(RoundId, (Guid)AliceId, BitcoinSecret.PrivateKey, cancellationToken).ConfigureAwait(false);
Logger.LogInfo($"Round ({RoundId}), Alice ({AliceId}): Ready to sign.");
}
-
- private static uint256 CalculateHash(Coin coin, BitcoinSecret bitcoinSecret, uint256 roundId)
- {
- var ownershipProof = OwnershipProof.GenerateCoinJoinInputProof(
- bitcoinSecret.PrivateKey,
- new CoinJoinInputCommitmentData("CoinJoinCoordinatorIdentifier", roundId));
-
- return Alice.CalculateHash(coin, ownershipProof);
- }
}
}

MODIFY
WalletWasabi/WabiSabi/Client/ArenaClient.cs
WalletWasabi/WabiSabi/Client/ArenaClient.cs
@@ -30,7 +30,7 @@ namespace WalletWasabi.WabiSabi.Client
public WabiSabiClient VsizeCredentialClient { get; }
public IWabiSabiApiRequestHandler RequestHandler { get; }
- public async Task<ArenaResponse<uint256>> RegisterInputAsync(
+ public async Task<ArenaResponse<Guid>> RegisterInputAsync(
uint256 roundId,
OutPoint outPoint,
Key key,
@@ -58,7 +58,7 @@ namespace WalletWasabi.WabiSabi.Client
return new(inputRegistrationResponse.AliceId, realAmountCredentials, realVsizeCredentials);
}
- public async Task RemoveInputAsync(uint256 roundId, uint256 aliceId, CancellationToken cancellationToken)
+ public async Task RemoveInputAsync(uint256 roundId, Guid aliceId, CancellationToken cancellationToken)
{
await RequestHandler.RemoveInputAsync(new InputsRemovalRequest(roundId, aliceId), cancellationToken).ConfigureAwait(false);
}
@@ -141,7 +141,7 @@ namespace WalletWasabi.WabiSabi.Client
public async Task<ArenaResponse<bool>> ConfirmConnectionAsync(
uint256 roundId,
- uint256 aliceId,
+ Guid aliceId,
IEnumerable<long> amountsToRequest,
IEnumerable<long> vsizesToRequest,
IEnumerable<Credential> amountCredentialsToPresent,
@@ -225,7 +225,7 @@ namespace WalletWasabi.WabiSabi.Client
public async Task ReadyToSignAsync(
uint256 roundId,
- uint256 aliceId,
+ Guid aliceId,
Key key,
CancellationToken cancellationToken)
{

MODIFY
WalletWasabi/WabiSabi/Models/ConnectionConfirmationRequest.cs
WalletWasabi/WabiSabi/Models/ConnectionConfirmationRequest.cs
@@ -6,7 +6,7 @@ namespace WalletWasabi.WabiSabi.Models
{
public record ConnectionConfirmationRequest(
uint256 RoundId,
- uint256 AliceId,
+ Guid AliceId,
ZeroCredentialsRequest ZeroAmountCredentialRequests,
RealCredentialsRequest RealAmountCredentialRequests,
ZeroCredentialsRequest ZeroVsizeCredentialRequests,

MODIFY
WalletWasabi/WabiSabi/Models/InputRegistrationResponse.cs
WalletWasabi/WabiSabi/Models/InputRegistrationResponse.cs
@@ -5,7 +5,7 @@ using WalletWasabi.WabiSabi.Crypto.CredentialRequesting;
namespace WalletWasabi.WabiSabi.Models
{
public record InputRegistrationResponse(
- uint256 AliceId,
+ Guid AliceId,
CredentialsResponse AmountCredentials,
CredentialsResponse VsizeCredentials
);

MODIFY
WalletWasabi/WabiSabi/Models/InputsRemovalRequest.cs
WalletWasabi/WabiSabi/Models/InputsRemovalRequest.cs
@@ -5,6 +5,6 @@ namespace WalletWasabi.WabiSabi.Models
{
public record InputsRemovalRequest(
uint256 RoundId,
- uint256 AliceId
+ Guid AliceId
);
}

MODIFY
WalletWasabi/WabiSabi/Models/ReadyToSignRequestRequest.cs
WalletWasabi/WabiSabi/Models/ReadyToSignRequestRequest.cs
@@ -10,6 +10,6 @@ namespace WalletWasabi.WabiSabi.Backend.PostRequests
{
public record ReadyToSignRequestRequest(
uint256 RoundId,
- uint256 AliceId,
+ Guid AliceId,
OwnershipProof OwnershipProof);
}

Make AliceId secret again (but nullable for now)