Exemple #1
0
        public async Task Start_Test()
        {
            var transactions = new List <Transaction>
            {
                _kernelTestHelper.GenerateTransaction(),
                _kernelTestHelper.GenerateTransaction()
            };

            var dto = new BlockchainNodeContextStartDto
            {
                ChainId = 1234,
                ZeroSmartContractType = typeof(IBlockchainNodeContextService),
                Transactions          = transactions.ToArray()
            };

            _kernelNodeTestContext.MockConsensusService.Verify(
                s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Never);

            var context = await _blockchainNodeContextService.StartAsync(dto);

            _kernelNodeTestContext.MockConsensusService.Verify(
                s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Once);

            context.ChainId.ShouldBe(dto.ChainId);
            var chain = await _blockchainService.GetChainAsync();

            chain.Id.ShouldBe(dto.ChainId);
            chain.BestChainHeight.ShouldBe(1);
            var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash);

            block.Body.TransactionIds.Count.ShouldBe(2);
            block.Body.TransactionIds.ShouldContain(transactions[0].GetHash());
            block.Body.TransactionIds.ShouldContain(transactions[1].GetHash());

            var block2 = await _kernelTestHelper.AttachBlockToBestChain();

            var block3 = await _kernelTestHelper.AttachBlockToBestChain();

            chain = await _blockchainService.GetChainAsync();

            chain.BestChainHeight.ShouldBe(3);
            chain.BestChainHash.ShouldBe(block3.GetHash());

            await _blockchainService.SetIrreversibleBlockAsync(chain, block2.Height, block2.GetHash());

            chain = await _blockchainService.GetChainAsync();

            chain.LastIrreversibleBlockHeight.ShouldBe(2);

            context = await _blockchainNodeContextService.StartAsync(dto);

            chain = await _blockchainService.GetChainAsync();

            context.ChainId.ShouldBe(dto.ChainId);
            chain.BestChainHeight.ShouldBe(2);
            chain.BestChainHash.ShouldBe(block2.GetHash());

            _kernelNodeTestContext.MockConsensusService.Verify(
                s => s.TriggerConsensusAsync(It.IsAny <ChainContext>()), Times.Exactly(2));
        }
        public async Task Add_Block_Success()
        {
            var block = new Block
            {
                Height = 2,
                Header = new BlockHeader(),
                Body   = new BlockBody()
            };

            for (var i = 0; i < 3; i++)
            {
                block.Body.AddTransaction(_kernelTestHelper.GenerateTransaction());
            }

            var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.ShouldBeNull();

            await _fullBlockchainService.AddBlockAsync(block);

            existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.GetHash().ShouldBe(block.GetHash());
            existBlock.Body.TransactionsCount.ShouldBe(3);

            foreach (var tx in block.Body.TransactionList)
            {
                var existTransaction = await _transactionManager.GetTransaction(tx.GetHash());

                existTransaction.ShouldBe(tx);
            }
        }
        public async Task Create_Chain_Success()
        {
            var transactions = new List <Transaction>
            {
                _kernelTestHelper.GenerateTransaction(),
                _kernelTestHelper.GenerateTransaction()
            };

            var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions);

            var chain = await _fullBlockchainService.GetChainAsync();

            chain.ShouldBeNull();

            var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.ShouldBeNull();

            var createChainResult = await _fullBlockchainService.CreateChainAsync(block, transactions);

            chain = await _fullBlockchainService.GetChainAsync();

            chain.ShouldNotBeNull();
            chain.ShouldBe(createChainResult);

            existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.GetHash().ShouldBe(block.GetHash());

            var existTransactions = await _fullBlockchainService.GetTransactionsAsync(transactions.Select(t => t.GetHash()));

            existTransactions.ShouldContain(transactions[0]);
            existTransactions.ShouldContain(transactions[1]);
        }
        public async Task Add_Block_Success()
        {
            var transactions = new List <Transaction>();

            for (var i = 0; i < 3; i++)
            {
                var transaction = _kernelTestHelper.GenerateTransaction();
                transactions.Add(transaction);
            }

            var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions);

            var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.ShouldBeNull();

            await _fullBlockchainService.AddBlockAsync(block);

            existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.ShouldBe(block);

            var blockHeader = await _fullBlockchainService.GetBlockHeaderByHashAsync(block.GetHash());

            blockHeader.ShouldBe(block.Header);
        }
        public async Task Insert_Transaction_Test()
        {
            var transaction = _kernelTestHelper.GenerateTransaction();
            var hash        = await _transactionManager.AddTransactionAsync(transaction);

            hash.ShouldNotBeNull();
        }
