Beispiel #1
0
        public void BlockIsValid_FollowsHappyFlow()
        {
            var        blockHash     = "000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        transactions  = new List <AbstractTransaction>()
            {
                new StateTransaction(null, "to", null, 0, 5000, 1, TransactionAction.ClaimCoinbase.ToString(), null, 0)
            };
            var blockToTest = new Block(new BlockHeader(_netId, 1, "merkleroot", 1, "block3"), transactions);

            var blockchain = new Blockchain(new List <Block>()
            {
                new Block(new BlockHeader(_netId, 1, "merkleroot", 1, "").Finalize("block1", "privkey"), transactions),
                new Block(new BlockHeader(_netId, 1, "merkleroot", 3, "block1").Finalize("block2", "privkey"), transactions),
                new Block(new BlockHeader(_netId, 1, "merkleroot", 10, "block2").Finalize("block3", "privkey"), transactions)
            }, _netId);

            blockToTest.Header.Finalize(blockHash, "signature");
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(blockHash);
            _timestamperMock.Setup(m => m.GetCurrentUtcTimestamp()).Returns(1);
            _signerMock.Setup(m => m.SignatureIsValid("signature", blockHash, "to")).Returns(true);
            _transactionValidatorMock.Setup(m => m.CalculateMerkleRoot(transactions)).Returns("merkleroot");
            _transactionValidatorMock.Setup(m => m.ValidateTransaction(transactions.First()));

            sut.ValidateBlock(blockToTest, currentTarget, blockchain, true, true);

            Assert.AreEqual(blockToTest, blockchain.Blocks.Last());
            Assert.AreEqual(4, blockchain.Blocks.Count());
        }
