Example #1
0
    def test_new_peer_replace_old(self):  # make sure that if all original peers crash the committee can proceed
        peers = make_sawtooth_committee(7)
        blockchain_size = 1
        for i in range(13):
            peers.append(SawtoothContainer())
            peers[-1].join_sawtooth([p.ip() for p in peers])
            # wait for blockchain catch up
            done = False
            start = time.time()
            while not done:
                if len(peers[-1].blocks()['data']) >= blockchain_size - 1:  # catch up cant get last tx
                    done = True
                elif time.time() - start > 30:
                    self.fail("New peers block catch up failed")
            peers[i % 4].update_committee([p.val_key() for p in peers])
            self.assertTrue(check_for_confirmation(peers, blockchain_size))
            blockchain_size += 1

        for _ in range(4):
            del peers[0]
        gc.collect()  # make sure that the containers are shutdown

        time.sleep(VIEW_CHANGE_WAIT_TIME_SEC + 30)  # wait for view change (timeout + time to do the view change)
        peers[0].submit_tx('test', '999')
        blockchain_size += 1
        self.assertTrue(check_for_confirmation(peers, blockchain_size, 'test'))

        for p in peers:
            print(p.ip())
            self.assertEqual(blockchain_size, len(p.blocks()['data']))
Example #2
0
    def test_peer_leave(self):
        intersections = make_peer_committees(7)
        number_of_tx = 1
        id_a = intersections[0].committee_id_a
        id_b = intersections[0].committee_id_b
        old_peer = intersections.pop()
        intersections[0].update_committee(id_a, [inter.val_key(id_a) for inter in intersections])
        intersections[0].update_committee(id_b, [inter.val_key(id_b) for inter in intersections])
        number_of_tx += 1
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx))
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections], number_of_tx))

        for inter in intersections:
            self.assertEqual(number_of_tx, len(inter.blocks(id_a)))
            self.assertEqual(number_of_tx, len(inter.blocks(id_b)))
        del old_peer

        tx_a = Transaction(id_a, 1)
        tx_a.key = 'test'
        tx_a.value = '999'
        tx_b = Transaction(id_b, 1)
        tx_b.key = 'test'
        tx_b.value = '888'

        # check consensus still works
        intersections[-1].submit(tx_a)
        intersections[-1].submit(tx_b)
        number_of_tx += 1
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx, 'test'))
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections], number_of_tx, 'test'))
        for inter in intersections:
            self.assertEqual(number_of_tx, len(inter.blocks(id_a)))
            self.assertEqual(number_of_tx, len(inter.blocks(id_b)))
Example #3
0
    def test_concurrent_large_committee(self):
        # if this fails then the following setting may need to be set in /etc/sysctl.conf
        #
        # # Setup DNS threshold for arp
        # net.ipv4.neigh.default.gc_thresh3 = 16384
        # net.ipv4.neigh.default.gc_thresh2 = 8192
        # net.ipv4.neigh.default.gc_thresh1 = 4096
        # this should work if default linux settings are being used
        peers1 = make_sawtooth_committee(30)
        peers2 = make_sawtooth_committee(30)
        number_of_tx = 1  # genesis

        peers1[0].submit_tx('test', '999')
        peers2[0].submit_tx('test', '999')
        number_of_tx += 1
        time.sleep(0.5)

        peers1[1].submit_tx('test1', '888')
        peers2[1].submit_tx('test1', '888')
        number_of_tx += 1
        time.sleep(0.5)

        peers1[2].submit_tx('test2', '777')
        peers2[2].submit_tx('test2', '777')
        number_of_tx += 1

        self.assertTrue(check_for_confirmation(peers1, number_of_tx, 'test2'))
        self.assertTrue(check_for_confirmation(peers2, number_of_tx, 'test2'))
        for p in peers1:
            blocks = p.blocks()['data']
            self.assertEqual(number_of_tx, len(blocks), p.ip())
        for p in peers2:
            blocks = p.blocks()['data']
            self.assertEqual(number_of_tx, len(blocks), p.ip())