Exemple #6
0
        public async Task Add_Block_Success()
        {
            var transactions = new List <Transaction>();

            for (var i = 0; i < 3; i++)
            {
                var transaction = _kernelTestHelper.GenerateTransaction();
                transactions.Add(transaction);
            }
            var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions);

            var existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.ShouldBeNull();

            await _fullBlockchainService.AddBlockAsync(block);

            await _fullBlockchainService.AddTransactionsAsync(transactions);

            existBlock = await _fullBlockchainService.GetBlockByHashAsync(block.GetHash());

            existBlock.GetHash().ShouldBe(block.GetHash());
            existBlock.Body.TransactionsCount.ShouldBe(3);

            foreach (var tx in transactions)
            {
                var existTransaction = await _transactionManager.GetTransaction(tx.GetHash());

                existTransaction.ShouldBe(tx);
            }
        }
        public async Task Validate_EconomicAddress_Test()
        {
            var tx = _kernelTestHelper.GenerateTransaction();
            var economicAddress =
                _smartContractAddressService.GetAddressByContractName(EconomicSmartContractAddressNameProvider.Name);

            tx.To = economicAddress;
            var result = await _validationProvider.ValidateTransactionAsync(tx);

            result.ShouldBeFalse();
        }
Exemple #8
0
        public async Task Attach_Block_To_Chain_ReturnNull()
        {
            var chain = await _blockchainService.GetChainAsync();

            var newBlock = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, Hash.Empty,
                                                           new List <Transaction> {
                _kernelTestHelper.GenerateTransaction()
            });

            var status = await _blockchainService.AttachBlockToChainAsync(chain, newBlock);

            var attachResult =
                await _fullBlockchainExecutingService.ExecuteBlocksAttachedToLongestChain(chain, status);

            attachResult.ShouldBeNull();
        }
        public async Task ExecuteBlocksAttachedToLongestChain_ExecuteFailed()
        {
            var chain = await _blockchainService.GetChainAsync();

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

            var newBlock = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash,
                                                           new List <Transaction> {
                _kernelTestHelper.GenerateTransaction()
            });

            await _blockchainService.AddBlockAsync(newBlock);

            var status = await _blockchainService.AttachBlockToChainAsync(chain, newBlock);

            var attachResult =
                await _fullBlockchainExecutingService.ExecuteBlocksAttachedToLongestChain(chain, status);

            attachResult.Count.ShouldBe(1);
            attachResult.Last().Height.ShouldBe(16);
            attachResult.Last().BlockHash.ShouldBe(newBlock.GetHash());

            chain = await _blockchainService.GetChainAsync();

            var newBlockLink = await _chainManager.GetChainBlockLinkAsync(newBlock.GetHash());

            newBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionFailed);
            chain.BestChainHash.ShouldBe(bestChainHash);
            chain.BestChainHeight.ShouldBe(bestChainHeight);
        }
        public async Task BlockWithTransactions_Test()
        {
            var chain = await _blockchainService.GetChainAsync();

            var transactions = new List <Transaction>();

            for (var i = 0; i < 5; i++)
            {
                transactions.Add(_kernelTestHelper.GenerateTransaction());
            }

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

            var blockWithTransactions = new BlockWithTransactions
            {
                Header       = block.Header,
                Transactions = { transactions }
            };

            blockWithTransactions.FullTransactionList.ShouldBe(transactions);
            blockWithTransactions.TransactionIds.ShouldBe(transactions.Select(o => o.GetHash()));
            blockWithTransactions.Height.ShouldBe(block.Height);
            blockWithTransactions.Body.ShouldBe(new BlockBody
            {
                TransactionIds = { transactions.Select(tx => tx.GetHash()).ToList() }
            });
        }
