Example #1
0
    public async Task Should_Call_Handler_AndDispose()
    {
        LocalEventBus.Subscribe <MySimpleEventData, MySimpleTransientEventHandler>();

        await LocalEventBus.PublishAsync(new MySimpleEventData(1));

        await LocalEventBus.PublishAsync(new MySimpleEventData(2));

        await LocalEventBus.PublishAsync(new MySimpleEventData(3));

        Assert.Equal(3, MySimpleTransientEventHandler.HandleCount);
        Assert.Equal(3, MySimpleTransientEventHandler.DisposeCount);
    }
Example #2
0
        public void ReplayEventsForHandlerType(Type handlerType, DateTime startDate, DateTime endDate)
        {
            runtime.Start();

            var serviceLocator   = runtime.ServiceLocator;
            var eventStore       = serviceLocator.Resolve <IEventStore>();
            var domainEventTypes = GetDomainEventTypesHandledByHandler(handlerType);

            var domainEvents = eventStore.GetEventsByEventTypes(domainEventTypes, startDate, endDate);
            var eventBus     = new LocalEventBus(new[] { handlerType }, new DomainEventHandlerFactory(serviceLocator));

            eventBus.PublishEvents(domainEvents);
        }
        public async Task <bool> ValidateTransactionAsync(Transaction transaction, IChainContext chainContext = null)
        {
            var isView = await _transactionReadOnlyExecutionService.IsViewTransactionAsync(chainContext, transaction);

            if (isView)
            {
                await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent
                {
                    TransactionId           = transaction.GetHash(),
                    TransactionResultStatus = TransactionResultStatus.NodeValidationFailed,
                    Error = "View transaction is not allowed."
                });
            }

            return(!isView);
        }
Example #4
0
        public void ReplayEventsForHandlerType(Type handlerType, Document selector)
        {
            runtime.Start();

            var serviceLocator   = runtime.ServiceLocator;
            var eventStore       = (MongoEventStore)serviceLocator.Resolve <IEventStore>();
            var domainEventTypes = GetDomainEventTypesHandledByHandler(handlerType);

            selector.Add("_t", new Document {
                { "$in", domainEventTypes }
            });
            var domainEvents = eventStore.GetEventsBySelector(selector);
            var eventBus     = new LocalEventBus(new [] { handlerType }, new DomainEventHandlerFactory(serviceLocator));

            eventBus.PublishEvents(domainEvents);
        }
Example #5
0
    public async Task Should_Trigger_For_Inherited_Generic_2()
    {
        var triggeredEvent = false;

        LocalEventBus.Subscribe <EntityChangedEventData <Person> >(
            eventData =>
        {
            eventData.Entity.Id.ShouldBe(42);
            triggeredEvent = true;
            return(Task.CompletedTask);
        });

        await LocalEventBus.PublishAsync(new EntityChangedEventData <Student>(new Student(42)));

        triggeredEvent.ShouldBe(true);
    }
