Ejemplo n.º 1
0
    def mineInvalidBlock(self, tx: Transaction, isInvalidPrevHash = False, isInvalidPOW = False) -> None:
        """
            This function is only used for testing.
            mine a new invalid block with the tx, either prev_hash or pow is invalid
        """
        if not isInvalidPrevHash and not isInvalidPOW:
            return
        # tx not valid
        if not self.verifyTx(tx):
            # because this transaction is already in the ledger
            if not self.__verifyTxNotOnBlockchain(tx):
                log.error("Node " + self.id + " :" + "Tx Verification Failed! This Tx is already on the ledger")
            return
        blockPow = str(self.miningDifficulty + 1)
        hashTarget = self.miningDifficulty
        prevBlock = self.latestBlockTreeNode

        prevHash = sha256(prevBlock.nowBlock.toString().encode('utf-8')).hexdigest()
        txAndPrevHashMsg = tx.toString() + prevHash
        nonce = 0
        while int(blockPow, base=16) > hashTarget:
            blockMessage = txAndPrevHashMsg + str(nonce)
            blockPow = sha256(blockMessage.encode('utf-8')).hexdigest()
            nonce += 1
        nonce -= 1

        newBlock = Block(tx, prevHash, nonce, blockPow)

        if isInvalidPrevHash:
            newBlock.prev += "1"  # make the prev hash invalid
        elif isInvalidPOW:
            newBlock.pow = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
        newBlockTreeNode = BlockTreeNode(prevBlock, newBlock, self.latestBlockTreeNode.blockHeight + 1)
        self.__updateNewMinedBlock(newBlock, newBlockTreeNode)
Ejemplo n.º 2
0
def data_blockchain():
    blockchain = Blockchain()
    blockchain_table = table("blockchain", "number", "hash", "previous", "data","time", "nonce")
    for b in blockchain_table.getall():
        blockchain.add(Block(int(b.get('number')), b.get('previous'), b.get('data'), b.get('time'),int(b.get('nonce'))))

    return blockchain
Ejemplo n.º 3
0
def bitcoin_tests():
    bc = BitcoinBlockchain()

    bc.genesis()

    for i in range(10):
        block = Block(bc.last_block, 1)
        bc.add_block(block)

    print(bc)
Ejemplo n.º 4
0
def check_chain():
    blockchain = Blockchain()
    database = ["hello", " here"]

    num = 0

    for data in database:
        num += 1
        blockchain.mine(Block(number=num, data=data))
    update_blockchain(blockchain)
Ejemplo n.º 5
0
def create_test_blockchain():
    miner_one = Miner(None, 1, [], 2, 0, None, None)
    miner_two = Miner(None, 1, [], 2, 1, None, None)
    b = Blockchain()
    block_one = generate_block_on_longest_chain(b.last_block[0], miner_one)
    b.extend(block_one)
    b.extend(generate_block_on_longest_chain(b.last_block[0], miner_one))
    edge1 = generate_block_on_longest_chain(b.last_block[0], miner_one)
    b.extend(edge1)
    edge2 = Block([], 2, block_one, 2, miner_two)
    b.extend(edge2)
    return b, edge1, edge2, miner_one, miner_two
def verify_and_add_block():
    block_data = request.get_json()
    block = Block(block_data["index"], block_data["transactions"],
                  block_data["timestamp"], block_data["previous_hash"],
                  block_data["nonce"])

    proof = block_data['hash']
    added = blockchain.add_block(block, proof)

    if not added:
        return "The block was discarded by the node", 400

    return "Block added to the chain", 201
def create_chain_from_dump(chain_dump):
    generated_blockchain = Blockchain()
    generated_blockchain.create_genesis_block()
    for idx, block_data in enumerate(chain_dump):
        if idx == 0:
            continue  # skip genesis block
        block = Block(block_data["index"], block_data["transactions"],
                      block_data["timestamp"], block_data["previous_hash"],
                      block_data["nonce"])
        proof = block_data['hash']
        added = generated_blockchain.add_block(block, proof)
        if not added:
            raise Exception("The chain dump is tampered!!")
    return generated_blockchain
