Exemple #1
0
        public async Task EnumerateOrdersByAccessAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            await CleanupWalletDirectoriesAsync(baseDir);

            var walletDirectories = new WalletDirectories(baseDir);

            var walletFile1 = Path.Combine(walletDirectories.WalletsDir, $"FooWallet1.json");
            await File.Create(walletFile1).DisposeAsync();

            File.SetLastAccessTimeUtc(walletFile1, new DateTime(2005, 1, 1, 1, 1, 1, DateTimeKind.Utc));

            var walletFile2 = Path.Combine(walletDirectories.WalletsDir, $"FooWallet2.json");
            await File.Create(walletFile2).DisposeAsync();

            File.SetLastAccessTimeUtc(walletFile2, new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc));

            var walletFile3 = Path.Combine(walletDirectories.WalletsDir, $"FooWallet3.json");
            await File.Create(walletFile3).DisposeAsync();

            File.SetLastAccessTimeUtc(walletFile3, new DateTime(2010, 1, 1, 1, 1, 1, DateTimeKind.Utc));

            var orderedWallets = new[] { walletFile3, walletFile1, walletFile2 };

            Assert.Equal(orderedWallets, walletDirectories.EnumerateWalletFiles().Select(x => x.FullName));
        }
Exemple #2
0
        public async Task GetNextWalletTestAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            await CleanupWalletDirectoriesAsync(baseDir);

            var walletDirectories = new WalletDirectories(baseDir);

            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));

            Assert.Equal("Random Wallet", walletDirectories.GetNextWalletName());
            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet.json"));
            Assert.Equal("Random Wallet 2", walletDirectories.GetNextWalletName());
            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 2.json"));
            Assert.Equal("Random Wallet 4", walletDirectories.GetNextWalletName());

            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 4.dat"));
            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 4"));
            Assert.Equal("Random Wallet 4", walletDirectories.GetNextWalletName());

            File.Delete(Path.Combine(walletDirectories.WalletsDir, "Random Wallet.json"));
            File.Delete(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));
            Assert.Equal("Random Wallet", walletDirectories.GetNextWalletName());
            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet.json"));
            Assert.Equal("Random Wallet 3", walletDirectories.GetNextWalletName());
            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));
            File.Delete(Path.Combine(walletDirectories.WalletsDir, "Random Wallet 3.json"));

            Assert.Equal("Foo", walletDirectories.GetNextWalletName("Foo"));
            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Foo.json"));
            Assert.Equal("Foo 2", walletDirectories.GetNextWalletName("Foo"));
            IoHelpers.CreateOrOverwriteFile(Path.Combine(walletDirectories.WalletsDir, "Foo 2.json"));
        }
Exemple #3
0
        public async Task EnumerateFilesAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            await CleanupWalletDirectoriesAsync(baseDir);

            var walletDirectories = new WalletDirectories(baseDir);

            var       wallets         = new List <string>();
            var       walletBackups   = new List <string>();
            const int NumberOfWallets = 4;

            for (int i = 0; i < NumberOfWallets; i++)
            {
                var walletFile = Path.Combine(walletDirectories.WalletsDir, $"FooWallet{i}.json");
                var dummyFile  = Path.Combine(walletDirectories.WalletsDir, $"FooWallet{i}.dummy");
                var backupFile = Path.Combine(walletDirectories.WalletsBackupDir, $"FooWallet{i}.json");

                await File.Create(walletFile).DisposeAsync();

                await File.Create(dummyFile).DisposeAsync();

                await File.Create(backupFile).DisposeAsync();

                wallets.Add(walletFile);
                walletBackups.Add(backupFile);
            }

            Assert.True(wallets.ToHashSet().SetEquals(walletDirectories.EnumerateWalletFiles().Select(x => x.FullName).ToHashSet()));
            Assert.True(wallets.Concat(walletBackups).ToHashSet().SetEquals(walletDirectories.EnumerateWalletFiles(true).Select(x => x.FullName).ToHashSet()));
        }
Exemple #4
0
        public async Task IoManagerTestsAsync()
        {
            var file1 = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName(), $"file1.dat");
            var file2 = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName(), $"file2.dat");

            Random        random = new Random();
            List <string> lines  = new List <string>();

            for (int i = 0; i < 1000; i++)
            {
                string line = RandomString.AlphaNumeric(100);

                lines.Add(line);
            }

            // Single thread file operations.

            DigestableSafeMutexIoManager ioman1 = new DigestableSafeMutexIoManager(file1);

            // Delete the file if Exist.

            ioman1.DeleteMe();
            Assert.False(ioman1.Exists());

            Assert.False(File.Exists(ioman1.DigestFilePath));

            // Write the data to the file.

            await ioman1.WriteAllLinesAsync(lines);

            Assert.True(ioman1.Exists());

            // Check if the digest file is created.

            Assert.True(File.Exists(ioman1.DigestFilePath));
