private SemaphoreSlim semaphore = new SemaphoreSlim(1); // we need to run tests in serial public static TransitWallet Restore(string privateKey) { var accountId = Signatures.GetAccountIdFromPrivateKey(privateKey); return(new TransitWallet(accountId, privateKey, LyraRestClient.Create(TestConfig.networkId, "Windows", "UnitTest", "1.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.NewestBlockUIndex - state.NewestBlockUIndex; //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} } // ); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _waitOrder = new AutoResetEvent(false); try { var networkId = LyraNodeConfig.GetNetworkId(); _log.LogInformation($"{LyraGlobal.PRODUCTNAME} {LyraGlobal.NODE_VERSION} Mode: {Neo.Settings.Default.LyraNode.Lyra.Mode}: Starting node daemon for {networkId}."); // something must be initialized first Wallet PosWallet; string lyrawalletfolder = Wallet.GetFullFolderName(networkId, "wallets"); if (!Directory.Exists(lyrawalletfolder)) { Directory.CreateDirectory(lyrawalletfolder); } var walletStore = new SecuredWalletStore(lyrawalletfolder); if (!walletStore.Exists(Neo.Settings.Default.LyraNode.Lyra.Wallet.Name)) { _log.LogInformation($"Creating wallet for {networkId}."); (var privateKey, var publicKey) = Signatures.GenerateWallet(); _log.LogInformation($"The new wallet {Neo.Settings.Default.LyraNode.Lyra.Wallet.Name} for {networkId} was created."); //Console.WriteLine($"Private Key: {privateKey}"); _log.LogInformation($"Account ID: {publicKey}"); walletStore.Create(Neo.Settings.Default.LyraNode.Lyra.Wallet.Name, Neo.Settings.Default.LyraNode.Lyra.Wallet.Password, networkId, privateKey, publicKey, ""); _log.LogInformation($"Wallet saved to: {lyrawalletfolder}{Neo.Settings.Default.LyraNode.Lyra.Wallet.Name}.lyrawallet"); } PosWallet = Wallet.Open(walletStore, Neo.Settings.Default.LyraNode.Lyra.Wallet.Name, Neo.Settings.Default.LyraNode.Lyra.Wallet.Password, LyraRestClient.Create(networkId, "", "NodeService", "1.0", LyraGlobal.SelectNode(networkId) + "Node/")); _log.LogInformation($"Staking wallet: {PosWallet.AccountId}"); PosWallet.SetVoteFor(PosWallet.AccountId); var blcokcount = await _store.GetBlockCountAsync(); if (blcokcount > 0 && networkId == "devnet") // not genesis { try { await PosWallet.SyncAsync(null); } catch { } } var localNode = DagSystem.ActorSystem.ActorOf(Neo.Network.P2P.LocalNode.Props()); Dag = new DagSystem(_hostEnv, _store, _lyraEventContext, PosWallet, localNode); _ = Task.Run(async() => await Dag.StartAsync()).ConfigureAwait(false); await Task.Delay(30000); } catch (Exception ex) { _log.LogCritical($"NodeService: Error Initialize! {ex}"); } while (!stoppingToken.IsCancellationRequested) { // do work if (_waitOrder.WaitOne(1000)) { _waitOrder.Reset(); } else { // no new order. do house keeping. } } }
/// <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."); }); }
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("Lyra-CLI-" + network_id); 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/LyraNode/"; rpcClient = await LyraRestClient.CreateAsync(network_id, "Windows", "Lyra Client Cli", "1.0a", apiUrl); } else { rpcClient = await LyraRestClient.CreateAsync(network_id, "Windows", "Lyra 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("Lyra Client is shutting down"); } catch (Exception ex) { Console.WriteLine(string.Format("Exception: {0}", ex.Message)); Console.WriteLine("Lyra Client is shutting down"); } finally { if (wallet != null) { wallet.Dispose(); } } return(0); }
public override async Task <GetTransByHashReply> GetTransByHash(GetTransByHashRequest request, ServerCallContext context) { try { var client = LyraRestClient.Create(_config["network"], Environment.OSVersion.ToString(), "LyraBroker", "1.0"); var result = await client.GetBlockAsync(request.Hash); if (result.ResultCode == Lyra.Core.Blocks.APIResultCodes.Success && result.GetBlock() is TransactionBlock block) { var tx = new GetTransByHashReply { TxHash = block.Hash, Height = block.Height, Time = Timestamp.FromDateTime(block.TimeStamp) }; tx.TxType = block is SendTransferBlock ? TransactionType.Send : TransactionType.Receive; if (tx.TxType == TransactionType.Send) { tx.OwnerAccountId = block.AccountID; tx.PeerAccountId = (block as SendTransferBlock).DestinationAccountId; var rcvBlockQuery = await client.GetBlockBySourceHashAsync(block.Hash); if (rcvBlockQuery.ResultCode == APIResultCodes.Success) { tx.IsReceived = true; tx.RecvHash = rcvBlockQuery.GetBlock().Hash; } else { tx.IsReceived = false; tx.RecvHash = ""; //gRPC don't like null } } else { tx.OwnerAccountId = block.AccountID; var sndBlockQuery = await client.GetBlockAsync((block as ReceiveTransferBlock).SourceHash); if (sndBlockQuery.ResultCode == APIResultCodes.Success) { tx.PeerAccountId = (sndBlockQuery.GetBlock() as SendTransferBlock).AccountID; } tx.IsReceived = true; tx.RecvHash = block.Hash; } return(tx); } } catch (Exception ex) { _logger.LogWarning("In OpenWallet: " + ex.ToString()); } return(new GetTransByHashReply { TxHash = "" }); }
public override async Task <GetTransactionsReply> GetTransactions(GetTransactionsRequest request, ServerCallContext context) { var resp = new GetTransactionsReply { }; try { var client = LyraRestClient.Create(_config["network"], Environment.OSVersion.ToString(), "LyraBroker", "1.0"); var result = await client.SearchTransactionsAsync(request.AccountId, request.StartTime.ToDateTime().Ticks, request.EndTime.ToDateTime().Ticks, request.Count); if (result.ResultCode == APIResultCodes.Success) { for (int i = 0; i < result.Transactions.Count; i++) { var txDesc = result.Transactions[i]; var tx = new LyraTransaction { Height = txDesc.Height, Time = Timestamp.FromDateTime(txDesc.TimeStamp), IsReceive = txDesc.IsReceive, SendAccountId = txDesc.SendAccountId ?? "", SendHash = txDesc.SendHash ?? "", RecvAccountId = txDesc.RecvAccountId, RecvHash = txDesc.RecvHash ?? "" // protobuf not like null }; if (txDesc.Changes == null || !txDesc.Changes.ContainsKey(LyraGlobal.OFFICIALTICKERCODE)) { tx.BalanceChange = 0; } else { tx.BalanceChange = txDesc.Changes[LyraGlobal.OFFICIALTICKERCODE] / LyraGlobal.TOKENSTORAGERITO; } if (txDesc.Balances == null || !txDesc.Balances.ContainsKey(LyraGlobal.OFFICIALTICKERCODE)) { tx.Balance = 0; } else { tx.Balance = txDesc.Balances[LyraGlobal.OFFICIALTICKERCODE] / LyraGlobal.TOKENSTORAGERITO; } resp.Transactions.Add(tx); } } } catch (Exception ex) { _logger.LogWarning("In OpenWallet: " + ex.ToString()); } return(resp); }
public TransactionTester(LyraRestClient client) { _client = client; }
public async Task InitAsync() { ServicePointManager.DefaultConnectionLimit = 30; var platform = Environment.OSVersion.Platform.ToString(); var appName = "LyraAggregatedClient"; var appVer = "1.0"; ushort peerPort = 4504; if (_networkId == "mainnet") { peerPort = 5504; } // get nodes list (from billboard) var seedNodes = GetSeedNodes(); var seeds = seedNodes.Select(a => LyraRestClient.Create(_networkId, platform, appName, appVer, $"https://{a}:{peerPort}/api/Node/")).ToList(); BillBoard currentBillBoard = null; do { try { Console.WriteLine($"LyraAggregatedClient.InitAsync Seed Only: {_seedsOnly}"); var rand = new Random(); foreach (var sd in seedNodes.OrderBy(a => rand.Next())) { try { var apiClient = LyraRestClient.Create(_networkId, platform, appName, appVer, $"https://{sd}:{peerPort}/api/Node/"); currentBillBoard = await apiClient.GetBillBoardAsync(); Console.WriteLine($"LyraAggregatedClient.InitAsync Got billboard from {sd}"); break; } catch (Exception e) { Console.WriteLine("LyraAggregatedClient.InitAsync: " + e.Message); } } //var bbtasks = seeds.Select(client => client.GetBillBoardAsync()).ToList(); //try //{ // await Task.WhenAll(bbtasks); //} //catch (Exception ex) //{ // Console.WriteLine($"In LyraAggregatedClient.InitAsync: " + ex.Message); //} //var goodbb = bbtasks.Where(a => !(a.IsFaulted || a.IsCanceled) && a.IsCompleted && a.Result != null).Select(a => a.Result).ToList(); //if (goodbb.Count == 0) // continue; //// pickup best result //var best = goodbb // .GroupBy(b => b.CurrentLeader) // .Select(g => new // { // Data = g.Key, // Count = g.Count() // }) // .OrderByDescending(x => x.Count) // .First(); //if (best.Count >= seedNodes.Length - 2 && !string.IsNullOrWhiteSpace(best.Data)) //{ // var r = new Random(); // currentBillBoard = goodbb.ElementAt(r.Next(0, goodbb.Count())); // //currentBillBoard = goodbb.First(a => a.CurrentLeader == best.Data); //} //else //{ // await Task.Delay(2000); // continue; //} if (_seedsOnly) { // create clients for primary nodes _primaryClients = seedNodes .Select(c => LyraRestClient.Create(_networkId, platform, appName, appVer, $"https://{c}:{peerPort}/api/Node/")) .ToList(); } else if (currentBillBoard == null) { Console.WriteLine("Error init LyraAggregatedClient. Billboard is null."); await Task.Delay(1000); continue; } else { // create clients for primary nodes _primaryClients = currentBillBoard.NodeAddresses .Where(a => currentBillBoard.PrimaryAuthorizers.Contains(a.Key)) .Where(a => a.Key != _poswallet) .Select(c => LyraRestClient.Create(_networkId, platform, appName, appVer, $"https://{c.Value}:{peerPort}/api/Node/")) //.Take(7) // don't spam the whole network .ToList(); } if (_primaryClients.Count < 2) // billboard not harvest address enough { await Task.Delay(2000); } foreach (var primaryClient in _primaryClients) { primaryClient.SetTimeout(TimeSpan.FromSeconds(5)); } } catch (Exception exx) { Console.WriteLine("Error init LyraAggregatedClient. Error: " + exx.ToString()); await Task.Delay(1000); continue; } } while (currentBillBoard == null || _primaryClients.Count < 2); }