// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddBlazoredLocalStorage(); services.Configure <reCAPTCHAVerificationOptions>(Configuration.GetSection("reCAPTCHA")); services.Configure <SwapOptions>(Configuration.GetSection("Swap")); services.AddTransient <SampleAPI>(); services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton <WeatherForecastService>(); services.AddMvc(); services.AddControllers(); // for Metamask wallet services.AddScoped <IMetamaskInterop, MetamaskBlazorInterop>(); services.AddScoped <MetamaskService>(); services.AddScoped <MetamaskInterceptor>(); services.AddHttpClient <FetchDataActionEffect>(); var networkid = Configuration["network"]; // use dedicate host to avoid "random" result from api.lyra.live which is dns round-robbined. <-- not fail safe //services.AddTransient<LyraRestClient>(a => LyraRestClient.Create(networkid, Environment.OSVersion.ToString(), "Nebula", "1.0"/*, $"http://nebula.{networkid}.lyra.live:{Neo.Settings.Default.P2P.WebAPI}/api/Node/"*/)); services.AddScoped <ILyraAPI>(provider => { var client = new LyraAggregatedClient(networkid, true); var t = Task.Run(async() => { await client.InitAsync(); }); Task.WaitAll(t); return(client); }); // for database services.Configure <LiteDbOptions>(Configuration.GetSection("LiteDbOptions")); services.AddSingleton <ILiteDbContext, LiteDbContext>(); services.Configure <MongoDbOptions>(Configuration.GetSection("Lyra")); services.AddSingleton <IMongoDbContext, MongoDbContext>(); services.AddSingleton <RichList>(); services.AddTransient <INodeHistory, NodeHistory>(); services.AddHostedService <IncentiveProgram>(); var currentAssembly = typeof(Startup).Assembly; services.AddFluxor(options => options.ScanAssemblies(currentAssembly)); services.AddAntDesign(); }
public async Task TestGetServiceBlockAsync() { var client = LyraRestClient.Create(networkId, "Windows", "UnitTest", "1.0"); var aggClient = new LyraAggregatedClient(networkId, false, null); await aggClient.InitAsync(); var svcBlock1 = await client.GetLastServiceBlockAsync(); var svcBlock2 = await aggClient.GetLastServiceBlockAsync(); Assert.AreEqual(svcBlock1, svcBlock2); }
protected override void OnInitialized() { BriefHist = Enumerable.Empty <HistInfo>(); base.OnInitialized(); // load history first var latest = History.FindLatest(); if (latest == null) { Dispatcher.Dispatch(new NodeViewAction()); } else { BriefHist = History.FindHistory(100); if (BriefHist.Any()) { selId = BriefHist.First().id; } Dispatcher.Dispatch(new LoadHistoryAction { historyState = latest }); StateHasChanged(); } NodeState.StateChanged += NodeState_StateChanged; seedHosts = new Dictionary <string, string>(); _ = Task.Run(() => { var aggClient = new LyraAggregatedClient(Configuration["network"], true); var seeds = aggClient.GetSeedNodes(); foreach (var seed in seeds) { try { var ip = Dns.GetHostEntry(seed); seedHosts.Add($"{ip.AddressList[0]}", seed); } catch { } } }); }
public async Task GenesisAsync() { // genesis _log.LogInformation("all seed nodes are ready. do genesis."); var svcGen = await CreateServiceGenesisBlockAsync(); await SendBlockToConsensusAndWaitResultAsync(svcGen, ProtocolSettings.Default.StandbyValidators.ToList()); await Task.Delay(5000); var tokenGen = CreateLyraTokenGenesisBlock(svcGen); // DEBUG //_log.LogInformation("genesis block string:\n" + tokenGen.GetHashInput()); await SendBlockToConsensusAndWaitResultAsync(tokenGen); await Task.Delay(2000); var pf = await CreatePoolFactoryBlockAsync(); await SendBlockToConsensusAndWaitResultAsync(pf); await Task.Delay(25000); // because cons block has a time shift. var consGen = CreateConsolidationGenesisBlock(svcGen, tokenGen, pf); await SendBlockToConsensusAndWaitResultAsync(consGen); await Task.Delay(1000); _log.LogInformation("Genesis is done."); await Task.Delay(30000); // distribute staking coin to pre-defined authorizers var memStore = new AccountInMemoryStorage(); Wallet.Create(memStore, "tmp", "", Settings.Default.LyraNode.Lyra.NetworkId, _sys.PosWallet.PrivateKey); var gensWallet = Wallet.Open(memStore, "tmp", ""); gensWallet.SetVoteFor(_sys.PosWallet.AccountId); foreach (var accId in ProtocolSettings.Default.StandbyValidators.Skip(1).Concat(ProtocolSettings.Default.StartupValidators)) { var client = new LyraAggregatedClient(Settings.Default.LyraNode.Lyra.NetworkId, true, _sys.PosWallet.AccountId); await client.InitAsync(); await gensWallet.SyncAsync(client); var amount = LyraGlobal.MinimalAuthorizerBalance + 100000; var sendResult = await gensWallet.SendAsync(amount, accId); if (sendResult.ResultCode == APIResultCodes.Success) { _log.LogInformation($"Genesis send {amount} successfull to accountId: {accId}"); } else { _log.LogError($"Genesis send {amount} failed to accountId: {accId}"); } } }
private async Task EngagingSyncAsync() { // most db is synced. // so make sure Last Float Hash equal to seed. var emptySyncTimes = 0; var client = new LyraAggregatedClient(Settings.Default.LyraNode.Lyra.NetworkId, false, _sys.PosWallet.AccountId); await client.InitAsync(); for (int ii = 0; ii < 15; ii++) { try { _log.LogInformation("Engaging Sync..."); var someBlockSynced = false; var myLastCons = await _sys.Storage.GetLastConsolidationBlockAsync(); var lastConsOfSeed = await client.GetLastConsolidationBlockAsync(); if (lastConsOfSeed.ResultCode == APIResultCodes.Success) { var lastConsBlockOfSeed = lastConsOfSeed.GetBlock(); if (myLastCons == null || myLastCons.Height < lastConsBlockOfSeed.Height) { _log.LogInformation($"Engaging: new consolidation block {lastConsBlockOfSeed.Height}"); if (!await SyncDatabaseAsync(client)) { _log.LogError($"Error sync database. wait 5 minutes and retry..."); await Task.Delay(5 * 60 * 1000); } someBlockSynced = true; continue; } } else { _log.LogError($"Error get database status: {lastConsOfSeed.ResultCode}. Please wait for retry..."); await Task.Delay(10 * 1000); _log.LogInformation("Recreate aggregated client..."); if (lastConsOfSeed.ResultCode == APIResultCodes.APIRouteFailed) { client.ReBase(false); } await client.InitAsync(); continue; } _log.LogInformation($"Engaging: Sync all unconsolidated blocks"); // sync unconsolidated blocks var endTime = DateTime.MaxValue; var unConsHashResult = await client.GetBlockHashesByTimeRangeAsync(myLastCons.TimeStamp, endTime); if (unConsHashResult.ResultCode == APIResultCodes.Success) { _log.LogInformation($"Engaging: total unconsolidated blocks {unConsHashResult.Entities.Count}"); var myUnConsHashes = await _sys.Storage.GetBlockHashesByTimeRangeAsync(myLastCons.TimeStamp, endTime); foreach (var h in myUnConsHashes) { if (!unConsHashResult.Entities.Contains(h)) { await _sys.Storage.RemoveBlockAsync(h); someBlockSynced = true; } } foreach (var hash in unConsHashResult.Entities) // the first one is previous consolidation block { //_log.LogInformation($"Engaging: Syncunconsolidated block {count++}/{unConsHashResult.Entities.Count}"); if (hash == myLastCons.Hash) { continue; // already synced by previous steps } var localBlock = await _sys.Storage.FindBlockByHashAsync(hash); if (localBlock != null) { continue; } var blockResult = await client.GetBlockByHashAsync(_sys.PosWallet.AccountId, hash, null); if (blockResult.ResultCode == APIResultCodes.Success) { await _sys.Storage.AddBlockAsync(blockResult.GetBlock()); someBlockSynced = true; } else if (blockResult.ResultCode == APIResultCodes.APISignatureValidationFailed) { throw new Exception("Desynced by new service block."); } else { someBlockSynced = true; break; } } } else if (unConsHashResult.ResultCode == APIResultCodes.APIRouteFailed) { //_log.LogInformation("Recreate aggregated client..."); // client.ReBase(true); await client.InitAsync(); continue; } else { continue; } // update billboard to latest var lastServiceBlock = await _sys.Storage.GetLastServiceBlockAsync(); ServiceBlockCreated(lastServiceBlock); //_log.LogInformation($"Engaging: finalizing..."); var remoteState = await client.GetSyncStateAsync(); if (remoteState.ResultCode != APIResultCodes.Success) { continue; } var localState = await GetNodeStatusAsync(); if (remoteState.Status.lastConsolidationHash == localState.lastConsolidationHash && remoteState.Status.lastUnSolidationHash == localState.lastUnSolidationHash ) { if (someBlockSynced) { emptySyncTimes = 0; continue; } else { emptySyncTimes++; if (emptySyncTimes >= 3) { break; } else { _log.LogInformation("Waiting for any new changes ..."); await Task.Delay(20000); } } } else { // we need to know why _log.LogWarning($"Engaging sync local vs remote: lastcons {localState.lastConsolidationHash.Shorten()} {remoteState.Status.lastConsolidationHash.Shorten()}, last uncons: {localState.lastUnSolidationHash.Shorten()} {remoteState.Status.lastUnSolidationHash.Shorten()}"); } _log.LogInformation("Engaging Sync partial success. continue..."); await Task.Delay(1000); } catch (Exception ex) { _log.LogInformation($"Engaging Sync failed with error \"{ex.Message}\". continue..."); await Task.Delay(1000); } } }
internal async Task ProcessMessageAsync(ViewChangeMessage vcm) { if (ViewId != 0 && vcm.ViewID != ViewId) { _log.LogInformation($"VC Msgs: view ID {vcm.ViewID} not valid with {ViewId}"); if (vcm.ViewID > ViewId) { // maybe outdated? if (_vcTaskMutex.Wait(1)) { _ = Task.Run(async() => { try { var client = new LyraAggregatedClient(Settings.Default.LyraNode.Lyra.NetworkId, false, _sys.PosWallet.AccountId); await client.InitAsync(); var lsb = await client.GetLastServiceBlockAsync(); if (lsb.ResultCode == Blocks.APIResultCodes.Success) { var sb = lsb.GetBlock() as ServiceBlock; if (sb.Height > ViewId) { // outdated _context.LocalConsolidationFailed(sb.Hash); } } } catch (Exception ex) { _log.LogError($"In detecting latest view: {ex}"); } finally { // throttle await Task.Delay(3000); _vcTaskMutex.Release(); } }).ConfigureAwait(false); } } return; } if (vcm.TimeStamp < DateTime.UtcNow.AddSeconds(-1 * LyraGlobal.VIEWCHANGE_TIMEOUT)) { return; } RemoveOutDatedMsgs(); if (vcm is ViewChangeRequestMessage req) { await CheckRequestAsync(req); return; } //_log.LogInformation($"ViewChangeHandler ProcessMessage From {vcm.From.Shorten()} with ViewID {vcm.ViewID} My ViewID {_viewId} "); if (_context.Board.AllVoters.Contains(vcm.From)) // not the next one { switch (vcm) { case ViewChangeReplyMessage reply: await CheckReplyAsync(reply); break; case ViewChangeCommitMessage commit: await CheckCommitAsync(commit); break; default: _log.LogWarning("Should not happen."); break; } } }