예제 #1
0
 def add_block(self, block):
     # Add the seed block to the known blocks
     self.blocks[sha256(block)] = block
     # Store the block in redis
     r.zadd("miners:" + str(self.id) + ":blocks", block.height, sha256(block))
     # Announce block if chain_head isn't empty
     if self.chain_head == "*":
         self.chain_head = sha256(block)
     # If block height is greater than chain head and valid, update chain head and announce new head
     if (block.height > self.blocks[self.chain_head].height) and block.valid:
         self.chain_head = sha256(block)
         self.announce_block(self.chain_head)
예제 #2
0
 def add_block(self, block):
     # Add the block to the known blocks
     self.blocks[sha256(block)] = block
     # Store the block in redis
     r.zadd("miners:" + str(self.id) + ":blocks", block.height, sha256(block))
     # Announce block if chain_head isn't empty
     if self.chain_head == "*":
         self.chain_head = sha256(block)
     # Ignore all blocks that are not mined by the bad miner
     if block.miner_id != self.id:
         return
     # If block height is greater than chain head, update chain head and announce new head
     if block.height > self.blocks[self.chain_head].height:
         self.chain_head = sha256(block)
         self.announce_block(block)
예제 #3
0
 def notify_new_block(self, block):
     self.total_blocks += 1
     if Miner.LOGGING_MODE == "debug": print("height  = {}, name = {}, valid = {}, time = {}, hash = {}".format(
         block.height,
         self.name,
         (block.valid == 1),
         round(self.env.now, 4),
         sha256(block)))
     self.block_mined.succeed(block)
     # Create a new mining event
     self.block_mined = self.env.event()
예제 #4
0
    def add_block(self, block):
        # Save block
        self.blocks[sha256(block)] = block
        if self.chain_head == "*":
            self.chain_head = sha256(block)
            self.chain_head_others = sha256(block)
            return
        if (block.miner_id == self.id) and (block.height > self.blocks[self.chain_head].height):
            delta_prev = self.blocks[self.chain_head].height - self.blocks[self.chain_head_others].height
            self.chain_head = sha256(block)
            self.private_branch_len += 1
            if (delta_prev == 0) and (self.private_branch_len == 2):
                self.announce_block(self.chain_head)
                self.private_branch_len = 0

        if (block.miner_id != self.id) and (block.height > self.blocks[self.chain_head_others].height):
            delta_prev = self.blocks[self.chain_head].height - self.blocks[self.chain_head_others].height
            self.chain_head_others = sha256(block)
            if delta_prev <= 0:
                self.chain_head = sha256(block)
                self.private_branch_len = 0
            elif delta_prev == 1:
                self.announce_block(self.chain_head)
            elif delta_prev == 2:
                self.announce_block(self.chain_head)
                self.private_branch_len = 0
            else:
                iter_hash = self.chain_head
                temp = 0
                print(delta_prev)
                if delta_prev >= 6:
                    temp = 1
                while self.blocks[iter_hash].height != block.height + temp:
                    iter_hash = self.blocks[iter_hash].prev
                self.announce_block(iter_hash)
예제 #5
0
 def store(self):
     key = "events:" + repr(self.id)
     # Store event
     data = {
         "destination": self.destination,
         "origin": self.origin,
         "action": self.action,
         "payload": self.payload,
         "time": self.time
     }
     if isinstance(self.payload, Block):
         data['payload'] = sha256(self.payload)
     r.hmset(key, data)
     day = moment.days_passed(self.time)
     r.zadd("events", self.time, self.id)
     r.zadd("days:" + repr(day) + ":events:" + repr(self.action), self.time,
            self.id)
     r.zadd("days:" + repr(day) + ":events", self.time, self.id)
     r.zadd("miners:" + repr(self.origin) + ":events", self.time, self.id)
예제 #6
0
    def add_block(self, block):
        # Add the seed block to the known blocks
        self.blocks[sha256(block)] = block
        # Store the block in redis
        r.zadd("miners:" + str(self.id) + ":blocks", block.height, sha256(block))
        # Announce block if chain_head isn't empty
        if self.chain_head == "*":
            self.chain_head = sha256(block)
            self.chain_head_others = sha256(block)

        if not block.valid:
            if block.height > self.blocks[self.chain_head].height:
                self.chain_head = sha256(block)
                self.invalid_len += 1
                self.announce_block(block)
        else:
            if block.height > self.blocks[self.chain_head_others].height:
                self.chain_head_others = sha256(block)
                # do we continue the attack or restart the "simulation"
                if not self.restart:
                    if self.invalid_len > 0: self.honest_len += 1
                    # if attacker has already forked to invalid chain, we increment the counter
                    # or if the attacker has not forked, we restart on top of the honest network
                    if ((block.height > self.blocks[self.chain_head].height and self.invalid_len == 0) or self.honest_len == self.tgt_cfrms):
                        self.chain_head = sha256(block)
                        if Miner.LOGGING_MODE == "debug": print('att - new chain head = {}, honest_lead = {}'.format(self.chain_head, self.honest_len))
                        self.announce_block(block)
                else:
                    self.honest_len += 1
        # if the attacker gets the final block for target confirmations here, reset values
        if self.invalid_len == self.tgt_cfrms or self.honest_len == self.tgt_cfrms:
            if self.invalid_len == self.tgt_cfrms:
                self.wins += 1
                self.win.succeed()
                self.win = self.env.event()
            else:
                self.loses += 1
                self.lose.succeed()
                self.lose = self.env.event()

            self.honest_len = 0
            self.invalid_len = 0
예제 #7
0
 def announce_block(self, block):
     if self.id == 8:
         print("Announce %s - %s" % (block, self.blocks[block].miner_id))
     self.broadcast(Miner.HEAD_NEW, sha256(block))
예제 #8
0
    def wait_for_new_block(self):
        while True:
            try:
                # Wait for a block to be mined or received
                blocks = yield self.block_mined | self.block_received
                # Interrupt the mining process so the block can be added
                self.stop_mining()
                #print("%d \tI stop mining" % self.id)
                for event, block in blocks.items():
                    if Miner.LOGGING_MODE == "debug": print("BBB | {} - received block at {}, height - {}, mined by {}, hash - {}, prev = {}".format(self.name, self.env.now, block.height, block.miner_name, sha256(block), block.prev))
                    # Add the new block to the pending ones
                    self.blocks_new.append(block)
                    # Process new blocks
                yield self.env.process(self.process_new_blocks())
                # Keep mining
                if self.blocks[self.chain_head].height > 0:
                    if not self.blocks[self.chain_head].validated_yet and self.val_frac > 0:
                        self.env.process(self.validate_chain_head())

                self.keep_mining()
            except simpy.Interrupt as i:
                # When the mining process is interrupted it cannot continue until it is told to continue
                yield self.continue_mining
예제 #9
0
 def process_new_blocks(self):
     blocks_later = []
     # Validate every new block
     for block in self.blocks_new:
         if Miner.LOGGING_MODE == "debug": print('PPP | {} processing block at height {}, hash - {}, prev - {}'.format(self.name, block.height, sha256(block), block.prev))
         # Block validation is skipped for SPV miners
         yield self.env.timeout(0.0000001)
         valid = self.verify_block(block)
         # print(block, valid)
         if valid == 1:
             self.add_block(block)
         elif valid == 0:
             #Logger.log(self.env.now, self.id, "NEED_DATA", sha256(block))
             self.request_block(block.prev)
             blocks_later.append(block)
     self.blocks_new = blocks_later