Example #6
0
    public async Task Should_Throw_Aggregate_Exception_If_More_Than_One_Of_Handlers_Fail()
    {
        LocalEventBus.Subscribe <MySimpleEventData>(
            eventData => throw new Exception("This exception is intentionally thrown #1!"));

        LocalEventBus.Subscribe <MySimpleEventData>(
            eventData => throw new Exception("This exception is intentionally thrown #2!"));

        var aggrException = await Assert.ThrowsAsync <AggregateException>(async() =>
        {
            await LocalEventBus.PublishAsync(new MySimpleEventData(1));
        });

        aggrException.InnerExceptions.Count.ShouldBe(2);
        aggrException.InnerExceptions[0].Message.ShouldBe("This exception is intentionally thrown #1!");
        aggrException.InnerExceptions[1].Message.ShouldBe("This exception is intentionally thrown #2!");
    }
        public async Task <bool> ValidateBlockAfterExecuteAsync(IBlock block)
        {
            if (block.Header.Height == AElfConstants.GenesisBlockHeight)
            {
                return(true);
            }

            try
            {
                var isSideChainBlockDataIndexed = TryDiscoverIndexedSideChainBlockData(block);
                Logger.LogDebug($"Try discovery indexed side chain block data: {isSideChainBlockDataIndexed}");
                var extraData        = ExtractCrossChainExtraData(block.Header);
                var validationResult = true;
                if (!isSideChainBlockDataIndexed && !extraData.IsNullOrEmpty())
                {
                    // cross chain extra data in block header should be null if no side chain block data indexed in contract
                    validationResult = false;
                }
                else if (isSideChainBlockDataIndexed)
                {
                    var indexedCrossChainBlockData =
                        await _crossChainIndexingDataService.GetIndexedCrossChainBlockDataAsync(block.Header.GetHash(), block.Header.Height);

                    if (indexedCrossChainBlockData.IsNullOrEmpty() ^ extraData.IsNullOrEmpty())
                    {
                        validationResult = false;
                    }
                    else if (!indexedCrossChainBlockData.IsNullOrEmpty())
                    {
                        validationResult = ValidateBlockExtraDataAsync(indexedCrossChainBlockData, extraData);
                    }
                }

                if (!validationResult)
                {
                    Logger.LogWarning(
                        $"Invalid cross chain extra data, block height {block.Header.Height}, hash {block.GetHash()}.");
                }
                return(validationResult);
            }
            finally
            {
                await LocalEventBus.PublishAsync(new CrossChainDataValidatedEvent());
            }
        }
Example #8
0
        private async Task SetBestChainAsync(List <ChainBlockLink> successLinks, Chain chain)
        {
            if (successLinks.Count == 0)
            {
                return;
            }

            Logger.LogTrace($"Set best chain for block height {string.Join(",", successLinks.Select(l => l.Height))}");
            var blockLink = successLinks.Last();
            await _blockchainService.SetBestChainAsync(chain, blockLink.Height, blockLink.BlockHash);

            await LocalEventBus.PublishAsync(new BestChainFoundEventData
            {
                BlockHash      = chain.BestChainHash,
                BlockHeight    = chain.BestChainHeight,
                ExecutedBlocks = successLinks.Select(p => p.BlockHash).ToList()
            });
        }
Example #9
0
        protected override async Task <TransactionTrace> ExecuteOneAsync(SingleTransactionExecutingDto singleTxExecutingDto, CancellationToken cancellationToken)
        {
            TransactionTrace trace = null;

            try
            {
                trace = await base.ExecuteOneAsync(singleTxExecutingDto, cancellationToken);
            }
            finally
            {
                await LocalEventBus.PublishAsync(new TransactionExecutedEventData
                {
                    TransactionTrace = trace
                });
            }

            return(trace);
        }
Example #10
0
    public async Task Should_Call_Handler_With_Non_Generic_Trigger()
    {
        var totalData = 0;

        LocalEventBus.Subscribe <MySimpleEventData>(
            eventData =>
        {
            totalData += eventData.Value;
            return(Task.CompletedTask);
        });

        await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(1));

        await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(2));

        await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(3));

        await LocalEventBus.PublishAsync(typeof(MySimpleEventData), new MySimpleEventData(4));

        Assert.Equal(10, totalData);
    }
Example #11
0
    public async Task Should_Not_Handle_Events_For_Base_Classes()
    {
        var totalData = 0;

        LocalEventBus.Subscribe <MyDerivedEventData>(
            eventData =>
        {
            totalData += eventData.Value;
            return(Task.CompletedTask);
        });

        await LocalEventBus.PublishAsync(new MySimpleEventData(1));  //Should not handle

        await LocalEventBus.PublishAsync(new MySimpleEventData(2));  //Should not handle

        await LocalEventBus.PublishAsync(new MyDerivedEventData(3)); //Should handle

        await LocalEventBus.PublishAsync(new MyDerivedEventData(4)); //Should handle

        Assert.Equal(7, totalData);
    }
Example #12
0
    public async Task Should_Call_Action_On_Event_With_Correct_Source()
    {
        var totalData = 0;

        LocalEventBus.Subscribe <MySimpleEventData>(
            eventData =>
        {
            totalData += eventData.Value;
            return(Task.CompletedTask);
        });

        await LocalEventBus.PublishAsync(new MySimpleEventData(1));

        await LocalEventBus.PublishAsync(new MySimpleEventData(2));

        await LocalEventBus.PublishAsync(new MySimpleEventData(3));

        await LocalEventBus.PublishAsync(new MySimpleEventData(4));

        Assert.Equal(10, totalData);
    }
