def test_fake_ownership(self):
        # Trying to spend someone else's output
        # (Re)Starting from GenBlock
        genesis_block = classes.GenesisBlock(self.address)
        fullnode_api.add_genesis_block(genesis_block)

        # Tx1 -> We send it to an address belonging to seed
        dict_of_inputs = {genesis_block.block_content[0].txhash: 0}
        dict_of_outputs = {self.address: 100}
        first_tx = classes.Transaction(dict_of_inputs, dict_of_outputs)
        first_tx.sign(self.seed)

        # Block1
        first_block = classes.Block([first_tx])
        first_mined_block = fullnode_api.mine_block(first_block)

        fullnode_api.add_block_to_db(first_mined_block)

        # Tx2 -> we try to spend someone else's output since we sign with seed2
        dict_of_inputs2 = {first_mined_block.block_content[0].txhash: 0}
        dict_of_outputs2 = {self.address3: 100}
        second_tx = classes.Transaction(dict_of_inputs2, dict_of_outputs2)
        second_tx.sign(self.seed2)

        # Block2
        second_block = classes.Block([second_tx])
        second_mined_block = fullnode_api.mine_block(second_block)

        fullnode_api.add_block_to_db(second_mined_block)

        with self.assertRaises(exceptions.ValidationError):
            validation.validate_block(second_mined_block)
    def test_wrong_input(self):
        # Trying to spend inexistant input
        # (Re)Starting from GenBlock
        genesis_block = classes.GenesisBlock(self.address)
        fullnode_api.add_genesis_block(genesis_block)

        # Tx1
        dict_of_inputs = {genesis_block.block_content[0].txhash: 0}
        dict_of_outputs = {self.address2: 100}
        first_tx = classes.Transaction(dict_of_inputs, dict_of_outputs)
        first_tx.sign(self.seed)

        # Block1
        first_block = classes.Block([first_tx])
        first_mined_block = fullnode_api.mine_block(first_block)

        fullnode_api.add_block_to_db(first_mined_block)

        # Tx2 -> we try to spend an unexisting input
        dict_of_inputs2 = {first_mined_block.block_content[0].txhash: 1}
        dict_of_outputs2 = {self.address3: 100}
        second_tx = classes.Transaction(dict_of_inputs2, dict_of_outputs2)
        second_tx.sign(self.seed2)

        # Block2
        second_block = classes.Block([second_tx])
        second_mined_block = fullnode_api.mine_block(second_block)

        fullnode_api.add_block_to_db(second_mined_block)

        with self.assertRaises(
                exceptions.APIError
        ):  # Since the exceptions comes from one level deeper.
            validation.validate_block(second_mined_block)
    def test_incorrect_amounts(self):
        # Trying to spend more than what we have in the inputs
        # (Re)Starting from GenBlock
        genesis_block = classes.GenesisBlock(self.address)
        fullnode_api.add_genesis_block(genesis_block)

        # Tx1
        dict_of_inputs = {genesis_block.block_content[0].txhash: 0}
        dict_of_outputs = {self.address2: 100}
        first_tx = classes.Transaction(dict_of_inputs, dict_of_outputs)
        first_tx.sign(self.seed)

        # Block1
        first_block = classes.Block([first_tx])
        first_mined_block = fullnode_api.mine_block(first_block)

        fullnode_api.add_block_to_db(first_mined_block)

        # Tx2 -> We try to put 101 as output amount
        dict_of_inputs2 = {first_mined_block.block_content[0].txhash: 0}
        dict_of_outputs2 = {self.address3: 101}
        second_tx = classes.Transaction(dict_of_inputs2, dict_of_outputs2)
        second_tx.sign(self.seed2)

        # Block2
        second_block = classes.Block([second_tx])
        second_mined_block = fullnode_api.mine_block(second_block)

        fullnode_api.add_block_to_db(second_mined_block)

        with self.assertRaises(exceptions.ValidationError):
            validation.validate_block(second_mined_block)
    def setUp(self):
        # Seed&Address (2 pairs)
        self.seed = crypto.new_seed()
        self.address = crypto.get_address(self.seed)
        self.verifying_key_string = crypto._get_verifying_key_string(self.seed)

        self.seed2 = crypto.new_seed()
        self.address2 = crypto.get_address(self.seed2)
        self.verifying_key_string2 = crypto._get_verifying_key_string(
            self.seed2)

        self.address3 = self.address2  # For testing purposes only

        # Db
        self.db_path = 'database/db_test'
        database.init_database_path(self.db_path)

        # GenBlock
        self.genesis_block = classes.GenesisBlock(self.address)
        fullnode_api.add_genesis_block(self.genesis_block)

        # Tx1
        self.dict_of_inputs = {self.genesis_block.block_content[0].txhash: 0}
        self.dict_of_outputs = {self.address2: 100}
        self.first_tx = classes.Transaction(self.dict_of_inputs,
                                            self.dict_of_outputs)
        self.first_tx.sign(self.seed)

        # Block1
        self.first_block = classes.Block([self.first_tx])
        self.first_mined_block = fullnode_api.mine_block(self.first_block)

        fullnode_api.add_block_to_db(self.first_mined_block)

        # Tx2
        self.dict_of_inputs2 = {
            self.first_mined_block.block_content[0].txhash: 0
        }
        self.dict_of_outputs2 = {self.address3: 100}
        self.second_tx = classes.Transaction(self.dict_of_inputs2,
                                             self.dict_of_outputs2)
        self.second_tx.sign(self.seed2)

        # Block2
        self.second_block = classes.Block([self.second_tx])
        self.second_mined_block = fullnode_api.mine_block(self.second_block)

        fullnode_api.add_block_to_db(self.second_mined_block)
 def test_transaction_signing(self):
     first_tx = classes.Transaction(self.dict_of_inputs,
                                    self.dict_of_outputs)
     first_tx.sign(self.seed)
     self.assertTrue(
         crypto.verify_signing(first_tx.txhash, first_tx.signature,
                               first_tx.verifying_key))
    def test_double_spend(self):
        # (Re)Starting from GenBlock
        genesis_block = classes.GenesisBlock(self.address)
        fullnode_api.add_genesis_block(genesis_block)

        # Tx1
        dict_of_inputs = {genesis_block.block_content[0].txhash: 0}
        dict_of_outputs = {self.address2: 100}
        first_tx = classes.Transaction(dict_of_inputs, dict_of_outputs)
        first_tx.sign(self.seed)

        # Block1
        first_block = classes.Block([first_tx])
        first_mined_block = fullnode_api.mine_block(first_block)

        fullnode_api.add_block_to_db(first_mined_block)

        # Tx2
        dict_of_inputs2 = {first_mined_block.block_content[0].txhash: 0}
        dict_of_outputs2 = {self.address3: 100}
        second_tx = classes.Transaction(dict_of_inputs2, dict_of_outputs2)
        second_tx.sign(self.seed2)

        # Block2
        second_block = classes.Block([second_tx])
        second_mined_block = fullnode_api.mine_block(second_block)

        fullnode_api.add_block_to_db(second_mined_block)

        # Tx3 -> We try to double spend the same input as we spent in the previous block
        dict_of_inputs3 = {first_mined_block.block_content[0].txhash: 0}
        dict_of_outputs3 = {self.address3: 100}
        third_tx = classes.Transaction(dict_of_inputs3, dict_of_outputs3)
        third_tx.sign(self.seed2)

        third_block = classes.Block([third_tx])
        third_mined_block = fullnode_api.mine_block(third_block)

        with self.assertRaises(exceptions.ValidationError):
            validation.validate_block(third_mined_block)
