public async Task RunAsync(IStorageProvider store, ExpressConsensusNode node, bool enableTrace, TextWriter writer, CancellationToken token) { if (IsNodeRunning(node)) { throw new Exception("Node already running"); } var tcs = new TaskCompletionSource <bool>(); _ = Task.Run(() => { try { var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(token); var defaultAccount = node.Wallet.Accounts.Single(a => a.IsDefault); using var mutex = new Mutex(true, GLOBAL_PREFIX + defaultAccount.ScriptHash); var wallet = DevWallet.FromExpressWallet(ProtocolSettings, node.Wallet); var multiSigAccount = wallet.GetMultiSigAccounts().Single(); var logPlugin = new Node.LogPlugin(writer); var storageProviderPlugin = new Node.StorageProviderPlugin(store); var appEngineProvider = enableTrace ? new Node.ApplicationEngineProvider() : null; var dbftPlugin = new Neo.Consensus.DBFTPlugin(GetConsensusSettings(chain)); var persistencePlugin = new Node.PersistencePlugin(store); using var neoSystem = new Neo.NeoSystem(ProtocolSettings, storageProviderPlugin.Name); _ = neoSystem.ActorSystem.ActorOf(EventWrapper <Blockchain.ApplicationExecuted> .Props(OnApplicationExecuted)); var rpcSettings = GetRpcServerSettings(chain, node); var rpcServer = new Neo.Plugins.RpcServer(neoSystem, rpcSettings); var expressRpcMethods = new ExpressRpcMethods(neoSystem, store, multiSigAccount.ScriptHash, linkedToken); rpcServer.RegisterMethods(expressRpcMethods); rpcServer.RegisterMethods(persistencePlugin); rpcServer.StartRpcServer(); neoSystem.StartNode(new Neo.Network.P2P.ChannelsConfig { Tcp = new IPEndPoint(IPAddress.Loopback, node.TcpPort), WebSocket = new IPEndPoint(IPAddress.Loopback, node.WebSocketPort), }); dbftPlugin.Start(wallet); // DevTracker looks for a string that starts with "Neo express is running" to confirm that the instance has started // Do not remove or re-word this console output: writer.WriteLine($"Neo express is running ({store.GetType().Name})"); linkedToken.Token.WaitHandle.WaitOne(); } catch (Exception ex) { tcs.SetException(ex); } finally { tcs.TrySetResult(true); } }); await tcs.Task.ConfigureAwait(false);
public JObject ExpressEnumNotifications(JArray @params) { var contracts = ((JArray)@params[0]).Select(j => UInt160.Parse(j.AsString())).ToHashSet(); var events = ((JArray)@params[1]).Select(j => j.AsString()).ToHashSet(StringComparer.OrdinalIgnoreCase); int skip = @params.Count >= 3 ? (int)@params[2].AsNumber() : 0; int take = @params.Count >= 4 ? (int)@params[3].AsNumber() : MAX_NOTIFICATIONS; if (take > MAX_NOTIFICATIONS) { take = MAX_NOTIFICATIONS; } var notifications = PersistencePlugin .GetNotifications( storageProvider, SeekDirection.Backward, contracts.Count > 0 ? contracts : null, events.Count > 0 ? events : null) .Skip(skip); var count = 0; var jsonNotifications = new JArray(); var truncated = false; foreach (var(blockIndex, _, notification) in notifications) { if (count++ > take) { truncated = true; break; } var jNotification = new JObject { ["block-index"] = blockIndex, ["script-hash"] = notification.ScriptHash.ToString(), ["event-name"] = notification.EventName, ["inventory-type"] = (byte)notification.InventoryType, ["inventory-hash"] = notification.InventoryHash.ToString(), ["state"] = Neo.VM.Helper.ToJson(notification.State), }; jsonNotifications.Add(jNotification); } return(new JObject { ["truncated"] = truncated, ["notifications"] = jsonNotifications, }); }
public OfflineNode(ProtocolSettings settings, RocksDbStorageProvider rocksDbStorageProvider, Wallet nodeWallet, ExpressChain chain, bool enableTrace) { this.nodeWallet = nodeWallet; this.chain = chain; this.rocksDbStorageProvider = rocksDbStorageProvider; applicationEngineProvider = enableTrace ? new ApplicationEngineProvider() : null; consensusNodesKeys = new Lazy <KeyPair[]>(() => chain.GetConsensusNodeKeys()); var storageProviderPlugin = new StorageProviderPlugin(rocksDbStorageProvider); _ = new PersistencePlugin(rocksDbStorageProvider); neoSystem = new NeoSystem(settings, storageProviderPlugin.Name); ApplicationEngine.Log += OnLog !; }
public JObject GetNep17Balances(JArray @params) { var address = AsScriptHash(@params[0]); using var snapshot = neoSystem.GetSnapshot(); // collect the non-zero balances of all the deployed Nep17 contracts for the specified account var addressBalances = TokenContract.Enumerate(snapshot) .Where(c => c.standard == TokenStandard.Nep17) .Select(c => ( scriptHash: c.scriptHash, balance: snapshot.GetNep17Balance(c.scriptHash, address, neoSystem.Settings))) .Where(t => !t.balance.IsZero) .ToList(); // collect the last block index a transfer occurred for all account balances var updateIndexes = new Dictionary <UInt160, uint>(); if (addressBalances.Count > 0) { var notifications = PersistencePlugin.GetNotifications( storageProvider, SeekDirection.Backward, addressBalances.Select(b => b.scriptHash).ToHashSet(), TRANSFER); foreach (var(blockIndex, _, notification) in notifications) { // iterate backwards thru the notifications looking for all the Transfer events from a contract // in assets where a Transfer event hasn't already been recorded if (!updateIndexes.ContainsKey(notification.ScriptHash)) { var transfer = TransferNotificationRecord.Create(notification); if (transfer is not null && (transfer.From == address || transfer.To == address)) { // if the specified account was the sender or receiver of the current transfer, // record the update index. Stop the iteration if indexes for all the assets are // have been recorded updateIndexes.Add(notification.ScriptHash, blockIndex); if (updateIndexes.Count == addressBalances.Count) { break; } } } } } var balances = new JArray(); for (int i = 0; i < addressBalances.Count; i++) { var(scriptHash, balance) = addressBalances[i]; var lastUpdatedBlock = updateIndexes.TryGetValue(scriptHash, out var _index) ? _index : 0; balances.Add(new JObject { ["assethash"] = scriptHash.ToString(), ["amount"] = balance.ToString(), ["lastupdatedblock"] = lastUpdatedBlock, }); } return(new JObject { ["address"] = address.ToAddress(neoSystem.Settings.AddressVersion), ["balance"] = balances, }); }
public JObject GetApplicationLog(JArray _params) { UInt256 hash = UInt256.Parse(_params[0].AsString()); return(PersistencePlugin.GetAppLog(storageProvider, hash) ?? throw new RpcException(-100, "Unknown transaction")); }