Пример #1
0
class Node:
    def __init__(self, node_type, initial_block_list, initial_known_nodes,
                 transmission_time, tied_to_network):
        self.short_name = str(self)[-5:-1:1]
        self.display_name = None
        self.type = node_type
        self.known_nodes = initial_known_nodes
        self.blockchain = Blockchain(initial_block_list=initial_block_list)
        self.transmission_time = transmission_time
        self.available_to_transmit_at_time = 0
        self.network = tied_to_network  # should probably be deleted later
        self.update_desc()

    def update_desc(self):
        self.display_name = self.short_name + ':' + str(
            self.blockchain.block_to_append_to.height)

    def simulate_pow(self):
        block = self.blockchain.simulate_pow(creating_node=self)
        if block.is_valid():
            self.blockchain.add_block_to_tree(block)
            self.update_desc()
            self.network.process_creation(block=block, creator=self)
            # print(
            #     'node', self.short_name,
            #     'block', block.short_name,
            #     'height', block.height,
            #     'average', block.average_of_recent_ancestors / 1000 if block.average_of_recent_ancestors else 'N/A',
            #     'factor', block.adjustment_factor,
            #     'difficulty', block.difficulty,
            #     '*')
            if globals.PLOT_ON_CREATE:
                self.network.graph.plot()

    # def adjust_difficulty(self, recent_block):  # should be done with blockchain data instead for difficulty
    #     if recent_block.height > globals.MIN_LEN:
    #         num_of_blocks_for_adjustment = min(recent_block.height, globals.STABILIZATION_LEN)
    #         recent_block.register_difficulty(self.network.difficulty)
    #     logging.debug('network difficulty:' + str(self.network.difficulty))
    #     measured_time_for_block = float(recent_block.time - recent_block.last_block.last_block.last_block.last_block.time)/5
    #     logging.debug('time for block:' + str(int(float(measured_time_for_block)/1000)))
    #     logging.debug('time wanted:' + str(globals.BLOCK_TIME))
    #     ratio_delta = measured_time_for_block / globals.BLOCK_TIME - 1
    #     logging.debug('delta ratio:' + str(ratio_delta))
    #     factor = 1.0 / (1 + (0.1 * ratio_delta))   # stabilizing parameters go here
    #     logging.debug('factor:' + str(factor))
    #     self.network.difficulty = int(float(self.network.difficulty) * factor)
    #     logging.debug('new difficulty:' + str(self.network.difficulty))
    #     logging.debug('time for block:' + str(int(float(measured_time_for_block)/1000)) + ' sec, difficulty:' + str(self.network.difficulty))
    # input()

    def _receiver_policy(self):  # type strategy for choosing receivers
        if self.type == 'share':
            receiver = random.choice(self.known_nodes)
        elif self.type == 'hide':
            receiver = None
        else:
            receiver = None
            logging.critical('node type not recognized')

        return receiver  # if type is undefined it is as if type is hide

    def send_blocks_to_random_receiver(
        self
    ):  # send the block the node is working to append to, along with its ancestors
        # only send if available (not busy with previous transmission
        if self.available_to_transmit_at_time > globals.time:
            return
        block = self.blockchain.block_to_append_to
        receiver = self._receiver_policy()
        if receiver is None:
            logging.debug('time:' + str(int(globals.time / 1000)) + ':' +
                          self.short_name + ' attempts to send block ' +
                          block.display_name + ', does not send to anyone')
        elif block in receiver.blockchain.tree:
            logging.debug('time:' + str(int(globals.time / 1000)) + ':' +
                          self.short_name + ' attempts to send block ' +
                          block.display_name + ' to ' + receiver.short_name +
                          ', but it knows it already')
        else:
            block_list = self.blockchain.prepare_block_list_to_send(block)
            # can allow for strategies in sending and\or receiving instead of the following
            receiver.receive_block(block_list)
            self.network.process_transmission(block=block,
                                              sender=self,
                                              receiver=receiver)
            # self.network.graph.add_edge(sender=self, receiver=receiver)

    def receive_block(self, block_list):
        self.blockchain.ordered_list_to_tree(block_list)
        self.update_desc()
        if globals.PLOT_ON_RECEIVE:
            self.network.graph.plot()