2019-09-09 18:35:56 -07:00
|
|
|
//! Definitions of network messages.
|
|
|
|
|
2019-09-11 19:44:13 -07:00
|
|
|
use std::net::SocketAddr;
|
2019-09-10 13:27:10 -07:00
|
|
|
|
2019-09-11 19:24:16 -07:00
|
|
|
use chrono::{DateTime, Utc};
|
|
|
|
|
2019-09-12 03:23:51 -07:00
|
|
|
use crate::types::*;
|
2019-09-10 13:27:10 -07:00
|
|
|
|
2019-09-09 18:35:56 -07:00
|
|
|
/// A Bitcoin-like network message for the Zcash protocol.
|
|
|
|
///
|
|
|
|
/// The Zcash network protocol is mostly inherited from Bitcoin, and a list of
|
|
|
|
/// Bitcoin network messages can be found [on the Bitcoin
|
|
|
|
/// wiki][btc_wiki_protocol].
|
|
|
|
///
|
|
|
|
/// That page describes the wire format of the messages, while this enum stores
|
|
|
|
/// an internal representation. The internal representation is unlinked from the
|
|
|
|
/// wire format, and the translation between the two happens only during
|
|
|
|
/// serialization and deserialization. For instance, Bitcoin identifies messages
|
|
|
|
/// by a 12-byte ascii command string; we consider this a serialization detail
|
|
|
|
/// and use the enum discriminant instead. (As a side benefit, this also means
|
|
|
|
/// that we have a clearly-defined validation boundary for network messages
|
|
|
|
/// during serialization).
|
|
|
|
///
|
|
|
|
/// [btc_wiki_protocol]: https://en.bitcoin.it/wiki/Protocol_documentation
|
2019-09-10 09:57:58 -07:00
|
|
|
//
|
|
|
|
// XXX not all messages are filled in yet. Messages written as { /* XXX add
|
|
|
|
// fields */ } are explicitly incomplete and we need to define a mapping between
|
|
|
|
// the serialized message data and the internal representation. Note that this
|
|
|
|
// is different from messages like GetAddr which have no data (and so have no
|
|
|
|
// fields).
|
2019-09-09 18:35:56 -07:00
|
|
|
pub enum Message {
|
|
|
|
/// A `version` message.
|
|
|
|
///
|
2019-09-10 13:27:10 -07:00
|
|
|
/// Note that although this is called `version` in Bitcoin, its role is really
|
|
|
|
/// analogous to a `ClientHello` message in TLS, used to begin a handshake, and
|
|
|
|
/// is distinct from a simple version number.
|
|
|
|
///
|
2019-09-09 18:35:56 -07:00
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#version)
|
2019-09-10 13:27:10 -07:00
|
|
|
Version {
|
|
|
|
/// The network version number supported by the sender.
|
|
|
|
version: Version,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
2019-09-10 13:27:10 -07:00
|
|
|
/// The network services advertised by the sender.
|
|
|
|
services: Services,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
2019-09-10 13:27:10 -07:00
|
|
|
/// The time when the version message was sent.
|
2019-09-11 19:24:16 -07:00
|
|
|
timestamp: DateTime<Utc>,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
|
|
|
/// The network address of the node receiving this message.
|
2019-09-10 13:27:10 -07:00
|
|
|
address_receiving: NetworkAddress,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
|
|
|
/// The network address of the node emitting this message.
|
2019-09-10 13:27:10 -07:00
|
|
|
address_from: NetworkAddress,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
|
|
|
/// Node random nonce, randomly generated every time a version
|
|
|
|
/// packet is sent. This nonce is used to detect connections
|
|
|
|
/// to self.
|
2019-09-10 13:27:10 -07:00
|
|
|
nonce: Nonce,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
2019-09-10 13:48:28 -07:00
|
|
|
/// The Zcash user agent advertised by the sender.
|
2019-09-10 13:27:10 -07:00
|
|
|
user_agent: String,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
|
|
|
/// The last block received by the emitting node.
|
2019-09-10 13:27:10 -07:00
|
|
|
start_height: zebra_chain::types::BlockHeight,
|
2019-09-10 13:43:14 -07:00
|
|
|
|
|
|
|
/// Whether the remote peer should announce relayed
|
|
|
|
/// transactions or not, see [BIP 0037](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki)
|
2019-09-11 19:44:13 -07:00
|
|
|
relay: bool,
|
2019-09-10 13:27:10 -07:00
|
|
|
},
|
2019-09-09 23:59:49 -07:00
|
|
|
|
2019-09-09 18:35:56 -07:00
|
|
|
/// A `verack` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#verack)
|
2019-09-11 11:11:48 -07:00
|
|
|
Verack,
|
2019-09-09 23:59:49 -07:00
|
|
|
|
2019-09-09 18:35:56 -07:00
|
|
|
/// A `ping` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#ping)
|
2019-09-10 13:27:10 -07:00
|
|
|
Ping(Nonce),
|
2019-09-09 23:59:49 -07:00
|
|
|
|
2019-09-09 18:35:56 -07:00
|
|
|
/// A `pong` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#pong)
|
2019-09-10 13:27:10 -07:00
|
|
|
Pong(
|
2019-09-09 18:35:56 -07:00
|
|
|
/// The nonce from the `Ping` message this was in response to.
|
2019-09-10 13:27:10 -07:00
|
|
|
Nonce,
|
|
|
|
),
|
2019-09-10 09:57:58 -07:00
|
|
|
|
|
|
|
/// A `reject` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#reject)
|
2019-09-11 11:11:48 -07:00
|
|
|
Reject {
|
|
|
|
/// Type of message rejected.
|
|
|
|
// Q: can we just reference the Type, rather than instantiate an instance of the enum type?
|
|
|
|
message: Box<Message>,
|
|
|
|
|
|
|
|
/// RejectReason code relating to rejected message.
|
|
|
|
ccode: RejectReason,
|
|
|
|
|
|
|
|
/// Human-readable version of rejection reason.
|
|
|
|
reason: String,
|
|
|
|
|
|
|
|
/// Optional extra data provided for some errors.
|
|
|
|
// Currently, all errors which provide this field fill it with
|
|
|
|
// the TXID or block header hash of the object being rejected,
|
|
|
|
// so the field is 32 bytes.
|
|
|
|
//
|
|
|
|
// Q: can we tell Rust that this field is optional? Or just
|
|
|
|
// default its value to an empty array, I guess.
|
2019-09-11 19:44:13 -07:00
|
|
|
data: [u8; 32],
|
2019-09-11 11:11:48 -07:00
|
|
|
},
|
2019-09-10 09:57:58 -07:00
|
|
|
|
|
|
|
/// An `addr` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#addr)
|
2019-09-11 19:44:13 -07:00
|
|
|
Addr {
|
|
|
|
/// Number of address entries (max: 1000)
|
|
|
|
count: u16,
|
|
|
|
|
|
|
|
/// Address of other nodes on the network, preceeded by a timestamp.
|
|
|
|
// Starting version 31402, addresses are prefixed with a
|
|
|
|
// timestamp. If no timestamp is present, the addresses should
|
|
|
|
// not be relayed to other peers, unless it is indeed
|
|
|
|
// confirmed they are up.
|
|
|
|
//
|
|
|
|
// XXX: I don't know how this serializes.
|
2019-09-11 20:05:08 -07:00
|
|
|
address_list: (DateTime<Utc>, Vec<NetworkAddress>),
|
2019-09-11 19:44:13 -07:00
|
|
|
},
|
2019-09-10 09:57:58 -07:00
|
|
|
|
|
|
|
/// A `getaddr` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#getaddr)
|
|
|
|
GetAddr,
|
|
|
|
|
|
|
|
/// A `block` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#block)
|
|
|
|
Block {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `getblocks` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#getblocks)
|
|
|
|
GetBlocks {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `headers` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#headers)
|
|
|
|
Headers {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `getheaders` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#getheaders)
|
|
|
|
GetHeaders {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// An `inv` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#inv)
|
|
|
|
// XXX the bitcoin reference above suggests this can be 1.8 MB in bitcoin -- maybe
|
|
|
|
// larger in Zcash, since Zcash objects could be bigger (?) -- does this tilt towards
|
|
|
|
// having serialization be async?
|
2019-09-11 19:44:13 -07:00
|
|
|
Inventory {
|
|
|
|
/// Number of inventory entries.
|
|
|
|
count: u64,
|
|
|
|
|
|
|
|
/// Inventory vectors.
|
|
|
|
inventory: Vec<zebra_chain::types::InventoryVector>,
|
|
|
|
},
|
2019-09-10 09:57:58 -07:00
|
|
|
|
|
|
|
/// A `getdata` message.
|
|
|
|
///
|
2019-09-11 19:44:13 -07:00
|
|
|
/// `getdata` is used in response to `inv`, to retrieve the content of
|
|
|
|
/// a specific object, and is usually sent after receiving an `inv`
|
|
|
|
/// packet, after filtering known elements.
|
|
|
|
///
|
2019-09-10 09:57:58 -07:00
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#getdata)
|
2019-09-11 19:44:13 -07:00
|
|
|
GetData {
|
|
|
|
/// Number of inventory entries.
|
|
|
|
count: u64,
|
|
|
|
|
|
|
|
/// Inventory vectors.
|
|
|
|
inventory: Vec<zebra_chain::types::InventoryVector>,
|
|
|
|
},
|
2019-09-10 09:57:58 -07:00
|
|
|
|
|
|
|
/// A `notfound` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#notfound)
|
2019-09-11 19:44:13 -07:00
|
|
|
// See note above on `Inventory`.
|
|
|
|
NotFound {
|
|
|
|
/// Number of inventory entries.
|
|
|
|
count: u64,
|
|
|
|
|
|
|
|
/// Inventory vectors.
|
|
|
|
inventory: Vec<zebra_chain::types::InventoryVector>,
|
|
|
|
},
|
2019-09-10 09:57:58 -07:00
|
|
|
|
|
|
|
/// A `tx` message.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#tx)
|
|
|
|
Tx {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `mempool` message.
|
|
|
|
///
|
|
|
|
/// This was defined in [BIP35], which is included in Zcash.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#mempool)
|
|
|
|
/// [BIP35]: https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki
|
|
|
|
Mempool {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `filterload` message.
|
|
|
|
///
|
|
|
|
/// This was defined in [BIP37], which is included in Zcash.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
|
|
|
|
/// [BIP37]: https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki
|
|
|
|
FilterLoad {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `filteradd` message.
|
|
|
|
///
|
|
|
|
/// This was defined in [BIP37], which is included in Zcash.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
|
|
|
|
/// [BIP37]: https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki
|
|
|
|
FilterAdd {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `filterclear` message.
|
|
|
|
///
|
|
|
|
/// This was defined in [BIP37], which is included in Zcash.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
|
|
|
|
/// [BIP37]: https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki
|
|
|
|
FilterClear {/* XXX add fields */},
|
|
|
|
|
|
|
|
/// A `merkleblock` message.
|
|
|
|
///
|
|
|
|
/// This was defined in [BIP37], which is included in Zcash.
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#filterload.2C_filteradd.2C_filterclear.2C_merkleblock)
|
|
|
|
/// [BIP37]: https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki
|
|
|
|
MerkleBlock {/* XXX add fields */},
|
2019-09-09 18:35:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Q: how do we want to implement serialization, exactly? do we want to have
|
|
|
|
// something generic over stdlib Read and Write traits, or over async versions
|
|
|
|
// of those traits?
|
2019-09-12 03:23:51 -07:00
|
|
|
//
|
|
|
|
// Note: because of the way the message structure is defined (checksum comes
|
|
|
|
// first) we can't write the message headers before collecting the whole body
|
|
|
|
// into a buffer
|
2019-09-11 11:11:48 -07:00
|
|
|
|
2019-09-11 19:44:13 -07:00
|
|
|
/// Reject Reason CCodes
|
|
|
|
///
|
|
|
|
/// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#reject)
|
2019-09-11 11:11:48 -07:00
|
|
|
#[repr(u8)]
|
|
|
|
#[allow(missing_docs)]
|
|
|
|
pub enum RejectReason {
|
|
|
|
Malformed = 0x01,
|
|
|
|
Invalid = 0x10,
|
|
|
|
Obsolete = 0x11,
|
|
|
|
Duplicate = 0x12,
|
|
|
|
Nonstandard = 0x40,
|
|
|
|
Dust = 0x41,
|
|
|
|
InsufficientFee = 0x42,
|
2019-09-11 19:44:13 -07:00
|
|
|
Checkpoint = 0x43,
|
2019-09-11 11:11:48 -07:00
|
|
|
}
|