Esempio n. 1
0
        public BlockSynchronizer(IChainService chainService, IBlockValidationService blockValidationService,
                                 IBlockExecutor blockExecutor, IBlockSet blockSet, IBlockHeaderValidator blockHeaderValidator)
        {
            _chainService           = chainService;
            _blockValidationService = blockValidationService;
            _blockExecutor          = blockExecutor;
            _blockSet             = blockSet;
            _blockHeaderValidator = blockHeaderValidator;

            _stateFSM = new NodeStateFSM().Create();

            _logger = LogManager.GetLogger(nameof(BlockSynchronizer));

            _terminated       = false;
            _executeNextBlock = true;

            MessageHub.Instance.Subscribe <StateEvent>(e =>
            {
                _stateFSM.ProcessWithStateEvent(e);
                _logger?.Trace($"BlockSynchronizer CurrentState: {CurrentState}");
                MessageHub.Instance.Publish(new FSMStateChanged(CurrentState));
            });

            MessageHub.Instance.Subscribe <EnteringState>(async inState =>
            {
                if (inState.NodeState.ShouldLockMiningWhenEntering())
                {
                    MessageHub.Instance.Publish(new LockMining(true));
                }

                switch (inState.NodeState)
                {
                case NodeState.Catching:
                    await ReceiveNextValidBlock();
                    break;

                case NodeState.Caught:
                    await ReceiveNextValidBlock();
                    break;

                case NodeState.ExecutingLoop:
                    // This node is free to mine a block during executing maybe-incorrect block again and again.
                    MessageHub.Instance.Publish(new LockMining(false));
                    break;

                case NodeState.GeneratingConsensusTx:
                    MessageHub.Instance.Publish(new LockMining(false));
                    break;

                case NodeState.Reverting:
                    await HandleFork();
                    break;
                }
            });

            MessageHub.Instance.Subscribe <LeavingState>(inState =>
            {
                if (inState.NodeState.ShouldUnlockMiningWhenLeaving())
                {
                    MessageHub.Instance.Publish(new LockMining(false));
                }
            });

            MessageHub.Instance.Subscribe <HeadersReceived>(async inHeaders =>
            {
                if (inHeaders?.Headers == null || !inHeaders.Headers.Any())
                {
                    _logger?.Warn("Null headers or header list is empty.");
                    return;
                }

                var headers = inHeaders.Headers.OrderByDescending(h => h.Index).ToList();

                foreach (var blockHeader in headers)
                {
                    // Get previous block from the chain
                    var correspondingBlockHeader = await BlockChain.GetBlockByHeightAsync(blockHeader.Index - 1);

                    // If the hash of this previous block corresponds to "previous block hash" of the current header
                    // the link has been found
                    if (correspondingBlockHeader.BlockHashToHex == blockHeader.PreviousBlockHash.DumpHex())
                    {
                        // Launch header accepted event and return
                        MessageHub.Instance.Publish(new HeaderAccepted(blockHeader));
                        return;
                    }
                }

                // Launch unlinkable again with the last headers index
                MessageHub.Instance.Publish(new UnlinkableHeader(headers.Last()));
            });

            MessageHub.Instance.Subscribe <DPoSStateChanged>(inState =>
            {
                MessageHub.Instance.Publish(inState.IsMining ? StateEvent.MiningStart : StateEvent.MiningEnd);
            });

            MessageHub.Instance.Subscribe <BlockMined>(inBlock =>
            {
                // Update DPoS process.
                //MessageHub.Instance.Publish(UpdateConsensus.Update);
                AddMinedBlock(inBlock.Block);
            });

            MessageHub.Instance.Subscribe <BlockMinedAndStored>(inBlock =>
            {
                // Update DPoS process.
                MessageHub.Instance.Publish(UpdateConsensus.Update);
                HandleMinedAndStroedBlock(inBlock.Block);
            });

            MessageHub.Instance.Subscribe <TerminationSignal>(signal =>
            {
                if (signal.Module == TerminatedModuleEnum.BlockSynchronizer)
                {
                    _terminated = true;
                    MessageHub.Instance.Publish(new TerminatedModule(TerminatedModuleEnum.BlockSynchronizer));
                }
            });
        }
Esempio n. 2
0
 public BlockHeaderValidator(IBlockSet blockSet, IChainService chainService)
 {
     _blockSet     = blockSet;
     _chainService = chainService;
 }