Example #4
0
    def test_peer_join(self):
        peers = make_sawtooth_committee(7)
        number_of_tx = 1  # genesis
        peers[0].submit_tx('test', '999')
        number_of_tx += 1
        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test'))

        peers[1].submit_tx('test1', '888')
        number_of_tx += 1
        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test1'))

        peers.append(SawtoothContainer())
        peers[-1].join_sawtooth([p.ip() for p in peers])

        # wait for block catch up
        done = False
        start = time.time()
        while not done:
            if len(peers[-1].blocks()['data']) >= number_of_tx - 1:  # catch up cant get last tx
                done = True
            elif time.time() - start > 30:
                self.fail("New peers block catch up failed")

        peers[0].update_committee([p.val_key() for p in peers])
        number_of_tx += 1  # +1 for membership of new peer
        time.sleep(VIEW_CHANGE_WAIT_TIME_SEC)  # wait in case leader has to change

        # submit new tx with new peer so it can finally match all the others (i.e. has full blockchain)
        peers[2].submit_tx('test2', '777')
        number_of_tx += 1
        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test2'))

        # makes sure all peers are configured to work with each other (this is not a test of connectivity just config)
        # and make sure they all have the whole blockchain
        ips = [p.ip() for p in peers]
        for p in peers:
            peers_blocks = len(p.blocks()['data'])
            self.assertEqual(number_of_tx, peers_blocks, p.ip())

            peers_config = p.sawtooth_api('http://localhost:8008/peers')['data']
            for ip in ips:
                if ip != p.ip():  # the peer it's self is not reported in the list
                    self.assertIn("tcp://{}:8800".format(ip), peers_config)

        # check consensus still works
        peers[-1].submit_tx('test3', '666')
        number_of_tx += 1
        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test3'))
        for p in peers:
            peers_blockchain = len(p.blocks()['data'])
            self.assertEqual(number_of_tx, peers_blockchain, p.ip())
Example #5
0
    def test_committee_independent_leave(self):
        intersections = make_peer_committees(7)
        number_of_tx_a = 1
        number_of_tx_b = 1
        id_a = intersections[0].committee_id_a
        id_b = intersections[0].committee_id_b

        # we need to drop only one instance make sure other committee is unaffected
        old_instance = intersections[-1].instance_b

        committee_val_b = [inter.val_key(id_b) for inter in intersections[:-1]]

        intersections[0].update_committee(id_b, committee_val_b)
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections], number_of_tx_b))
        number_of_tx_b += 1
        del old_instance
        gc.collect()
        intersections[-1].instance_b = None
        intersections[-1].committee_id_b = None

        tx_a = Transaction(id_a, 1)
        tx_a.key = 'test'
        tx_a.value = '999'
        tx_b = Transaction(id_b, 1)
        tx_b.key = 'test'
        tx_b.value = '888'

        intersections[-1].submit(tx_a)
        number_of_tx_a += 1
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx_a, 'test'))
        intersections[0].submit(tx_b)
        number_of_tx_b += 1
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections[:-1]], number_of_tx_b, 'test'))

        for inter in intersections:
            self.assertEqual(number_of_tx_a, len(inter.blocks(id_a)))

        for inter in intersections[:-1]:
            self.assertEqual(number_of_tx_b, len(inter.blocks(id_b)))

        self.assertEqual(None, intersections[-1].blocks(id_b))

        # confirm membership
        committee_b = intersections.copy()[:-1]
        committee_ips_b = [inter.ip(id_b) for inter in intersections[:-1]]
        for inter in committee_b:
            intersections_config = inter.sawtooth_api(id_b, 'http://localhost:8008/peers')['data']
            for ip in committee_ips_b:
                if ip != inter.ip(id_b):  # the peer it's self is not reported in the list
                    self.assertIn("tcp://{}:8800".format(ip), intersections_config)