Beispiel #2
0
        public void BlockIsValid_ThrowsException_PreviousHashDoesNotExist()
        {
            var        blockHash     = "000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        transactions  = new List <AbstractTransaction>()
            {
                new StateTransaction(null, "to", null, 0, 5000, 1, TransactionAction.ClaimCoinbase.ToString(), null, 0)
            };
            var blockchain = new Blockchain(new List <Block>()
            {
                new Block(new BlockHeader(_netId, 1, "merkleroot", 1, ""), transactions)
            }, _netId);
            var blockToTest = new Block(new BlockHeader(_netId, 1, "merkleroot", 1, ""), transactions);

            blockToTest.Header.Finalize(blockHash, "signature");
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(blockHash);
            _timestamperMock.Setup(m => m.GetCurrentUtcTimestamp()).Returns(1);
            _signerMock.Setup(m => m.SignatureIsValid("signature", blockHash, "to")).Returns(true);
            _transactionValidatorMock.Setup(m => m.CalculateMerkleRoot(transactions)).Returns("merkleroot");

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, blockchain, true, true)
                );

            Assert.AreEqual("Previous blockhash does not exist in our chain", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #3
0
        public void BlockIsValid_ThrowsException_ExistingBlockWithHigherDifficulty()
        {
            var        lowerBlockHash = "000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            var        highBlockHash  = "00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            BigDecimal currentTarget  = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut            = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        transactions   = new List <AbstractTransaction>()
            {
                new StateTransaction(null, "to", null, 0, 5000, 1, TransactionAction.ClaimCoinbase.ToString(), null, 0)
            };
            var blockToTest = new Block(new BlockHeader(_netId, 1, "merkleroot", 16, "block2"), transactions); // Also point to block 2

            var blockchain = new Blockchain(new List <Block>()
            {
                new Block(new BlockHeader(_netId, 1, "merkleroot", 1, "").Finalize("block1", "privkey"), transactions),
                new Block(new BlockHeader(_netId, 1, "merkleroot", 3, "block1").Finalize("block2", "privkey"), transactions),
                new Block(new BlockHeader(_netId, 1, "merkleroot", 10, "block2").Finalize(highBlockHash, "privkey"), transactions)
            }, _netId);

            blockToTest.Header.Finalize(lowerBlockHash, "signature");
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(lowerBlockHash);
            _timestamperMock.Setup(m => m.GetCurrentUtcTimestamp()).Returns(1);
            _signerMock.Setup(m => m.SignatureIsValid("signature", lowerBlockHash, "to")).Returns(true);
            _transactionValidatorMock.Setup(m => m.CalculateMerkleRoot(transactions)).Returns("merkleroot");
            _transactionValidatorMock.Setup(m => m.ValidateTransaction(transactions.First()));

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, blockchain, true, true)
                );

            Assert.AreEqual("Another block with higher difficulty points to the same PreviousHash", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #4
0
        public void BlockIsValid_ThrowsException_NotFinalized()
        {
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        blockToTest   = new Block(new BlockHeader(_netId, 1, "abc", 1, ""), new List <AbstractTransaction>()); // Block is not finalized
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain(_netId), true, true)
                );

            Assert.AreEqual("Block is not hashed or signed or hashed properly", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #5
0
        public void BlockIsValid_ThrowsException_HashDoesNotEqual()
        {
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        blockToTest   = new Block(new BlockHeader(_netId, 1, "abc", 1, ""), new List <AbstractTransaction>());

            blockToTest.Header.Finalize("abc", "signature"); // Invalid block hash
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns("otherhash");

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain(_netId), true, true)
                );

            Assert.AreEqual("The hash property of the block is not equal to the calculated hash", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #6
0
        public void BlockIsValid_ThrowsException_HashHasHighValueWithLeadingZero()
        {
            var        blockHash     = "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; // High hash value
            BigDecimal currentTarget = BigInteger.Parse("0000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        blockToTest   = new Block(new BlockHeader(_netId, 1, "abc", 1, ""), new List <AbstractTransaction>());

            blockToTest.Header.Finalize(blockHash, "signature");
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(blockHash);

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain(_netId), true, true)
                );

            Assert.AreEqual("Hash value is equal or higher than the current target", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #7
0
        public void BlockIsValid_ThrowsException_EmptyTransactionList()
        {
            var        blockHash     = "000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        blockToTest   = new Block(new BlockHeader(_netId, 1, "abc", 1, ""), new List <AbstractTransaction>());

            blockToTest.Header.Finalize(blockHash, "signature");
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(blockHash);
            _timestamperMock.Setup(m => m.GetCurrentUtcTimestamp()).Returns(1);

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain(_netId), true, true)
                );

            Assert.AreEqual("Transaction list cannot be empty", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #8
0
        public void BlockIsValid_ThrowsException_TimestampIsTooLate()
        {
            var        blockHash     = "000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        blockToTest   = new Block(new BlockHeader(_netId, 1, "abc", BlockchainConstants.MaximumTimestampOffset + 10, ""), new List <AbstractTransaction>());

            blockToTest.Header.Finalize(blockHash, "signature");
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(blockHash);
            _timestamperMock.Setup(m => m.GetCurrentUtcTimestamp()).Returns(1); // The blockToTest's timestamp is too late

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain(_netId), true, true)
                );

            Assert.AreEqual("Timestamp is not within the acceptable time range", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #9
0
        public void BlockIsValid_ThrowsException_HashValueEqualsTargetWithLeadingZero()
        {
            // The currentTarget is the exact same hash value as the blockToTest header.
            var        blockHash     = "078ECE2577907E270349C3FD60F1B1B28B233BE6DC936C2415624E65C6159E1E";
            BigDecimal currentTarget = BigInteger.Parse(blockHash, NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        blockToTest   = new Block(new BlockHeader(_netId, 1, "abc", 1, ""), new List <AbstractTransaction>());

            blockToTest.Header.Finalize(blockHash, "signature"); // The same as target
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(blockHash);

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain(_netId), true, true)
                );

            Assert.AreEqual("Hash value is equal or higher than the current target", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #10
0
        public void BlockIsValid_ThrowsException_DifferentNetwork()
        {
            var        blockHash     = "000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        transactions  = new List <AbstractTransaction>()
            {
                new StateTransaction(null, "to", null, 0, 5000, 1, TransactionAction.ClaimCoinbase.ToString(), null, 0)
            };
            var blockToTest = new Block(new BlockHeader("network1", 1, "merkleroot", 1, ""), transactions);

            blockToTest.Header.Finalize(blockHash, "signature");

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain("network2"), true, true)
                );

            Assert.AreEqual("Block comes from a different network", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }
Beispiel #11
0
        public void BlockIsValid_ThrowsException_FirstTransactionNotCoinbase()
        {
            var        blockHash     = "000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
            BigDecimal currentTarget = BigInteger.Parse("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.HexNumber);
            var        sut           = new PowBlockValidator(_blockFinalizerMock.Object, _transactionValidatorMock.Object, _timestamperMock.Object, _signerMock.Object);
            var        transactions  = new List <AbstractTransaction>()
            {
                new StateTransaction("from", "tp", null, 0, 1, 1, TransactionAction.TransferToken.ToString(), null, 1)
            };
            var blockToTest = new Block(new BlockHeader(_netId, 1, "merkleroot", 1, ""), transactions);

            blockToTest.Header.Finalize(blockHash, "signature");
            _blockFinalizerMock.Setup(m => m.CalculateHash(blockToTest)).Returns(blockHash);
            _timestamperMock.Setup(m => m.GetCurrentUtcTimestamp()).Returns(1);
            _transactionValidatorMock.Setup(m => m.CalculateMerkleRoot(transactions)).Returns("merkleroot");

            var ex = Assert.ThrowsException <BlockRejectedException>(
                () => sut.ValidateBlock(blockToTest, currentTarget, new Blockchain(_netId), true, true)
                );

            Assert.AreEqual("First transaction is not coinbase", ex.Message);
            Assert.AreEqual(blockToTest, ex.Block);
        }