public async Task Set_BestChain_Success()
        {
            BestChainFoundEventData eventData = null;

            _eventBus.Subscribe <BestChainFoundEventData>(d =>
            {
                eventData = d;
                return(Task.CompletedTask);
            });

            var chain = await _fullBlockchainService.GetChainAsync();

            chain.BestChainHeight.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().Height);
            chain.BestChainHash.ShouldBe(_kernelTestHelper.BestBranchBlockList.Last().GetHash());

            await _fullBlockchainService.SetBestChainAsync(chain, chain.LongestChainHeight, chain.LongestChainHash);

            chain = await _fullBlockchainService.GetChainAsync();

            chain.BestChainHeight.ShouldBe(_kernelTestHelper.LongestBranchBlockList.Last().Height);
            chain.BestChainHash.ShouldBe(_kernelTestHelper.LongestBranchBlockList.Last().GetHash());

            eventData.ShouldNotBeNull();
            eventData.BlockHash.ShouldBe(chain.BestChainHash);
            eventData.BlockHeight.ShouldBe(chain.BestChainHeight);
        }
Example #2
0
        public async Task Should_Trigger_Domain_Events_For_Aggregate_Root()
        {
            //Arrange

            var isTriggered = false;

            LocalEventBus.Subscribe <PersonNameChangedEvent>(data =>
            {
                data.OldName.ShouldBe("Douglas");
                data.Person.Name.ShouldBe("Douglas-Changed");
                isTriggered = true;
                return(Task.CompletedTask);
            });

            //Act

            await WithUnitOfWorkAsync(async() =>
            {
                var dougles = PersonRepository.Single(b => b.Name == "Douglas");
                dougles.ChangeName("Douglas-Changed");
                await PersonRepository.UpdateAsync(dougles);
            });

            //Assert

            isTriggered.ShouldBeTrue();
        }
        public async Task HandleEvent_Test()
        {
            var eventData = new PeerConnectedEventData
                            (
                new NodeInfo {
                Endpoint = "127.0.0.1:1234", Pubkey = ByteString.CopyFromUtf8("Pubkey")
            },
                HashHelper.ComputeFrom("BestChainHash"),
                100
                            );

            AnnouncementReceivedEventData announcementEventData = null;

            _eventBus.Subscribe <AnnouncementReceivedEventData>(d =>
            {
                announcementEventData = d;
                return(Task.CompletedTask);
            });

            await _peerConnectedEventHandler.HandleEventAsync(eventData);

            var nodes = await _peerDiscoveryService.GetNodesAsync(1);

            nodes.Nodes[0].ShouldBe(eventData.NodeInfo);

            announcementEventData.ShouldNotBeNull();
            announcementEventData.Announce.BlockHash.ShouldBe(eventData.BestChainHash);
            announcementEventData.Announce.BlockHeight.ShouldBe(eventData.BestChainHeight);
            announcementEventData.SenderPubKey.ShouldBe(eventData.NodeInfo.Pubkey.ToHex());
        }
Example #4
0
        public async Task Start_ShouldLaunch_NetInitEvent()
        {
            NetworkInitializedEvent eventData = null;

            _eventBus.Subscribe <NetworkInitializedEvent>(ed =>
            {
                eventData = ed;
                return(Task.CompletedTask);
            });

            await _networkServer.StartAsync();

            await _networkServer.StopAsync();

            eventData.ShouldNotBeNull();
        }
        public async Task ValidateTransactionTest()
        {
            TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null;

            _eventBus.Subscribe <TransactionValidationStatusChangedEvent>(d =>
            {
                transactionValidationStatusChangedEventData = d;
                return(Task.CompletedTask);
            });

            var kernelTestHelper = GetRequiredService <KernelTestHelper>();
            var transaction      = kernelTestHelper.GenerateTransaction();

            var result =
                await _transactionMethodValidationProvider.ValidateTransactionAsync(transaction, await _kernelTestHelper.GetChainContextAsync());

            result.ShouldBeTrue();

            transactionValidationStatusChangedEventData.ShouldBeNull();

            transaction.MethodName = "View";

            result =
                await _transactionMethodValidationProvider.ValidateTransactionAsync(transaction, await _kernelTestHelper.GetChainContextAsync());

            result.ShouldBeFalse();

            transactionValidationStatusChangedEventData.ShouldNotBeNull();
            transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed);
            transactionValidationStatusChangedEventData.Error.ShouldBe("View transaction is not allowed.");
        }
