Ejemplo n.º 1
0
        private async Task SyncManyBlocksAsync(LyraClientForNode client, List <string> hashes)
        {
            _log.LogInformation($"Syncing {hashes.Count()} blocks...");

            foreach (var hash in hashes)
            {
                var blockResult = await client.GetBlockByHash(hash);

                if (blockResult.ResultCode == APIResultCodes.Success)
                {
                    var localBlock = await FindBlockByHashAsync(hash);

                    if (localBlock != null)
                    {
                        await RemoveBlockAsync(hash);
                    }

                    await AddBlockAsync(blockResult.GetBlock());
                }
            }
        }
Ejemplo n.º 2
0
        private async Task SyncManyBlocksAsync(LyraClientForNode client, ConsolidationBlock consBlock)
        {
            _log.LogInformation($"Syncing Consolidations {consBlock.Height} / {consBlock.Hash.Shorten()} ");

            var blocksResult = await client.GetBlocksByConsolidation(consBlock.Hash);

            if (blocksResult.ResultCode == APIResultCodes.Success)
            {
                foreach (var block in blocksResult.GetBlocks())
                {
                    var localBlock = await FindBlockByHashAsync(block.Hash);

                    if (localBlock != null)
                    {
                        await RemoveBlockAsync(block.Hash);
                    }

                    await AddBlockAsync(block);
                }
            }
        }
Ejemplo n.º 3
0
        public async Task ConsolidationBlockFailedAsync(string hash)
        {
            _log.LogError($"ConsolidationBlockFailed for {hash.Shorten()}");

            var client       = new LyraClientForNode(await FindValidSeedForSyncAsync());
            var consBlockReq = await client.GetBlockByHash(hash);

            if (consBlockReq.ResultCode == APIResultCodes.Success)
            {
                var consBlock = consBlockReq.GetBlock() as ConsolidationBlock;

                if (!await VerifyConsolidationBlock(consBlock))
                {
                    await SyncManyBlocksAsync(client, consBlock.blockHashes);
                }
            }
            else
            {
                if (_stateMachine.State == BlockChainState.Almighty)
                {
                    _stateMachine.Fire(_engageTriggerConsolidateFailed, hash);
                }
            }
        }
