Ejemplo n.º 1
0
        public NexusAPI(Nexus nexus, Mempool mempool = null)
        {
            Throw.IfNull(nexus, nameof(nexus));

            Nexus   = nexus;
            Mempool = mempool;

            var methodInfo = GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);

            foreach (var entry in methodInfo)
            {
                if (entry.ReturnType != typeof(IAPIResult))
                {
                    continue;
                }

                if (entry.Name == nameof(Execute))
                {
                    continue;
                }

                var temp = new APIEntry(this, entry);
                if (temp.ReturnType != null)
                {
                    _methods[entry.Name.ToLower()] = temp;
                }
            }
        }
Ejemplo n.º 2
0
        private void InitMainNode()
        {
            var log   = new ConsoleLogger();
            var seeds = new List <string>();

            Console.ForegroundColor = ConsoleColor.DarkGray;

            string wif = nexusWif;

            int port = 7077;

            var node_keys = KeyPair.FromWIF(wif);

            var simulator = new ChainSimulator(node_keys, 1234, -1);

            nexus = simulator.Nexus;

            /*
             * for (int i = 0; i < 100; i++)
             * {
             *  simulator.GenerateRandomBlock();
             * }
             */
            // mempool setup
            mempool = new Mempool(node_keys, nexus, Mempool.MinimumBlockTime);
            mempool.Start();

            // node setup
            var node = new Node(nexus, mempool, node_keys, port, seeds, log);

            log.Message("Phantasma Node address: " + node_keys.Address.Text);
            node.Start();
        }
Ejemplo n.º 3
0
        private void InitMainNode(int _port = 7077)
        {
            var log = new ConsoleLogger();

            string wif = nexusWif;

            int port = _port;

            var node_keys = PhantasmaKeys.FromWIF(wif);

            var nexus = new Nexus("simnet", null, null);

            nexus.SetOracleReader(new OracleSimulator(nexus));
            var simulator = new NexusSimulator(nexus, node_keys, 1234);

            // mempool setup
            mempool = new Mempool(nexus, Mempool.MinimumBlockTime, 1, System.Text.Encoding.UTF8.GetBytes("TEST"));
            mempool.SetKeys(node_keys);
            mempool.Start();

            // node setup
            node = new Node("test node", nexus, mempool, node_keys, port, PeerCaps.Mempool, Enumerable.Empty <String>(), log);
            log.Message("Phantasma Node address: " + node_keys.Address.Text);
            node.Start();
        }
Ejemplo n.º 4
0
        public Node(string version, Nexus nexus, Mempool mempool, PhantasmaKeys keys, string publicHost, int port, PeerCaps caps, IEnumerable <string> seeds, Logger log)
        {
            if (mempool != null)
            {
                Throw.If(!caps.HasFlag(PeerCaps.Mempool), "mempool not included in caps but a mempool instance was passed");
                Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool");
            }
            else
            {
                Throw.If(caps.HasFlag(PeerCaps.Mempool), "mempool included in caps but mempool instance is null");
            }

            this.Logger = Logger.Init(log);

            this.Version      = version;
            this.Nexus        = nexus;
            this.Port         = port;
            this.Keys         = keys;
            this.Capabilities = caps;

            if (Capabilities.HasFlag(PeerCaps.Sync))
            {
                this.Nexus.AddPlugin(new NodePlugin(this));
            }

            if (Capabilities.HasFlag(PeerCaps.Mempool))
            {
                Throw.IfNull(mempool, nameof(mempool));
                this._mempool = mempool;
            }
            else
            {
                this._mempool = null;
            }

            Throw.IfNullOrEmpty(publicHost, nameof(publicHost));

            Throw.If(publicHost.Contains(":"), "invalid host, protocol or port number should not be included");
            this.Host = publicHost;

            this.PublicEndpoint = $"tcp:{publicHost}:{port}";

            if (this.Capabilities.HasFlag(PeerCaps.Sync))
            {
                QueueEndpoints(seeds);

                // TODO this is a security issue, later change this to be configurable and default to localhost
                var bindAddress = IPAddress.Any;

                listener = new TcpListener(bindAddress, port);

                if (seeds.Any())
                {
                    // temporary HACK
                    var baseURL = "http:" + seeds.First().Split(':')[1];
                    ProxyURL = baseURL + ":7078/api";
                }
            }
        }
Ejemplo n.º 5
0
        public Transaction BroadcastTransaction(Transaction tx)
        {
            var h = tx.GetHash();

            Mempool.Add(h, tx);
            OnNewTransaction(tx);
            return(tx);
        }
Ejemplo n.º 6
0
 public MempoolTests()
 {
     _hashProvider   = new HashProvider(HashingAlgorithm.GetAlgorithmMetadata("blake2b-256"));
     _memPool        = new Mempool(Substitute.For <IMempoolService <PublicEntryDao> >());
     _mapperProvider = new TestMapperProvider();
     _mempoolItem    = TransactionHelper
                       .GetPublicTransaction().PublicEntry
                       .ToDao <PublicEntry, PublicEntryDao>(_mapperProvider);
 }
Ejemplo n.º 7
0
        protected override void OnStart()
        {
            Console.CancelKeyPress += delegate
            {
                this.Terminate();
            };

            ValidateConfig();

            Version = Assembly.GetAssembly(typeof(Spook)).GetVersion();

            _nodeKeys = SetupNodeKeys();

            if (!SetupNexus())
            {
                this.OnStop();
                return;
            }

            SetupOracleApis();

            if (Settings.Node.HasMempool && !Settings.Node.Readonly)
            {
                _mempool = SetupMempool();
            }

            _peerCaps = SetupPeerCaps();

            _node = SetupNode();

            _nexusApi = SetupNexusApi();


            if (_node != null && Settings.App.NodeStart)
            {
                _node.StartInThread();
            }

            _commandDispatcher = SetupCommandDispatcher();

            if (Settings.Simulator.Enabled)
            {
                StartSimulator(_commandDispatcher);
            }
            else
            {
                MakeReady(_commandDispatcher);
            }

            if (!string.IsNullOrEmpty(Settings.Oracle.Swaps))
            {
                _tokenSwapper = StartTokenSwapper();
            }
        }
Ejemplo n.º 8
0
        public Transaction GiveMoney(Script scriptPubKey, Money value)
        {
            var tx = new Transaction();

            tx.Outputs.Add(new TxOut(value, scriptPubKey));
            var h = tx.GetHash();

            Mempool.Add(h, tx);
            OnNewTransaction(tx);
            return(tx);
        }
Ejemplo n.º 9
0
        public MempoolPlugin(Mempool mempool, Logger logger, int periodInSeconds)
        {
            this.Mempool         = mempool;
            this.logger          = logger;
            this.periodInSeconds = periodInSeconds;
            this.gui             = logger as ConsoleGUI;

            if (gui != null)
            {
                this.graph = new Graph();
                gui.SetChannelGraph(Channel, graph);
            }
        }
Ejemplo n.º 10
0
        public Node(string version, Nexus nexus, Mempool mempool, PhantasmaKeys keys, int port, PeerCaps caps, IEnumerable <string> seeds, Logger log)
        {
            Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool");

            this.Logger = Logger.Init(log);

            this.Version      = version;
            this.Nexus        = nexus;
            this.Port         = port;
            this.Keys         = keys;
            this.Capabilities = caps;

            if (Capabilities.HasFlag(PeerCaps.Sync))
            {
                this.Nexus.AddPlugin(new NodePlugin(this));
            }

            if (Capabilities.HasFlag(PeerCaps.Mempool))
            {
                Throw.IfNull(mempool, nameof(mempool));
                this._mempool = mempool;
            }
            else
            {
                this._mempool = null;
            }

            var ip = GetPublicIP();

            Throw.IfNull(ip, nameof(ip));

            this.PublicIP = ip.ToString();

            QueueEndpoints(seeds.Select(seed => ParseEndpoint(seed)));

            // TODO this is a security issue, later change this to be configurable and default to localhost
            var bindAddress = IPAddress.Any;

            listener = new TcpListener(bindAddress, port);
            client   = new TcpClient();
        }
Ejemplo n.º 11
0
        public Node(Nexus nexus, Mempool mempool, KeyPair keys, int port, IEnumerable <string> seeds, Logger log)
        {
            Throw.IfNull(mempool, nameof(mempool));
            Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool");

            this.Nexus = nexus;
            this.Port  = port;
            this.Keys  = keys;

            this.Logger = Logger.Init(log);

            this._mempool = mempool;

            QueueEndpoints(seeds.Select(seed => ParseEndpoint(seed)));

            // TODO this is a security issue, later change this to be configurable and default to localhost
            var bindAddress = IPAddress.Any;

            listener = new TcpListener(bindAddress, port);
            client   = new TcpClient();
        }
