Exemple #1
0
    def test_transactionCreation(self):
        # Invalid number of addresses for amounts
        with self.assertRaises(AssertionError):
            transaction.createTransaction(outputAddresses=[public1, public2],
                                          outputAmounts=[1000],
                                          timestamp=time.time())

        # Invalid output amount
        with self.assertRaises(AssertionError):
            transaction.createTransaction(outputAddresses=[public1],
                                          outputAmounts=[0],
                                          timestamp=time.time())
Exemple #2
0
    def test_serialization(self):
        h = "2ac9a6746aca543af8dff39894cfe8173afba21eb01c6fae33d52947222855ef"

        public = TestBlock.public1
        private = TestBlock.private1

        t1 = transaction.createTransaction(
            outputAddresses=[public],
            outputAmounts=[700],
            timestamp=time.time(),
            previousTransactionHashes=[h],  # This is just a dummy value
            previousOutputIndices=[0],
            privateKeys=[private]
        )

        b = block.Block(32, 32, [t1], 0, h)
        serialized = b.asJSON()
        deserialized = block.createFromJSON(serialized)
        self.assertTrue(b == deserialized)

        # Corrupt t1 before serialization, make sure that it cannot be
        # deserialized.
        t1.outputs[-1].amount = 1  # Corrupt the transaction data.
        b = block.Block(32, 32, [t1], 0, h)
        serialized = b.asJSON()
        print("_____")
        with self.assertRaises(block.BlockException):
            block.createFromJSON(serialized)
Exemple #3
0
    def test_validSyntax(self):
        timestamp = time.time()
        tx1 = transaction.createTransaction([public1], [1000], timestamp)
        tx2 = transaction.createTransaction([public2, public3], [500, 500],
                                            timestamp, [tx1.hash], [0],
                                            [private1])
        txList = [tx1, tx2]
        self.assertTrue(
            chain.verifyTransactionsSyntax(txList)[0],
            "Test valid transactions")

        # Test duplicate transactions
        txList = [tx1, tx1]
        self.assertFalse(
            chain.verifyTransactionsSyntax(txList)[0],
            "Test duplicate transactions")

        # Test invalid hash
        temp = tx1.hash
        txList = [tx1, tx2]
        tx1.hash = tx2.hash
        self.assertFalse(
            chain.verifyTransactionsSyntax(txList)[0], "Test invalid hash")
        tx1.hash = temp

        # Test duplicate references
        tx3 = transaction.createTransaction([public2], [1000], timestamp,
                                            [tx1.hash], [0], [private1])
        txList = [tx1, tx2, tx3]
        self.assertFalse(
            chain.verifyTransactionsSyntax(txList)[0],
            "Test duplicate references")

        tx4 = transaction.createTransaction([public2], [1000], timestamp)
        txList = [tx1, tx2, tx4]

        self.assertFalse(
            chain.verifyTransactionsSyntax(txList)[0],
            "Test multiple coinbase transaction list")

        tx4 = transaction.createTransaction([public2, public3], [1000, 1000],
                                            timestamp)
        txList = [tx2, tx4]
        self.assertFalse(
            chain.verifyTransactionsSyntax(txList)[0],
            "Test multi-output coinbase")
Exemple #4
0
def genesisBlock() -> Block:
    """
    Returns the hard-coded genesis block, which is the first Block in
    everybody's chain.
    """
    f = open("./core/genesisKey/publicKey.der")
    genesisAddress = f.read()
    f.close()
    genesisTimestamp = 1514689482.0

    genesisTransaction = createTransaction(
        outputAddresses=[genesisAddress],
        outputAmounts=[1000],
        timestamp=genesisTimestamp
    )

    return Block(
        index=0,
        timestamp=1514689482.0,
        transactions=[genesisTransaction],
        noonce=0,
        previousHash=""
    )