Example #6
0
    def test_committee_churn(self):
        self.skipTest("Complete committee churn not supported")
        peers = make_sawtooth_committee(7)
        blockchain_size = 1

        peers[0].submit_tx('start', '1')
        blockchain_size += 1
        self.assertTrue(check_for_confirmation(peers, blockchain_size, 'start'))

        for i in range(7):
            # add new peer
            peers.append(SawtoothContainer())
            peers[-1].join_sawtooth([p.ip() for p in peers])
            # wait for blockchain catch up
            done = False
            start = time.time()
            while not done:
                if len(peers[-1].blocks()['data']) >= blockchain_size - 1:  # catch up cant get last tx
                    done = True
                elif time.time() - start > 30:
                    self.fail("New peers block catch up failed")
            peers[0].update_committee([p.val_key() for p in peers])
            peers[0].submit_tx("update_{}".format(i), 999)
            blockchain_size += 1
            self.assertTrue(check_for_confirmation(peers, blockchain_size, "update_{}".format(i),
                                                   timeout=VIEW_CHANGE_WAIT_TIME_SEC))
            blockchain_size += 1

            for p in peers:
                self.assertEqual(blockchain_size, len(p.blocks()['data']))

            old_peer = peers.pop(0)
            peers[0].update_committee([p.val_key() for p in peers])
            self.assertTrue(check_for_confirmation(peers, blockchain_size))
            blockchain_size += 1

            self.assertTrue(check_for_confirmation(peers, blockchain_size, 'test_{}'.format(i)))
            for p in peers:
                self.assertEqual(blockchain_size, len(p.blocks()['data']))

            del old_peer
            gc.collect()  # make sure that the containers are shutdown

        peers[0].submit_tx('test', '999')
        blockchain_size += 1
        self.assertTrue(check_for_confirmation(peers, blockchain_size, 'test'))
        for p in peers:
            self.assertEqual(blockchain_size, len(p.blocks()['data']))
            self.assertEqual('999', p.get_tx('test'))
Example #7
0
    def test_concurrent_committees(self):
        set_a = make_sawtooth_committee(20)
        set_b = make_sawtooth_committee(20)
        tx_a = 'test_a'
        tx_b = 'test_b'
        set_a[0].submit_tx(tx_a, '999')
        set_b[0].submit_tx(tx_b, '888')
        self.assertTrue(check_for_confirmation(set_a, 2, tx_a))
        self.assertTrue(check_for_confirmation(set_b, 2, tx_b))
        for p in set_a:
            self.assertEqual(2, len(p.blocks()['data']))
        for p in set_b:
            self.assertEqual(2, len(p.blocks()['data']))

        set_b[0].submit_tx('test_b_2', '777')
        self.assertTrue(check_for_confirmation(set_b, 3, tx_b))
Example #8
0
    def test_committee_shrink(self):
        peers = make_sawtooth_committee(15)
        blockchain_size = 1
        for i in range(11):
            old_peer = peers.pop()
            peers[0].update_committee([p.val_key() for p in peers])
            self.assertTrue(check_for_confirmation(peers, blockchain_size))
            blockchain_size += 1
            time.sleep(VIEW_CHANGE_WAIT_TIME_SEC)  # wait for potential view change
            del old_peer
            gc.collect()  # make sure that the containers are shutdown

        peers[0].submit_tx('test', '999')
        blockchain_size += 1
        self.assertTrue(check_for_confirmation(peers, blockchain_size, 'test'))
        for p in peers:
            self.assertEqual(blockchain_size, len(p.blocks()['data']))
            self.assertEqual('999', p.get_tx('test'))
Example #9
0
    def test_committee_growth(self):
        peers = make_sawtooth_committee(7)
        number_of_tx = 1

        peers[0].submit_tx('test', '999')
        number_of_tx += 1
        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test', timeout=120))

        peers[1].submit_tx('test1', '888')
        number_of_tx += 1
        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test1', timeout=120))

        for i in range(13):
            peers.append(SawtoothContainer())
            peers[-1].join_sawtooth([p.ip() for p in peers])
            # wait for blockchain catch up
            done = False
            start = time.time()
            while not done:
                if len(peers[-1].blocks()['data']) >= number_of_tx - 1:  # catch up cant get last tx
                    done = True
                elif time.time() - start > 30:
                    self.fail("New peers block catch up failed")

            peers[i].update_committee([p.val_key() for p in peers])
            self.assertTrue(check_for_confirmation(peers, number_of_tx, timeout=120))
            number_of_tx += 1  # +1 for membership of new peer

            # check consensus still works
            peers[i].submit_tx('test_{}'.format(i), '777')
            number_of_tx += 1
            self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test_{}'.format(i), timeout=120))

            # makes sure all peers are configured to work with each other (this only tests config not connectivity)
            ips = [p.ip() for p in peers]
            for p in peers:
                peers_blocks = len(p.blocks()['data'])
                self.assertGreaterEqual(number_of_tx, peers_blocks)

                peers_config = p.sawtooth_api('http://localhost:8008/peers')['data']
                for ip in ips:
                    if ip != p.ip():  # the peer it's self is not reported in the list
                        self.assertIn("tcp://{}:8800".format(ip), peers_config)
