Improve wrt hashes count
MODIFY
WalletWasabi.Tests/UnitTests/Blockchain/Blocks/SmarthHeaderChainTests.cs
WalletWasabi.Tests/UnitTests/Blockchain/Blocks/SmarthHeaderChainTests.cs
@@ -121,6 +121,33 @@ public class SmarthHeaderChainTests
Assert.Equal(0, chain.HashesLeft);
}
+ [Fact]
+ public void HashCountTests()
+ {
+ SmartHeaderChain chain = new(maxChainSize: 2);
+ Assert.Equal(0u, chain.ServerTipHeight);
+
+ // Add 1st header.
+ SmartHeader header = CreateGenesisHeader();
+ chain.AppendTip(header);
+ Assert.Equal(1, chain.HashCount);
+
+ // Add 2nd header.
+ header = CreateSmartHeader(new uint256(1), chain.TipHash!, height: 1);
+ chain.AppendTip(header);
+ Assert.Equal(2, chain.HashCount);
+
+ // Add 3rd header.
+ header = CreateSmartHeader(new uint256(2), chain.TipHash!, height: 2);
+ chain.AppendTip(header);
+ Assert.Equal(3, chain.HashCount);
+
+ // Add 4th header.
+ header = CreateSmartHeader(new uint256(3), chain.TipHash!, height: 3);
+ chain.AppendTip(header);
+ Assert.Equal(4, chain.HashCount);
+ }
+
/// <remarks>Dummy genesis header.</remarks>
private static SmartHeader CreateGenesisHeader()
{

MODIFY
WalletWasabi/Blockchain/Blocks/SmartHeaderChain.cs
WalletWasabi/Blockchain/Blocks/SmartHeaderChain.cs
@@ -9,6 +9,8 @@ namespace WalletWasabi.Blockchain.Blocks;
/// </summary>
public class SmartHeaderChain
{
+ public const int Unlimited = 0;
+
/// <remarks>Guarded by <see cref="Lock"/>.</remarks>
private uint _tipHeight;
@@ -27,6 +29,15 @@ public class SmartHeaderChain
/// <remarks>Guarded by <see cref="Lock"/>.</remarks>
private int _hashesCount;
+ /// <param name="maxChainSize"><see cref="Unlimited"/> for no limit, otherwise the chain is capped to the specified number of elements.</param>
+ public SmartHeaderChain(int maxChainSize = Unlimited)
+ {
+ MaxChainSize = maxChainSize;
+ }
+
+ /// <remarks>Useful to save memory by removing elements at the beginning of the chain.</remarks>
+ private int MaxChainSize { get; }
+
private LinkedList<SmartHeader> Chain { get; } = new();
private object Lock { get; } = new();
@@ -85,6 +96,12 @@ public class SmartHeaderChain
}
}
+ /// <summary>Number of hashes in the chain.</summary>
+ /// <remarks>
+ /// Optimizations are taken into account for this value. So if the chain is
+ /// 1000 elements long and we remove first 100 to save memory, the reported
+ /// number will still be 1000.
+ /// </remarks>
public int HashCount
{
get
@@ -119,10 +136,12 @@ public class SmartHeaderChain
}
Chain.AddLast(tip);
+ _hashesCount++;
SetTipNoLock(tip);
- if (Chain.Count > 150_000)
+ if (MaxChainSize != Unlimited && Chain.Count > MaxChainSize)
{
+ // Intentionally, we do not modify hashes count here.
Chain.RemoveFirst();
}
}
@@ -137,6 +156,7 @@ public class SmartHeaderChain
if (Chain.Count > 0)
{
Chain.RemoveLast();
+ _hashesCount--;
SmartHeader? newTip = (Chain.Count > 0) ? Chain.Last!.Value : null;
SetTipNoLock(newTip);
@@ -172,7 +192,6 @@ public class SmartHeaderChain
_tip = tip;
_tipHeight = tip?.Height ?? default;
_tipHash = tip?.BlockHash;
- _hashesCount = Chain?.Count ?? default;
SetHashesLeftNoLock();
}

Improve wrt hashes count