Ejemplo n.º 1
0
        private async Task <LyraRestClient> FindValidSeedForSyncAsync()
        {
            do
            {
                var rand = new Random();
                int ndx;
                do
                {
                    ndx = rand.Next(0, ProtocolSettings.Default.SeedList.Length);
                } while (NodeService.Instance.PosWallet.AccountId == ProtocolSettings.Default.StandbyValidators[ndx]);

                var addr   = ProtocolSettings.Default.SeedList[ndx].Split(':')[0];
                var apiUrl = $"https://{addr}:4505/api/LyraNode/";
                _log.LogInformation("Platform {1} Use seed node of {0}", apiUrl, Environment.OSVersion.Platform);
                var client = await LyraRestClient.CreateAsync(NetworkID, Environment.OSVersion.Platform.ToString(), "LyraNode2", "1.0", apiUrl);

                var mode = await client.GetSyncState();

                if (mode.ResultCode == APIResultCodes.Success)
                {
                    return(client);
                }
                await Task.Delay(10000);    // incase of hammer
            } while (true);
        }
Ejemplo n.º 2
0
 public async Task <LyraRestClient> GetClientForSeed0()
 {
     if (_seed0Client == null)
     {
         var addr   = ProtocolSettings.Default.SeedList[0].Split(':')[0];
         var apiUrl = $"https://{addr}:4505/api/LyraNode/";
         _seed0Client = await LyraRestClient.CreateAsync(BlockChain.Singleton.NetworkID, Environment.OSVersion.Platform.ToString(), "LyraNode2", "1.0", apiUrl);
     }
     return(_seed0Client);
 }
Ejemplo n.º 3
0
 public async Task <LyraRestClient> GetClientForSeed0()
 {
     if (_seed0Client == null)
     {
         var addr   = ProtocolSettings.Default.SeedList[0].Split(':')[0];
         var apiUrl = $"https://{addr}:4505/api/LyraNode/";
         _log.LogInformation("Platform {1} Use seed node of {0}", apiUrl, Environment.OSVersion.Platform);
         _seed0Client = await LyraRestClient.CreateAsync(NetworkID, Environment.OSVersion.Platform.ToString(), "LyraNode2", "1.0", apiUrl);
     }
     return(_seed0Client);
 }
Ejemplo n.º 4
0
        private async Task<Wallet> RefreshBalanceAsync(string masterKey)
        {
            // create wallet and update balance
            var memStor = new AccountInMemoryStorage();
            var acctWallet = new ExchangeAccountWallet(memStor, _network);
            acctWallet.AccountName = "tmpAcct";
            await acctWallet.RestoreAccountAsync("", masterKey);
            acctWallet.OpenAccount("", acctWallet.AccountName);

            Console.WriteLine("Sync wallet for " + acctWallet.AccountId);
            var rpcClient = await LyraRestClient.CreateAsync(_network, "Windows", "Lyra Client Cli", "1.0a");
            await acctWallet.Sync(rpcClient);
            return acctWallet;
        }
        public async Task <Dictionary <string, Decimal> > RefreshBalance(string networkId)
        {
            var rpcClient = await LyraRestClient.CreateAsync(networkId, "Windows", "AutoSender", "0.1");

            var result = await wallet.Sync(rpcClient);

            if (result == Lyra.Core.Blocks.APIResultCodes.Success)
            {
                return(wallet.GetLatestBlock()?.Balances);
            }
            else
            {
                throw new Exception(result.ToString());
            }
        }