Exemple #11
0
        public async Task ExecuteBlocks_ValidateFailed()
        {
            var chain = await _blockchainService.GetChainAsync();

            var previousHash   = chain.BestChainHash;
            var previousHeight = chain.BestChainHeight;

            var blockList = new List <Block>();

            for (var i = 0; i < 3; i++)
            {
                var transactions = new List <Transaction> {
                    _kernelTestHelper.GenerateTransaction()
                };
                var lastBlock = _kernelTestHelper.GenerateBlock(previousHeight, previousHash, transactions);

                await _blockchainService.AddBlockAsync(lastBlock);

                await _blockchainService.AddTransactionsAsync(transactions);

                await _blockchainService.AttachBlockToChainAsync(chain, lastBlock);

                previousHash   = lastBlock.GetHash();
                previousHeight = lastBlock.Height;
                blockList.Add(lastBlock);
            }

            var executionResult =
                await _fullBlockchainExecutingService.ExecuteBlocksAsync(blockList);

            executionResult.SuccessBlockExecutedSets.Count.ShouldBe(0);
            executionResult.ExecutedFailedBlocks.Count.ShouldBe(1);
            executionResult.ExecutedFailedBlocks[0].GetHash().ShouldBe(blockList[0].GetHash());
        }
Exemple #12
0
        public async Task ValidateBeforeAttach_DuplicatesTransactions_ReturnFalse()
        {
            var transaction = _kernelTestHelper.GenerateTransaction();
            var block       = _kernelTestHelper.GenerateBlock(9, Hash.FromString("PreviousBlockHash"),
                                                              new List <Transaction> {
                transaction, transaction
            });

            block.Header.Signature =
                ByteString.CopyFrom(CryptoHelper.SignWithPrivateKey(_kernelTestHelper.KeyPair.PrivateKey,
                                                                    block.GetHash().ToByteArray()));

            var validateResult = await _blockValidationProvider.ValidateBeforeAttachAsync(block);

            validateResult.ShouldBeFalse();
        }
Exemple #13
0
        public async Task Validation_ValidTx_Test()
        {
            var tx = _kernelTestHelper.GenerateTransaction();

            //system tx free
            tx.MethodName = "SystemMethod";
            var validateResult = await _validationProvider.ValidateTransactionAsync(tx);

            validateResult.ShouldBe(true);

            var mockTx = _kernelTestHelper.GenerateTransaction();

            mockTx.From    = SampleAddress.AddressList[0];
            validateResult = await _validationProvider.ValidateTransactionAsync(mockTx);

            validateResult.ShouldBe(true);
        }
        public async Task Add_TransactionResult_With_BlockHash()
        {
            var tx = _kernelTestHelper.GenerateTransaction();

            var(block, results) = GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last()
                                                                        .Header, new[] { tx });

            var result = results.First();

            (await _transactionResultService.GetTransactionResultAsync(tx.GetHash())).ShouldBeNull();
            // Complete block
            await AddTransactionResultsWithPostMiningAsync(block, new[] { result });

            var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash());

            queried.ShouldBe(result);

            var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block.GetHash());

            queried2.ShouldBe(result);
        }
Exemple #15
0
        private BlockExecutedSet GenerateBlockExecutedSet(long blockHeight, List <LogEvent> logEvents)
        {
            var blockExecutedSet = new BlockExecutedSet();
            var transactions     = new List <Transaction>();

            for (var i = 0; i < logEvents.Count + 1; i++)
            {
                transactions.Add(_kernelTestHelper.GenerateTransaction());
            }

            var block = _kernelTestHelper.GenerateBlock(blockHeight - 1, HashHelper.ComputeFrom("PreviousBlockHash"),
                                                        transactions);

            blockExecutedSet.Block = block;
            blockExecutedSet.TransactionResultMap = new Dictionary <Hash, TransactionResult>
            {
                {
                    transactions[0].GetHash(),
                    new TransactionResult {
                        TransactionId = transactions[0].GetHash(), Bloom = ByteString.Empty
                    }
                }
            };

            var bloom   = new Bloom();
            var logs    = new List <LogEvent>();
            var txIndex = 1;

            foreach (var logEvent in logEvents)
            {
                bloom.Combine(new List <Bloom> {
                    logEvent.GetBloom()
                });
                logs.Add(logEvent);

                var transactionResult = new TransactionResult
                {
                    TransactionId = transactions[txIndex].GetHash(),
                    Bloom         = ByteString.CopyFrom(bloom.Data),
                };
                transactionResult.Logs.AddRange(logs);

                blockExecutedSet.TransactionResultMap.Add(transactions[txIndex].GetHash(), transactionResult);
                txIndex++;
            }

            block.Header.Bloom = ByteString.CopyFrom(bloom.Data);

            return(blockExecutedSet);
        }
