Beispiel #1
0
        public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData)
        {
            _taskQueueManager.Enqueue(async() =>
            {
                await _blockchainStateService.MergeBlockStateAsync(eventData.BlockHeight,
                                                                   eventData.BlockHash);
            }, KernelConstants.MergeBlockStateQueueName);

            _taskQueueManager.Enqueue(async() =>
            {
                // Clean chain branch
                var chain           = await _blockchainService.GetChainAsync();
                var discardedBranch = await _blockchainService.GetDiscardedBranchAsync(chain);

                if (discardedBranch.BranchKeys.Count > 0 || discardedBranch.NotLinkedKeys.Count > 0)
                {
                    _taskQueueManager.Enqueue(
                        async() => { await _blockchainService.CleanChainBranchAsync(discardedBranch); },
                        KernelConstants.UpdateChainQueueName);
                }

                // Clean transaction block index cache
                await _transactionBlockIndexService.CleanTransactionBlockIndexCacheAsync(eventData.BlockHeight);
            }, KernelConstants.ChainCleaningQueueName);

            return(Task.CompletedTask);
        }
Beispiel #2
0
        public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData)
        {
            _taskQueueManager.Enqueue(async() =>
            {
                await _blockchainStateService.MergeBlockStateAsync(eventData.BlockHeight,
                                                                   eventData.BlockHash);

                CleanChain(eventData.BlockHash, eventData.BlockHeight);
            }, KernelConstants.MergeBlockStateQueueName);

            return(Task.CompletedTask);
        }
        public Task HandleEventAsync(ConsensusRequestMiningEventData eventData)
        {
            _taskQueueManager.Enqueue(async() =>
            {
                var chain = await _blockchainService.GetChainAsync();
                if (eventData.PreviousBlockHash != chain.BestChainHash)
                {
                    Logger.LogDebug("Mining canceled because best chain already updated.");
                    return;
                }

                try
                {
                    var block = await _miningRequestService.RequestMiningAsync(new ConsensusRequestMiningDto
                    {
                        BlockTime           = eventData.BlockTime,
                        BlockExecutionTime  = eventData.BlockExecutionTime,
                        MiningDueTime       = eventData.MiningDueTime,
                        PreviousBlockHash   = eventData.PreviousBlockHash,
                        PreviousBlockHeight = eventData.PreviousBlockHeight
                    });

                    if (block != null)
                    {
                        await _blockchainService.AddBlockAsync(block);

                        Logger.LogTrace("Before enqueue attach job.");
                        _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(block),
                                                  KernelConstants.UpdateChainQueueName);

                        Logger.LogTrace("Before publish block.");

                        await LocalEventBus.PublishAsync(new BlockMinedEventData
                        {
                            BlockHeader = block.Header,
                        });
                    }
                    else
                    {
                        await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                    }
                }
                catch (Exception)
                {
                    await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                    throw;
                }
            }, KernelConstants.ConsensusRequestMiningQueueName);

            return(Task.CompletedTask);
        }
        public async Task HandleEventAsync(AnnouncementReceivedEventData eventData)
        {
            //Disable network lib
            return;

            var irreversibleBlockIndex =
                await _idpoSLastLastIrreversibleBlockDiscoveryService.FindLastLastIrreversibleBlockAsync(
                    eventData.SenderPubKey);

            if (irreversibleBlockIndex != null)
            {
                _taskQueueManager.Enqueue(async() =>
                {
                    var chain = await _blockchainService.GetChainAsync();
                    if (chain.LastIrreversibleBlockHeight < irreversibleBlockIndex.Height)
                    {
                        var hash = await _blockchainService.GetBlockHashByHeightAsync(chain,
                                                                                      irreversibleBlockIndex.Height, chain.BestChainHash);
                        if (hash == irreversibleBlockIndex.Hash)
                        {
                            await _blockchainService.SetIrreversibleBlockAsync(chain, irreversibleBlockIndex.Height,
                                                                               irreversibleBlockIndex.Hash);
                        }
                    }
                }, KernelConstants.UpdateChainQueueName);
            }
        }
        private async Task ProcessNewBlock(AnnouncementReceivedEventData header, string senderPubKey)
        {
            var blockHeight = header.Announce.BlockHeight;
            var blockHash   = header.Announce.BlockHash;

            Logger.LogTrace($"Receive header {{ hash: {blockHash}, height: {blockHeight} }} from {senderPubKey}.");

            if (!VerifyAnnouncement(header.Announce))
            {
                return;
            }

            var chain = await _blockchainService.GetChainAsync();

            if (blockHeight < chain.LastIrreversibleBlockHeight)
            {
                Logger.LogTrace($"Receive lower header {{ hash: {blockHash}, height: {blockHeight} }} " +
                                $"form {senderPubKey}, ignore.");
                return;
            }

            _taskQueueManager.Enqueue(async() =>
            {
                await _blockSyncJob.ExecuteAsync(new BlockSyncJobArgs
                {
                    SuggestedPeerPubKey = senderPubKey,
                    BlockHash           = blockHash,
                    BlockHeight         = blockHeight
                });
            }, OSConsts.BlockSyncQueueName);
        }
        public Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData)
        {
            _taskQueueManager.Enqueue(
                async() => { await _resourceExtractionService.HandleNewIrreversibleBlockFoundAsync(eventData); },
                KernelConstants.ChainCleaningQueueName);

            return(Task.CompletedTask);
        }
 public async Task HandleEventAsync(NewIrreversibleBlockFoundEvent eventData)
 {
     _taskQueueManager.Enqueue(async() =>
     {
         await _blockchainStateMergingService.MergeBlockStateAsync(eventData.BlockHeight,
                                                                   eventData.BlockHash);
     }, KernelConsts.MergeBlockStateQueueName);
 }