Ejemplo n.º 6
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _waitOrder = new AutoResetEvent(false);
            try
            {
                _log.LogInformation($"NodeService: ExecuteAsync Called.");

                // something must be initialized first
                new AuthorizersFactory().Init();

                var    walletStore = new LiteAccountDatabase();
                var    tmpWallet   = new Wallet(walletStore, Neo.Settings.Default.LyraNode.Lyra.NetworkId);
                string lyra_folder = BaseAccount.GetFullFolderName("Lyra-CLI-" + Neo.Settings.Default.LyraNode.Lyra.NetworkId);
                string full_path   = BaseAccount.GetFullPath(lyra_folder);
                tmpWallet.OpenAccount(full_path, Neo.Settings.Default.LyraNode.Lyra.Wallet.Name);

                if (ProtocolSettings.Default.StandbyValidators.Any(a => a == tmpWallet.AccountId))
                {
                    // not update balance for seed nodes.
                    PosWallet = tmpWallet;
                }
                else
                {
                    // create wallet and update balance
                    var memStor    = new AccountInMemoryStorage();
                    var acctWallet = new ExchangeAccountWallet(memStor, Neo.Settings.Default.LyraNode.Lyra.NetworkId);
                    acctWallet.AccountName = "tmpAcct";
                    await acctWallet.RestoreAccountAsync("", tmpWallet.PrivateKey);

                    acctWallet.OpenAccount("", acctWallet.AccountName);

                    Console.WriteLine("Sync wallet for " + acctWallet.AccountId);
                    var rpcClient = await LyraRestClient.CreateAsync(Neo.Settings.Default.LyraNode.Lyra.NetworkId, Environment.OSVersion.Platform.ToString(), "Lyra Client Cli", "1.0a");

                    await acctWallet.Sync(rpcClient);

                    PosWallet = acctWallet;
                }

                var sys = new LyraSystem();
                sys.Start();

                if (_db == null)
                {
                    //BsonSerializer.RegisterSerializer(typeof(decimal), new DecimalSerializer(BsonType.Decimal128));
                    //BsonSerializer.RegisterSerializer(typeof(decimal?), new NullableSerializer<decimal>(new DecimalSerializer(BsonType.Decimal128)));

                    client = new MongoClient(Neo.Settings.Default.LyraNode.Lyra.Database.DexDBConnect);
                    _db    = client.GetDatabase("Dex");

                    var exchangeAccounts = _db.GetCollection <ExchangeAccount>("exchangeAccounts");
                    var queue            = _db.GetCollection <ExchangeOrder>("queuedDexOrders");
                    var finished         = _db.GetCollection <ExchangeOrder>("finishedDexOrders");

                    // TODO: make it DI
                    Dealer             = new DealEngine(exchangeAccounts, queue, finished);
                    Dealer.OnNewOrder += (s, a) => _waitOrder.Set();
                }

                //_watcher = new ZooKeeperWatcher(_log);
                //await UsingZookeeper(_zkClusterOptions.ConnectionString, async (zk) => {
                //    // get Lyra network configurations from /lyra
                //    // {"mode":"permissioned","seeds":["node1","node2"]}
                //    var cfg = await zk.getDataAsync("/lyra");
                //    var runtimeConfig = JsonConvert.DeserializeObject<ConsensusRuntimeConfig>(Encoding.ASCII.GetString(cfg.Data));
                //    // do copy because the object is global
                //    _consensus.Mode = runtimeConfig.Mode;
                //    _consensus.Seeds = runtimeConfig.Seeds;
                //    _consensus.CurrentSeed = runtimeConfig.CurrentSeed;
                //    _consensus.PrimaryAuthorizerNodes = runtimeConfig.PrimaryAuthorizerNodes;
                //    _consensus.BackupAuthorizerNodes = runtimeConfig.BackupAuthorizerNodes;
                //    _consensus.VotingNodes = runtimeConfig.VotingNodes;

                //    _log.LogInformation($"NodeService: Got runtimeconfig success.");
                //});

                // all seeds do node election
                //if (_consensus.Seeds.Contains(Neo.Settings.Default.LyraNode.Orleans.EndPoint.AdvertisedIPAddress))
                //{
                //while(true)     // we do nothing without zk
                //{
                //    try
                //    {
                //        var electRoot = "/lyra/seedelect";
                //        var zk = new ZooKeeper(_zkClusterOptions.ConnectionString, ZOOKEEPER_CONNECTION_TIMEOUT, _watcher);
                //        var stat = await zk.existsAsync(electRoot);
                //        if (stat == null)
                //            await zk.createAsync(electRoot, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                //        _leader = new LeaderElectionSupport(zk, electRoot, Neo.Settings.Default.LyraNode.Orleans.EndPoint.AdvertisedIPAddress);

                //        _leader.addListener(this);
                //        await _leader.start();

                //        break;
                //    }
                //    catch(Exception ex)
                //    {
                //        _log.Fail(Orleans.ErrorCode.MembershipShutDownFailure, ex.Message);
                //        await Task.Delay(1000);
                //    }
                //}
                //}
            }
            catch (Exception ex)
            {
                throw new Exception("Error Initialize Node Service", ex);
            }

            while (!stoppingToken.IsCancellationRequested)
            {
                // do work
                if (_waitOrder.WaitOne(1000))
                {
                    _waitOrder.Reset();

                    await Dealer.MakeDealAsync();
                }
                else
                {
                    // no new order. do house keeping.
                }
            }
        }
