fix spent issue
MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/CoinViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/CoinViewModel.cs
@@ -83,7 +83,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
.Subscribe(_ => RefreshSmartCoinStatus())
.DisposeWith(Disposables);
- Global.BitcoinStore.HashChain
+ Global.BitcoinStore.SmartHeaderChain
.WhenAnyValue(x => x.TipHeight)
.Select(x => new Height(x))
.Merge(Model.WhenAnyValue(x => x.Height))
@@ -114,7 +114,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
public string Address => Model.ScriptPubKey.GetDestinationAddress(Global.Network).ToString();
public int Confirmations => Model.Height.Type == HeightType.Chain
- ? (int)Global.BitcoinStore.HashChain.TipHeight - Model.Height.Value + 1
+ ? (int)Global.BitcoinStore.SmartHeaderChain.TipHeight - Model.Height.Value + 1
: 0;
public bool IsSelected

MODIFY
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabViewModel.cs
WalletWasabi.Gui/Controls/WalletExplorer/HistoryTabViewModel.cs
@@ -92,7 +92,7 @@ namespace WalletWasabi.Gui.Controls.WalletExplorer
{
DateTime = txr.DateTime.ToLocalTime(),
Confirmed = txr.Height.Type == HeightType.Chain,
- Confirmations = txr.Height.Type == HeightType.Chain ? (int)Global.BitcoinStore.HashChain.TipHeight - txr.Height.Value + 1 : 0,
+ Confirmations = txr.Height.Type == HeightType.Chain ? (int)Global.BitcoinStore.SmartHeaderChain.TipHeight - txr.Height.Value + 1 : 0,
AmountBtc = $"{txr.Amount.ToString(fplus: true, trimExcessZero: true)}",
Label = txr.Label,
TransactionId = txr.TransactionId.ToString()

MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -467,15 +467,6 @@ namespace WalletWasabi.Gui
ChaumianClient = new CoinJoinClient(Synchronizer, Network, keyManager, Config.GetFallbackBackendUri(), null);
}
- try
- {
- keyManager.CorrectBlockHeights(BitcoinStore.HashChain); // Block heights are wrong sometimes. It's a hack. We have to retroactively fix existing wallets, but also we have to figure out where we ruin the block heights.
- }
- catch (Exception ex) // Whatever this is not critical, but let's log it.
- {
- Logger.LogWarning(ex);
- }
-
WalletService = new WalletService(BitcoinStore, keyManager, Synchronizer, ChaumianClient, Nodes, DataDir, Config.ServiceConfiguration, FeeProviders, BitcoinCoreNode);
ChaumianClient.Start();