Beispiel #8
0
        public async Task HandleEventAsync(ConsensusRequestMiningEventData eventData)
        {
            try
            {
                _taskQueueManager.Enqueue(async() =>
                {
                    if (eventData.BlockTime > new Timestamp {
                        Seconds = 3600
                    } &&
                        eventData.BlockTime + eventData.BlockExecutionTime <
                        TimestampHelper.GetUtcNow())
                    {
                        Logger.LogTrace(
                            $"Will cancel mining due to timeout: Actual mining time: {eventData.BlockTime}, " +
                            $"execution limit: {eventData.BlockExecutionTime.Milliseconds()} ms.");
                    }

                    var block = await _minerService.MineAsync(eventData.PreviousBlockHash,
                                                              eventData.PreviousBlockHeight,
                                                              eventData.BlockTime, eventData.BlockExecutionTime);

                    await _blockchainService.AddBlockAsync(block);

                    var chain = await _blockchainService.GetChainAsync();
                    await LocalEventBus.PublishAsync(new BlockMinedEventData()
                    {
                        BlockHeader = block.Header,
                        HasFork     = block.Height <= chain.BestChainHeight
                    });

                    // Self mined block do not need do verify
                    _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(block),
                                              KernelConstants.UpdateChainQueueName);
                }, KernelConstants.ConsensusRequestMiningQueueName);
            }
            catch (Exception e)
            {
                Logger.LogError(e.ToString());
                throw;
            }
        }
