Exemplo n.º 1
0
        /*private void ExecuteQuery(MySqlConnection connection, string query)
         * {
         *
         * }*/

        private void Execute()
        {
            var logger = new ConsoleLogger(LogLevel.Maximum);

            var path = @"Storage/";

            this.nexus = new Nexus("mainnet", logger,
                                   (name) => new DBPartition(logger, path + name));

            if (!nexus.HasGenesis)
            {
                throw new Exception("Genesis block not found, check storage path");
            }

            this.nexus.SetOracleReader(new DummyOracle(this.nexus));

            var chains = nexus.GetChains(nexus.RootStorage).Select(x => nexus.GetChainByName(x)).ToArray();
            var tokens = nexus.GetTokens(nexus.RootStorage).Select(x => nexus.GetTokenInfo(nexus.RootStorage, x)).ToArray();

            foreach (var chain in chains)
            {
                foreach (var token in tokens)
                {
                    DumpBalances(chain, token);
                }

                DumpBlocks(chain);
            }
        }
Exemplo n.º 2
0
        protected override bool Run()
        {
            Thread.Sleep(1000);

            if (this.Capabilities.HasFlag(PeerCaps.Sync))
            {
                if (!listening)
                {
                    listening = true;
                    var accept = listener.BeginAcceptSocket(new AsyncCallback(DoAcceptSocketCallback), listener);
                }

                var now  = DateTime.UtcNow;
                var diff = now - _lastPeerConnect;
                if (diff.TotalSeconds >= 1)
                {
                    ConnectToPeers();
                    _lastPeerConnect = now;
                }
            }

            // check if we have any cached blocks TODO: needs to be revisited when we have multiple chains
            lock (_pendingBlocks)
            {
                if (_pendingBlocks.Count > 0)
                {
                    var chains = Nexus.GetChains(Nexus.RootStorage).Select(x => Nexus.GetChainByName(x));

                    foreach (var chain in chains)
                    {
                        HandlePendingBlocks(chain);
                    }
                }
                else
                {
                    UpdateRequests();
                }
            }

            return(true);
        }
Exemplo n.º 3
0
        /*private void ExecuteQuery(MySqlConnection connection, string query)
         * {
         *
         * }*/

        private void Execute()
        {
            var logger = new ConsoleLogger(LogLevel.Maximum);

            var path = @"C:\Code\Spook\Spook\bin\Debug\netcoreapp3.1\Storage\";

            this.nexus = new Nexus("mainnet", logger,
                                   (name) => new DBPartition(logger, path + name));

            var chains = nexus.GetChains(nexus.RootStorage).Select(x => nexus.GetChainByName(x)).ToArray();
            var tokens = nexus.GetTokens(nexus.RootStorage).Select(x => nexus.GetTokenInfo(nexus.RootStorage, x)).ToArray();

            foreach (var chain in chains)
            {
                foreach (var token in tokens)
                {
                    DumpBalances(chain, token);
                }

                DumpBlocks(chain);
            }
        }
Exemplo n.º 4
0
 public string[] GetChains()
 {
     return(Nexus.GetChains(this.RootStorage));
 }