Exemple #5
0
        public async Task CanLoadLegalDocsAsync()
        {
            var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName());

            if (Directory.Exists(dir))
            {
                Directory.Delete(dir, true);
            }

            var res = LegalDocuments.TryLoadAgreed(dir);

            Assert.Null(res);
            var legalDir = Assert.Single(Directory.GetDirectories(dir));

            var version = new Version(1, 1);

            // Deletes them if multiple legal docs found.
            var candidate = File.Create(Path.Combine(legalDir, $"{version}.txt"));
            await candidate.DisposeAsync();

            res = LegalDocuments.TryLoadAgreed(dir);
            Assert.NotNull(res);
            Assert.Single(Directory.GetFiles(legalDir));
            Assert.Empty(Directory.GetDirectories(legalDir));
            Assert.Equal(version, res.Version);
            Assert.Equal(Path.Combine(legalDir, $"{version}.txt"), res.FilePath);
        }
Exemple #6
0
        public async Task LeavesTrashAloneAsync()
        {
            var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName());

            if (Directory.Exists(dir))
            {
                Directory.Delete(dir, true);
            }

            var res = LegalDocuments.TryLoadAgreed(dir);

            Assert.Null(res);
            var legalDir = Assert.Single(Directory.GetDirectories(dir));

            // Leaves one trash alone.
            var trash1 = File.Create(Path.Combine(legalDir, "foo"));
            await trash1.DisposeAsync();

            res = LegalDocuments.TryLoadAgreed(dir);
            Assert.Null(res);
            Assert.Single(Directory.GetFiles(legalDir));
            Assert.Empty(Directory.GetDirectories(legalDir));

            // Leaves 3 trash alone.
            var trash2 = File.Create(Path.Combine(legalDir, "foo.txt"));
            var trash3 = File.Create(Path.Combine(legalDir, "foo2"));
            await trash2.DisposeAsync();

            await trash3.DisposeAsync();

            res = LegalDocuments.TryLoadAgreed(dir);
            Assert.Null(res);
            Assert.Equal(3, Directory.GetFiles(legalDir).Length);
            Assert.Empty(Directory.GetDirectories(legalDir));
        }
Exemple #7
0
        public async Task CanSerializeFileAsync()
        {
            var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName());

            if (Directory.Exists(dir))
            {
                Directory.Delete(dir, true);
            }

            string filePath = Path.Combine(dir, "1.1.txt");
            var    legal    = new LegalDocuments(filePath);

            Assert.False(File.Exists(filePath));
            await legal.ToFileAsync("bar");

            Assert.True(File.Exists(filePath));

            string filePath2 = Path.Combine(dir, "1.2.txt");
            var    legal2    = new LegalDocuments(filePath2);

            Assert.True(File.Exists(filePath));
            Assert.False(File.Exists(filePath2));
            await legal2.ToFileAsync("bar");

            Assert.False(File.Exists(filePath));
            Assert.True(File.Exists(filePath2));
        }
        public async Task MempoolNotifiesAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            using var node = await coreNode.CreateNewP2pNodeAsync();

            try
            {
                var network          = coreNode.Network;
                var rpc              = coreNode.RpcClient;
                var dir              = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());
                var indexStore       = new IndexStore(Path.Combine(dir, "indexStore"), network, new SmartHeaderChain());
                var transactionStore = new AllTransactionStore(Path.Combine(dir, "transactionStore"), network);
                var mempoolService   = new MempoolService();
                var blocks           = new FileSystemBlockRepository(Path.Combine(dir, "blocks"), network);
                var bitcoinStore     = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks);
                await bitcoinStore.InitializeAsync();

                await rpc.GenerateAsync(101);

                node.Behaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior());
                node.VersionHandshake();

                var addr = new Key().PubKey.GetSegwitAddress(network);

                var txNum        = 10;
                var eventAwaiter = new EventsAwaiter <SmartTransaction>(
                    h => bitcoinStore.MempoolService.TransactionReceived += h,
                    h => bitcoinStore.MempoolService.TransactionReceived -= h,
                    txNum);

                var txTasks = new List <Task <uint256> >();
                var batch   = rpc.PrepareBatch();
                for (int i = 0; i < txNum; i++)
                {
                    txTasks.Add(batch.SendToAddressAsync(addr, Money.Coins(1)));
                }
                var batchTask = batch.SendBatchAsync();

                var stxs = await eventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));

                await batchTask;
                var   hashes = await Task.WhenAll(txTasks);

                foreach (var stx in stxs)
                {
                    Assert.Contains(stx.GetHash(), hashes);
                }
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                node.Disconnect();
                await coreNode.TryStopAsync();
            }
        }
