Beispiel #1
0
        private void OnGetBlocksMessageReceived(GetBlocksPayload payload)
        {
            if (!localNode.ServiceEnabled)
            {
                return;
            }
            if (Blockchain.Default == null)
            {
                return;
            }
            UInt256 hash = payload.HashStart.Select(p => Blockchain.Default.GetHeader(p)).Where(p => p != null).OrderBy(p => p.Index).Select(p => p.Hash).FirstOrDefault();

            if (hash == null || hash == payload.HashStop)
            {
                return;
            }
            List <UInt256> hashes = new List <UInt256>();

            do
            {
                hash = Blockchain.Default.GetNextBlockHash(hash);
                if (hash == null)
                {
                    break;
                }
                hashes.Add(hash);
            } while (hash != payload.HashStop && hashes.Count < 500);
            EnqueueMessage("inv", InvPayload.Create(InventoryType.Block, hashes.ToArray()));
        }
Beispiel #2
0
        private void OnGetHeadersMessageReceived(GetBlocksPayload payload)
        {
            if (!localNode.ServiceEnabled)
            {
                return;
            }
            if (Blockchain.Default == null)
            {
                return;
            }
            UInt256 hash = payload.HashStart.Select(p => Blockchain.Default.GetHeader(p)).Where(p => p != null).OrderBy(p => p.Index).Select(p => p.Hash).FirstOrDefault();

            if (hash == null || hash == payload.HashStop)
            {
                return;
            }
            List <Header> headers = new List <Header>();

            do
            {
                hash = Blockchain.Default.GetNextBlockHash(hash);
                if (hash == null)
                {
                    break;
                }
                headers.Add(Blockchain.Default.GetHeader(hash));
            } while (hash != payload.HashStop && headers.Count < 2000);
            EnqueueMessage("headers", HeadersPayload.Create(headers));
        }
Beispiel #3
0
        private void OnGetBlocksMessageReceived(GetBlocksPayload payload)
        {
            UInt256      hash  = payload.HashStart;
            int          count = payload.Count < 0 ? InvPayload.MaxHashesCount : payload.Count;
            TrimmedBlock state = Blockchain.Singleton.Store.GetBlocks().TryGet(hash);

            if (state == null)
            {
                return;
            }
            List <UInt256> hashes = new List <UInt256>();

            for (uint i = 1; i <= count; i++)
            {
                uint index = state.Index + i;
                if (index > Blockchain.Singleton.Height)
                {
                    break;
                }
                hash = Blockchain.Singleton.GetBlockHash(index);
                if (hash == null)
                {
                    break;
                }
                hashes.Add(hash);
            }
            if (hashes.Count == 0)
            {
                return;
            }
            Context.Parent.Tell(Message.Create(MessageCommand.Inv, InvPayload.Create(InventoryType.Block, hashes.ToArray())));
        }
Beispiel #4
0
        private void OnGetHeadersMessageReceived(GetBlocksPayload payload)
        {
            UInt256 hash  = payload.HashStart;
            int     count = payload.Count < 0 ? HeadersPayload.MaxHeadersCount : payload.Count;
            DataCache <UInt256, TrimmedBlock> cache = Blockchain.Singleton.Store.GetBlocks();
            TrimmedBlock state = cache.TryGet(hash);

            if (state == null)
            {
                return;
            }
            List <Header> headers = new List <Header>();

            for (uint i = 1; i <= count; i++)
            {
                uint index = state.Index + i;
                hash = Blockchain.Singleton.GetBlockHash(index);
                if (hash == null)
                {
                    break;
                }
                Header header = cache.TryGet(hash)?.Header;
                if (header == null)
                {
                    break;
                }
                headers.Add(header);
            }
            if (headers.Count == 0)
            {
                return;
            }
            Context.Parent.Tell(Message.Create(MessageCommand.Headers, HeadersPayload.Create(headers)));
        }