Example #13
0
        public async Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight,
                                                    Hash irreversibleBlockHash)
        {
            // Create before IChainManager.SetIrreversibleBlockAsync so that we can correctly get the previous LIB info
            var eventDataToPublish = new NewIrreversibleBlockFoundEvent()
            {
                PreviousIrreversibleBlockHash   = chain.LastIrreversibleBlockHash,
                PreviousIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight,
                BlockHash   = irreversibleBlockHash,
                BlockHeight = irreversibleBlockHeight
            };

            var success = await _chainManager.SetIrreversibleBlockAsync(chain, irreversibleBlockHash);

            if (!success)
            {
                return;
            }

            await LocalEventBus.PublishAsync(eventDataToPublish);
        }
Example #14
0
    public async Task Should_Handle_Events_For_Derived_Classes()
    {
        var totalData = 0;

        LocalEventBus.Subscribe <MySimpleEventData>(
            eventData =>
        {
            totalData += eventData.Value;
            return(Task.CompletedTask);
        });

        await LocalEventBus.PublishAsync(new MySimpleEventData(1));  //Should handle directly registered class

        await LocalEventBus.PublishAsync(new MySimpleEventData(2));  //Should handle directly registered class

        await LocalEventBus.PublishAsync(new MyDerivedEventData(3)); //Should handle derived class too

        await LocalEventBus.PublishAsync(new MyDerivedEventData(4)); //Should handle derived class too

        Assert.Equal(10, totalData);
    }
Example #15
0
        public async Task WhiteHouse_Service_Insert_Valid_Presidents()
        {
            //Arrange
            LocalEventBus.Register <PresidentCreatedEvent>(
                eventData =>
            {
                var presidentEvent = eventData.President;
                Assert.True(presidentEvent.Id == "1" || presidentEvent.Id == "2");
            });

            var builder = new PresidentBuilder(LocalNotification)
                          .WithId("1")
                          .WithName("George Washington")
                          .WithAddress(new Address("Rua de teste", "123", "APT 12", new ZipCode("12345678")));

            // Act
            await _whiteHouseService.InsertPresidentAsync(builder);

            // Assert
            Assert.False(LocalNotification.HasNotification());
        }
        public void ParallelPubAndSub()
        {
            int count = 0;
            var mq    = new LocalEventBus(CreateLogger <LocalEventBus>());

            mq.Subscribe("topic", msg =>
            {
                Interlocked.Increment(ref count);
            });

            Parallel.For(0, 100, async(i) => { await mq.PublishAsync("topic", "a"); });
            int j = 0;

            while (count < 100 && j < 150)
            {
                Thread.Sleep(500);
                ++j;
            }

            Assert.Equal(100, count);
        }
        public async Task AttachBlockWithTransactionsAsync(BlockWithTransactions blockWithTransactions,
                                                           string senderPubkey, Func <Task> attachFinishedCallback = null)
        {
            var blockValid = await _blockSyncValidationService.ValidateBlockBeforeAttachAsync(blockWithTransactions);

            if (!blockValid)
            {
                Logger.LogDebug(
                    $"Sync block validation failed, peer: {senderPubkey}, block hash: {blockWithTransactions.GetHash()}, block height: {blockWithTransactions.Height}");
                await LocalEventBus.PublishAsync(new AbnormalPeerFoundEventData
                {
                    BlockHash   = blockWithTransactions.GetHash(),
                    BlockHeight = blockWithTransactions.Height,
                    PeerPubkey  = senderPubkey
                });

                return;
            }

            await _blockchainService.AddTransactionsAsync(blockWithTransactions.Transactions);

            var block = blockWithTransactions.ToBlock();
            await _blockchainService.AddBlockAsync(block);

            _blockSyncQueueService.Enqueue(async() =>
            {
                try
                {
                    await _blockAttachService.AttachBlockAsync(block);
                }
                finally
                {
                    if (attachFinishedCallback != null)
                    {
                        await attachFinishedCallback();
                    }
                }
            },
                                           KernelConstants.UpdateChainQueueName);
        }
        public async Task <bool> ValidateTransactionAsync(Transaction transaction, IChainContext chainContext)
        {
            if (!_transactionOptions.EnableTransactionExecutionValidation)
            {
                return(true);
            }

            var executionReturnSets = await _plainTransactionExecutingService.ExecuteAsync(new TransactionExecutingDto()
            {
                Transactions = new[] { transaction },
                BlockHeader  = new BlockHeader
                {
                    PreviousBlockHash = chainContext.BlockHash,
                    Height            = chainContext.BlockHeight + 1,
                    Time = TimestampHelper.GetUtcNow(),
                }
            }, CancellationToken.None);

            var executionValidationResult =
                executionReturnSets.FirstOrDefault()?.Status == TransactionResultStatus.Mined;

            if (!executionValidationResult)
            {
                var transactionId = transaction.GetHash();
                // TODO: Consider to remove TransactionExecutionValidationFailedEvent.
                await LocalEventBus.PublishAsync(new TransactionExecutionValidationFailedEvent
                {
                    TransactionId = transactionId
                });

                await LocalEventBus.PublishAsync(new TransactionValidationStatusChangedEvent
                {
                    TransactionId           = transactionId,
                    TransactionResultStatus = TransactionResultStatus.NodeValidationFailed,
                    Error = executionReturnSets.FirstOrDefault()?.TransactionResult?.Error ?? string.Empty
                });
            }

            return(executionValidationResult);
        }
