Exemple #1
0
class RoundIter:
    def __init__(self, dag, block_hash, round_type):
        block_number = dag.get_block_number(block_hash)
        epoch_number = Epoch.get_epoch_number(block_number)
        round_start, round_end = Epoch.get_round_bounds(
            epoch_number, round_type)

        self.round_end = round_start
        self.chain_iter = ChainIter(dag, block_hash)
        while self.chain_iter.block_number > round_end + 1:
            self.chain_iter.next()

    def __iter__(self):
        return self

    def __next__(self):
        block = self.chain_iter.next()
        block_number = self.chain_iter.block_number
        if block_number < self.round_end:
            raise StopIteration()

        return block

    def current_block_number(self):
        return self.chain_iter.block_number

    def next(self):
        return self.__next__()
Exemple #2
0
    def __init__(self, dag, block_hash, round_type):
        block_number = dag.get_block_number(block_hash)
        epoch_number = Epoch.get_epoch_number(block_number)
        round_start, round_end = Epoch.get_round_bounds(
            epoch_number, round_type)

        self.round_end = round_start
        self.chain_iter = ChainIter(dag, block_hash)
        while self.chain_iter.block_number > round_end + 1:
            self.chain_iter.next()
    def flatten_with_merge(merger, from_hash, to_hash):
        flat_chain = []
        chain_iter = ChainIter(merger.dag, from_hash)
        block = chain_iter.next()
        block_hash = block.get_hash()
        while block_hash != to_hash:
            if not block:
                flat_chain.append(None)
            else:
                flat_chain.append(block)
                if len(block.block.prev_hashes) > 1:
                    merge_chain = merger.merge(block.block.prev_hashes)
                    flat_chain += list(reversed(merge_chain))
                    chain_iter = ChainIter(merger.dag,
                                           merge_chain[0].get_hash())
                    chain_iter.next(
                    )  # immediately transfer to next block because this one is already in chain

            block = chain_iter.next()
            if block: block_hash = block.get_hash()
            else: block_hash = None

        flat_chain.append(merger.dag.blocks_by_hash[to_hash])

        return MergedChain(list(reversed(flat_chain)))
Exemple #4
0
    def calculate_zeta(self, block_hash):
        import sys
        max_zeta = -sys.maxsize - 1  # TODO replace with reasonable number

        tops = self.dag.get_top_blocks_hashes()
        for top in tops:
            zeta = 0
            iterator = ChainIter(self.dag, top)
            consecutive_skips = 0
            consecutive_blocks = 0
            for block in iterator:
                if block:
                    if block.get_hash() == block_hash:
                        if max_zeta < zeta:
                            max_zeta = zeta
                        continue

                if block:
                    consecutive_blocks += 1
                    consecutive_skips = 0
                else:
                    consecutive_skips += 1
                    consecutive_blocks = 0

                if consecutive_skips == CONSECUTIVE_CONST:
                    zeta -= 1
                    consecutive_skips = 0
                elif consecutive_blocks == CONSECUTIVE_CONST:
                    zeta += 1
                    consecutive_blocks = 0

        return max_zeta
    def get_stake_actions(self, epoch_hash):
        epoch_iter = ChainIter(self.epoch.dag, epoch_hash)

        stake_actions = []

        count = 0
        for block in epoch_iter:
            if epoch_iter.block_number == 0:
                break

            if block:
                for tx in block.block.system_txs:
                    if isinstance(tx, StakeHoldTransaction) \
                    or isinstance(tx, StakeReleaseTransaction) \
                    or isinstance(tx, PenaltyTransaction) \
                    or isinstance(tx, PenaltyGossipTransaction):
                        stake_actions.append(tx)

            count += 1
            if count == Epoch.get_duration():
                break

        stake_actions = list(reversed(stake_actions))

        return stake_actions
