コード例 #1
0
        private bool handleBlock(InventoryItem item, RemoteEndpoint endpoint)
        {
            InventoryItemBlock iib  = (InventoryItemBlock)item;
            ulong last_block_height = IxianHandler.getLastBlockHeight();

            if (iib.blockNum > last_block_height)
            {
                byte include_tx = 2;
                if (Node.isMasterNode())
                {
                    include_tx = 0;
                }
                BlockProtocolMessages.broadcastGetBlock(last_block_height + 1, null, endpoint, include_tx, true);
                if (iib.blockNum == last_block_height + 1)
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #2
0
            // Removes event subscriptions for the provided endpoint
            public static void handleBlockSignature(byte[] data, RemoteEndpoint endpoint)
            {
                if (Node.blockSync.synchronizing)
                {
                    return;
                }

                if (data == null)
                {
                    Logging.warn(string.Format("Invalid protocol message signature data"));
                    return;
                }

                using (MemoryStream m = new MemoryStream(data))
                {
                    using (BinaryReader reader = new BinaryReader(m))
                    {
                        ulong block_num = reader.ReadUInt64();

                        int    checksum_len = reader.ReadInt32();
                        byte[] checksum     = reader.ReadBytes(checksum_len);

                        int    sig_len = reader.ReadInt32();
                        byte[] sig     = reader.ReadBytes(sig_len);

                        int    sig_addr_len = reader.ReadInt32();
                        byte[] sig_addr     = reader.ReadBytes(sig_addr_len);

                        ulong last_bh = IxianHandler.getLastBlockHeight();

                        lock (Node.blockProcessor.localBlockLock)
                        {
                            if (last_bh + 1 < block_num || (last_bh + 1 == block_num && Node.blockProcessor.getLocalBlock() == null))
                            {
                                Logging.info("Received signature for block {0} which is missing", block_num);
                                // future block, request the next block
                                BlockProtocolMessages.broadcastGetBlock(last_bh + 1, null, endpoint);
                                return;
                            }
                        }

                        if (PresenceList.getPresenceByAddress(sig_addr) == null)
                        {
                            Logging.info("Received signature for block {0} whose signer isn't in the PL", block_num);
                            return;
                        }

                        Node.inventoryCache.setProcessedFlag(InventoryItemTypes.blockSignature, InventoryItemSignature.getHash(sig_addr, checksum), true);

                        if (Node.blockProcessor.addSignatureToBlock(block_num, checksum, sig, sig_addr, endpoint))
                        {
                            Node.blockProcessor.acceptLocalNewBlock();
                            if (Node.isMasterNode())
                            {
                                broadcastBlockSignature(sig, sig_addr, block_num, checksum, endpoint);
                            }
                        }
                        else
                        {
                            // discard - it might have already been applied
                        }
                    }
                }
            }
コード例 #3
0
            public static void handleSigfreezedBlockSignatures(byte[] data, RemoteEndpoint endpoint)
            {
                using (MemoryStream m = new MemoryStream(data))
                {
                    using (BinaryReader reader = new BinaryReader(m))
                    {
                        ulong block_num = reader.ReadUInt64();

                        int    checksum_len = reader.ReadInt32();
                        byte[] checksum     = reader.ReadBytes(checksum_len);

                        ulong last_block_height = IxianHandler.getLastBlockHeight();

                        Block target_block = Node.blockChain.getBlock(block_num, true);
                        if (target_block == null)
                        {
                            if (block_num == last_block_height + 1)
                            {
                                // target block missing, request the next block
                                Logging.warn("Target block {0} missing, requesting...", block_num);
                                BlockProtocolMessages.broadcastGetBlock(block_num, null, endpoint);
                            }
                            else
                            {
                                // target block missing
                                Logging.warn("Target block {0} missing", block_num);
                            }
                            return;
                        }
                        else if (!target_block.blockChecksum.SequenceEqual(checksum))
                        {
                            // incorrect target block
                            Logging.warn("Incorrect target block {0} - {1}, possibly forked", block_num, Crypto.hashToString(checksum));
                            return;
                        }


                        Block sf_block = null;
                        if (block_num + 4 == last_block_height)
                        {
                            sf_block = Node.blockProcessor.getLocalBlock();
                        }
                        else if (block_num + 4 > last_block_height)
                        {
                            Logging.warn("Sigfreezing block {0} missing", block_num + 5);
                            return;
                        }
                        else
                        {
                            // block already sigfreezed, do nothing
                            return;
                        }

                        lock (target_block)
                        {
                            if (sf_block != null)
                            {
                                if (target_block.calculateSignatureChecksum().SequenceEqual(sf_block.signatureFreezeChecksum))
                                {
                                    // we already have the correct sigfreeze
                                    return;
                                }
                            }
                            else
                            {
                                // sf_block missing
                                Logging.warn("Sigfreezing block {0} missing", block_num + 5);
                                return;
                            }


                            int sig_count = reader.ReadInt32();

                            if (sig_count > ConsensusConfig.maximumBlockSigners)
                            {
                                sig_count = ConsensusConfig.maximumBlockSigners;
                            }

                            Block dummy_block = new Block();
                            dummy_block.blockNum      = block_num;
                            dummy_block.blockChecksum = checksum;
                            dummy_block.blockProposer = sf_block.blockProposer;

                            for (int i = 0; i < sig_count; i++)
                            {
                                if (m.Position == m.Length)
                                {
                                    break;
                                }

                                int    sig_len = reader.ReadInt32();
                                byte[] sig     = reader.ReadBytes(sig_len);

                                int    addr_len = reader.ReadInt32();
                                byte[] addr     = reader.ReadBytes(addr_len);

                                Node.inventoryCache.setProcessedFlag(InventoryItemTypes.blockSignature, InventoryItemSignature.getHash(addr, checksum), true);

                                dummy_block.addSignature(sig, addr);
                            }

                            Node.blockProcessor.handleSigFreezedBlock(dummy_block, endpoint);
                        }
                    }
                }
            }
コード例 #4
0
ファイル: BlockSync.cs プロジェクト: ProjectIxian/Ixian-DLT
        private bool requestMissingBlocks()
        {
            if (syncDone)
            {
                return(false);
            }

            if (syncTargetBlockNum == 0)
            {
                return(false);
            }

            long currentTime = Clock.getTimestamp();

            // Check if the block has already been requested
            lock (requestedBlockTimes)
            {
                Dictionary <ulong, long> tmpRequestedBlockTimes = new Dictionary <ulong, long>(requestedBlockTimes);
                foreach (var entry in tmpRequestedBlockTimes)
                {
                    if (!running)
                    {
                        return(false);
                    }
                    ulong blockNum = entry.Key;
                    // Check if the request expired (after 10 seconds)
                    if (currentTime - requestedBlockTimes[blockNum] > 10)
                    {
                        // Re-request block
                        if (BlockProtocolMessages.broadcastGetBlock(blockNum, null, null, 1, true) == false)
                        {
                            Logging.warn(string.Format("Failed to rebroadcast getBlock request for {0}", blockNum));
                            Thread.Sleep(500);
                        }
                        else
                        {
                            // Re-set the block request time
                            requestedBlockTimes[blockNum] = currentTime;
                        }
                    }
                }
            }


            ulong syncToBlock = syncTargetBlockNum;

            ulong firstBlock = getLowestBlockNum();


            lock (pendingBlocks)
            {
                ulong lastBlock = syncToBlock;
                if (missingBlocks == null)
                {
                    missingBlocks = new List <ulong>(Enumerable.Range(0, (int)(lastBlock - firstBlock + 1)).Select(x => (ulong)x + firstBlock));
                    missingBlocks.Sort();
                }

                int total_count     = 0;
                int requested_count = 0;

                // whatever is left in missingBlocks is what we need to request
                if (missingBlocks.Count() == 0)
                {
                    receivedAllMissingBlocks = true;
                    return(false);
                }

                List <ulong> tmpMissingBlocks = new List <ulong>(missingBlocks.Take(maxBlockRequests * 2));

                foreach (ulong blockNum in tmpMissingBlocks)
                {
                    if (!running)
                    {
                        return(false);
                    }
                    total_count++;
                    lock (requestedBlockTimes)
                    {
                        if (requestedBlockTimes.ContainsKey(blockNum))
                        {
                            requested_count++;
                            continue;
                        }
                    }

                    bool readFromStorage = false;
                    if (blockNum <= lastBlockToReadFromStorage)
                    {
                        readFromStorage = true;
                    }

                    ulong last_block_height = IxianHandler.getLastBlockHeight();
                    if (blockNum > last_block_height + (ulong)maxBlockRequests)
                    {
                        if (last_block_height > 0 || (last_block_height == 0 && total_count > 10))
                        {
                            break;
                        }
                    }

                    // First check if the missing block can be found in storage
                    Block block = Node.blockChain.getBlock(blockNum, readFromStorage);
                    if (block != null)
                    {
                        if (CoreConfig.preventNetworkOperations || Config.recoverFromFile)
                        {
                            if (!lastBlocks.Exists(x => x.blockNum == blockNum))
                            {
                                lastBlocks.Add(new Block(block));
                                if (lastBlocks.Count > maxBlockRequests * 2)
                                {
                                    lastBlocks.RemoveAt(0);
                                }
                            }
                        }
                        Node.blockSync.onBlockReceived(block, null);
                    }
                    else
                    {
                        if (readFromStorage)
                        {
                            Logging.warn("Expecting block {0} in storage but had to request it from network.", blockNum);
                        }
                        // Didn't find the block in storage, request it from the network
                        if (BlockProtocolMessages.broadcastGetBlock(blockNum, null, null, 1, true) == false)
                        {
                            Logging.warn(string.Format("Failed to broadcast getBlock request for {0}", blockNum));
                            Thread.Sleep(500);
                        }
                        else
                        {
                            requested_count++;
                            // Set the block request time
                            lock (requestedBlockTimes)
                            {
                                requestedBlockTimes.Add(blockNum, currentTime);
                            }
                        }
                    }
                }

                if (requested_count > 0)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #5
0
            static void handleInventory2(byte[] data, RemoteEndpoint endpoint)
            {
                using (MemoryStream m = new MemoryStream(data))
                {
                    using (BinaryReader reader = new BinaryReader(m))
                    {
                        ulong item_count = reader.ReadIxiVarUInt();
                        if (item_count > (ulong)CoreConfig.maxInventoryItems)
                        {
                            Logging.warn("Received {0} inventory items, max items is {1}", item_count, CoreConfig.maxInventoryItems);
                            item_count = (ulong)CoreConfig.maxInventoryItems;
                        }

                        ulong last_block_height = IxianHandler.getLastBlockHeight();

                        Dictionary <ulong, List <InventoryItemSignature> > sig_lists = new Dictionary <ulong, List <InventoryItemSignature> >();
                        List <InventoryItemKeepAlive> ka_list = new List <InventoryItemKeepAlive>();
                        List <byte[]> tx_list            = new List <byte[]>();
                        bool          request_next_block = false;
                        for (ulong i = 0; i < item_count; i++)
                        {
                            ulong         len        = reader.ReadIxiVarUInt();
                            byte[]        item_bytes = reader.ReadBytes((int)len);
                            InventoryItem item       = InventoryCache.decodeInventoryItem(item_bytes);
                            if (item.type == InventoryItemTypes.transaction)
                            {
                                PendingTransactions.increaseReceivedCount(item.hash, endpoint.presence.wallet);
                            }
                            PendingInventoryItem pii = Node.inventoryCache.add(item, endpoint);
                            if (!pii.processed && pii.lastRequested == 0)
                            {
                                // first time we're seeing this inventory item
                                switch (item.type)
                                {
                                case InventoryItemTypes.keepAlive:
                                    ka_list.Add((InventoryItemKeepAlive)item);
                                    pii.lastRequested = Clock.getTimestamp();
                                    break;

                                case InventoryItemTypes.transaction:
                                    tx_list.Add(item.hash);
                                    pii.lastRequested = Clock.getTimestamp();
                                    break;

                                case InventoryItemTypes.blockSignature:
                                    var iis = (InventoryItemSignature)item;
                                    if (iis.blockNum < last_block_height - 5 && iis.blockNum > last_block_height + 6)
                                    {
                                        continue;
                                    }
                                    if (!sig_lists.ContainsKey(iis.blockNum))
                                    {
                                        sig_lists.Add(iis.blockNum, new List <InventoryItemSignature>());
                                    }
                                    sig_lists[iis.blockNum].Add(iis);
                                    pii.lastRequested = Clock.getTimestamp();
                                    break;

                                case InventoryItemTypes.block:
                                    var iib = ((InventoryItemBlock)item);
                                    if (iib.blockNum <= last_block_height)
                                    {
                                        Node.inventoryCache.processInventoryItem(pii);
                                    }
                                    else
                                    {
                                        pii.lastRequested  = Clock.getTimestamp();
                                        request_next_block = true;
                                        if (iib.blockNum > endpoint.blockHeight)
                                        {
                                            endpoint.blockHeight = iib.blockNum;
                                        }

                                        if (iib.blockNum > Node.blockProcessor.highestNetworkBlockNum)
                                        {
                                            Node.blockProcessor.highestNetworkBlockNum = iib.blockNum;
                                        }
                                    }
                                    break;

                                default:
                                    Node.inventoryCache.processInventoryItem(pii);
                                    break;
                                }
                            }
                        }
                        PresenceProtocolMessages.broadcastGetKeepAlives(ka_list, endpoint);
                        if (Node.blockSync.synchronizing)
                        {
                            return;
                        }
                        TransactionProtocolMessages.broadcastGetTransactions(tx_list, 0, endpoint);
                        if (request_next_block)
                        {
                            byte include_tx = 2;
                            if (Node.isMasterNode())
                            {
                                include_tx = 0;
                            }
                            BlockProtocolMessages.broadcastGetBlock(last_block_height + 1, null, endpoint, include_tx, true);
                        }
                        foreach (var sig_list in sig_lists)
                        {
                            SignatureProtocolMessages.broadcastGetSignatures(sig_list.Key, sig_list.Value, endpoint);
                        }
                    }
                }
            }
コード例 #6
0
            // Unified protocol message parsing
            public static void parseProtocolMessage(ProtocolMessageCode code, byte[] data, RemoteEndpoint endpoint)
            {
                if (endpoint == null)
                {
                    Logging.error("Endpoint was null. parseProtocolMessage");
                    return;
                }

                try
                {
                    switch (code)
                    {
                    case ProtocolMessageCode.hello:
                        handleHello(data, endpoint);
                        break;

                    case ProtocolMessageCode.helloData:
                        handleHelloData(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBlock:
                        BlockProtocolMessages.handleGetBlock(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBalance:
                        WalletStateProtocolMessages.handleGetBalance(data, endpoint);
                        break;

                    case ProtocolMessageCode.getTransaction:
                        TransactionProtocolMessages.handleGetTransaction(data, endpoint);
                        break;

                    case ProtocolMessageCode.getTransaction2:
                        TransactionProtocolMessages.handleGetTransaction2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getTransaction3:
                        TransactionProtocolMessages.handleGetTransaction3(data, endpoint);
                        break;

                    case ProtocolMessageCode.newTransaction:
                    case ProtocolMessageCode.transactionData:
                        TransactionProtocolMessages.handleTransactionData(data, endpoint);
                        break;

                    case ProtocolMessageCode.bye:
                        CoreProtocolMessage.processBye(data, endpoint);
                        break;

                    case ProtocolMessageCode.newBlock:
                    case ProtocolMessageCode.blockData:
                        BlockProtocolMessages.handleBlockData(data, endpoint);
                        break;

                    case ProtocolMessageCode.syncWalletState:
                        WalletStateProtocolMessages.handleSyncWalletState(data, endpoint);
                        break;

                    case ProtocolMessageCode.walletState:
                        WalletStateProtocolMessages.handleWalletState(data, endpoint);
                        break;

                    case ProtocolMessageCode.getWalletStateChunk:
                        WalletStateProtocolMessages.handleGetWalletStateChunk(data, endpoint);
                        break;

                    case ProtocolMessageCode.walletStateChunk:
                        WalletStateProtocolMessages.handleWalletStateChunk(data, endpoint);
                        break;

                    case ProtocolMessageCode.updatePresence:
                        PresenceProtocolMessages.handleUpdatePresence(data, endpoint);
                        break;

                    case ProtocolMessageCode.keepAlivePresence:
                        PresenceProtocolMessages.handleKeepAlivePresence(data, endpoint);
                        break;

                    case ProtocolMessageCode.getPresence:
                        PresenceProtocolMessages.handleGetPresence(data, endpoint);
                        break;

                    case ProtocolMessageCode.getPresence2:
                        PresenceProtocolMessages.handleGetPresence2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getKeepAlives:
                        PresenceProtocolMessages.handleGetKeepAlives(data, endpoint);
                        break;

                    case ProtocolMessageCode.keepAlivesChunk:
                        PresenceProtocolMessages.handleKeepAlivesChunk(data, endpoint);
                        break;

                    // return 10 random presences of the selected type
                    case ProtocolMessageCode.getRandomPresences:
                        PresenceProtocolMessages.handleGetRandomPresences(data, endpoint);
                        break;

                    case ProtocolMessageCode.getUnappliedTransactions:
                        TransactionProtocolMessages.handleGetUnappliedTransactions(data, endpoint);
                        break;

                    case ProtocolMessageCode.blockTransactionsChunk:
                        BlockProtocolMessages.handleBlockTransactionsChunk(data, endpoint);
                        break;

                    case ProtocolMessageCode.attachEvent:
                        NetworkEvents.handleAttachEventMessage(data, endpoint);
                        break;

                    case ProtocolMessageCode.detachEvent:
                        NetworkEvents.handleDetachEventMessage(data, endpoint);
                        break;

                    case ProtocolMessageCode.blockSignature:
                        SignatureProtocolMessages.handleBlockSignature(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBlockSignatures:
                    {
                        using (MemoryStream m = new MemoryStream(data))
                        {
                            using (BinaryReader reader = new BinaryReader(m))
                            {
                                ulong block_num = reader.ReadUInt64();

                                int    checksum_len = reader.ReadInt32();
                                byte[] checksum     = reader.ReadBytes(checksum_len);

                                SignatureProtocolMessages.handleGetBlockSignatures(block_num, checksum, endpoint);
                            }
                        }
                    }
                    break;

                    case ProtocolMessageCode.blockSignatures:
                        SignatureProtocolMessages.handleSigfreezedBlockSignatures(data, endpoint);
                        break;

                    case ProtocolMessageCode.getNextSuperBlock:
                        BlockProtocolMessages.handleGetNextSuperBlock(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBlockHeaders:
                        BlockProtocolMessages.handleGetBlockHeaders(data, endpoint);
                        break;

                    case ProtocolMessageCode.getPIT:
                        BlockProtocolMessages.handleGetPIT(data, endpoint);
                        break;

                    case ProtocolMessageCode.inventory:
                        handleInventory(data, endpoint);
                        break;

                    case ProtocolMessageCode.inventory2:
                        handleInventory2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getSignatures:
                        SignatureProtocolMessages.handleGetSignatures(data, endpoint);
                        break;

                    case ProtocolMessageCode.signaturesChunk:
                        SignatureProtocolMessages.handleSignaturesChunk(data, endpoint);
                        break;

                    case ProtocolMessageCode.getTransactions:
                        TransactionProtocolMessages.handleGetTransactions(data, endpoint);
                        break;

                    case ProtocolMessageCode.getTransactions2:
                        TransactionProtocolMessages.handleGetTransactions2(data, endpoint);
                        break;

                    case ProtocolMessageCode.transactionsChunk:
                        TransactionProtocolMessages.handleTransactionsChunk(data, endpoint);
                        break;

                    case ProtocolMessageCode.transactionsChunk2:
                        TransactionProtocolMessages.handleTransactionsChunk2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBlockHeaders2:
                        BlockProtocolMessages.handleGetBlockHeaders2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getPIT2:
                        BlockProtocolMessages.handleGetPIT2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBlock2:
                        BlockProtocolMessages.handleGetBlock2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBlock3:
                        BlockProtocolMessages.handleGetBlock3(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBalance2:
                        WalletStateProtocolMessages.handleGetBalance2(data, endpoint);
                        break;

                    case ProtocolMessageCode.getBlockSignatures2:
                    {
                        using (MemoryStream m = new MemoryStream(data))
                        {
                            using (BinaryReader reader = new BinaryReader(m))
                            {
                                ulong block_num = reader.ReadIxiVarUInt();

                                int    checksum_len = (int)reader.ReadIxiVarUInt();
                                byte[] checksum     = reader.ReadBytes(checksum_len);

                                SignatureProtocolMessages.handleGetBlockSignatures2(block_num, checksum, endpoint);
                            }
                        }
                    }
                    break;

                    case ProtocolMessageCode.blockSignature2:
                        SignatureProtocolMessages.handleBlockSignature2(data, endpoint);
                        break;

                    default:
                        break;
                    }
                }
                catch (Exception e)
                {
                    Logging.error("Error parsing network message. Details: {0}", e.ToString());
                }
            }