Ejemplo n.º 8
0
def mine():
    #Last proof of work
    last_block = blockchain[len(blockchain) - 1]
    last_proof = json.loads(last_block.data)['proof-of-work']

    #The program will be stuck here
    #until a new valid proof of work
    #is found
    proof = proof_of_work(last_proof)

    #Once the proof is valid, new block
    #can be added and miner can be rewarded
    transaction_list.append(
        json.dumps(Transaction("network-reward", miner_address, 1).reprJSON(), cls=ComplexEncoder)
    )

    #Data needed to create a new block
    new_block_data = json.dumps({
        "proof-of-work": proof,
        "transactions": json.dumps(list(transaction_list), cls=ComplexEncoder)
    }, cls=ComplexEncoder)

    #Clear the transaction list
    transaction_list[:] = []

    #New block
    mined_block = Block(
        last_block.index + 1,
        datetime.datetime.now(),
        new_block_data,
        last_block.hash
    )
    blockchain.append(mined_block)

    #Response for new block mined
    return json.dumps(mined_block.reprJSON(), cls=ComplexEncoder) + "\n"
Ejemplo n.º 9
0
    def extend_with_reference(self, block: Block) -> None:
        def iteratore_backwards_block(block_to_iterate):
            while block_to_iterate is not None:
                yield block_to_iterate
                block_to_iterate = block_to_iterate.previous_block

        for edge in self.edges:
            for b in iteratore_backwards_block(edge):
                if b == block.previous_block:
                    block = block.copy(b)
                    return self.extend(block)
                elif b.block_num < block.previous_block.block_num:
                    break

        raise ValueError("There must be some error here")
Ejemplo n.º 10
0
    def run(self):
        # Broadcast genesis blockchain without interference
        block = Block.genesis_block(self.difficulty)
        blockchain = Blockchain(block)
        self.broadcast(pickle.dumps(blockchain), interference=False)

        # Starting line for miners
        self.starting_line = threading.Barrier(total_miners + 1)

        # Start miners
        for miner in self.miners:
            miner.start()

        self.starting_line.wait()  # Start mining once all miners ready

        self.stop_event.wait()
Ejemplo n.º 11
0
def test_creating_edges_correctly():
    """
    create a blockchain:

    1 -> 2 -> 3
      -> 2

    :return:
    """
    b, edge1, edge2, miner_one, miner_two = create_test_blockchain()
    assert len(b.edges) == 2
    assert b.edges[0] == edge1
    assert b.edges[1] == edge2
    assert b.edges[1].previous_block == b.edges[
        0].previous_block.previous_block

    edge1 = Block([], 4, b.last_block[0], 4, miner_one)
    b.extend(edge1)
    assert b.edges[0] == edge1
Ejemplo n.º 12
0
def send_money(sender, recipient, amount):

    #verify that the amount is an integer or floating value
    try: amount = float(amount)
    except ValueError:
        raise InvalidTransactionException("Invalid Transaction.")

    if amount > get_balance(sender) and sender != "ROOT":
        raise InsufficientFundsException("Insufficient Funds.")

    elif sender == recipient or amount <= 0.00:
        raise InvalidTransactionException("Invalid Transaction.")

    elif isnewuser(recipient):
        raise InvalidTransactionException("User Does Not Exist.")
    blockchain = data_blockchain()
    number = len(blockchain.chain) + 1
    data = "%s-->%s-->%s" %(sender, recipient, amount)
    blockchain.mine(Block(number, data=data))
    update_blockchain(blockchain)
Ejemplo n.º 13
0
def create_chain_from_dump(chain_dump):
    """ 
    Internally calls the `register_node` endpoint to
    register current node with the remote node specified 
    in the request, and sync the blockchain as well with 
    the remote node.

    Args:
        chain_dump (JSON): chain dump.

    Raises:
        Exception: If the chain was tempered.

    Returns:
        Object: retrns Blockchain
    """

    blockchain = Blockchain()
    
    for index, block_data in enumerate(chain_dump):
        block = Block(block_data["index"],
                      block_data["transactions"],
                      block_data["timestamp"],
                      block_data["previous_hash"])
        proof = block_data["hash"]

        # Exclude the genesis block
        if index > 0:
            added = blockchain.add_block(block, proof)

            if not added:
                raise Exception("The chain dump is tampered!!")
        
        # For the genesis block
        else:
            blockchain.chain.append(block)
    
    return blockchain