Exemple #9
0
        public async Task CorrestWalletDirectoryNameAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            (string walletsPath, string walletsBackupPath) = await CleanupWalletDirectoriesAsync(baseDir);

            var walletDirectories = new WalletDirectories($" {baseDir} ");

            Assert.Equal(baseDir, walletDirectories.WorkDir);
            Assert.Equal(walletsPath, walletDirectories.WalletsDir);
            Assert.Equal(walletsBackupPath, walletDirectories.WalletsBackupDir);
        }
Exemple #10
0
        public async Task TrustedNotifierNotifiesTxAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var rpc = coreNode.RpcClient;
                await rpc.GenerateAsync(101);

                var network = rpc.Network;

                var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

                var addr     = new Key().PubKey.GetSegwitAddress(network);
                var notifier = coreNode.MempoolService;

                var txNum          = 10;
                var txEventAwaiter = new EventsAwaiter <SmartTransaction>(
                    h => notifier.TransactionReceived += h,
                    h => notifier.TransactionReceived -= h,
                    txNum);

                var txTasks = new List <Task <uint256> >();
                var batch   = rpc.PrepareBatch();
                for (int i = 0; i < txNum; i++)
                {
                    txTasks.Add(batch.SendToAddressAsync(addr, Money.Coins(1)));
                }
                var batchTask = batch.SendBatchAsync();

                var arrivedTxs = await txEventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));

                await batchTask;
                var   hashes = await Task.WhenAll(txTasks);

                foreach (var hash in arrivedTxs.Select(x => x.GetHash()))
                {
                    Assert.Contains(hash, hashes);
                }
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
Exemple #11
0
        public async Task ServesWalletFilesAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            await CleanupWalletDirectoriesAsync(baseDir);

            var    walletDirectories = new WalletDirectories(baseDir);
            string walletName        = "FooWallet.json";

            (string walletPath, string walletBackupPath) = walletDirectories.GetWalletFilePaths(walletName);

            Assert.Equal(Path.Combine(walletDirectories.WalletsDir, walletName), walletPath);
            Assert.Equal(Path.Combine(walletDirectories.WalletsBackupDir, walletName), walletBackupPath);
        }
Exemple #12
0
        public async Task CreatesWalletDirectoriesAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            (string walletsPath, string walletsBackupPath) = await CleanupWalletDirectoriesAsync(baseDir);

            new WalletDirectories(baseDir);
            Assert.True(Directory.Exists(walletsPath));
            Assert.True(Directory.Exists(walletsBackupPath));

            // Testing what happens if the directories are already exist.
            new WalletDirectories(baseDir);
            Assert.True(Directory.Exists(walletsPath));
            Assert.True(Directory.Exists(walletsBackupPath));
        }
Exemple #13
0
        public async Task EnumerateMissingDirAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            (string walletsPath, string walletsBackupPath) = await CleanupWalletDirectoriesAsync(baseDir);

            var walletDirectories = new WalletDirectories(baseDir);

            Assert.Empty(walletDirectories.EnumerateWalletFiles());
            Directory.Delete(walletsBackupPath);
            Assert.Empty(walletDirectories.EnumerateWalletFiles());
            Directory.Delete(walletsPath);
            Assert.Empty(walletDirectories.EnumerateWalletFiles());
            Directory.Delete(baseDir);
            Assert.Empty(walletDirectories.EnumerateWalletFiles());
        }
Exemple #14
0
        public void CantLoadNotAgreed()
        {
            var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName());

            if (Directory.Exists(dir))
            {
                Directory.Delete(dir, true);
            }

            var res = LegalDocuments.TryLoadAgreed(dir);

            Assert.Null(res);
            Assert.True(Directory.Exists(dir));
            Assert.Empty(Directory.GetFiles(dir));
            var legalDir = Assert.Single(Directory.GetDirectories(dir));

            Assert.Empty(Directory.GetFiles(legalDir));
            Assert.Empty(Directory.GetDirectories(legalDir));
        }
