Example #1
0
def test_calculate_balance():
    blockchain = Blockchain()
    wallet = Wallet()

    assert Wallet.calculate_balance(blockchain,
                                    wallet.address) == STARTING_BALANCE

    amount = 20
    transacion = Transaction(wallet, 'recipient', amount)
    blockchain.add_block([transacion.to_json()])
    assert Wallet.calculate_balance(
        blockchain, wallet.address) == STARTING_BALANCE - amount

    recieved_amount1 = 10
    recieved_transaction1 = Transaction(Wallet(), wallet.address,
                                        recieved_amount1)
    recieved_amount2 = 40
    recieved_transaction2 = Transaction(Wallet(), wallet.address,
                                        recieved_amount2)
    blockchain.add_block(
        [recieved_transaction1.to_json(),
         recieved_transaction2.to_json()])
    assert Wallet.calculate_balance(
        blockchain, wallet.address
    ) == STARTING_BALANCE - amount + recieved_amount1 + recieved_amount2
def test_calculate_balance():
    blockchain = Blockchain()
    wallet = Wallet()

    assert wallet.calculate_balance(blockchain,
                                    wallet.address) == STARTING_BALANCE

    amount = 34
    transaction = Transaction(wallet, 'recipient', amount)
    blockchain.add_block([transaction.to_json()])

    assert wallet.calculate_balance(blockchain, wallet.address) ==\
         STARTING_BALANCE - amount

    received_amount_1 = 40
    received_transaction_1 = Transaction(Wallet(), wallet.address,
                                         received_amount_1)
    received_amount_2 = 110
    received_transaction_2 = Transaction(Wallet(), wallet.address,
                                         received_amount_2)

    blockchain.add_block(
        [received_transaction_1.to_json(),
         received_transaction_2.to_json()])

    assert wallet.calculate_balance(blockchain, wallet.address) ==\
         STARTING_BALANCE - amount + received_amount_1 +received_amount_2
def test_calculate_balance():
    blockchain = Blockchain()
    wallet = Wallet()

    # NEW: new Wallet() `wallet` should have initial balance
    assert Wallet.calculate_balance(blockchain,
                                    wallet.address) == INITIAL_BALANCE

    sent_amt = 50
    outgoing_transaction = Transaction(
        wallet, "a13b2bf4", sent_amt)  # send to `wallet` from "a13b2bf4"
    blockchain.add_block([outgoing_transaction.serialize_to_json()])
    # SEND: `wallet` should have initial balance sans amt
    assert Wallet.calculate_balance(
        blockchain, wallet.address) == INITIAL_BALANCE - sent_amt

    received_amt_1 = 25
    incoming_transaction_1 = Transaction(
        Wallet(), wallet.address,
        received_amt_1)  # receive by `wallet` from new Wallet()
    received_amt_2 = 77
    incoming_transaction_2 = Transaction(Wallet(), wallet.address,
                                         received_amt_2)
    blockchain.add_block([
        incoming_transaction_1.serialize_to_json(),
        incoming_transaction_2.serialize_to_json()
    ])
    # RECEIVE: `wallet` should have initial balance plus incoming amt(s)
    assert Wallet.calculate_balance(
        blockchain, wallet.address
    ) == INITIAL_BALANCE - sent_amt + received_amt_1 + received_amt_2
Example #4
0
  def is_valid_transaction_chain(chain):
    """
    enforce the rules of a chain composed of blocks of transactions
      - each transaction must only appear once in a chain
      - only 1 mining reward per block
      - each transaction must be valid
    """
    transaction_ids=set()
    for i in range(len(chain)):
      block = chain[i]
      has_mining_reward = False
      for transaction_json in block.data:
        transaction = Transaction.from_json(transaction_json)
        if transaction.id in transaction_ids:
          raise Exception(f'Transaction {transaction.id} is not unique!')
        
        transaction_ids.add(transaction.id)

        if transaction.input == MINING_REWARD_INPUT:
          if has_mining_reward == True:
            raise Exception('There can only be one mining reward per block!'+f' Check block with hash {block.hash}')
          has_mining_reward = True
        else:
          blockchain_history = Blockchain()
          blockchain_history.chain = chain[0:i]

          balance_history = Wallet.calculate_balance(blockchain_history,transaction.input['address'])
    
          if balance_history != transaction.input['amount']:
            raise Exception(f'Transaction {transaction.id} has an invalid input amount!')

          Transaction.is_valid_transaction(transaction)
