public async Task InconsistentImmatureIndexAsync() { var(dir, _, immatureFilters) = await GetIndexStorePathsAsync(); var network = Network.Main; var headersChain = new SmartHeaderChain(); await using var indexStore = new IndexStore(dir, network, headersChain); var dummyFilter = GolombRiceFilter.Parse("00"); var startingFilter = StartingFilters.GetStartingFilter(network); var immatureIndexStoreContent = new[] { new FilterModel(new SmartHeader(new uint256(2), startingFilter.Header.BlockHash, startingFilter.Header.Height + 1, MinutesAgo(30)), dummyFilter), new FilterModel(new SmartHeader(new uint256(3), new uint256(2), startingFilter.Header.Height + 2, MinutesAgo(20)), dummyFilter), new FilterModel(new SmartHeader(new uint256(99), new uint256(98), startingFilter.Header.Height + 98, MinutesAgo(10)), dummyFilter) }; await File.WriteAllLinesAsync(immatureFilters, immatureIndexStoreContent.Select(x => x.ToLine())); await Assert.ThrowsAsync <InvalidOperationException>(async() => await indexStore.InitializeAsync()); Assert.Equal(new uint256(3), headersChain.TipHash); Assert.Equal(startingFilter.Header.Height + 2u, headersChain.TipHeight); // Check if the immatureIndex is deleted Assert.False(File.Exists(immatureFilters)); }
protected ClosedWalletViewModel(WalletManagerViewModel walletManagerViewModel, Wallet wallet) : base(wallet) { _smartHeaderChain = Services.BitcoinStore.SmartHeaderChain; OpenCommand = ReactiveCommand.Create(() => OnOpen(walletManagerViewModel)); }
public async Task GapInIndexAsync() { var(dir, matureFilters, immatureFilters) = await GetIndexStorePathsAsync(); var network = Network.Main; var headersChain = new SmartHeaderChain(); await using var indexStore = new IndexStore(dir, network, headersChain); var dummyFilter = GolombRiceFilter.Parse("00"); var matureIndexStoreContent = new[] { new FilterModel(new SmartHeader(new uint256(2), new uint256(1), 1, MinutesAgo(30)), dummyFilter), new FilterModel(new SmartHeader(new uint256(3), new uint256(2), 2, MinutesAgo(20)), dummyFilter), }; await File.WriteAllLinesAsync(matureFilters, matureIndexStoreContent.Select(x => x.ToLine())); var immatureIndexStoreContent = new[] { new FilterModel(new SmartHeader(new uint256(5), new uint256(4), 4, MinutesAgo(30)), dummyFilter), new FilterModel(new SmartHeader(new uint256(6), new uint256(5), 5, MinutesAgo(20)), dummyFilter), }; await File.WriteAllLinesAsync(immatureFilters, immatureIndexStoreContent.Select(x => x.ToLine())); await Assert.ThrowsAsync <InvalidOperationException>(async() => await indexStore.InitializeAsync()); Assert.Equal(new uint256(3), headersChain.TipHash); Assert.Equal(2u, headersChain.TipHeight); Assert.True(File.Exists(matureFilters)); // mature filters are ok Assert.False(File.Exists(immatureFilters)); // immature filters are NOT ok }
public async Task InitializeAsync(string workFolderPath, Network network) { using (BenchmarkLogger.Measure()) { WorkFolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(workFolderPath), workFolderPath, trim: true); IoHelpers.EnsureDirectoryExists(WorkFolderPath); Network = Guard.NotNull(nameof(network), network); IndexStore = new IndexStore(); TransactionStore = new AllTransactionStore(); var networkWorkFolderPath = Path.Combine(WorkFolderPath, Network.ToString()); var indexStoreFolderPath = Path.Combine(networkWorkFolderPath, "IndexStore"); SmartHeaderChain = new SmartHeaderChain(); MempoolService = new MempoolService(); var initTasks = new[] { IndexStore.InitializeAsync(indexStoreFolderPath, Network, SmartHeaderChain), TransactionStore.InitializeAsync(networkWorkFolderPath, Network) }; await Task.WhenAll(initTasks).ConfigureAwait(false); IsInitialized = true; } }
private static void AssertEverythingDefault(SmartHeaderChain hashChain) { Assert.Equal(0, hashChain.HashCount); Assert.Equal(0, hashChain.HashesLeft); Assert.Equal(0u, hashChain.ServerTipHeight); Assert.Null(hashChain.TipHash); Assert.Equal(0u, hashChain.TipHeight); }
public IndexStore(string workFolderPath, Network network, SmartHeaderChain hashChain) { WorkFolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(workFolderPath), workFolderPath, trim: true); IoHelpers.EnsureDirectoryExists(WorkFolderPath); Network = Guard.NotNull(nameof(network), network); SmartHeaderChain = Guard.NotNull(nameof(hashChain), hashChain); }
public async Task InconsistentMatureIndexAsync() { var(dir, matureFilters, _) = await GetIndexStorePathsAsync(); var network = Network.Main; var headersChain = new SmartHeaderChain(); var indexStore = new IndexStore(dir, network, headersChain); var dummyFilter = GolombRiceFilter.Parse("00");
public IndexStore(string workFolderPath, Network network, SmartHeaderChain smartHeaderChain) { WorkFolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(workFolderPath), workFolderPath, trim: true); IoHelpers.EnsureDirectoryExists(WorkFolderPath); var indexFilePath = Path.Combine(WorkFolderPath, "MatureIndex.dat"); MatureIndexFileManager = new DigestableSafeIoManager(indexFilePath, useLastCharacterDigest: true); var immatureIndexFilePath = Path.Combine(WorkFolderPath, "ImmatureIndex.dat"); ImmatureIndexFileManager = new DigestableSafeIoManager(immatureIndexFilePath, useLastCharacterDigest: true); Network = network; StartingFilter = StartingFilters.GetStartingFilter(Network); SmartHeaderChain = smartHeaderChain; }
private volatile bool _disposedValue = false; // To detect redundant calls public StatusBarViewModel(string dataDir, Network network, Config config, HostedServices hostedServices, SmartHeaderChain smartHeaderChain, WasabiSynchronizer synchronizer, LegalDocuments?legalDocuments) { DataDir = dataDir; Network = network; Config = config; HostedServices = hostedServices; SmartHeaderChain = smartHeaderChain; Synchronizer = synchronizer; LegalDocuments = legalDocuments; Backend = BackendStatus.NotConnected; UseTor = false; Tor = TorStatus.NotRunning; Peers = 0; BtcPrice = "$0"; ActiveStatuses = new StatusSet(); }
private volatile bool _disposedValue = false; // To detect redundant calls public StatusBarViewModel(string dataDir, Network network, Config config, HostedServices hostedServices, SmartHeaderChain smartHeaderChain, WasabiSynchronizer synchronizer) { DataDir = dataDir; Network = network; Config = config; HostedServices = hostedServices; SmartHeaderChain = smartHeaderChain; Synchronizer = synchronizer; Backend = BackendStatus.NotConnected; UseTor = false; Tor = TorStatus.NotRunning; Peers = 0; _exchangeRate = ""; IsExchangeRateAvailable = false; ActiveStatuses = new StatusSet(); }
public IndexStore(string workFolderPath, Network network, SmartHeaderChain hashChain) { WorkFolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(workFolderPath), workFolderPath, trim: true); IoHelpers.EnsureDirectoryExists(WorkFolderPath); var indexFilePath = Path.Combine(WorkFolderPath, "MatureIndex.dat"); MatureIndexFileManager = new DigestableSafeIoManager(indexFilePath, digestRandomIndex: -1); var immatureIndexFilePath = Path.Combine(WorkFolderPath, "ImmatureIndex.dat"); ImmatureIndexFileManager = new DigestableSafeIoManager(immatureIndexFilePath, digestRandomIndex: -1); Network = Guard.NotNull(nameof(network), network); StartingFilter = StartingFilters.GetStartingFilter(Network); SmartHeaderChain = Guard.NotNull(nameof(hashChain), hashChain); }
private bool TryProcessFilter(FilterModel filter, bool enqueue) { try { SmartHeaderChain.AddOrReplace(filter.Header); if (enqueue) { ImmatureFilters.Add(filter); } return(true); } catch (Exception ex) { Logger.LogError(ex); return(false); } }
public async Task ReceiveNonMatchingFilterAsync() { var(dir, matureFilters, immatureFilters) = await GetIndexStorePathsAsync(); var network = Network.Main; var headersChain = new SmartHeaderChain(); await using var indexStore = new IndexStore(dir, network, headersChain); var dummyFilter = GolombRiceFilter.Parse("00"); var matureIndexStoreContent = new[] { new FilterModel(new SmartHeader(new uint256(2), new uint256(1), 1, MinutesAgo(30)), dummyFilter), new FilterModel(new SmartHeader(new uint256(3), new uint256(2), 2, MinutesAgo(20)), dummyFilter), }; await File.WriteAllLinesAsync(matureFilters, matureIndexStoreContent.Select(x => x.ToLine())); await indexStore.InitializeAsync(); Assert.Equal(new uint256(3), headersChain.TipHash); Assert.Equal(2u, headersChain.TipHeight); Assert.True(File.Exists(matureFilters)); // mature filters are ok var nonMatchingBlockHashFilter = new FilterModel(new SmartHeader(new uint256(2), new uint256(1), 1, MinutesAgo(30)), dummyFilter); await indexStore.AddNewFiltersAsync(new[] { nonMatchingBlockHashFilter }, CancellationToken.None); Assert.Equal(new uint256(3), headersChain.TipHash); // the filter is not added! Assert.Equal(2u, headersChain.TipHeight); var nonMatchingHeightFilter = new FilterModel(new SmartHeader(new uint256(4), new uint256(3), 37, MinutesAgo(1)), dummyFilter); await indexStore.AddNewFiltersAsync(new[] { nonMatchingHeightFilter }, CancellationToken.None); Assert.Equal(new uint256(3), headersChain.TipHash); // the filter is not added! Assert.Equal(2u, headersChain.TipHeight); var correctFilter = new FilterModel(new SmartHeader(new uint256(4), new uint256(3), 3, MinutesAgo(1)), dummyFilter); await indexStore.AddNewFiltersAsync(new[] { correctFilter }, CancellationToken.None); Assert.Equal(new uint256(4), headersChain.TipHash); // the filter is not added! Assert.Equal(3u, headersChain.TipHeight); }
public async Task InitializeAsync(string workFolderPath, Network network, SmartHeaderChain hashChain) { using (BenchmarkLogger.Measure()) { WorkFolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(workFolderPath), workFolderPath, trim: true); Network = Guard.NotNull(nameof(network), network); SmartHeaderChain = Guard.NotNull(nameof(hashChain), hashChain); var indexFilePath = Path.Combine(WorkFolderPath, "MatureIndex.dat"); MatureIndexFileManager = new DigestableSafeMutexIoManager(indexFilePath, digestRandomIndex: -1); var immatureIndexFilePath = Path.Combine(WorkFolderPath, "ImmatureIndex.dat"); ImmatureIndexFileManager = new DigestableSafeMutexIoManager(immatureIndexFilePath, digestRandomIndex: -1); StartingFilter = StartingFilters.GetStartingFilter(Network); StartingHeight = StartingFilter.Header.Height; ImmatureFilters = new List <FilterModel>(150); IndexLock = new AsyncLock(); using (await IndexLock.LockAsync().ConfigureAwait(false)) using (await MatureIndexFileManager.Mutex.LockAsync().ConfigureAwait(false)) using (await ImmatureIndexFileManager.Mutex.LockAsync().ConfigureAwait(false)) { IoHelpers.EnsureDirectoryExists(WorkFolderPath); await EnsureBackwardsCompatibilityAsync().ConfigureAwait(false); if (Network == Network.RegTest) { MatureIndexFileManager.DeleteMe(); // RegTest is not a global ledger, better to delete it. ImmatureIndexFileManager.DeleteMe(); } if (!MatureIndexFileManager.Exists()) { await MatureIndexFileManager.WriteAllLinesAsync(new[] { StartingFilter.ToLine() }).ConfigureAwait(false); } await InitializeFiltersAsync().ConfigureAwait(false); } } }
public async Task <FilterModel> RemoveLastFilterAsync(CancellationToken cancel) { FilterModel?filter = null; using (await IndexLock.LockAsync(cancel).ConfigureAwait(false)) { filter = ImmatureFilters.Last(); ImmatureFilters.RemoveLast(); if (SmartHeaderChain.TipHeight != filter.Header.Height) { throw new InvalidOperationException($"{nameof(SmartHeaderChain)} and {nameof(ImmatureFilters)} are not in sync."); } SmartHeaderChain.RemoveTip(); } Reorged?.Invoke(this, filter); AbandonedTasks.AddAndClearCompleted(TryCommitToFileAsync(TimeSpan.FromSeconds(3), cancel)); return(filter); }
private bool TryProcessFilter(FilterModel filter, bool enqueue) { try { if (IsWrongFilter(filter)) { return(false); } SmartHeaderChain.AppendTip(filter.Header); if (enqueue) { ImmatureFilters.Add(filter); } return(true); } catch (Exception ex) { Logger.LogError(ex); return(false); } }
public void GeneralHashChainTests() { var hashChain = new SmartHeaderChain(); // ASSERT PROPERTIES // Assert everything is default value. AssertEverythingDefault(hashChain); // ASSERT EVENTS // Assert some functions do not raise any events when default. Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashCount), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashesLeft), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.ServerTipHeight), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHash), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHeight), () => { // ASSERT FUNCTIONS // Assert RemoveLast does not modify nor throw anything when nothing is added. hashChain.RemoveLast(); AssertEverythingDefault(hashChain); })); // Assert the correct events are thrown and not thrown when applicable. var newServerHeight = hashChain.ServerTipHeight + 1; Assert.PropertyChanged(hashChain, nameof(hashChain.ServerTipHeight), // ASSERT FUNCTION // Assert update server height raises. () => hashChain.UpdateServerTipHeight(newServerHeight)); newServerHeight++; Assert.PropertyChanged(hashChain, nameof(hashChain.HashesLeft), // ASSERT FUNCTION // Assert update server height raises. () => hashChain.UpdateServerTipHeight(newServerHeight)); newServerHeight++; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashCount), // ASSERT FUNCTIONS // Assert update server height does not raise unnecessary events. () => hashChain.UpdateServerTipHeight(newServerHeight))); newServerHeight++; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHash), // ASSERT FUNCTIONS // Assert update server height does not raise unnecessary events. () => hashChain.UpdateServerTipHeight(newServerHeight))); newServerHeight++; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.TipHeight), // ASSERT FUNCTIONS // Assert update server height does not raise unnecessary events. () => hashChain.UpdateServerTipHeight(newServerHeight))); var sameServerheight = newServerHeight; Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.ServerTipHeight), // ASSERT FUNCTIONS // Assert update server height does not raise without actually changing. () => hashChain.UpdateServerTipHeight(sameServerheight))); Assert.Throws <PropertyChangedException>(() => Assert.PropertyChanged(hashChain, nameof(hashChain.HashesLeft), // ASSERT FUNCTIONS // Assert update server height does not raise without actually changing. () => hashChain.UpdateServerTipHeight(sameServerheight))); // ASSERT PROPERTIES Assert.Equal(0, hashChain.HashCount); var hashesLeft = sameServerheight; Assert.Equal((int)hashesLeft, hashChain.HashesLeft); Assert.Equal(hashesLeft, hashChain.ServerTipHeight); Assert.Null(hashChain.TipHash); Assert.Equal(0u, hashChain.TipHeight); }
public IndexStore(Network network, SmartHeaderChain hashChain) { Network = Guard.NotNull(nameof(network), network); SmartHeaderChain = Guard.NotNull(nameof(hashChain), hashChain); }