public MerkleBlockMessage(BlockHeader blockHeader, uint totalTransactions, byte[][] hashes, byte[] flags)
 {
     this.blockHeader = blockHeader;
     this.totalTransactions = totalTransactions;
     this.hashes = new List<byte[]>(hashes);
     this.flags = flags;
 }
 //todo: split BlockHeaderValidator to static and non-static parts
 public static bool IsValid(BlockHeader header)
 {
     return
         IsNBitsValid(header) &&
         IsTimestampValid(header) &&
         IsHashValid(header);
 }
 internal StoredBlock(BlockHeader header, byte[] hash, int height, double totalWork, bool hasContent, bool isInBestHeaderChain, bool isInBestBlockChain)
 {
     Header = header;
     Hash = hash;
     Height = height;
     TotalWork = totalWork;
     HasContent = hasContent;
     IsInBestHeaderChain = isInBestHeaderChain;
     IsInBestBlockChain = isInBestBlockChain;
 }
        public void TestIsTimestampValid()
        {
            List<StoredBlock> blocks = new List<StoredBlock>();

            StoredBlock prevBlock = null;

            for (int i = 0; i < 11; i++)
            {
                BlockHeader header = new BlockHeader
                    (
                    genesisBlockHeader.Version,
                    prevBlock == null ? new byte[32] : prevBlock.Hash,
                    new byte[32],
                    (uint) i,
                    0x21100000,
                    0);
                StoredBlock storedBlock = new StoredBlockBuilder(header).Build();
                blocks.Add(storedBlock);
                prevBlock = storedBlock;
            }

            Subchain subchain = new Subchain(blocks);

            {
                BlockHeader header = new BlockHeader
                    (
                    genesisBlockHeader.Version,
                    new byte[32],
                    new byte[32],
                    5,
                    0x21100000,
                    0);

                StoredBlock storedBlock = new StoredBlockBuilder(header).Build();

                Assert.False(BlockHeaderValidator.IsTimeStampValid(storedBlock, subchain));
            }

            {
                BlockHeader header = new BlockHeader
                    (
                    genesisBlockHeader.Version,
                    new byte[32],
                    new byte[32],
                    6,
                    0x21100000,
                    0);

                StoredBlock storedBlock = new StoredBlockBuilder(header).Build();

                Assert.True(BlockHeaderValidator.IsTimeStampValid(storedBlock, subchain));
            }
        }
        public void TestIsHashValid()
        {
            Assert.True(BlockHeaderValidator.IsHashValid(genesisBlockHeader));

            BlockHeader blockHeader = new BlockHeader(
                genesisBlockHeader.Version,
                genesisBlockHeader.PrevBlock,
                genesisBlockHeader.MerkleRoot,
                genesisBlockHeader.Timestamp,
                genesisBlockHeader.NBits,
                1);
            Assert.False(BlockHeaderValidator.IsHashValid(blockHeader));
        }
        /// <summary>
        /// Checks that a hash of the header matches nBits field in the block.
        /// </summary>
        internal static bool IsHashValid(BlockHeader header)
        {
            byte[] text = BitcoinStreamWriter.GetBytes(header.Write);
            //todo: This hash is calculated too often. Save it somewhere.
            byte[] hash = CryptoUtils.DoubleSha256(text);

            BigInteger hashAsNumber = NumberUtils.ToBigInteger(hash);
            BigInteger difficultyTarget = DifficultyUtils.NBitsToTarget(header.NBits);

            if (hashAsNumber > difficultyTarget)
            {
                return false;
            }

            return true;
        }
        public void TestIsTimestampValidStatic()
        {
            BlockHeader blockHeader1 = new BlockHeader(
                genesisBlockHeader.Version,
                genesisBlockHeader.PrevBlock,
                genesisBlockHeader.MerkleRoot,
                (uint) UnixTime.ToTimestamp(DateTime.UtcNow.AddMinutes(110)),
                genesisBlockHeader.NBits,
                genesisBlockHeader.Nonce);
            Assert.True(BlockHeaderValidator.IsTimestampValid(blockHeader1));

            BlockHeader blockHeader2 = new BlockHeader(
                genesisBlockHeader.Version,
                genesisBlockHeader.PrevBlock,
                genesisBlockHeader.MerkleRoot,
                (uint) UnixTime.ToTimestamp(DateTime.UtcNow.AddMinutes(130)),
                genesisBlockHeader.NBits,
                genesisBlockHeader.Nonce);
            Assert.False(BlockHeaderValidator.IsTimestampValid(blockHeader2));
        }
 public BlockMessage(BlockHeader blockHeader, Tx[] transactions)
 {
     this.blockHeader = blockHeader;
     this.transactions = transactions;
 }
 public HeadersMessage(BlockHeader[] headers)
 {
     this.headers = headers;
 }
        public StoredBlockBuilder(BlockHeader header)
        {
            byte[] text = BitcoinStreamWriter.GetBytes(header.Write);

            Header = header;
            Hash = CryptoUtils.DoubleSha256(text);
            Height = -1;
            TotalWork = 0;
            HasContent = false;
            IsInBestHeaderChain = false;
            IsInBestBlockChain = false;
        }
 /// <summary>
 /// Checks that the difficulty defined by the nBits field is not lower than the network minimum.
 /// </summary>
 internal static bool IsNBitsValid(BlockHeader blockHeader)
 {
     BigInteger target = DifficultyUtils.NBitsToTarget(blockHeader.NBits);
     return target <= DifficultyUtils.MaxDifficultyTarget;
 }
 /// <summary>
 /// Checks that timestamp of the block header is not too far in the future.
 /// </summary>
 /// <remarks>Specification: https://en.bitcoin.it/wiki/Block_timestamp </remarks>
 internal static bool IsTimestampValid(BlockHeader header)
 {
     //todo: Specification requires to adjust current time. Why is it necessary?
     return UnixTime.ToDateTime(header.Timestamp) < SystemTime.UtcNow.AddHours(2);
 }