Exemplo n.º 5
0
        private Message HandleMessage(Peer peer, Message msg)
        {
            if (msg.IsSigned && !msg.Address.IsNull)
            {
                if (msg.Address.IsUser)
                {
                    peer.SetAddress(msg.Address);
                }
                else
                {
                    return(new ErrorMessage(Address, this.PublicEndpoint, P2PError.InvalidAddress));
                }
            }
            else
            {
                return(new ErrorMessage(Address, this.PublicEndpoint, P2PError.MessageShouldBeSigned));
            }

            Endpoint endpoint;

            try
            {
                endpoint = Endpoint.FromString(msg.Host);
            }
            catch (ChainException e)
            {
                return(new ErrorMessage(Address, this.PublicEndpoint, P2PError.InvalidEndpoint));
            }

            var peerKey = endpoint.ToString();

            lock (_peers)
            {
                if (!_peers.ContainsKey(peerKey))
                {
                    Logger.Message("Added peer: " + peerKey);
                    peer.UpdateEndpoint(endpoint);
                    _peers[peerKey] = peer;
                }
            }

            Logger.Debug($"Got {msg.Opcode} message from {peerKey}");

            switch (msg.Opcode)
            {
            case Opcode.EVENT:
            {
                var evtMessage = (EventMessage)msg;
                var evt        = evtMessage.Event;
                Logger.Message("New event: " + evt.ToString());
                return(null);
            }

            case Opcode.REQUEST:
            {
                var request = (RequestMessage)msg;

                if (request.NexusName != Nexus.Name)
                {
                    return(new ErrorMessage(Address, this.PublicEndpoint, P2PError.InvalidNexus));
                }

                if (request.Kind == RequestKind.None)
                {
                    return(null);
                }

                var answer = new ListMessage(this.Address, this.PublicEndpoint, request.Kind);

                if (request.Kind.HasFlag(RequestKind.Peers))
                {
                    answer.SetPeers(this.Peers.Where(x => x != peer).Select(x => x.Endpoint.ToString()));
                }

                if (request.Kind.HasFlag(RequestKind.Chains))
                {
                    var chainList = Nexus.GetChains(Nexus.RootStorage);
                    var chains    = chainList.Select(x => Nexus.GetChainByName(x)).Select(x => new ChainInfo(x.Name, Nexus.GetParentChainByName(x.Name), x.Height)).ToArray();
                    answer.SetChains(chains);
                }

                if (request.Kind.HasFlag(RequestKind.Mempool) && Capabilities.HasFlag(PeerCaps.Mempool))
                {
                    var txs = _mempool.GetTransactions().Select(x => Base16.Encode(x.ToByteArray(true)));
                    answer.SetMempool(txs);
                }

                if (request.Kind.HasFlag(RequestKind.Blocks))
                {
                    foreach (var entry in request.Blocks)
                    {
                        var chain = this.Nexus.GetChainByName(entry.Key);
                        if (chain == null)
                        {
                            continue;
                        }

                        answer.AddBlockRange(chain, entry.Value);
                    }
                }

                return(answer);
            }

            case Opcode.LIST:
            {
                var listMsg = (ListMessage)msg;

                var outKind = RequestKind.None;

                if (listMsg.Kind.HasFlag(RequestKind.Peers))
                {
                    IEnumerable <string> newPeers;

                    lock (_peers)
                    {
                        newPeers = listMsg.Peers.Where(x => !_peers.ContainsKey(x));
                    }

                    foreach (var entry in newPeers)
                    {
                        Logger.Message("New peer: " + entry);
                    }
                    QueueEndpoints(newPeers);
                }

                var blockFetches = new Dictionary <string, RequestRange>();
                if (listMsg.Kind.HasFlag(RequestKind.Chains))
                {
                    foreach (var entry in listMsg.Chains)
                    {
                        var chain = Nexus.GetChainByName(entry.name);
                        // NOTE if we dont find this chain then it is too soon for ask for blocks from that chain
                        if (chain != null)
                        {
                            if (chain.Height < entry.height)
                            {
                                var start = chain.Height + 1;
                                var end   = entry.height;
                                var limit = start + ListMessage.MaxBlocks - 1;

                                if (end > limit)
                                {
                                    end = limit;
                                }

                                blockFetches[entry.name] = new RequestRange(start, end);

                                lock (_knownHeights)
                                {
                                    BigInteger lastKnowHeight = _knownHeights.ContainsKey(chain.Name) ? _knownHeights[chain.Name] : 0;
                                    if (entry.height > lastKnowHeight)
                                    {
                                        _knownHeights[chain.Name] = entry.height;
                                        IsFullySynced             = false;
                                    }
                                }
                            }

                            if (chain.Height == entry.height)
                            {
                                IsFullySynced = true;
                            }
                        }
                    }
                }

                if (listMsg.Kind.HasFlag(RequestKind.Mempool) && Capabilities.HasFlag(PeerCaps.Mempool))
                {
                    int submittedCount = 0;
                    foreach (var txStr in listMsg.Mempool)
                    {
                        var bytes = Base16.Decode(txStr);
                        var tx    = Transaction.Unserialize(bytes);
                        try
                        {
                            _mempool.Submit(tx);
                            submittedCount++;
                        }
                        catch
                        {
                        }

                        Logger.Message(submittedCount + " new transactions");
                    }
                }

                if (listMsg.Kind.HasFlag(RequestKind.Blocks))
                {
                    Chain chain = null;
                    foreach (var entry in listMsg.Blocks)
                    {
                        chain = Nexus.GetChainByName(entry.Key);
                        if (chain == null)
                        {
                            continue;
                        }

                        var blockRange = entry.Value;
                        foreach (var block in blockRange.blocks)
                        {
                            var transactions = new List <Transaction>();
                            foreach (var txHash in block.TransactionHashes)
                            {
                                var tx = entry.Value.transactions[txHash];
                                transactions.Add(tx);
                            }

                            var maxPendingHeightExpected = chain.Height + ListMessage.MaxBlocks;

                            if (block.Height > chain.Height && block.Height <= maxPendingHeightExpected)
                            {
                                var key = $"{chain.Name}.{block.Height}";
                                lock (_pendingBlocks)
                                {
                                    _pendingBlocks[key] = new PendingBlock(chain.Name, block, transactions);
                                }
                            }
                        }

                        _lastRequestTime = DateTime.UtcNow;
                        //Thread.Sleep(10000);
                    }
                }

                if (blockFetches.Count > 0)
                {
                    outKind |= RequestKind.Blocks;
                }

                if (outKind != RequestKind.None)
                {
                    var answer = new RequestMessage(this.Address, this.PublicEndpoint, outKind, Nexus.Name);

                    if (blockFetches.Count > 0)
                    {
                        answer.SetBlocks(blockFetches);
                    }

                    return(answer);
                }

                return(null);
            }

            case Opcode.MEMPOOL_Add:
            {
                if (Capabilities.HasFlag(PeerCaps.Mempool))
                {
                    var memtx           = (MempoolAddMessage)msg;
                    int submissionCount = 0;
                    foreach (var tx in memtx.Transactions)
                    {
                        try
                        {
                            if (_mempool.Submit(tx))
                            {
                                submissionCount++;
                            }
                        }
                        catch
                        {
                            // ignore
                        }
                    }

                    Logger.Message($"Added {submissionCount} txs to the mempool");
                }

                return(null);
            }

            case Opcode.BLOCKS_List:
            {
                break;
            }

            case Opcode.ERROR:
            {
                var errorMsg = (ErrorMessage)msg;
                if (string.IsNullOrEmpty(errorMsg.Text))
                {
                    Logger.Error($"ERROR: {errorMsg.Code}");
                }
                else
                {
                    Logger.Error($"ERROR: {errorMsg.Code} ({errorMsg.Text})");
                }

                return(null);
            }
            }

            throw new NodeException("No answer sent to request " + msg.Opcode);
        }