Ejemplo n.º 12
0
        private void InitMainNode(int _port = 7077)
        {
            string wif = nexusWif;

            int port = _port;

            var node_keys = PhantasmaKeys.FromWIF(wif);

            var nexus = new Nexus("simnet", null, null);

            nexus.SetOracleReader(new OracleSimulator(nexus));
            var simulator = new NexusSimulator(nexus, node_keys, 1234);

            // mempool setup
            mempool = new Mempool(nexus, Mempool.MinimumBlockTime, 1, System.Text.Encoding.UTF8.GetBytes("TEST"));
            mempool.SetKeys(node_keys);
            mempool.StartInThread();

            // node setup
            node = new Node("test node", nexus, mempool, node_keys, "localhost", port, PeerCaps.Mempool, Enumerable.Empty <String>(), new DebugLogger());
            node.StartInThread();
        }
Ejemplo n.º 13
0
        public Node(string version, Nexus nexus, Mempool mempool, PhantasmaKeys keys, int port, PeerCaps caps, IEnumerable <string> seeds, Logger log)
        {
            Throw.If(keys.Address != mempool.ValidatorAddress, "invalid mempool");

            this.Version      = version;
            this.Nexus        = nexus;
            this.Port         = port;
            this.Keys         = keys;
            this.Capabilities = caps;

            if (Capabilities.HasFlag(PeerCaps.Events))
            {
                this.Nexus.AddPlugin(new NodePlugin(this));
            }

            if (Capabilities.HasFlag(PeerCaps.Mempool))
            {
                Throw.IfNull(mempool, nameof(mempool));
                this._mempool = mempool;
            }
            else
            {
                this._mempool = null;
            }

            // obtains the public IP of the node. This might not be the most sane way to do it...
            this.PublicIP = new WebClient().DownloadString("http://icanhazip.com").Trim();
            Throw.IfNullOrEmpty(PublicIP, nameof(PublicIP));

            this.Logger = Logger.Init(log);

            QueueEndpoints(seeds.Select(seed => ParseEndpoint(seed)));

            // TODO this is a security issue, later change this to be configurable and default to localhost
            var bindAddress = IPAddress.Any;

            listener = new TcpListener(bindAddress, port);
            client   = new TcpClient();
        }
Ejemplo n.º 14
0
        private void InitializeInstance()
        {
            Concensus  = new Consensus();
            Blockchain = new Blockchain();
            Miner      = new Miner();
            Network    = new Network();
            Accounts   = new Accounts();
            Mempool    = new Mempool();
            Wallet     = new Wallet();

            Client.Socket.On(Socket.EVENT_CONNECT, () => { Client.Connected = true; });
            Client.Socket.On(Socket.EVENT_DISCONNECT, () => { Client.Connected = false; });
            Client.Socket.On("LifeCheck", (jData) =>
            {
                JObject jObject = (JObject)jData;
                var deserialize = jObject.ToObject <LifeCheckStruct>();
                if (LifeCheck != null)
                {
                    LifeCheck.Invoke(deserialize);
                }
            });
        }
Ejemplo n.º 15
0
        private void InitMainNode()
        {
            var log = new ConsoleLogger();

            string wif = nexusWif;

            int port = 7077;

            var node_keys = KeyPair.FromWIF(wif);

            var simulator = new ChainSimulator(node_keys, 1234);

            nexus = simulator.Nexus;

            // mempool setup
            mempool = new Mempool(node_keys, nexus, Mempool.MinimumBlockTime);
            mempool.Start();

            // node setup
            node = new Node(nexus, mempool, node_keys, port, Enumerable.Empty <String>(), log);
            log.Message("Phantasma Node address: " + node_keys.Address.Text);
            node.Start();
        }
Ejemplo n.º 16
0
        private void Forward(IxgbeDevice rxDev, int rxQueue, IxgbeDevice txDev, int txQueue, Span <PacketBuffer> buffers)
        {
            var rxBuffCount = rxDev.RxBatch(rxQueue, buffers);

            if (rxBuffCount > 0)
            {
                var rxBuffers = buffers.Slice(0, rxBuffCount);
                //Touch all buffers to simulate a realistic scenario
                foreach (var buffer in rxBuffers)
                {
                    buffer.Touch();
                }

                var txBuffCount = txDev.TxBatch(txQueue, rxBuffers);
                _mempool = (_mempool == null) ? Mempool.FindPool(rxBuffers[0].MempoolId) : _mempool;

                //Drop unsent packets
                foreach (var buffer in rxBuffers.Slice(txBuffCount))
                {
                    _mempool.FreeBuffer(buffer);
                }
            }
        }
Ejemplo n.º 17
0
        private void InitMempool()
        {
            _mempool = MemoryHelper.AllocateMempool(BuffersCount);

            //Pre-fill all our packet buffers with some templates that can be modified later
            var buffers = new PacketBuffer[BuffersCount];

            for (int i = 0; i < BuffersCount; i++)
            {
                var buffer = _mempool.GetPacketBuffer();
                buffer.Size = (uint)PacketData.Length;
                buffer.WriteData(0, PacketData);
                var ipData = buffer.CopyData(14, 20);
                buffer.WriteData(24, (short)CalcIpChecksum(ipData));
                buffers[i] = buffer;
            }

            //Return them all to the mempool, all future allocations will return buffers with the data set above
            foreach (var buffer in buffers)
            {
                _mempool.FreeBuffer(buffer);
            }
        }
Ejemplo n.º 18
0
        private Mempool SetupMempool()
        {
            var mempool = new Mempool(_nexus
                                      , Settings.Node.BlockTime
                                      , Settings.Node.MinimumFee
                                      , System.Text.Encoding.UTF8.GetBytes(TxIdentifier)
                                      , 0
                                      , Logger
                                      , Settings.Node.ProfilerPath
                                      );

            if (Settings.Node.MempoolLog)
            {
                mempool.OnTransactionFailed    += Mempool_OnTransactionFailed;
                mempool.OnTransactionAdded     += (hash) => Logger.Message($"Received transaction {hash}");
                mempool.OnTransactionCommitted += (hash) => Logger.Message($"Commited transaction {hash}");
                mempool.OnTransactionDiscarded += (hash) => Logger.Message($"Discarded transaction {hash}");
            }
            if (Settings.App.NodeStart)
            {
                mempool.StartInThread(ThreadPriority.AboveNormal);
            }
            return(mempool);
        }
Ejemplo n.º 19
0
        protected override void OnStart()
        {
            Console.CancelKeyPress += delegate
            {
                this.Terminate();
            };

            ValidateConfig();

            Version = Assembly.GetAssembly(typeof(Spook)).GetVersion();

            _nodeKeys = SetupNodeKeys();

            if (Settings.Node.Mode != NodeMode.Proxy && !SetupNexus())
            {
                this.OnStop();
                return;
            }

            SetupOracleApis();

            if (Settings.Node.HasMempool && !Settings.Node.Readonly)
            {
                _mempool = SetupMempool();
            }

            if (Settings.Node.Mode != NodeMode.Proxy)
            {
                _availablePorts.Add(new PeerPort("sync", Settings.Node.NodePort));
            }

            if (Settings.Node.HasRpc)
            {
                _availablePorts.Add(new PeerPort("rpc", Settings.Node.RpcPort));
            }

            if (Settings.Node.HasRest)
            {
                _availablePorts.Add(new PeerPort("rest", Settings.Node.RestPort));
            }

            _peerCaps = SetupPeerCaps();

            _node = SetupNode();

            _nexusApi = SetupNexusApi();


            if (_node != null && Settings.App.NodeStart)
            {
                if (_peerCaps.HasFlag(PeerCaps.Sync) && Settings.Node.NodeHost.Contains("localhost"))
                {
                    Logger.Warning($"This node host external endpoint is not properly configured and it won't appear on other nodes GetPeers API call.");
                }

                _node.StartInThread();
            }

            _commandDispatcher = SetupCommandDispatcher();

            if (Settings.Simulator.Enabled)
            {
                StartSimulator(_commandDispatcher);
            }
            else
            {
                MakeReady(_commandDispatcher);
            }

            var enabledSwapPlatforms = Settings.Oracle.SwapPlatforms.Select(x => x.Chain != SwapPlatformChain.Phantasma && x.Enabled);

            if (enabledSwapPlatforms.Any())
            {
                _tokenSwapper = StartTokenSwapper();
            }
            else
            {
                Logger.Warning("No swap platforms found in config, token swapper won't be available");
            }
        }
Ejemplo n.º 20
0
        public static async Task FlushAll()
        {
            await Mempool.Flush();

            await Peers.Flush();
        }
