Beispiel #1
0
    def test_merge_with_conflict_simple(self):
        dag = Dag(0)

        genesis_hash = dag.genesis_block().get_hash()

        block_hash1 = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)

        conflicting_block_hash1 = ChainGenerator.insert_dummy(
            dag, [block_hash1], 2)
        conflicting_block_hash2 = ChainGenerator.insert_dummy(
            dag, [block_hash1], 2)

        block_hash3 = ChainGenerator.insert_dummy(dag,
                                                  [conflicting_block_hash2], 3)

        # DagVisualizer.visualize(dag, True)  # uncomment for discover in visualization folder

        conflicts = [conflicting_block_hash1]

        merger = Merger(dag)
        res = merger.merge(dag.get_top_hashes(), conflicts)
        res = res.filter_out_skipped_blocks()

        # self.assertEqual(res[0].get_hash(), genesis_hash) #no genesis hash since common ancestor is first block
        self.assertEqual(res[0].get_hash(), block_hash1)
        self.assertEqual(res[1].get_hash(), conflicting_block_hash2)
        self.assertEqual(res[2].get_hash(), block_hash3)
Beispiel #2
0
    def test_both_types_of_conflicts(self):
        dag = Dag(0)
        watcher = ConflictWatcher(dag)

        actor1 = Private.publickey(Private.generate())
        actor2 = Private.publickey(Private.generate())
        actor3 = Private.publickey(Private.generate())

        block1_hash = ChainGenerator.insert_dummy(dag, [dag.genesis_hash()], 1)
        watcher.on_new_block_by_validator(block1_hash, 1, actor1)

        block2_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        watcher.on_new_block_by_validator(block2_hash, 1, actor2)

        block2c_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        watcher.on_new_block_by_validator(block2c_hash, 1, actor2)

        block3_hash = ChainGenerator.insert_dummy(dag, [block2_hash], 3)
        watcher.on_new_block_by_validator(block3_hash, 1, actor3)

        #this is possible if we have two epoch seeds
        block4_hash = ChainGenerator.insert_dummy(dag, [block2c_hash], 4)
        watcher.on_new_block_by_validator(block4_hash, 1, actor1)

        tops = dag.get_top_hashes()

        explicits, candidate_groups = watcher.find_conflicts_in_between(tops)
        self.assertEqual(len(explicits), 1)
        self.assertIn(block4_hash, explicits)

        self.assertEqual(len(candidate_groups), 1)
        self.assertEqual(len(candidate_groups[0]), 2)
        self.assertIn(block2_hash, candidate_groups[0])
        self.assertIn(block2c_hash, candidate_groups[0])
Beispiel #3
0
    def test_different_timeslot_watch(self):
        dag = Dag(0)
        conflict_watcher = ConflictWatcher(dag)

        actor1 = Private.publickey(Private.generate())
        actor2 = Private.publickey(Private.generate())
        actor3 = Private.publickey(Private.generate())

        block1_hash = ChainGenerator.insert_dummy(dag, [dag.genesis_hash()], 1)
        conflict_watcher.on_new_block_by_validator(block1_hash, 1, actor1)

        block2_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        conflict_watcher.on_new_block_by_validator(block2_hash, 1, actor2)

        # second block is signed by third validator
        # its not possible by usual means, but quite possible when we have two different epoch seeds
        block2c_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        conflict_watcher.on_new_block_by_validator(block2c_hash, 1, actor3)

        block3_hash = ChainGenerator.insert_dummy(dag,
                                                  [block2_hash, block2c_hash],
                                                  3)
        conflict_watcher.on_new_block_by_validator(block3_hash, 1, actor3)

        conflicts = conflict_watcher.get_conflicts_by_block(block3_hash)
        self.assertEqual(len(conflicts), 2)
        self.assertIn(block2c_hash, conflicts)
        self.assertIn(block3_hash, conflicts)
Beispiel #4
0
    def test_same_timeslot_watch(self):
        dag = Dag(0)
        conflict_watcher = ConflictWatcher(dag)

        actor1 = Private.publickey(Private.generate())
        actor2 = Private.publickey(Private.generate())
        actor3 = Private.publickey(Private.generate())

        block1_hash = ChainGenerator.insert_dummy(dag, [dag.genesis_hash()], 1)
        conflict_watcher.on_new_block_by_validator(block1_hash, 1, actor1)

        block2_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        conflict_watcher.on_new_block_by_validator(block2_hash, 1, actor2)

        block2c_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        conflict_watcher.on_new_block_by_validator(block2c_hash, 1, actor2)

        block3_hash = ChainGenerator.insert_dummy(dag,
                                                  [block2_hash, block2c_hash],
                                                  3)
        conflict_watcher.on_new_block_by_validator(block3_hash, 1, actor3)

        conflicts = conflict_watcher.get_conflicts_by_block(block2_hash)
        self.assertEqual(len(conflicts), 2)
        self.assertIn(block2_hash, conflicts)
        self.assertIn(block2c_hash, conflicts)

        conflicts = conflict_watcher.get_conflicts_by_block(block1_hash)
        self.assertEqual(conflicts, None)
