public async Task <long> GetUnacceptableDistanceToLastIrreversibleBlockHeightAsync(Hash blockHash)
        {
            PrepareBloomForIrreversibleBlockHeightUnacceptable();

            var block = await _blockchainService.GetBlockByHashAsync(blockHash);

            if (_bloomOfLibUnacceptable.IsIn(new Bloom(block.Header.Bloom.ToByteArray())))
            {
                foreach (var transactionId in block.Body.TransactionIds)
                {
                    var result = await _transactionResultQueryService.GetTransactionResultAsync(transactionId);

                    if (result == null)
                    {
                        Logger.LogTrace($"Transaction result is null, transactionId: {transactionId}");
                        continue;
                    }

                    if (result.Status == TransactionResultStatus.Failed)
                    {
                        Logger.LogTrace(
                            $"Transaction failed, transactionId: {transactionId}, error: {result.Error}");
                        continue;
                    }

                    if (result.Bloom.Length == 0 || !_bloomOfLibUnacceptable.IsIn(new Bloom(result.Bloom.ToByteArray())))
                    {
                        continue;
                    }

                    foreach (var log in result.Logs)
                    {
                        if (log.Address != _contractAddress || log.Name != _logEventOfLibUnacceptable.Name)
                        {
                            continue;
                        }

                        var message = new IrreversibleBlockHeightUnacceptable();
                        message.MergeFrom(log);
                        Logger.LogTrace(
                            $"IrreversibleBlockHeightUnacceptable detected: {message}");
                        return(message.DistanceToIrreversibleBlockHeight);
                    }
                }
            }

            return(0);
        }
        public async Task ProcessAsync_Test()
        {
            var chain = await _smartContractExecutionHelper.CreateChainAsync();

            var block = await _blockchainService.GetBlockByHashAsync(chain.BestChainHash);

            var tasks = block.Body.TransactionIds
                        .Select(t => _transactionResultQueryService.GetTransactionResultAsync(t)).ToList();
            var transactionResultList = await Task.WhenAll(tasks);

            await ProcessTransactionResultsAsync(transactionResultList, block);

            var transaction = new Transaction
            {
                From       = _smartContractAddressService.GetZeroSmartContractAddress(),
                To         = _smartContractAddressService.GetZeroSmartContractAddress(),
                MethodName = nameof(ACS0Container.ACS0Stub.DeploySmartContract),
                Params     = new ContractDeploymentInput
                {
                    Category = KernelConstants.DefaultRunnerCategory,
                    Code     = ByteString.CopyFrom(
                        _smartContractExecutionHelper.ContractCodes["AElf.Contracts.MultiToken"])
                }.ToByteString()
            };
            var blockExecutedSet = await _smartContractExecutionHelper.ExecuteTransactionAsync(transaction);

            await ProcessTransactionResultsAsync(blockExecutedSet.TransactionResultMap.Values.ToArray(), blockExecutedSet.Block);

            await ProcessCodeUpdateAsync(chain);
        }
示例#3
0
        public async Task ApplyAsync(IEnumerable <Block> blocks)
        {
            Logger.LogTrace("Apply log event handler.");
            foreach (var block in blocks)
            {
                var blockBloom = new Bloom(block.Header.Bloom.ToByteArray());
                if (!Blooms.Values.Any(b => b.IsIn(blockBloom)))
                {
                    // No interested event in the block
                    continue;
                }

                foreach (var transactionId in block.Body.TransactionIds)
                {
                    var result =
                        await _transactionResultQueryService.GetTransactionResultAsync(transactionId, block.GetHash());

                    if (result == null)
                    {
                        continue;
                    }

                    if (result.Status == TransactionResultStatus.Failed)
                    {
                        continue;
                    }

                    if (result.Bloom.Length == 0)
                    {
                        continue;
                    }

                    var resultBloom = new Bloom(result.Bloom.ToByteArray());

                    foreach (var handler in _eventHandlers)
                    {
                        var interestedEvent = handler.InterestedEvent;
                        var interestedBloom = Blooms[interestedEvent];
                        if (!interestedBloom.IsIn(resultBloom))
                        {
                            // Interested bloom is not found in the transaction result
                            continue;
                        }

                        // Interested bloom is found in the transaction result,
                        // find the log that yields the bloom and apply the handler
                        foreach (var log in result.Logs)
                        {
                            if (log.Address != interestedEvent.Address || log.Name != interestedEvent.Name)
                            {
                                continue;
                            }
                            await handler.HandleAsync(block, result, log);
                        }
                    }
                }
            }

            Logger.LogTrace("Finish apply log event handler.");
        }
