示例#1
0
    def run_test(self):
        # Create all the connections we will need to node0 at the start because they all need to be
        # setup before we call NetworkThread().start()

        # Create a P2P connection just so that the test framework is happy we're connected
        dummyCB = NodeConnCB()
        dummyConn = NodeConn('127.0.0.1',
                             p2p_port(0),
                             self.nodes[0],
                             dummyCB,
                             nullAssocID=True)
        dummyCB.add_connection(dummyConn)

        # By setting the assocID on this second NodeConn we prevent it sending a version message
        badConnCB = TestNode()
        badConn = NodeConn('127.0.0.1',
                           p2p_port(0),
                           self.nodes[0],
                           badConnCB,
                           assocID=0x01)
        badConnCB.add_connection(badConn)

        # Start up network handling in another thread. This needs to be called
        # after the P2P connections have been created.
        NetworkThread().start()

        # Check initial state
        dummyCB.wait_for_protoconf()
        with mininode_lock:
            assert_equal(len(badConnCB.message_count), 0)

        # Send a badly formatted version message
        badConn.send_message(msg_version_bad())
        # Connection will be closed with a reject
        wait_until(lambda: badConnCB.last_reject is not None,
                   lock=mininode_lock,
                   timeout=5)
        wait_until(lambda: badConn.state == "closed",
                   lock=mininode_lock,
                   timeout=5)

        # Check clear log message was generated
        assert check_for_log_msg(
            self, "Failed to process version: (Badly formatted association ID",
            "/node0")
    def run_test(self):
        # Create all the connections we will need to node0 at the start because they all need to be
        # setup before we call NetworkThread().start()

        # Create a P2P connection with no association ID (old style)
        oldStyleConnCB = TestNode()
        oldStyleConn = NodeConn('127.0.0.1',
                                p2p_port(0),
                                self.nodes[0],
                                oldStyleConnCB,
                                nullAssocID=True)
        oldStyleConnCB.add_connection(oldStyleConn)

        # Create a P2P connection with a new association ID
        newStyleConnCB = TestNode()
        newStyleConn = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0],
                                newStyleConnCB)
        newStyleConnCB.add_connection(newStyleConn)

        # Create a P2P connection with a new association ID and another connection that uses the same ID
        newStyleFirstConnCB = TestNode()
        newStyleFirstConn = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0],
                                     newStyleFirstConnCB)
        newStyleFirstConnCB.add_connection(newStyleFirstConn)
        # By setting the assocID on this second NodeConn we prevent it sending a version message
        newStyleSecondConnCB = TestNode()
        newStyleSecondConn = NodeConn('127.0.0.1',
                                      p2p_port(0),
                                      self.nodes[0],
                                      newStyleSecondConnCB,
                                      assocID=newStyleFirstConn.assocID)
        newStyleSecondConnCB.add_connection(newStyleSecondConn)

        # Some connections we will use to test setup of DATA2, DATA3, DATA4 streams
        newStyleSecondConnCB_Data2 = TestNode()
        newStyleSecondConn_Data2 = NodeConn('127.0.0.1',
                                            p2p_port(0),
                                            self.nodes[0],
                                            newStyleSecondConnCB_Data2,
                                            assocID=newStyleFirstConn.assocID)
        newStyleSecondConnCB_Data2.add_connection(newStyleSecondConn_Data2)
        newStyleSecondConnCB_Data3 = TestNode()
        newStyleSecondConn_Data3 = NodeConn('127.0.0.1',
                                            p2p_port(0),
                                            self.nodes[0],
                                            newStyleSecondConnCB_Data3,
                                            assocID=newStyleFirstConn.assocID)
        newStyleSecondConnCB_Data3.add_connection(newStyleSecondConn_Data3)
        newStyleSecondConnCB_Data4 = TestNode()
        newStyleSecondConn_Data4 = NodeConn('127.0.0.1',
                                            p2p_port(0),
                                            self.nodes[0],
                                            newStyleSecondConnCB_Data4,
                                            assocID=newStyleFirstConn.assocID)
        newStyleSecondConnCB_Data4.add_connection(newStyleSecondConn_Data4)

        # Some connections we will use to test error scenarios
        newStyleThirdConnCB = TestNode()
        badStreamConn1 = NodeConn('127.0.0.1',
                                  p2p_port(0),
                                  self.nodes[0],
                                  newStyleThirdConnCB,
                                  assocID=create_association_id())
        newStyleThirdConnCB.add_connection(badStreamConn1)
        newStyleFourthConnCB = TestNode()
        badStreamConn2 = NodeConn('127.0.0.1',
                                  p2p_port(0),
                                  self.nodes[0],
                                  newStyleFourthConnCB,
                                  assocID=newStyleFirstConn.assocID)
        newStyleFourthConnCB.add_connection(badStreamConn2)
        newStyleFifthConnCB = TestNode()
        badStreamConn3 = NodeConn('127.0.0.1',
                                  p2p_port(0),
                                  self.nodes[0],
                                  newStyleFifthConnCB,
                                  assocID=newStyleFirstConn.assocID)
        newStyleFifthConnCB.add_connection(badStreamConn3)
        newStyleSixthConnCB = TestNode()
        badStreamConn4 = NodeConn('127.0.0.1',
                                  p2p_port(0),
                                  self.nodes[0],
                                  newStyleSixthConnCB,
                                  assocID=newStyleFirstConn.assocID)
        newStyleSixthConnCB.add_connection(badStreamConn4)
        newStyleSeventhConnCB = TestNode()
        badStreamConn5 = NodeConn('127.0.0.1',
                                  p2p_port(0),
                                  self.nodes[0],
                                  newStyleSeventhConnCB,
                                  assocID=newStyleFirstConn.assocID)
        newStyleSeventhConnCB.add_connection(badStreamConn5)

        # Start up network handling in another thread. This needs to be called
        # after the P2P connections have been created.
        NetworkThread().start()

        # Wait for all connections to come up to the required initial state
        oldStyleConnCB.wait_for_protoconf()
        newStyleConnCB.wait_for_protoconf()
        newStyleFirstConnCB.wait_for_protoconf()

        # Check initial state
        with mininode_lock:
            assert_equal(oldStyleConnCB.recvAssocID, None)
        with mininode_lock:
            assert_equal(oldStyleConnCB.recvStreamPolicies,
                         b'BlockPriority,Default')
        with mininode_lock:
            assert_equal(newStyleConnCB.recvAssocID, newStyleConn.assocID)
        with mininode_lock:
            assert_equal(newStyleConnCB.recvStreamPolicies,
                         b'BlockPriority,Default')
        with mininode_lock:
            assert_equal(newStyleFirstConnCB.recvAssocID,
                         newStyleFirstConn.assocID)
        with mininode_lock:
            assert_equal(newStyleFirstConnCB.recvStreamPolicies,
                         b'BlockPriority,Default')
        with mininode_lock:
            assert_equal(len(newStyleSecondConnCB.message_count), 0)
        with mininode_lock:
            assert_equal(len(newStyleSecondConnCB_Data2.message_count), 0)
        with mininode_lock:
            assert_equal(len(newStyleSecondConnCB_Data3.message_count), 0)
        with mininode_lock:
            assert_equal(len(newStyleSecondConnCB_Data4.message_count), 0)
        expected = [
            {
                'id': 0,  # oldStyleConn
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 1,  # newStyleConn
                'associd': str(newStyleConn.assocID),
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 2,  # newStyleFirstConn
                'associd': str(newStyleFirstConn.assocID),
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 3,  # newStyleSecondConn
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 4,  # newStyleSecondConn_Data2
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 5,  # newStyleSecondConn_Data3
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 6,  # newStyleSecondConn_Data4
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 7,  # badStreamConn1
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 8,  # badStreamConn2
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 9,  # badStreamConn3
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 10,  # badStreamConn4
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 11,  # badStreamConn5
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[0], expected),
                   timeout=5)

        # Check a new block is recieved by all connections
        self.nodes[0].generate(1)
        tip = self.nodes[0].getbestblockhash()
        wait_until(lambda: oldStyleConnCB.seen_block(tip),
                   lock=mininode_lock,
                   timeout=5)
        wait_until(lambda: newStyleConnCB.seen_block(tip),
                   lock=mininode_lock,
                   timeout=5)
        wait_until(lambda: newStyleFirstConnCB.seen_block(tip),
                   lock=mininode_lock,
                   timeout=5)
        with mininode_lock:
            assert (not newStyleSecondConnCB.seen_block(tip))
        with mininode_lock:
            assert (not newStyleSecondConnCB_Data2.seen_block(tip))
        with mininode_lock:
            assert (not newStyleSecondConnCB_Data3.seen_block(tip))
        with mininode_lock:
            assert (not newStyleSecondConnCB_Data4.seen_block(tip))

        # Send create new stream message
        newStyleSecondConn.send_message(
            msg_createstream(stream_type=StreamType.DATA1.value,
                             stream_policy=b"BlockPriority",
                             assocID=newStyleFirstConn.assocID))
        expected = [
            {
                'id': 0,  # oldStyleConn
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 1,
                'associd': str(newStyleConn.assocID),  # newStyleConn
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 2,
                'associd': str(newStyleFirstConn.assocID
                               ),  # newStyleFirstConn & newStyleSecondConn
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1']
            },
            {
                'id': 4,  # newStyleSecondConn_Data2
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 5,  # newStyleSecondConn_Data3
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 6,  # newStyleSecondConn_Data4
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 7,  # badStreamConn1
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 8,  # badStreamConn2
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 9,  # badStreamConn3
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 10,  # badStreamConn4
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 11,  # badStreamConn5
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[0], expected),
                   timeout=5)
        with mininode_lock:
            assert (newStyleSecondConnCB.last_streamack is not None)

        # Send create stream with wrong association ID
        badStreamConn1.send_message(
            msg_createstream(stream_type=StreamType.DATA2.value,
                             assocID=badStreamConn1.assocID))
        # Should receive reject, no streamack
        wait_until(lambda: newStyleThirdConnCB.last_reject is not None,
                   lock=mininode_lock,
                   timeout=5)
        with mininode_lock:
            assert (newStyleThirdConnCB.last_streamack is None)
        assert ("No node found with association ID"
                in str(newStyleThirdConnCB.last_reject.reason))
        # Connection will be closed
        wait_until(lambda: badStreamConn1.state == "closed",
                   lock=mininode_lock,
                   timeout=5)

        # Send create stream with missing association ID
        badStreamConn5.send_message(
            msg_createstream(stream_type=StreamType.DATA2.value, assocID=""))
        # Should receive reject, no streamack
        wait_until(lambda: newStyleSeventhConnCB.last_reject is not None,
                   lock=mininode_lock,
                   timeout=5)
        with mininode_lock:
            assert (newStyleSeventhConnCB.last_streamack is None)
        assert ("Badly formatted message"
                in str(newStyleSeventhConnCB.last_reject.reason))
        # Connection will be closed
        wait_until(lambda: badStreamConn5.state == "closed",
                   lock=mininode_lock,
                   timeout=5)

        # Send create stream for unknown stream type
        badStreamConn2.send_message(
            msg_createstream(stream_type=9, assocID=badStreamConn2.assocID))
        # Should receive reject, no streamack
        wait_until(lambda: newStyleFourthConnCB.last_reject is not None,
                   lock=mininode_lock,
                   timeout=5)
        with mininode_lock:
            assert (newStyleFourthConnCB.last_streamack is None)
        assert ("StreamType out of range"
                in str(newStyleFourthConnCB.last_reject.reason))
        # Connection will be closed
        wait_until(lambda: badStreamConn2.state == "closed",
                   lock=mininode_lock,
                   timeout=5)

        # Send create stream for existing stream type
        badStreamConn3.send_message(
            msg_createstream(stream_type=StreamType.GENERAL.value,
                             assocID=badStreamConn3.assocID))
        # Should receive reject, no streamack
        wait_until(lambda: newStyleFifthConnCB.last_reject is not None,
                   lock=mininode_lock,
                   timeout=5)
        with mininode_lock:
            assert (newStyleFifthConnCB.last_streamack is None)
        assert ("Attempt to overwrite existing stream"
                in str(newStyleFifthConnCB.last_reject.reason))
        # Connection will be closed
        wait_until(lambda: badStreamConn3.state == "closed",
                   lock=mininode_lock,
                   timeout=5)

        # Send create stream with unknown stream policy specified
        badStreamConn4.send_message(
            msg_createstream(stream_type=StreamType.GENERAL.value,
                             stream_policy=b"UnknownPolicy",
                             assocID=badStreamConn3.assocID))
        # Should receive reject, no streamack
        wait_until(lambda: newStyleSixthConnCB.last_reject is not None,
                   lock=mininode_lock,
                   timeout=5)
        with mininode_lock:
            assert (newStyleSixthConnCB.last_streamack is None)
        assert ("Unknown stream policy name"
                in str(newStyleSixthConnCB.last_reject.reason))
        # Connection will be closed
        wait_until(lambda: badStreamConn4.state == "closed",
                   lock=mininode_lock,
                   timeout=5)

        # Check streams are in the expected state after all those errors
        expected = [
            {
                'id': 0,  # oldStyleConn
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 1,  # newStyleConn
                'associd': str(newStyleConn.assocID),
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 2,  # newStyleFirstConn & newStyleSecondConn
                'associd': str(newStyleFirstConn.assocID),
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1']
            },
            {
                'id': 4,  # newStyleSecondConn_Data2
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 5,  # newStyleSecondConn_Data3
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 6,  # newStyleSecondConn_Data4
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[0], expected),
                   timeout=5)

        # See if we can establish all the possible stream types
        newStyleSecondConn_Data2.send_message(
            msg_createstream(stream_type=StreamType.DATA2.value,
                             assocID=newStyleFirstConn.assocID))
        newStyleSecondConn_Data3.send_message(
            msg_createstream(stream_type=StreamType.DATA3.value,
                             assocID=newStyleFirstConn.assocID))
        newStyleSecondConn_Data4.send_message(
            msg_createstream(stream_type=StreamType.DATA4.value,
                             assocID=newStyleFirstConn.assocID))
        expected = [
            {
                'id': 0,  # oldStyleConn
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 1,
                'associd': str(newStyleConn.assocID),  # newStyleConn
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id':
                2,  # newStyleFirstConn, newStyleSecondConn, newStyleSecondConn_Data2,
                'associd':
                str(newStyleFirstConn.assocID
                    ),  # newStyleSecondConn_Data3, newStyleSecondConn_Data4
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1', 'DATA2', 'DATA3', 'DATA4']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[0], expected),
                   timeout=5)

        # Connect 2 nodes and check they establish the expected streams
        connect_nodes(self.nodes[0], 1)
        expected0 = [
            {
                'id': 0,  # oldStyleConn
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 1,  # newStyleConn
                'associd': str(newStyleConn.assocID),
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id':
                2,  # newStyleFirstConn, newStyleSecondConn, newStyleSecondConn_Data2,
                'associd':
                str(newStyleFirstConn.assocID
                    ),  # newStyleSecondConn_Data3, newStyleSecondConn_Data4
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1', 'DATA2', 'DATA3', 'DATA4']
            },
            {
                'id': 12,  # A new association established to node1
                'associd': '<UNKNOWN>',
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[0], expected0),
                   timeout=5)
        expected1 = [
            {
                'id': 0,  # An association to node0
                'associd': '<UNKNOWN>',
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[1], expected1),
                   timeout=5)

        # Connect 2 nodes, one of which has streams disabled, and check they establish the expected streams
        connect_nodes(self.nodes[0], 2)
        expected0 = [
            {
                'id': 0,  # oldStyleConn
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id': 1,  # newStyleConn
                'associd': str(newStyleConn.assocID),
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
            {
                'id':
                2,  # newStyleFirstConn, newStyleSecondConn, newStyleSecondConn_Data2,
                'associd':
                str(newStyleFirstConn.assocID
                    ),  # newStyleSecondConn_Data3, newStyleSecondConn_Data4
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1', 'DATA2', 'DATA3', 'DATA4']
            },
            {
                'id': 12,  # Association to node 1
                'associd': '<UNKNOWN>',
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1']
            },
            {
                'id': 14,  # Old style association to node 2
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[0], expected0),
                   timeout=5)
        expected2 = [
            {
                'id': 0,  # An association to node0
                'associd': 'Not-Set',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[2], expected2),
                   timeout=5)

        # Make sure everyone sees all blocks over whatever stream
        self.nodes[0].generate(1)
        tip = self.nodes[0].getbestblockhash()
        wait_until(lambda: self.nodes[1].getbestblockhash() == tip, timeout=5)
        wait_until(lambda: self.nodes[2].getbestblockhash() == tip, timeout=5)

        self.nodes[1].generate(1)
        tip = self.nodes[1].getbestblockhash()
        wait_until(lambda: self.nodes[0].getbestblockhash() == tip, timeout=5)
        wait_until(lambda: self.nodes[2].getbestblockhash() == tip, timeout=5)

        self.nodes[2].generate(1)
        tip = self.nodes[2].getbestblockhash()
        wait_until(lambda: self.nodes[0].getbestblockhash() == tip, timeout=5)
        wait_until(lambda: self.nodes[1].getbestblockhash() == tip, timeout=5)

        # Add another node, configured to only support the Default stream policy
        self.add_node(3,
                      extra_args=[
                          '-whitelist=127.0.0.1',
                          '-multistreampolicies=Default'
                      ],
                      init_data_dir=True)
        self.start_node(3)

        # Check streampolicies field from getnetworkinfo
        assert_equal(self.nodes[0].getnetworkinfo()["streampolicies"],
                     "BlockPriority,Default")
        assert_equal(self.nodes[1].getnetworkinfo()["streampolicies"],
                     "BlockPriority,Default")
        assert_equal(self.nodes[2].getnetworkinfo()["streampolicies"],
                     "BlockPriority,Default")
        assert_equal(self.nodes[3].getnetworkinfo()["streampolicies"],
                     "Default")

        # Connect the new node to one of the existing nodes and check that they establish a Default association
        connect_nodes(self.nodes[1], 3)
        expected1 = [
            {
                'id': 0,  # An association to node0
                'associd': '<UNKNOWN>',
                'streampolicy': 'BlockPriority',
                'streams': ['GENERAL', 'DATA1']
            },
            {
                'id': 2,  # An association to node3
                'associd': '<UNKNOWN>',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[1], expected1),
                   timeout=5)
        expected3 = [
            {
                'id': 0,  # An association to node1
                'associd': '<UNKNOWN>',
                'streampolicy': 'Default',
                'streams': ['GENERAL']
            },
        ]
        wait_until(lambda: self.check_peer_info(self.nodes[3], expected3),
                   timeout=5)