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();
            }
        }
        private void ConfigureRabbitMq(IServiceCollection services, ServiceProvider loggerServicesProvier)
        {
            var config = new RabbitMqConfig();

            Configuration.GetSection("RabbitMq").Bind(config);
            var factory = RabbitMqFactory.Create(config);

            var cardsConsumer = factory.CreateConsumer(Queues.Cards);
            var awaiter       = new EventsAwaiter("Cards", loggerServicesProvier.GetService <ILogger <EventsAwaiter> >());

            awaiter.BindConsumer(cardsConsumer);
            services.AddSingleton(awaiter);

            var publishers = new Dictionary <string, IPublisher>();

            publishers.Add(Queues.APIGateway, factory.CreatePublisher(Queues.APIGateway));
            publishers.Add(Queues.Accounts, factory.CreatePublisher(Queues.Accounts));
            publishers.Add(Queues.Transactions, factory.CreatePublisher(Queues.Transactions));
            var publishingRouter = new PublishingRouter(publishers);

            services.AddSingleton(publishingRouter);

            var servicesProvider = services.BuildServiceProvider();
            var cardsService     = servicesProvider.GetService <CardsService>();

            var consumingRouter = ConsumingRouter <CardsService> .Create(cardsService, publishingRouter, "Cards", loggerServicesProvier.GetService <ILogger <IConsumer> >());

            consumingRouter.LinkConsumer(cardsConsumer);
            services.AddSingleton(consumingRouter);
        }
Beispiel #3
0
 public CardsService(CardsRepository cardsRepository, ILogger <CardsService> logger, PublishingRouter publishingRouter, EventsAwaiter eventsAwaiter)
 {
     this.cardsRepository  = cardsRepository;
     this.logger           = logger;
     this.publishingRouter = publishingRouter;
     this.eventsAwaiter    = eventsAwaiter;
 }
 public CardController(ILogger <CardController> logger, Mapper mapper, PublishingRouter publishingRouter, EventsAwaiter eventsAwaiter)
 {
     this.logger           = logger;
     this.mapper           = mapper;
     this.publishingRouter = publishingRouter;
     this.eventsAwaiter    = eventsAwaiter;
 }
Beispiel #5
0
        public async Task TrustedNotifierNotifiesTxAsync()
        {
            var coreNode = await TestNodeBuilder.CreateAsync();

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

                var network = rpc.Network;

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

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

                var txNum             = 10;
                var txInvEventAwaiter = new EventsAwaiter <uint256>(
                    h => notifier.TransactionInv += h,
                    h => notifier.TransactionInv -= h,
                    txNum);

                var txEventAwaiter = new EventsAwaiter <SmartTransaction>(
                    h => notifier.Transaction += h,
                    h => notifier.Transaction -= 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 aht        = txInvEventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));
                var arrivedTxs = await txEventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));

                var arrivedHashes = await aht;

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

                foreach (var hash in arrivedHashes)
                {
                    Assert.Contains(hash, hashes);
                }
                foreach (var hash in arrivedTxs.Select(x => x.GetHash()))
                {
                    Assert.Contains(hash, hashes);
                }
            }
            finally
            {
                await coreNode.TryStopAsync();
            }
        }
