Ejemplo n.º 1
0
        private bool processBlockHeader(BlockHeader header)
        {
            if (lastBlockHeader != null && lastBlockHeader.blockChecksum != null && !header.lastBlockChecksum.SequenceEqual(lastBlockHeader.blockChecksum))
            {
                Logging.warn("TIV: Invalid last block checksum");

                // discard the block

                // TODO require previous block to get verifications from 3 nodes
                // if in verification mode, detect liar and flag him
                // below is an implementation that's good enough for now

                if (minBlockHeightReorg < lastBlockHeader.blockNum - 7)
                {
                    minBlockHeightReorg = lastBlockHeader.blockNum - 7;
                }

                BlockHeader prev_header = BlockHeaderStorage.getBlockHeader(minBlockHeightReorg);

                if (prev_header == null)
                {
                    return(false);
                }

                lastBlockHeader = prev_header;

                ConsensusConfig.redactedWindowSize    = ConsensusConfig.getRedactedWindowSize(lastBlockHeader.version);
                ConsensusConfig.minRedactedWindowSize = ConsensusConfig.getRedactedWindowSize(lastBlockHeader.version);

                return(false);
            }

            if (!header.calculateChecksum().SequenceEqual(header.blockChecksum))
            {
                Logging.warn("TIV: Invalid block checksum");
                return(false);
            }

            lastBlockHeader = header;

            ConsensusConfig.redactedWindowSize    = ConsensusConfig.getRedactedWindowSize(lastBlockHeader.version);
            ConsensusConfig.minRedactedWindowSize = ConsensusConfig.getRedactedWindowSize(lastBlockHeader.version);

            if (BlockHeaderStorage.saveBlockHeader(lastBlockHeader))
            {
                // Cleanup every n blocks
                if ((header.blockNum > CoreConfig.maxBlockHeadersPerDatabase * 25) && header.blockNum % CoreConfig.maxBlockHeadersPerDatabase == 0)
                {
                    BlockHeaderStorage.removeAllBlocksBefore(header.blockNum - (CoreConfig.maxBlockHeadersPerDatabase * 25));
                }
            }

            IxianHandler.receivedBlockHeader(lastBlockHeader, true);

            return(true);
        }
Ejemplo n.º 2
0
        private void verifyUnprocessedTransactions()
        {
            if (lastBlockHeader == null)
            {
                return;
            }
            lock (txQueue)
            {
                var tmp_txQueue = txQueue.Values.Where(x => x.applied != 0 && x.applied <= lastBlockHeader.blockNum).ToArray();
                foreach (var tx in tmp_txQueue)
                {
                    BlockHeader bh = BlockHeaderStorage.getBlockHeader(tx.applied);
                    if (bh is null)
                    {
                        // TODO: need to wait for the block to arrive, or re-request
                        // maybe something similar to PIT cache, or extend PIT cache to handle older blocks, too
                        continue;
                    }
                    if (bh.version < BlockVer.v6)
                    {
                        txQueue.Remove(tx.id);

                        if (bh.transactions.Contains(tx.id, new ByteArrayComparer()))
                        {
                            // valid
                            IxianHandler.receivedTransactionInclusionVerificationResponse(tx.id, true);
                        }
                        else
                        {
                            // invalid
                            IxianHandler.receivedTransactionInclusionVerificationResponse(tx.id, false);
                        }
                    }
                    else
                    {
                        lock (pitCache)
                        {
                            // check if we already have the partial tree for this transaction
                            if (pitCache.ContainsKey(tx.applied) && pitCache[tx.applied].pit != null)
                            {
                                // Note: PIT has been verified against the block header when it was received, so additional verification is not needed here.
                                // Note: the PIT we have cached might have been requested for different txids (the current txid could have been added later)
                                // For that reason, the list of TXIDs we requested is stored together with the cached PIT
                                byte[] txid = null;
                                if (bh.version < BlockVer.v8)
                                {
                                    txid = UTF8Encoding.UTF8.GetBytes(Transaction.txIdV8ToLegacy(tx.id));
                                }
                                else
                                {
                                    txid = tx.id;
                                }
                                if (pitCache[tx.applied].requestedForTXIDs.Contains(tx.id, new ByteArrayComparer()))
                                {
                                    // TODO TODO it shouldn't be immediatelly removed but checked with other nodes first
                                    txQueue.Remove(tx.id);

                                    if (pitCache[tx.applied].pit.contains(txid))
                                    {
                                        // valid
                                        IxianHandler.receivedTransactionInclusionVerificationResponse(tx.id, true);
                                    }
                                    else
                                    {
                                        // invalid
                                        IxianHandler.receivedTransactionInclusionVerificationResponse(tx.id, false);
                                    }
                                }
                                else
                                {
                                    // PIT cache for the correct block exists, but it was originally requested for different txids
                                    // we have to re-request it for any remaining txids in the queue. (We do not need to request the already-verified ids)
                                    requestPITForBlock(tx.applied,
                                                       txQueue.Values
                                                       .Where(x => x.applied == tx.applied && x.applied <= lastBlockHeader.blockNum)
                                                       .Select(x => x.id)
                                                       .ToList());
                                    continue;
                                }
                            }
                            else
                            {
                                // PIT cache has not been received yet, or maybe it has never been requested for this block
                                requestPITForBlock(tx.applied,
                                                   txQueue.Values
                                                   .Where(x => x.applied == tx.applied && x.applied <= lastBlockHeader.blockNum)
                                                   .Select(x => x.id)
                                                   .ToList());
                            }
                        }
                    }
                }
                tmp_txQueue = txQueue.Values.Where(x => x.blockHeight + ConsensusConfig.getRedactedWindowSize() < lastBlockHeader.blockNum).ToArray();
                foreach (var tx in tmp_txQueue)
                {
                    txQueue.Remove(tx.id);
                    // invalid
                    IxianHandler.receivedTransactionInclusionVerificationResponse(tx.id, false);
                }
            }
        }