Beispiel #9
0
        private async Task ProcessLogEventAsync(Block block, IrreversibleBlockFound irreversibleBlockFound)
        {
            try
            {
                var chain = await _blockchainService.GetChainAsync();

                if (chain.LastIrreversibleBlockHeight > irreversibleBlockFound.IrreversibleBlockHeight)
                {
                    return;
                }

                var libBlockHash = await _blockchainService.GetBlockHashByHeightAsync(chain,
                                                                                      irreversibleBlockFound.IrreversibleBlockHeight, block.GetHash());

                if (libBlockHash == null)
                {
                    return;
                }

                // enable transaction packing
                _transactionPackingService.EnableTransactionPacking();
                if (chain.LastIrreversibleBlockHeight == irreversibleBlockFound.IrreversibleBlockHeight)
                {
                    return;
                }

                if (chain.LastIrreversibleBlockHeight == irreversibleBlockFound.IrreversibleBlockHeight)
                {
                    return;
                }

                var blockIndex = new BlockIndex(libBlockHash, irreversibleBlockFound.IrreversibleBlockHeight);
                Logger.LogDebug($"About to set new lib height: {blockIndex.BlockHeight} " +
                                $"Event: {irreversibleBlockFound} " +
                                $"BlockIndex: {blockIndex.BlockHash} - {blockIndex.BlockHeight}");
                _taskQueueManager.Enqueue(
                    async() =>
                {
                    var currentChain = await _blockchainService.GetChainAsync();
                    if (currentChain.LastIrreversibleBlockHeight < blockIndex.BlockHeight)
                    {
                        await _blockchainService.SetIrreversibleBlockAsync(currentChain, blockIndex.BlockHeight,
                                                                           blockIndex.BlockHash);
                    }
                }, KernelConstants.UpdateChainQueueName);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Failed to resolve IrreversibleBlockFound event.");
                throw;
            }
        }
        public async Task HandleEventAsync(ConsensusRequestMiningEventData eventData)
        {
            try
            {
                var block = await _minerService.MineAsync(eventData.PreviousBlockHash, eventData.PreviousBlockHeight,
                                                          eventData.BlockTime, eventData.TimeSpan);

                //TODO: Before attach block should add block signature verify
                _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(block),
                                          KernelConsts.UpdateChainQueueName);
            }
            catch (Exception e)
            {
                Logger.LogError(e.ToString());
                throw;
            }
        }
Beispiel #11
0
        public Task HandleEventAsync(BlockAcceptedEvent eventData)
        {
            if (_syncStateService.SyncState == SyncState.Finished)
            {
                // if sync is finished we announce the block
                _networkService.BroadcastAnnounceAsync(eventData.Block.Header);
            }
            else if (_syncStateService.SyncState == SyncState.Syncing)
            {
                // if syncing and the block is higher the current target, try and update.
                if (_syncStateService.GetCurrentSyncTarget() <= eventData.Block.Header.Height)
                {
                    _taskQueueManager.Enqueue(async() => { await _syncStateService.UpdateSyncStateAsync(); },
                                              OSConstants.InitialSyncQueueName);
                }
            }

            return(Task.CompletedTask);
        }
Beispiel #12
0
        public void Enqueue(Func <Task> task, string queueName)
        {
            var enqueueTime = TimestampHelper.GetUtcNow();

            _taskQueueManager.Enqueue(async() =>
            {
                try
                {
                    Logger.LogTrace($"Execute block sync job: {queueName}, enqueue time: {enqueueTime}");

                    _blockSyncStateProvider.SetEnqueueTime(queueName, enqueueTime);
                    await task();
                }
                finally
                {
                    _blockSyncStateProvider.SetEnqueueTime(queueName, null);
                }
            }, queueName);
        }
Beispiel #13
0
        public async Task HandleEventAsync(BestChainFoundEventData eventData)
        {
            var chain = await _blockchainService.GetChainAsync();

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

            if (index != null)
            {
                _taskQueueManager.Enqueue(
                    async() =>
                {
                    var currentChain = await _blockchainService.GetChainAsync();
                    if (currentChain.LastIrreversibleBlockHeight < index.Height)
                    {
                        await _blockchainService.SetIrreversibleBlockAsync(currentChain, index.Height, index.Hash);
                    }
                }, KernelConsts.UpdateChainQueueName);
            }
        }