Beispiel #6
0
        private void AddAwaiter(IServiceCollection services, RabbitMqFactory factory, ServiceProvider loggerServicesProvier)
        {
            var awaiter = new EventsAwaiter("APIGateway", loggerServicesProvier.GetService <ILogger <EventsAwaiter> >());

            var consumer = factory.CreateConsumer(Queues.APIGateway);

            awaiter.BindConsumer(consumer);

            services.AddSingleton(awaiter);
        }
        public async Task LongChainReorgAsync()
        {
            var chain = new ConcurrentChain(Network.RegTest);

            using var notifier = CreateNotifier(chain);

            var blockAwaiter = new EventsAwaiter <Block>(
                h => notifier.OnBlock += h,
                h => notifier.OnBlock -= h,
                11);

            var reorgAwaiter = new EventsAwaiter <uint256>(
                h => notifier.OnReorg += h,
                h => notifier.OnReorg -= h,
                3);

            await notifier.StartAsync(CancellationToken.None);

            await AddBlockAsync(chain);

            var forkPoint         = chain.Tip;
            var firstReorgedChain = new[]
            {
                await AddBlockAsync(chain, wait : false),
                await AddBlockAsync(chain)
            };

            chain.SetTip(forkPoint);
            var secondReorgedChain = new[]
            {
                await AddBlockAsync(chain, wait : false),
                await AddBlockAsync(chain, wait : false),
                await AddBlockAsync(chain)
            };

            chain.SetTip(secondReorgedChain[1]);
            await AddBlockAsync(chain, wait : false);
            await AddBlockAsync(chain, wait : false);
            await AddBlockAsync(chain, wait : false);
            await AddBlockAsync(chain, wait : false);
            await AddBlockAsync(chain);

            // Three blocks notifications
            await blockAwaiter.WaitAsync(TimeSpan.FromSeconds(2));

            // No reorg notifications
            var reorgedkBlock = await reorgAwaiter.WaitAsync(TimeSpan.FromSeconds(1));

            var expectedReorgedBlocks = firstReorgedChain.ToList().Concat(new[] { secondReorgedChain[2] });

            Assert.Subset(reorgedkBlock.ToHashSet(), expectedReorgedBlocks.Select(x => x.Header.GetHash()).ToHashSet());
            Assert.Equal(chain.Tip.HashBlock, notifier.BestBlockHash);

            await notifier.StopAsync(CancellationToken.None);
        }
Beispiel #8
0
        public async Task MempoolNotifiesAsync()
        {
            var coreNode = await TestNodeBuilder.CreateAsync();

            using var node = await coreNode.CreateP2pNodeAsync();

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

                var network      = rpc.Network;
                var bitcoinStore = new BitcoinStore();

                var dir = Path.Combine(Global.Instance.DataDir, EnvironmentHelpers.GetMethodName());
                await bitcoinStore.InitializeAsync(dir, network);

                node.Behaviors.Add(bitcoinStore.CreateMempoolBehavior());
                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
            {
                node.Disconnect();
                await coreNode.StopAsync();
            }
        }
        public async Task TrustedNotifierNotifiesTxAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync();

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

                var network = rpc.Network;

                var dir = Common.GetWorkDir();

                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();

                await coreNode.TryStopAsync();
            }
        }
        public async Task SuperFastNodeValidationAsync()
        {
            var chain = new ConcurrentChain(Network.RegTest);

            using var notifier = CreateNotifier(chain);
            var blockAwaiter = new EventsAwaiter <Block>(
                h => notifier.OnBlock += h,
                h => notifier.OnBlock -= h,
                144);

            await notifier.StartAsync(CancellationToken.None);

            var lastKnownBlock = await AddBlockAsync(chain);

            foreach (var i in Enumerable.Range(0, 200))
            {
                await AddBlockAsync(chain, wait : false);
            }
            await AddBlockAsync(chain, wait : true);

            notifier.TriggerRound();

            Assert.Equal(chain.Tip.HashBlock, notifier.BestBlockHash);

            var nofifiedBlocks = (await blockAwaiter.WaitAsync(TimeSpan.FromSeconds(1))).ToArray();

            var tip = chain.Tip;
            var pos = nofifiedBlocks.Length - 1;

            while (tip.HashBlock != nofifiedBlocks[pos].GetHash())
            {
                tip = tip.Previous;
            }

            while (pos >= 0)
            {
                Assert.Equal(tip.HashBlock, nofifiedBlocks[pos].GetHash());
                tip = tip.Previous;
                pos--;
            }

            await notifier.StopAsync(CancellationToken.None);
        }
        public async Task SimpleReorgAsync()
        {
            var chain = new ConcurrentChain(Network.RegTest);

            using var notifier = CreateNotifier(chain);

            var blockAwaiter = new EventsAwaiter <Block>(
                h => notifier.OnBlock += h,
                h => notifier.OnBlock -= h,
                5);

            var reorgAwaiter = new EventAwaiter <BlockHeader>(
                h => notifier.OnReorg += h,
                h => notifier.OnReorg -= h);

            await notifier.StartAsync(CancellationToken.None);

            await AddBlockAsync(chain);

            var forkPoint        = chain.Tip;
            var blockToBeReorged = await AddBlockAsync(chain);

            chain.SetTip(forkPoint);
            await AddBlockAsync(chain, wait : false);
            await AddBlockAsync(chain, wait : false);
            await AddBlockAsync(chain);

            notifier.TriggerRound();

            // Three blocks notifications
            await blockAwaiter.WaitAsync(TimeSpan.FromSeconds(2));

            // No reorg notifications
            var reorgedkBlock = await reorgAwaiter.WaitAsync(TimeSpan.FromSeconds(1));

            Assert.Equal(forkPoint.HashBlock, reorgedkBlock.HashPrevBlock);
            Assert.Equal(blockToBeReorged.HashBlock, reorgedkBlock.GetHash());
            Assert.Equal(chain.Tip.HashBlock, notifier.BestBlockHash);

            await notifier.StopAsync(CancellationToken.None);
        }