Ejemplo n.º 21
0
        public override int TxBatch(int queueId, Span <PacketBuffer> buffers)
        {
            if (queueId < 0 || queueId >= RxQueues.Length)
            {
                throw new ArgumentOutOfRangeException("Queue id out of bounds");
            }

            var    queue        = TxQueues[queueId] as IxgbeTxQueue;
            ushort cleanIndex   = queue.CleanIndex;
            ushort currentIndex = (ushort)queue.Index;
            var    cmdTypeFlags = IxgbeDefs.ADVTXD_DCMD_EOP | IxgbeDefs.ADVTXD_DCMD_RS | IxgbeDefs.ADVTXD_DCMD_IFCS |
                                  IxgbeDefs.ADVTXD_DCMD_DEXT | IxgbeDefs.ADVTXD_DTYP_DATA;
            //All packet buffers that will be handled here will belong to the same mempool
            Mempool pool = null;

            //Step 1: Clean up descriptors that were sent out by the hardware and return them to the mempool
            //Start by reading step 2 which is done first for each packet
            //Cleaning up must be done in batches for performance reasons, so this is unfortunately somewhat complicated
            while (true)
            {
                //currentIndex is always ahead of clean (invariant of our queue)
                int cleanable = currentIndex - cleanIndex;
                if (cleanable < 0)
                {
                    cleanable = queue.EntriesCount + cleanable;
                }
                if (cleanable < TxCleanBatch)
                {
                    break;
                }

                //Calculate the index of the last transcriptor in the clean batch
                //We can't check all descriptors for performance reasons
                int cleanupTo = cleanIndex + TxCleanBatch - 1;
                if (cleanupTo >= queue.EntriesCount)
                {
                    cleanupTo -= queue.EntriesCount;
                }

                var  descAddr = queue.GetDescriptorAddress((ushort)cleanupTo);
                uint status   = queue.ReadWbStatus(descAddr);

                //Hardware sets this flag as soon as it's sent out, we can give back all bufs in the batch back to the mempool
                if ((status & IxgbeDefs.ADVTXD_STAT_DD) != 0)
                {
                    int i = cleanIndex;
                    while (true)
                    {
                        var packetBuffer = new PacketBuffer(queue.VirtualAddresses[i]);
                        if (pool == null)
                        {
                            pool = Mempool.FindPool(packetBuffer.MempoolId);
                            if (pool == null)
                            {
                                throw new NullReferenceException("Could not find mempool with id specified by PacketBuffer");
                            }
                        }
                        pool.FreeBufferFast(packetBuffer);
                        if (i == cleanupTo)
                        {
                            break;
                        }
                        i = WrapRing(i, queue.EntriesCount);
                    }
                    //Next descriptor to be cleaned up is one after the one we just cleaned
                    cleanIndex = (ushort)WrapRing(cleanupTo, queue.EntriesCount);
                }
                //Clean the whole batch or nothing. This will leave some packets in the queue forever
                //if you stop transmitting but that's not a real concern
                else
                {
                    break;
                }
            }
            queue.CleanIndex = cleanIndex;

            //Step 2: Send out as many of our packets as possible
            int sent;

            for (sent = 0; sent < buffers.Length; sent++)
            {
                var    descAddr  = queue.GetDescriptorAddress(currentIndex);
                ushort nextIndex = WrapRing(currentIndex, (ushort)queue.EntriesCount);
                //We are full if the next index is the one we are trying to reclaim
                if (cleanIndex == nextIndex)
                {
                    break;
                }

                var buffer = buffers[sent];
                //Remember virtual address to clean it up later
                queue.VirtualAddresses[currentIndex] = buffer.VirtualAddress;
                queue.Index = WrapRing(queue.Index, queue.EntriesCount);
                //NIC reads from here
                queue.WriteBufferAddress(descAddr, buffer.PhysicalAddress + PacketBuffer.DataOffset);
                //Always the same flags: One buffer (EOP), advanced data descriptor, CRC offload, data length
                var bufSize = buffer.Size;
                queue.WriteCmdTypeLength(descAddr, cmdTypeFlags | bufSize);
                //No fancy offloading - only the total payload length
                //implement offloading flags here:
                // * ip checksum offloading is trivial: just set the offset
                // * tcp/udp checksum offloading is more annoying, you have to precalculate the pseudo-header checksum
                queue.WriteOlInfoStatus(descAddr, bufSize << (int)IxgbeDefs.ADVTXD_PAYLEN_SHIFT);
                currentIndex = nextIndex;
            }

            //Send out by advancing tail, i.e. pass control of the bus to the NIC
            SetReg(IxgbeDefs.TDT((uint)queueId), (uint)queue.Index);
            return(sent);
        }
        public MempoolTests()
        {
            _memPool = new Mempool(Substitute.For <IMempoolRepository <MempoolDocument> >());

            _transactionBroadcast = TransactionHelper.GetPublicTransaction();
        }