Example #6
0
        public async Task Announce_ShouldPublishEvent_Test()
        {
            AnnouncementReceivedEventData received = null;

            _eventBus.Subscribe <AnnouncementReceivedEventData>(a =>
            {
                received = a;
                return(Task.CompletedTask);
            });

            await _service.SendAnnouncement(null, BuildServerCallContext());

            Assert.Null(received);

            var pubkey   = _peerPool.GetPeers(true).First().Info.Pubkey;
            var metadata = new Metadata {
                {
                    GrpcConstants.PubkeyMetadataKey, pubkey
                }
            };

            Hash hash = Hash.FromRawBytes(new byte[] { 3, 6, 9 });
            await _service.SendAnnouncement(new BlockAnnouncement
            {
                BlockHeight = 10, BlockHash = hash
            }, BuildServerCallContext(metadata));

            Assert.NotNull(received);
            Assert.Equal(10, received.Announce.BlockHeight);
            Assert.Equal(received.Announce.BlockHash, hash);
        }
        public async Task ConfirmHandshake_Test()
        {
            PeerConnectedEventData received = null;

            _eventBus.Subscribe <PeerConnectedEventData>(t =>
            {
                received = t;
                return(Task.CompletedTask);
            });
            var request = new ConfirmHandshakeRequest();
            var context = BuildServerCallContext(null, "ipv4:127.0.0.1:7878");

            var result = await _serverService.ConfirmHandshake(request, context);

            result.ShouldBe(new VoidReply());
            received.ShouldBe(null);

            var peer     = _peerPool.GetPeers(true).First();
            var pubkey   = peer.Info.Pubkey;
            var metadata = new Metadata {
                { GrpcConstants.PubkeyMetadataKey, pubkey }
            };

            context = BuildServerCallContext(metadata, "ipv4:127.0.0.1:7878");
            result  = await _serverService.ConfirmHandshake(request, context);

            result.ShouldBe(new VoidReply());
            received.ShouldNotBeNull();
        }
        public async Task StartSync_NoEnoughPeer_Test()
        {
            _peerPool.TryAddPeer(CreatePeer(0));
            _peerPool.TryAddPeer(CreatePeer(16));

            InitialSyncFinishedEvent eventData = null;

            _eventBus.Subscribe <InitialSyncFinishedEvent>(args =>
            {
                eventData = args;
                return(Task.CompletedTask);
            });

            await _syncStateService.StartSyncAsync();

            _syncStateService.GetCurrentSyncTarget().ShouldBe(-1);

            eventData.ShouldNotBeNull();
        }
Example #9
0
        public async Task Announce_ShouldPublishEvent()
        {
            AnnouncementReceivedEventData received = null;

            _eventBus.Subscribe <AnnouncementReceivedEventData>(a =>
            {
                received = a;
                return(Task.CompletedTask);
            });

            Hash hash = Hash.Generate();
            await _service.Announce(new PeerNewBlockAnnouncement
            {
                BlockHeight = 10, BlockHash = hash, BlockTime = DateTime.UtcNow.ToTimestamp()
            }, BuildServerCallContext());

            Assert.NotNull(received);
            Assert.Equal(10, received.Announce.BlockHeight);
            Assert.Equal(received.Announce.BlockHash, hash);
        }
Example #10
0
        public async Task Announce_ShouldPublishEvent()
        {
            AnnouncementReceivedEventData received = null;

            _eventBus.Subscribe <AnnouncementReceivedEventData>(a =>
            {
                received = a;
                return(Task.CompletedTask);
            });

            Hash hash = Hash.FromRawBytes(new byte[] { 3, 6, 9 });
            await _service.SendAnnouncement(new BlockAnnouncement
            {
                BlockHeight = 10, BlockHash = hash
            }, BuildServerCallContext());

            Assert.NotNull(received);
            Assert.Equal(10, received.Announce.BlockHeight);
            Assert.Equal(received.Announce.BlockHash, hash);
        }
Example #11
0
        public async Task AnnounceAsync_Success()
        {
            AnnouncementReceivedEventData received = null;

            _eventBus.Subscribe <AnnouncementReceivedEventData>(a =>
            {
                received = a;
                return(Task.CompletedTask);
            });

            var header = new BlockAnnouncement
            {
                BlockHeight = 100,
                BlockHash   = Hash.FromRawBytes(new byte[] { 9, 2 })
            };

            await _grpcPeer.SendAnnouncementAsync(header);

            received.ShouldNotBeNull();
            received.Announce.BlockHeight.ShouldBe(100);
        }