Example #5
0
    def is_valid_transaction_chain(chain):
        transaction_ids = set()
        for i in range(len(chain)):
            block = chain[i]
            has_mining_reward = False
            for transaction_json in block.data:
                transaction = Transaction.from_json(transaction_json)
                if transaction.id in transaction_ids:
                    raise Exception(
                        f'Transaction {transaction.id} is not unique')
                transaction_ids.add(transaction.id)
                if transaction.input == MINING_REWARD_INPUT:
                    if has_mining_reward:
                        raise Exception('There can only be one mining reward per block'\
                        f'Check block with hash:{block.hash}'
                        )
                    has_mining_reward = True

                else:
                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]
                    historic_balance = Wallet.calculate_balance(
                        historic_blockchain, transaction.input['address'])
                    if historic_balance != transaction.input['amount']:
                        raise Exception(
                            'Transaction {transaction.id} has an invalid input amount'
                        )
                Transaction.is_valid_transaction(transaction)
Example #6
0
    def is_transaction_chain_valid(chain):
        """
        Validate chain with blocks of transactions
         -- Only one reward per transaction.
         -- Each transaction must only apprear once in chain.
        """
        transaction_ids = []
        for i in range(len(chain)):
            block = chain[i]
            contains_mining_reward = False
            for transaction_json in block.data:
                transaction_obj = Transaction.from_json(transaction_json)

                if transaction_obj.id in transaction_ids:
                    raise Exception(
                        f"Transaction: {transaction_obj.id} is not unique")

                transaction_ids.append(transaction_obj.id)

                if transaction_obj.input == MINIING_REWARD_INPUT:
                    if contains_mining_reward:
                        raise Exception(
                            f'Duplicate mining reward in block: {block.hash}')
                    contains_mining_reward = True
                else:
                    blockchain_tillnow = BlockChain()
                    blockchain_tillnow.chain = chain[0:i]
                    balance_tillnow = Wallet.calculate_balance(
                        blockchain_tillnow, transaction_obj.input["address"])
                    if balance_tillnow != transaction_obj.input["amount"]:
                        raise Exception(
                            f"Transaction: {transaction_obj.id} has invalid input"
                        )

                Transaction.is_transaction_valid(transaction_obj)
def test_wallet_balance_amount():
	wallet = Wallet()
	blockchain = Blockchain()
	amount = 34
	tr1 = Transactions(wallet, 'recp1', amount)
	blockchain.add_block([tr1.to_json()])
	assert Wallet.calculate_balance(blockchain, wallet.address) == STARTING_BALANCE - amount
    def is_valid_transaction_chain(chain):
        """
        Enforce the rules of a chain composed of blocks of transactions
         - each transaction must only appear once in the chain
         - There can be only one mining reward per block
         - Each transaction must be valid
        """
        transaction_ids = set()
        for i in range(len(chain)): 
            block = chain[i]
            has_mining_reward = False

            for transaction_json in block.data:
                transaction = Transaction.from_json(transaction_json)

                if transaction.id in transaction_ids:
                    raise Exception(f'Transaction: {transaction.id} is not unique')

                transaction_ids.add(transaction.id)

                if transaction.input == MINING_REWARD_INPUT:
                    if has_mining_reward:
                        raise Exception(f'There can be only one mining reward per block check this block: {block.hash}')
                    has_mining_reward = True

                else:
                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]
                    historic_balance = Wallet.calculate_balance(historic_blockchain, transaction.input['address'])
                    if historic_balance != transaction.input['amount']:
                        raise Exception(f'Transaction {transaction.id} has '\
                            'invalid input amount')
                    Transaction.transaction_is_valid(transaction)
