def test_NetAddressDecodeErrors():
    """
    Peform negative tests against wire encode and decode NetAddress to confirm
    error paths work correctly.
    """

    # baseNetAddr is used in the various tests as a baseline NetAddress.
    baseNetAddr = netaddress.NetAddress(
        ip="127.0.0.1",
        port=8333,
        services=wire.SFNodeNetwork,
        stamp=0x495FAB29,  # 2009-01-03 12:15:05 -0600 CST
    )

    bufWithTime = netaddress.writeNetAddress(baseNetAddr, True)
    bufWithoutTime = netaddress.writeNetAddress(baseNetAddr, False)

    tests = [
        (bufWithTime[:-1], True),
        (bufWithTime + [0], True),
        (bufWithoutTime[:-1], False),
        (bufWithoutTime + [0], False),
        (ByteArray(), True),
    ]

    for buf, hasStamp in tests:
        with pytest.raises(DecredError):
            netaddress.readNetAddress(buf, hasStamp)
def test_NetAddress():
    ip = "127.0.0.1"
    port = 8333

    # Test NewNetAddress.
    na = netaddress.NetAddress(ip, port, 0)

    # Ensure we get the same ip, port, and services back out.
    assert byteIP4 == na.ip
    assert port == na.port
    assert na.services == 0
    assert not na.hasService(wire.SFNodeNetwork)

    # Ensure adding the full service node flag works.
    na.addService(wire.SFNodeNetwork)
    assert na.services == wire.SFNodeNetwork
    assert na.hasService(wire.SFNodeNetwork)

    # Ensure max payload is expected value for latest protocol version.
    wantPayload = 30
    maxPayload = netaddress.MaxNetAddressPayload
    assert maxPayload == wantPayload

    # Ensure max payload length is not more than MaxMessagePayload.
    assert maxPayload <= wire.MaxMessagePayload
Exemple #3
0
def test_VersionOptionalFields():
    """
    Perform tests to ensure that an encoded version messages that omit optional
    fields are handled correctly.
    """
    # onlyRequiredVersion is a version message that only contains the
    # required versions and all other values set to their default values.
    onlyRequiredVersion = minimumMsgVersion()

    onlyRequiredVersionEncoded = baseVersionEncoded()[:-55]

    # addrMeVersion is a version message that contains all fields through
    # the AddrMe field.
    addrMe = netaddress.NetAddress(
        ip="127.0.0.1",
        port=8333,
        services=wire.SFNodeNetwork,
        stamp=0,
    )
    addrMeVersion = minimumMsgVersion()
    addrMeVersion.addrMe = addrMe

    addrMeVersionEncoded = baseVersionEncoded()[:-29]

    # nonceVersion is a version message that contains all fields through
    # the Nonce field.
    nonceVersion = minimumMsgVersion()
    nonceVersion.addrMe = addrMe
    nonceVersion.nonce = 123123  # 0x1e0f3
    nonceVersionEncoded = baseVersionEncoded()[:-21]

    # uaVersion is a version message that contains all fields through
    # the UserAgent field.
    uaVersion = minimumMsgVersion()
    uaVersion.addrMe = addrMe
    uaVersion.nonce = 123123
    uaVersion.userAgent = "/dcrdtest:0.0.1/"
    uaVersionEncoded = baseVersionEncoded()[:-4]

    # lastBlockVersion is a version message that contains all fields
    # through the LastBlock field.
    lastBlockVersion = minimumMsgVersion()
    lastBlockVersion.addrMe = addrMe
    lastBlockVersion.nonce = 123123
    lastBlockVersion.userAgent = "/dcrdtest:0.0.1/"
    lastBlockVersion.lastBlock = 234234  # 0x392fa
    lastBlockVersionEncoded = baseVersionEncoded()

    tests = [
        (onlyRequiredVersion, onlyRequiredVersionEncoded),
        (addrMeVersion, addrMeVersionEncoded),
        (nonceVersion, nonceVersionEncoded),
        (uaVersion, uaVersionEncoded),
        (lastBlockVersion, lastBlockVersionEncoded),
    ]

    for expMsg, buf in tests:
        # Decode the message from wire format.
        msg = msgversion.MsgVersion.btcDecode(buf, wire.ProtocolVersion)
        assert sameMsgVersion(msg, expMsg)