Beispiel #5
0
        private bool OnBroadcastCommand(string[] args)
        {
            string        command = args[1].ToLower();
            ISerializable payload = null;

            switch (command)
            {
            case "addr":
                payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[2]), ushort.Parse(args[3])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp()));
                break;

            case "block":
                if (args[2].Length == 64 || args[2].Length == 66)
                {
                    payload = Blockchain.Default.GetBlock(UInt256.Parse(args[2]));
                }
                else
                {
                    payload = Blockchain.Default.GetBlock(uint.Parse(args[2]));
                }
                break;

            case "getblocks":
            case "getheaders":
                payload = GetBlocksPayload.Create(UInt256.Parse(args[2]));
                break;

            case "getdata":
            case "inv":
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(p => UInt256.Parse(p)).ToArray());
                break;

            case "tx":
                payload = LocalNode.GetTransaction(UInt256.Parse(args[2]));
                if (payload == null)
                {
                    payload = Blockchain.Default.GetTransaction(UInt256.Parse(args[2]));
                }
                break;

            case "alert":
            case "consensus":
            case "filteradd":
            case "filterload":
            case "headers":
            case "merkleblock":
            case "ping":
            case "pong":
            case "reject":
            case "verack":
            case "version":
                Console.WriteLine($"Command \"{command}\" is not supported.");
                return(true);
            }
            foreach (RemoteNode node in LocalNode.GetRemoteNodes())
            {
                node.EnqueueMessage(command, payload);
            }
            return(true);
        }
Beispiel #6
0
        private bool CheckPrevHash(Node node, Block block)
        {
            // If we don't already have its previous block, shunt it off to holding area until we get it
            if (!this.chainIndex.InAnyTip(block.Header.HashPrevBlock))
            {
                var blockHash = block.GetHash();

                //LogPrintf("ProcessBlock: ORPHAN BLOCK %lu, prev=%s\n", (unsigned long)mapOrphanBlocks.size(), pblock->hashPrevBlock.ToString());

                // Accept orphans as long as there is a node to request its parents from
                if (node != null)
                {
                    // ppcoin: check proof-of-stake
                    if (block.IsProofOfStake())
                    {
                        // Limited duplicity on stake: prevents block flood attack
                        // Duplicate stake allowed only when there is orphan child block
                        //if (setStakeSeenOrphan.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash))
                        //	return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for orphan block %s",
                        //		pblock->GetProofOfStake().first.ToString(), pblock->GetProofOfStake().second, hash.ToString());
                    }
                }
                var orphan = new OrphanBlock
                {
                    BlockHash    = blockHash,
                    PreviousHash = block.Header.HashPrevBlock,
                    Block        = block,
                };

                if (block.IsProofOfStake())
                {
                    orphan.Stake = block.GetProofOfStake();
                }

                if (this.orphanBlocks.TryAdd(blockHash, orphan))
                {
                    if (!this.Context.DownloadMode)
                    {
                        if (node != null)
                        {
                            // call get blocks
                            var message = new GetBlocksPayload()
                            {
                                BlockLocators = this.chainIndex.Tip.GetLocator(),
                                HashStop      = this.GetOrphanRoot(blockHash)
                            };
                            node.SendMessage(message);

                            // ppcoin: getblocks may not obtain the ancestor block rejected
                            // earlier by duplicate-stake check so we ask for it again directly
                            //node.SendMessage(new InvPayload(InventoryType.MSG_BLOCK, block.Header.HashPrevBlock));
                        }
                    }
                }
                return(false);
            }

            return(true);
        }
Beispiel #7
0
 public static byte[] EncodeGetBlocksPayload(GetBlocksPayload getBlocksPayload)
 {
     using (var stream = new MemoryStream())
     {
         EncodeGetBlocksPayload(stream, getBlocksPayload);
         return(stream.ToArray());
     }
 }
Beispiel #8
0
        private void RespondToGetBlocksPayload(Node node, GetBlocksPayload getBlocksPayload)
        {
            // ideally this would go on in a queue running in its own thread
            // and serves getblock requests this can also be throttled
            // if our node is too busy we just send a reject message

            // push the GetBlocksPayload to the hug for processing
        }
