Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse MSG_WTX inventory type (part of ZIP-239) #2446

Merged
merged 15 commits into from
Jul 7, 2021

Conversation

jvff
Copy link
Contributor

@jvff jvff commented Jul 6, 2021

Motivation

ZIP-239 describes a new inv type (MSG_WTX), to be applied from the NU5 network upgrade onward. This message type is to be used for both inv messages and getdata requests for relaying mempool transactions.

Even though a mempool implementation is not the current focus, Zebra could close connections to peers that send these messages. This could lead to Zebra not having enough peers to function properly after the NU5 activation.

Specifications

A transaction has a transaction ID that can be used to refer to it. ... Version 5 transactions also have a wtxid , which is used instead of the transaction ID when gossiping transactions in the peer-to-peer protocol

https://zips.z.cash/protocol/protocol.pdf#transactions

The transaction ID of a version 4 or earlier transaction is the SHA-256d hash of the transaction encoding in the
pre-v5 format described above.

The transaction ID of a version 5 transaction is as defined in [ZIP-244]. A v5 transaction also has a wtxid (used for example in the peer-to-peer protocol) as defined in [ZIP-239].

https://zips.z.cash/protocol/protocol.pdf#txnidentifiers

A new inv type MSG_WTX (0x00000005) is added, for use in both inv messages and getdata requests, indicating that the hash being referenced is the wtxid (i.e. the 64-byte value txid || auth_digest). This inv type MUST be used when announcing v5 transactions. The txid and auth_digest are as defined in 4.

An inv or getdata message MUST NOT use the MSG_WTX inv type for v4 or earlier transactions, or on peer connections that have not negotiated at least the peer protocol version specified in Deployment.

Note that MSG_WTX might also be used for future transaction versions after v5. Since such versions are not currently consensus-valid, this is left unspecified for now.

MSG_TX and MSG_WTX entries may be mixed in arbitrary order in an inv message or a getdata message. Since these entry types are of different lengths (36 bytes or 68 bytes respectively including the 4-byte type field), this implies that the size of the message is not determined by its initial count field, and has to be determined by parsing the whole message.

it is possible for a node to receive an inv or getdata message with a MSG_WTX inv type, on a peer connection that has negotiated protocol version 170014 or later, before NU5 has activated. The node MUST handle this case in the same way that it would after NU5 activation when it has no v5 transactions to relay. Receiving a MSG_WTX inv type on a peer connection that has negotiated a protocol version before 170014, on the other hand, SHOULD be treated as a protocol error.

ZIP-239

Bitcoin equivalent

Solution

This PR adds an InventoryHash::Wtx variant. This variant is currently assumed to not be used and simply stores the raw bytes of the data it contains. This is currently not an issue because Zebra does not have a mempool implementation.

A test vector was added to make sure that the deserialization completes successfully. Some property tests were also added:

  • a serialization roundtrip of arbitrary InventoryHash variants
  • an encoding roundtrip of Message::Inv and Message::GetData (I tried including all variants, but that led to some issues with the strategy used, which required more work, so I decided to limit the scope for now)
  • a deserialization of an InventoryHash from random bytes (this ended up being less useful than expected, but maybe it can be converted into some sort of fuzz test in the future?)

Also included in the PR is an update to two existing preallocation tests, because now the InventoryHash no longer has a constant size.

Review

@teor2345 and @oxarbitrage

Reviewer Checklist

  • Code implements Specs and Designs
  • Tests for Expected Behaviour
  • Tests for Errors

Follow Up Work

Related issues

This PR closes #2233.

@jvff jvff requested review from teor2345 and oxarbitrage July 6, 2021 01:18
@zfnd-bot zfnd-bot bot assigned jvff Jul 6, 2021
@jvff jvff force-pushed the parse-msg-wtx branch 2 times, most recently from a7194c7 to 8c26e91 Compare July 6, 2021 01:26
Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good and minimal.

I made some comments about test coverage and future bug risks - I'd like to merge after they are resolved.