Ejemplo n.º 23
0
        public void GenerateRandomBlock(Mempool mempool = null)
        {
            BeginBlock();

            int transferCount = 1 + _rnd.Next() % 10;
            int tries         = 0;

            while (tries < 10000)
            {
                if (transactions.Count >= transferCount)
                {
                    break;
                }

                tries++;
                var source = _keys[_rnd.Next() % _keys.Count];

                if (usedAddresses.Contains(source.Address))
                {
                    continue;
                }

                var prevTxCount = transactions.Count;

                var sourceChain = Nexus.RootChain;
                var fee         = 9999;

                string tokenSymbol;

                switch (_rnd.Next() % 4)
                {
                case 1: tokenSymbol = DomainSettings.FiatTokenSymbol; break;

                //case 2: token = Nexus.FuelTokenSymbol; break;
                default: tokenSymbol = DomainSettings.StakingTokenSymbol; break;
                }

                switch (_rnd.Next() % 7)
                {
                /*
                 * // side-chain send
                 * case 1:
                 *  {
                 *      var sourceChainList = Nexus.Chains.ToArray();
                 *      sourceChain = Nexus.GetChainByName( sourceChainList[_rnd.Next() % sourceChainList.Length]);
                 *
                 *      var targetChainList = Nexus.Chains.Select(x => Nexus.GetChainByName(x)).Where(x => Nexus.GetParentChainByName(x.Name) == sourceChain.Name || Nexus.GetParentChainByName(sourceChain.Name) == x.Name).ToArray();
                 *      var targetChain = targetChainList[_rnd.Next() % targetChainList.Length];
                 *
                 *      var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, DomainSettings.FuelTokenDecimals);
                 *
                 *      var tokenBalance = sourceChain.GetTokenBalance(sourceChain.Storage, tokenSymbol, source.Address);
                 *      var fuelBalance = sourceChain.GetTokenBalance(sourceChain.Storage, DomainSettings.FuelTokenSymbol, source.Address);
                 *
                 *      var expectedTotal = total;
                 *      if (tokenSymbol == DomainSettings.FuelTokenSymbol)
                 *      {
                 *          expectedTotal += fee;
                 *      }
                 *
                 *      var sideFee = 0;
                 *      if (tokenSymbol != DomainSettings.FuelTokenSymbol)
                 *      {
                 *          sideFee = fee;
                 *      }
                 *
                 *      if (tokenBalance > expectedTotal && fuelBalance > fee + sideFee)
                 *      {
                 *          Logger.Debug($"Rnd.SideChainSend: {total} {tokenSymbol} from {source.Address}");
                 *          GenerateSideChainSend(source, tokenSymbol, sourceChain, source.Address, targetChain, total, sideFee);
                 *      }
                 *      break;
                 *  }
                 *
                 * // side-chain receive
                 * case 2:
                 *  {
                 *      if (_pendingBlocks.Any())
                 *      {
                 *          var pendingBlock = _pendingBlocks.First();
                 *
                 *          if (mempool == null || Nexus.GetConfirmationsOfHash(pendingBlock.hash) > 0)
                 *          {
                 *
                 *              var balance = pendingBlock.destChain.GetTokenBalance(pendingBlock.destChain.Storage, pendingBlock.tokenSymbol, source.Address);
                 *              if (balance > 0)
                 *              {
                 *                  Logger.Message($"...Settling {pendingBlock.sourceChain.Name}=>{pendingBlock.destChain.Name}: {pendingBlock.hash}");
                 *                  GenerateSideChainSettlement(source, pendingBlock.sourceChain, pendingBlock.destChain, pendingBlock.hash);
                 *              }
                 *          }
                 *      }
                 *
                 *      break;
                 *  }
                 */
                /*
                 * // stable claim
                 * case 3:
                 * {
                 *  sourceChain = bankChain;
                 *  tokenSymbol = Nexus.FuelTokenSymbol;
                 *
                 *  var balance = sourceChain.GetTokenBalance(tokenSymbol, source.Address);
                 *
                 *  var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals - 1);
                 *
                 *  if (balance > total + fee)
                 *  {
                 *      Logger.Debug($"Rnd.StableClaim: {total} {tokenSymbol} from {source.Address}");
                 *      GenerateStableClaim(source, sourceChain, total);
                 *  }
                 *
                 *  break;
                 * }
                 *
                 * // stable redeem
                 * case 4:
                 * {
                 *  sourceChain = bankChain;
                 *  tokenSymbol = Nexus.FiatTokenSymbol;
                 *
                 *  var tokenBalance = sourceChain.GetTokenBalance(tokenSymbol, source.Address);
                 *  var fuelBalance = sourceChain.GetTokenBalance(Nexus.FuelTokenSymbol, source.Address);
                 *
                 *  var rate = (BigInteger) bankChain.InvokeContract("bank", "GetRate", Nexus.FuelTokenSymbol);
                 *  var total = tokenBalance / 10;
                 *  if (total >= rate && fuelBalance > fee)
                 *  {
                 *      Logger.Debug($"Rnd.StableRedeem: {total} {tokenSymbol} from {source.Address}");
                 *      GenerateStableRedeem(source, sourceChain, total);
                 *  }
                 *
                 *  break;
                 * }*/

                // name register
                case 5:
                {
                    sourceChain = this.Nexus.RootChain;
                    tokenSymbol = DomainSettings.FuelTokenSymbol;

                    var token = Nexus.GetTokenInfo(Nexus.RootStorage, tokenSymbol);

                    var balance = sourceChain.GetTokenBalance(sourceChain.Storage, token, source.Address);
                    if (balance > fee + AccountContract.RegistrationCost && !pendingNames.Contains(source.Address))
                    {
                        var randomName = accountNames[_rnd.Next() % accountNames.Length];

                        switch (_rnd.Next() % 10)
                        {
                        case 1:
                        case 2:
                            randomName += (_rnd.Next() % 10).ToString();
                            break;

                        case 3:
                        case 4:
                        case 5:
                            randomName += (10 + _rnd.Next() % 90).ToString();
                            break;

                        case 6:
                            randomName += (100 + _rnd.Next() % 900).ToString();
                            break;
                        }

                        var currentName = Nexus.RootChain.LookUpAddressName(Nexus.RootStorage, source.Address);
                        if (currentName == ValidationUtils.ANONYMOUS)
                        {
                            var lookup = Nexus.LookUpName(Nexus.RootStorage, randomName);
                            if (lookup.IsNull)
                            {
                                Logger.Debug($"Rnd.GenerateAccount: {source.Address} => {randomName}");
                                GenerateAccountRegistration(source, randomName);
                            }
                        }
                    }

                    break;
                }

                // normal transfer
                default:
                {
                    var     temp = _rnd.Next() % 5;
                    Address targetAddress;

                    if ((_keys.Count < 2 || temp == 0) && _keys.Count < 2000)
                    {
                        var key = PhantasmaKeys.Generate();
                        _keys.Add(key);
                        targetAddress = key.Address;
                    }
                    else
                    {
                        targetAddress = _keys[_rnd.Next() % _keys.Count].Address;
                    }

                    if (source.Address != targetAddress)
                    {
                        var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, DomainSettings.FuelTokenDecimals - 1);

                        var token        = Nexus.GetTokenInfo(Nexus.RootStorage, tokenSymbol);
                        var tokenBalance = sourceChain.GetTokenBalance(sourceChain.Storage, token, source.Address);

                        var fuelToken   = Nexus.GetTokenInfo(Nexus.RootStorage, DomainSettings.FuelTokenSymbol);
                        var fuelBalance = sourceChain.GetTokenBalance(sourceChain.Storage, fuelToken, source.Address);

                        var expectedTotal = total;
                        if (tokenSymbol == DomainSettings.FuelTokenSymbol)
                        {
                            expectedTotal += fee;
                        }

                        if (tokenBalance > expectedTotal && fuelBalance > fee)
                        {
                            Logger.Message($"Rnd.Transfer: {total} {tokenSymbol} from {source.Address} to {targetAddress}");
                            GenerateTransfer(source, targetAddress, sourceChain, tokenSymbol, total);
                        }
                    }
                    break;
                }
                }
            }

            if (transactions.Count > 0)
            {
                EndBlock(mempool);
            }
            else
            {
                CancelBlock();
            }
        }
Ejemplo n.º 24
0
        public IEnumerable <Block> EndBlock(Mempool mempool = null)
        {
            if (!blockOpen)
            {
                throw new Exception("Simulator block not open");
            }

            usedAddresses.Clear();

            blockOpen = false;

            var blocks = new List <Block>();

            if (txChainMap.Count > 0)
            {
                var chains = txChainMap.Values.Distinct();

                foreach (var chain in chains)
                {
                    var hashes = txChainMap.Where((p) => p.Value == chain).Select(x => x.Key);
                    if (hashes.Any())
                    {
                        var txs = new List <Transaction>();
                        foreach (var hash in hashes)
                        {
                            txs.Add(txHashMap[hash]);
                        }

                        uint nextHeight = chain.LastBlock != null ? chain.LastBlock.Height + 1 : Chain.InitialHeight;
                        var  prevHash   = chain.LastBlock != null ? chain.LastBlock.Hash : Hash.Null;

                        var block = new Block(nextHeight, chain.Address, CurrentTime, hashes, prevHash);

                        bool submitted;

                        if (mempool != null)
                        {
                            submitted = true;
                            foreach (var tx in txs)
                            {
                                try
                                {
                                    mempool.Submit(tx);
                                }
                                catch
                                {
                                    submitted = false;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            try
                            {
                                chain.AddBlock(block, txs, null);
                                submitted = true;
                            }
                            catch (Exception e)
                            {
                                submitted = false;
                            }
                        }

                        if (submitted)
                        {
                            blocks.Add(block);

                            CurrentTime += TimeSpan.FromMinutes(45);

                            // add the finished block hash to each pending side chain tx
                            if (_pendingEntries.Count > 0)
                            {
                                foreach (var entry in _pendingEntries.Values)
                                {
                                    if (entry.sourceChain != chain)
                                    {
                                        continue;
                                    }

                                    var pendingBlock = new SideChainPendingBlock()
                                    {
                                        sourceChain = entry.sourceChain,
                                        destChain   = entry.destChain,
                                        hash        = block.Hash,
                                        tokenSymbol = entry.tokenSymbol
                                    };

                                    _pendingBlocks.Add(pendingBlock);
                                    Logger.Debug($"...Sending {entry.sourceChain.Name}=>{entry.destChain.Name}: {block.Hash}");
                                }
                            }

                            Logger.Message($"End block #{step} @ {chain.Name} chain: {block.Hash}");
                        }
                        else
                        {
                            throw new Exception($"add block @ {chain.Name} failed");
                        }
                    }
                }

                _pendingEntries.Clear();
                return(blocks);
            }

            return(Enumerable.Empty <Block>());
        }
Ejemplo n.º 25
0
        public CLI(string[] args)
        {
            var culture = new CultureInfo("en-US");

            CultureInfo.DefaultThreadCurrentCulture = culture;

            var seeds = new List <string>();

            var settings = new Arguments(args);

            /*
             * for (int i = 0; i < 20; i++)
             * {
             *  var k = KeyPair.Generate();
             *  Console.WriteLine(k.ToWIF() + " => " + k.Address.Text);
             * }*/

            var useGUI = settings.GetBool("gui.enabled", true);

            if (useGUI)
            {
                gui    = new ConsoleGUI();
                logger = gui;
            }
            else
            {
                gui    = null;
                logger = new ConsoleLogger();
            }

            string mode = settings.GetString("node.mode", "validator");

            bool hasRPC  = settings.GetBool("rpc.enabled", false);
            bool hasREST = settings.GetBool("rest.enabled", false);

            string wif = settings.GetString("node.wif");

            var nexusName = settings.GetString("nexus.name", "simnet");

            switch (mode)
            {
            case "sender":
                string host               = settings.GetString("sender.host");
                int    threadCount        = settings.GetInt("sender.threads", 8);
                int    addressesPerSender = settings.GetInt("sender.addressCount", 100);
                RunSender(wif, host, threadCount, addressesPerSender);
                Console.WriteLine("Sender finished operations.");
                return;

            case "validator": break;

            default:
            {
                logger.Error("Unknown mode: " + mode);
                return;
            }
            }

            int defaultPort = 0;

            for (int i = 0; i < validatorWIFs.Length; i++)
            {
                if (validatorWIFs[i] == wif)
                {
                    defaultPort = (7073 + i);
                }
            }

            if (defaultPort == 0)
            {
                defaultPort = (7073 + validatorWIFs.Length);
            }

            int port = settings.GetInt("node.port", defaultPort);
            var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage";
            var storagePath        = settings.GetString("storage.path", defaultStoragePath);

            storagePath = storagePath.Replace("\\", "/");
            if (!storagePath.EndsWith('/'))
            {
                storagePath += '/';
            }

            var storageFix = settings.GetBool("storage.fix", false);

            // TODO remove this later
            if (storageFix)
            {
                if (Directory.Exists(storagePath))
                {
                    logger.Warning("Storage fix enabled... Cleaning up all storage...");
                    var di = new DirectoryInfo(storagePath);
                    foreach (FileInfo file in di.EnumerateFiles())
                    {
                        file.Delete();
                    }
                }
            }

            logger.Message("Storage path: " + storagePath);

            var node_keys = KeyPair.FromWIF(wif);

            nexus = new Nexus(logger, (name) => new BasicDiskStore(storagePath + name + ".txt"));

            bool bootstrap = false;

            if (wif == validatorWIFs[0])
            {
                if (!nexus.Ready)
                {
                    logger.Debug("Boostraping nexus...");
                    bootstrap = true;
                    if (!nexus.CreateGenesisBlock(nexusName, node_keys, Timestamp.Now))
                    {
                        throw new ChainException("Genesis block failure");
                    }

                    logger.Debug("Genesis block created: " + nexus.GenesisHash);
                }
            }
            else
            {
                //nexus = new Nexus(nexusName, genesisAddress, logger);
                nexus = new Nexus(logger);
                seeds.Add("127.0.0.1:7073");
            }

            // TODO this should be later optional to enable
            nexus.AddPlugin(new ChainAddressesPlugin());
            nexus.AddPlugin(new TokenTransactionsPlugin());
            nexus.AddPlugin(new AddressTransactionsPlugin());
            nexus.AddPlugin(new UnclaimedTransactionsPlugin());

            running = true;

            // mempool setup
            int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime);

            this.mempool = new Mempool(node_keys, nexus, blockTime, ReadFromOracle);
            mempool.Start(ThreadPriority.AboveNormal);

            mempool.OnTransactionFailed += Mempool_OnTransactionFailed;

            api = new NexusAPI(nexus, mempool);

            // RPC setup
            if (hasRPC)
            {
                int rpcPort = settings.GetInt("rpc.port", 7077);

                logger.Message($"RPC server listening on port {rpcPort}...");
                var rpcServer = new RPCServer(api, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text));
                rpcServer.Start(ThreadPriority.AboveNormal);
            }

            // REST setup
            if (hasREST)
            {
                int restPort = settings.GetInt("rest.port", 7078);

                logger.Message($"REST server listening on port {restPort}...");
                var restServer = new RESTServer(api, "/api", restPort, (level, text) => WebLogMapper("rest", level, text));
                restServer.Start(ThreadPriority.AboveNormal);
            }


            cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", "");
            if (!string.IsNullOrEmpty(cryptoCompareAPIKey))
            {
                logger.Message($"CryptoCompare API enabled...");
            }

            // node setup
            this.node = new Node(nexus, mempool, node_keys, port, seeds, logger);
            node.Start();

            if (gui != null)
            {
                int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds
                RegisterPlugin(new TPSPlugin(logger, pluginPeriod));
                RegisterPlugin(new RAMPlugin(logger, pluginPeriod));
                RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod));
            }

            Console.CancelKeyPress += delegate {
                Terminate();
            };

            var dispatcher = new CommandDispatcher();

            SetupCommands(dispatcher);

            bool useSimulator = settings.GetBool("simulator.enabled", false);

            if (useSimulator && bootstrap)
            {
                new Thread(() =>
                {
                    logger.Message("Initializing simulator...");
                    var simulator = new ChainSimulator(this.nexus, node_keys, 1234);

                    logger.Message("Bootstrapping validators");
                    simulator.BeginBlock();
                    for (int i = 1; i < validatorWIFs.Length; i++)
                    {
                        simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, Nexus.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, Nexus.StakingTokenDecimals));
                    }
                    simulator.EndBlock();

                    for (int i = 0; i < 3; i++)
                    {
                        logger.Message("Generating sim block #" + i);
                        simulator.GenerateRandomBlock();
                    }

                    NachoServer.InitNachoServer(nexus, simulator, node_keys, logger);
                    MakeReady(dispatcher);
                }).Start();
            }
            else
            {
                MakeReady(dispatcher);
            }

            this.Run();
        }