Example #9
0
def test_calculate_balance():
    blockchain = BlockChain()
    wallet = Wallet()
    assert wallet.calculate_balance(blockchain,
                                    wallet.address) == STARTING_BALANCE

    sent_amount = 100
    transaction = Transaction(wallet, "abcd", sent_amount)
    blockchain.add_block([transaction.to_json()])
    assert wallet.calculate_balance(
        blockchain, wallet.address) == STARTING_BALANCE - sent_amount

    received_amount_1 = 100
    received_1 = Transaction(Wallet(), wallet.address, received_amount_1)

    received_amount_2 = 100
    received_2 = Transaction(Wallet(), wallet.address, received_amount_2)

    blockchain.add_block([received_1.to_json(), received_2.to_json()])
    assert wallet.calculate_balance(blockchain, wallet.address) == STARTING_BALANCE - \
        sent_amount + received_amount_1 + received_amount_2
Example #10
0
def test_calculate_balance():
    blockchain = Blockchain()
    wallet = Wallet()
    assert Wallet.calculate_balance(blockchain,
                                    wallet.address) == wallet.balance
    transaction = Transaction(wallet, 'recipient', 30)
    blockchain.add_block([transaction.to_json()])
    assert Wallet.calculate_balance(blockchain,
                                    wallet.address) == wallet.balance - 30
    received_amount_1 = 25
    recieved_transaction_1 = Transaction(Wallet(), wallet.address,
                                         received_amount_1)
    received_amount_2 = 25
    recieved_transaction_2 = Transaction(Wallet(), wallet.address,
                                         received_amount_2)
    blockchain.add_block(
        [recieved_transaction_1.to_json(),
         recieved_transaction_2.to_json()])
    assert Wallet.calculate_balance(
        blockchain, wallet.address
    ) == wallet.balance - 30 + received_amount_1 + received_amount_2
Example #11
0
def test_calculate_balance():
    ''' Test that a wallet can calculate its balance correctly. '''
    blockchain = Blockchain()
    wallet = Wallet()

    # Assert that the wallet's balance on a new blockchain is equal to the
    # global starting balance.
    assert (Wallet.calculate_balance(blockchain,
                                     wallet.address) == STARTING_BALANCE)

    # Create a transaction of amount 50 and verify that it is subtracted from
    # the wallet's balance after adding the new transaction to the blockchain.
    amount = 50
    trans = Transaction(wallet, 'recipient', amount)
    blockchain.add_block([trans.to_json()])
    EXPECTED_BALANCE = STARTING_BALANCE - amount

    # Assert that the new calculated balance is equal to the expected balance.
    assert (Wallet.calculate_balance(blockchain,
                                     wallet.address) == EXPECTED_BALANCE)

    # Create first transaction to be recieved by the wallet after the calculation.
    recieved_amount1 = 25
    recieved_trans1 = Transaction(Wallet(), wallet.address, recieved_amount1)

    # Create second transaction to be recieved by the wallet after the calculation.
    recieved_amount2 = 43
    recieved_trans2 = Transaction(Wallet(), wallet.address, recieved_amount2)

    blockchain.add_block(
        [recieved_trans1.to_json(),
         recieved_trans2.to_json()])
    EXPECTED_BALANCE = (STARTING_BALANCE - amount + recieved_amount1 +
                        recieved_amount2)

    # Assert that the new calculated balance is equal to the expected balance.
    assert (Wallet.calculate_balance(blockchain,
                                     wallet.address) == EXPECTED_BALANCE)
    def is_tx_chain_valid(blockchain):
        """
        Validate incoming blockchain comprised of blocks with Tx therein qua the following ruleset:
            - each Tx occurs once in the blockchain (i.e. 'double spend')
            - there is only one valid reward Tx per block 
            - transaction obj must be intrinsically valid
        """
        # Tx tracked by id, raise if duplicate
        tx_tracking_pool = set()
        # unwrap blockchain, unwrap blocks therein, deserialize ea block's Tx and parse them
        for i in range(len(blockchain)):
            block = blockchain[i]
            mining_reward_extant = False
            for serialized_tx in block.data:
                deserialized_tx = Transaction.deserialize_from_json(
                    serialized_tx)

                # if Tx already exists
                if (deserialized_tx.id in tx_tracking_pool):
                    raise Exception(
                        f"Transaction {deserialized_tx.id} is not unique; this transaction is therefore invalid."
                    )
                # add Tx to tracking pool
                tx_tracking_pool.add(deserialized_tx.id)

                # if Tx is a block reward, only validate against reward fields
                if (deserialized_tx.input == MINING_REWARD_INPUT):
                    if (mining_reward_extant):
                        raise Exception(f"""
                            There can only be one mining reward per block. 
                            Evaluation of block with hash: {block.hash} recommended."""
                                        )
                    mining_reward_extant = True
                else:
                    # recalc balance after every Tx to prevent input tamper
                    blockchain_provenance = Blockchain()
                    blockchain_provenance.chain = blockchain[0:i]
                    balance_provenance = Wallet.calculate_balance(
                        blockchain_provenance,
                        deserialized_tx.input["address"])

                    if (balance_provenance != deserialized_tx.input["amount"]):
                        raise Exception(
                            f"Transaction {deserialized_tx.id} contains an invalid input amount."
                        )
                # last, run validator to check format
                Transaction.is_tx_valid(deserialized_tx)
    def is_valid_transaction_chain(chain):
        """
        Enforce the rules of a chain composed of blocks of transactions
            - Each transaction must only appear once in the chain
            - There can only be one mining reward per block
            - Each transaction must be valid
        """

        transaction_ids = set()

        # for block in chain:
        for i in range(len(chain)):
            block = chain[i]
            has_mining_reward = False

            for transaction_json in block.data:
                transaction = Transaction.from_json(transaction_json)

                # if transaction.input == MINING_REWARD_INPUT:
                #     if has_mining_reward:
                #         raise Exception('There can only be one mining reward per block.' \
                #                         f'Check block with hash: {block.hash}')
                #     has_mining_reward = True

                if transaction.id in transaction_ids:
                    raise Exception(f'Transaction {transaction.id} is not unique')

                transaction_ids.add(transaction.id)

                if transaction.input == MINING_REWARD_INPUT:
                    if has_mining_reward:
                        raise Exception('There can only be one mining reward per block.' \
                                        f'Check block with hash: {block.hash}')
                    has_mining_reward = True
                else:
                    # Seperate the mining reward blocks from other blocks for amount validation
                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]
                    historic_balance = Wallet.calculate_balance(
                        historic_blockchain,
                        transaction.input['address']
                    )

                    if historic_balance != transaction.input['amount']:
                        raise Exception(f'Transaction {transaction.id} has an invalid input amount')

                Transaction.is_valid_transaction(transaction)