Beispiel #9
0
 private void RequestTasks(TaskSession session)
 {
     if (session.HasTask)
     {
         return;
     }
     if (session.AvailableTasks.Count > 0)
     {
         session.AvailableTasks.Remove(knownHashes);
         session.AvailableTasks.RemoveWhere(p => Blockchain.Singleton.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         if (hashes.Count > 0)
         {
             foreach (UInt256 hash in hashes.ToArray())
             {
                 if (!IncrementGlobalTask(hash))
                 {
                     hashes.Remove(hash);
                 }
             }
             session.AvailableTasks.Remove(hashes);
             foreach (UInt256 hash in hashes)
             {
                 session.Tasks[hash] = DateTime.UtcNow;
             }
             foreach (InvPayload group in InvPayload.CreateGroup(InventoryType.Block, hashes.ToArray()))
             {
                 session.RemoteNode.Tell(Message.Create("getdata", group));
             }
             return;
         }
     }
     if ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.LastBlockIndex)
     {
         session.Tasks[HeaderTaskHash] = DateTime.UtcNow;
         IncrementGlobalTask(HeaderTaskHash);
         session.RemoteNode.Tell(Message.Create("getheaders", GetBlocksPayload.Create(Blockchain.Singleton.CurrentHeaderHash)));
     }
     else if (Blockchain.Singleton.Height < session.LastBlockIndex)
     {
         UInt256 hash = Blockchain.Singleton.CurrentBlockHash;
         for (uint i = Blockchain.Singleton.Height + 1; i <= Blockchain.Singleton.HeaderHeight; i++)
         {
             hash = Blockchain.Singleton.GetBlockHash(i);
             if (!globalTasks.ContainsKey(hash))
             {
                 hash = Blockchain.Singleton.GetBlockHash(i - 1);
                 break;
             }
         }
         session.RemoteNode.Tell(Message.Create("getblocks", GetBlocksPayload.Create(hash)));
     }
     else if (Blockchain.Singleton.HeaderHeight >= session.LastBlockIndex &&
              TimeProvider.Current.UtcNow.ToTimestamp() - PingCoolingOffPeriod >= Blockchain.Singleton.GetBlock(Blockchain.Singleton.CurrentHeaderHash)?.Timestamp)
     {
         session.RemoteNode.Tell(Message.Create("ping", PingPayload.Create(Blockchain.Singleton.Height)));
     }
 }
Beispiel #10
0
        public void TryDeserialize_FailTest(FastStreamReader stream, string expErr)
        {
            GetBlocksPayload pl = new GetBlocksPayload();

            bool b = pl.TryDeserialize(stream, out string error);

            Assert.False(b);
            Assert.Equal(expErr, error);
        }
Beispiel #11
0
        private void HandleGetHeaders(GetBlocksPayload payload)
        {
            var handler = this.OnGetHeaders;

            if (handler != null)
            {
                handler(this, payload);
            }
        }
Beispiel #12
0
 public static void EncodeGetBlocksPayload(Stream stream, GetBlocksPayload getBlocksPayload)
 {
     using (var writer = new BinaryWriter(stream, Encoding.ASCII, leaveOpen: true))
     {
         writer.WriteUInt32(getBlocksPayload.Version);
         writer.WriteList(getBlocksPayload.BlockLocatorHashes, locatorHash => writer.WriteUInt256(locatorHash));
         writer.WriteUInt256(getBlocksPayload.HashStop);
     }
 }
Beispiel #13
0
        internal void RequestGetBlocks()
        {
            RemoteNode[] nodes = GetRemoteNodes();

            GetBlocksPayload payload = GetBlocksPayload.Create(Blockchain.Default.CurrentBlockHash);

            foreach (RemoteNode node in nodes)
            {
                node.EnqueueMessage("getblocks", payload);
            }
        }