Ejemplo n.º 26
0
        public void GenerateRandomBlock(Mempool mempool = null)
        {
            //Console.WriteLine("begin block #" + Nexus.RootChain.BlockHeight);
            BeginBlock();

            int transferCount = 1 + _rnd.Next() % 10;
            int tries         = 0;

            while (transactions.Count < transferCount && tries < 1000)
            {
                tries++;
                var source = _keys[_rnd.Next() % _keys.Count];

                if (usedAddresses.Contains(source.Address))
                {
                    continue;
                }

                var prevTxCount = transactions.Count;

                var sourceChain = Nexus.RootChain;
                var fee         = 9999;

                Token token;

                switch (_rnd.Next() % 4)
                {
                case 1: token = Nexus.StableToken; break;

                //case 2: token = Nexus.FuelToken; break;
                default: token = Nexus.StakingToken; break;
                }

                switch (_rnd.Next() % 7)
                {
                // side-chain send
                case 1:
                {
                    var sourceChainList = Nexus.Chains.ToArray();
                    sourceChain = sourceChainList[_rnd.Next() % sourceChainList.Length];

                    var targetChainList = Nexus.Chains.Where(x => x.ParentChain == sourceChain || sourceChain.ParentChain == x).ToArray();
                    var targetChain     = targetChainList[_rnd.Next() % targetChainList.Length];

                    var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals);

                    var tokenBalance = sourceChain.GetTokenBalance(token, source.Address);
                    var fuelBalance  = sourceChain.GetTokenBalance(Nexus.FuelToken, source.Address);

                    var expectedTotal = total;
                    if (token == Nexus.FuelToken)
                    {
                        expectedTotal += fee;
                    }

                    var sideFee = 0;
                    if (token != Nexus.FuelToken)
                    {
                        sideFee = fee;
                    }

                    if (tokenBalance > expectedTotal && fuelBalance > fee + sideFee)
                    {
                        GenerateSideChainSend(source, token, sourceChain, source.Address, targetChain, total, sideFee);
                    }
                    break;
                }

                // side-chain receive
                case 2:
                {
                    if (_pendingBlocks.Any())
                    {
                        var pendingBlock = _pendingBlocks.First();

                        if (mempool == null || Nexus.GetConfirmationsOfHash(pendingBlock.hash) > 0)
                        {
                            var balance = pendingBlock.destChain.GetTokenBalance(pendingBlock.token, source.Address);
                            if (balance > 0)
                            {
                                Logger.Message($"...Settling {pendingBlock.sourceChain.Name}=>{pendingBlock.destChain.Name}: {pendingBlock.hash}");
                                GenerateSideChainSettlement(source, pendingBlock.sourceChain, pendingBlock.destChain, pendingBlock.hash);
                            }
                        }
                    }

                    break;
                }

                // stable claim
                case 3:
                {
                    sourceChain = bankChain;
                    token       = Nexus.FuelToken;

                    var balance = sourceChain.GetTokenBalance(token, source.Address);

                    var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals - 1);

                    if (balance > total + fee)
                    {
                        GenerateStableClaim(source, sourceChain, total);
                    }

                    break;
                }

                // stable redeem
                case 4:
                {
                    sourceChain = bankChain;
                    token       = Nexus.StableToken;

                    var tokenBalance = sourceChain.GetTokenBalance(token, source.Address);
                    var fuelBalance  = sourceChain.GetTokenBalance(Nexus.FuelToken, source.Address);

                    var bankContract = bankChain.FindContract <BankContract>("bank");
                    var rate         = bankContract.GetRate(Nexus.FuelTokenSymbol);
                    var total        = tokenBalance / 10;
                    if (total >= rate && fuelBalance > fee)
                    {
                        GenerateStableRedeem(source, sourceChain, total);
                    }

                    break;
                }

                // name register
                case 5:
                {
                    sourceChain = this.Nexus.RootChain;
                    token       = Nexus.FuelToken;

                    var balance = sourceChain.GetTokenBalance(token, source.Address);
                    if (balance > fee + AccountContract.RegistrationCost && !pendingNames.Contains(source.Address))
                    {
                        var randomName = accountNames[_rnd.Next() % accountNames.Length];

                        switch (_rnd.Next() % 10)
                        {
                        case 1:
                        case 2:
                            randomName += (_rnd.Next() % 10).ToString();
                            break;

                        case 3:
                        case 4:
                        case 5:
                            randomName += (10 + _rnd.Next() % 90).ToString();
                            break;

                        case 6:
                            randomName += (100 + _rnd.Next() % 900).ToString();
                            break;
                        }

                        var currentName = Nexus.LookUpAddress(source.Address);
                        if (currentName == AccountContract.ANONYMOUS)
                        {
                            var lookup = Nexus.LookUpName(randomName);
                            if (lookup == Address.Null)
                            {
                                GenerateAccountRegistration(source, randomName);
                            }
                        }
                    }

                    break;
                }

                // normal transfer
                default:
                {
                    var     temp = _rnd.Next() % 5;
                    Address targetAddress;

                    if ((_keys.Count < 2 || temp == 0) && _keys.Count < 2000)
                    {
                        var key = KeyPair.Generate();
                        _keys.Add(key);
                        targetAddress = key.Address;
                    }
                    else
                    {
                        targetAddress = _keys[_rnd.Next() % _keys.Count].Address;
                    }

                    if (source.Address != targetAddress)
                    {
                        var total = UnitConversion.ToBigInteger(1 + _rnd.Next() % 100, Nexus.FuelTokenDecimals - 1);

                        var tokenBalance = sourceChain.GetTokenBalance(token, source.Address);
                        var fuelBalance  = sourceChain.GetTokenBalance(Nexus.FuelToken, source.Address);

                        var expectedTotal = total;
                        if (token == Nexus.FuelToken)
                        {
                            expectedTotal += fee;
                        }

                        if (tokenBalance > expectedTotal && fuelBalance > fee)
                        {
                            GenerateTransfer(source, targetAddress, sourceChain, token, total);
                            //Console.WriteLine(source.Address + " => " + targetAddress + " " + TokenUtils.ToDecimal( total, token.Decimals) + " " + token.Symbol);
                        }
                    }
                    break;
                }
                }
            }

            EndBlock(mempool);
        }