Example #14
0
    def is_valid_transaction_chain(chain):
        """
        Enforce the rules of the blockchain
            - Each transaction must only appear once int ge blockchain
            - There can only be one mining reward per block
            - Each transaction must be valid
        :param chain:
        :return:
        """
        transaction_ids = set()

        for i in range(len(chain)):
            block = chain[i]
            has_mining_reward = False

            for transaction_json in block.data:
                transaction = Transaction.from_json(transaction_json)

                if transaction.input == MINING_REWARD_INPUT:
                    if has_mining_reward:
                        raise Exception(
                            f"There can only be one mining reward in a block. Check block {block.hash}"
                        )
                    has_mining_reward = True
                else:
                    if transaction.id in transaction_ids:
                        raise Exception(
                            f"Transaction {transaction.id} is not unique")

                    transaction_ids.add(transaction.id)

                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]

                    historic_balance = Wallet.calculate_balance(
                        historic_blockchain, transaction.input['address'])

                    if historic_balance != transaction.input['amount']:
                        raise Exception(
                            f"Transaction {transaction.id} has an invalid input amount"
                        )

                    Transaction.is_valid_transaction(transaction)
Example #15
0
    def is_valid_transaction_chain(chain):
        """
        enforces the rules of a chain composed of blocks of transctions.
         - Each transaction must only appear once in a chain
         - there can only be one mining reward per block
         - each transaction must be valid
         
        """
        transaction_ids = set()

        for i in range(len(chain)):
            block = chain[i]
            has_mining_reward = False

            for transaction_json in block.data:
                transaction = Transaction.from_json(transaction_json)

                if transaction.id in transaction_ids:
                    raise Exception(
                        f'Transaction {transaction.id} is duplicated')

                if transaction.input == MINING_REWARD_INPUT:
                    if has_mining_reward:
                        raise Exception('Invalid mining rewards'\
                            f'check with the hash: {block.hash}')
                    has_mining_reward = True

                else:
                    transaction_ids.add(transaction.id)

                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]

                    historic_balance = Wallet.calculate_balance(
                        historic_blockchain, transaction.input['address'])

                    if historic_balance != transaction.input['amount']:
                        raise Exception(
                            f'Transaction {transaction.id} has an invalid input amount'
                        )

                Transaction.is_valid_transaction(transaction)
