def add(self, block: Block) -> bool:
        log("BLOCKCHAIN {} ADDING {}".format(self, block))
        if block.difficulty < self.difficulty:
            log("BLOCKCHAIN {} REJECT {} TOO LIGHT {} < {}".format(self, block, block.difficulty, self.difficulty))
            return False
        if block.previous.id != self.tip.id:
            if block.previous.id in self.blocks:
                log("BLOCKCHAIN {} REJECT {} STALE".format(self, block))
            else:
                log("BLOCKCHAIN {} REJECT {} UNKNOWN TIP {}".format(self, block, block.previous.id))
            return False

        log("BLOCKCHAIN {} ACCEPT {}".format(self, block))
        self.blocks[block.id] = block
        self.heights.append(block.id)
        self.height += 1
        self.weight += block.difficulty
        # if self.height % self.difficulty_readjustment_period == 0:
        #     self.readjust_difficulty()
        return True
 def readjust_difficulty(self):
     #
     # By construction,
     # 
     #      old_difficulty                           new_difficulty
     #   -------------------  = observed hashrate = -----------------
     #   observed block time                        target block time
     #
     # so new_difficulty = (target block time * old_difficulty) / (observed block time)
     # 
     log("BLOCKCHAIN {} DIFF READJ AT BLOCK {}".format(self, self.height))
     blocks = [self.blocks[block_id] for block_id in list(reversed(self.heights))[:self.difficulty_readjustment_period]]
     block_gaps = [(blocks[index+1].time - block.time) for index, block in enumerate(blocks[:-1])]
     observed_block_time = mean(block_gaps)
     old_difficulty = self.difficulty
     new_difficulty = (self.block_time * old_difficulty) / observed_block_time
     difficulty_change_ratio = new_difficulty / old_difficulty
     if difficulty_change_ratio > self.max_difficulty_change_factor:
         difficulty_change_ratio = self.max_difficulty_change_factor
     elif difficulty_change_ratio < self.inverse_max_difficulty_change_factor:
         difficulty_change_ratio = self.inverse_max_difficulty_change_factor
     self.difficulty = old_difficulty * difficulty_change_ratio
     log("BLOCKCHAIN {} DIFF. ADJ. {} => {}".format(self, old_difficulty, self.difficulty))
    def merge(self, other: 'Blockchain') -> bool:
        log("BLOCKCHAIN {} MERGING {}".format(self, other))

        assert other.chain_params == self.chain_params

        if other.weight < self.weight:
            log("BLOCKCHAIN {} REJECT {} AS LIGHTER CHAIN".format(self, other))
            return False

        log("BLOCKCHAIN {} ACCEPT {}".format(self, other))
        self.blocks = {block_id:block for (block_id, block) in other.blocks.items()}
        self.heights = [block_id for block_id in other.heights]
        self.height = other.height
        self.weight = other.weight
        self.difficulty = other.difficulty
        return True
Beispiel #4
0
 def receive(self, time, transmission):
     log("AGENT {} RECEIVE {}".format(self.id, transmission.id))
     self.transmissions_received[time] = transmission
Beispiel #5
0
 def log_advance(self, duration):
     log("AGENT {} ADVANCE w/ {}".format(self.id, [
         transmission.id
         for transmission in self.transmissions_received.values()
     ]))