Example #19
0
    public async Task Should_Call_Action_On_Event_With_Correct_Source_Async()
    {
        int totalData = 0;

        LocalEventBus.Subscribe <MySimpleEventData>(
            async eventData =>
        {
            await Task.Delay(20);
            Interlocked.Add(ref totalData, eventData.Value);
            await Task.Delay(20);
        });

        await LocalEventBus.PublishAsync(new MySimpleEventData(1));

        await LocalEventBus.PublishAsync(new MySimpleEventData(2));

        await LocalEventBus.PublishAsync(new MySimpleEventData(3));

        await LocalEventBus.PublishAsync(new MySimpleEventData(4));

        Assert.Equal(10, totalData);
    }
Example #20
0
    public async Task Should_Not_Call_Action_After_Unregister_1()
    {
        var totalData = 0;

        var registerDisposer = LocalEventBus.Subscribe <MySimpleEventData>(
            eventData =>
        {
            totalData += eventData.Value;
            return(Task.CompletedTask);
        });

        await LocalEventBus.PublishAsync(new MySimpleEventData(1));

        await LocalEventBus.PublishAsync(new MySimpleEventData(2));

        await LocalEventBus.PublishAsync(new MySimpleEventData(3));

        registerDisposer.Dispose();

        await LocalEventBus.PublishAsync(new MySimpleEventData(4));

        Assert.Equal(6, totalData);
    }