Ejemplo n.º 4
0
        //private async Task ResetUIDAsync()
        //{
        //    long uid = -1;
        //    if (_sys.Consensus != null)
        //    {
        //        var uidObj = await _sys.Consensus.Ask(new ConsensusService.AskForMaxActiveUID()) as ConsensusService.ReplyForMaxActiveUID;
        //        if (uidObj != null && uidObj.uid.HasValue)
        //        {
        //            uid = uidObj.uid.Value;
        //        }
        //    }
        //}

        private void CreateStateMachine()
        {
            _stateMachine.Configure(BlockChainState.Initializing)
            .Permit(BlockChainTrigger.LocalNodeStartup, BlockChainState.Startup);

            _stateMachine.Configure(BlockChainState.Startup)
            .PermitReentry(BlockChainTrigger.QueryingConsensusNode)
            .OnEntry(() => Task.Run(async() =>
            {
                while (true)
                {
                    while (Neo.Network.P2P.LocalNode.Singleton.ConnectedCount < 2)
                    {
                        await Task.Delay(1000);
                    }

                    _sys.Consensus.Tell(new ConsensusService.Startup());

                    await Task.Delay(10000);

                    _nodeStatus = new List <NodeStatus>();
                    _sys.Consensus.Tell(new ConsensusService.NodeInquiry());

                    await Task.Delay(10000);

                    var q = from ns in _nodeStatus
                            where ConsensusService.Board.PrimaryAuthorizers != null && ConsensusService.Board.PrimaryAuthorizers.Contains(ns.accountId)
                            group ns by ns.totalBlockCount into heights
                            orderby heights.Count() descending
                            select new
                    {
                        Height = heights.Key,
                        Count  = heights.Count()
                    };

                    if (q.Any())
                    {
                        var majorHeight = q.First();

                        _log.LogInformation($"CheckInquiryResult: Major Height = {majorHeight.Height} of {majorHeight.Count}");

                        var myStatus = await GetNodeStatusAsync();
                        if (myStatus.totalBlockCount == 0 && majorHeight.Height == 0 && majorHeight.Count >= 2)
                        {
                            _stateMachine.Fire(_engageTriggerStartupSync, majorHeight.Height);
                            //_stateMachine.Fire(BlockChainTrigger.ConsensusBlockChainEmpty);
                            if (await FindLatestBlockAsync() == null && ConsensusService.IsThisNodeSeed0)
                            {
                                await Task.Delay(15000);
                                Genesis();
                            }
                        }
                        else if (majorHeight.Height >= 2 && majorHeight.Count >= 2)
                        {
                            _stateMachine.Fire(_engageTriggerStartupSync, majorHeight.Height);
                        }
                        //else if (majorHeight.Height > 2 && majorHeight.Count < 2)
                        //{
                        //    _state.Fire(BlockChainTrigger.ConsensusNodesOutOfSync);
                        //}
                        else
                        {
                            _stateMachine.Fire(BlockChainTrigger.QueryingConsensusNode);
                        }
                        break;
                    }
                }
            }))
            .Permit(BlockChainTrigger.ConsensusBlockChainEmpty, BlockChainState.Genesis)
            .Permit(BlockChainTrigger.ConsensusNodesSynced, BlockChainState.Engaging);

            _stateMachine.Configure(BlockChainState.Genesis)
            .OnEntry(() => Task.Run(async() =>
            {
                if (await FindLatestBlockAsync() == null && ConsensusService.IsThisNodeSeed0)
                {
                    Genesis();
                }
            }))
            .Permit(BlockChainTrigger.GenesisDone, BlockChainState.Startup);

            _stateMachine.Configure(BlockChainState.Engaging)
            .OnEntryFrom(_engageTriggerStartupSync, (uid) => Task.Run(async() =>
            {
                var stateFn = $"{Utilities.LyraDataDir}{Utilities.PathSeperator}Consolidation.json";

                var state = new ConsolidationState {
                    LocalLastConsolidationHeight = 0
                };
                if (File.Exists(stateFn))
                {
                    state = JsonConvert.DeserializeObject <ConsolidationState>(File.ReadAllText(stateFn));
                }

                var unConsSynced = 0;
                while (true)
                {
                    var client = new LyraClientForNode(await FindValidSeedForSyncAsync());

                    // compare state
                    var seedSyncState = await client.GetSyncState();
                    var mySyncState   = await GetNodeStatusAsync();
                    if (seedSyncState.ResultCode == APIResultCodes.Success && seedSyncState.Status.Equals(mySyncState))
                    {
                        _log.LogInformation("Fully Synced with seeds.");
                        break;
                    }

                    var latestSeedCons = (await client.GetLastConsolidationBlockAsync()).GetBlock() as ConsolidationBlock;

                    if (state.LocalLastConsolidationHeight < latestSeedCons.Height)
                    {
                        var consBlocksResult = await client.GetConsolidationBlocks(state.LocalLastConsolidationHeight);
                        if (consBlocksResult.ResultCode == APIResultCodes.Success)
                        {
                            var consBlocks = consBlocksResult.GetBlocks().Cast <ConsolidationBlock>();
                            foreach (var consBlock in consBlocks)
                            {
                                if (!await VerifyConsolidationBlock(consBlock, latestSeedCons.Height))
                                {
                                    await SyncManyBlocksAsync(client, consBlock);
                                }

                                state.LocalLastConsolidationHeight = consBlock.Height;
                            }
                        }
                    }
                    else
                    {
                        // sync unconsolidated blocks
                        var unConsBlockResult = await client.GetUnConsolidatedBlocks();
                        if (unConsBlockResult.ResultCode == APIResultCodes.Success)
                        {
                            if (unConsSynced < unConsBlockResult.Entities.Count)
                            {
                                await SyncManyBlocksAsync(client, unConsBlockResult.Entities);
                                unConsSynced = unConsBlockResult.Entities.Count;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    File.WriteAllText(stateFn, JsonConvert.SerializeObject(state));
                }

                _stateMachine.Fire(BlockChainTrigger.LocalNodeConsolidated);
            }))
            .Permit(BlockChainTrigger.LocalNodeConsolidated, BlockChainState.Almighty);

            _stateMachine.Configure(BlockChainState.Almighty)
            .OnEntry(() => Task.Run(async() =>
            {
                LyraSystem.Singleton.Consensus.Tell(new ConsensusService.Startup());
            }))
            .Permit(BlockChainTrigger.LocalNodeOutOfSync, BlockChainState.Startup);

            _stateMachine.OnTransitioned(t => _log.LogWarning($"OnTransitioned: {t.Source} -> {t.Destination} via {t.Trigger}({string.Join(", ", t.Parameters)})"));
        }