示例#4
0
        private async Task <TransactionResult> GetTransactionResult(Hash txHash)
        {
            // in storage
            var res = await _transactionResultQueryService.GetTransactionResultAsync(txHash);

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

            // in tx pool
            var receipt = await _txHub.GetTransactionReceiptAsync(txHash);

            if (receipt != null)
            {
                return(new TransactionResult
                {
                    TransactionId = receipt.TransactionId,
                    Status = TransactionResultStatus.Pending
                });
            }

            // not existed
            return(new TransactionResult
            {
                TransactionId = txHash,
                Status = TransactionResultStatus.NotExisted
            });
        }
        public async Task <IEnumerable <T> > GetEventMessagesAsync(Hash blockHash, Address contractAddress)
        {
            try
            {
                PrepareBloom(contractAddress);
                var block = await _blockchainService.GetBlockByHashAsync(blockHash);

                var messages = new List <T>();

                if (!_bloom.IsIn(new Bloom(block.Header.Bloom.ToByteArray())))
                {
                    return(messages);
                }

                foreach (var transactionId in block.Body.TransactionIds)
                {
                    var transactionExecutingResult =
                        await _transactionResultQueryService.GetTransactionResultAsync(transactionId);

                    if (!CheckTransactionExecutingResult(transactionExecutingResult, transactionId))
                    {
                        continue;
                    }

                    foreach (var log in transactionExecutingResult.Logs)
                    {
                        if (contractAddress == null || log.Address != contractAddress || log.Name != _logEvent.Name)
                        {
                            continue;
                        }

                        var message = new T();
                        try
                        {
                            message.MergeFrom(log);
                            messages.Add(message);
                        }
                        catch (Exception e)
                        {
                            Logger.LogError($"Failed to generate message of type {message.GetType().FullName}. {e}");
                            throw;
                        }
                    }
                }

                Logger.LogTrace($"Event of type {typeof(T).FullName} found.");

                return(messages);
            }
            catch (Exception)
            {
                Logger.LogError($"Failed to resolve event {typeof(T).FullName}");
                throw;
            }
        }
