Beispiel #1
0
 def start(quorum_id_a=None, quorum_id_b=None):
     if app.config[PBFT_INSTANCES] is not None:
         app.logger.warning("peer has already started, restarting")
         del app.config[PBFT_INSTANCES]
     instance_a = SawtoothContainer()
     instance_b = SawtoothContainer()
     app.config[PBFT_INSTANCES] = Intersection(instance_a, instance_b,
                                               quorum_id_a, quorum_id_b)
     app.config[QUORUMS][quorum_id_a] = []
     app.config[QUORUMS][quorum_id_b] = []
     return ROUTE_EXECUTED_CORRECTLY
Beispiel #2
0
def make_sawtooth_committee(size: int, network=DEFAULT_DOCKER_NETWORK):
    if size < 4:
        logging.error(
            "COMMITTEE IMPOSSIBLE: can not make committees of less then 4 members, {} asked for"
            .format(size))
        return []
    if size < 7:
        logging.warning(
            "COMMITTEE UNSTABLE: making committees of less then 7 members can lead to issues with adding "
            "and removing. ")
    peers = [SawtoothContainer(network) for _ in range(size)]
    peers[0].make_genesis([p.val_key() for p in peers],
                          [p.user_key() for p in peers])

    committee_ips = [p.ip() for p in peers]
    for p in peers:
        p.join_sawtooth(committee_ips)

    # if the there are a lot of containers running wait longer for process to start
    time.sleep(5 * size)

    done = False
    while not done:
        done = True
        for p in peers:
            if len(p.blocks()['data']) < 1:
                logging.info("Peer {ip} could not get genesis block\n"
                             "     blocks:{b}".format(ip=p.ip(),
                                                      b=p.blocks()['data']))
                done = False
                time.sleep(0.5)
                break

    return peers
Beispiel #3
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']))
Beispiel #4
0
    def test_start_with_peer(self):
        a = SawtoothContainer()
        b = SawtoothContainer()
        id_a = 'a'
        id_b = 'b'
        p = Intersection(a, b, id_a, id_b)

        app = api.create_app(p)
        app.config['TESTING'] = True
        app.config['DEBUG'] = False
        client = app.test_client()

        docker = docker_api.from_env()
        # get info on container a
        container_ip = docker.containers.list()[1].exec_run(
            "hostname -i").output.decode('utf-8').strip()
        container_val_key = docker.containers.list()[1].exec_run("cat {val_pub}".format(val_pub=VKEY["pub"])) \
            .output.decode('utf-8').strip()
        container_user_key = docker.containers.list()[1].exec_run("cat {user_pub}".format(user_pub=UKEY["pub"])) \
            .output.decode('utf-8').strip()

        self.assertEqual(get_plain_text(client.get('/ip/a')), container_ip)
        self.assertEqual(get_plain_text(client.get('/val+key/a')),
                         container_val_key)
        self.assertEqual(get_plain_text(client.get('/user+key/a')),
                         container_user_key)
        self.assertNotEqual(get_plain_text(client.get('/val+key/a')),
                            get_plain_text(client.get('/user+key/a')))

        # get info on container b
        container_ip = docker.containers.list()[0].exec_run(
            "hostname -i").output.decode('utf-8').strip()
        container_val_key = docker.containers.list()[0].exec_run("cat {val_pub}".format(val_pub=VKEY["pub"])) \
            .output.decode('utf-8').strip()
        container_user_key = docker.containers.list()[0].exec_run("cat {user_pub}".format(user_pub=UKEY["pub"])) \
            .output.decode('utf-8').strip()

        self.assertEqual(get_plain_text(client.get('/ip/b')), container_ip)
        self.assertEqual(get_plain_text(client.get('/val+key/b')),
                         container_val_key)
        self.assertEqual(get_plain_text(client.get('/user+key/b')),
                         container_user_key)
        self.assertNotEqual(get_plain_text(client.get('/val+key/b')),
                            get_plain_text(client.get('/user+key/b')))
    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)
