public OnlineNode(ProtocolSettings settings, ExpressChain chain, ExpressConsensusNode node) { this.ProtocolSettings = settings; this.chain = chain; rpcClient = new RpcClient(new Uri($"http://localhost:{node.RpcPort}"), protocolSettings: settings); consensusNodesKeys = new Lazy <KeyPair[]>(() => chain.GetConsensusNodeKeys()); }
public static void Preload(uint preloadGasAmount, Store store, ExpressConsensusNode node, TextWriter writer, CancellationToken cancellationToken) { Debug.Assert(preloadGasAmount > 0); var wallet = DevWallet.FromExpressWallet(node.Wallet); using var system = new NeoSystem(store); var generationAmount = Blockchain.GenerationAmount[0]; var gas = preloadGasAmount / generationAmount; var preloadCount = preloadGasAmount % generationAmount == 0 ? gas : gas + 1; writer.WriteLine($"Creating {preloadCount} empty blocks to preload {preloadGasAmount} GAS"); Random random = new Random(); for (int i = 1; i <= preloadCount; i++) { if (i % 100 == 0) { writer.WriteLine($" Creating Block {i}"); } var block = CreatePreloadBlock(wallet, random); var relayResult = system.Blockchain.Ask <RelayResultReason>(block).Result; if (relayResult != RelayResultReason.Succeed) { throw new Exception($"Preload block {i} failed {relayResult}"); } } ClaimPreloadGas(system, wallet, random); writer.WriteLine($"Preload complete. {preloadCount * generationAmount} GAS loaded into genesis account."); }
public static string GetMultiSigAddress(this ExpressConsensusNode node) { var account = DevWalletAccount.FromExpressWalletAccount(node.Wallet.Accounts .Single(a => Neo.SmartContract.Helper.IsMultiSigContract(a.Contract.Script.ToByteArray()))); return(account.Address); }
static RpcServerSettings GetRpcServerSettings(ExpressChain chain, ExpressConsensusNode node) { var ipAddress = chain.TryReadSetting <IPAddress>("rpc.BindAddress", IPAddress.TryParse, out var bindAddress) ? bindAddress : IPAddress.Loopback; var settings = new Dictionary <string, string>() { { "PluginConfiguration:Network", $"{chain.Network}" }, { "PluginConfiguration:BindAddress", $"{ipAddress}" }, { "PluginConfiguration:Port", $"{node.RpcPort}" } }; if (chain.TryReadSetting <decimal>("rpc.MaxGasInvoke", decimal.TryParse, out var maxGasInvoke)) { settings.Add("PluginConfiguration:MaxGasInvoke", $"{maxGasInvoke}"); } if (chain.TryReadSetting <decimal>("rpc.MaxFee", decimal.TryParse, out var maxFee)) { settings.Add("PluginConfiguration:MaxFee", $"{maxFee}"); } if (chain.TryReadSetting <int>("rpc.MaxIteratorResultItems", int.TryParse, out var maxIteratorResultItems) && maxIteratorResultItems > 0) { settings.Add("PluginConfiguration:MaxIteratorResultItems", $"{maxIteratorResultItems}"); } var config = new ConfigurationBuilder().AddInMemoryCollection(settings).Build(); return(RpcServerSettings.Load(config.GetSection("PluginConfiguration"))); }
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);
static bool IsNodeRunning(ExpressConsensusNode node) { // Check to see if there's a neo-express blockchain currently running by // attempting to open a mutex with the multisig account address for a name var account = node.Wallet.Accounts.Single(a => a.IsDefault); return(Mutex.TryOpenExisting(GLOBAL_PREFIX + account.ScriptHash, out var _)); }
public async Task RunAsync(IExpressStore store, ExpressConsensusNode node, uint secondsPerBlock, bool enableTrace, TextWriter writer, CancellationToken token) { if (IsRunning(node)) { throw new Exception("Node already running"); } chain.InitalizeProtocolSettings(secondsPerBlock); await writer.WriteLineAsync(store.GetType().Name).ConfigureAwait(false); var tcs = new TaskCompletionSource <bool>(); _ = Task.Run(() => { try { var defaultAccount = node.Wallet.Accounts.Single(a => a.IsDefault); using var mutex = new Mutex(true, GLOBAL_PREFIX + defaultAccount.ScriptHash); var wallet = DevWallet.FromExpressWallet(node.Wallet); var multiSigAccount = node.Wallet.Accounts.Single(a => a.IsMultiSigContract()); var dbftPlugin = new Neo.Consensus.DBFTPlugin(); var logPlugin = new Node.LogPlugin(writer); var storageProvider = new Node.ExpressStorageProvider((IStore)store); var appEngineProvider = enableTrace ? new Node.ExpressApplicationEngineProvider() : null; var appLogsPlugin = new Node.ExpressAppLogsPlugin(store); using var system = new Neo.NeoSystem(storageProvider.Name); var rpcSettings = new Neo.Plugins.RpcServerSettings(port: node.RpcPort); var rpcServer = new Neo.Plugins.RpcServer(system, rpcSettings); var expressRpcServer = new ExpressRpcServer(store, multiSigAccount); rpcServer.RegisterMethods(expressRpcServer); rpcServer.RegisterMethods(appLogsPlugin); rpcServer.StartRpcServer(); system.StartNode(new Neo.Network.P2P.ChannelsConfig { Tcp = new IPEndPoint(IPAddress.Loopback, node.TcpPort), WebSocket = new IPEndPoint(IPAddress.Loopback, node.WebSocketPort), }); dbftPlugin.Start(wallet); token.WaitHandle.WaitOne(); } catch (Exception ex) { tcs.SetException(ex); } finally { tcs.TrySetResult(true); } }); await tcs.Task.ConfigureAwait(false); }
public static string GetBlockchainPath(this ExpressConsensusNode node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } return(node.Wallet.GetBlockchainPath()); }
static bool NodeRunning(ExpressConsensusNode node) { // Check to see if there's a neo-express blockchain currently running // by attempting to open a mutex with the multisig account address for // a name. If so, do an online checkpoint instead of offline. if (Mutex.TryOpenExisting(node.GetMultiSigAddress(), out var _)) { return(true); } return(false); }
public async Task <bool> StopNodeAsync(ExpressConsensusNode node) { if (!IsNodeRunning(node)) { return(false); } var rpcClient = new Neo.Network.RPC.RpcClient(new Uri($"http://localhost:{node.RpcPort}"), protocolSettings: ProtocolSettings); var json = await rpcClient.RpcSendAsync("expressshutdown").ConfigureAwait(false); var processId = int.Parse(json["process-id"].AsString()); var process = System.Diagnostics.Process.GetProcessById(processId); await process.WaitForExitAsync().ConfigureAwait(false); return(true); }
public static Task RunAsync(Store store, ExpressConsensusNode node, TextWriter writer, CancellationToken cancellationToken) { var tcs = new TaskCompletionSource <bool>(); Task.Run(() => { try { var wallet = DevWallet.FromExpressWallet(node.Wallet); using (var system = new NeoSystem(store)) { var logPlugin = new LogPlugin(writer); var rpcPlugin = new ExpressNodeRpcPlugin(store); system.StartNode(node.TcpPort, node.WebSocketPort); system.StartConsensus(wallet); system.StartRpc(IPAddress.Loopback, node.RpcPort, wallet); { using var snapshot = Blockchain.Singleton.GetSnapshot(); var validators = snapshot.GetValidators(); ; } cancellationToken.WaitHandle.WaitOne(); } } catch (Exception ex) { tcs.SetException(ex); } finally { if (store is IDisposable disposable) { disposable.Dispose(); } tcs.TrySetResult(true); } }); return(tcs.Task); }
public static string GetNodePath(this IFileSystem fileSystem, ExpressConsensusNode node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node.Wallet == null) { throw new ArgumentNullException(nameof(node.Wallet)); } var account = node.Wallet.Accounts.Single(a => a.IsDefault); var rootPath = fileSystem.Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.DoNotVerify), "Neo-Express", "blockchain-nodes"); return(fileSystem.Path.Combine(rootPath, account.ScriptHash)); }
public void ResetNode(ExpressConsensusNode node, bool force) { if (IsNodeRunning(node)) { var scriptHash = node.Wallet.DefaultAccount?.ScriptHash ?? "<unknown>"; throw new InvalidOperationException($"node {scriptHash} currently running"); } var nodePath = fileSystem.GetNodePath(node); if (fileSystem.Directory.Exists(nodePath)) { if (!force) { throw new InvalidOperationException("--force must be specified when resetting a node"); } fileSystem.Directory.Delete(nodePath, true); } }
public IExpressStore GetNodeStore(ExpressConsensusNode node, bool discard) { var folder = fileSystem.GetNodePath(node); if (discard) { try { var rocksDbStore = RocksDbStore.OpenReadOnly(folder); return(new CheckpointStore(rocksDbStore)); } catch { return(new CheckpointStore(NullReadOnlyStore.Instance)); } } else { return(RocksDbStore.Open(folder)); } }
static RpcServerSettings GetRpcServerSettings(ExpressChain chain, ExpressConsensusNode node) { var settings = new Dictionary <string, string>() { { "PluginConfiguration:Network", $"{chain.Network}" }, { "PluginConfiguration:BindAddress", $"{IPAddress.Loopback}" }, { "PluginConfiguration:Port", $"{node.RpcPort}" } }; if (chain.TryReadSetting <long>("rpc.MaxGasInvoke", long.TryParse, out var maxGasInvoke)) { settings.Add("PluginConfiguration:MaxGasInvoke", $"{maxGasInvoke}"); } if (chain.TryReadSetting <long>("rpc.MaxFee", long.TryParse, out var maxFee)) { settings.Add("PluginConfiguration:MaxFee", $"{maxFee}"); } var config = new ConfigurationBuilder().AddInMemoryCollection(settings).Build(); return(RpcServerSettings.Load(config.GetSection("PluginConfiguration"))); }
public static Uri GetUri(this ExpressConsensusNode node) => new Uri($"http://localhost:{node.RpcPort}");
public OnlineNode(ProtocolSettings settings, ExpressChain chain, ExpressConsensusNode node) { this.ProtocolSettings = settings; this.chain = chain; rpcClient = new RpcClient(new Uri($"http://localhost:{node.RpcPort}"), protocolSettings: settings); }
public OnlineNode(ExpressChain chain, ExpressConsensusNode node) { this.chain = chain; rpcClient = new RpcClient(node.GetUri()); }