示例#6
0
        public async Task GetExecutive_With_GenesisContract_Test()
        {
            var chain = await _smartContractHelper.CreateChainWithGenesisContractAsync();

            var chainContext = new ChainContext
            {
                BlockHash   = chain.BestChainHash,
                BlockHeight = chain.BestChainHeight
            };
            //Get executive of genesis contract by smartContractRegistration in genesis contract and blockHeight=1
            var executive = await _smartContractExecutiveService
                            .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress);

            executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash);

            var transaction = _smartContractHelper.BuildDeploySystemSmartContractTransaction(
                ConfigurationSmartContractAddressNameProvider.Name,
                _smartContractHelper.Codes["AElf.Contracts.Configuration"]);
            var block = await _smartContractHelper.GenerateBlockAsync(chain.BestChainHeight, chain.BestChainHash, new List <Transaction>
            {
                transaction
            });

            await _smartContractHelper.MineBlockAsync(block);

            chainContext = new ChainContext
            {
                BlockHash   = block.GetHash(),
                BlockHeight = block.Height
            };

            var transactionResult = await _transactionResultQueryService.GetTransactionResultAsync(transaction.GetHash(), block.GetHash());

            var contractDeployed = new ContractDeployed();

            contractDeployed.MergeFrom(transactionResult.Logs.First(l => l.Name == nameof(ContractDeployed)));

            //Get executive of configuration contract in genesis contract
            executive = await _smartContractExecutiveService.GetExecutiveAsync(chainContext, contractDeployed.Address);

            executive.ContractHash.ShouldBe(
                HashHelper.ComputeFrom(_smartContractHelper.Codes["AElf.Contracts.Configuration"]));

            //Get executive of genesis contract by smartContractRegistration in genesis contract and blockHeight=2
            executive = await _smartContractExecutiveService
                        .GetExecutiveAsync(chainContext, _defaultContractZeroCodeProvider.ContractZeroAddress);

            executive.ContractHash.ShouldBe(_defaultContractZeroCodeProvider.DefaultContractZeroRegistration.CodeHash);
        }
        public async Task <IBlockIndex> DiscoverAndSetIrreversibleAsync(Chain chain, IEnumerable <Hash> blockIdsInOrder)
        {
            PrepareBloom();

            var reverse = blockIdsInOrder.Reverse();

            foreach (var blockId in reverse)
            {
                var block = await _blockchainService.GetBlockByHashAsync(blockId);

                Logger.LogTrace($"Check event for block {blockId} - {block.Height}");

                if (!_bloom.IsIn(new Bloom(block.Header.Bloom.ToByteArray())))
                {
                    // No interested event in the block
                    continue;
                }

                foreach (var transactionId in block.Body.TransactionIds)
                {
                    var result = await _transactionResultQueryService.GetTransactionResultAsync(transactionId);

                    if (result == null)
                    {
                        Logger.LogTrace($"Transaction result is null, transactionId: {transactionId}");
                        continue;
                    }

                    if (result.Status == TransactionResultStatus.Failed)
                    {
                        Logger.LogTrace(
                            $"Transaction failed, transactionId: {transactionId}, error: {result.Error}");
                        continue;
                    }

                    if (result.Bloom.Length == 0 || !_bloom.IsIn(new Bloom(result.Bloom.ToByteArray())))
                    {
                        continue;
                    }

                    foreach (var log in result.Logs)
                    {
                        if (log.Address != _contractAddress || log.Name != _logEvent.Name)
                        {
                            continue;
                        }

                        var message = new IrreversibleBlockFound();
                        message.MergeFrom(log);

                        //var offset = message.Offset;
                        //var libHeight = block.Height - offset;

                        var libHeight = message.IrreversibleBlockHeight;

                        if (chain.LastIrreversibleBlockHeight >= libHeight)
                        {
                            return(null);
                        }

                        var libBlock = await _blockchainService.GetBlockHashByHeightAsync(chain, libHeight, blockId);

                        return(new BlockIndex(libBlock, libHeight));
                    }
                }
            }

            return(null);
        }
        public async Task <string> GetPrimaryTokenSymbol()
        {
            PrepareBloom();

            var blockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync();

            if (blockHeader.Height != Constants.GenesisBlockHeight)
            {
                return(null);
            }

            var block = await _blockchainService.GetBlockByHashAsync(blockHeader.GetHash());

            if (!_bloom.IsIn(new Bloom(block.Header.Bloom.ToByteArray())))
            {
                // No interested event in the block
                return(null);
            }

            Logger.LogTrace("ChainPrimaryTokenSymbolSet event received.");

            foreach (var transactionId in block.Body.TransactionIds)
            {
                var result = await _transactionResultQueryService.GetTransactionResultAsync(transactionId);

                if (result == null)
                {
                    Logger.LogTrace($"Transaction result is null, transactionId: {transactionId}");
                    continue;
                }

                if (result.Status == TransactionResultStatus.Failed)
                {
                    Logger.LogTrace(
                        $"Transaction failed, transactionId: {transactionId}, error: {result.Error}");
                    continue;
                }

                if (result.Bloom.Length == 0 || !_bloom.IsIn(new Bloom(result.Bloom.ToByteArray())))
                {
                    continue;
                }

                foreach (var log in result.Logs)
                {
                    if (log.Address != _contractAddress || log.Name != _logEvent.Name)
                    {
                        continue;
                    }

                    var message = new ChainPrimaryTokenSymbolSet();
                    message.MergeFrom(log);

                    Logger.LogTrace($"Chain primary token symbol: {message.TokenSymbol}");

                    return(message.TokenSymbol);
                }
            }

            return(null);
        }
示例#9
0
        public async Task <List <Address> > GetDeployedContractAddresses(Chain chain, IEnumerable <Hash> blockIdsInOrder)
        {
            PrepareBloom();

            var addresses = new List <Address>();

            foreach (var blockId in blockIdsInOrder)
            {
                var block = await _blockchainService.GetBlockByHashAsync(blockId);

                Logger.LogTrace($"Check event for block {blockId} - {block.Height}");

                if (!_bloom.IsIn(new Bloom(block.Header.Bloom.ToByteArray())))
                {
                    // No interested event in the block
                    continue;
                }

                Logger.LogTrace("ContractDeployed event received.");

                foreach (var transactionId in block.Body.TransactionIds)
                {
                    var result = await _transactionResultQueryService.GetTransactionResultAsync(transactionId);

                    if (result == null)
                    {
                        Logger.LogTrace($"Transaction result is null, transactionId: {transactionId}");
                        continue;
                    }

                    if (result.Status == TransactionResultStatus.Failed)
                    {
                        Logger.LogTrace(
                            $"Transaction failed, transactionId: {transactionId}, error: {result.Error}");
                        continue;
                    }

                    if (result.Bloom.Length == 0 || !_bloom.IsIn(new Bloom(result.Bloom.ToByteArray())))
                    {
                        continue;
                    }

                    foreach (var log in result.Logs)
                    {
                        if (log.Address != _contractAddress || log.Name != _logEvent.Name)
                        {
                            continue;
                        }

                        var message = new ContractDeployed();
                        message.MergeFrom(log);

                        Logger.LogTrace($"Add {message.Address} to deployed contract address list.");

                        addresses.Add(message.Address);
                    }
                }
            }

            return(addresses);
        }