Beispiel #6
0
    def test_setting_instances(self):
        a = SawtoothContainer()
        b = SawtoothContainer()
        inter = Intersection(a, b, 'a', 'b')
        peer = SmartShardPeer(inter)
        peer.start()
        client = peer.app.api.test_client()

        docker = docker_api.from_env()
        # get info on container a
        container_ip = docker.containers.list()[1].exec_run(
            "hostname -i").output.decode('utf-8').strip()
        container_val_key = docker.containers.list()[1].exec_run("cat {val_pub}".format(val_pub=VKEY["pub"])) \
            .output.decode('utf-8').strip()
        container_user_key = docker.containers.list()[1].exec_run("cat {user_pub}".format(user_pub=UKEY["pub"])) \
            .output.decode('utf-8').strip()

        self.assertEqual(get_plain_text(client.get('/ip/a')), container_ip)
        self.assertEqual(get_plain_text(client.get('/val+key/a')),
                         container_val_key)
        self.assertEqual(get_plain_text(client.get('/user+key/a')),
                         container_user_key)
        self.assertNotEqual(get_plain_text(client.get('/val+key/a')),
                            get_plain_text(client.get('/user+key/a')))

        # get info on container b
        container_ip = docker.containers.list()[0].exec_run(
            "hostname -i").output.decode('utf-8').strip()
        container_val_key = docker.containers.list()[0].exec_run("cat {val_pub}".format(val_pub=VKEY["pub"])) \
            .output.decode('utf-8').strip()
        container_user_key = docker.containers.list()[0].exec_run("cat {user_pub}".format(user_pub=UKEY["pub"])) \
            .output.decode('utf-8').strip()

        self.assertEqual(get_plain_text(client.get('/ip/b')), container_ip)
        self.assertEqual(get_plain_text(client.get('/val+key/b')),
                         container_val_key)
        self.assertEqual(get_plain_text(client.get('/user+key/b')),
                         container_user_key)
        self.assertNotEqual(get_plain_text(client.get('/val+key/b')),
                            get_plain_text(client.get('/user+key/b')))
    def test_committee_setup_single(self):
        id_a = '1'
        id_b = '2'

        containers_a = [SawtoothContainer() for _ in range(4)]
        user_keys_a = [i.user_key() for i in containers_a]
        val_keys_a = [i.val_key() for i in containers_a]
        committee_ips_a = [i.ip() for i in containers_a]

        containers_b = [SawtoothContainer() for _ in range(4)]
        user_keys_b = [i.user_key() for i in containers_b]
        val_keys_b = [i.val_key() for i in containers_b]
        committee_ips_b = [i.ip() for i in containers_b]

        intersections = [Intersection(containers_a[i], containers_b[i], id_a, id_b) for i in range(4)]

        intersections[0].make_genesis(id_a, val_keys_a, user_keys_a)
        intersections[0].make_genesis(id_b, val_keys_b, user_keys_b)

        for inter in intersections:
            inter.start_sawtooth(committee_ips_a, committee_ips_b)

        # make sure genesis is in every peer and that they can communicate with other committee members
        self.assertEqual(len(intersections), 4)
        for inter in intersections:
            self.assertEqual(len(inter.blocks(id_a)), 1)

        for inter in intersections:
            self.assertEqual(len(inter.blocks(id_b)), 1)

        # make sure util func works
        del containers_a
        del containers_b
        intersections = make_peer_committees(4)
        self.assertEqual(len(intersections), 4)
        for inter in intersections:
            self.assertEqual(len(inter.blocks(id_a)), 1)

        for inter in intersections:
            self.assertEqual(len(inter.blocks(id_b)), 1)
Beispiel #8
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())
Beispiel #9
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'))
Beispiel #10
0
    def test_peer_setup(self):
        a = SawtoothContainer()
        b = SawtoothContainer()
        id_a = '1'
        id_b = '2'
        inter = Intersection(a, b, id_a, id_b)

        self.assertEqual(inter.committee_id_a, id_a)
        self.assertEqual(inter.committee_id_b, id_b)
        self.assertEqual(inter.ip(id_a), a.ip())
        self.assertEqual(inter.ip(id_b), b.ip())
        self.assertEqual(inter.attached_network(), DEFAULT_DOCKER_NETWORK)
        self.assertTrue(inter.in_committee(id_a))
        self.assertTrue(inter.in_committee(id_b))
        self.assertFalse(inter.in_committee('c'))
        self.assertFalse(inter.in_committee(0))

        del a, b, inter
        a = SawtoothContainer('host')
        b = SawtoothContainer('host')
        id_a = '1'
        id_b = '2'
        inter = Intersection(a, b, id_a, id_b)
        self.assertEqual(inter.attached_network(), 'host')