MODIFY
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
@@ -68,7 +68,7 @@ namespace WalletWasabi.Gui.ViewModels
{
Nodes = nodes;
Synchronizer = synchronizer;
- HashChain = synchronizer.BitcoinStore.HashChain;
+ HashChain = synchronizer.BitcoinStore.SmartHeaderChain;
UseTor = Global.Config.UseTor; // Do not make it dynamic, because if you change this config settings only next time will it activate.
UseBitcoinCore = Global.Config.StartLocalBitcoinCoreOnStartup;
var hostedServices = Global.HostedServices;

MODIFY
WalletWasabi.Tests/IntegrationTests/RegTests.cs
WalletWasabi.Tests/IntegrationTests/RegTests.cs
@@ -249,7 +249,7 @@ namespace WalletWasabi.Tests.IntegrationTests
// Test initial synchronization.
var times = 0;
int filterCount;
- while ((filterCount = bitcoinStore.HashChain.HashCount) < blockCount)
+ while ((filterCount = bitcoinStore.SmartHeaderChain.HashCount) < blockCount)
{
if (times > 500) // 30 sec
{
@@ -259,12 +259,12 @@ namespace WalletWasabi.Tests.IntegrationTests
times++;
}
- Assert.Equal(blockCount, bitcoinStore.HashChain.HashCount);
+ Assert.Equal(blockCount, bitcoinStore.SmartHeaderChain.HashCount);
// Test later synchronization.
await RegTestFixture.BackendRegTestNode.GenerateAsync(10);
times = 0;
- while ((filterCount = bitcoinStore.HashChain.HashCount) < blockCount + 10)
+ while ((filterCount = bitcoinStore.SmartHeaderChain.HashCount) < blockCount + 10)
{
if (times > 500) // 30 sec
{
@@ -275,7 +275,7 @@ namespace WalletWasabi.Tests.IntegrationTests
}
// Test correct number of filters is received.
- Assert.Equal(blockCount + 10, bitcoinStore.HashChain.HashCount);
+ Assert.Equal(blockCount + 10, bitcoinStore.SmartHeaderChain.HashCount);
// Test filter block hashes are correct.
var filterList = new List<FilterModel>();
@@ -337,9 +337,9 @@ namespace WalletWasabi.Tests.IntegrationTests
await WaitForIndexesToSyncAsync(global, TimeSpan.FromSeconds(90), bitcoinStore);
var tip = await rpc.GetBestBlockHashAsync();
- Assert.Equal(tip, bitcoinStore.HashChain.TipHash);
+ Assert.Equal(tip, bitcoinStore.SmartHeaderChain.TipHash);
var tipBlock = await rpc.GetBlockHeaderAsync(tip);
- Assert.Equal(tipBlock.HashPrevBlock, bitcoinStore.HashChain.GetChain().Select(x => x.header.BlockHash).ToArray()[bitcoinStore.HashChain.HashCount - 2]);
+ Assert.Equal(tipBlock.HashPrevBlock, bitcoinStore.SmartHeaderChain.GetChain().Select(x => x.header.BlockHash).ToArray()[bitcoinStore.SmartHeaderChain.HashCount - 2]);
var utxoPath = global.IndexBuilderService.Bech32UtxoSetFilePath;
var utxoLines = await File.ReadAllTextAsync(utxoPath);
@@ -366,12 +366,12 @@ namespace WalletWasabi.Tests.IntegrationTests
Assert.DoesNotContain(tx4.ToString(), utxoLines);
Assert.DoesNotContain(tx5.ToString(), utxoLines);
- var hashes = bitcoinStore.HashChain.GetChain().Select(x => x.header.BlockHash).ToArray();
+ var hashes = bitcoinStore.SmartHeaderChain.GetChain().Select(x => x.header.BlockHash).ToArray();
Assert.DoesNotContain(tip, hashes);
Assert.DoesNotContain(tipBlock.HashPrevBlock, hashes);
tip = await rpc.GetBestBlockHashAsync();
- Assert.Equal(tip, bitcoinStore.HashChain.TipHash);
+ Assert.Equal(tip, bitcoinStore.SmartHeaderChain.TipHash);
var filterList = new List<FilterModel>();
await bitcoinStore.IndexStore.ForeachFiltersAsync(async x =>
@@ -430,7 +430,7 @@ namespace WalletWasabi.Tests.IntegrationTests
var bestHash = await global.RpcClient.GetBestBlockHashAsync();
var times = 0;
- while (bitcoinStore.HashChain.TipHash != bestHash)
+ while (bitcoinStore.SmartHeaderChain.TipHash != bestHash)
{
if (times > timeout.TotalSeconds)
{
@@ -498,7 +498,7 @@ namespace WalletWasabi.Tests.IntegrationTests
Assert.Single(wallet.Coins);
var firstCoin = wallet.Coins.Single();
Assert.Equal(Money.Coins(0.1m), firstCoin.Amount);
- Assert.Equal(new Height((int)bitcoinStore.HashChain.TipHeight), firstCoin.Height);
+ Assert.Equal(new Height((int)bitcoinStore.SmartHeaderChain.TipHeight), firstCoin.Height);
Assert.InRange(firstCoin.Index, 0U, 1U);
Assert.False(firstCoin.Unavailable);
Assert.Equal("foo label", firstCoin.Label);
@@ -527,9 +527,9 @@ namespace WalletWasabi.Tests.IntegrationTests
var thirdCoin = wallet.Coins.OrderBy(x => x.Height).Last();
Assert.Equal(Money.Coins(0.01m), secondCoin.Amount);
Assert.Equal(Money.Coins(0.02m), thirdCoin.Amount);
- Assert.Equal(new Height(bitcoinStore.HashChain.TipHeight).Value - 2, firstCoin.Height.Value);
- Assert.Equal(new Height(bitcoinStore.HashChain.TipHeight).Value - 1, secondCoin.Height.Value);
- Assert.Equal(new Height(bitcoinStore.HashChain.TipHeight), thirdCoin.Height);
+ Assert.Equal(new Height(bitcoinStore.SmartHeaderChain.TipHeight).Value - 2, firstCoin.Height.Value);
+ Assert.Equal(new Height(bitcoinStore.SmartHeaderChain.TipHeight).Value - 1, secondCoin.Height.Value);
+ Assert.Equal(new Height(bitcoinStore.SmartHeaderChain.TipHeight), thirdCoin.Height);
Assert.False(thirdCoin.Unavailable);
Assert.Equal("foo label", firstCoin.Label);
Assert.Equal("bar label", secondCoin.Label);
@@ -585,7 +585,7 @@ namespace WalletWasabi.Tests.IntegrationTests
var rbfCoin = wallet.Coins.Single(x => x.TransactionId == tx4bumpRes.TransactionId);
Assert.Equal(Money.Coins(0.03m), rbfCoin.Amount);
- Assert.Equal(new Height(bitcoinStore.HashChain.TipHeight).Value - 2, rbfCoin.Height.Value);
+ Assert.Equal(new Height(bitcoinStore.SmartHeaderChain.TipHeight).Value - 2, rbfCoin.Height.Value);
Assert.False(rbfCoin.Unavailable);
Assert.Equal("bar label", rbfCoin.Label);
Assert.Equal(key2.P2wpkhScript, rbfCoin.ScriptPubKey);
@@ -619,7 +619,7 @@ namespace WalletWasabi.Tests.IntegrationTests
await rpc.GenerateAsync(1);
await WaitForFiltersToBeProcessedAsync(TimeSpan.FromSeconds(120), 1);
var res = await rpc.GetTxOutAsync(mempoolCoin.TransactionId, (int)mempoolCoin.Index, true);
- Assert.Equal(new Height(bitcoinStore.HashChain.TipHeight), mempoolCoin.Height);
+ Assert.Equal(new Height(bitcoinStore.SmartHeaderChain.TipHeight), mempoolCoin.Height);
}
finally
{
@@ -1036,7 +1036,7 @@ namespace WalletWasabi.Tests.IntegrationTests
await rpc.GenerateAsync(1);
await WaitForFiltersToBeProcessedAsync(TimeSpan.FromSeconds(120), 1);
- var bestHeight = new Height(bitcoinStore.HashChain.TipHeight);
+ var bestHeight = new Height(bitcoinStore.SmartHeaderChain.TipHeight);
IEnumerable<string> confirmedCoinLabels = wallet.Coins.Where(x => x.Height == bestHeight).SelectMany(x => x.Label.Labels);
Assert.Contains("outgoing", confirmedCoinLabels);
Assert.Contains("outgoing2", confirmedCoinLabels);
@@ -1487,8 +1487,8 @@ namespace WalletWasabi.Tests.IntegrationTests
var curBlockHash = await rpc.GetBestBlockHashAsync();
blockCount = await rpc.GetBlockCountAsync();
- Assert.Equal(bitcoinStore.HashChain.TipHash, curBlockHash);
- Assert.Equal((int)bitcoinStore.HashChain.TipHeight, blockCount);
+ Assert.Equal(bitcoinStore.SmartHeaderChain.TipHash, curBlockHash);
+ Assert.Equal((int)bitcoinStore.SmartHeaderChain.TipHeight, blockCount);
// Make sure the funding transaction is not in any block of the chain
while (curBlockHash != rpc.Network.GenesisHash)

MODIFY
WalletWasabi/Blockchain/Blocks/SmartHeaderChain.cs
WalletWasabi/Blockchain/Blocks/SmartHeaderChain.cs
@@ -134,6 +134,23 @@ namespace WalletWasabi.Blockchain.Blocks
}
}
+ public bool TryGetHeader(uint height, out SmartHeader header)
+ {
+ header = null;
+ lock (Lock)
+ {
+ if (Chain.ContainsKey(height))
+ {
+ header = Chain[height];
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
public bool TryGetHeight(uint256 hash, out uint height)
{
lock (Lock)

DELETE
WalletWasabi/Blockchain/Keys/BlockState.cs
-using NBitcoin;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using WalletWasabi.JsonConverters;
-using WalletWasabi.Models;
-
-namespace WalletWasabi.Blockchain.Keys
-{
- [JsonObject(MemberSerialization.OptIn)]
- public class BlockState : IComparable<BlockState>
- {
- [JsonProperty(Order = 1)]
- [JsonConverter(typeof(Uint256JsonConverter))]
- public uint256 BlockHash { get; }
-
- [JsonProperty(Order = 2)]
- [JsonConverter(typeof(HeightJsonConverter))]
- public Height BlockHeight { get; }
-
- [JsonProperty(Order = 3)]
- public List<int> TransactionIndices { get; }
-
- [JsonConstructor]
- public BlockState(uint256 blockHash, Height blockHeight, IEnumerable<int> transactionIndices)
- {
- BlockHash = blockHash;
- BlockHeight = blockHeight;
- TransactionIndices = transactionIndices?.OrderBy(x => x).ToList() ?? new List<int>();
- }
-
- /// <summary>
- /// Performs a comparison and return if compared values are equal, greater or less than the other one
- /// </summary>
- /// <param name="other">The blockheight to compare against.</param>
- /// <returns>0 if this an other are equal, -1 if this is less than other and 1 if this is greater than other.</returns>
- public int CompareTo(BlockState other) => BlockHeight.CompareTo(other.BlockHeight);
- }
-}

MODIFY
WalletWasabi/Blockchain/Keys/BlockchainState.cs
WalletWasabi/Blockchain/Keys/BlockchainState.cs
@@ -12,30 +12,23 @@ namespace WalletWasabi.Blockchain.Keys
[JsonObject(MemberSerialization.OptIn)]
public class BlockchainState
{
- [JsonProperty(Order = 0)]
[JsonConverter(typeof(NetworkJsonConverter))]
public Network Network { get; set; }
- [JsonProperty(Order = 1)]
[JsonConverter(typeof(HeightJsonConverter))]
- public Height BestHeight { get; set; }
-
- [JsonProperty(Order = 2)]
- public List<BlockState> BlockStates { get; }
+ public Height Height { get; set; }
[JsonConstructor]
- public BlockchainState(Network network, Height bestHeight, IEnumerable<BlockState> blockStates)
+ public BlockchainState(Network network, Height height)
{
Network = network;
- BestHeight = bestHeight;
- BlockStates = blockStates?.OrderBy(x => x).ToList() ?? new List<BlockState>();
+ Height = height;
}
public BlockchainState()
{
Network = Network.Main;
- BestHeight = 0;
- BlockStates = new List<BlockState>();
+ Height = 0;
}
}
}

MODIFY
WalletWasabi/Blockchain/Keys/KeyManager.cs
WalletWasabi/Blockchain/Keys/KeyManager.cs
@@ -240,19 +240,16 @@ namespace WalletWasabi.Blockchain.Keys
IoHelpers.EnsureContainingDirectoryExists(filePath);
// Remove the last 100 blocks to ensure verification on the next run. This is needed of reorg.
int maturity = 101;
- Height prevHeight = BlockchainState.BestHeight;
+ Height prevHeight = BlockchainState.Height;
int matureHeight = Math.Max(0, prevHeight.Value - maturity);
- BlockchainState.BestHeight = new Height(matureHeight);
- HashSet<BlockState> toRemove = BlockchainState.BlockStates.Where(x => x.BlockHeight >= BlockchainState.BestHeight).ToHashSet();
- BlockchainState.BlockStates.RemoveAll(x => toRemove.Contains(x));
+ BlockchainState.Height = new Height(matureHeight);
string jsonString = JsonConvert.SerializeObject(this, Formatting.Indented);
File.WriteAllText(filePath, jsonString, Encoding.UTF8);
// Re-add removed items for further operations.
- BlockchainState.BlockStates.AddRange(toRemove.OrderBy(x => x));
- BlockchainState.BestHeight = prevHeight;
+ BlockchainState.Height = prevHeight;
}
public static KeyManager FromFile(string filePath)
@@ -642,136 +639,30 @@ namespace WalletWasabi.Blockchain.Keys
#region BlockchainState
- public void CorrectBlockHeights(SmartHeaderChain hashChain)
- {
- lock (BlockchainStateLock)
- {
- // Block heights are wrong sometimes. It's a hack. We have to retroactively fix existing wallets, but also we have to figure out where we ruin the block heights.
- // Assert the correct height.
- var toRemove = new List<uint256>();
- var toAdd = new List<BlockState>();
- foreach (var state in BlockchainState.BlockStates)
- {
- if (hashChain.TryGetHeight(state.BlockHash, out uint foundHeight) && foundHeight != state.BlockHeight.Value)
- {
- toRemove.Add(state.BlockHash);
- toAdd.Add(new BlockState(state.BlockHash, new Height((int)foundHeight), state.TransactionIndices));
- }
- }
-
- foreach (var rem in toRemove)
- {
- TryRemoveBlockState(rem);
- }
-
- foreach (var add in toAdd)
- {
- AddBlockState(add, setItsHeightToBest: false);
- }
-
- if (toRemove.Any())
- {
- ToFileNoBlockchainStateLock();
- Logger.LogInfo($"Corrected {toRemove.Count} heights.");
- }
- }
- }
-
public Height GetBestHeight()
{
Height res;
lock (BlockchainStateLock)
{
- res = BlockchainState.BestHeight;
- }
- return res;
- }
-
- public IEnumerable<BlockState> GetTransactionIndex()
- {
- IEnumerable<BlockState> res = null;
- lock (BlockchainStateLock)
- {
- res = BlockchainState.BlockStates.ToList();
+ res = BlockchainState.Height;
}
return res;
}
- /// <returns>Removed element.</returns>
- public BlockState TryRemoveBlockState(uint256 blockHash)
- {
- BlockState found = null;
- lock (BlockchainStateLock)
- {
- found = BlockchainState.BlockStates.FirstOrDefault(x => x.BlockHash == blockHash);
- if (found != null)
- {
- if (BlockchainState.BlockStates.Remove(found))
- {
- ToFileNoBlockchainStateLock();
- }
- }
- }
- return found;
- }
-
- public bool CointainsBlockState(uint256 blockHash)
- {
- bool res = false;
- lock (BlockchainStateLock)
- {
- res = BlockchainState.BlockStates.Any(x => x.BlockHash == blockHash);
- }
- return res;
- }
-
- public void AddBlockState(BlockState state, bool setItsHeightToBest)
+ public void SetBestHeight(Height height)
{
lock (BlockchainStateLock)
{
- // Make sure of proper ordering here.
-
- // If found same hash then update.
- // Else If found same height then replace.
- // Else add.
- // Note same hash diff height makes no sense.
-
- BlockState foundWithHash = BlockchainState.BlockStates.FirstOrDefault(x => x.BlockHash == state.BlockHash);
- if (foundWithHash != null)
- {
- IEnumerable<int> newIndices = state.TransactionIndices.Where(x => !foundWithHash.TransactionIndices.Contains(x));
- if (newIndices.Any())
- {
- foundWithHash.TransactionIndices.AddRange(newIndices);
- foundWithHash.TransactionIndices.Sort();
- }
- }
- else
- {
- BlockState foundWithHeight = BlockchainState.BlockStates.FirstOrDefault(x => x.BlockHeight == state.BlockHeight);
- if (foundWithHeight != null)
- {
- BlockchainState.BlockStates.Remove(foundWithHeight);
- }
-
- BlockchainState.BlockStates.Add(state);
- BlockchainState.BlockStates.Sort();
- }
-
- if (setItsHeightToBest)
- {
- BlockchainState.BestHeight = state.BlockHeight;
- }
-
+ BlockchainState.Height = height;
ToFileNoBlockchainStateLock();
}
}
- public void SetBestHeight(Height height)
+ public void SetMaxBestHeight(Height height)
{
lock (BlockchainStateLock)
{
- BlockchainState.BestHeight = height;
+ BlockchainState.Height = Math.Min(BlockchainState.Height, height);
ToFileNoBlockchainStateLock();
}
}
@@ -784,8 +675,7 @@ namespace WalletWasabi.Blockchain.Keys
if (lastNetwork is null || lastNetwork != expectedNetwork)
{
BlockchainState.Network = expectedNetwork;
- BlockchainState.BestHeight = 0;
- BlockchainState.BlockStates.Clear();
+ BlockchainState.Height = 0;
ToFileNoBlockchainStateLock();
if (lastNetwork != null)

MODIFY
WalletWasabi/Blockchain/Transactions/TransactionHistoryBuilder.cs
WalletWasabi/Blockchain/Transactions/TransactionHistoryBuilder.cs
@@ -2,6 +2,7 @@ using NBitcoin;
using System;
using System.Collections.Generic;
using System.Linq;
+using WalletWasabi.Blockchain.Blocks;
using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.Models;
using WalletWasabi.Services;
@@ -27,8 +28,6 @@ namespace WalletWasabi.Blockchain.Transactions
return txRecordList;
}
- var processedBlockTimeByHeight = walletService.ProcessedBlocks?.Values.ToDictionary(x => x.height, x => x.dateTime)
- ?? new Dictionary<Height, DateTimeOffset>();
var allCoins = ((CoinsRegistry)walletService.Coins).AsAllCoinsView();
foreach (SmartCoin coin in allCoins)
{
@@ -41,9 +40,9 @@ namespace WalletWasabi.Blockchain.Transactions
DateTimeOffset dateTime;
if (foundTransaction.Height.Type == HeightType.Chain)
{
- if (processedBlockTimeByHeight.TryGetValue(foundTransaction.Height, out var blockDateTime))
+ if (walletService.BitcoinStore.SmartHeaderChain.TryGetHeader((uint)foundTransaction.Height.Value, out SmartHeader header))
{
- dateTime = blockDateTime;
+ dateTime = header.BlockTime;
}
else
{
@@ -85,9 +84,9 @@ namespace WalletWasabi.Blockchain.Transactions
if (foundSpenderTransaction.Height.Type == HeightType.Chain)
{
- if (processedBlockTimeByHeight.TryGetValue(foundSpenderTransaction.Height, out var blockDateTime))
+ if (walletService.BitcoinStore.SmartHeaderChain.TryGetHeader((uint)foundSpenderTransaction.Height.Value, out SmartHeader header))
{
- dateTime = blockDateTime;
+ dateTime = header.BlockTime;
}
else
{

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -68,8 +68,6 @@ namespace WalletWasabi.Services
public ServiceConfiguration ServiceConfiguration { get; }
- public ConcurrentDictionary<uint256, (Height height, DateTimeOffset dateTime)> ProcessedBlocks { get; }
-
/// <summary>
/// Unspent Transaction Outputs
/// </summary>
@@ -103,7 +101,6 @@ namespace WalletWasabi.Services
FeeProvider = Guard.NotNull(nameof(feeProvider), feeProvider);
CoreNode = coreNode;
- ProcessedBlocks = new ConcurrentDictionary<uint256, (Height height, DateTimeOffset dateTime)>();
HandleFiltersLock = new AsyncLock();
BlocksFolderPath = Path.Combine(workFolderDir, "Blocks", Network.ToString());
@@ -197,15 +194,11 @@ namespace WalletWasabi.Services
{
uint256 invalidBlockHash = invalidFilter.Header.BlockHash;
await DeleteBlockAsync(invalidBlockHash);
- var blockState = KeyManager.TryRemoveBlockState(invalidBlockHash);
- ProcessedBlocks.TryRemove(invalidBlockHash, out _);
- if (blockState != null && blockState.BlockHeight != default(Height))
- {
- TransactionProcessor.UndoBlock(blockState.BlockHeight);
+ KeyManager.SetMaxBestHeight(new Height(invalidFilter.Header.Height - 1));
+ TransactionProcessor.UndoBlock((int)invalidFilter.Header.Height);
BitcoinStore.TransactionStore.TryReorg(invalidBlockHash);
}
}
- }
catch (Exception ex)
{
Logger.LogWarning(ex);
@@ -218,7 +211,7 @@ namespace WalletWasabi.Services
{
using (await HandleFiltersLock.LockAsync())
{
- if (filterModel.Filter != null && !KeyManager.CointainsBlockState(filterModel.Header.BlockHash))
+ if (KeyManager.GetBestHeight() < filterModel.Header.Height)
{
await ProcessFilterModelAsync(filterModel, CancellationToken.None);
}
@@ -228,12 +221,12 @@ namespace WalletWasabi.Services
do
{
await Task.Delay(100);
- if (Synchronizer is null || BitcoinStore?.HashChain is null)
+ if (Synchronizer is null || BitcoinStore?.SmartHeaderChain is null)
{
return;
}
// Make sure fully synced and this filter is the lastest filter.
- if (BitcoinStore.HashChain.HashesLeft != 0 || BitcoinStore.HashChain.TipHash != filterModel.Header.BlockHash)
+ if (BitcoinStore.SmartHeaderChain.HashesLeft != 0 || BitcoinStore.SmartHeaderChain.TipHash != filterModel.Header.BlockHash)
{
return;
}
@@ -274,12 +267,12 @@ namespace WalletWasabi.Services
{
KeyManager.AssertNetworkOrClearBlockState(Network);
Height bestKeyManagerHeight = KeyManager.GetBestHeight();
-
- foreach (BlockState blockState in KeyManager.GetTransactionIndex())
+ lock (TransactionProcessor.Lock)
{
- var relevantTransactions = BitcoinStore.TransactionStore.ConfirmedStore.GetTransactions().Where(x => x.BlockHash == blockState.BlockHash).ToArray();
- var block = await FetchBlockAsync(blockState.BlockHash, cancel);
- ProcessBlock(blockState.BlockHeight, block, blockState.TransactionIndices, relevantTransactions);
+ foreach (var tx in BitcoinStore.TransactionStore.ConfirmedStore.GetTransactions().TakeWhile(x => x.Height <= bestKeyManagerHeight))
+ {
+ TransactionProcessor.Process(tx);
+ }
}
// Go through the filters and queue to download the matches.
@@ -339,11 +332,6 @@ namespace WalletWasabi.Services
private async Task ProcessFilterModelAsync(FilterModel filterModel, CancellationToken cancel)
{
- if (ProcessedBlocks.ContainsKey(filterModel.Header.BlockHash))
- {
- return;
- }
-
var matchFound = filterModel.Filter.MatchAny(KeyManager.GetPubKeyScriptBytes(), filterModel.FilterKey);
if (!matchFound)
{
@@ -383,26 +371,14 @@ namespace WalletWasabi.Services
{
if (filterByTxIndexes is null)
{
- var relevantIndices = new List<int>();
for (int i = 0; i < block.Transactions.Count; i++)
{
Transaction tx = block.Transactions[i];
- if (TransactionProcessor.Process(new SmartTransaction(tx, height, block.GetHash(), i, firstSeen: block.Header.BlockTime)))
- {
- relevantIndices.Add(i);
- }
+ TransactionProcessor.Process(new SmartTransaction(tx, height, block.GetHash(), i, firstSeen: block.Header.BlockTime));
}
- if (relevantIndices.Any())
- {
- var blockState = new BlockState(block.GetHash(), height, relevantIndices);
- KeyManager.AddBlockState(blockState, setItsHeightToBest: true); // Set the height here (so less toFile and lock.)
- }
- else
- {
KeyManager.SetBestHeight(height);
}
- }
else
{
foreach (var i in filterByTxIndexes.OrderBy(x => x))
@@ -413,8 +389,6 @@ namespace WalletWasabi.Services
}
}
- ProcessedBlocks.TryAdd(block.GetHash(), (height, block.Header.BlockTime));
-
NewBlockProcessed?.Invoke(this, block);
}

MODIFY
WalletWasabi/Services/WasabiSynchronizer.cs
WalletWasabi/Services/WasabiSynchronizer.cs
@@ -151,7 +151,7 @@ namespace WalletWasabi.Services
{
DateTimeOffset lastFeeQueried = DateTimeOffset.UtcNow - feeQueryRequestInterval;
bool ignoreRequestInterval = false;
- var hashChain = BitcoinStore.HashChain;
+ var hashChain = BitcoinStore.SmartHeaderChain;
EnableRequests();
while (IsRunning)
{

MODIFY
WalletWasabi/Stores/BitcoinStore.cs
WalletWasabi/Stores/BitcoinStore.cs
@@ -25,7 +25,7 @@ namespace WalletWasabi.Stores
public IndexStore IndexStore { get; private set; }
public AllTransactionStore TransactionStore { get; private set; }
- public SmartHeaderChain HashChain { get; private set; }
+ public SmartHeaderChain SmartHeaderChain { get; private set; }
public MempoolService MempoolService { get; private set; }
/// <summary>
@@ -47,12 +47,12 @@ namespace WalletWasabi.Stores
TransactionStore = new AllTransactionStore();
var networkWorkFolderPath = Path.Combine(WorkFolderPath, Network.ToString());
var indexStoreFolderPath = Path.Combine(networkWorkFolderPath, "IndexStore");
- HashChain = new SmartHeaderChain();
+ SmartHeaderChain = new SmartHeaderChain();
MempoolService = new MempoolService();
var initTasks = new[]
{
- IndexStore.InitializeAsync(indexStoreFolderPath, Network, HashChain),
+ IndexStore.InitializeAsync(indexStoreFolderPath, Network, SmartHeaderChain),
TransactionStore.InitializeAsync(networkWorkFolderPath, Network)
};

fix spent issue