Exemple #4
0
def minimumMsgVersion():
    return msgversion.MsgVersion(
        protocolVersion=60002,
        services=wire.SFNodeNetwork,
        timestamp=0x495FAB29,
        addrYou=netaddress.NetAddress(
            ip="192.168.0.1",
            port=8333,
            services=wire.SFNodeNetwork,
            stamp=0,
        ),
        addrMe=netaddress.NetAddress(
            ip=ByteArray(length=16),
            port=0,
            services=0,
            stamp=0,
        ),
        nonce=0,
        userAgent="",
        lastBlock=0,
        disableRelayTx=False,
    )
Exemple #5
0
def baseVersion():
    return msgversion.MsgVersion(
        addrMe=netaddress.NetAddress(
            ip="127.0.0.1",
            port=8333,
            services=wire.SFNodeNetwork,
            stamp=0,
        ),
        addrYou=netaddress.NetAddress(
            ip="192.168.0.1",
            port=8333,
            services=wire.SFNodeNetwork,
            stamp=0,
        ),
        nonce=123123,
        lastBlock=234234,
        services=wire.SFNodeNetwork,
        disableRelayTx=False,
        protocolVersion=60002,
        timestamp=0x495FAB29,
        userAgent="/dcrdtest:0.0.1/",
    )
Exemple #6
0
    def btcDecode(b, pver):
        """
        btcDecode decodes b using the Decred protocol encoding into the
        receiver. The version message is special in that the protocol version
        hasn't been negotiated yet.  As a result, the pver field is ignored and
        any fields which are added in new versions are optional.

        This is part of the Message API.

        Args:
            b (ByteArray): The encoded MsgVersion.
            pver (int): The protocol version. Unused.

        Returns:
            MsgVersion: The decoded MsgVersion.
        """
        uint64 = 8
        int32 = 4

        pver = b.pop(int32).unLittle().int()
        services = b.pop(uint64).unLittle().int()
        stamp = b.pop(uint64).unLittle().int()

        addrYou = netaddress.readNetAddress(b.pop(26), False)

        # Protocol versions >= 106 added a from address, nonce, and user agent
        # field and they are only considered present if there are bytes
        # remaining in the message.
        if len(b) > 0:
            addrMe = netaddress.readNetAddress(b.pop(26), False)
        else:
            addrMe = netaddress.NetAddress(
                ByteArray(length=16), port=0, services=0, stamp=0
            )

        nonce = 0
        if len(b) > 0:
            nonce = b.pop(uint64).unLittle().int()

        userAgent = ""
        if len(b) > 0:
            userAgent = wire.readVarString(b, pver)

            if not validateUserAgent(userAgent):
                raise DecredError(f"bad user agent: {userAgent}")

        # Protocol versions >= 209 added a last known block field.  It is only
        # considered present if there are bytes remaining in the message.
        lastBlock = 0
        if len(b) > 0:
            lastBlock = b.pop(int32).unLittle().int()

        # There was no relay transactions field before BIP0037Version, but
        # the default behavior prior to the addition of the field was to always
        # relay transactions.
        disableRelayTx = False
        if len(b) > 0:
            # The wire encoding for the field is true when transactions should
            # be relayed, so reverse it for the DisableRelayTx field.
            disableRelayTx = b.pop(1) == [0]

        return MsgVersion(
            protocolVersion=pver,
            services=services,
            timestamp=stamp,
            addrYou=addrYou,
            addrMe=addrMe,
            nonce=nonce,
            userAgent=userAgent,
            lastBlock=lastBlock,
            disableRelayTx=disableRelayTx,
        )