Beispiel #11
0
    def test_committee_init_setup(self):
        docker = docker_api.from_env()

        # a committee needs a min of 4 members. Any less peers can not join or leave cleanly and they can not confirm
        # new transactions
        peers = [None, None, None, None]
        for i in range(len(peers)):
            peers[i] = SawtoothContainer()

        # make sure all containers have started
        self.assertEqual(4, len(docker.containers.list()))

        peers[0].make_genesis([p.val_key() for p in peers], [p.user_key() for p in peers])
        committee_ips = [p.ip() for p in peers]
        for p in peers:
            p.join_sawtooth(committee_ips)

        # make sure all peers are running
        process_names = []
        for p in peers:
            for process in p.top()['Processes']:
                process_names.append(process[-1])
            self.assertIn('sawtooth-validator', [i for i in process_names if 'sawtooth-validator' in i][0])
            self.assertIn('/usr/bin/python3 /usr/bin/sawtooth-rest-api -v', process_names)
            self.assertIn('settings-tp -v', process_names)
            self.assertIn('/usr/bin/python3 /usr/bin/intkey-tp-python -v', process_names)
            self.assertIn('pbft-engine -vv --connect',
                          [i for i in process_names if 'pbft-engine -vv --connect' in i][0])

        # give the genesis block some time to get to all peers
        time.sleep(3)

        # makes sure genesis block is in each peer
        for p in peers:
            blocks = p.blocks()['data']
            self.assertEqual(1, len(blocks))

        # makes sure all peers are configured to work with each other (this is not a test of connectivity just config)
        ips = [p.ip() for p in peers]
        admin = peers[0].admin_key()  # peer 0 made genesis so it has the admin key make sure all other peers get it
        for p in peers:
            self.assertEqual(admin, p.admin_key())
            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)

        docker.close()
Beispiel #12
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)
Beispiel #13
0
    def test_kill_container(self):
        docker = docker_api.from_env()

        sawtooth_instance = SawtoothContainer()
        self.assertEqual(1, len(docker.containers.list()))
        self.assertIn(sawtooth_instance.id(), get_container_ids())

        sawtooth_instance_2nd = SawtoothContainer()
        self.assertEqual(2, len(docker.containers.list()))
        self.assertIn(sawtooth_instance.id(), get_container_ids())
        self.assertIn(sawtooth_instance_2nd.id(), get_container_ids())

        # test that if one instance is stop only one instance stops
        del sawtooth_instance
        self.assertEqual(1, len(docker.containers.list()))
        self.assertIn(sawtooth_instance_2nd.id(), get_container_ids())

        del sawtooth_instance_2nd
        self.assertEqual(0, len(docker.containers.list()))

        # clean up
        docker.close()
Beispiel #14
0
    def test_start_container(self):
        docker = docker_api.from_env()

        # test that once an instance is started that it has an id, ip and key
        sawtooth_instance = SawtoothContainer()
        self.assertEqual(1, len(docker.containers.list()))
        self.assertIsNot(sawtooth_instance.id(), None)
        self.assertIsNot(sawtooth_instance.ip(), None)
        self.assertIsNot(sawtooth_instance.val_key(), None)

        container_ip = docker.containers.list()[0].exec_run("hostname -i").output.decode('utf-8').strip()
        container_val_key = docker.containers.list()[0].exec_run("cat {val_pub}".format(val_pub=VALIDATOR_KEY["pub"])) \
            .output.decode('utf-8').strip()
        container_user_key = docker.containers.list()[0].exec_run("cat {user_pub}".format(user_pub=USER_KEY["pub"])) \
            .output.decode('utf-8').strip()
        container_network = DEFAULT_DOCKER_NETWORK

        self.assertEqual(sawtooth_instance.id(), docker.containers.list()[0].id)
        self.assertEqual(sawtooth_instance.ip(), container_ip)
        self.assertEqual(sawtooth_instance.val_key(), container_val_key)
        self.assertEqual(sawtooth_instance.user_key(), container_user_key)
        self.assertNotEqual(sawtooth_instance.user_key(), sawtooth_instance.val_key())
        self.assertEqual(sawtooth_instance.attached_network(), container_network)

        number_of_running_processes = len(docker.containers.list()[0].top()['Processes'][0])
        # should only be 2 processes bash and tail -f /dev/null
        # each process has 4 columns so 2*4 = 8
        self.assertEqual(8, number_of_running_processes)

        # test that containers are made unique
        sawtooth_instance_2nd = SawtoothContainer()

        self.assertEqual(2, len(docker.containers.list()))
        # tests that the two instance to not have the same IP or Key
        self.assertNotEqual(sawtooth_instance.id(), sawtooth_instance_2nd.id())
        self.assertNotEqual(sawtooth_instance.ip(), sawtooth_instance_2nd.ip())
        self.assertNotEqual(sawtooth_instance.val_key(), sawtooth_instance_2nd.val_key())
        self.assertNotEqual(sawtooth_instance.user_key(), sawtooth_instance_2nd.user_key())

        # clean up
        docker.close()
Beispiel #15
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)))