Exemple #6
0
    def test_iterator(self):
        dag = Dag(0)
        private = Private.generate()
        block1 = BlockFactory.create_block_with_timestamp(
            [dag.genesis_block().get_hash()], BLOCK_TIME)
        signed_block1 = BlockFactory.sign_block(block1, private)
        dag.add_signed_block(1, signed_block1)

        block2 = BlockFactory.create_block_with_timestamp([block1.get_hash()],
                                                          BLOCK_TIME * 2)
        signed_block2 = BlockFactory.sign_block(block2, private)
        dag.add_signed_block(2, signed_block2)

        block3 = BlockFactory.create_block_with_timestamp([block2.get_hash()],
                                                          BLOCK_TIME * 3)
        signed_block3 = BlockFactory.sign_block(block3, private)
        dag.add_signed_block(3, signed_block3)

        # alternative chain
        other_block2 = BlockFactory.create_block_with_timestamp(
            [block1.get_hash()], BLOCK_TIME * 2 + 1)
        other_signed_block2 = BlockFactory.sign_block(other_block2, private)
        dag.add_signed_block(2, other_signed_block2)

        # intentionally skipped block

        # alternative chain
        other_block4 = BlockFactory.create_block_with_timestamp(
            [other_block2.get_hash()], BLOCK_TIME * 3 + 1)
        other_signed_block4 = BlockFactory.sign_block(other_block4, private)
        dag.add_signed_block(4, other_signed_block4)

        chain_iter = ChainIter(dag, block3.get_hash())
        self.assertEqual(chain_iter.next().block.get_hash(), block3.get_hash())
        self.assertEqual(chain_iter.next().block.get_hash(), block2.get_hash())
        self.assertEqual(chain_iter.next().block.get_hash(), block1.get_hash())

        chain_iter = ChainIter(dag, other_block4.get_hash())
        self.assertEqual(chain_iter.next().block.get_hash(),
                         other_block4.get_hash())
        self.assertEqual(chain_iter.next(),
                         None)  # detect intentionally skipped block
        self.assertEqual(chain_iter.next().block.get_hash(),
                         other_block2.get_hash())
        self.assertEqual(chain_iter.next().block.get_hash(), block1.get_hash())
Exemple #7
0
 def find_epoch_hash_for_block(self, block_hash):
     chain_iter = ChainIter(self.dag, block_hash)
     just_take_next_non_skipped_block = False
     for block in chain_iter:
         if self.is_last_block_of_epoch(
                 chain_iter.block_number
         ) or just_take_next_non_skipped_block:
             if block:
                 return block.get_hash()
             else:
                 just_take_next_non_skipped_block = True
     return None
Exemple #8
0
    def get_mutable_part_of_chain(self, top):
        chain_part = []
        chain_iter = ChainIter(self.dag, top)
        count = 0
        for block in chain_iter:
            count += 1
            if count == ZETA:
                if block:
                    chain_part.append(block)
                else:
                    chain_part.append(None)

        return list(reversed(chain_part))
Exemple #9
0
    def get_top_chain_block_hashes(self, from_hash, to_hash):
        """ Method return list of logical block by block chain
            from hash to hash IN THE OPPOSITE DIRECTION (from current top to to_hash)
            :param from_hash: current top hash
            :param to_hash: any hash from chain
            :return: list of block hashes in logical sequences WITHOUT SKIPS
        """
        flat_chain = []
        chain_iter = ChainIter(self.dag, from_hash)
        block = chain_iter.next()
        block_hash = block.get_hash()
        while block_hash != to_hash:
            if block:
                flat_chain.append(block.get_hash())

            block = chain_iter.next()
            if block:
                block_hash = block.get_hash()
            else:
                block_hash = None

        flat_chain.append(self.dag.blocks_by_hash[to_hash])

        return list(reversed(flat_chain))
Exemple #10
0
    def calculate_confirmations(self, block_hash):
        confirmations = [0]
        block_number = self.dag.get_block_number(block_hash)

        tops = self.dag.get_branches_for_timeslot_range(
            block_number + 1, block_number + ZETA + 1)

        for top in tops:
            branch_confirmations = 0
            chain_iter = ChainIter(self.dag, top)
            for block in chain_iter:
                if chain_iter.block_number == block_number:  # if we counted enough
                    if block.get_hash(
                    ) == block_hash:  # if we counted on the branch including target block
                        confirmations.append(branch_confirmations)
                    break
                if block:
                    branch_confirmations += 1

        return max(confirmations)