public bool IsChainUpToDate(out NodeChainHeight longestChainNode) { longestChainNode = null; bool isUpToDate = false; int margin = 1; Node longestNode = null; int longestChain = GetLongestChain(out longestNode); if (longestChain == -1) { throw new ValidationException(ResponseCodes.NoChainExistOnNetwork, "Failed to sync chain: " + ResponseMessages.NoChainExistOnNetwork); } //Compare with self height ViewerServices viewerServices = new ViewerServices(); int localHeight = viewerServices.GetChainHeight(); if (longestChain > (localHeight + margin)) { isUpToDate = false; } else { isUpToDate = true; } longestChainNode = new NodeChainHeight(); longestChainNode.Address = longestNode.ServerAddress; longestChainNode.ChainHeight = longestChain; return(isUpToDate); }
public void SyncChain(NodeChainHeight longestChainNode) { ApplicationLog.Info("Downloading chain."); ApplicationState.ConsensusState = ConsensusStates.SyncingChain; ViewerServices viewerServices = new ViewerServices(); int localHeight = viewerServices.GetChainHeight(); if (localHeight < 0) { localHeight = 0; } //TODO: Future enhancement to download from different nodes in parellel int currentHeight = localHeight; int lastHeight = longestChainNode.ChainHeight; while (currentHeight <= lastHeight) { var blocks = GetBlocks(longestChainNode.Address, currentHeight, currentHeight + 10); foreach (var block in blocks) { AddBlockToChain(block); currentHeight++; } } }
public async void NextEpoch() { try { ApplicationLog.Info("Beginning new epoch iteration"); ApplicationState.ConsensusState = ConsensusStates.BeginningEpoch; ApplicationState.CurrentSpeaker = null; NodeChainHeight longestChainNode = null; if (ApplicationState.DisconnectedNodes.Count > 0) { RemoveDisconnectedNodes(); //TODO: subsequent epoch can retrieve network nodes from other nodes instead of from seed RetrieveNetworkNodes(); } if (IsChainUpToDate(out longestChainNode)) { ApplicationState.IsChainUpToDate = true; ApplicationState.LiveEpochCount++; SelectSpeaker(); } else { ApplicationState.IsChainUpToDate = false; SyncChain(longestChainNode); ApplicationState.LiveEpochCount = 0; ApplicationState.PendingRecords.Clear(); RegisterSelfOnNetwork(ApplicationState.Node.WalletAddress, ApplicationState.Node.Signature, false); NextEpoch(); } } catch (Exception ex) { ApplicationLog.Exception(ex); ApplicationLog.Info("Retry in 30 seconds."); await Task.Delay(30 * 1000); NextEpoch(); } }