Ejemplo n.º 1
0
    def __init__(self, ring, my_id, no_of_nodes):

        self.ring = ring  # List of ring nodes

        # Genesis block
        self.genesis = Block(index=0,
                             previous_hash=1,
                             transactions=[],
                             nonce=0)
        self.my_id = my_id
        # Genesis transaction
        transaction = Transaction(sender_address="0",
                                  receiver_address=self.ring[0]['public_key'],
                                  amount=no_of_nodes * 100,
                                  transaction_inputs='',
                                  wallet=None,
                                  ids="id0",
                                  genesis=True)

        self.genesis.transactions.append(transaction)
        self.genesis.timestamp = 0
        self.genesis.current_hash = self.genesis.get_hash()

        self.blocks = [self.genesis]  # List of added blocks (aka chain)
        self.resolve = False  # Check chain updates (bigger was found)
Ejemplo n.º 2
0
 def create_genesis_block(self):
     """
     A method to generate the genesis (first) block and append it to the chain.
     The block has index 0, previous_hash as 0, and a valid hash. 
     """
     genesis_block = Block(0, [], time.time(), "0")
     genesis_block.hash = genesis_block.compute_hash()
     self.chain.append(genesis_block)
Ejemplo n.º 3
0
    def resolve_conflict(self):

        for member in self.ring:
            # This time we do really care about the others and not ourself
            if self.my_id != f'id{member.get("id")}':

                # Request chain from nodes
                new_blocks = requests.get(
                    f'{member.get("address")}/chain').json()

                # Generate correct blocks in order to replace ones in the chain
                new_blocks = json.loads(new_blocks)
                tmp_blockchain = []
                # parse the json block to an actual block item
                for block in new_blocks["blockchain"]:
                    transactions = []

                    # Load transactions for that block
                    for t in block["transactions"]:
                        transaction = Transaction(
                            sender_address=t["sender_address"],
                            receiver_address=t["receiver_address"],
                            amount=int(t["amount"]),
                            wallet=None,
                            transaction_inputs=t["transaction_inputs"],
                            ids=t["node_id"])

                        transaction.transaction_id = t["transaction_id"]
                        transaction.signature = t["signature"]
                        transaction.transaction_outputs = t[
                            "transaction_outputs"]
                        transaction.change = int(t["change"])

                        transactions.append(transaction)

                    block = Block(block["index"], transactions, block["nonce"],
                                  block["previous_hash"], block["timestamp"])

                    block.current_hash = block.get_hash()

                    tmp_blockchain.append(block)

                # If bigger is to be found, replace existing chain
                if len(tmp_blockchain) > len(
                        self.blocks) and self.validate_chain(tmp_blockchain):
                    print(f'-- Updated Chain from Node {member.get("id")}')
                    self.blocks = tmp_blockchain

        return self
Ejemplo n.º 4
0
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'])
    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
Ejemplo n.º 5
0
def create_chain_from_dump(chain_dump):
    blockchain = Blockchain()
    for idx, 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']
        if idx > 0:
            added = blockchain.add_block(block, proof)
            if not added:
                raise Exception(" the chain dump is tampered!!")
        else:
            # the block is a genesis block, no verification needed. This would be dangerous in wild implementations.
            blockchain.append(block)
    return blockchain
Ejemplo n.º 6
0
    def mine(self):
        """
        This method serves as an interface to add the pending transactions
        to the blockchain by adding them to the block and figuring out 
        proof of work. 
        """

        if not self.unconfirmed_transactions:
            return False

        last_block = self.last_block

        new_block = Block(index=last_block.index + 1,
                          transactions=self.unconfirmed_transactions,
                          timestamp=time.time(),
                          previous_hash=last_block.hash)

        proof = self.proof_of_work(new_block)

        self.add_block(new_block, proof)
        self.unconfirmed_transactions = []
        return new_block.index
Ejemplo n.º 7
0
    def __init__(self, subject_name: str):
        self.subject_name = subject_name
        # Randomized keyboard bindings.
        if random() > 0.5:
            self.keyboard_key_for_presented = configuration.KEYBOARD_KEY_1.upper(
            )
            self.keyboard_key_for_absent = configuration.KEYBOARD_KEY_2.upper()
        else:
            self.keyboard_key_for_presented = configuration.KEYBOARD_KEY_2.upper(
            )
            self.keyboard_key_for_absent = configuration.KEYBOARD_KEY_1.upper()

        block_generators = [
            block.conjunction_condition_block, block.switch_condition_block,
            block.streak_condition_block, block.random_condition_block
        ]
        conditions_repeats = [
            configuration.CONJUNCTION_CONDITION_BLOCKS_NUMBER,
            configuration.SWITCH_CONDITION_BLOCKS_NUMBER,
            configuration.STREAK_CONDITION_BLOCKS_NUMBER,
            configuration.RANDOM_CONDITION_BLOCKS_NUMBER
        ]
        # Random conditions sequence.
        block_generators = create_shuffled_list(
            block_generators, items_repeats=conditions_repeats)

        self.practice_block = Block(configuration.RANDOM_CONDITION_NAME,
                                    block.random_rotations_generator,
                                    configuration.PRACTICE_TRIALS_NUMBER)
        self.blocks = [
            block_generator() for block_generator in block_generators
        ]
        self.current_block_id = 0
        self.current_trial_id = 0
        self.is_practice_complete = False if configuration.PRACTICE_TRIALS_NUMBER > 0 else True
        self.is_block_complete = False
        self.is_experiment_complete = False