def test_NetAddressWire():
    """
    test the NetAddress wire encode and decode for various protocol versions and
    timestamp flag combinations.
    """
    # baseNetAddr is used in the various tests as a baseline NetAddress.
    baseNetAddr = netaddress.NetAddress(
        ip="127.0.0.1",
        port=8333,
        services=wire.SFNodeNetwork,
        stamp=0x495FAB29,  # 2009-01-03 12:15:05 -0600 CST
    )

    # baseNetAddrNoTS is baseNetAddr with a zero value for the timestamp.
    baseNetAddrNoTS = netaddress.NetAddress(
        ip=baseNetAddr.ip,
        port=baseNetAddr.port,
        services=baseNetAddr.services,
        stamp=0,
    )

    # fmt: off
    # baseNetAddrEncoded is the wire encoded bytes of baseNetAddr.
    baseNetAddrEncoded = ByteArray([
        0x29,
        0xab,
        0x5f,
        0x49,  # Timestamp
        0x01,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,  # SFNodeNetwork
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0xff,
        0xff,
        0x7f,
        0x00,
        0x00,
        0x01,  # IP 127.0.0.1
        0x20,
        0x8d,  # Port 8333 in big-endian
    ])

    # baseNetAddrNoTSEncoded is the wire encoded bytes of baseNetAddrNoTS.
    baseNetAddrNoTSEncoded = ByteArray([
        # No timestamp
        0x01,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,  # SFNodeNetwork
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0xff,
        0xff,
        0x7f,
        0x00,
        0x00,
        0x01,  # IP 127.0.0.1
        0x20,
        0x8d,  # Port 8333 in big-endian
    ])
    # fmt: on
    """
    addrIn NetAddress to encode
    out    Expected decoded NetAddress
    ts     Include timestamp?
    buf    Wire encoding
    pver   Protoc
    """

    tests = [
        # Latest protocol version without ts flag.
        dict(
            addrIn=baseNetAddr,
            out=baseNetAddrNoTS,
            ts=False,
            buf=baseNetAddrNoTSEncoded,
            pver=wire.ProtocolVersion,
        ),
        # Latest protocol version with ts flag.
        dict(
            addrIn=baseNetAddr,
            out=baseNetAddr,
            ts=True,
            buf=baseNetAddrEncoded,
            pver=wire.ProtocolVersion,
        ),
    ]

    for test in tests:
        # Encode to wire format.
        b = netaddress.writeNetAddress(test["addrIn"], test["ts"])
        assert b == test["buf"]

        # Decode the message from wire format.
        na = netaddress.readNetAddress(test["buf"], test["ts"])
        assert byteIP4 == test["out"].ip
        assert na.port == test["out"].port
        assert na.services == test["out"].services
        assert na.timestamp == test["out"].timestamp

    baseNetAddr.ip = None
    b = netaddress.writeNetAddress(baseNetAddr, True)
    reNA = netaddress.readNetAddress(b, True)
    assert reNA.ip == ByteArray(length=16)

    # make sure a ipv6 address parses without an exception.
    netaddress.NetAddress(
        ip="2001:0db8:85a3:0000:0000:8a2e:0370:7334",
        port=8333,
        services=wire.SFNodeNetwork,
        stamp=0x495FAB29,  # 2009-01-03 12:15:05 -0600 CST
    )
Exemple #8
0
def test_MsgVersion():
    pver = wire.ProtocolVersion

    # Create version message data.
    lastBlock = 234234

    me = netaddress.NetAddress(ip="127.0.0.1",
                               port=8333,
                               services=wire.SFNodeNetwork)
    you = netaddress.NetAddress(ip="192.168.0.1",
                                port=8333,
                                services=wire.SFNodeNetwork)

    nonce = random.randint(0, 0xFFFFFFFF)

    # Ensure we get the correct data back out.
    msg = msgversion.MsgVersion(
        addrMe=me,
        addrYou=you,
        nonce=nonce,
        lastBlock=lastBlock,
        services=0,
    )
    assert msg.protocolVersion == pver

    assert sameNetAddress(msg.addrMe, me)
    assert sameNetAddress(msg.addrYou, you)
    assert msg.nonce == nonce
    assert msg.userAgent == msgversion.DefaultUserAgent
    assert msg.lastBlock == lastBlock
    assert not msg.disableRelayTx

    msg.addUserAgent("myclient", "1.2.3", "optional", "comments")
    customUserAgent = (msgversion.DefaultUserAgent +
                       "myclient:1.2.3(optional; comments)/")
    assert msg.userAgent == customUserAgent

    msg.addUserAgent("mygui", "3.4.5")
    customUserAgent += "mygui:3.4.5/"
    assert msg.userAgent == customUserAgent

    # accounting for ":", "/"
    with pytest.raises(DecredError):
        msg.addUserAgent(
            "t" * (msgversion.MaxUserAgentLen - len(customUserAgent) - 2 + 1),
            "")

    # Version message should not have any services set by default.
    assert msg.services == 0
    assert not msg.hasService(wire.SFNodeNetwork)

    # Ensure the command is expected value.
    assert msg.command() == "version"

    # Ensure max payload is expected value.
    # Protocol version 4 bytes + services 8 bytes + timestamp 8 bytes +
    # remote and local net addresses + nonce 8 bytes + length of user agent
    # (varInt) + max allowed user agent length + last block 4 bytes +
    # relay transactions flag 1 byte.
    wantPayload = 358
    maxPayload = msg.maxPayloadLength(pver)
    assert maxPayload == wantPayload

    # Ensure max payload length is not more than MaxMessagePayload.
    assert maxPayload <= wire.MaxMessagePayload

    # Ensure adding the full service node flag works.
    msg.addService(wire.SFNodeNetwork)
    assert msg.services == wire.SFNodeNetwork
    assert msg.hasService(wire.SFNodeNetwork)