public async Task <BlockIndex> GetTransactionBlockIndexAsync(Hash txId)
        {
            var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId);

            if (transactionBlockIndex == null)
            {
                return(null);
            }

            return(await GetBlockIndexAsync(transactionBlockIndex));
        }
        public async Task <TransactionResult> GetTransactionResultAsync(Hash transactionId)
        {
            var transactionBlockIndex =
                await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(transactionId);

            var chain = await _blockchainService.GetChainAsync();

            if (transactionBlockIndex != null)
            {
                var blockHashInBestChain =
                    await _blockchainService.GetBlockHashByHeightAsync(chain, transactionBlockIndex.BlockHeight,
                                                                       chain.BestChainHash);

                // check whether it is on best chain or a fork branch
                if (transactionBlockIndex.BlockHash == blockHashInBestChain)
                {
                    // If TransactionBlockIndex exists, then read the result via TransactionBlockIndex
                    return(await _transactionResultManager.GetTransactionResultAsync(transactionId,
                                                                                     transactionBlockIndex.BlockHash));
                }
            }

            var hash  = chain.BestChainHash;
            var until = chain.LastIrreversibleBlockHeight > Constants.GenesisBlockHeight
                ? chain.LastIrreversibleBlockHeight - 1
                : Constants.GenesisBlockHeight;

            while (true)
            {
                var result = await _transactionResultManager.GetTransactionResultAsync(transactionId, hash);

                if (result != null)
                {
                    return(result);
                }

                var header = await _blockchainService.GetBlockHeaderByHashAsync(hash);

                result = await _transactionResultManager.GetTransactionResultAsync(transactionId,
                                                                                   header.GetPreMiningHash());

                if (result != null)
                {
                    return(result);
                }

                if (header.Height <= until)
                {
                    // do until 1 block below LIB, in case the TransactionBlockIndex is not already added during
                    // NewIrreversibleBlockFoundEvent handling
                    break;
                }

                hash = header.PreviousBlockHash;
            }

            return(null);
        }
Esempio n. 3
0
        public async Task LoadTransactionBlockIndexAsync()
        {
            var chain = await _blockchainService.GetChainAsync();

            if (chain == null)
            {
                return;
            }

            var blockHeight = chain.LastIrreversibleBlockHeight;
            var blockHash   = chain.LastIrreversibleBlockHash;

            while (true)
            {
                if (blockHeight < AElfConstants.GenesisBlockHeight ||
                    blockHeight + KernelConstants.ReferenceBlockValidPeriod <= chain.LastIrreversibleBlockHeight)
                {
                    break;
                }

                var block = await _blockchainService.GetBlockByHashAsync(blockHash);

                if (block == null)
                {
                    return;
                }

                foreach (var txId in block.TransactionIds)
                {
                    var txBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId);

                    _transactionBlockIndexProvider.AddTransactionBlockIndex(txId, txBlockIndex);
                }

                blockHash = block.Header.PreviousBlockHash;
                blockHeight--;
            }
        }
        public async Task GetTransactionBlockIndexBelowLibTest()
        {
            var previousBlockHeader = _kernelTestHelper.BestBranchBlockList.Last().Header;
            var block1 =
                _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, HashHelper.ComputeFrom("PreBlockHash1"));
            var block2 =
                _kernelTestHelper.GenerateBlock(previousBlockHeader.Height, previousBlockHeader.PreviousBlockHash);

            var txId  = HashHelper.ComputeFrom("Transaction");
            var chain = await _blockchainService.GetChainAsync();

            await AddBlockAsync(chain, block1);

            var blockIndex =
                await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId);

            blockIndex.ShouldBeNull();

            var blockIndex1 = new BlockIndex
            {
                BlockHash   = block1.GetHash(),
                BlockHeight = block1.Height
            };
            await _transactionBlockIndexService.AddBlockIndexAsync(new List <Hash> {
                txId
            }, blockIndex1);

            var blockIndex2 = new BlockIndex
            {
                BlockHash   = block2.GetHash(),
                BlockHeight = block2.Height
            };
            await _transactionBlockIndexService.AddBlockIndexAsync(new List <Hash> {
                txId
            }, blockIndex2);

            chain = await _blockchainService.GetChainAsync();
            await AddBlockAsync(chain, block2);
            await SetBestChain(chain, block2);

            {
                var existsOnForkBranch =
                    await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId,
                                                                                                         block1.GetHash());

                Assert.True(existsOnForkBranch);

                var actualBlockIndexOnBestChain =
                    await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId);

                Assert.Equal(blockIndex2, actualBlockIndexOnBestChain);

                var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId);

                transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash);
                transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight);
                transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(1);
                transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHash.ShouldBe(blockIndex1.BlockHash);
                transactionBlockIndex.PreviousExecutionBlockIndexList[0].BlockHeight.ShouldBe(blockIndex1.BlockHeight);

                _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out var transactionBlockIndexCache)
                .ShouldBeTrue();
                transactionBlockIndexCache.ShouldBe(transactionBlockIndex);
            }

            var i            = 0;
            var currentBlock = block2;

            while (i++ < KernelConstants.ReferenceBlockValidPeriod)
            {
                var block = await _kernelTestHelper.AttachBlock(currentBlock.Height, currentBlock.GetHash());

                // await AddBlockAsync(chain, block);
                currentBlock = block;
            }

            await SetBestChain(chain, currentBlock);

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

            await _transactionBlockIndexService.UpdateTransactionBlockIndicesByLibHeightAsync(currentBlock.Height);

            {
                _transactionBlockIndexProvider.TryGetTransactionBlockIndex(txId, out _).ShouldBeFalse();

                var existsOnForkBranch =
                    await _transactionBlockIndexService.ValidateTransactionBlockIndexExistsInBranchAsync(txId,
                                                                                                         block1.GetHash());

                Assert.False(existsOnForkBranch);
                var actualBlockIndexOnBestChain =
                    await _transactionBlockIndexService.GetTransactionBlockIndexAsync(txId);

                Assert.Equal(blockIndex2, actualBlockIndexOnBestChain);

                var transactionBlockIndex = await _transactionBlockIndexManager.GetTransactionBlockIndexAsync(txId);

                transactionBlockIndex.BlockHash.ShouldBe(blockIndex2.BlockHash);
                transactionBlockIndex.BlockHeight.ShouldBe(blockIndex2.BlockHeight);
                transactionBlockIndex.PreviousExecutionBlockIndexList.Count.ShouldBe(0);
            }
        }