Beispiel #14
0
 private void RequestTasks(TaskSession session)
 {
     if (session.HasTask)
     {
         return;
     }
     if (session.AvailableTasks.Count > 0)
     {
         session.AvailableTasks.ExceptWith(knownHashes);
         session.AvailableTasks.RemoveWhere(p => Blockchain.Singleton.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         if (hashes.Count > 0)
         {
             foreach (UInt256 hash in hashes.ToArray())
             {
                 if (!IncrementGlobalTask(hash))
                 {
                     hashes.Remove(hash);
                 }
             }
             session.AvailableTasks.ExceptWith(hashes);
             foreach (UInt256 hash in hashes)
             {
                 session.Tasks[hash] = DateTime.UtcNow;
             }
             foreach (InvPayload group in InvPayload.CreateGroup(InventoryType.Block, hashes.ToArray()))
             {
                 session.RemoteNode.Tell(Message.Create(MessageCommand.GetData, group));
             }
             return;
         }
     }
     if ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.StartHeight)
     {
         session.Tasks[HeaderTaskHash] = DateTime.UtcNow;
         IncrementGlobalTask(HeaderTaskHash);
         session.RemoteNode.Tell(Message.Create(MessageCommand.GetHeaders, GetBlocksPayload.Create(Blockchain.Singleton.CurrentHeaderHash)));
     }
     else if (Blockchain.Singleton.Height < session.StartHeight)
     {
         UInt256 hash = Blockchain.Singleton.CurrentBlockHash;
         for (uint i = Blockchain.Singleton.Height + 1; i <= Blockchain.Singleton.HeaderHeight; i++)
         {
             hash = Blockchain.Singleton.GetBlockHash(i);
             if (!globalTasks.ContainsKey(hash))
             {
                 hash = Blockchain.Singleton.GetBlockHash(i - 1);
                 break;
             }
         }
         session.RemoteNode.Tell(Message.Create(MessageCommand.GetBlocks, GetBlocksPayload.Create(hash)));
     }
 }
Beispiel #15
0
 private async Task OnHeadersMessageReceivedAsync(HeadersPayload payload)
 {
     if (Blockchain.Default == null)
     {
         return;
     }
     Blockchain.Default.AddHeaders(payload.Headers);
     if (Blockchain.Default.HeaderHeight < Version.StartHeight)
     {
         await SendMessageAsync("getheaders", GetBlocksPayload.Create(Blockchain.Default.GetLeafHeaderHashes()));
     }
 }
Beispiel #16
0
 private void OnHeadersMessageReceived(HeadersPayload payload)
 {
     if (Blockchain.Default == null)
     {
         return;
     }
     Blockchain.Default.AddHeaders(payload.Headers);
     if (Blockchain.Default.HeaderHeight < Version.StartHeight)
     {
         EnqueueMessage("getheaders", GetBlocksPayload.Create(Blockchain.Default.CurrentHeaderHash), true);
     }
 }