Ejemplo n.º 7
0
        public async Task <int> RunWallet(Options options)
        {
            Console.WriteLine("Personal and Business Banking, Payments, and Digital Asset Management");
            Console.WriteLine("");
            Console.WriteLine("Banking: Store, transfer, and receive interest on multiple digital assets");
            Console.WriteLine("Payments: Make or accept instant payments using various currencies, online and in store");
            Console.WriteLine("Digital Asset Management: Issue your own tokens within seconds");
            Console.WriteLine("");

            string network_id = options.NetworkId;
            bool   INMEMORY   = options.Database == Options.INMEMORY_DATABASE;
            bool   WEB        = options.Protocol == Options.WEBAPI_PROTOCOL;

            Wallet wallet;

            if (INMEMORY)
            {
                var inmemory_storage = new AccountInMemoryStorage();
                wallet = new Wallet(inmemory_storage, network_id);
            }
            else
            {
                wallet = new Wallet(new LiteAccountDatabase(), network_id);
            }

            string lyra_folder = BaseAccount.GetFullFolderName(network_id, "wallets");

            if (!Directory.Exists(lyra_folder))
            {
                Directory.CreateDirectory(lyra_folder);
            }

            Console.WriteLine("Storage Location: " + lyra_folder);

            if (options.GenWalletName != null)
            {
                wallet.AccountName = options.GenWalletName;
                wallet.CreateAccount(lyra_folder, wallet.AccountName, AccountTypes.Standard);
                var ep = Neo.Cryptography.ECC.ECPoint.FromBytes(Base58Encoding.DecodeAccountId(wallet.AccountId), Neo.Cryptography.ECC.ECCurve.Secp256r1);
                Console.WriteLine($"The new wallet {wallet.AccountName} for {network_id}: ");
                Console.WriteLine(ep.ToString());
                Console.WriteLine(wallet.AccountId);
                return(0);
            }

            CommandProcessor command = new CommandProcessor(wallet);
            string           input   = null;

            try
            {
                while (!wallet.AccountExistsLocally(lyra_folder, input))
                {
                    Console.WriteLine("Press Enter for default account, or enter account name: ");
                    input = Console.ReadLine();

                    if (string.IsNullOrEmpty(input))
                    {
                        input = "My Account";
                    }

                    wallet.AccountName = input;

                    string fileName = "";
                    if (INMEMORY)
                    {
                        fileName = lyra_folder + wallet.AccountName + ".key";

                        if (System.IO.File.Exists(fileName))
                        {
                            string private_key = System.IO.File.ReadAllText(fileName);
                            if (wallet.ValidatePrivateKey(private_key))
                            {
                                var result = await wallet.RestoreAccountAsync(lyra_folder, private_key);

                                if (!result.Successful())
                                {
                                    Console.WriteLine("Could not restore account from file: " + result.ResultMessage);
                                    continue;
                                }
                            }
                        }
                    }


                    if (!wallet.AccountExistsLocally(lyra_folder, wallet.AccountName))
                    {
                        Console.WriteLine("Local account data not found. Would you like to create a new account? (Y/n): ");
                        if (command.ReadYesNoAnswer())
                        {
                            wallet.CreateAccount(lyra_folder, wallet.AccountName, AccountTypes.Standard);
                        }
                        else
                        {
                            Console.WriteLine("Please enter private key to restore account: ");
                            string privatekey = Console.ReadLine();

                            if (!wallet.ValidatePrivateKey(privatekey))
                            {
                                continue;
                            }

                            var result = await wallet.RestoreAccountAsync(lyra_folder, privatekey);

                            if (!result.Successful())
                            {
                                Console.WriteLine("Could not restore account from file: " + result.ResultMessage);
                                continue;
                            }
                        }
                        if (INMEMORY)
                        {
                            System.IO.File.WriteAllText(fileName, wallet.PrivateKey);
                        }
                    }
                    else
                    {
                        wallet.OpenAccount(lyra_folder, wallet.AccountName);
                    }
                }

                LyraRestClient rpcClient;
                if (!string.IsNullOrWhiteSpace(options.Node))
                {
                    var apiUrl = $"https://{options.Node}:4505/api/Node/";
                    rpcClient = await LyraRestClient.CreateAsync(network_id, "Windows", "WizDAG Client Cli", "1.0a", apiUrl);
                }
                else
                {
                    rpcClient = await LyraRestClient.CreateAsync(network_id, "Windows", "WizDAG Client Cli", "1.0a");//await LyraRpcClient.CreateAsync(network_id, "Lyra Client Cli", "1.0");
                }
                Console.WriteLine("Type 'help' to see the list of available commands");
                Console.WriteLine("");

                await wallet.Sync(rpcClient);

                //timer1 = new Timer(async _ =>
                //{
                //    if (timer_busy1)
                //        return;
                //    try
                //    {
                //        timer_busy1 = true;
                //        var sync_result = await wallet.Sync(rpcClient);
                //    }
                //    finally
                //    {
                //        timer_busy1 = false;
                //    }
                //},
                //null, 2000, 30000);


                input = CommandProcessor.COMMAND_STATUS;

                while (input != CommandProcessor.COMMAND_STOP)
                {
                    var result = await command.Execute(input);

                    Console.Write(string.Format("{0}> ", wallet.AccountName));
                    //Console.Write
                    input = Console.ReadLine();
                }

                Console.WriteLine("WizDAG Client is shutting down");
            }
            catch (Exception ex)
            {
                Console.WriteLine(string.Format("Exception: {0}", ex.Message));
                Console.WriteLine("WizDAG Client is shutting down");
            }
            finally
            {
                if (wallet != null)
                {
                    wallet.Dispose();
                }
            }

            return(0);
        }