Beispiel #14
0
        public async Task HandleEventAsync(BestChainFoundEventData eventData)
        {
            Logger.LogDebug(
                $"Handle best chain found for lib: BlockHeight: {eventData.BlockHeight}, BlockHash: {eventData.BlockHash}");

            var chain = await _blockchainService.GetChainAsync();

            var index = await _irreversibleBlockRelatedEventsDiscoveryService.GetLastIrreversibleBlockIndexAsync(chain,
                                                                                                                 eventData.ExecutedBlocks);

            var unacceptableDistanceToLib = await _irreversibleBlockRelatedEventsDiscoveryService
                                            .GetUnacceptableDistanceToLastIrreversibleBlockHeightAsync(eventData.BlockHash);

            if (unacceptableDistanceToLib > 0)
            {
                Logger.LogDebug($"Unacceptable distance to lib height: {unacceptableDistanceToLib}");
                _transactionInclusivenessProvider.IsTransactionPackable = false;
            }
            else
            {
                _transactionInclusivenessProvider.IsTransactionPackable = true;
            }

            if (index != null)
            {
//                _transactionInclusivenessProvider.IsTransactionPackable = true;
                _taskQueueManager.Enqueue(
                    async() =>
                {
                    var currentChain = await _blockchainService.GetChainAsync();
                    if (currentChain.LastIrreversibleBlockHeight < index.Height)
                    {
                        await _blockchainService.SetIrreversibleBlockAsync(currentChain, index.Height, index.Hash);
                    }
                }, KernelConstants.UpdateChainQueueName);
            }

            Logger.LogDebug(
                $"Finish handle best chain found for lib : BlockHeight: {eventData.BlockHeight}, BlockHash: {eventData.BlockHash}");
        }
Beispiel #15
0
        public async Task ExecuteAsync(BlockSyncJobArgs args)
        {
            Logger.LogDebug($"Start block sync job, target height: {args.BlockHeight}, target block hash: {args.BlockHash}, peer: {args.SuggestedPeerPubKey}");

            var chain = await _blockchainService.GetChainAsync();

            try
            {
                if (args.BlockHash != null && args.BlockHeight < chain.BestChainHeight + 5)
                {
                    var peerBlockHash = args.BlockHash;
                    var peerBlock     = await _blockchainService.GetBlockByHashAsync(peerBlockHash);

                    if (peerBlock != null)
                    {
                        Logger.LogDebug($"Block {peerBlock} already know.");
                        return;
                    }

                    peerBlock = await _networkService.GetBlockByHashAsync(peerBlockHash, args.SuggestedPeerPubKey);

                    if (peerBlock == null)
                    {
                        Logger.LogWarning($"Get null block from peer, request block hash: {peerBlockHash}");
                        return;
                    }

                    _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(peerBlock),
                                              KernelConsts.UpdateChainQueueName);
                    return;
                }

                var blockHash = chain.LastIrreversibleBlockHash;
                Logger.LogDebug($"Trigger sync blocks from peers, lib height: {chain.LastIrreversibleBlockHeight}, lib block hash: {blockHash}");

                var blockHeight         = chain.LastIrreversibleBlockHeight;
                var count               = _networkOptions.BlockIdRequestCount;
                var peerBestChainHeight = await _networkService.GetBestChainHeightAsync(args.SuggestedPeerPubKey);

                while (true)
                {
                    // Limit block sync job count, control memory usage
                    chain = await _blockchainService.GetChainAsync();

                    if (chain.BestChainHeight < blockHeight - BlockSyncJobLimit)
                    {
                        Logger.LogWarning($"Pause sync task and wait for synced block to be processed, best chain height: {chain.BestChainHeight}");
                        break;
                    }

                    Logger.LogDebug($"Request blocks start with {blockHash}");

                    var blocks = await _networkService.GetBlocksAsync(blockHash, blockHeight, count, args.SuggestedPeerPubKey);

                    if (blocks == null || !blocks.Any())
                    {
                        Logger.LogDebug($"No blocks returned, current chain height: {chain.LongestChainHeight}.");
                        break;
                    }

                    Logger.LogDebug($"Received [{blocks.First()},...,{blocks.Last()}] ({blocks.Count})");

                    if (blocks.First().Header.PreviousBlockHash != blockHash)
                    {
                        Logger.LogError($"Current job hash : {blockHash}");
                        throw new InvalidOperationException($"Previous block not match previous {blockHash}, network back {blocks.First().Header.PreviousBlockHash}");
                    }

                    foreach (var block in blocks)
                    {
                        if (block == null)
                        {
                            Logger.LogWarning($"Get null block from peer, request block start: {blockHash}");
                            break;
                        }

                        Logger.LogDebug($"Processing block {block},  longest chain hash: {chain.LongestChainHash}, best chain hash : {chain.BestChainHash}");
                        _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(block),
                                                  KernelConsts.UpdateChainQueueName);
                    }

                    peerBestChainHeight = await _networkService.GetBestChainHeightAsync(args.SuggestedPeerPubKey);

                    if (blocks.Last().Height >= peerBestChainHeight)
                    {
                        break;
                    }

                    var lastBlock = blocks.Last();
                    blockHash   = lastBlock.GetHash();
                    blockHeight = lastBlock.Height;
                }
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Failed to finish block sync job");
            }
            finally
            {
                Logger.LogDebug($"Finishing block sync job, longest chain height: {chain.LongestChainHeight}");
            }
        }