Example #21
0
        public async Task SetIrreversibleBlockAsync(Chain chain, long irreversibleBlockHeight,
                                                    Hash irreversibleBlockHash)
        {
            // Create before IChainManager.SetIrreversibleBlockAsync so that we can correctly get the previous LIB info
            var eventDataToPublish = new NewIrreversibleBlockFoundEvent()
            {
                PreviousIrreversibleBlockHash   = chain.LastIrreversibleBlockHash,
                PreviousIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight,
                BlockHash   = irreversibleBlockHash,
                BlockHeight = irreversibleBlockHeight
            };

            // TODO: move to background job, it will slow down our system
            // Clean last branches and not linked
            var toCleanBlocks = await _chainManager.CleanBranchesAsync(chain, chain.LastIrreversibleBlockHash,
                                                                       chain.LastIrreversibleBlockHeight);

            await RemoveBlocksAsync(toCleanBlocks);

            await _chainManager.SetIrreversibleBlockAsync(chain, irreversibleBlockHash);

            await LocalEventBus.PublishAsync(eventDataToPublish);
        }
        /// <summary>
        /// Call ACS4 method ValidateConsensusAfterExecution.
        /// </summary>
        /// <param name="chainContext"></param>
        /// <param name="consensusExtraData"></param>
        /// <returns></returns>
        public async Task <bool> ValidateConsensusAfterExecutionAsync(ChainContext chainContext,
                                                                      byte[] consensusExtraData)
        {
            var now = TimestampHelper.GetUtcNow();

            _blockTimeProvider.SetBlockTime(now);

            Logger.LogDebug($"Set block time to utc now: {now.ToDateTime():hh:mm:ss.ffffff}. Validate After.");

            var contractReaderContext =
                await _consensusReaderContextService.GetContractReaderContextAsync(chainContext);

            var validationResult = await _contractReaderFactory
                                   .Create(contractReaderContext)
                                   .ValidateConsensusAfterExecution
                                   .CallAsync(new BytesValue {
                Value = ByteString.CopyFrom(consensusExtraData)
            });

            if (validationResult == null)
            {
                Logger.LogDebug("Validation of consensus failed after execution.");
                return(false);
            }

            if (!validationResult.Success)
            {
                Logger.LogDebug($"Consensus validating after execution failed: {validationResult.Message}");
                await LocalEventBus.PublishAsync(new ConsensusValidationFailedEventData
                {
                    ValidationResultMessage = validationResult.Message,
                    IsReTrigger             = validationResult.IsReTrigger
                });
            }

            return(validationResult.Success);
        }
        public async Task PubAndSub()
        {
            int count = 0;
            var mq    = new LocalEventBus(CreateLogger <LocalEventBus>());

            mq.Subscribe("topic", msg =>
            {
                Interlocked.Increment(ref count);
            });
            for (int i = 0; i < 100; ++i)
            {
                await mq.PublishAsync("topic", "a");
            }

            int j = 0;

            while (count < 100 && j < 150)
            {
                Thread.Sleep(500);
                ++j;
            }

            Assert.Equal(100, count);
        }
        public async Task <BlockExecutionResult> ExecuteBlocksAsync(IEnumerable <Block> blocks)
        {
            var executionResult = new BlockExecutionResult();

            try
            {
                foreach (var block in blocks)
                {
                    var blockExecutedSet = await ProcessBlockAsync(block);

                    if (blockExecutedSet == null)
                    {
                        executionResult.ExecutedFailedBlocks.Add(block);
                        return(executionResult);
                    }

                    executionResult.SuccessBlockExecutedSets.Add(blockExecutedSet);
                    Logger.LogInformation(
                        $"Executed block {block.GetHash()} at height {block.Height}, with {block.Body.TransactionsCount} txns.");

                    await LocalEventBus.PublishAsync(new BlockAcceptedEvent { BlockExecutedSet = blockExecutedSet });
                }
            }
            catch (BlockValidationException ex)
            {
                if (!(ex.InnerException is ValidateNextTimeBlockValidationException))
                {
                    throw;
                }

                Logger.LogDebug(
                    $"Block validation failed: {ex.Message}. Inner exception {ex.InnerException.Message}");
            }

            return(executionResult);
        }
Example #25
0
 // This is the callback.
 public void OnNext(ConsensusRequestMiningEventData value)
 {
     Logger.LogDebug($"Published block mining event. Current block height: {value.PreviousBlockHeight}");
     LocalEventBus.PublishAsync(value);
 }