Ejemplo n.º 8
0
        // args: [number] the tps to simulate
        //
        static async System.Threading.Tasks.Task Main(string[] args)
        {
            var workingFolder = @"C:\working\Friday";

            var lyraFolder = BaseAccount.GetFullFolderName("Lyra-CLI-" + network_id);

            Console.WriteLine("Press enter to begin.");
            Console.ReadLine();

            // create and save wallets
            //var tt = new TransactionTester();
            //var wlts = tt.CreateWallet(1000);
            //var json = JsonConvert.SerializeObject(wlts);
            //File.WriteAllText(workingFolder + @"\wallets.json", json);

            // key is account id
            var wallets = JsonConvert.DeserializeObject <Dictionary <string, string> >(File.ReadAllText(workingFolder + @"\\wallets.json"));

            //var rpcClient = await LyraRestClient.CreateAsync(network_id, "Windows", "Lyra Client Cli", "1.0a", "https://192.168.3.62:4505/api/LyraNode/");
            var rpcClient = await LyraRestClient.CreateAsync(network_id, "Windows", "Lyra Client Cli", "1.0a");

            var tt = new TransactionTester(rpcClient);

            var masterWallet = new Wallet(new LiteAccountDatabase(), network_id);

            masterWallet.AccountName = "My Account";
            masterWallet.OpenAccount(lyraFolder, masterWallet.AccountName);
            await masterWallet.Sync(rpcClient);

            _ = Task.Run(async() =>
            {
                while (true)
                {
                    var state = await rpcClient.GetSyncState();
                    await Task.Delay(10000);
                    var state2 = await rpcClient.GetSyncState();

                    var tps = state2.Status.totalBlockCount - state.Status.totalBlockCount;

                    Console.WriteLine($"\n============> TPS: {tps} / 10\n");
                }
            });

            //var all = await tt.RefreshBalancesAsync(wallets.Select(a => new KeyPair(Base58Encoding.DecodePrivateKey(a.Value))).ToArray());
            //File.WriteAllText(workingFolder + @"\balances.json", JsonConvert.SerializeObject(all));

            var rich10     = JsonConvert.DeserializeObject <List <WalletBalance> >(File.ReadAllText(workingFolder + @"\balances.json"));
            var realRich10 = rich10.Where(a => a.balance.ContainsKey(lyraCoin) && a.balance.ContainsKey(testCoin))
                             .Where(a => a.balance[testCoin] >= 10000).ToDictionary(a => a.privateKey, a => a.balance);

            //var rich90 = wallets.Where(a => !realRich10.ContainsKey(a.Value)).Take(90);
            var rich90 = JsonConvert.DeserializeObject <List <KeyValuePair <string, string> > >(File.ReadAllText(workingFolder + @"\\rich90.json"));
            //File.WriteAllText(workingFolder + @"\rich90.json", JsonConvert.SerializeObject(rich90));

            var poors = wallets.Where(a => !rich90.Any(x => x.Key == a.Key));

            var testGroup1 = rich90.Take(350);
            await tt.MultiThreadedSendAsync(new [] { masterWallet.PrivateKey }, testGroup1.Select(a => a.Key).ToArray(), new Dictionary <string, decimal> {
                { lyraCoin, 5000 }
            }, true);

            Console.WriteLine("Coin distribute OK. Press Enter to continue...");
            Console.ReadLine();

            await tt.MultiThreadedSendAsync(testGroup1.Select(a => a.Value).ToArray(), poors.Select(a => a.Key).ToArray(), new Dictionary <string, decimal> {
                { lyraCoin, 1 }
            });

            Console.ReadLine();

            //foreach(var b in masterWallet.GetLatestBlock().Balances)
            //{
            //    Console.WriteLine($"{b.Key}: {b.Value}");
            //}
            //Console.WriteLine("Hello Lyra!");

            //var top10 = wallets.Take(10).ToDictionary(a => a.Key, a => a.Value);

            //await tt.SingleThreadedSendAsync(10, masterWallet, top10.Keys.ToArray(), new Dictionary<string, decimal> {
            //    { lyraCoin, 10000 }, {testCoin, 1000000}
            //});

            //var top100 = wallets.Skip(10).Take(100).ToDictionary(a => a.Key, a => a.Value);
            //await tt.MultiThreadedSendAsync(10, top10.Select(a => new KeyPair(Base58Encoding.DecodePrivateKey(a.Value))).ToArray(),
            //    top100.Values.ToArray(), new Dictionary<string, decimal> {
            //        { lyraCoin, 100 }, {testCoin, 10000} }
            //    );
        }
        /// <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.");
            });
        }
Ejemplo n.º 10
0
        /// <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.");
            });
        }