Beispiel #16
0
 private void QueueNetworkTask(Func <Task> task)
 {
     _taskQueueManager.Enqueue(task, NetworkConstants.PeerReconnectionQueueName);
 }
        public Task HandleEventAsync(ConsensusRequestMiningEventData eventData)
        {
            try
            {
                _taskQueueManager.Enqueue(async() =>
                {
                    var chain = await _blockchainService.GetChainAsync();
                    if (eventData.PreviousBlockHash != chain.BestChainHash)
                    {
                        Logger.LogWarning("Mining canceled because best chain already updated.");
                        return;
                    }

                    if (!ValidateBlockMiningTime(eventData.BlockTime, eventData.MiningDueTime,
                                                 eventData.BlockExecutionTime))
                    {
                        await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                        return;
                    }

                    var blockExecutionDuration =
                        CalculateBlockMiningDuration(eventData.BlockTime, eventData.BlockExecutionTime);

                    Block block;
                    try
                    {
                        block = await _minerService.MineAsync(eventData.PreviousBlockHash,
                                                              eventData.PreviousBlockHeight, eventData.BlockTime, blockExecutionDuration);
                    }
                    catch (Exception)
                    {
                        await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                        throw;
                    }

                    if (TimestampHelper.GetUtcNow() <= eventData.MiningDueTime - blockExecutionDuration)
                    {
                        await _blockchainService.AddBlockAsync(block);

                        Logger.LogTrace("Before enqueue attach job.");
                        _taskQueueManager.Enqueue(async() => await _blockAttachService.AttachBlockAsync(block),
                                                  KernelConstants.UpdateChainQueueName);

                        Logger.LogTrace("Before publish block.");

                        await LocalEventBus.PublishAsync(new BlockMinedEventData
                        {
                            BlockHeader = block.Header,
//                            HasFork = block.Height <= chain.BestChainHeight
                        });
                    }
                    else
                    {
                        Logger.LogWarning(
                            $"Discard block {block.Height} and trigger once again because mining time slot expired. " +
                            $"MiningDueTime : {eventData.MiningDueTime}, " +
                            $"block execution duration limit : {blockExecutionDuration}");
                        await TriggerConsensusEventAsync(chain.BestChainHash, chain.BestChainHeight);
                    }
                }, KernelConstants.ConsensusRequestMiningQueueName);

                return(Task.CompletedTask);
            }
            catch (Exception e)
            {
                Logger.LogError(e.ToString());
                throw;
            }
        }