Example #10
0
    def test_peer_leave(self):
        peers = make_sawtooth_committee(8)
        blockchain_size = 1

        old_peer = peers.pop()
        peers[0].update_committee([p.val_key() for p in peers])
        self.assertTrue(check_for_confirmation(peers, blockchain_size))
        blockchain_size += 1

        for p in peers:
            self.assertEqual(blockchain_size, len(p.blocks()['data']))

        del old_peer
        gc.collect()  # make sure that the containers are shutdown

        # make sure consensus still works
        peers[0].submit_tx('test', '999')
        blockchain_size += 1
        self.assertTrue(check_for_confirmation(peers, blockchain_size, 'test'))
        for p in peers:
            self.assertEqual('999', p.get_tx('test'))
            self.assertEqual(blockchain_size, len(p.blocks()['data']))
Example #11
0
    def test_high_transaction_load(self):
        peers = make_sawtooth_committee(5)
        number_of_tx = 1
        i = 0
        for _ in range(10):  # peers start to drop old blocks at 100
            peers[i].submit_tx('test{}'.format(number_of_tx), '999')

            i = i + 1 if i < (len(peers) - 1) else 0  # cycle peers

            number_of_tx += 1
            time.sleep(1.5)  # prevent DOS attack counter measure

        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test{}'.format(number_of_tx - 1)))
        for p in peers:
            self.assertEqual(number_of_tx, len(p.blocks()['data']))
Example #12
0
    def test_committee_independent_confirmation(self):
        intersections = make_peer_committees(5)
        number_of_tx = 1
        id_a = intersections[0].committee_id_a
        id_b = intersections[0].committee_id_b
        number_of_tx_a = number_of_tx
        number_of_tx_b = number_of_tx
        tx_a = Transaction(id_a, 1)
        tx_a.key = 'test2'
        tx_a.value = '999'
        intersections[-1].submit(tx_a)
        number_of_tx_a += 1
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx, 'test2'))
        for inter in intersections:
            a_blocks = len(inter.blocks(id_a))
            b_blocks = len(inter.blocks(id_b))

            self.assertEqual(number_of_tx_a, a_blocks)
            self.assertEqual(number_of_tx_b, b_blocks)
Example #13
0
    def test_fault_tolerance(self):
        peers = make_sawtooth_committee(9)
        number_of_tx = 1  # genesis

        del peers[0]
        peers[0].submit_tx('test', '999')
        number_of_tx += 1
        # can take some time for peers to commit (potentially 5 min for failed leader)
        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test{}'.format(number_of_tx - 1),
                                               timeout=VIEW_CHANGE_WAIT_TIME_SEC * len(peers)))
        for p in peers:
            self.assertEqual(number_of_tx, len(p.blocks()['data']), "Peers did not commit tx in time")

        # should fail now
        del peers[:5]
        peers[0].submit_tx('fail', '000')
        time.sleep(VIEW_CHANGE_WAIT_TIME_SEC * len(peers))  # give it plenty of time to be confirmed + 30 for buffer
        for p in peers:
            peers_blockchain = len(p.blocks()['data'])
            self.assertEqual(number_of_tx, peers_blockchain, p.ip())
Example #14
0
    def test_large_committee(self):

        peers = make_sawtooth_committee(30)
        number_of_tx = 1  # genesis

        peers[0].submit_tx('test', '999')
        number_of_tx += 1
        time.sleep(0.5)

        peers[1].submit_tx('test1', '888')
        number_of_tx += 1
        time.sleep(0.5)

        peers[2].submit_tx('test2', '777')
        number_of_tx += 1

        self.assertTrue(check_for_confirmation(peers, number_of_tx, 'test2'))

        for p in peers:
            blocks = p.blocks()['data']
            self.assertEqual(number_of_tx, len(blocks), p.ip())