Beispiel #17
0
        private void OnGetHeaders(Peer peer, GetBlocksPayload payload)
        {
            if (this.Type == RulesEnum.ComparisonToolTestNet)
            {
                this.coreDaemon.WaitForUpdate();
            }

            var targetChainLocal = this.coreDaemon.TargetChain;

            if (targetChainLocal == null)
            {
                return;
            }

            ChainedHeader matchingChainedHeader = null;

            foreach (var blockHash in payload.BlockLocatorHashes)
            {
                ChainedHeader chainedHeader;
                if (this.coreStorage.TryGetChainedHeader(blockHash, out chainedHeader))
                {
                    if (chainedHeader.Height < targetChainLocal.Blocks.Count &&
                        chainedHeader.Hash == targetChainLocal.Blocks[chainedHeader.Height].Hash)
                    {
                        matchingChainedHeader = chainedHeader;
                        break;
                    }
                }
            }

            if (matchingChainedHeader == null)
            {
                matchingChainedHeader = this.rules.GenesisChainedHeader;
            }

            var limit        = 500;
            var blockHeaders = ImmutableArray.CreateBuilder <BlockHeader>(limit);

            for (var i = matchingChainedHeader.Height; i < targetChainLocal.Blocks.Count && blockHeaders.Count < limit; i++)
            {
                var chainedHeader = targetChainLocal.Blocks[i];

                blockHeaders.Add(chainedHeader.BlockHeader);

                if (chainedHeader.Hash == payload.HashStop)
                {
                    break;
                }
            }

            peer.Sender.SendHeaders(blockHeaders.ToImmutable()).Forget();
        }
        public void DeserializeAndSerialize()
        {
            var test  = GetBlocksPayload.Create(UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01"), 5);
            var clone = test.ToArray().AsSerializable <GetBlocksPayload>();

            Assert.AreEqual(test.Count, clone.Count);
            Assert.AreEqual(test.HashStart, clone.HashStart);
            Assert.AreEqual(5, clone.Count);
            Assert.AreEqual("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01", clone.HashStart.ToString());

            Assert.ThrowsException <FormatException>(() => GetBlocksPayload.Create(UInt256.Zero, -2).ToArray().AsSerializable <GetBlocksPayload>());
            Assert.ThrowsException <FormatException>(() => GetBlocksPayload.Create(UInt256.Zero, 0).ToArray().AsSerializable <GetBlocksPayload>());
        }
Beispiel #19
0
        public void SerializeTest()
        {
            byte[]           hd1    = Helper.HexToBytes(Header1);
            byte[]           hd2    = Helper.HexToBytes(Header2);
            GetBlocksPayload pl     = new GetBlocksPayload(Version, new byte[][] { hd1, hd2 }, new byte[32]);
            FastStream       stream = new FastStream(4 + 32 + 32 + 32);

            pl.Serialize(stream);

            byte[] actual   = stream.ToByteArray();
            byte[] expected = Helper.HexToBytes(PayloadHex);

            Assert.Equal(expected, actual);
        }
        public void Size_Get()
        {
            var test = new GetBlocksPayload()
            {
                Count = 5, HashStart = UInt256.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff01")
            };

            test.Size.Should().Be(34);

            test = new GetBlocksPayload()
            {
                Count = 1, HashStart = UInt256.Zero
            };
            test.Size.Should().Be(34);
        }
Beispiel #21
0
        private void OnGetBlocks(RemoteNode remoteNode, GetBlocksPayload payload)
        {
            var targetChainLocal = this.blockchainDaemon.TargetChain;

            if (targetChainLocal == null)
            {
                return;
            }

            ChainedHeader matchingChainedHeader = null;

            foreach (var blockHash in payload.BlockLocatorHashes)
            {
                ChainedHeader chainedHeader;
                if (this.chainedHeaderCache.TryGetValue(blockHash, out chainedHeader))
                {
                    if (chainedHeader.Height < targetChainLocal.Blocks.Count &&
                        chainedHeader.Hash == targetChainLocal.Blocks[chainedHeader.Height].Hash)
                    {
                        matchingChainedHeader = chainedHeader;
                        break;
                    }
                }
            }

            if (matchingChainedHeader == null)
            {
                matchingChainedHeader = this.rules.GenesisChainedHeader;
            }

            var count      = 0;
            var limit      = 500;
            var invVectors = new InventoryVector[limit];

            for (var i = matchingChainedHeader.Height; i < targetChainLocal.Blocks.Count && count <= limit; i++, count++)
            {
                var chainedHeader = targetChainLocal.Blocks[i];
                invVectors[count] = new InventoryVector(InventoryVector.TYPE_MESSAGE_BLOCK, chainedHeader.Hash);

                if (chainedHeader.Hash == payload.HashStop)
                {
                    break;
                }
            }
            Array.Resize(ref invVectors, count);

            remoteNode.Sender.SendInventory(invVectors.ToImmutableArray()).Forget();
        }
Beispiel #22
0
        public void TryDeserializeTest()
        {
            GetBlocksPayload pl     = new GetBlocksPayload();
            FastStreamReader stream = new FastStreamReader(Helper.HexToBytes(PayloadHex));
            bool             b      = pl.TryDeserialize(stream, out string error);

            byte[] hd1 = Helper.HexToBytes(Header1);
            byte[] hd2 = Helper.HexToBytes(Header2);

            Assert.True(b, error);
            Assert.Null(error);
            Assert.Equal(Version, pl.Version);
            Assert.Equal(new byte[][] { hd1, hd2 }, pl.Hashes);
            Assert.Equal(new byte[32], pl.StopHash);
            Assert.Equal(PayloadType.GetBlocks, pl.PayloadType);
        }
Beispiel #23
0
        private void AskBlocksIfBehind()
        {
            if (this.blockSyncHub.Context.DownloadMode)
            {
                return;
            }

            if (this.AttachedNode.PeerVersion.StartHeight - this.blockSyncHub.ChainIndex.Height > 10)
            {
                var message = new GetBlocksPayload()
                {
                    BlockLocators = this.blockSyncHub.ChainIndex.Tip.GetLocator()
                };
                this.AttachedNode.SendMessage(message);
            }
        }
Beispiel #24
0
        private bool OnBroadcastCommand(string[] args)
        {
            if (!Enum.TryParse(args[1], true, out MessageCommand command))
            {
                Console.WriteLine($"Command \"{args[1]}\" is not supported.");
                return(true);
            }
            ISerializable payload = null;

            switch (command)
            {
            case MessageCommand.Addr:
                payload = AddrPayload.Create(NetworkAddressWithTime.Create(IPAddress.Parse(args[2]), DateTime.UtcNow.ToTimestamp(), new FullNodeCapability(), new ServerCapability(NodeCapabilityType.TcpServer, ushort.Parse(args[3]))));
                break;

            case MessageCommand.Block:
                if (args[2].Length == 64 || args[2].Length == 66)
                {
                    payload = Blockchain.Singleton.GetBlock(UInt256.Parse(args[2]));
                }
                else
                {
                    payload = Blockchain.Singleton.Store.GetBlock(uint.Parse(args[2]));
                }
                break;

            case MessageCommand.GetBlocks:
            case MessageCommand.GetHeaders:
                payload = GetBlocksPayload.Create(UInt256.Parse(args[2]));
                break;

            case MessageCommand.GetData:
            case MessageCommand.Inv:
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(UInt256.Parse).ToArray());
                break;

            case MessageCommand.Transaction:
                payload = Blockchain.Singleton.GetTransaction(UInt256.Parse(args[2]));
                break;

            default:
                Console.WriteLine($"Command \"{command}\" is not supported.");
                return(true);
            }
            system.LocalNode.Tell(Message.Create(command, payload));
            return(true);
        }