예제 #7
0
def create_transaction(from_address, to_address, amount=0):
    """Creates an unsigned transaction. If amount=0, it spends everything.
    If not everything is spend, returns the remainder to the sender."""
    global stack_of_used_inputs
    valid_inputs_list = get_valid_inputs_from_address(from_address)
    balance = get_balance_from_address(from_address)

    dict_of_inputs = {}
    dict_of_outputs = {}

    if amount == 0:  # We spend everything
        for inpt in valid_inputs_list:
            dict_of_inputs[inpt[0]] = inpt[1]
        dict_of_outputs[to_address] = amount

    if balance == amount:  # We spend everything
        for inpt in valid_inputs_list:
            dict_of_inputs[inpt[0]] = inpt[1]
        dict_of_outputs[to_address] = amount

    if balance > amount:  # We return part of the amount to the sender
        for inpt in valid_inputs_list:
            dict_of_inputs[inpt[0]] = inpt[
                1]  # Even when not spending all the balance, we burn all the inputs
        dict_of_outputs[to_address] = amount
        dict_of_outputs[from_address] = balance - amount

    if balance < amount:
        raise exceptions.APIError(
            "Balance of address not sufficient to create transaction")

    for txhash, pos in dict_of_inputs.items(
    ):  # We update the local state of the ledger to include the new tx.
        stack_of_used_inputs.append((txhash, pos))

    if not dict_of_inputs:
        raise exceptions.APIError(
            "Trying to create a transaction with no inputs.")

    return classes.Transaction(dict_of_inputs, dict_of_outputs)