Ejemplo n.º 14
0
    def mineBlock(self, tx: Transaction) -> None:  # mine a new block with the tx
        # tx not valid
        if not self.verifyTx(tx):
            # because this transaction is already in the ledger
            if not self.__verifyTxNotOnBlockchain(tx):
                log.error("Node " + self.id + " :" + "Tx Verification Failed! This Tx is already on the ledger")
            return
        blockPow = str(self.miningDifficulty + 1)
        hashTarget = self.miningDifficulty
        prevBlock = self.latestBlockTreeNode

        prevHash = sha256(prevBlock.nowBlock.toString().encode('utf-8')).hexdigest()
        txAndPrevHashMsg = tx.toString() + prevHash
        nonce = 0
        while int(blockPow, base=16) > hashTarget:
            blockMessage = txAndPrevHashMsg + str(nonce)
            blockPow = sha256(blockMessage.encode('utf-8')).hexdigest()
            nonce += 1
        nonce -= 1

        newBlock = Block(tx, prevHash, nonce, blockPow)
        newBlockTreeNode = BlockTreeNode(prevBlock, newBlock, self.latestBlockTreeNode.blockHeight + 1)
        self.__updateNewMinedBlock(newBlock, newBlockTreeNode)
Ejemplo n.º 15
0
 def __verifyBlockPrevHash(self, prevBlock: Block, newBlock: Block) -> bool:
     prevEncode = prevBlock.toString().encode('utf-8')
     prevHash = sha256(prevEncode).hexdigest()
     __flag = prevHash == newBlock.prev
     return __flag
Ejemplo n.º 16
0
    def run(self):
        # Get initial blockchain from mailbox
        self.blockchain = pickle.loads(self.read_mail())

        # Construct miner payload comment
        comment = "I, miner number {:d}, did this!".format(self.id_number)

        # Wait for supervisor's go signal
        self.supervisor.starting_line.wait()

        # Start mining!
        while not self.stopped:

            # Create new block miner wants on chain

            # Get latest block
            latest_block = self.blockchain.latest_block
            # Create hash pointer for block
            hash_pointer = latest_block.hash().digest()
            # Get milliseconds for block
            time_stamp = get_ms_since_epoch()
            # At this point the comment should be gotten, but it has already been made
            # comment = comment
            # Get new counter by incrementing old counter
            new_counter = latest_block.counter + 1
            # Get difficulty from latest block
            difficulty = latest_block.difficulty
            # Get nonce, but it is not known yet!
            no_nonce = b""

            # Calculate base hash
            no_nonce_block = Block(
                                    hash_pointer
                                  , time_stamp
                                  , comment
                                  , new_counter
                                  , difficulty
                                  , no_nonce
                                  )
            base_hash = no_nonce_block.hash()

            # Create new slave to find good nonce
            self.slave = Slave(self, base_hash, difficulty)
            self.slave.start()

            while True:
                # Wait for notification from:
                #  - Supervisor stopping the "gold rush"/mining
                #  - Other miners sending messages
                #  - Slave having found nonce
                self.wait()

                # Check if supervisor announced stop
                if self.stopped:
                    break

                # Read mail
                if self.has_mail():
                    with self.mailbox_lock:
                        blockchain_replaced = False
                        while self.has_mail():
                            # Read messages
                            message = self.read_mail()
                            received_blockchain = pickle.loads(message)
                            if len(received_blockchain) > len(self.blockchain):
                                # Take up blockchain if bigger
                                self.blockchain = received_blockchain
                                blockchain_replaced = True
                        if blockchain_replaced:
                            self.supervisor.refresh.set()
                            break

                # Check on slave
                if not self.slave.is_alive():
                    # Slave has found nonce!
                    self.slave.join()
                    if self.stopped:
                        break
                    block = Block(
                                   hash_pointer
                                 , time_stamp
                                 , comment
                                 , new_counter
                                 , difficulty
                                 , self.slave.result
                                 )
                    self.blockchain.append(block)
                    self.blockchain.verify()
                    self.supervisor.refresh.set()
                    self.supervisor.broadcast(pickle.dumps(self.blockchain), exclude=self)
                    break
            # Take care of the slave
            self.slave.stop()
            self.slave.join()
Ejemplo n.º 17
0
def generate_block_on_longest_chain(prev_block, miner):
    return Block([], prev_block.block_time + 1, prev_block,
                 prev_block.block_num + 1, miner)