private async Task RefreshNodeStatusAsync() { int port = 4504; if (config["network"].Equals("mainnet", StringComparison.InvariantCultureIgnoreCase)) { port = 5504; } var bb = await client.GetBillBoardAsync(); var bag = new ConcurrentDictionary <string, GetSyncStateAPIResult>(); var tasks = bb.NodeAddresses .Select(async node => { var lcx = LyraRestClient.Create(config["network"], Environment.OSVersion.ToString(), "Nebula", "1.4", $"https://{node.Value}:{port}/api/Node/"); try { var syncState = await lcx.GetSyncState(); bag.TryAdd(node.Key, syncState); } catch (Exception ex) { bag.TryAdd(node.Key, null); } }); await Task.WhenAll(tasks); var nvs = new NodeViewState( isLoading: false, billBoard: bb, NodeStatus: bag, ipdb: config["ipdb"]); nvs.Id = 0; // create new for liteDB nvs.TimeStamp = DateTime.UtcNow; History.Insert(nvs); }
/// <summary> /// if this node is seed0 then sync with seeds others (random choice the one that is in normal state) /// if this node is seed1+ then sync with seed0 /// otherwise sync with any seed node /// </summary> private void SyncBlocksFromSeeds(long ToUIndex) { return; Task.Run(async() => { while (true) { _log.LogInformation("BlockChain Doing Sync..."); string syncWithUrl = null; LyraRestClient client = null; long syncToUIndex = ToUIndex; if (syncWithUrl == null) { // no node to sync. if (NodeService.Instance.PosWallet.AccountId == ProtocolSettings.Default.StandbyValidators[0]) { // seed0. no seed to sync. this seed must have the NORMAL blockchain break; } else { _log.LogError("No seed node in normal state. Wait..."); await Task.Delay(300 * 1000); } } else { // update latest billboard var board = await client.GetBillBoardAsync(); LyraSystem.Singleton.Consensus.Tell(board); // do sync with node long startUIndex = 0;//await _store.GetNewestBlockUIndexAsync() + 1; // seed0 not rollback. seed0 rollback manually if necessary. if (startUIndex - 1 > syncToUIndex && NodeService.Instance.PosWallet.AccountId != ProtocolSettings.Default.StandbyValidators[0]) { // detect blockchain rollback _log.LogCritical($"BlockChain roll back detected!!! Roll back from {startUIndex} to {syncToUIndex}."); // Confirm? [Y/n]"); string answer = "y"; // Console.ReadLine(); if (string.IsNullOrEmpty(answer) || answer.ToLower() == "y" || answer.ToLower() == "yes") { for (var i = syncToUIndex + 1; i <= startUIndex - 1; i++) { //await RemoveBlockAsync(i); } startUIndex = syncToUIndex + 1; } else { // can't go Environment.Exit(1); } } _log.LogInformation($"BlockChain Doing sync from {startUIndex} to {syncToUIndex} from node {syncWithUrl}"); async Task <bool> DoCopyBlock(long fromUIndex, long toUIndex) { var authorizers = new AuthorizersFactory(); for (long j = fromUIndex; j <= toUIndex; j++) { /*var blockResult = await client.GetBlockByUIndex(j).ConfigureAwait(false); * if (blockResult.ResultCode == APIResultCodes.Success) * { * var blockX = blockResult.GetBlock() as TransactionBlock; * //if(blockX.UIndex <= 2) // the two genesis service block * //{ * // await AddBlockAsync(blockX); * // continue; * //} * * //var stopwatch = Stopwatch.StartNew(); * * var authorizer = authorizers.Create(blockX.BlockType); * var localAuthResult = await authorizer.AuthorizeAsync(blockX, false); * * //stopwatch.Stop(); * //_log.LogInformation($"Authorize takes {stopwatch.ElapsedMilliseconds} ms"); * * if(localAuthResult.Item1 == APIResultCodes.Success) * { * await AddBlockAsync(blockX); * fromUIndex = j + 1; * _log.LogInformation($"BlockChain Synced Block Number: {j}"); * } * else * { * _log.LogInformation($"BlockChain Block Number: {j} verify failed for {localAuthResult.Item1}"); * return false; * } * } * else * { * // error * _log.LogInformation($"Error syncing block: {blockResult.ResultCode}"); * continue; * }*/ } return(true); } var copyOK = await DoCopyBlock(startUIndex, syncToUIndex).ConfigureAwait(false); if (copyOK) { //// check missing block //for(long k = 1; k <= startUIndex; k++) //{ // if(await BlockChain.Singleton.GetBlockByUIndex(k) == null) // { // _log.LogInformation($"syncing one missing block: {k}"); // await DoCopyBlock(k, k).ConfigureAwait(false); // } //} break; } else { await Task.Delay(5000).ConfigureAwait(false); } } } LyraSystem.Singleton.Consensus.Tell(new ConsensusService.BlockChainSynced()); _log.LogInformation("BlockChain Sync Completed."); }); }
/// <summary> /// if this node is seed0 then sync with seeds others (random choice the one that is in normal state) /// if this node is seed1+ then sync with seed0 /// otherwise sync with any seed node /// </summary> private void SyncBlocksFromSeeds(long ToUIndex) { InSyncing = true; Task.Run(async() => { while (true) { _log.LogInformation("BlockChain Doing Sync..."); string syncWithUrl = null; LyraRestClient client = null; long syncToUIndex = ToUIndex; for (int i = 0; i < ProtocolSettings.Default.SeedList.Length; i++) { if (NodeService.Instance.PosWallet.AccountId == ProtocolSettings.Default.StandbyValidators[i]) // self { continue; } try { var addr = ProtocolSettings.Default.SeedList[i].Split(':')[0]; var apiUrl = $"https://{addr}:4505/api/LyraNode/"; _log.LogInformation("Platform {1} Use seed node of {0}", apiUrl, Environment.OSVersion.Platform); client = await LyraRestClient.CreateAsync(NetworkID, Environment.OSVersion.Platform.ToString(), "LyraNode2", "1.0", apiUrl); var mode = await client.GetSyncState(); if (mode.ResultCode == APIResultCodes.Success && mode.Mode == ConsensusWorkingMode.Normal) { syncWithUrl = apiUrl; if (syncToUIndex == 0) { syncToUIndex = mode.NewestBlockUIndex; } break; } } catch (Exception ex) { _log.LogWarning($"Trying to sync.. {ex.Message}"); } } if (syncWithUrl == null) { // no node to sync. if (NodeService.Instance.PosWallet.AccountId == ProtocolSettings.Default.StandbyValidators[0]) { // seed0. no seed to sync. this seed must have the NORMAL blockchain var board = new BillBoard(); board.Add(NodeService.Instance.PosWallet.AccountId); // add me! LyraSystem.Singleton.Consensus.Tell(board); break; } else { _log.LogError("No seed node in normal state. Wait..."); await Task.Delay(300 * 1000); } } else { // update latest billboard var board = await client.GetBillBoardAsync(); LyraSystem.Singleton.Consensus.Tell(board); // do sync with node long startUIndex = _store.GetNewestBlockUIndex() + 1; _log.LogInformation($"BlockChain Doing sync from {startUIndex} to {syncToUIndex} from node {syncWithUrl}"); async Task <bool> DoCopyBlock() { for (long j = startUIndex; j <= syncToUIndex; j++) { var blockResult = await client.GetBlockByUIndex(j).ConfigureAwait(false); if (blockResult.ResultCode == APIResultCodes.Success) { AddBlock(blockResult.GetBlock() as TransactionBlock); startUIndex = j + 1; _log.LogInformation($"BlockChain Synced Block Number: {j}"); } else if (blockResult.ResultCode == APIResultCodes.BlockNotFound) { return(true); } else { // error _log.LogError($"Error syncing block: {blockResult.ResultCode}"); return(false); } } return(true); } var copyOK = await DoCopyBlock().ConfigureAwait(false); if (copyOK) { break; } else { await Task.Delay(5000).ConfigureAwait(false); } } } InSyncing = false; LyraSystem.Singleton.Consensus.Tell(new ConsensusService.BlockChainSynced()); _log.LogInformation("BlockChain Sync Completed."); }); }
/// <summary> /// if this node is seed0 then sync with seeds others (random choice the one that is in normal state) /// if this node is seed1+ then sync with seed0 /// otherwise sync with any seed node /// </summary> private void SyncBlocksFromSeeds(long ToUIndex) { InSyncing = true; Task.Run(async() => { while (true) { _log.LogInformation("BlockChain Doing Sync..."); string syncWithUrl = null; LyraRestClient client = null; long syncToUIndex = ToUIndex; #if DEBUG for (int i = 0; i < 2; i++) // save time #else for (int i = 0; i < ProtocolSettings.Default.SeedList.Length; i++) #endif { if (NodeService.Instance.PosWallet.AccountId == ProtocolSettings.Default.StandbyValidators[i]) // self { continue; } try { var addr = ProtocolSettings.Default.SeedList[i].Split(':')[0]; var apiUrl = $"https://{addr}:4505/api/LyraNode/"; _log.LogInformation("Platform {1} Use seed node of {0}", apiUrl, Environment.OSVersion.Platform); client = await LyraRestClient.CreateAsync(NetworkID, Environment.OSVersion.Platform.ToString(), "LyraNode2", "1.0", apiUrl); var mode = await client.GetSyncState(); if (mode.ResultCode == APIResultCodes.Success && mode.Mode == ConsensusWorkingMode.Normal) { syncWithUrl = apiUrl; if (syncToUIndex == 0) { syncToUIndex = mode.NewestBlockUIndex; } break; } } catch (Exception ex) { _log.LogWarning($"Trying to sync.. {ex.Message}"); } } if (syncWithUrl == null) { // no node to sync. if (NodeService.Instance.PosWallet.AccountId == ProtocolSettings.Default.StandbyValidators[0]) { // seed0. no seed to sync. this seed must have the NORMAL blockchain break; } else { _log.LogError("No seed node in normal state. Wait..."); await Task.Delay(300 * 1000); } } else { // update latest billboard var board = await client.GetBillBoardAsync(); LyraSystem.Singleton.Consensus.Tell(board); // do sync with node long startUIndex = await _store.GetNewestBlockUIndexAsync() + 1; _log.LogInformation($"BlockChain Doing sync from {startUIndex} to {syncToUIndex} from node {syncWithUrl}"); async Task <bool> DoCopyBlock(long fromUIndex, long toUIndex) { var authorizers = new AuthorizersFactory(); for (long j = fromUIndex; j <= toUIndex; j++) { var blockResult = await client.GetBlockByUIndex(j).ConfigureAwait(false); if (blockResult.ResultCode == APIResultCodes.Success) { var blockX = blockResult.GetBlock() as TransactionBlock; if (blockX.UIndex <= 2) // the two genesis service block { await AddBlockAsync(blockX); continue; } var stopwatch = Stopwatch.StartNew(); var authorizer = authorizers.Create(blockX.BlockType); var localAuthResult = await authorizer.AuthorizeAsync(blockX, false); stopwatch.Stop(); _log.LogInformation($"Authorize takes {stopwatch.ElapsedMilliseconds} ms"); if (localAuthResult.Item1 == APIResultCodes.Success) { await AddBlockAsync(blockX); fromUIndex = j + 1; _log.LogInformation($"BlockChain Synced Block Number: {j}"); } else { _log.LogInformation($"BlockChain Block Number: {j} verify failed for {localAuthResult.Item1}"); return(false); } } else { // error _log.LogInformation($"Error syncing block: {blockResult.ResultCode}"); continue; } } return(true); } var copyOK = await DoCopyBlock(startUIndex, syncToUIndex).ConfigureAwait(false); if (copyOK) { //// check missing block //for(long k = 1; k <= startUIndex; k++) //{ // if(await BlockChain.Singleton.GetBlockByUIndex(k) == null) // { // _log.LogInformation($"syncing one missing block: {k}"); // await DoCopyBlock(k, k).ConfigureAwait(false); // } //} break; } else { await Task.Delay(5000).ConfigureAwait(false); } } } InSyncing = false; LyraSystem.Singleton.Consensus.Tell(new ConsensusService.BlockChainSynced()); _log.LogInformation("BlockChain Sync Completed."); }); }