Ejemplo n.º 27
0
        public IEnumerable <Block> EndBlock(Mempool mempool = null)
        {
            if (!blockOpen)
            {
                throw new Exception("Simulator block not open");
            }

            usedAddresses.Clear();

            blockOpen = false;

            var blocks   = new List <Block>();
            var protocol = (uint)Nexus.GetGovernanceValue(Nexus.RootStorage, Nexus.NexusProtocolVersionTag);

            if (txChainMap.Count > 0)
            {
                var chains = txChainMap.Values.Distinct();

                foreach (var chain in chains)
                {
                    var hashes = txChainMap.Where((p) => p.Value == chain).Select(x => x.Key);
                    if (hashes.Any())
                    {
                        var txs = new List <Transaction>();
                        foreach (var hash in hashes)
                        {
                            txs.Add(txHashMap[hash]);
                        }

                        var        lastBlockHash = chain.GetLastBlockHash();
                        var        lastBlock     = chain.GetBlockByHash(lastBlockHash);
                        BigInteger nextHeight    = lastBlock != null ? lastBlock.Height + 1 : Chain.InitialHeight;
                        var        prevHash      = lastBlock != null ? lastBlock.Hash : Hash.Null;

                        var block = new Block(nextHeight, chain.Address, CurrentTime, hashes, prevHash, protocol, this.blockValidator.Address, System.Text.Encoding.UTF8.GetBytes("SIM"));

                        bool submitted;

                        string reason = "unknown";

                        if (mempool != null)
                        {
                            submitted = true;
                            foreach (var tx in txs)
                            {
                                try
                                {
                                    mempool.Submit(tx);
                                }
                                catch (Exception e)
                                {
                                    reason    = e.Message;
                                    submitted = false;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            try
                            {
                                var changeSet = chain.ProcessBlock(block, transactions, MinimumFee);
                                block.Sign(this.blockValidator);
                                chain.AddBlock(block, txs, MinimumFee, changeSet);
                                submitted = true;
                            }
                            catch (Exception e)
                            {
                                reason    = e.Message;
                                submitted = false;
                            }
                        }

                        if (submitted)
                        {
                            blocks.Add(block);

                            CurrentTime += blockTimeSkip;

                            Logger.Message($"End block #{step} @ {chain.Name} chain: {block.Hash}");
                        }
                        else
                        {
                            throw new ChainException($"add block @ {chain.Name} failed, reason: {reason}");
                        }
                    }
                }

                return(blocks);
            }

            return(Enumerable.Empty <Block>());
        }
Ejemplo n.º 28
0
        public CLI(string[] args)
        {
            var culture = new CultureInfo("en-US");

            Thread.CurrentThread.CurrentCulture     = culture;
            CultureInfo.DefaultThreadCurrentCulture = culture;

            var seeds = new List <string>();

            var settings = new Arguments(args);

            var useGUI = settings.GetBool("gui.enabled", true);

            if (useGUI)
            {
                gui    = new ConsoleGUI();
                logger = gui;
            }
            else
            {
                gui    = null;
                logger = new ConsoleLogger();
            }

            string mode = settings.GetString("node.mode", "default");

            restartTime = settings.GetInt("node.reboot", 0);

            showWebLogs = settings.GetBool("web.log", false);
            bool apiLog = settings.GetBool("api.log", true);

            string apiProxyURL = settings.GetString("api.proxy", "");

            if (string.IsNullOrEmpty(apiProxyURL))
            {
                apiProxyURL = null;
            }

            bool hasSync    = settings.GetBool("sync.enabled", true);
            bool hasMempool = settings.GetBool("mempool.enabled", true);
            bool hasEvents  = settings.GetBool("events.enabled", true);
            bool hasRelay   = settings.GetBool("relay.enabled", true);
            bool hasArchive = settings.GetBool("archive.enabled", true);
            bool hasRPC     = settings.GetBool("rpc.enabled", false);
            bool hasREST    = settings.GetBool("rest.enabled", false);

            var nexusName = settings.GetString("nexus.name", "simnet");

            string profilePath = settings.GetString("mempool.profile", "");

            if (string.IsNullOrEmpty(profilePath))
            {
                profilePath = null;
            }

            bool isValidator = false;

            switch (mode)
            {
            case "sender":
            {
                string host               = settings.GetString("sender.host");
                int    threadCount        = settings.GetInt("sender.threads", 8);
                int    addressesPerSender = settings.GetInt("sender.addressCount", 100);

                string wif = settings.GetString("node.wif");
                RunSender(wif, nexusName, host, threadCount, addressesPerSender);
                Console.WriteLine("Sender finished operations.");
                return;
            }

            case "validator": isValidator = true; break;

            case "default": break;

            default:
            {
                logger.Error("Unknown mode: " + mode);
                return;
            }
            }

            int port = settings.GetInt("node.port", 7073);
            var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage";
            var defaultOraclePath  = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Oracle";
            var storagePath        = FixPath(settings.GetString("storage.path", defaultStoragePath));
            var oraclePath         = FixPath(settings.GetString("storage.oracle", defaultOraclePath));
            var storageBackend     = settings.GetString("storage.backend", "file");

            logger.Message("Storage backend: " + storageBackend);

            var storageFix = settings.GetBool("storage.fix", false);

            // TODO remove this later
            if (storageFix)
            {
                if (Directory.Exists(storagePath))
                {
                    logger.Warning("Storage fix enabled... Cleaning up all storage...");
                    var di = new DirectoryInfo(storagePath);
                    foreach (FileInfo file in di.EnumerateFiles())
                    {
                        file.Delete();
                    }
                }
            }

            logger.Message("Storage path: " + storagePath);
            logger.Message("Oracle path: " + oraclePath);

            switch (storageBackend)
            {
            case "file":
                nexus = new Nexus(logger,
                                  (name) => new BasicDiskStore(storagePath + name + ".csv"),
                                  (n) => new SpookOracle(this, n, oraclePath)
                                  );
                break;

            case "db":
                nexus = new Nexus(logger,
                                  (name) => new DBPartition(storagePath + name),
                                  (n) => new SpookOracle(this, n, oraclePath)
                                  );
                break;

            default:
                throw new Exception("Backend has to be set to either \"db\" or \"file\"");
            }


            running = true;

            // mempool setup
            int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime);

            int minimumFee;

            try
            {
                minimumFee = settings.GetInt("mempool.fee", 100000);
                if (minimumFee < 1)
                {
                    logger.Error("Invalid mempool fee value. Expected a positive value.");
                }
            }
            catch (Exception e)
            {
                logger.Error("Invalid mempool fee value. Expected something in fixed point format.");
                return;
            }

            int minimumPow;

            try
            {
                minimumPow = settings.GetInt("mempool.pow", 0);
                int maxPow = 5;
                if (minimumPow < 0 || minimumPow > maxPow)
                {
                    logger.Error($"Invalid mempool pow value. Expected a value between 0 and {maxPow}.");
                }
            }
            catch (Exception e)
            {
                logger.Error("Invalid mempool fee value. Expected something in fixed point format.");
                return;
            }

            if (apiProxyURL != null)
            {
                hasMempool  = false;
                isValidator = false;
                hasSync     = false;
                hasEvents   = false;
                hasRelay    = false;
                hasArchive  = false;

                if (!hasRPC && !hasREST)
                {
                    logger.Error("API proxy must have REST or RPC enabled.");
                    return;
                }
            }

            if (hasMempool)
            {
                this.mempool = new Mempool(nexus, blockTime, minimumFee, System.Text.Encoding.UTF8.GetBytes(Identifier), 0, logger, profilePath);

                var mempoolLogging = settings.GetBool("mempool.log", true);
                if (mempoolLogging)
                {
                    mempool.OnTransactionFailed    += Mempool_OnTransactionFailed;
                    mempool.OnTransactionAdded     += (hash) => logger.Message($"Received transaction {hash}");
                    mempool.OnTransactionCommitted += (hash) => logger.Message($"Commited transaction {hash}");
                    mempool.OnTransactionDiscarded += (hash) => logger.Message($"Discarded transaction {hash}");
                }

                mempool.Start(ThreadPriority.AboveNormal);
            }
            else
            {
                this.mempool = null;
            }

            if (!isValidator && !hasSync && apiProxyURL == null)
            {
                logger.Warning("Non-validator nodes require sync feature to be enabled, auto enabled now");
                hasSync = true;
            }

            PeerCaps caps = PeerCaps.None;

            if (hasSync)
            {
                caps |= PeerCaps.Sync;
            }
            if (hasMempool)
            {
                caps |= PeerCaps.Mempool;
            }
            if (hasEvents)
            {
                caps |= PeerCaps.Events;
            }
            if (hasRelay)
            {
                caps |= PeerCaps.Relay;
            }
            if (hasArchive)
            {
                caps |= PeerCaps.Archive;
            }
            if (hasRPC)
            {
                caps |= PeerCaps.RPC;
            }
            if (hasREST)
            {
                caps |= PeerCaps.REST;
            }

            var possibleCaps = Enum.GetValues(typeof(PeerCaps)).Cast <PeerCaps>().ToArray();

            foreach (var cap in possibleCaps)
            {
                if (cap != PeerCaps.None && caps.HasFlag(cap))
                {
                    logger.Message("Feature enabled: " + cap);
                }
            }

            PhantasmaKeys node_keys = null;
            bool          bootstrap = false;

            if (hasSync)
            {
                string wif = settings.GetString("node.wif");
                node_keys         = PhantasmaKeys.FromWIF(wif);
                WalletModule.Keys = PhantasmaKeys.FromWIF(wif);

                try
                {
                    if (this.mempool != null)
                    {
                        this.mempool.SetKeys(node_keys);
                    }
                    this.node = new Node("Spook v" + SpookVersion, nexus, mempool, node_keys, port, caps, seeds, logger);
                }
                catch (Exception e)
                {
                    logger.Error(e.Message);
                    return;
                }

                if (!nexus.HasGenesis)
                {
                    if (isValidator)
                    {
                        if (settings.GetBool("nexus.bootstrap"))
                        {
                            if (!ValidationUtils.IsValidIdentifier(nexusName))
                            {
                                logger.Error("Invalid nexus name: " + nexusName);
                                this.Terminate();
                                return;
                            }

                            logger.Debug($"Boostraping {nexusName} nexus using {node_keys.Address}...");

                            var genesisTimestamp = new Timestamp(settings.GetUInt("genesis.timestamp", Timestamp.Now.Value));

                            bootstrap = true;
                            if (!nexus.CreateGenesisBlock(nexusName, node_keys, genesisTimestamp))
                            {
                                throw new ChainException("Genesis block failure");
                            }

                            logger.Debug("Genesis block created: " + nexus.GetGenesisHash(nexus.RootStorage));
                        }
                        else
                        {
                            logger.Error("No Nexus found.");
                            this.Terminate();
                        }
                    }
                }
                else
                {
                    var genesisAddress = nexus.GetGenesisAddress(nexus.RootStorage);
                    if (isValidator && node_keys.Address != genesisAddress)
                    {
                        logger.Error("Specified node key does not match genesis address " + genesisAddress.Text);
                        return;
                    }
                    else
                    {
                        logger.Success("Loaded Nexus with genesis " + nexus.GetGenesisHash(nexus.RootStorage));
                        //seeds.Add("127.0.0.1:7073");
                    }
                }
            }
            else
            {
                this.node = null;
            }

            if (mempool != null)
            {
                if (isValidator)
                {
                    this.mempool.SetKeys(node_keys);
                }
                else
                {
                    this.mempool.SubmissionCallback = (tx, chain) =>
                    {
                        logger.Message($"Relaying tx {tx.Hash} to other node");
                        //this.node.
                    };
                }
            }

            var useAPICache = settings.GetBool("api.cache", true);

            if (apiProxyURL != null)
            {
                useAPICache = true;
            }

            logger.Message($"API cache is {(useAPICache ? "enabled" : "disabled")}.");
            nexusApi         = new NexusAPI(nexus, useAPICache, apiLog ? logger : null);
            nexusApi.Mempool = mempool;

            if (!string.IsNullOrEmpty(apiProxyURL))
            {
                nexusApi.ProxyURL = apiProxyURL;
                logger.Message($"API will be acting as proxy for {apiProxyURL}");
            }
            else
            {
                nexusApi.Node = node;
            }

            var readOnlyMode = settings.GetBool("readonly", false);

            if (apiProxyURL != null)
            {
                readOnlyMode = true;
            }

            if (readOnlyMode)
            {
                logger.Warning($"Node will be running in read-only mode.");
                nexusApi.acceptTransactions = false;
            }

            // RPC setup
            if (hasRPC)
            {
                rpcPort = settings.GetInt("rpc.port", 7077);
                logger.Message($"RPC server listening on port {rpcPort}...");
                var rpcServer = new RPCServer(nexusApi, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text));
                rpcServer.Start(ThreadPriority.AboveNormal);
            }
            else
            {
                rpcPort = 0;
            }

            // REST setup
            if (hasREST)
            {
                restPort = settings.GetInt("rest.port", 7078);
                logger.Message($"REST server listening on port {restPort}...");
                var restServer = new RESTServer(nexusApi, "/api", restPort, (level, text) => WebLogMapper("rest", level, text));
                restServer.Start(ThreadPriority.AboveNormal);
            }
            else
            {
                restPort = 0;
            }

            if (node != null)
            {
                var neoScanURL = settings.GetString("neoscan.url", "https://api.neoscan.io");

                var rpcList    = settings.GetString("neo.rpc", "http://seed6.ngd.network:10332,http://seed.neoeconomy.io:10332");
                var neoRpcURLs = rpcList.Split(',');
                this.neoAPI = new Neo.Core.RemoteRPCNode(neoScanURL, neoRpcURLs);
                this.neoAPI.SetLogger((s) => logger.Message(s));

                this.neoScanAPI = new NeoScanAPI(neoScanURL, logger, nexus, node_keys);

                cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", "");
                if (!string.IsNullOrEmpty(cryptoCompareAPIKey))
                {
                    logger.Message($"CryptoCompare API enabled...");
                }

                node.Start();
            }

            if (gui != null)
            {
                int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds

                if (settings.GetBool("plugin.tps", false))
                {
                    RegisterPlugin(new TPSPlugin(logger, pluginPeriod));
                }

                if (settings.GetBool("plugin.ram", false))
                {
                    RegisterPlugin(new RAMPlugin(logger, pluginPeriod));
                }

                if (settings.GetBool("plugin.mempool", false))
                {
                    RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod));
                }
            }

            Console.CancelKeyPress += delegate
            {
                Terminate();
            };

            useSimulator = settings.GetBool("simulator.enabled", false);

            var dispatcher = new CommandDispatcher();

            SetupCommands(dispatcher);

            if (settings.GetBool("swaps.enabled"))
            {
                var tokenSwapper = new TokenSwapper(node_keys, nexusApi, neoScanAPI, neoAPI, minimumFee, logger, settings);
                nexusApi.TokenSwapper = tokenSwapper;

                new Thread(() =>
                {
                    logger.Message("Running token swapping service...");
                    while (running)
                    {
                        Thread.Sleep(5000);

                        if (nodeReady)
                        {
                            tokenSwapper.Update();
                        }
                    }
                }).Start();
            }

            if (useSimulator && bootstrap)
            {
                new Thread(() =>
                {
                    logger.Message("Initializing simulator...");
                    simulator            = new NexusSimulator(this.nexus, node_keys, 1234);
                    simulator.MinimumFee = minimumFee;

                    /*
                     * logger.Message("Bootstrapping validators");
                     * simulator.BeginBlock();
                     * for (int i = 1; i < validatorWIFs.Length; i++)
                     * {
                     *  simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, DomainSettings.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, DomainSettings.StakingTokenDecimals));
                     * }
                     * simulator.EndBlock();*/

                    string[] dapps = settings.GetString("dapps", "").Split(',');

                    DappServer.InitDapps(nexus, simulator, node_keys, dapps, minimumFee, logger);

                    bool genBlocks = settings.GetBool("simulator.blocks", false);
                    if (genBlocks)
                    {
                        int blockNumber = 0;
                        while (running)
                        {
                            Thread.Sleep(5000);
                            blockNumber++;
                            logger.Message("Generating sim block #" + blockNumber);
                            try
                            {
                                simulator.CurrentTime = DateTime.UtcNow;
                                simulator.GenerateRandomBlock();
                            }
                            catch (Exception e)
                            {
                                logger.Error("Fatal error: " + e.ToString());
                                Environment.Exit(-1);
                            }
                        }
                    }

                    MakeReady(dispatcher);
                }).Start();
            }
            else
            {
                MakeReady(dispatcher);
            }

            this.Run();
        }