Example #12
0
        public async Task ValidateTransactionTest()
        {
            TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null;

            _eventBus.Subscribe <TransactionValidationStatusChangedEvent>(d =>
            {
                transactionValidationStatusChangedEventData = d;
                return(Task.CompletedTask);
            });

            TransactionExecutionValidationFailedEvent transactionExecutionValidationFailedEvent = null;

            _eventBus.Subscribe <TransactionExecutionValidationFailedEvent>(d =>
            {
                transactionExecutionValidationFailedEvent = d;
                return(Task.CompletedTask);
            });

            var transactionMockExecutionHelper = GetRequiredService <TransactionMockExecutionHelper>();

            transactionMockExecutionHelper.SetTransactionResultStatus(TransactionResultStatus.Mined);
            var kernelTestHelper = GetRequiredService <KernelTestHelper>();
            var transaction      = kernelTestHelper.GenerateTransaction();

            var result =
                await _transactionExecutionValidationProvider.ValidateTransactionAsync(transaction, await _kernelTestHelper.GetChainContextAsync());

            result.ShouldBeTrue();

            transactionValidationStatusChangedEventData.ShouldBeNull();
            transactionExecutionValidationFailedEvent.ShouldBeNull();
        }
Example #13
0
        public async Task AnnounceAsync_Success()
        {
            AnnouncementReceivedEventData received = null;

            _eventBus.Subscribe <AnnouncementReceivedEventData>(a =>
            {
                received = a;
                return(Task.CompletedTask);
            });

            var header = new PeerNewBlockAnnouncement
            {
                BlockHeight = 100,
                BlockHash   = Hash.Generate(),
                BlockTime   = DateTime.UtcNow.ToTimestamp()
            };

            await _grpcPeer.AnnounceAsync(header);

            received.ShouldNotBeNull();
            received.Announce.BlockHeight.ShouldBe(100);
        }
Example #14
0
        public async Task Sync_Finished_Should_Launch_Event()
        {
            InitialSyncFinishedEvent eventData = null;

            _eventBus.Subscribe <InitialSyncFinishedEvent>(args =>
            {
                eventData = args;
                return(Task.CompletedTask);
            });

            await _syncStateService.StartSyncAsync();

            eventData.ShouldNotBeNull();
        }
Example #15
0
        public async Task FinishInitialSync_Test()
        {
            InitialSyncFinishedEvent eventData = null;

            _localEventBus.Subscribe <InitialSyncFinishedEvent>(d =>
            {
                eventData = d;
                return(Task.CompletedTask);
            });

            await _blockchainNodeContextService.FinishInitialSyncAsync();

            eventData.ShouldNotBeNull();
        }
        public async Task DialPeerAsync_GoodPeer_Test()
        {
            PeerConnectedEventData eventData = null;

            _eventBus.Subscribe <PeerConnectedEventData>(e =>
            {
                eventData = e;
                return(Task.CompletedTask);
            });

            AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint);

            var added = await _connectionService.ConnectAsync(endpoint);

            added.ShouldBeTrue();

            var peer = (GrpcPeer)_peerPool.FindPeerByEndpoint(endpoint);

            peer.ShouldNotBeNull();
            peer.IsConnected.ShouldBeTrue();
            peer.SyncState.ShouldBe(SyncState.Syncing);

            eventData.ShouldNotBeNull();
        }
        public async Task StartServer_Test()
        {
            NetworkInitializedEvent received = null;

            _eventBus.Subscribe <NetworkInitializedEvent>(a =>
            {
                received = a;
                return(Task.CompletedTask);
            });

            await _networkServer.StartAsync();

            received.ShouldNotBeNull();

            await _networkServer.StopAsync();
        }
        public async Task StartServer_Test()
        {
            NetworkInitializedEvent received = null;

            _eventBus.Subscribe <NetworkInitializedEvent>(a =>
            {
                received = a;
                return(Task.CompletedTask);
            });

            await _networkServer.StartAsync();

            received.ShouldNotBeNull();

            var reconnections = _reconnectionService.GetPeersReadyForReconnection(null);

            reconnections.Count.ShouldBe(1);
            reconnections.First().Endpoint.ShouldBe("127.0.0.1:2018");

            await _networkServer.StopAsync();
        }
        public async Task ValidateTransaction_Test()
        {
            TransactionValidationStatusChangedEvent eventData = null;

            _eventBus.Subscribe <TransactionValidationStatusChangedEvent>(d =>
            {
                eventData = d;
                return(Task.CompletedTask);
            });

            var transaction = _kernelTestHelper.GenerateTransaction();
            var result      =
                await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext());

            result.ShouldBeTrue();
            eventData.ShouldBeNull();

            transaction.Signature = ByteString.Empty;
            result =
                await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext());

            result.ShouldBeFalse();
            eventData.ShouldNotBeNull();
            eventData.TransactionId.ShouldBe(transaction.GetHash());
            eventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed);
            eventData.Error.ShouldBe("Incorrect transaction signature.");

            eventData   = null;
            transaction = GenerateBigTransaction();
            result      =
                await _basicTransactionValidationProvider.ValidateTransactionAsync(transaction, new ChainContext());

            result.ShouldBeFalse();
            eventData.ShouldNotBeNull();
            eventData.TransactionId.ShouldBe(transaction.GetHash());
            eventData.TransactionResultStatus.ShouldBe(TransactionResultStatus.NodeValidationFailed);
            eventData.Error.ShouldBe("Transaction size exceeded.");
        }
 public IDisposable Subscribe <TEvent> (Func <TEvent, Task> action) where TEvent : class
 {
     return(_localEventBus.Subscribe(action));
 }