Beispiel #12
0
        public async Task BlockNotifierTestsAsync()
        {
            using var services = new HostedServices();
            var coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync(CancellationToken.None);

            try
            {
                var           rpc      = coreNode.RpcClient;
                BlockNotifier notifier = services.FirstOrDefault <BlockNotifier>();

                // Make sure we get notification for one block.
                var blockEventAwaiter = new EventAwaiter <Block>(
                    h => notifier.OnBlock += h,
                    h => notifier.OnBlock -= h);

                var hash  = (await rpc.GenerateAsync(1)).First();
                var block = await blockEventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));

                Assert.Equal(hash, block.GetHash());

                // Make sure we get notifications about 10 blocks created at the same time.
                var blockNum           = 10;
                var blockEventsAwaiter = new EventsAwaiter <Block>(
                    h => notifier.OnBlock += h,
                    h => notifier.OnBlock -= h,
                    blockNum);

                var hashes = (await rpc.GenerateAsync(blockNum)).ToArray();

                var arrivedBlocks = (await blockEventsAwaiter.WaitAsync(TimeSpan.FromSeconds(21))).ToArray();

                for (int i = 0; i < hashes.Length; i++)
                {
                    var expected = hashes[i];
                    var actual   = arrivedBlocks[i].GetHash();
                    Assert.Equal(expected, actual);
                }

                // Make sure we get reorg notifications.
                var reorgNum           = 3;
                var newBlockNum        = reorgNum + 1;
                var reorgEventsAwaiter = new EventsAwaiter <uint256>(
                    h => notifier.OnReorg += h,
                    h => notifier.OnReorg -= h,
                    reorgNum);
                blockEventsAwaiter         = new EventsAwaiter <Block>(
                    h => notifier.OnBlock += h,
                    h => notifier.OnBlock -= h,
                    newBlockNum);

                var reorgedHashes = hashes.TakeLast(reorgNum).ToArray();
                await rpc.InvalidateBlockAsync(reorgedHashes[0]);

                var newHashes = (await rpc.GenerateAsync(newBlockNum)).ToArray();

                var reorgedHeaders = (await reorgEventsAwaiter.WaitAsync(TimeSpan.FromSeconds(21))).ToArray();
                var newBlocks      = (await blockEventsAwaiter.WaitAsync(TimeSpan.FromSeconds(21))).ToArray();

                reorgedHashes = reorgedHashes.Reverse().ToArray();
                for (int i = 0; i < reorgedHashes.Length; i++)
                {
                    var expected = reorgedHashes[i];
                    var actual   = reorgedHeaders[i];
                    Assert.Equal(expected, actual);
                }

                for (int i = 0; i < newHashes.Length; i++)
                {
                    var expected = newHashes[i];
                    var actual   = newBlocks[i].GetHash();
                    Assert.Equal(expected, actual);
                }
            }
            finally
            {
                await services.StopAllAsync(CancellationToken.None);

                await coreNode.TryStopAsync();
            }
        }
        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 { })
 public ReportsDataFetcher(PublishingRouter publishingRouter, EventsAwaiter eventsAwaiter)
 {
     this.publishingRouter = publishingRouter;
     this.eventsAwaiter    = eventsAwaiter;
 }
        public async Task MempoolNotifiesAsync()
        {
            using var services = new HostedServices();
            CoreNode coreNode = await TestNodeBuilder.CreateAsync(services);

            await services.StartAllAsync();

            BitcoinStore?bitcoinStore = null;

            using var node = await coreNode.CreateNewP2pNodeAsync();

            try
            {
                string dir              = Common.GetWorkDir();
                var    network          = coreNode.Network;
                var    rpc              = coreNode.RpcClient;
                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);

                // Construct BitcoinStore.
                bitcoinStore = new BitcoinStore(indexStore, transactionStore, mempoolService, blocks);
                await bitcoinStore.InitializeAsync();

                await rpc.GenerateAsync(blockCount : 101);

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

                BitcoinWitPubKeyAddress address = new Key().PubKey.GetSegwitAddress(network);

                // Number of transactions to send.
                const int TransactionsCount = 10;

                var eventAwaiter = new EventsAwaiter <SmartTransaction>(
                    subscribe: h => mempoolService.TransactionReceived   += h,
                    unsubscribe: h => mempoolService.TransactionReceived -= h,
                    count: TransactionsCount);

                var        txHashesList = new List <Task <uint256> >();
                IRPCClient rpcBatch     = rpc.PrepareBatch();

                // Add to the batch 10 RPC commands: Send 1 coin to the same address.
                for (int i = 0; i < TransactionsCount; i++)
                {
                    txHashesList.Add(rpcBatch.SendToAddressAsync(address, Money.Coins(1)));
                }

                // Publish the RPC batch.
                Task rpcBatchTask = rpcBatch.SendBatchAsync();

                // Wait until the mempool service receives all the sent transactions.
                IEnumerable <SmartTransaction> mempoolSmartTxs = await eventAwaiter.WaitAsync(TimeSpan.FromSeconds(30));

                await rpcBatchTask;

                // Collect all the transaction hashes of the sent transactions.
                uint256[] hashes = await Task.WhenAll(txHashesList);

                // Check that all the received transaction hashes are in the set of sent transaction hashes.
                foreach (SmartTransaction tx in mempoolSmartTxs)
                {
                    Assert.Contains(tx.GetHash(), hashes);
                }
            }
            finally
            {
                if (bitcoinStore is { } store)
                {
                    await store.DisposeAsync();
                }
                await services.StopAllAsync();

                node.Disconnect();
                await coreNode.TryStopAsync();
            }
        }
