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); }
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); }
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); }
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); }
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()); } }
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() }); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
// This is the callback. public void OnNext(ConsensusRequestMiningEventData value) { Logger.LogDebug($"Published block mining event. Current block height: {value.PreviousBlockHeight}"); LocalEventBus.PublishAsync(value); }
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); }
/// <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); }
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); }
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); }