Example #21
0
        public async Task HandleEvent_Test()
        {
            BlockMinedEventData blockMinedEventData = null;

            _localEventBus.Subscribe <BlockMinedEventData>(d =>
            {
                blockMinedEventData = d;
                return(Task.CompletedTask);
            });

            var chain = await _blockchainService.GetChainAsync();

            var bestChainHash   = chain.BestChainHash;
            var bestChainHeight = chain.BestChainHeight;

            _testContext.MockConsensusService.Verify(
                s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(10));

            {
                var eventData = new ConsensusRequestMiningEventData(HashHelper.ComputeFrom("NotBestChain"),
                                                                    bestChainHeight,
                                                                    TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500),
                                                                    TimestampHelper.GetUtcNow().AddMilliseconds(499));

                await HandleConsensusRequestMiningEventAsync(eventData);

                blockMinedEventData.ShouldBeNull();
                chain = await _blockchainService.GetChainAsync();

                chain.BestChainHeight.ShouldBe(bestChainHeight);
                chain.BestChainHash.ShouldBe(bestChainHash);

                _testContext.MockConsensusService.Verify(
                    s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(10));
            }

            {
                var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight,
                                                                    TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500),
                                                                    TimestampHelper.GetUtcNow().AddMilliseconds(499));

                await HandleConsensusRequestMiningEventAsync(eventData);

                blockMinedEventData.ShouldBeNull();
                chain = await _blockchainService.GetChainAsync();

                chain.BestChainHeight.ShouldBe(bestChainHeight);
                chain.BestChainHash.ShouldBe(bestChainHash);

                _testContext.MockConsensusService.Verify(
                    s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(11));
            }

            {
                var eventData = new ConsensusRequestMiningEventData(bestChainHash, bestChainHeight,
                                                                    TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(500),
                                                                    TimestampHelper.GetUtcNow().AddSeconds(30));

                await HandleConsensusRequestMiningEventAsync(eventData);

                blockMinedEventData.ShouldNotBeNull();
                blockMinedEventData.BlockHeader.Height.ShouldBe(bestChainHeight + 1);
                blockMinedEventData.BlockHeader.PreviousBlockHash.ShouldBe(bestChainHash);

                chain = await _blockchainService.GetChainAsync();

                chain.Branches.ShouldContainKey(blockMinedEventData.BlockHeader.GetHash().ToStorageKey());

                (await _blockchainService.HasBlockAsync(blockMinedEventData.BlockHeader.GetHash())).ShouldBeTrue();

                _testContext.MockConsensusService.Verify(
                    s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(11));
            }
        }
