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 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);
示例#3
0
        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);
        }
示例#4
0
        public static (Wallet wallet, UInt160 accountHash) GetGenesisAccount(this ExpressChain chain, ProtocolSettings settings)
        {
            Debug.Assert(chain.ConsensusNodes != null && chain.ConsensusNodes.Count > 0);

            var wallet  = DevWallet.FromExpressWallet(settings, chain.ConsensusNodes[0].Wallet);
            var account = wallet.GetMultiSigAccounts().Single();

            return(wallet, account.ScriptHash);
        }
示例#5
0
        public static bool TryGetSigningAccount(this ExpressChainManager chainManager, string name, string password, [MaybeNullWhen(false)] out Wallet wallet, [MaybeNullWhen(false)] out UInt160 accountHash)
        {
            if (!string.IsNullOrEmpty(name))
            {
                var settings = chainManager.Chain.GetProtocolSettings();

                if (name.Equals(ExpressChainExtensions.GENESIS, StringComparison.OrdinalIgnoreCase))
                {
                    (wallet, accountHash) = chainManager.Chain.GetGenesisAccount(settings);
                    return(true);
                }

                if (chainManager.Chain.Wallets != null && chainManager.Chain.Wallets.Count > 0)
                {
                    for (int i = 0; i < chainManager.Chain.Wallets.Count; i++)
                    {
                        var expWallet = chainManager.Chain.Wallets[i];
                        if (name.Equals(expWallet.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            wallet      = DevWallet.FromExpressWallet(settings, expWallet);
                            accountHash = wallet.GetAccounts().Single(a => a.IsDefault).ScriptHash;
                            return(true);
                        }
                    }
                }

                for (int i = 0; i < chainManager.Chain.ConsensusNodes.Count; i++)
                {
                    var expWallet = chainManager.Chain.ConsensusNodes[i].Wallet;
                    if (name.Equals(expWallet.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        wallet      = DevWallet.FromExpressWallet(settings, expWallet);
                        accountHash = wallet.GetAccounts().Single(a => !a.Contract.Script.IsMultiSigContract()).ScriptHash;
                        return(true);
                    }
                }

                if (!string.IsNullOrEmpty(password))
                {
                    if (TryGetNEP2Wallet(name, password, settings, out wallet, out accountHash))
                    {
                        return(true);
                    }

                    if (TryGetNEP6Wallet(name, password, settings, out wallet, out accountHash))
                    {
                        return(true);
                    }
                }
            }

            wallet      = null;
            accountHash = null;
            return(false);
        public void RestoreCheckpoint(string checkPointArchive, bool force)
        {
            if (chain.ConsensusNodes.Count != 1)
            {
                throw new ArgumentException("Checkpoint restore is only supported on single node express instances", nameof(chain));
            }

            checkPointArchive = ResolveCheckpointFileName(checkPointArchive);
            if (!fileSystem.File.Exists(checkPointArchive))
            {
                throw new Exception($"Checkpoint {checkPointArchive} couldn't be found");
            }

            var node = chain.ConsensusNodes[0];

            if (IsNodeRunning(node))
            {
                var scriptHash = node.Wallet.DefaultAccount?.ScriptHash ?? "<unknown>";
                throw new InvalidOperationException($"node {scriptHash} currently running");
            }

            var checkpointTempPath = fileSystem.GetTempFolder();

            using var folderCleanup = AnonymousDisposable.Create(() =>
            {
                if (fileSystem.Directory.Exists(checkpointTempPath))
                {
                    fileSystem.Directory.Delete(checkpointTempPath, true);
                }
            });

            var nodePath = fileSystem.GetNodePath(node);

            if (fileSystem.Directory.Exists(nodePath))
            {
                if (!force)
                {
                    throw new Exception("You must specify force to restore a checkpoint to an existing blockchain.");
                }

                fileSystem.Directory.Delete(nodePath, true);
            }

            var wallet          = DevWallet.FromExpressWallet(ProtocolSettings, node.Wallet);
            var multiSigAccount = wallet.GetMultiSigAccounts().Single();

            RocksDbUtility.RestoreCheckpoint(checkPointArchive, checkpointTempPath,
                                             ProtocolSettings.Network, ProtocolSettings.AddressVersion, multiSigAccount.ScriptHash);
            fileSystem.Directory.Move(checkpointTempPath, nodePath);
        }
        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 bool TryGetAccountHash(this ExpressChain chain, string name, [MaybeNullWhen(false)] out UInt160 accountHash, ProtocolSettings?settings = null)
        {
            settings ??= chain.GetProtocolSettings();

            if (chain.Wallets != null && chain.Wallets.Count > 0)
            {
                for (int i = 0; i < chain.Wallets.Count; i++)
                {
                    if (string.Equals(name, chain.Wallets[i].Name, StringComparison.OrdinalIgnoreCase))
                    {
                        var wallet  = DevWallet.FromExpressWallet(settings, chain.Wallets[i]);
                        var account = wallet.GetAccounts().Single(a => a.IsDefault);
                        accountHash = account.ScriptHash;
                        return(true);
                    }
                }
            }

            Debug.Assert(chain.ConsensusNodes != null && chain.ConsensusNodes.Count > 0);

            for (int i = 0; i < chain.ConsensusNodes.Count; i++)
            {
                var nodeWallet = chain.ConsensusNodes[i].Wallet;
                if (string.Equals(name, nodeWallet.Name, StringComparison.OrdinalIgnoreCase))
                {
                    var wallet  = DevWallet.FromExpressWallet(settings, nodeWallet);
                    var account = wallet.GetAccounts().Single(a => a.IsDefault);
                    accountHash = account.ScriptHash;
                    return(true);
                }
            }

            if (GENESIS.Equals(name, StringComparison.OrdinalIgnoreCase))
            {
                (_, accountHash) = chain.GetGenesisAccount(settings);
                return(true);
            }

            if (TryToScriptHash(name, settings.AddressVersion, out accountHash))
            {
                return(true);
            }

            accountHash = default;
            return(false);
示例#9
0
        Block RunConsensus()
        {
            if (chain.ConsensusNodes.Count == 1)
            {
                var ctx = new ConsensusContext(nodeWallet, Blockchain.Singleton.Store);
                ctx.Reset(0);
                ctx.MakePrepareRequest();
                ctx.MakeCommit();
                return(ctx.CreateBlock());
            }

            // create ConsensusContext for each ConsensusNode
            var contexts = new ConsensusContext[chain.ConsensusNodes.Count];

            for (int x = 0; x < contexts.Length; x++)
            {
                contexts[x] = new ConsensusContext(DevWallet.FromExpressWallet(chain.ConsensusNodes[x].Wallet), Blockchain.Singleton.Store);
                contexts[x].Reset(0);
            }

            // find the primary node for this consensus round
            var primary = contexts.Single(c => c.IsPrimary);
            var prepareRequestPayload = primary.MakePrepareRequest();

            for (int x = 0; x < contexts.Length; x++)
            {
                var context = contexts[x];
                if (context.MyIndex == primary.MyIndex)
                {
                    continue;
                }
                var prepareRequestMessage = context.GetMessage <PrepareRequest>(prepareRequestPayload);
                OnPrepareRequestReceived(context, prepareRequestPayload, prepareRequestMessage);
                var commitPayload = context.MakeCommit();
                var commitMessage = primary.GetMessage <Commit>(commitPayload);
                OnCommitReceived(primary, commitPayload, commitMessage);
            }

            return(primary.CreateBlock());
        }
示例#10
0
        // this method only used in Online/OfflineNode ExecuteAsync
        public static IReadOnlyList <Wallet> GetMultiSigWallets(this ExpressChain chain, ProtocolSettings settings, UInt160 accountHash)
        {
            var builder = ImmutableList.CreateBuilder <Wallet>();

            for (int i = 0; i < chain.ConsensusNodes.Count; i++)
            {
                var wallet = DevWallet.FromExpressWallet(settings, chain.ConsensusNodes[i].Wallet);
                if (wallet.GetAccount(accountHash) != null)
                {
                    builder.Add(wallet);
                }
            }

            for (int i = 0; i < chain.Wallets.Count; i++)
            {
                var wallet = DevWallet.FromExpressWallet(settings, chain.Wallets[i]);
                if (wallet.GetAccount(accountHash) != null)
                {
                    builder.Add(wallet);
                }
            }

            return(builder.ToImmutable());
        }
示例#11
0
 public OfflineNode(IExpressStore store, ExpressWallet nodeWallet, ExpressChain chain, bool enableTrace)
     : this(store, DevWallet.FromExpressWallet(nodeWallet), chain, enableTrace)
 {
 }
示例#12
0
 public OfflineNode(ProtocolSettings settings, RocksDbStorageProvider rocksDbStorageProvider, ExpressWallet nodeWallet, ExpressChain chain, bool enableTrace)
     : this(settings, rocksDbStorageProvider, DevWallet.FromExpressWallet(settings, nodeWallet), chain, enableTrace)
 {
 }
        public static void ExportWallet(ExpressWallet wallet, string filename, string password)
        {
            var devWallet = DevWallet.FromExpressWallet(wallet);

            devWallet.Export(filename, password);
        }