Beispiel #16
0
        public async Task ReorgTestAsync()
        {
            (string password, IRPCClient rpc, Network network, _, _, BitcoinStore bitcoinStore, Backend.Global global) = await Common.InitializeTestEnvironmentAsync(RegTestFixture, 1);

            var keyManager = KeyManager.CreateNew(out _, password, network);

            // Mine some coins, make a few bech32 transactions then make it confirm.
            await rpc.GenerateAsync(1);

            var key = keyManager.GenerateNewKey(SmartLabel.Empty, KeyState.Clean, isInternal: false);
            var tx2 = await rpc.SendToAddressAsync(key.GetP2wpkhAddress(network), Money.Coins(0.1m));

            key = keyManager.GenerateNewKey(SmartLabel.Empty, KeyState.Clean, isInternal: false);
            var tx3 = await rpc.SendToAddressAsync(key.GetP2wpkhAddress(network), Money.Coins(0.1m));

            var tx4 = await rpc.SendToAddressAsync(key.GetP2pkhAddress(network), Money.Coins(0.1m));

            var tx5 = await rpc.SendToAddressAsync(key.GetP2shOverP2wpkhAddress(network), Money.Coins(0.1m));

            var tx1 = await rpc.SendToAddressAsync(key.GetP2wpkhAddress(network), Money.Coins(0.1m), replaceable : true);

            await rpc.GenerateAsync(2);             // Generate two, so we can test for two reorg

            var node = RegTestFixture.BackendRegTestNode;

            using HttpClientFactory httpClientFactory = new(torEndPoint : null, backendUriGetter : () => new Uri(RegTestFixture.BackendEndPoint));
            WasabiSynchronizer synchronizer = new(bitcoinStore, httpClientFactory);

            try
            {
                synchronizer.Start(requestInterval: TimeSpan.FromSeconds(3), 1000);

                var reorgAwaiter = new EventsAwaiter <FilterModel>(
                    h => bitcoinStore.IndexStore.Reorged += h,
                    h => bitcoinStore.IndexStore.Reorged -= h,
                    2);

                // Test initial synchronization.
                await WaitForIndexesToSyncAsync(global, TimeSpan.FromSeconds(90), bitcoinStore);

                var tip = await rpc.GetBestBlockHashAsync();

                Assert.Equal(tip, bitcoinStore.SmartHeaderChain.TipHash);
                var tipBlock = await rpc.GetBlockHeaderAsync(tip);

                Assert.Equal(tipBlock.HashPrevBlock, bitcoinStore.SmartHeaderChain.GetChain().Select(x => x.header.BlockHash).ToArray()[bitcoinStore.SmartHeaderChain.HashCount - 2]);

                // Test synchronization after fork.
                await rpc.InvalidateBlockAsync(tip);                 // Reorg 1

                tip = await rpc.GetBestBlockHashAsync();

                await rpc.InvalidateBlockAsync(tip);                 // Reorg 2

                var tx1bumpRes = await rpc.BumpFeeAsync(tx1);        // RBF it

                await rpc.GenerateAsync(5);
                await WaitForIndexesToSyncAsync(global, TimeSpan.FromSeconds(90), bitcoinStore);

                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.SmartHeaderChain.TipHash);

                var filterList = new List <FilterModel>();
                await bitcoinStore.IndexStore.ForeachFiltersAsync(async x =>
                {
                    filterList.Add(x);
                    await Task.CompletedTask;
                },
                                                                  new Height(0));

                var filterTip = filterList.Last();
                Assert.Equal(tip, filterTip.Header.BlockHash);

                // Test filter block hashes are correct after fork.
                var blockCountIncludingGenesis = await rpc.GetBlockCountAsync() + 1;

                filterList.Clear();
                await bitcoinStore.IndexStore.ForeachFiltersAsync(async x =>
                {
                    filterList.Add(x);
                    await Task.CompletedTask;
                },
                                                                  new Height(0));

                FilterModel[] filters = filterList.ToArray();
                for (int i = 0; i < blockCountIncludingGenesis; i++)
                {
                    var expectedHash = await rpc.GetBlockHashAsync(i);

                    var filter = filters[i];
                    Assert.Equal(i, (int)filter.Header.Height);
                    Assert.Equal(expectedHash, filter.Header.BlockHash);
                    if (i < 101)                     // Later other tests may fill the filter.
                    {
                        Assert.Equal(IndexBuilderService.CreateDummyEmptyFilter(expectedHash).ToString(), filter.Filter.ToString());
                    }
                }

                // Test the serialization, too.
                tip = await rpc.GetBestBlockHashAsync();

                var blockHash = tip;
                for (var i = 0; i < hashes.Length; i++)
                {
                    var block = await rpc.GetBlockHeaderAsync(blockHash);

                    Assert.Equal(blockHash, hashes[hashes.Length - i - 1]);
                    blockHash = block.HashPrevBlock;
                }

                // Assert reorg happened exactly as many times as we reorged.
                await reorgAwaiter.WaitAsync(TimeSpan.FromSeconds(10));
            }
            finally
            {
                await synchronizer.StopAsync();
            }
        }
 public ReportController(ILogger <ReportController> logger, EventsAwaiter eventsAwaiter, PublishingRouter publishingRouter)
 {
     this.logger           = logger;
     this.eventsAwaiter    = eventsAwaiter;
     this.publishingRouter = publishingRouter;
 }