Example #15
0
    def test_peer_join(self):
        intersections = make_peer_committees(7)
        id_a = intersections[0].committee_id_a
        id_b = intersections[0].committee_id_b

        intersections[0].submit(Transaction(id_a, 'update_a_1', 999))
        number_of_tx = 2
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx, 'update_a_1', ))
        intersections[0].submit(Transaction(id_b, 'update_b_1', 999))
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections], number_of_tx, 'update_b_1', ))

        intersections.append(Intersection(SawtoothContainer(), SawtoothContainer(), id_a, id_b))
        committee_ips_a = [inter.instance_a.ip() for inter in intersections]
        committee_ips_b = [inter.instance_b.ip() for inter in intersections]

        intersections[-1].peer_join(id_a, committee_ips_a)
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx - 1))  # catch up
        intersections[0].update_committee(id_a, [inter.instance_a.val_key() for inter in intersections])
        number_of_tx += 1
        intersections[0].submit(Transaction(id_a, 'update_a_2', 888))
        number_of_tx += 1
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx, 'update_a_2'))

        intersections[-1].peer_join(id_b, committee_ips_b)
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx - 1))  # catch up
        intersections[0].update_committee(id_b, [inter.instance_b.val_key() for inter in intersections])
        intersections[0].submit(Transaction(id_b, 'update_b_2', 888))
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx, 'update_b_2'))

        # makes sure all intersections are configured to work with each other (this is not a test of connectivity
        # just config) and make sure they all have the three tx
        for inter in intersections:
            intersections_config = inter.sawtooth_api(id_a, 'http://localhost:8008/peers')['data']
            for ip in committee_ips_a:
                if ip != inter.ip(id_a):  # the peer it's self is not reported in the list
                    self.assertIn("tcp://{}:8800".format(ip), intersections_config)

            intersections_config = inter.sawtooth_api(id_b, 'http://localhost:8008/peers')['data']
            for ip in committee_ips_b:
                if ip != inter.ip(id_b):
                    self.assertIn("tcp://{}:8800".format(ip), intersections_config)
Example #16
0
    def test_committee_independent_join(self):
        intersections = make_peer_committees(7)
        number_of_tx_a = 1
        id_a = intersections[0].committee_id_a

        new_peer = Intersection(SawtoothContainer(), None, id_a, None)

        committee_ips_a = [inter.ip(id_a) for inter in intersections]
        committee_ips_a.append(new_peer.ip(id_a))

        committee_val_a = [inter.val_key(id_a) for inter in intersections]
        committee_val_a.append(new_peer.val_key(id_a))

        intersections[0].submit(Transaction(id_a, 'update_a_1', 999))
        number_of_tx_a += 1
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx_a, 'update_a_1'))

        new_peer.peer_join(id_a, committee_ips_a)
        intersections[0].update_committee(id_a, committee_val_a)
        number_of_tx_a += 1

        intersections[0].submit(Transaction(id_a, 'update_a_2', 888))
        number_of_tx_a += 1
        self.assertTrue(check_for_confirmation([i.instance_a for i in intersections], number_of_tx_a, 'update_a_2'))

        # confirm membership
        committee_a = intersections.copy()
        committee_a.append(new_peer)
        self.assertEqual(None, new_peer.committee_id_b)
        for inter in committee_a:
            intersections_config = inter.sawtooth_api(id_a, 'http://localhost:8008/peers')['data']
            for ip in committee_ips_a:
                if ip != inter.ip(id_a):  # the peer it's self is not reported in the list
                    self.assertIn("tcp://{}:8800".format(ip), intersections_config)
        for inter in committee_a:
            self.assertEqual(number_of_tx_a, len(inter.blocks(id_a)))

        # now committee B
        id_b = intersections[0].committee_id_b
        number_of_tx_b = 1
        new_peer = Intersection(None, SawtoothContainer(), None, id_b)

        committee_ips_b = [inter.ip(id_b) for inter in intersections]
        committee_ips_b.append(new_peer.ip(id_b))

        committee_val_b = [inter.val_key(id_b) for inter in intersections]
        committee_val_b.append(new_peer.val_key(id_b))

        intersections[0].submit(Transaction(id_b, 'update_b_1', 999))
        number_of_tx_b += 1
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections], number_of_tx_b, 'update_b_1'))

        new_peer.peer_join(id_b, committee_ips_b)
        intersections[0].update_committee(id_b, committee_val_b)
        number_of_tx_b += 1
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections], number_of_tx_b))

        intersections[0].submit(Transaction(id_b, 'update_b_2', 888))
        number_of_tx_b += 1
        self.assertTrue(check_for_confirmation([i.instance_b for i in intersections], number_of_tx_b, 'update_b_2'))

        # confirm membership
        committee_b = intersections.copy()
        committee_b.append(new_peer)
        for inter in committee_b:
            intersections_config = inter.sawtooth_api(id_b, 'http://localhost:8008/peers')['data']
            for ip in committee_ips_b:
                if ip != inter.ip(id_b):  # the peer it's self is not reported in the list
                    self.assertIn("tcp://{}:8800".format(ip), intersections_config)
        for inter in committee_b:
            self.assertEqual(number_of_tx_b, len(inter.blocks(id_b)))