rust-bitcoin-unsafe-fast/src/network/message_blockdata.rs

177 lines
6.0 KiB
Rust
Raw Normal View History

2014-07-18 13:56:17 +00:00
// Rust Bitcoin Library
// Written in 2014 by
// Andrew Poelstra <apoelstra@wpsoftware.net>
2014-07-18 13:56:17 +00:00
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//
//! Blockdata network messages
2014-07-18 13:56:17 +00:00
//!
//! This module describes network messages which are used for passing
//! Bitcoin data (blocks and transactions) around.
//!
use network::constants;
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{SimpleDecoder, SimpleEncoder};
2014-07-18 13:56:17 +00:00
use util::hash::Sha256dHash;
2015-03-26 15:35:31 +00:00
#[derive(PartialEq, Eq, Clone, Debug)]
2014-07-18 13:56:17 +00:00
/// The type of an inventory object
pub enum InvType {
/// Error --- these inventories can be ignored
Error,
/// Transaction
Transaction,
/// Block
2018-05-28 13:24:35 +00:00
Block,
/// Witness Block
WitnessBlock,
/// Witness Transaction
WitnessTransaction
2014-07-18 13:56:17 +00:00
}
// Some simple messages
/// The `getblocks` message
2015-03-26 15:35:31 +00:00
#[derive(PartialEq, Eq, Clone, Debug)]
2014-07-18 13:56:17 +00:00
pub struct GetBlocksMessage {
/// The protocol version
pub version: u32,
/// Locator hashes --- ordered newest to oldest. The remote peer will
/// reply with its longest known chain, starting from a locator hash
/// if possible and block 1 otherwise.
pub locator_hashes: Vec<Sha256dHash>,
/// References the block to stop at, or zero to just fetch the maximum 500 blocks
pub stop_hash: Sha256dHash
2014-07-18 13:56:17 +00:00
}
/// The `getheaders` message
2015-03-26 15:35:31 +00:00
#[derive(PartialEq, Eq, Clone, Debug)]
2014-07-18 13:56:17 +00:00
pub struct GetHeadersMessage {
/// The protocol version
pub version: u32,
/// Locator hashes --- ordered newest to oldest. The remote peer will
/// reply with its longest known chain, starting from a locator hash
/// if possible and block 1 otherwise.
pub locator_hashes: Vec<Sha256dHash>,
/// References the header to stop at, or zero to just fetch the maximum 2000 headers
pub stop_hash: Sha256dHash
2014-07-18 13:56:17 +00:00
}
/// An inventory object --- a reference to a Bitcoin object
2015-03-26 15:35:31 +00:00
#[derive(PartialEq, Eq, Clone, Debug)]
2014-07-18 13:56:17 +00:00
pub struct Inventory {
/// The type of object that is referenced
pub inv_type: InvType,
/// The object's hash
pub hash: Sha256dHash
2014-07-18 13:56:17 +00:00
}
impl GetBlocksMessage {
/// Construct a new `getblocks` message
pub fn new(locator_hashes: Vec<Sha256dHash>, stop_hash: Sha256dHash) -> GetBlocksMessage {
GetBlocksMessage {
version: constants::PROTOCOL_VERSION,
locator_hashes: locator_hashes.clone(),
stop_hash: stop_hash
}
2014-07-18 13:56:17 +00:00
}
}
impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash);
2014-07-18 13:56:17 +00:00
impl GetHeadersMessage {
/// Construct a new `getheaders` message
pub fn new(locator_hashes: Vec<Sha256dHash>, stop_hash: Sha256dHash) -> GetHeadersMessage {
GetHeadersMessage {
version: constants::PROTOCOL_VERSION,
locator_hashes: locator_hashes,
stop_hash: stop_hash
}
2014-07-18 13:56:17 +00:00
}
}
impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash);
2014-07-18 13:56:17 +00:00
impl<S: SimpleEncoder> ConsensusEncodable<S> for Inventory {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
match self.inv_type {
InvType::Error => 0u32,
InvType::Transaction => 1,
2018-05-28 13:24:35 +00:00
InvType::Block => 2,
InvType::WitnessBlock => 0x40000002,
InvType::WitnessTransaction => 0x40000001
}.consensus_encode(s)?;
self.hash.consensus_encode(s)
}
}
2014-07-18 13:56:17 +00:00
impl<D: SimpleDecoder> ConsensusDecodable<D> for Inventory {
#[inline]
fn consensus_decode(d: &mut D) -> Result<Inventory, D::Error> {
let int_type: u32 = ConsensusDecodable::consensus_decode(d)?;
Ok(Inventory {
inv_type: match int_type {
0 => InvType::Error,
1 => InvType::Transaction,
2 => InvType::Block,
// TODO do not fail here
_ => { panic!("bad inventory type field") }
},
hash: ConsensusDecodable::consensus_decode(d)?
})
}
2014-07-18 13:56:17 +00:00
}
#[cfg(test)]
mod tests {
use super::{GetHeadersMessage, GetBlocksMessage};
use hex::decode as hex_decode;
use network::serialize::{deserialize, serialize};
use std::default::Default;
#[test]
fn getblocks_message_test() {
let from_sat = hex_decode("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap();
let genhash = hex_decode("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap();
let decode: Result<GetBlocksMessage, _> = deserialize(&from_sat);
assert!(decode.is_ok());
let real_decode = decode.unwrap();
assert_eq!(real_decode.version, 70002);
assert_eq!(real_decode.locator_hashes.len(), 1);
assert_eq!(serialize(&real_decode.locator_hashes[0]).ok(), Some(genhash));
assert_eq!(real_decode.stop_hash, Default::default());
assert_eq!(serialize(&real_decode).ok(), Some(from_sat));
}
#[test]
fn getheaders_message_test() {
let from_sat = hex_decode("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap();
let genhash = hex_decode("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap();
let decode: Result<GetHeadersMessage, _> = deserialize(&from_sat);
assert!(decode.is_ok());
let real_decode = decode.unwrap();
assert_eq!(real_decode.version, 70002);
assert_eq!(real_decode.locator_hashes.len(), 1);
assert_eq!(serialize(&real_decode.locator_hashes[0]).ok(), Some(genhash));
assert_eq!(real_decode.stop_hash, Default::default());
assert_eq!(serialize(&real_decode).ok(), Some(from_sat));
}
2014-07-18 13:56:17 +00:00
}