Exemple #16
0
        public async Task ExecuteBlocksAttachedToLongestChain_ValidateFailed()
        {
            var chain = await _blockchainService.GetChainAsync();

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

            var previousHash   = chain.BestChainHash;
            var previousHeight = chain.BestChainHeight;

            BlockAttachOperationStatus status = BlockAttachOperationStatus.None;
            var blockList = new List <Block>();
//            Block lastBlock = null;
            int count = 0;

            while (!status.HasFlag(BlockAttachOperationStatus.LongestChainFound))
            {
                var transactions = new List <Transaction> {
                    _kernelTestHelper.GenerateTransaction()
                };
                var lastBlock = _kernelTestHelper.GenerateBlock(previousHeight, previousHash, transactions);

                await _blockchainService.AddBlockAsync(lastBlock);

                await _blockchainService.AddTransactionsAsync(transactions);

                status = await _blockchainService.AttachBlockToChainAsync(chain, lastBlock);

                count++;
                previousHash   = lastBlock.GetHash();
                previousHeight = lastBlock.Height;
                blockList.Add(lastBlock);
            }

            var attachResult =
                await _fullBlockchainExecutingService.ExecuteBlocksAttachedToLongestChain(chain, status);

            attachResult.ShouldBeNull();

            chain = await _blockchainService.GetChainAsync();

            var newBlockLink = await _chainManager.GetChainBlockLinkAsync(blockList.First().GetHash());

            newBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionFailed);
            chain.BestChainHash.ShouldBe(bestChainHash);
            chain.BestChainHeight.ShouldBe(bestChainHeight);
            chain.LongestChainHash.ShouldBe(bestChainHash);
            chain.LongestChainHeight.ShouldBe(bestChainHeight);
            chain.Branches.ShouldNotContainKey(previousHash.ToStorageKey());
        }
Exemple #17
0
        public async Task ValidateTransaction_Test()
        {
            var tx     = _kernelTestHelper.GenerateTransaction();
            var result = await _validationProvider.ValidateTransactionAsync(tx);

            result.ShouldBe(true);

            _smartContractAddressService.SetAddress(TokenSmartContractAddressNameProvider.Name,
                                                    SampleAddress.AddressList.Last());
            tx.To         = SampleAddress.AddressList.Last();
            tx.MethodName = "ClaimTransactionFees";
            result        = await _validationProvider.ValidateTransactionAsync(tx);

            result.ShouldBe(false);
        }
        public async Task ExecuteBlocksAttachedToLongestChain_ValidateFailed()
        {
            var chain = await _blockchainService.GetChainAsync();

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

            var transactions = new List <Transaction> {
                _kernelTestHelper.GenerateTransaction()
            };

            var newBlock = _kernelTestHelper.GenerateBlock(chain.BestChainHeight, chain.BestChainHash,
                                                           transactions);

            await _blockchainService.AddBlockAsync(newBlock);

            await _blockchainService.AddTransactionsAsync(transactions);

            var status = await _blockchainService.AttachBlockToChainAsync(chain, newBlock);

            chain = await _blockchainService.GetChainAsync();

            chain.LongestChainHash.ShouldBe(newBlock.GetHash());
            chain.LongestChainHeight.ShouldBe(newBlock.Height);
            chain.Branches.ShouldContainKey(newBlock.GetHash().ToStorageKey());

            var attachResult =
                await _fullBlockchainExecutingService.ExecuteBlocksAttachedToLongestChain(chain, status);

            attachResult.ShouldBeNull();

            chain = await _blockchainService.GetChainAsync();

            var newBlockLink = await _chainManager.GetChainBlockLinkAsync(newBlock.GetHash());

            newBlockLink.ExecutionStatus.ShouldBe(ChainBlockLinkExecutionStatus.ExecutionFailed);
            chain.BestChainHash.ShouldBe(bestChainHash);
            chain.BestChainHeight.ShouldBe(bestChainHeight);
            chain.LongestChainHash.ShouldBe(bestChainHash);
            chain.LongestChainHeight.ShouldBe(bestChainHeight);
            chain.Branches.ShouldNotContainKey(newBlock.GetHash().ToStorageKey());
        }
        public async Task GetBlockTransactions_Test()
        {
            var transactions = new List <Transaction>();

            for (var i = 0; i < 3; i++)
            {
                var transaction = _kernelTestHelper.GenerateTransaction();
                transactions.Add(transaction);
            }

            var block = _kernelTestHelper.GenerateBlock(0, Hash.Empty, transactions);

            await _blockchainService.AddBlockAsync(block);

            await _blockchainService.AddTransactionsAsync(transactions);

            var blockTransactions = await _smartContractBridgeService.GetBlockTransactions(block.GetHash());

            blockTransactions.ShouldBe(transactions);
        }
        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 async Task Add_TransactionResult_With_PreMiningHash()
        {
            var tx = _kernelTestHelper.GenerateTransaction();

            var(block, results) =
                GetNextBlockWithTransactionAndResults(_kernelTestHelper.BestBranchBlockList.Last().Header, new[] { tx });

            var result = results.First();

            await AddTransactionResultsWithPreMiningAsync(block, new[] { result });

            var queried = await _transactionResultService.GetTransactionResultAsync(tx.GetHash());

            queried.ShouldBe(null);
            var queried2 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash(), block.GetHash());

            queried2.ShouldBe(result);

            var blockIndex = new BlockIndex
            {
                BlockHash   = block.GetHash(),
                BlockHeight = block.Height
            };

            // Add TransactionResult after completing and adding block
            await _transactionResultService.AddTransactionResultsAsync(results, block.Header);

            await _transactionBlockIndexService.UpdateTransactionBlockIndexAsync(new List <Hash> {
                tx.GetHash()
            },
                                                                                 blockIndex);

            var queried3 = await _transactionResultService.GetTransactionResultAsync(tx.GetHash());

            queried3.ShouldBe(result);
        }