Example #26
0
        public async Task <List <ChainBlockLink> > ExecuteBlocksAttachedToLongestChain(Chain chain, BlockAttachOperationStatus status)
        {
            if (!status.HasFlag(BlockAttachOperationStatus.LongestChainFound))
            {
                Logger.LogTrace($"Try to attach to chain but the status is {status}.");
                return(null);
            }

            var successLinks = new List <ChainBlockLink>();
            var blockLinks   = await _chainManager.GetNotExecutedBlocks(chain.LongestChainHash);

            try
            {
                foreach (var blockLink in blockLinks)
                {
                    var linkedBlock = await _blockchainService.GetBlockByHashAsync(blockLink.BlockHash);

                    // Set the other blocks as bad block if found the first bad block
                    if (!await _blockValidationService.ValidateBlockBeforeExecuteAsync(linkedBlock))
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionFailed);

                        Logger.LogWarning($"Block validate fails before execution. block hash : {blockLink.BlockHash}");
                        break;
                    }

                    if (!await ExecuteBlock(blockLink, linkedBlock))
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionFailed);

                        Logger.LogWarning($"Block execution failed. block hash : {blockLink.BlockHash}");
                        break;
                    }

                    if (!await _blockValidationService.ValidateBlockAfterExecuteAsync(linkedBlock))
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionFailed);

                        Logger.LogWarning($"Block validate fails after execution. block hash : {blockLink.BlockHash}");
                        break;
                    }

                    await _chainManager.SetChainBlockLinkExecutionStatus(blockLink, ChainBlockLinkExecutionStatus.ExecutionSuccess);

                    successLinks.Add(blockLink);

                    Logger.LogInformation($"Executed block {blockLink.BlockHash} at height {blockLink.Height}.");

                    await LocalEventBus.PublishAsync(new BlockAcceptedEvent()
                    {
                        BlockHeader = linkedBlock.Header
                    });
                }
            }
            catch (ValidateNextTimeBlockValidationException ex)
            {
                Logger.LogWarning($"Block validate fails after execution. Exception message {ex.Message}");
            }

            if (successLinks.Count > 0)
            {
                var blockLink = successLinks.Last();
                await _blockchainService.SetBestChainAsync(chain, blockLink.Height, blockLink.BlockHash);

                await LocalEventBus.PublishAsync(new BestChainFoundEventData
                {
                    BlockHash      = chain.BestChainHash,
                    BlockHeight    = chain.BestChainHeight,
                    ExecutedBlocks = successLinks.Select(p => p.BlockHash).ToList()
                });
            }

            Logger.LogInformation($"Attach blocks to best chain, status: {status}, best chain hash: {chain.BestChainHash}, height: {chain.BestChainHeight}");

            return(blockLinks);
        }
Example #27
0
        /// <summary>
        /// Download and attach blocks
        /// UseSuggestedPeer == true: Download blocks from suggested peer directly;
        /// Target download height > peer lib height, download blocks from suggested peer;
        /// Target download height <= peer lib height, select a random peer to download.
        /// </summary>
        /// <param name="downloadBlockDto"></param>
        /// <returns></returns>
        public async Task <DownloadBlocksResult> DownloadBlocksAsync(DownloadBlockDto downloadBlockDto)
        {
            DownloadBlocksResult downloadResult;
            var peerPubkey = downloadBlockDto.SuggestedPeerPubkey;

            if (UseSuggestedPeer(downloadBlockDto))
            {
                downloadResult = await DownloadBlocksAsync(downloadBlockDto.PreviousBlockHash,
                                                           peerPubkey, downloadBlockDto.BatchRequestBlockCount,
                                                           downloadBlockDto.MaxBlockDownloadCount);
            }
            else
            {
                // If cannot get the blocks, there should be network problems or bad peer,
                // because we have selected peer with lib height greater than or equal to the target height.
                // 1. network problems, need to retry from other peer.
                // 2. not network problems, this peer or the last peer is bad peer, we need to remove it.
                var downloadTargetHeight =
                    downloadBlockDto.PreviousBlockHeight + downloadBlockDto.MaxBlockDownloadCount;
                var exceptedPeers = new List <string> {
                    _blockSyncStateProvider.LastRequestPeerPubkey
                };
                var retryTimes = 1;

                while (true)
                {
                    peerPubkey = GetRandomPeerPubkey(downloadBlockDto.SuggestedPeerPubkey, downloadTargetHeight,
                                                     exceptedPeers);

                    downloadResult = await DownloadBlocksAsync(downloadBlockDto.PreviousBlockHash, peerPubkey,
                                                               downloadBlockDto.BatchRequestBlockCount, downloadBlockDto.MaxBlockDownloadCount);

                    if (downloadResult.Success || retryTimes <= 0)
                    {
                        break;
                    }

                    exceptedPeers.Add(peerPubkey);
                    retryTimes--;
                }

                if (downloadResult.Success && downloadResult.DownloadBlockCount == 0)
                {
                    var checkResult = await CheckIrreversibleBlockHashAsync(downloadBlockDto.PreviousBlockHash,
                                                                            downloadBlockDto.PreviousBlockHeight);

                    if (checkResult.HasValue)
                    {
                        Logger.LogWarning(
                            $"Found bad peer: peerPubkey: {peerPubkey}, block hash: {downloadBlockDto.PreviousBlockHash}, block height: {downloadBlockDto.PreviousBlockHeight}");
                        await LocalEventBus.PublishAsync(new IncorrectIrreversibleBlockEventData
                        {
                            BlockHash         = downloadBlockDto.PreviousBlockHash,
                            BlockHeight       = downloadBlockDto.PreviousBlockHeight,
                            BlockSenderPubkey = checkResult.Value
                                ? peerPubkey
                                : _blockSyncStateProvider.LastRequestPeerPubkey
                        });
                    }
                }
            }

            return(downloadResult);
        }