Beispiel #5
0
    def test_find_conflicts(self):
        dag = Dag(0)
        watcher = ConflictWatcher(dag)

        actor1 = Private.publickey(Private.generate())
        actor2 = Private.publickey(Private.generate())

        block1_hash = ChainGenerator.insert_dummy(dag, [dag.genesis_hash()], 1)
        watcher.on_new_block_by_validator(block1_hash, 1, actor1)

        block2_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        watcher.on_new_block_by_validator(block2_hash, 1, actor2)

        block2c_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        watcher.on_new_block_by_validator(block2c_hash, 1, actor2)

        # block3_hash = ChainGenerator.insert_dummy(dag, [block2_hash, block2c_hash], 3)
        # watcher.on_new_block_by_validator(block3_hash, 1, actor3)

        tops = dag.get_top_hashes()

        explicits, candidate_groups = watcher.find_conflicts_in_between(tops)
        self.assertEqual(len(explicits), 0)
        self.assertEqual(len(candidate_groups), 1)
        self.assertEqual(len(candidate_groups[0]), 2)
        self.assertIn(block2_hash, candidate_groups[0])
        self.assertIn(block2c_hash, candidate_groups[0])
Beispiel #6
0
    def test_explicit_conflict(self):
        dag = Dag(0)
        watcher = ConflictWatcher(dag)

        actor1 = Private.publickey(Private.generate())
        actor2 = Private.publickey(Private.generate())

        block1_hash = ChainGenerator.insert_dummy(dag, [dag.genesis_hash()], 1)
        watcher.on_new_block_by_validator(block1_hash, 1, actor2)

        block2_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        watcher.on_new_block_by_validator(block2_hash, 1, actor1)

        block3_hash = ChainGenerator.insert_dummy(dag, [block2_hash], 3)
        watcher.on_new_block_by_validator(block3_hash, 1, actor2)

        block3c_hash = ChainGenerator.insert_dummy(dag, [block2_hash], 3)
        watcher.on_new_block_by_validator(block3c_hash, 1, actor2)

        tops = dag.get_top_hashes()

        #here block was signed by node even before merge appeared
        #this is explicit merge and both following blocks are conflicting
        explicits, candidates = watcher.find_conflicts_in_between(tops)
        self.assertEqual(len(explicits), 2)
        self.assertEqual(len(candidates), 0)
        self.assertIn(block3_hash, explicits)
        self.assertIn(block3c_hash, explicits)
    def test_sane_prev_hashes_found(self):
        dag = Dag(0)
        epoch = Epoch(dag)
        genesis_hash = dag.genesis_block().get_hash()

        block_hash1 = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        block_hash2 = ChainGenerator.insert_dummy(dag, [block_hash1], 2)
        _block_hash3 = ChainGenerator.insert_dummy(dag,
                                                   [genesis_hash, block_hash2],
                                                   3)

        verifier = BlockAcceptor(epoch, None)

        with self.assertRaises(AcceptionException):
            verifier.validate_non_ancestor_prev_hashes(
                [genesis_hash, block_hash2])
Beispiel #8
0
    def test_skip_confirmation_requirement(self):
        dag = Dag(0)
        conf_req = ConfirmationRequirement(dag)

        genesis_hash = dag.genesis_block().get_hash()

        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        # confirmation requirement decreases because we have large skip
        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 5)

        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 3)
        skip = SkippedBlock(block_hash, 1)
        confirmation_requirement = conf_req.get_confirmation_requirement(skip)
        self.assertEqual(confirmation_requirement, 5)

        # do a larger gap
        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 11)

        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 3)

        confirmation_requirement = conf_req.get_confirmation_requirement(
            SkippedBlock(block_hash, 1))
        self.assertEqual(confirmation_requirement, 3)

        confirmation_requirement = conf_req.get_confirmation_requirement(
            SkippedBlock(block_hash, 2))
        self.assertEqual(confirmation_requirement, 4)

        confirmation_requirement = conf_req.get_confirmation_requirement(
            SkippedBlock(block_hash, 4))
        self.assertEqual(confirmation_requirement, 4)

        confirmation_requirement = conf_req.get_confirmation_requirement(
            SkippedBlock(block_hash, 5))
        self.assertEqual(confirmation_requirement, 5)

        confirmation_requirement = conf_req.get_confirmation_requirement(
            SkippedBlock(block_hash, 6))
        self.assertEqual(confirmation_requirement, 5)

        confirmation_requirement = conf_req.get_confirmation_requirement(
            SkippedBlock(block_hash, 10))
        self.assertEqual(confirmation_requirement, ZETA_MAX)