Exemple #22
0
        public async Task Test_TxHub()
        {
            {
                // Empty transaction pool
                // Chain:
                //         BestChainHeight: 11
                // TxHub:
                //         BestChainHeight: 0
                //          AllTransaction: 0
                //   ExecutableTransaction: 0
                ExecutableTransactionShouldBe(Hash.Empty, 0);

                TransactionPoolSizeShouldBe(0);
            }

            var transactionHeight100 = _kernelTestHelper.GenerateTransaction(100);
            {
                // Receive a feature transaction twice
                // Chain:
                //         BestChainHeight: 11
                // TxHub:
                //         BestChainHeight: 0
                //          AllTransaction: 1
                //   ExecutableTransaction: 0

                // Receive the transaction first time
                await _txHub.HandleTransactionsReceivedAsync(new TransactionsReceivedEvent
                {
                    Transactions = new List <Transaction> {
                        transactionHeight100
                    }
                });

                ExecutableTransactionShouldBe(Hash.Empty, 0);

                TransactionPoolSizeShouldBe(1);
                TransactionShouldInPool(transactionHeight100);

                // Receive the same transaction again
                await _txHub.HandleTransactionsReceivedAsync(new TransactionsReceivedEvent
                {
                    Transactions = new List <Transaction> {
                        transactionHeight100
                    }
                });

                ExecutableTransactionShouldBe(Hash.Empty, 0);

                TransactionPoolSizeShouldBe(1);
                TransactionShouldInPool(transactionHeight100);
            }

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

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

                await _txHub.HandleTransactionsReceivedAsync(new TransactionsReceivedEvent
                {
                    Transactions = new List <Transaction> {
                        transactionValid
                    }
                });

                TransactionPoolSizeShouldBe(2);
                TransactionShouldInPool(transactionHeight100);
                TransactionShouldInPool(transactionValid);

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

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

                await _txHub.HandleBlockAcceptedAsync(new BlockAcceptedEvent
                {
                    BlockHeader = newBlock.Header
                });

                TransactionPoolSizeShouldBe(1);
                TransactionShouldInPool(transactionHeight100);
            }

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

                await _txHub.HandleBestChainFoundAsync(new BestChainFoundEventData
                {
                    BlockHash   = chain.BestChainHash,
                    BlockHeight = chain.BestChainHeight
                });

                ExecutableTransactionShouldBe(chain.BestChainHash, chain.BestChainHeight);

                TransactionPoolSizeShouldBe(1);
                TransactionShouldInPool(transactionHeight100);
            }

            {
                // Receive a valid transaction and a invalid transaction
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 3
                //   ExecutableTransaction: 1
                var chain = await _blockchainService.GetChainAsync();

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

                await _txHub.HandleTransactionsReceivedAsync(new TransactionsReceivedEvent
                {
                    Transactions = new List <Transaction>
                    {
                        transactionValid,
                        transactionInvalid
                    }
                });

                ExecutableTransactionShouldBe(chain.BestChainHash, chain.BestChainHeight, new List <Transaction>
                {
                    transactionValid
                });

                TransactionPoolSizeShouldBe(3);
                TransactionShouldInPool(transactionHeight100);
                TransactionShouldInPool(transactionValid);
                TransactionShouldInPool(transactionInvalid);

                // Receive lib found event
                // Chain:
                //         BestChainHeight: 12
                // TxHub:
                //         BestChainHeight: 12
                //          AllTransaction: 2
                //   ExecutableTransaction: 1
                await _txHub.HandleNewIrreversibleBlockFoundAsync(new NewIrreversibleBlockFoundEvent
                {
                    BlockHash   = chain.BestChainHash,
                    BlockHeight = chain.BestChainHeight
                });

                ExecutableTransactionShouldBe(chain.BestChainHash, chain.BestChainHeight, new List <Transaction>
                {
                    transactionValid
                });

                TransactionPoolSizeShouldBe(2);
                TransactionShouldInPool(transactionHeight100);
                TransactionShouldInPool(transactionValid);
            }

            {
                // After 513 blocks
                // Chain:
                //         BestChainHeight: 525
                // TxHub:
                //         BestChainHeight: 525
                //          AllTransaction: 0
                //   ExecutableTransaction: 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.HandleBestChainFoundAsync(new BestChainFoundEventData
                    {
                        BlockHash   = chain.BestChainHash,
                        BlockHeight = chain.BestChainHeight
                    });

                    await _txHub.HandleNewIrreversibleBlockFoundAsync(new NewIrreversibleBlockFoundEvent
                    {
                        BlockHash   = chain.BestChainHash,
                        BlockHeight = chain.BestChainHeight
                    });
                }

                ExecutableTransactionShouldBe(chain.BestChainHash, chain.BestChainHeight);

                TransactionPoolSizeShouldBe(0);
            }
        }
        public async Task Test_HandleEvent()
        {
            {
                // Null event
                //             BestChainHeight: 11
                // LastIrreversibleBlockHeight: 5
                var chain = await _blockchainService.GetChainAsync();

                var currentLibHeight = chain.LastIrreversibleBlockHeight;
                var currentLibHash   = chain.LastIrreversibleBlockHash;

                var index = await _irreversibleBlockDiscoveryService.DiscoverAndSetIrreversibleAsync(chain, new List <Hash>());

                if (index != null)
                {
                    await _blockchainService.SetIrreversibleBlockAsync(chain, index.Height, index.Hash);
                }

                LibShouldBe(currentLibHeight, currentLibHash);
            }

            {
                // Transaction execute failed
                //             BestChainHeight: 12
                // LastIrreversibleBlockHeight: 5
                var chain = await _blockchainService.GetChainAsync();

                var currentLibHeight = chain.LastIrreversibleBlockHeight;
                var currentLibHash   = chain.LastIrreversibleBlockHash;

                var transaction       = _kernelTestHelper.GenerateTransaction();
                var transactionResult =
                    _kernelTestHelper.GenerateTransactionResult(transaction, TransactionResultStatus.Failed);
                var newBlock = await _kernelTestHelper.AttachBlock(chain.BestChainHeight, chain.LongestChainHash, new
                                                                   List <Transaction> {
                    transaction
                }, new List <TransactionResult> {
                    transactionResult
                });

                await _blockchainService.SetBestChainAsync(chain, newBlock.Height, newBlock.GetHash());

                var executedBlocks = new List <Hash> {
                    newBlock.GetHash()
                };

                var index = await _irreversibleBlockDiscoveryService.DiscoverAndSetIrreversibleAsync(chain, executedBlocks);

                if (index != null)
                {
                    await _blockchainService.SetIrreversibleBlockAsync(chain, index.Height, index.Hash);
                }
                LibShouldBe(currentLibHeight, currentLibHash);
            }

            {
                // Event not from consensus smart contract
                //             BestChainHeight: 13
                // LastIrreversibleBlockHeight: 5
                var chain = await _blockchainService.GetChainAsync();

                var currentLibHeight = chain.LastIrreversibleBlockHeight;
                var currentLibHash   = chain.LastIrreversibleBlockHash;

                var transaction = _kernelTestHelper.GenerateTransaction();
                var logEvent    = new AElf.Contracts.Consensus.DPoS.IrreversibleBlockFound()
                {
                    Offset = 6
                }.ToLogEvent(Address.FromString("TokenContract"));

                var transactionResult =
                    _kernelTestHelper.GenerateTransactionResult(transaction, TransactionResultStatus.Mined, logEvent);
                var newBlock = await _kernelTestHelper.AttachBlock(chain.BestChainHeight, chain.LongestChainHash,
                                                                   new List <Transaction> {
                    transaction
                }, new List <TransactionResult> {
                    transactionResult
                });

                await _blockchainService.SetBestChainAsync(chain, newBlock.Height, newBlock.GetHash());

                var executedBlocks = new List <Hash> {
                    newBlock.GetHash()
                };

                var index = await _irreversibleBlockDiscoveryService.DiscoverAndSetIrreversibleAsync(chain, executedBlocks);

                if (index != null)
                {
                    await _blockchainService.SetIrreversibleBlockAsync(chain, index.Height, index.Hash);
                }
                LibShouldBe(currentLibHeight, currentLibHash);
            }

            {
                // Event from consensus smart contract, not contains 'LIBFound'
                //             BestChainHeight: 14
                // LastIrreversibleBlockHeight: 5
                var chain = await _blockchainService.GetChainAsync();

                var currentLibHeight = chain.LastIrreversibleBlockHeight;
                var currentLibHash   = chain.LastIrreversibleBlockHash;

                var transaction = _kernelTestHelper.GenerateTransaction();
                var logEvent    = new LogEvent
                {
                    Address = _consensusAddress,
                    Name    = "NonExistentEvent"
                };
                var transactionResult =
                    _kernelTestHelper.GenerateTransactionResult(transaction, TransactionResultStatus.Mined, logEvent);
                var newBlock = await _kernelTestHelper.AttachBlock(chain.BestChainHeight, chain.LongestChainHash,
                                                                   new List <Transaction> {
                    transaction
                }, new List <TransactionResult> {
                    transactionResult
                });

                await _blockchainService.SetBestChainAsync(chain, newBlock.Height, newBlock.GetHash());

                var executedBlocks = new List <Hash> {
                    newBlock.GetHash()
                };

                var index = await _irreversibleBlockDiscoveryService.DiscoverAndSetIrreversibleAsync(chain, executedBlocks);

                if (index != null)
                {
                    await _blockchainService.SetIrreversibleBlockAsync(chain, index.Height, index.Hash);
                }
                LibShouldBe(currentLibHeight, currentLibHash);
            }

            {
                // LIBFound
                //             BestChainHeight: 15
                // LastIrreversibleBlockHeight: 10
                var chain = await _blockchainService.GetChainAsync();

                var transaction = _kernelTestHelper.GenerateTransaction();
                var offset      = 5;
                var logEvent    = new AElf.Contracts.Consensus.DPoS.IrreversibleBlockFound()
                {
                    Offset = offset
                }.ToLogEvent(_consensusAddress);
                var transactionResult =
                    _kernelTestHelper.GenerateTransactionResult(transaction, TransactionResultStatus.Mined, logEvent);
                var newBlock = await _kernelTestHelper.AttachBlock(chain.BestChainHeight, chain.BestChainHash,
                                                                   new List <Transaction> {
                    transaction
                }, new List <TransactionResult> {
                    transactionResult
                });

                await _blockchainService.SetBestChainAsync(chain, newBlock.Height, newBlock.GetHash());

                var libHash = await _blockchainService.GetBlockHashByHeightAsync(chain, 10, chain.LongestChainHash);

                var executedBlocks = new List <Hash> {
                    newBlock.GetHash()
                };

                var index = await _irreversibleBlockDiscoveryService.DiscoverAndSetIrreversibleAsync(chain, executedBlocks);

                if (index != null)
                {
                    await _blockchainService.SetIrreversibleBlockAsync(chain, index.Height, index.Hash);
                }
                LibShouldBe(10, libHash);
            }
        }
        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);
            }
        }