Ejemplo n.º 8
0
class Blockchain:
    def __init__(self, ring, my_id, no_of_nodes):

        self.ring = ring  # List of ring nodes

        # Genesis block
        self.genesis = Block(index=0,
                             previous_hash=1,
                             transactions=[],
                             nonce=0)
        self.my_id = my_id
        # Genesis transaction
        transaction = Transaction(sender_address="0",
                                  receiver_address=self.ring[0]['public_key'],
                                  amount=no_of_nodes * 100,
                                  transaction_inputs='',
                                  wallet=None,
                                  ids="id0",
                                  genesis=True)

        self.genesis.transactions.append(transaction)
        self.genesis.timestamp = 0
        self.genesis.current_hash = self.genesis.get_hash()

        self.blocks = [self.genesis]  # List of added blocks (aka chain)
        self.resolve = False  # Check chain updates (bigger was found)

    def __str__(self):
        chain = f'{self.genesis.index} ({0})'

        # ignore genesis
        for block in self.blocks[1:]:
            chain += f' -> {block.index} ({block.current_hash})'

        return chain

    def add_block(self, new_block):
        self.blocks.append(new_block)
        return self

    def mine_block(self, block, difficulty):
        # We mine the whole block until the conditions are met or we get the block from another user
        nonce = 0
        block_to_mine = block
        block_to_mine.nonce = nonce

        # update hash
        block_hash = block_to_mine.get_hash()

        # try new hashes until first n characters are 0
        while block_hash[:difficulty] != '0' * difficulty:
            nonce += 1
            block_to_mine.nonce = nonce
            block_hash = block_to_mine.get_hash()

        print("I GOT A BLOCK")
        block_to_mine.current_hash = block_hash

        return block_to_mine

    def broadcast_block(self, block):

        # Actually post it at http://{address}/broadcast/block
        for member in self.ring:
            # Don't send it to myself
            if self.my_id != f'id{member.get("id")}':
                url = f'{member.get("address")}/broadcast/block'
                print(url)
                response = requests.post(url, json=block.to_json())
                if response.status_code == 400 or response.status_code == 500:
                    print('Block declined, needs resolving')
                if response.status_code == 409:
                    self.resolve = True

        return self

    def resolve_conflict(self):

        for member in self.ring:
            # This time we do really care about the others and not ourself
            if self.my_id != f'id{member.get("id")}':

                # Request chain from nodes
                new_blocks = requests.get(
                    f'{member.get("address")}/chain').json()

                # Generate correct blocks in order to replace ones in the chain
                new_blocks = json.loads(new_blocks)
                tmp_blockchain = []
                # parse the json block to an actual block item
                for block in new_blocks["blockchain"]:
                    transactions = []

                    # Load transactions for that block
                    for t in block["transactions"]:
                        transaction = Transaction(
                            sender_address=t["sender_address"],
                            receiver_address=t["receiver_address"],
                            amount=int(t["amount"]),
                            wallet=None,
                            transaction_inputs=t["transaction_inputs"],
                            ids=t["node_id"])

                        transaction.transaction_id = t["transaction_id"]
                        transaction.signature = t["signature"]
                        transaction.transaction_outputs = t[
                            "transaction_outputs"]
                        transaction.change = int(t["change"])

                        transactions.append(transaction)

                    block = Block(block["index"], transactions, block["nonce"],
                                  block["previous_hash"], block["timestamp"])

                    block.current_hash = block.get_hash()

                    tmp_blockchain.append(block)

                # If bigger is to be found, replace existing chain
                if len(tmp_blockchain) > len(
                        self.blocks) and self.validate_chain(tmp_blockchain):
                    print(f'-- Updated Chain from Node {member.get("id")}')
                    self.blocks = tmp_blockchain

        return self

    def to_od(self):
        od = OrderedDict([('blockchain',
                           [block.to_od() for block in self.blocks])])

        return od

    def to_od_with_hash(self):
        od = OrderedDict([('blockchain', [(block.to_od(), block.current_hash)
                                          for block in self.blocks])])

        return od

    def to_json(self):
        # Convert object to json
        # return json.dumps(self.to_od())
        return json.dumps(self.to_od(), default=str)

# ---------------------------------------------- VERIFICATION FUNCTIONS ----------------------------------------------

    def validate_block(self, block, difficulty):
        # check the proof of work
        if difficulty * "0" != block.get_hash_obj().hexdigest()[:difficulty]:
            print("I failed the nonce test")
            return False
        # check tha it sticks to our chain
        if self.blocks[
                -1].current_hash != block.previous_hash and block.index != 0:
            print("I failed the previous hash test")
            return False

        return True

    def validate_chain(self, blockchain):
        # Loop chain to validate that hashes are connected
        for (index, block) in enumerate(blockchain):
            if index == 0:
                continue
            if block.current_hash != block.get_hash():
                print("My blocks are wrong :(")
                return False
            if block.previous_hash != blockchain[index - 1].current_hash:
                print("I am not well connected :(")
                return False

        return True