Exemple #15
0
        public async Task ResolvesConflictsAsync()
        {
            var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName());

            if (Directory.Exists(dir))
            {
                Directory.Delete(dir, true);
            }

            var res = LegalDocuments.TryLoadAgreed(dir);

            Assert.Null(res);
            var legalDir = Assert.Single(Directory.GetDirectories(dir));

            // Deletes them if multiple legal docs found.
            var candidate1 = File.Create(Path.Combine(legalDir, "1.1.txt"));
            var candidate2 = File.Create(Path.Combine(legalDir, "1.2.txt"));
            await candidate1.DisposeAsync();

            await candidate2.DisposeAsync();

            res = LegalDocuments.TryLoadAgreed(dir);
            Assert.Null(res);
            Assert.Empty(Directory.GetFiles(legalDir));
            Assert.Empty(Directory.GetDirectories(legalDir));

            // Only the candidates are deleted.
            var trash = File.Create(Path.Combine(legalDir, "1.txt"));

            candidate1 = File.Create(Path.Combine(legalDir, "1.1.txt"));
            candidate2 = File.Create(Path.Combine(legalDir, "1.2.txt"));
            await trash.DisposeAsync();

            await candidate1.DisposeAsync();

            await candidate2.DisposeAsync();

            res = LegalDocuments.TryLoadAgreed(dir);
            Assert.Null(res);
            Assert.Single(Directory.GetFiles(legalDir));
            Assert.Empty(Directory.GetDirectories(legalDir));
        }
Exemple #16
0
        public void CanSerialize()
        {
            string password = "******";

            var filePath = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName(), "Wallet.json");

            DeleteFileAndDirectoryIfExists(filePath);

            Logger.TurnOff();
            Assert.Throws <FileNotFoundException>(() => KeyManager.FromFile(filePath));
            Logger.TurnOn();

            var manager = KeyManager.CreateNew(out _, password, filePath);

            KeyManager.FromFile(filePath);

            manager.ToFile();

            manager.ToFile();             // assert it does not throw

            var random = new Random();

            for (int i = 0; i < 1000; i++)
            {
                var isInternal = random.Next(2) == 0;
                var label      = RandomString.AlphaNumeric(21);
                var keyState   = (KeyState)random.Next(3);
                manager.GenerateNewKey(label, keyState, isInternal, toFile: false);
            }
            manager.ToFile();

            Assert.True(File.Exists(filePath));

            var sameManager = KeyManager.FromFile(filePath);

            Assert.Equal(manager.ChainCode, sameManager.ChainCode);
            Assert.Equal(manager.EncryptedSecret, sameManager.EncryptedSecret);
            Assert.Equal(manager.ExtPubKey, sameManager.ExtPubKey);

            DeleteFileAndDirectoryIfExists(filePath);
        }