Beispiel #9
0
    def test_merge_with_conflict_simplest(self):
        dag = Dag(0)

        genesis_hash = dag.genesis_block().get_hash()

        block_hash1 = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        block_hash2 = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)

        # DagVisualizer.visualize(dag, True)  # uncomment for discover in visualization folder

        conflicts = [block_hash1]

        merger = Merger(dag)
        res = merger.merge(dag.get_top_hashes(), conflicts)
        res = res.filter_out_skipped_blocks()

        self.assertEqual(res[0].get_hash(), genesis_hash)
        self.assertEqual(res[1].get_hash(), block_hash2)
    def test_sane_prev_hashes_not_found(self):
        dag = Dag(0)
        epoch = Epoch(dag)
        genesis_hash = dag.genesis_block().get_hash()

        block_hash1 = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        block_hash2 = ChainGenerator.insert_dummy(dag, [block_hash1], 2)
        block_hash3 = ChainGenerator.insert_dummy(dag, [genesis_hash], 3)
        _block_hash4 = ChainGenerator.insert_dummy(dag,
                                                   [block_hash2, block_hash3],
                                                   4)

        verifier = BlockAcceptor(epoch, None)

        try:
            verifier.validate_non_ancestor_prev_hashes(
                [block_hash2, block_hash3])
        except:
            self.fail("Prev hashes should not be self referential")
Beispiel #11
0
    def test_recursive_sequence_skips(self):
        dag = Dag(0)
        conf_req = ConfirmationRequirement(dag)

        genesis_hash = dag.genesis_block().get_hash()

        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 5
        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 5)

        # confirmation requirement decreases because we have large skip
        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 4)

        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 9)

        # DagVisualizer.visualize(dag, True) # take a look to understand what's going on

        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 3)
Beispiel #12
0
    def test_explicit_conflict_right_on_common_ancestor(self):
        dag = Dag(0)
        watcher = ConflictWatcher(dag)

        actor2 = Private.publickey(Private.generate())

        #consider common ancestor already resolved
        block1_hash = ChainGenerator.insert_dummy(dag, [dag.genesis_hash()], 1)
        watcher.on_new_block_by_validator(block1_hash, 1, actor2)

        block2_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        watcher.on_new_block_by_validator(block2_hash, 1, actor2)

        block2c_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        watcher.on_new_block_by_validator(block2c_hash, 1, actor2)

        tops = dag.get_top_hashes()

        explicits, candidates = watcher.find_conflicts_in_between(tops)
        self.assertEqual(len(explicits), 2)
        self.assertEqual(len(candidates), 0)
        self.assertIn(block2_hash, explicits)
        self.assertIn(block2c_hash, explicits)