Beispiel #25
0
 private void RequestTasks(TaskSession session)
 {
     if (session.HasTask)
     {
         return;
     }
     if (session.AvailableTasks.Count > 0)
     {
         session.AvailableTasks.ExceptWith(knownHashes);
         session.AvailableTasks.RemoveWhere(p => blockchain.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         hashes.ExceptWith(globalTasks);
         if (hashes.Count > 0)
         {
             session.AvailableTasks.ExceptWith(hashes);
             globalTasks.UnionWith(hashes);
             foreach (UInt256 hash in hashes)
             {
                 session.Tasks[hash] = DateTime.UtcNow;
             }
             foreach (InvPayload group in InvPayload.CreateGroup(InventoryType.Block, hashes.ToArray()))
             {
                 session.RemoteNode.Tell(Message.Create("getdata", group));
             }
             return;
         }
     }
     if (!HeaderTask && blockchain.HeaderHeight < session.Version.StartHeight)
     {
         session.Tasks[UInt256.Zero] = DateTime.UtcNow;
         session.RemoteNode.Tell(Message.Create("getheaders", GetBlocksPayload.Create(blockchain.CurrentHeaderHash)));
     }
     else if (blockchain.Height < session.Version.StartHeight)
     {
         UInt256 hash = blockchain.CurrentBlockHash;
         for (uint i = blockchain.Height + 1; i <= blockchain.HeaderHeight; i++)
         {
             hash = blockchain.GetBlockHash(i);
             if (!globalTasks.Contains(hash))
             {
                 hash = blockchain.GetBlockHash(i - 1);
                 break;
             }
         }
         session.RemoteNode.Tell(Message.Create("getblocks", GetBlocksPayload.Create(hash)));
     }
 }
Beispiel #26
0
        private void OnGetBlocks(Peer peer, GetBlocksPayload payload)
        {
            var targetChainLocal = this.coreDaemon.TargetChain;

            if (targetChainLocal == null)
            {
                return;
            }

            ChainedHeader matchingChainedHeader = null;

            foreach (var blockHash in payload.BlockLocatorHashes)
            {
                ChainedHeader chainedHeader;
                if (this.coreStorage.TryGetChainedHeader(blockHash, out chainedHeader))
                {
                    if (chainedHeader.Height < targetChainLocal.Blocks.Count &&
                        chainedHeader.Hash == targetChainLocal.Blocks[chainedHeader.Height].Hash)
                    {
                        matchingChainedHeader = chainedHeader;
                        break;
                    }
                }
            }

            if (matchingChainedHeader == null)
            {
                matchingChainedHeader = this.rules.GenesisChainedHeader;
            }

            var limit      = 500;
            var invVectors = ImmutableArray.CreateBuilder <InventoryVector>(limit);

            for (var i = matchingChainedHeader.Height; i < targetChainLocal.Blocks.Count && invVectors.Count < limit; i++)
            {
                var chainedHeader = targetChainLocal.Blocks[i];
                invVectors.Add(new InventoryVector(InventoryVector.TYPE_MESSAGE_BLOCK, chainedHeader.Hash));

                if (chainedHeader.Hash == payload.HashStop)
                {
                    break;
                }
            }

            peer.Sender.SendInventory(invVectors.ToImmutable()).Forget();
        }
Beispiel #27
0
        private void OnGetHeadersMessageReceived(Message msg)
        {
            GetBlocksPayload payload = msg.GetPayload <GetBlocksPayload>();

            UInt256 hash = payload.HashStart[0];

            if (hash == payload.HashStop)
            {
                return;
            }
            DataCache <UInt256, BlockState> cache = blockchain.Store.GetBlocks();
            BlockState state = cache.TryGet(hash);

            if (state == null)
            {
                return;
            }
            List <Header> headers = new List <Header>();

            for (uint i = 1; i <= HeadersPayload.MaxHeadersCount; i++)
            {
                uint index = state.TrimmedBlock.Index + i;
                hash = blockchain.GetBlockHash(index);
                if (hash == null)
                {
                    break;
                }
                if (hash == payload.HashStop)
                {
                    break;
                }
                Header header = cache.TryGet(hash)?.TrimmedBlock.Header;
                if (header == null)
                {
                    break;
                }
                headers.Add(header);
            }
            blockchain.Log($"OnGetHeaders, blockIndex:{state.TrimmedBlock.Index}, count:{headers.Count}, [{remoteNode.Remote.Address}]");
            if (headers.Count == 0)
            {
                return;
            }
            Context.Parent.Tell(Message.Create(MessageType.Headers, HeadersPayload.Create(headers)));
        }
Beispiel #28
0
        private void OnGetBlocksMessageReceived(Message msg)
        {
            GetBlocksPayload payload = msg.GetPayload <GetBlocksPayload>();

            UInt256 hash = payload.HashStart[0];

            if (hash == payload.HashStop)
            {
                return;
            }
            BlockState state = blockchain.Store.GetBlocks().TryGet(hash);

            if (state == null)
            {
                return;
            }
            List <UInt256> hashes = new List <UInt256>();

            for (uint i = 1; i <= InvPayload.MaxHashesCount; i++)
            {
                uint index = state.TrimmedBlock.Index + i;
                if (index > blockchain.Height)
                {
                    break;
                }
                hash = blockchain.GetBlockHash(index);
                if (hash == null)
                {
                    break;
                }
                if (hash == payload.HashStop)
                {
                    break;
                }
                hashes.Add(hash);
            }
            if (hashes.Count == 0)
            {
                return;
            }
            Context.Parent.Tell(Message.Create(MessageType.Inv, InvPayload.Create(InventoryType.Block, hashes.ToArray())));
            blockchain.Log($"OnGetBlocks, blockIndex:{state.TrimmedBlock.Index}, count:{hashes.Count}, [{remoteNode.Remote.Address}]");
        }
Beispiel #29
0
        private bool OnBroadcastCommand(string[] args)
        {
            string        command = args[1].ToLower();
            ISerializable payload = null;

            switch (command)
            {
            case "addr":
                payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[2]), ushort.Parse(args[3])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp()));
                break;

            case "block":
                if (args[2].Length == 64 || args[2].Length == 66)
                {
                    payload = Blockchain.Singleton.GetBlock(UInt256.Parse(args[2]));
                }
                else
                {
                    payload = Blockchain.Singleton.Store.GetBlock(uint.Parse(args[2]));
                }
                break;

            case "getblocks":
            case "getheaders":
                payload = GetBlocksPayload.Create(UInt256.Parse(args[2]));
                break;

            case "getdata":
            case "inv":
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(UInt256.Parse).ToArray());
                break;

            case "tx":
                payload = Blockchain.Singleton.GetTransaction(UInt256.Parse(args[2]));
                break;

            default:
                Console.WriteLine($"Command \"{command}\" is not supported.");
                return(true);
            }
            system.LocalNode.Tell(Message.Create(command, payload));
            return(true);
        }