Exemple #17
0
        public async Task GetNextWalletTestAsync()
        {
            var baseDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName(), EnvironmentHelpers.GetMethodName());

            await CleanupWalletDirectoriesAsync(baseDir);

            var walletDirectories = new WalletDirectories(baseDir);

            Assert.Equal("Wallet0", walletDirectories.GetNextWalletName());

            await File.Create(Path.Combine(walletDirectories.WalletsDir, $"Wallet0.json")).DisposeAsync();

            await File.Create(Path.Combine(walletDirectories.WalletsDir, $"Wallet1.json")).DisposeAsync();

            await File.Create(Path.Combine(walletDirectories.WalletsDir, $"Wallet3.json")).DisposeAsync();

            // This should not matter.
            await File.Create(Path.Combine(walletDirectories.WalletsBackupDir, $"Wallet2.json")).DisposeAsync();

            Assert.Equal("Wallet2", walletDirectories.GetNextWalletName());

            Assert.Equal("Foo0", walletDirectories.GetNextWalletName("Foo"));
        }
        public async Task TestServicesAsync(string networkString)
        {
            await RuntimeParams.LoadAsync();

            var network          = Network.GetNetwork(networkString);
            var blocksToDownload = new List <uint256>();

            if (network == Network.Main)
            {
                blocksToDownload.Add(new uint256("00000000000000000037c2de35bd85f3e57f14ddd741ce6cee5b28e51473d5d0"));
                blocksToDownload.Add(new uint256("000000000000000000115315a43cb0cdfc4ea54a0e92bed127f4e395e718d8f9"));
                blocksToDownload.Add(new uint256("00000000000000000011b5b042ad0522b69aae36f7de796f563c895714bbd629"));
            }
            else if (network == Network.TestNet)
            {
                blocksToDownload.Add(new uint256("0000000097a664c4084b49faa6fd4417055cb8e5aac480abc31ddc57a8208524"));
                blocksToDownload.Add(new uint256("000000009ed5b82259ecd2aa4cd1f119db8da7a70e7ea78d9c9f603e01f93bcc"));
                blocksToDownload.Add(new uint256("00000000e6da8c2da304e9f5ad99c079df2c3803b49efded3061ecaf206ddc66"));
            }
            else
            {
                throw new NotSupportedNetworkException(network);
            }
            var dataDir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetCallerFileName());

            BitcoinStore bitcoinStore = new BitcoinStore();
            await bitcoinStore.InitializeAsync(Path.Combine(dataDir, EnvironmentHelpers.GetMethodName()), network);

            var            addressManagerFolderPath = Path.Combine(dataDir, "AddressManager");
            var            addressManagerFilePath   = Path.Combine(addressManagerFolderPath, $"AddressManager{network}.dat");
            var            blocksFolderPath         = Path.Combine(dataDir, "Blocks", network.ToString());
            var            connectionParameters     = new NodeConnectionParameters();
            AddressManager addressManager           = null;

            try
            {
                addressManager = await NBitcoinHelpers.LoadAddressManagerFromPeerFileAsync(addressManagerFilePath);

                Logger.LogInfo($"Loaded {nameof(AddressManager)} from `{addressManagerFilePath}`.");
            }
            catch (DirectoryNotFoundException)
            {
                addressManager = new AddressManager();
            }
            catch (FileNotFoundException)
            {
                addressManager = new AddressManager();
            }
            catch (OverflowException)
            {
                File.Delete(addressManagerFilePath);
                addressManager = new AddressManager();
            }
            catch (FormatException)
            {
                File.Delete(addressManagerFilePath);
                addressManager = new AddressManager();
            }

            connectionParameters.TemplateBehaviors.Add(new AddressManagerBehavior(addressManager));
            connectionParameters.TemplateBehaviors.Add(bitcoinStore.CreateUntrustedP2pBehavior());

            using var nodes = new NodesGroup(network, connectionParameters, requirements: Constants.NodeRequirements);

            KeyManager           keyManager    = KeyManager.CreateNew(out _, "password");
            WasabiSynchronizer   syncer        = new WasabiSynchronizer(network, bitcoinStore, new Uri("http://localhost:12345"), Global.Instance.TorSocks5Endpoint);
            ServiceConfiguration serviceConfig = new ServiceConfiguration(50, 2, 21, 50, new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(Constants.DefaultDustThreshold));
            CachedBlockProvider  blockProvider = new CachedBlockProvider(
                new P2pBlockProvider(nodes, null, syncer, serviceConfig, network),
                new FileSystemBlockRepository(blocksFolderPath, network));

            using Wallet wallet = Wallet.CreateAndRegisterServices(
                      network,
                      bitcoinStore,
                      keyManager,
                      syncer,
                      nodes,
                      dataDir,
                      new ServiceConfiguration(50, 2, 21, 50, new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(Constants.DefaultDustThreshold)),
                      syncer,
                      blockProvider);
            Assert.True(Directory.Exists(blocksFolderPath));

            try
            {
                var mempoolTransactionAwaiter = new EventsAwaiter <SmartTransaction>(
                    h => bitcoinStore.MempoolService.TransactionReceived += h,
                    h => bitcoinStore.MempoolService.TransactionReceived -= h,
                    3);

                var nodeConnectionAwaiter = new EventsAwaiter <NodeEventArgs>(
                    h => nodes.ConnectedNodes.Added += h,
                    h => nodes.ConnectedNodes.Added -= h,
                    3);

                nodes.Connect();

                var downloadTasks = new List <Task <Block> >();
                using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(4));
                foreach (var hash in blocksToDownload)
                {
                    downloadTasks.Add(blockProvider.GetBlockAsync(hash, cts.Token));
                }

                await nodeConnectionAwaiter.WaitAsync(TimeSpan.FromMinutes(3));

                var i         = 0;
                var hashArray = blocksToDownload.ToArray();
                foreach (var block in await Task.WhenAll(downloadTasks))
                {
                    Assert.True(File.Exists(Path.Combine(blocksFolderPath, hashArray[i].ToString())));
                    i++;
                }

                await mempoolTransactionAwaiter.WaitAsync(TimeSpan.FromMinutes(1));
            }
            finally
            {
                // So next test will download the block.
                foreach (var hash in blocksToDownload)
                {
                    await blockProvider.BlockRepository.RemoveAsync(hash, CancellationToken.None);
                }
                if (wallet is { })