コード例 #1
0
    def build_new_block(self):
        """Builds a new candidate block and propagate it to the network

        We input in our model the block size limit, and also extrapolate the probability
        distribution for the number of transactions per block, based on measurements from
        the public network (https://www.blockchain.com/charts/n-transactions-per-block?timespan=2years).
        If the block size limit is 1 MB, as we know in Bitcoin, we take from the probability
        distribution the number of transactions, but if the user choose to simulate an
        environment with a 2 MB block, we multiply by two the number of transactions.
        With this we can see the performance in different block size limits."""
        if self.is_mining is False:
            raise RuntimeError(f'Node {self.location} is not a miner')
        block_size = self.env.config['bitcoin']['block_size_limit_mb']
        transactions_per_block_dist = self.env.config['bitcoin'][
            'number_transactions_per_block']
        transactions_per_block = int(
            get_random_values(transactions_per_block_dist)[0])
        pending_txs = []
        for i in range(transactions_per_block * block_size):
            if self.transaction_queue.is_empty():
                break
            pending_tx = self.transaction_queue.get()
            pending_txs.append(pending_tx)
        candidate_block = self._build_candidate_block(pending_txs)
        print(
            f'{self.address} at {time(self.env)}: New candidate block #{candidate_block.header.number} created {candidate_block.header.hash[:8]} with difficulty {candidate_block.header.difficulty}'
        )
        # Add the candidate block to the chain of the miner node
        self.chain.add_block(candidate_block)
        # We need to broadcast the new candidate block across the network
        self.broadcast_new_blocks([candidate_block])
コード例 #2
0
    def verify_block(self, header, block_txs, verificationMode):
        if verificationMode == "WithMerkle":
            count = math.log(len(block_txs), 2)
        else:
            count = block_txs
        delay = round(
            get_random_values(self.env.delays['block_verification'])[0], 4)

        return count * delay
コード例 #3
0
    def start_heartbeat(self):
        """ The "heartbeat" frequency of any blockchain network based on PoW is time difference
        between blocks. With this function we simulate the network heartbeat frequency.

        During all the simulation, between time intervals (corresponding to the time between blocks)
        its chosen 1 or 2 nodes to broadcast a candidate block.

        We choose 2 nodes, when we want to simulate an orphan block situation.

        A fork due to orphan blocks occurs when there are two equally or nearly equally
        valid candidates for the next block of data in the blockchain.  This event can occur
        when the two blocks are found close in time, and are submitted to the network at different “ends”

        Each node has a corresponding hashrate. The greater the hashrate, the greater the
        probability of the node being chosen.
        """
        self._init_lists()
        while True:
            time_between_blocks = round(
                get_random_values(
                    self.env.delays['time_between_blocks_seconds'])[0], 2)
            yield self.env.timeout(time_between_blocks)
            orphan_blocks_probability = self.env.config[
                self.blockchain]['orphan_blocks_probability']
            simulate_orphan_blocks = scipy.random.choice(
                [True, False],
                1,
                p=[orphan_blocks_probability,
                   1 - orphan_blocks_probability])[0]
            if simulate_orphan_blocks:
                selected_nodes = scipy.random.choice(
                    self._list_nodes,
                    2,
                    replace=False,
                    p=self._list_probabilities)
                for selected_node in selected_nodes:
                    self._build_new_block(selected_node)
            else:
                selected_node = scipy.random.choice(
                    self._list_nodes,
                    1,
                    replace=False,
                    p=self._list_probabilities)[0]
                self._build_new_block(selected_node)
コード例 #4
0
 def validate_transaction(self, tx=None):
     """ Simulates the transaction validation.
     For now, it only calculates a delay in simulation, corresponding to previous measurements"""
     delay = round(
         get_random_values(self.env.delays['tx_validation'])[0], 4)
     return delay
コード例 #5
0
 def validate_block(self, block=None):
     """ Simulates the block validation.
     For now, it only applies a delay in simulation, corresponding to previous measurements"""
     delay = round(
         get_random_values(self.env.delays['block_validation'])[0], 4)
     return delay