Ejemplo n.º 29
0
        public CLI(string[] args)
        {
            var seeds = new List <string>();

            var settings = new Arguments(args);

            var useGUI = settings.GetBool("gui.enabled", true);

            if (useGUI)
            {
                gui    = new ConsoleGUI();
                logger = gui;
            }
            else
            {
                gui    = null;
                logger = new ConsoleLogger();
            }

            string mode = settings.GetString("node.mode", "validator");

            bool hasRPC  = settings.GetBool("rpc.enabled", false);
            bool hasREST = settings.GetBool("rest.enabled", false);

            string wif = settings.GetString("node.wif");

            var nexusName      = settings.GetString("nexus.name", "simnet");
            var genesisAddress = Address.FromText(settings.GetString("nexus.genesis", KeyPair.FromWIF(validatorWIFs[0]).Address.Text));

            switch (mode)
            {
            case "sender":
                string host               = settings.GetString("sender.host");
                int    threadCount        = settings.GetInt("sender.threads", 8);
                int    addressesPerSender = settings.GetInt("sender.addressCount", 100);
                RunSender(wif, host, threadCount, addressesPerSender);
                Console.WriteLine("Sender finished operations.");
                return;

            case "validator": break;

            default:
            {
                logger.Error("Unknown mode: " + mode);
                return;
            }
            }

            int defaultPort = 0;

            for (int i = 0; i < validatorWIFs.Length; i++)
            {
                if (validatorWIFs[i] == wif)
                {
                    defaultPort = (7073 + i);
                }
            }

            if (defaultPort == 0)
            {
                defaultPort = (7073 + validatorWIFs.Length);
            }

            int port = settings.GetInt("node.port", defaultPort);

            var node_keys = KeyPair.FromWIF(wif);

            // TODO increase this later
            int cacheSize = 32;

            nexus = new Nexus(logger);
            if (wif != validatorWIFs[0])
            {
                seeds.Add("127.0.0.1:7073");
            }

            // TODO this should be later optional to enable
            nexus.AddPlugin(new ChainAddressesPlugin());
            nexus.AddPlugin(new TokenTransactionsPlugin());
            nexus.AddPlugin(new AddressTransactionsPlugin());
            nexus.AddPlugin(new UnclaimedTransactionsPlugin());

            /*if (simulator != null)
             * {
             *  for (int i = 0; i < 100; i++)
             *  {
             *      simulator.GenerateRandomBlock();
             *  }
             * }*/

            running = true;

            // mempool setup
            int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime);

            this.mempool = new Mempool(node_keys, nexus, blockTime);
            mempool.Start(ThreadPriority.AboveNormal);

            mempool.OnTransactionFailed += Mempool_OnTransactionFailed;

            api = new NexusAPI(nexus, mempool);

            // RPC setup
            if (hasRPC)
            {
                int rpcPort = settings.GetInt("rpc.port", 7077);

                logger.Message($"RPC server listening on port {rpcPort}...");
                var rpcServer = new RPCServer(api, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text));
                rpcServer.Start(ThreadPriority.AboveNormal);
            }

            // REST setup
            if (hasREST)
            {
                int restPort = settings.GetInt("rest.port", 7078);

                logger.Message($"REST server listening on port {restPort}...");
                var restServer = new RESTServer(api, "/api", restPort, (level, text) => WebLogMapper("rest", level, text));
                restServer.Start(ThreadPriority.AboveNormal);
            }

            /*if (simulator != null && settings.GetBool("simulator", false))
             * {
             *  new Thread(() =>
             *  {
             *      Thread.CurrentThread.IsBackground = true;
             *      while (running)
             *      {
             *          Thread.Sleep(Mempool.MinimumBlockTime + 1000);
             *          simulator.CurrentTime = Timestamp.Now;
             *          simulator.GenerateRandomBlock(mempool);
             *      }
             *  }).Start();
             * }*/

            // node setup
            this.node = new Node(nexus, mempool, node_keys, port, seeds, logger);
            node.Start();

            int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds

            RegisterPlugin(new TPSPlugin(logger, pluginPeriod));
            RegisterPlugin(new RAMPlugin(logger, pluginPeriod));
            RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod));

            Console.CancelKeyPress += delegate {
                Terminate();
            };

            logger.Success("Node is ready");

            var dispatcher = new CommandDispatcher();

            SetupCommands(dispatcher);

            if (gui != null)
            {
                gui.MakeReady(dispatcher);
            }

            this.Run();
        }