Beispiel #13
0
    def test_recursive_sequence_found(self):
        dag = Dag(0)
        conf_req = ConfirmationRequirement(dag)

        genesis_hash = dag.genesis_block().get_hash()

        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 2
        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 3

        block_hash = ChainGenerator.insert_dummy(dag, dag.get_top_hashes(), 2)
        conf_req.blocks[block_hash] = 3

        last_block_in_seq_hash = ChainGenerator.insert_dummy(
            dag, [genesis_hash], 1)
        conf_req.blocks[last_block_in_seq_hash] = 3
        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 3

        block_hash = ChainGenerator.insert_dummy(
            dag, [last_block_in_seq_hash, block_hash], 2)
        conf_req.blocks[block_hash] = 4

        block_hash = ChainGenerator.insert_dummy(dag, dag.get_top_hashes(), 3)
        conf_req.blocks[block_hash] = 4

        block_hash = ChainGenerator.insert_dummy(dag, dag.get_top_hashes(), 4)

        # DagVisualizer.visualize(dag, True) # take a look to understand what's going on

        # there will be only two blocks with consecutive 4 behind, which is not enough to increase
        best_requirement = conf_req.choose_next_best_requirement(block_hash)
        self.assertEqual(best_requirement, 4)

        # make three blocks with consecutive 4 behind
        # it should lead to following block increasing requirement value
        conf_req.blocks[last_block_in_seq_hash] = 4
        best_requirement = conf_req.choose_next_best_requirement(block_hash)
        self.assertEqual(best_requirement, 5)
    def test_merged_dag(self):
        dag = Dag(0)
        # generate test case
        # time_slot [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        # ----------------------------------------
        # 1 ------- [0, 1, 2, 3, 4]
        # 2 ------- [-, -, 2, s, s]
        # 3 ------- [-, -, 2, s, s]
        # 4 ------- [-, -, 2, 3, s]
        # s - same block (merged)
        conf_req = ConfirmationRequirement(dag)

        genesis_hash = dag.genesis_block().get_hash()

        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 2
        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 3
        block_hash = ChainGenerator.insert_dummy(dag, dag.get_top_hashes(), 2)
        conf_req.blocks[block_hash] = 3
        last_block_in_seq_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[last_block_in_seq_hash] = 3
        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 3
        block_hash = ChainGenerator.insert_dummy(dag, [last_block_in_seq_hash, block_hash], 2)
        conf_req.blocks[block_hash] = 4
        block_hash = ChainGenerator.insert_dummy(dag, dag.get_top_hashes(), 3)
        conf_req.blocks[block_hash] = 4
        top_hash = ChainGenerator.insert_dummy(dag, dag.get_top_hashes(), 4)

        # DagVisualizer.visualize(dag)

        conflict_finder = ConflictFinder(dag)
        top_blocks = list(dag.get_top_blocks().keys())
        top, conflicts = conflict_finder.find_conflicts(top_blocks)
        self.assertEqual(top, top_hash)  # strong determined top
        # CHAIN ALREADY MERGED
        self.assertEqual(len(conflicts), 0)
Beispiel #15
0
    def test_skips_and_restoring(self):
        dag = Dag(0)
        conf_req = ConfirmationRequirement(dag)

        genesis_hash = dag.genesis_block().get_hash()

        block_hash = ChainGenerator.insert_dummy(dag, [genesis_hash], 1)
        conf_req.blocks[block_hash] = 5
        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 5)

        # confirmation requirement decreases because we have large skip
        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 4)

        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 6)
        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 7)

        #we still have 4 here
        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 4)

        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 8)

        #but we have restored to 5 here, because of 3 previous consecutive blocks
        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 5)

        #let's skip one
        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 10)

        block_hash = ChainGenerator.insert_dummy(dag, [block_hash], 11)

        # DagVisualizer.visualize(dag, True) # take a look to understand what's going on

        #not affected by small skip
        confirmation_requirement = conf_req.get_confirmation_requirement(
            block_hash)
        self.assertEqual(confirmation_requirement, 5)
Beispiel #16
0
    def test_different_epoch_watch(self):
        dag = Dag(0)
        conflict_watcher = ConflictWatcher(dag)

        actor1 = Private.publickey(Private.generate())
        actor2 = Private.publickey(Private.generate())
        actor3 = Private.publickey(Private.generate())

        block1_hash = ChainGenerator.insert_dummy(dag, [dag.genesis_hash()], 1)
        conflict_watcher.on_new_block_by_validator(block1_hash, 1, actor1)

        block2_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        conflict_watcher.on_new_block_by_validator(block2_hash, 1, actor2)

        block2c_hash = ChainGenerator.insert_dummy(dag, [block1_hash], 2)
        conflict_watcher.on_new_block_by_validator(block2c_hash, 1, actor2)

        block3_hash = ChainGenerator.insert_dummy(dag,
                                                  [block2_hash, block2c_hash],
                                                  3)
        conflict_watcher.on_new_block_by_validator(block3_hash, 1, actor3)

        #switch to next epoch
        block4_hash = ChainGenerator.insert_dummy(dag, [block3_hash], 4)
        conflict_watcher.on_new_block_by_validator(block4_hash, 2, actor2)

        block4c_hash = ChainGenerator.insert_dummy(dag, [block3_hash], 4)
        conflict_watcher.on_new_block_by_validator(block4c_hash, 2, actor2)

        #first epoch conflicts
        conflicts = conflict_watcher.get_conflicts_by_block(block2_hash)
        self.assertEqual(len(conflicts), 2)
        self.assertIn(block2_hash, conflicts)
        self.assertIn(block2c_hash, conflicts)

        #second epoch conflicts of the same public key
        conflicts = conflict_watcher.get_conflicts_by_block(block4_hash)
        self.assertEqual(len(conflicts), 2)
        self.assertIn(block4_hash, conflicts)
        self.assertIn(block4c_hash, conflicts)

        conflicts = conflict_watcher.get_conflicts_by_block(block1_hash)
        self.assertEqual(conflicts, None)