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()); } } }
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); } } }
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); } } }
//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)})")); }