Ejemplo n.º 30
0
        public IEnumerable <Block> EndBlock(Mempool mempool = null)
        {
            if (!blockOpen)
            {
                throw new Exception("Simulator block not open");
            }

            usedAddresses.Clear();

            blockOpen = false;

            var blocks   = new List <Block>();
            var protocol = (uint)Nexus.GetGovernanceValue(Nexus.RootStorage, Nexus.NexusProtocolVersionTag);

            if (txChainMap.Count > 0)
            {
                var chains = txChainMap.Values.Distinct();

                foreach (var chain in chains)
                {
                    var hashes = txChainMap.Where((p) => p.Value == chain).Select(x => x.Key);
                    if (hashes.Any())
                    {
                        var txs = new List <Transaction>();
                        foreach (var hash in hashes)
                        {
                            txs.Add(txHashMap[hash]);
                        }

                        var        lastBlockHash = chain.GetLastBlockHash();
                        var        lastBlock     = chain.GetBlockByHash(lastBlockHash);
                        BigInteger nextHeight    = lastBlock != null ? lastBlock.Height + 1 : Chain.InitialHeight;
                        var        prevHash      = lastBlock != null ? lastBlock.Hash : Hash.Null;

                        var block = new Block(nextHeight, chain.Address, CurrentTime, hashes, prevHash, protocol);

                        bool submitted;

                        string reason = "unknown";

                        if (mempool != null)
                        {
                            submitted = true;
                            foreach (var tx in txs)
                            {
                                try
                                {
                                    mempool.Submit(tx);
                                }
                                catch (Exception e)
                                {
                                    reason    = e.Message;
                                    submitted = false;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            try
                            {
                                chain.BakeBlock(ref block, ref txs, MinimumFee, blockValidator, CurrentTime);
                                chain.AddBlock(block, txs, MinimumFee);
                                submitted = true;
                            }
                            catch (Exception e)
                            {
                                reason    = e.Message;
                                submitted = false;
                            }
                        }

                        if (submitted)
                        {
                            blocks.Add(block);

                            CurrentTime += blockTimeSkip;

                            // add the finished block hash to each pending side chain tx
                            if (_pendingEntries.Count > 0)
                            {
                                foreach (var entry in _pendingEntries.Values)
                                {
                                    if (entry.sourceChain != chain)
                                    {
                                        continue;
                                    }

                                    var pendingBlock = new SideChainPendingBlock()
                                    {
                                        sourceChain = entry.sourceChain,
                                        destChain   = entry.destChain,
                                        hash        = block.Hash,
                                        tokenSymbol = entry.tokenSymbol
                                    };

                                    _pendingBlocks.Add(pendingBlock);
                                    Logger.Debug($"...Sending {entry.sourceChain.Name}=>{entry.destChain.Name}: {block.Hash}");
                                }
                            }

                            Logger.Message($"End block #{step} @ {chain.Name} chain: {block.Hash}");
                        }
                        else
                        {
                            throw new ChainException($"add block @ {chain.Name} failed, reason: {reason}");
                        }
                    }
                }

                _pendingEntries.Clear();
                return(blocks);
            }

            return(Enumerable.Empty <Block>());
        }