Can you open a ticket in the mempool epic for the remaining consensus rules?
It was good to leave out codec and network protocol version changes, they're more risky.

Here are the rules that I think aren't covered by this PR, highlighted in bold.
Can you double check against the rules in the ticket and the code in the PR?

A new inv type MSG_WTX ... is added, for use in both inv messages and getdata requests, indicating that the hash being referenced is the wtxid (i.e. the 64-byte value txid || auth_digest). This inv type MUST be used when announcing v5 transactions.

An inv or getdata message MUST NOT use the MSG_WTX inv type for v4 or earlier transactions, or on peer connections that have not negotiated at least the peer protocol version specified in Deployment.

it is possible for a node to receive an inv or getdata message with a MSG_WTX inv type, on a peer connection that has negotiated protocol version 170014 or later, before NU5 has activated. The node MUST handle this case in the same way that it would after NU5 activation when it has no v5 transactions to relay. Receiving a MSG_WTX inv type on a peer connection that has negotiated a protocol version before 170014, on the other hand, SHOULD be treated as a protocol error.

ZIP-239

Copy link
Contributor Author

@jvff jvff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open a ticket in the mempool epic for the remaining consensus rules?

Done: #2449. I tried to list all the rules that are missing (or partially missing, as is the case for the first one). I kept them all together, but maybe some of them should be split in separate issues? (E.g., the protocol version handling)

jvff added 15 commits July 6, 2021 21:05
Because the size is not constant anymore, since the `MSG_WTX` inventory
type is larger.
A method for a proptest strategy that generates the `InventoryHash`
variants that have the smallest serialized size.
In order to properly test the maximum allocation.
Make it easier to navigate from the documentation of the proptest
strategies to the variants they generate.
Avoid returning an error if a received `GetData` or `Inv` message
contains a `MSG_WTX` inventory type. This prevents Zebra from
disconnecting from peers that announce V5 transactions.
The serialized size now depends on what type of `InventoryHash` is being
tested.
For now it just copies the stored bytes, in order to allow the tests to
run correctly.
Create some mock input bytes representing a serialized `MSG_WTX`
inventory item, and check that it can be deserialized successfully.
Create a strategy that only generates `InventoryHash::Wtx` instances,
and also update the `Arbitrary` implementation for `InventoryHash` to
also generate `Wtx` variants.
Given an arbitrary `InventoryHash`, check that it does not change after
being serialized and deserialized.

Currently, `InventoryHash::Wtx` can't be serialized, so this test will
is expected to panic for now, but it will fail once the serialization
code is implemented, and then the `should_panic` should be removed.
Create an random input vector of bytes, and try to deserialize an
`InventoryHash` from it. This should either succeed or fail in an
expected way.
The attribute is redundant because the `arbitrary` module already has
that attribute.
A method to return a proptest strategy that creates `Message::Inv`
instances.
A method that returns a proptest strategy that creates
`Message::GetData` instances.
Create a `Message` instance, encode it and then decode it using a
`Codec` instance and check that the result is the same as the initial
`Message`.

For now, this only tests `Message::Inv` and `Message::GetData`, because
these are the variants that are related to the scope of the current set
of changes to support parsing the `MSG_WTX` inventory type.

Even so, the test relies on being able to serialize an
`InventoryHash::Wtx`, which is currently not implemented. Therefore the
test was marked as `should_panic` until the serialization code is
implemented.
@teor2345
Copy link
Contributor

teor2345 commented Jul 7, 2021

I kept them all together, but maybe some of them should be split in separate issues? (E.g., the protocol version handling)

I split off ticket #2451.

The data structures and sending messages are essential.
But we can delay the protocol version handling changes, or make some simpler alternative changes.

Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, let's merge

@teor2345 teor2345 merged commit 20eeddc into ZcashFoundation:main Jul 7, 2021
@jvff jvff deleted the parse-msg-wtx branch November 23, 2021 22:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Parse ZIP-239 Messages: Relay of Version 5 Transactions Outside Blocks
2 participants