Example #28
0
        private async Task <string[]> PublishTransactionsAsync(string[] rawTransactions)
        {
            var txIds        = new string[rawTransactions.Length];
            var transactions = new List <Transaction>();

            for (var i = 0; i < rawTransactions.Length; i++)
            {
                Transaction transaction;
                try
                {
                    var byteArray = ByteArrayHelper.HexStringToByteArray(rawTransactions[i]);
                    transaction = Transaction.Parser.ParseFrom(byteArray);
                }
                catch
                {
                    throw new UserFriendlyException(Error.Message[Error.InvalidTransaction],
                                                    Error.InvalidTransaction.ToString());
                }

                if (!IsValidMessage(transaction))
                {
                    throw new UserFriendlyException(Error.Message[Error.InvalidTransaction],
                                                    Error.InvalidTransaction.ToString());
                }

                var contractMethodDescriptor =
                    await GetContractMethodDescriptorAsync(transaction.To, transaction.MethodName);

                if (contractMethodDescriptor == null)
                {
                    throw new UserFriendlyException(Error.Message[Error.NoMatchMethodInContractAddress],
                                                    Error.NoMatchMethodInContractAddress.ToString());
                }

                var parameters = contractMethodDescriptor.InputType.Parser.ParseFrom(transaction.Params);

                if (!IsValidMessage(parameters))
                {
                    throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString());
                }

                if (!transaction.VerifySignature())
                {
                    throw new UserFriendlyException(Error.Message[Error.InvalidSignature],
                                                    Error.InvalidSignature.ToString());
                }

                transactions.Add(transaction);
                txIds[i] = transaction.GetHash().ToHex();
            }

            foreach (var transaction in transactions)
            {
                _transactionResultStatusCacheProvider.AddTransactionResultStatus(transaction.GetHash());
            }

            await LocalEventBus.PublishAsync(new TransactionsReceivedEvent
            {
                Transactions = transactions
            });

            return(txIds);
        }