Exemple #5
0
    def test_validUTXO(self):
        manager = chain.UTXOManager()
        # 1 2 and 3 should all start with 1000 SPC
        timestamp = time.time()
        tx1 = transaction.createTransaction([public1], [1000], timestamp)
        tx2 = transaction.createTransaction([public2], [1000], timestamp)
        tx3 = transaction.createTransaction([public3], [1000], timestamp)

        self.assertTrue(manager.canSpend(tx1))
        self.assertTrue(manager.canSpend(tx2))
        self.assertTrue(manager.canSpend(tx3))

        manager.spend(tx1)
        manager.spend(tx2)
        manager.spend(tx3)

        # 1 gives 500 to 2 and 500 to 1
        tx4 = transaction.createTransaction(
            outputAddresses=[public2, public1],
            outputAmounts=[500, 500],
            timestamp=time.time(),
            previousTransactionHashes=[tx1.hash],
            previousOutputIndices=[0],
            privateKeys=[private1])

        self.assertTrue(chain.verifyTransactionsSyntax([tx4]))
        self.assertTrue(manager.canSpend(tx4)[0])
        manager.spend(tx4)

        # 2 gives 1500 to 3, 1 gives 500 to 3
        tx5 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[1500],
            timestamp=time.time(),
            previousTransactionHashes=[tx2.hash, tx4.hash],
            previousOutputIndices=[0, 0],
            privateKeys=[private2, private2])
        self.assertTrue(manager.canSpend(tx5)[0])

        tx6 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[500],
            timestamp=time.time(),
            previousTransactionHashes=[tx4.hash],
            previousOutputIndices=[1],
            privateKeys=[private1])

        self.assertTrue(manager.canSpend(tx6)[0])
        self.assertTrue(chain.verifyTransactionsSyntax([tx5, tx6]))
        manager.spend(tx5)
        manager.spend(tx6)

        # Revert the 500 transaction to 3. 3 should now have 2500,
        # 1 should now have 500.
        manager.revert(tx6)

        # Should not be able to spend 3000
        tx7 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[3000],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash, tx5.hash, tx6.hash],
            previousOutputIndices=[0, 0, 0],
            privateKeys=[private3, private3, private3])
        self.assertFalse(manager.canSpend(tx7)[0])

        # Should be able to spend 2500 instead.
        tx7 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[2500],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash, tx5.hash],
            previousOutputIndices=[0, 0],
            privateKeys=[private3, private3])
        self.assertTrue(manager.canSpend(tx7)[0])

        # Give the 500 back to 3 from 1.
        manager.spend(tx6)

        tx7 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[3000],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash, tx5.hash, tx6.hash],
            previousOutputIndices=[0, 0, 0],
            privateKeys=[private3, private3, private3])
        self.assertTrue(manager.canSpend(tx7)[0])

        # Use invald private key
        tx7 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[3000],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash],
            previousOutputIndices=[0],
            privateKeys=[private2])
        self.assertFalse(manager.canSpend(tx7)[0])
Exemple #6
0
    def test_createLongChainValid(self):
        # Genesis has 1000 coins
        testChain = chain.Chain()
        tx1 = transaction.createTransaction([public1], [1000], time.time())
        tx2 = transaction.createTransaction(
            outputAddresses=[public1],
            outputAmounts=[1000],
            timestamp=time.time(),
            previousTransactionHashes=[tx1.hash],
            previousOutputIndices=[0],
            privateKeys=[private1])

        # 1 has 1000 SPC
        b1 = mine.generateNextBlock(testChain.head, [tx1, tx2])
        testChain.addBlock(b1)

        # 1 gives 400 to 2 and 600 to 1
        tx3 = transaction.createTransaction(
            outputAddresses=[public2, public1],
            outputAmounts=[400, 600],
            timestamp=time.time(),
            previousTransactionHashes=[tx2.hash],
            previousOutputIndices=[0],
            privateKeys=[private1])
        b2 = mine.generateNextBlock(testChain.head, [tx3])
        testChain.addBlock(b2)

        # Test that an invalid transaction does not mess up the state
        # 2 gives 400 to 3
        tx4 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[400],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash],
            previousOutputIndices=[0],
            privateKeys=[private2])
        # 1 tries to give not enough money to 3
        badTx = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[10],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash],
            previousOutputIndices=[1],
            privateKeys=[private1])

        b3 = mine.generateNextBlock(testChain.head, [badTx, tx4])
        with self.assertRaises(chain.UTXOException):
            testChain.addBlock(b3)
        assert testChain.head == b2

        # Proper transaction. 3 should now have 400 from 2 and 600 from 1
        tx5 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[600],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash],
            previousOutputIndices=[1],
            privateKeys=[private1])

        b3 = mine.generateNextBlock(testChain.head, [tx5, tx4])
        testChain.addBlock(b3)
        assert testChain.head == b3

        # Create a fork off b2. It should be added to the chain.
        # 2 gives 200 to 2 and 100 to 3. This is techincally invalid.
        tx4alt = transaction.createTransaction(
            outputAddresses=[public3, public2],
            outputAmounts=[100, 200],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash],
            previousOutputIndices=[0],
            privateKeys=[private2])
        b3alt = mine.generateNextBlock(b2, [tx4alt])
        testChain.addBlock(b3alt)

        # 2 gives 200 to 1
        tx5alt = transaction.createTransaction(
            outputAddresses=[public1],
            outputAmounts=[200],
            timestamp=time.time(),
            previousTransactionHashes=[tx4alt.hash],
            previousOutputIndices=[1],
            privateKeys=[private2])
        b4alt = mine.generateNextBlock(b3alt, [tx5alt])
        with self.assertRaises(chain.UTXOException):
            testChain.addBlock(b4alt)

        with self.assertRaises(chain.NoParentException):
            testChain.addBlock(b4alt)

        # The fork was invalid. Try adding it again,
        # except
        tx4alt = transaction.createTransaction(
            outputAddresses=[public3, public2],
            outputAmounts=[200, 200],
            timestamp=time.time(),
            previousTransactionHashes=[tx3.hash],
            previousOutputIndices=[0],
            privateKeys=[private2])
        b3alt = mine.generateNextBlock(b2, [tx4alt])
        testChain.addBlock(b3alt)

        tx5alt = transaction.createTransaction(
            outputAddresses=[public1],
            outputAmounts=[200],
            timestamp=time.time(),
            previousTransactionHashes=[tx4alt.hash],
            previousOutputIndices=[1],
            privateKeys=[private2])
        b4alt = mine.generateNextBlock(b3alt, [tx5alt])
        testChain.addBlock(b4alt)
        assert testChain.head == b4alt
