Beispiel #1
0
        // 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();
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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}");
                }
            }
        }
Beispiel #4
0
        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;
                }
            }
        }