Example #29
0
        public async Task <bool> ValidateBlockAfterExecuteAsync(IBlock block)
        {
            if (block.Header.Height == Constants.GenesisBlockHeight)
            {
                return(true);
            }

            var isParentChainBlockDataIndexed =
                _indexedCrossChainBlockDataDiscoveryService.TryDiscoverIndexedParentChainBlockDataAsync(block);

            Logger.LogTrace($"Try discovery indexed parent chain block data: {isParentChainBlockDataIndexed}");

            var isSideChainBlockDataIndexed =
                _indexedCrossChainBlockDataDiscoveryService.TryDiscoverIndexedSideChainBlockDataAsync(block);

            Logger.LogTrace($"Try discovery indexed side chain block data: {isSideChainBlockDataIndexed}");

            var extraData = ExtractCrossChainExtraData(block.Header);

            try
            {
                if (!isSideChainBlockDataIndexed && extraData != null)
                {
                    // cross chain extra data in block header should be null if no side chain block data indexed in contract
                    Logger.LogWarning(
                        $"Cross chain extra data should not be null, block height {block.Header.Height}, hash {block.GetHash()}.");
                    return(false);
                }

                if (!isParentChainBlockDataIndexed && !isSideChainBlockDataIndexed)
                {
                    return(true);
                }

                var indexedCrossChainBlockData =
                    await _crossChainIndexingDataService.GetIndexedCrossChainBlockDataAsync(block.Header.GetHash(), block.Header.Height);

                if (isSideChainBlockDataIndexed && indexedCrossChainBlockData.SideChainBlockData.Count > 0)
                {
                    if (extraData == null || !ValidateBlockExtraDataAsync(indexedCrossChainBlockData, extraData))
                    {
                        // extra data is null, or it is not consistent with contract
                        Logger.LogWarning(
                            $"Invalid cross chain extra data, block height {block.Header.Height}, hash {block.GetHash()}.");
                        return(false);
                    }
                }

                var validationResult = await ValidateCrossChainBlockDataAsync(indexedCrossChainBlockData, block.Header.PreviousBlockHash,
                                                                              block.Header.Height - 1);

                return(validationResult);
            }
            catch (ValidateNextTimeBlockValidationException ex)
            {
                throw new BlockValidationException(
                          $"Cross chain data is not ready at height: {block.Header.Height}, hash: {block.GetHash()}.", ex);
            }
            finally
            {
                await LocalEventBus.PublishAsync(new CrossChainDataValidatedEvent());
            }
        }
        public async Task <List <ChainBlockLink> > ExecuteBlocksAttachedToLongestChain(Chain chain,
                                                                                       BlockAttachOperationStatus status)
        {
            if (!status.HasFlag(BlockAttachOperationStatus.LongestChainFound))
            {
                Logger.LogTrace($"Try to attach to chain but the status is {status}.");
                return(null);
            }

            var successLinks  = new List <ChainBlockLink>();
            var successBlocks = new List <Block>();
            var blockLinks    = await _chainManager.GetNotExecutedBlocks(chain.LongestChainHash);

            try
            {
                foreach (var blockLink in blockLinks)
                {
                    var linkedBlock = await _blockchainService.GetBlockByHashAsync(blockLink.BlockHash);

                    var processResult = await TryProcessBlockAsync(linkedBlock);

                    if (!processResult)
                    {
                        await _chainManager.SetChainBlockLinkExecutionStatusAsync(blockLink,
                                                                                  ChainBlockLinkExecutionStatus.ExecutionFailed);

                        await _chainManager.RemoveLongestBranchAsync(chain);

                        return(null);
                    }

                    successLinks.Add(blockLink);
                    successBlocks.Add(linkedBlock);
                    Logger.LogInformation(
                        $"Executed block {blockLink.BlockHash} at height {blockLink.Height}, with {linkedBlock.Body.TransactionsCount} txns.");

                    await LocalEventBus.PublishAsync(new BlockAcceptedEvent { Block = linkedBlock });
                }
            }
            catch (BlockValidationException ex)
            {
                if (!(ex.InnerException is ValidateNextTimeBlockValidationException))
                {
                    await _chainManager.RemoveLongestBranchAsync(chain);

                    throw;
                }

                Logger.LogWarning(
                    $"Block validation failed: {ex.Message}. Inner exception {ex.InnerException.Message}");
            }
            catch (Exception ex)
            {
                await _chainManager.RemoveLongestBranchAsync(chain);

                Logger.LogWarning($"Block validate or execute fails. Exception message {ex.Message}");
                throw;
            }

            if (successLinks.Count == 0 || successLinks.Last().Height < chain.BestChainHeight)
            {
                Logger.LogWarning("No block execution succeed or no block is higher than best chain.");
                await _chainManager.RemoveLongestBranchAsync(chain);

                return(null);
            }

            await SetBestChainAsync(successLinks, chain);

            await _chainManager.SetChainBlockLinkExecutionStatusesAsync(successLinks,
                                                                        ChainBlockLinkExecutionStatus.ExecutionSuccess);

            await PublishBestChainFoundEventAsync(chain, successBlocks);

            Logger.LogInformation(
                $"Attach blocks to best chain, status: {status}, best chain hash: {chain.BestChainHash}, height: {chain.BestChainHeight}");

            return(blockLinks);
        }