Beispiel #30
0
        private void OnGetHeaders(RemoteNode remoteNode, GetBlocksPayload payload)
        {
            // if in comparison mode, synchronize all work before returning current headers
            if (this.Type == LocalClientType.ComparisonToolTestNet)
            {
                this.blockchainDaemon.WaitForFullUpdate();
            }

            var currentBlockchainLocal = this.blockchainDaemon.CurrentBlockchain;
            var blockHeaders           = new List <BlockHeader>(currentBlockchainLocal.BlockCount);

            foreach (var chainedBlock in currentBlockchainLocal.BlockList)
            {
                BlockHeader blockHeader;
                if (this.blockchainDaemon.CacheContext.BlockHeaderCache.TryGetValue(chainedBlock.BlockHash, out blockHeader))
                {
                    blockHeaders.Add(blockHeader);
                }
                else
                {
                    Debugger.Break();
                    Debug.WriteLine("Couldn't generate getheaders response");
                    return;
                }
            }

            var payloadStream = new MemoryStream();

            using (var payloadWriter = new BinaryWriter(payloadStream))
            {
                payloadWriter.WriteVarInt((UInt64)blockHeaders.Count);
                foreach (var blockHeader in blockHeaders)
                {
                    NetworkEncoder.EncodeBlockHeader(payloadStream, blockHeader);
                    payloadWriter.WriteVarInt(0);
                }
            }

            remoteNode.Sender.SendMessageAsync(Messaging.ConstructMessage("headers", payloadStream.ToArray())).Wait();
        }
Beispiel #31
0
 public static byte[] EncodeGetBlocksPayload(GetBlocksPayload getBlocksPayload)
 {
     using (var stream = new MemoryStream())
     using (var writer = new BinaryWriter(stream))
     {
         EncodeGetBlocksPayload(writer, getBlocksPayload);
         return stream.ToArray();
     }
 }
Beispiel #32
0
 public static void EncodeGetBlocksPayload(BinaryWriter writer, GetBlocksPayload getBlocksPayload)
 {
     writer.WriteUInt32(getBlocksPayload.Version);
     writer.WriteList(getBlocksPayload.BlockLocatorHashes, locatorHash => writer.WriteUInt256(locatorHash));
     writer.WriteUInt256(getBlocksPayload.HashStop);
 }