Example #16
0
    def is_valid_transaction_chain(chain):
        """
        Enforce the rules of a chain compoesd of blocks of transactions.
        1) Each transaction must only appear once in the chain.
        2) There can only be one mining reward per block.
        3) Each transaction must be valid.
        """
        transaction_ids = set()

        for i in range(len(chain)):
            block = chain[i]
            has_mining_reward = False

            for transaction_json in block.data:
                transaction = Transaction.from_json(transaction_json)

                if transaction.id in transaction_ids:
                    raise Exception(
                        f"Transaction: {transaction.id} is not unique.")

                transaction_ids.add(transaction.id)

                if transaction.input == MINING_REWARD_INPUT:
                    if has_mining_reward:
                        raise Exception(
                            "There can only be one mining reward per block.",
                            f"Check block with this has: {block.hash}.")
                    has_mining_reward = True

                else:
                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]

                    historic_balance = Wallet.calculate_balance(
                        historic_blockchain, transaction.input["address"])

                    if historic_balance != transaction.input["amount"]:
                        raise Exception(
                            f"The transaction {transaction.id} has an invalid input amount."
                        )

                Transaction.is_valid_transaction(transaction)
    def is_chain_transaction_valid(chain):
        """
		Method to verify if each of the transactions in the chain is valid.
		Transaction is valid if:
		1. Each transation appears only once in the blockchain.
		2. There is only one reward transaction.
		3. The transaction is valid.
		"""
        transaction_ids = set()
        for index, block in enumerate(chain):
            if index == 0:
                continue
            has_reward_transaction = False
            for transaction_json in block.data:
                transaction = Transactions.from_json(transaction_json)
                if transaction.input == MINING_REWARD_INPUT:
                    if has_reward_transaction is True:
                        raise Exception(
                            "Transaction with id %s has multiple rewards" %
                            (transaction.id))
                    has_reward_transaction = True
                else:
                    #calculate historical balance using a historical balance
                    historical_chain = chain[:index]
                    historical_blockchain = Blockchain()
                    historical_blockchain.chain = historical_chain
                    #get the balance amount of the address
                    balance = Wallet.calculate_balance(
                        historical_blockchain, transaction.input['address'])
                    if balance != transaction.input['amount']:
                        raise Exception(
                            "Transaction id %s did not have the correct balance"
                            % (transaction.id))
                if transaction.id in transaction_ids:
                    raise Exception("Transaction with id %s is not unique" %
                                    (transaction.id))
                transaction_ids.add(transaction.id)
                Transactions.verify_transaction(transaction)
Example #18
0
    def is_valid_trans_chain(chain):
        '''
            Enforce the rules of a chain composed of blocks of transaction.
                - Each transaction must only appear ONCE in the chain.
                - There can only be ONE mining reward per block.
                - Each transaction MUST be valid.
        '''
        trans_ids = set()
        for i in range(len(chain)):
            block = chain[i]
            has_mining_reward = False

            for trans_json in block.data:
                trans = Transaction.from_json(trans_json)

                if trans.input == MINING_REWARD_INPUT:
                    if has_mining_reward:
                        raise Exception('There can only be one mining reward '
                                        'per block. Check block with hash: '
                                        f'{block.hash}')
                    has_mining_reward = True
                else:
                    if trans.id in trans_ids:
                        raise Exception(
                            f'Transaction {trans.id} is not unique.')

                    trans_ids.add(trans.id)
                    historic_blockchain = Blockchain()
                    historic_blockchain.chain = chain[0:i]
                    historic_balance = Wallet.calculate_balance(
                        historic_blockchain, trans.input['address'])
                    if historic_balance != trans.input['amount']:
                        raise Exception(
                            f'Transaction {trans.id} has an invalid input amount.'
                        )
                    Transaction.is_valid(trans)
def test_wallet_starting_balance():
	wallet = Wallet()
	blockchain = Blockchain()
	assert Wallet.calculate_balance(blockchain, wallet.address) == STARTING_BALANCE