Example #22
0
        public async Task TxHub_Test()
        {
            TransactionValidationStatusChangedEvent transactionValidationStatusChangedEventData = null;

            _eventBus.Subscribe <TransactionValidationStatusChangedEvent>(d =>
            {
                transactionValidationStatusChangedEventData = d;
                return(Task.CompletedTask);
            });

            TransactionAcceptedEvent transactionAcceptedEvent = null;

            _eventBus.Subscribe <TransactionAcceptedEvent>(d =>
            {
                transactionAcceptedEvent = d;
                return(Task.CompletedTask);
            });

            {
                // Empty transaction pool
                // Chain:
                //         BestChainHeight: 11
                // TxHub:
                //         BestChainHeight: 0
                //          AllTransaction: 0
                //    ValidatedTransaction: 0
                await TxHubBestChainShouldBeAsync(Hash.Empty, 0);
                await TransactionPoolSizeShouldBeAsync(0, 0);

                transactionValidationStatusChangedEventData.ShouldBeNull();
                transactionAcceptedEvent.ShouldBeNull();
            }

            {
                // Receive a valid transaction
                // Chain:
                //         BestChainHeight: 11
                // TxHub:
                //         BestChainHeight: 0
                //          AllTransaction: 0
                //    ValidatedTransaction: 0
                var chain = await _blockchainService.GetChainAsync();

                var transactionValid =
                    _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash);

                await AddTransactionsAsync(new List <Transaction> {
                    transactionValid
                });
                await TxHubBestChainShouldBeAsync(Hash.Empty, 0);
                await TransactionPoolSizeShouldBeAsync(0, 0);
                await CheckTransactionInPoolAsync(transactionValid, false);

                transactionValidationStatusChangedEventData.ShouldBeNull();
                transactionAcceptedEvent.ShouldBeNull();
            }

            {
                // Receive best chain found event
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 0
                //    ValidatedTransaction: 0
                await _kernelTestHelper.AttachBlockToBestChain();

                var chain = await _blockchainService.GetChainAsync();

                await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight);
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(0, 0);
            }

            {
                // Receive a different branch transaction
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 1
                //    ValidatedTransaction: 0
                var transactionDifferent = _kernelTestHelper.GenerateTransaction(12);
                var chain = await _blockchainService.GetChainAsync();
                await AddTransactionsAsync(new List <Transaction> {
                    transactionDifferent
                });
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(1, 0);
                await CheckTransactionInPoolAsync(transactionDifferent, true);

                transactionValidationStatusChangedEventData.ShouldBeNull();
                transactionAcceptedEvent.ShouldBeNull();
            }

            {
                // Receive a future transaction
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 1
                //    ValidatedTransaction: 0
                var chain = await _blockchainService.GetChainAsync();

                var transactionFuture = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight + 1);
                await AddTransactionsAsync(new List <Transaction> {
                    transactionFuture
                });
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(1, 0);
                await CheckTransactionInPoolAsync(transactionFuture, false);

                transactionAcceptedEvent.ShouldBeNull();
                transactionValidationStatusChangedEventData.ShouldNotBeNull();
                transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionFuture.GetHash());
                transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus
                                                                                             .NodeValidationFailed);
                transactionValidationStatusChangedEventData.Error.ShouldContain("Transaction expired");

                transactionValidationStatusChangedEventData = null;
            }

            {
                // Receive a invalid transaction
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 1
                //    ValidatedTransaction: 0
                var chain = await _blockchainService.GetChainAsync();

                var transactionInvalid =
                    _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash);
                transactionInvalid.Signature = ByteString.Empty;
                await AddTransactionsAsync(new List <Transaction> {
                    transactionInvalid
                });
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(1, 0);
                await CheckTransactionInPoolAsync(transactionInvalid, false);

                transactionValidationStatusChangedEventData.ShouldNotBeNull();
                transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionInvalid.GetHash());
                transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus
                                                                                             .NodeValidationFailed);
                transactionValidationStatusChangedEventData.Error.ShouldBe("Incorrect transaction signature.");
                transactionAcceptedEvent.ShouldBeNull();

                transactionValidationStatusChangedEventData = null;
            }

            {
                // Receive a transaction already in DB
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 1
                //    ValidatedTransaction: 0
                var chain = await _blockchainService.GetChainAsync();

                var transactionInDB =
                    _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash);
                await _blockchainService.AddTransactionsAsync(new List <Transaction> {
                    transactionInDB
                });
                await AddTransactionsAsync(new List <Transaction> {
                    transactionInDB
                });
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(1, 0);
                await CheckTransactionInPoolAsync(transactionInDB, false);

                transactionValidationStatusChangedEventData.ShouldBeNull();
                transactionAcceptedEvent.ShouldBeNull();
            }

            {
                // Receive a valid transaction
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 2
                //    ValidatedTransaction: 1
                var chain = await _blockchainService.GetChainAsync();

                var transactionValid =
                    _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash);

                await AddTransactionsAsync(new List <Transaction> {
                    transactionValid
                });

                await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight);
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(2, 1);
                await CheckTransactionInPoolAsync(transactionValid, true);

                transactionValidationStatusChangedEventData.ShouldBeNull();
                transactionAcceptedEvent.ShouldNotBeNull();
                transactionAcceptedEvent.Transaction.ShouldBe(transactionValid);
                transactionAcceptedEvent.ChainId.ShouldBe(chain.Id);

                transactionAcceptedEvent = null;

                // Receive the valid transaction again
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 2
                //    ValidatedTransaction: 1
                await AddTransactionsAsync(new List <Transaction> {
                    transactionValid
                });
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(2, 1);
                await CheckTransactionInPoolAsync(transactionValid, true);

                transactionValidationStatusChangedEventData.ShouldBeNull();
                transactionAcceptedEvent.ShouldBeNull();

                // Mined a block
                // Chain:
                //         BestChainHeight: 13
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 1
                //    ValidatedTransaction: 0
                var transactionNotInPool =
                    _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash);

                var newBlock = await _kernelTestHelper.AttachBlockToBestChain(new List <Transaction>
                {
                    transactionValid,
                    transactionNotInPool
                });

                await _txHub.CleanByTransactionIdsAsync(newBlock.TransactionIds);
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 12);
                await TransactionPoolSizeShouldBeAsync(1, 1);
                await CheckTransactionInPoolAsync(transactionValid, false);
            }

            {
                // Receive best chain found event
                // Chain:
                //         BestChainHeight: 13
                // TxHub:
                //         BestChainHeight: 13
                //          AllTransaction: 1
                //    ValidatedTransaction: 0
                var chain = await _blockchainService.GetChainAsync();

                await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight);

                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13);
                await TransactionPoolSizeShouldBeAsync(1, 0);
            }

            {
                // Receive a valid transaction and a expired transaction
                // Chain:
                //         BestChainHeight: 13
                // TxHub:
                //         BestChainHeight: 13
                //          AllTransaction: 2
                //    ValidatedTransaction: 1
                var chain = await _blockchainService.GetChainAsync();

                var transactionValid =
                    _kernelTestHelper.GenerateTransaction(chain.BestChainHeight, chain.BestChainHash);
                var transactionExpired = _kernelTestHelper.GenerateTransaction(chain.BestChainHeight + 100);

                await AddTransactionsAsync(new List <Transaction>
                {
                    transactionValid,
                    transactionExpired
                });

                await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight);
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13);
                await TransactionPoolSizeShouldBeAsync(2, 1);
                await CheckTransactionInPoolAsync(transactionValid, true);
                await CheckTransactionInPoolAsync(transactionExpired, false);

                transactionValidationStatusChangedEventData.ShouldNotBeNull();
                transactionValidationStatusChangedEventData.TransactionId.ShouldBe(transactionExpired.GetHash());
                transactionValidationStatusChangedEventData.TransactionResultStatus.ShouldBe(TransactionResultStatus
                                                                                             .NodeValidationFailed);
                transactionValidationStatusChangedEventData.Error.ShouldContain("Transaction expired");

                transactionAcceptedEvent.ShouldNotBeNull();
                transactionAcceptedEvent.Transaction.ShouldBe(transactionValid);
                transactionAcceptedEvent.ChainId.ShouldBe(chain.Id);

                transactionAcceptedEvent = null;
                transactionValidationStatusChangedEventData = null;
            }

            {
                // Set lib 12
                // Chain:
                //         BestChainHeight: 13
                // TxHub:
                //         BestChainHeight: 13
                //          AllTransaction: 1
                //    ValidatedTransaction: 1
                var chain = await _blockchainService.GetChainAsync();

                await _txHub.CleanByHeightAsync(12);
                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 13);
                await TransactionPoolSizeShouldBeAsync(1, 1);
            }

            {
                // After 513 blocks
                // Chain:
                //         BestChainHeight: 526
                // TxHub:
                //         BestChainHeight: 526
                //          AllTransaction: 1
                //    ValidatedTransaction: 0
                var chain = await _blockchainService.GetChainAsync();

                var bestChainHeight = chain.BestChainHeight;
                for (var i = 0; i < KernelConstants.ReferenceBlockValidPeriod + 1; i++)
                {
                    var transaction = _kernelTestHelper.GenerateTransaction(bestChainHeight + i);
                    await _kernelTestHelper.AttachBlockToBestChain(new List <Transaction> {
                        transaction
                    });

                    chain = await _blockchainService.GetChainAsync();

                    await _txHub.UpdateTransactionPoolByBestChainAsync(chain.BestChainHash, chain.BestChainHeight);
                }

                await TxHubBestChainShouldBeAsync(chain.BestChainHash, 526);

                await TransactionPoolSizeShouldBeAsync(0, 0);
            }
        }
        public async Task WrongParallelTest()
        {
            var chain = await _blockchainService.GetChainAsync();

            await _blockchainService.SetIrreversibleBlockAsync(chain, chain.BestChainHeight, chain.BestChainHash);

            //prepare token for tx verify
            var(tokenTransactions, groupUsers) =
                await _parallelTestHelper.PrepareTokenForParallel(_groupCount, 1000_00000000);

            await _parallelTestHelper.BroadcastTransactions(tokenTransactions);

            var prepareBlock =
                _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, tokenTransactions);

            prepareBlock =
                (await _blockExecutingService.ExecuteBlockAsync(prepareBlock.Header,
                                                                tokenTransactions)).Block;
            await _blockchainService.AddBlockAsync(prepareBlock);

            await _blockAttachService.AttachBlockAsync(prepareBlock);

            chain = await _blockchainService.GetChainAsync();

            var transactions =
                _parallelTestHelper.GenerateBasicFunctionWithParallelTransactions(groupUsers, _transactionCount);
            var transferTransaction = await _parallelTestHelper.GenerateTransferTransaction(Address.FromPublicKey(groupUsers[1].PublicKey)
                                                                                            , "ELF", 10);

            transactions.Add(transferTransaction);
            await _parallelTestHelper.BroadcastTransactions(transactions);

            var otherTransactions        = _parallelTestHelper.GenerateBasicFunctionWithParallelTransactions(groupUsers, _transactionCount);
            var otherTransferTransaction = await _parallelTestHelper.GenerateTransferTransaction(Address.FromPublicKey(groupUsers[2].PublicKey)
                                                                                                 , "ELF", 10);

            otherTransactions.Add(otherTransferTransaction);
            await _parallelTestHelper.BroadcastTransactions(otherTransactions);

            var transferTransactions = await _parallelTestHelper.GenerateTransferTransactions(16);

            await _parallelTestHelper.BroadcastTransactions(transferTransactions);

            var poolSize = (await _txHub.GetTransactionPoolStatusAsync()).AllTransactionCount;

            poolSize.ShouldBe(transactions.Count * 2 + transferTransactions.Count);

            var groupedTransactions = await _grouper.GroupAsync(
                new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight },
                transactions);

            groupedTransactions.Parallelizables.Count.ShouldBe(_transactionCount + 1);
            groupedTransactions.NonParallelizables.Count.ShouldBe(0);
            for (var i = 0; i < transactions.Count; i++)
            {
                transactions[i].GetHash().ShouldBe(groupedTransactions.Parallelizables[i][0].GetHash());
            }

            var otherGroupedTransactions = await _grouper.GroupAsync(
                new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight },
                otherTransactions);

            otherGroupedTransactions.Parallelizables.Count.ShouldBe(_transactionCount + 1);
            otherGroupedTransactions.NonParallelizables.Count.ShouldBe(0);

            var groupedTransferTransactions = await _grouper.GroupAsync(
                new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight },
                transferTransactions);

            groupedTransferTransactions.Parallelizables.Count.ShouldBe(1);
            groupedTransferTransactions.Parallelizables[0].Count.ShouldBe(transferTransactions.Count);
            groupedTransferTransactions.NonParallelizables.Count.ShouldBe(0);

            _localEventBus.Subscribe <ConflictingTransactionsFoundInParallelGroupsEvent>(e =>
            {
                e.ConflictingSets.Count.ShouldBe(_groupCount + 1);
                e.ExistingSets.Count.ShouldBe(_groupCount);
                return(Task.CompletedTask);
            });

            var block = _parallelTestHelper.GenerateBlock(chain.BestChainHash, chain.BestChainHeight, transactions);

            block = (await _blockExecutingService.ExecuteBlockAsync(block.Header, transactions)).Block;
            block.TransactionIds.Count().ShouldBe(_transactionCount + 1);

            var transactionResults = await GetTransactionResultsAsync(block.Body.TransactionIds.ToList(), block.Header);

            transactionResults.Count(t => t.Status == TransactionResultStatus.Mined).ShouldBe(_groupCount);
            transactionResults.Count(t => t.Status == TransactionResultStatus.Conflict).ShouldBe(_groupCount + 1);
            await _blockchainService.AddBlockAsync(block);

            await _blockAttachService.AttachBlockAsync(block);

            var accountAddress = await _accountService.GetAccountAsync();

            var chainContext = new ChainContext
            {
                BlockHash   = block.GetHash(),
                BlockHeight = block.Height
            };
            var tokenContractAddress =
                await _smartContractAddressService.GetAddressByContractNameAsync(chainContext, TokenSmartContractAddressNameProvider.StringName);

            var nonparallelContractCode =
                await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(chainContext,
                                                                                       tokenContractAddress);

            nonparallelContractCode.ShouldBeNull();

            foreach (var transaction in transactions)
            {
                if (transaction.To == tokenContractAddress)
                {
                    continue;
                }
                var param = IncreaseWinMoneyInput.Parser.ParseFrom(transaction.Params);
                var input = new QueryTwoUserWinMoneyInput
                {
                    First  = param.First,
                    Second = param.Second
                };
                var queryTransaction = _parallelTestHelper.GenerateTransaction(accountAddress,
                                                                               ParallelTestHelper.BasicFunctionWithParallelContractAddress,
                                                                               nameof(BasicFunctionWithParallelContract.QueryTwoUserWinMoney), input);
                var byteString = await _parallelTestHelper.ExecuteReadOnlyAsync(queryTransaction, block.GetHash(), block.Height);

                var output = TwoUserMoneyOut.Parser.ParseFrom(byteString);
                output.FirstInt64Value.ShouldBe(1);
                var result = transactionResults.First(t => t.TransactionId == transaction.GetHash());
                if (result.Status == TransactionResultStatus.Mined)
                {
                    output.SecondInt64Value.ShouldBe(1);
                }
                else if (result.Status == TransactionResultStatus.Conflict)
                {
                    output.SecondInt64Value.ShouldBe(0);
                }
            }

            nonparallelContractCode =
                await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(new ChainContext
            {
                BlockHash   = block.GetHash(),
                BlockHeight = block.Height
            }, ParallelTestHelper.BasicFunctionWithParallelContractAddress);

            nonparallelContractCode.CodeHash.ShouldBe(HashHelper.ComputeFrom(_parallelTestHelper.BasicFunctionWithParallelContractCode));

            var blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash());

            blockStateSet.Changes.Count.ShouldBeGreaterThan(0);
            var blockExecutedData = blockStateSet.BlockExecutedData.First();
            var versionedState    = await _versionedStates.GetAsync(blockExecutedData.Key);

            versionedState.ShouldBeNull();

            await _blockchainStateService.MergeBlockStateAsync(block.Height, block.GetHash());

            blockStateSet = await _blockStateSetManger.GetBlockStateSetAsync(block.GetHash());

            blockStateSet.ShouldBeNull();

            nonparallelContractCode =
                await _nonparallelContractCodeProvider.GetNonparallelContractCodeAsync(new ChainContext
            {
                BlockHash   = block.GetHash(),
                BlockHeight = block.Height
            }, ParallelTestHelper.BasicFunctionWithParallelContractAddress);

            nonparallelContractCode.CodeHash.ShouldBe(HashHelper.ComputeFrom(_parallelTestHelper.BasicFunctionWithParallelContractCode));

            versionedState = await _versionedStates.GetAsync(blockExecutedData.Key);

            versionedState.Key.ShouldBe(blockExecutedData.Key);
            versionedState.Value.ShouldBe(blockExecutedData.Value);

            groupedTransactions = await _grouper.GroupAsync(
                new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height },
                transactions);

            groupedTransactions.Parallelizables.Count.ShouldBe(1);
            groupedTransactions.Parallelizables[0][0].To.ShouldBe(tokenContractAddress);
            groupedTransactions.NonParallelizables.Count.ShouldBe(_transactionCount);

            otherGroupedTransactions = await _grouper.GroupAsync(
                new ChainContext { BlockHash = block.GetHash(), BlockHeight = block.Height },
                otherTransactions);

            otherGroupedTransactions.Parallelizables.Count.ShouldBe(1);
            otherGroupedTransactions.Parallelizables[0][0].To.ShouldBe(tokenContractAddress);
            otherGroupedTransactions.NonParallelizables.Count.ShouldBe(_transactionCount);

            groupedTransferTransactions = await _grouper.GroupAsync(
                new ChainContext { BlockHash = chain.BestChainHash, BlockHeight = chain.BestChainHeight },
                transferTransactions);

            groupedTransferTransactions.Parallelizables.Count.ShouldBe(1);
            groupedTransferTransactions.Parallelizables[0].Count.ShouldBe(transferTransactions.Count);
            groupedTransferTransactions.NonParallelizables.Count.ShouldBe(0);

            poolSize = (await _txHub.GetTransactionPoolStatusAsync()).AllTransactionCount;

            poolSize.ShouldBe(transactions.Count * 2 + transferTransactions.Count - block.TransactionIds.Count());
        }