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