Exemple #7
0
    def test_transactionInputValidation(self):
        privateKey = private1
        publicKey = public1
        """
        Simulated transaction
        1 gets 1000 bitcoin
        1 sends 700 bitcoin to 2 and 300 bitcoin to 3
        2 sends 700 bitcoin to 3
        3 sends 1000 bitcoin to 1
        """

        firstTransaction = transaction.createTransaction(
            outputAddresses=[publicKey],
            outputAmounts=[1000],
            timestamp=time.time())

        # Create a valid input based on that first transaction
        nextTransaction = transaction.createTransaction(
            outputAddresses=[public2, public3],
            outputAmounts=[700, 300],
            timestamp=time.time(),
            previousTransactionHashes=[firstTransaction.hash],
            previousOutputIndices=[0],
            privateKeys=[privateKey])

        self.assertTrue(
            transaction.verifyTransactionInput(firstTransaction,
                                               nextTransaction, 0)[0])

        transactionFrom2to3 = transaction.createTransaction(
            outputAddresses=[public3],
            outputAmounts=[700],
            timestamp=time.time(),
            previousTransactionHashes=[nextTransaction.hash],
            previousOutputIndices=[0],
            privateKeys=[private2])

        self.assertTrue(
            transaction.verifyTransactionInput(nextTransaction,
                                               transactionFrom2to3, 0)[0])

        finalTransaction = transaction.createTransaction(
            outputAddresses=[public1],
            outputAmounts=[10000],
            timestamp=time.time(),
            previousTransactionHashes=[
                transactionFrom2to3.hash, nextTransaction.hash
            ],
            previousOutputIndices=[0, 1],
            privateKeys=[private3, private3])

        self.assertTrue(
            transaction.verifyTransactionInput(nextTransaction,
                                               finalTransaction, 1)[0])
        self.assertTrue(
            transaction.verifyTransactionInput(transactionFrom2to3,
                                               finalTransaction, 0)[0])

        # Forger tries to create a transaction with an output that they don't
        # own the public key to.
        validTransaction = transaction.createTransaction(
            outputAddresses=[publicKey],
            outputAmounts=[1000],
            timestamp=time.time(),
            previousTransactionHashes=[firstTransaction.hash],
            previousOutputIndices=[0],
            privateKeys=[privateKey])

        forgerTransaction = validTransaction
        forgerTransaction.outputs[0].address = public3

        self.assertFalse(
            transaction.verifyTransactionInput(firstTransaction,
                                               forgerTransaction, 0)[0])