Fix utxo serialization issue, add test
MODIFY
WalletWasabi.Tests/ModelTests.cs
WalletWasabi.Tests/ModelTests.cs
@@ -7,6 +7,7 @@ using System.Linq;
using System.Threading;
using WalletWasabi.JsonConverters;
using WalletWasabi.Models;
+using WalletWasabi.Services;
using WalletWasabi.Tests.XunitConfiguration;
using Xunit;
@@ -116,6 +117,32 @@ namespace WalletWasabi.Tests
Assert.Empty(deserializedWithoutLabel.Label);
}
+ [Fact]
+ [Trait("Category", "RunOnCi")]
+ public void UtxoRefereeSerialization()
+ {
+ var record = UtxoReferee.BannedRecordFromLine("2018-11-23 15-23-14:1:44:2716e680f47d74c1bc6f031da22331564dd4c6641d7216576aad1b846c85d492:True:195");
+
+ Assert.Equal(new DateTimeOffset(2018, 11, 23, 15, 23, 14, TimeSpan.Zero), record.timeOfBan);
+ Assert.Equal(1, record.severity);
+ Assert.Equal(44u, record.utxo.N);
+ Assert.Equal(new uint256("2716e680f47d74c1bc6f031da22331564dd4c6641d7216576aad1b846c85d492"), record.utxo.Hash);
+ Assert.True(record.isNoted);
+ Assert.Equal(195, record.bannedForRound);
+
+ DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+ DateTimeOffset now = new DateTimeOffset(dateTime.Ticks - (dateTime.Ticks % TimeSpan.TicksPerSecond), TimeSpan.Zero);
+ string record2Line = UtxoReferee.BannedRecordToLine(record.utxo, 3, now, false, 99);
+ var record2 = UtxoReferee.BannedRecordFromLine(record2Line);
+
+ Assert.Equal(now, record2.timeOfBan);
+ Assert.Equal(3, record2.severity);
+ Assert.Equal(44u, record2.utxo.N);
+ Assert.Equal(new uint256("2716e680f47d74c1bc6f031da22331564dd4c6641d7216576aad1b846c85d492"), record2.utxo.Hash);
+ Assert.False(record2.isNoted);
+ Assert.Equal(99, record2.bannedForRound);
+ }
+
[Fact]
[Trait("Category", "RunOnCi")]
public void SmartCoinSerialization()

MODIFY
WalletWasabi/Services/UtxoReferee.cs
WalletWasabi/Services/UtxoReferee.cs
@@ -52,14 +52,9 @@ namespace WalletWasabi.Services
string[] allLines = File.ReadAllLines(BannedUtxosFilePath);
foreach (string line in allLines)
{
- var parts = line.Split(':');
- var isNoted = parts.Length <= 4 ? false : bool.Parse(parts[4]);
- var bannedForRound = parts.Length <= 4 ? 0 : long.Parse(parts[5]);
- var utxo = new OutPoint(new uint256(parts[3]), int.Parse(parts[2]));
- var severity = int.Parse(parts[1]);
- var timeOfBan = DateTimeOffset.Parse(parts[0], CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
+ var bannedRecord = BannedRecordFromLine(line);
- GetTxOutResponse getTxOutResponse = RpcClient.GetTxOut(utxo.Hash, (int)utxo.N, includeMempool: true);
+ GetTxOutResponse getTxOutResponse = RpcClient.GetTxOut(bannedRecord.utxo.Hash, (int)bannedRecord.utxo.N, includeMempool: true);
// Check if inputs are unspent.
if (getTxOutResponse is null)
@@ -68,7 +63,7 @@ namespace WalletWasabi.Services
}
else
{
- BannedUtxos.TryAdd(utxo, (severity, timeOfBan, isNoted, bannedForRound));
+ BannedUtxos.TryAdd(bannedRecord.utxo, (bannedRecord.severity, bannedRecord.timeOfBan, bannedRecord.isNoted, bannedRecord.bannedForRound));
}
}
@@ -137,7 +132,7 @@ namespace WalletWasabi.Services
}
if (BannedUtxos.TryAdd(utxo, (severity, timeOfBan, isNoted, bannedForRound)))
{
- string line = $"{timeOfBan.ToString(CultureInfo.InvariantCulture)}:{severity}:{utxo.N}:{utxo.Hash}:{isNoted}:{bannedForRound}";
+ string line = BannedRecordToLine(utxo, severity, timeOfBan, isNoted, bannedForRound);
lines.Add(line);
}
else
@@ -171,7 +166,7 @@ namespace WalletWasabi.Services
{
if (BannedUtxos.TryRemove(output, out _))
{
- IEnumerable<string> lines = BannedUtxos.Select(x => $"{x.Value.timeOfBan.ToString(CultureInfo.InvariantCulture)}:{x.Value.severity}:{x.Key.N}:{x.Key.Hash}:{x.Value.isNoted}:{x.Value.bannedForRound}");
+ IEnumerable<string> lines = BannedUtxos.Select(x => BannedRecordToLine(x.Key, x.Value.severity, x.Value.timeOfBan, x.Value.isNoted, x.Value.bannedForRound));
await File.WriteAllLinesAsync(BannedUtxosFilePath, lines);
Logger.LogInfo<UtxoReferee>($"UTXO unbanned: {output.N}:{output.Hash}.");
}
@@ -237,5 +232,23 @@ namespace WalletWasabi.Services
File.Delete(BannedUtxosFilePath);
}
}
+
+ internal static string BannedRecordToLine(OutPoint utxo, int severity, DateTimeOffset timeOfBan, bool isNoted, long bannedForRound)
+ {
+ return $"{timeOfBan.ToString("yyyy-MM-dd HH-mm-ss")}:{severity}:{utxo.N}:{utxo.Hash}:{isNoted}:{bannedForRound}";
+ }
+
+ internal static (OutPoint utxo, int severity, DateTimeOffset timeOfBan, bool isNoted, long bannedForRound) BannedRecordFromLine(string line)
+ {
+ var parts = line.Split(':');
+ var isNoted = bool.Parse(parts[4]);
+ var bannedForRound = long.Parse(parts[5]);
+ var utxo = new OutPoint(new uint256(parts[3]), int.Parse(parts[2]));
+ var severity = int.Parse(parts[1]);
+ var timeParts = parts[0].Split('-', ' ').Select(x => int.Parse(x)).ToArray();
+ var timeOfBan = new DateTimeOffset(timeParts[0], timeParts[1], timeParts[2], timeParts[3], timeParts[4], timeParts[5], TimeSpan.Zero);
+
+ return (utxo, severity, timeOfBan, isNoted, bannedForRound);
+ }
}
}

Fix utxo serialization issue, add test