Skip to content

Commit e33be0f

Browse files
committed
Merge rust-bitcoin/rust-bitcoin#1088: Add BIP152 (Compact Blocks) structures
ee29910 BIP152: Test net msg ser/der and diff encoding (0xb10c) cd1aaaf BIP152: Add Compact Block unit test based on Elements (Steven Roose) d4d92a8 BIP152: Add Compact Blocks network messages (Steven Roose) f2fcdc8 BIP152: Add basic Compact Block structures (Steven Roose) a9a39c4 blockdata: Derive PartialOrd, Ord and Hash for BlockHeader (Steven Roose) Pull request description: > Adds the basic structures for BIP152 and a method to create a compact block from a full block. This is a rebase of #249 by stevenroose (see rust-bitcoin/rust-bitcoin#249 (comment)) with a milestone for 29.0. I've added deserialization and serialization tests for the network messages and fixed an off-by-one bug in the deserialization of the differentially encoded varints in the `getblocktxn` message (see rust-bitcoin/rust-bitcoin#249 (comment)). Closes #249. ACKs for top commit: tcharding: ACK ee29910 apoelstra: ACK ee29910 Tree-SHA512: 462a91576281f5a2ffdc2610769ea93970b60dac75a150c827966c48daec7cf93f526f9f202e7ba1dbb1410b49148579880260a3c3df298b98330c0d891a4cca
2 parents bd00fbb + a951e8c commit e33be0f

File tree

8 files changed

+574
-1
lines changed

8 files changed

+574
-1
lines changed

src/blockdata/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::internal_macros::impl_consensus_encoding;
3737
/// ### Bitcoin Core References
3838
///
3939
/// * [CBlockHeader definition](https://github.com/bitcoin/bitcoin/blob/345457b542b6a980ccfbc868af0970a6f91d1b82/src/primitives/block.h#L20)
40-
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
40+
#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
4141
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4242
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
4343
pub struct BlockHeader {

src/consensus/encode.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use crate::io::{self, Cursor, Read};
2727

2828
use crate::util::endian;
2929
use crate::util::psbt;
30+
use crate::util::bip152::{ShortId, PrefilledTransaction};
3031
use crate::util::taproot::TapLeafHash;
3132
use crate::hashes::hex::ToHex;
3233

@@ -558,6 +559,7 @@ macro_rules! impl_array {
558559

559560
impl_array!(2);
560561
impl_array!(4);
562+
impl_array!(6);
561563
impl_array!(8);
562564
impl_array!(10);
563565
impl_array!(12);
@@ -629,6 +631,9 @@ impl_vec!(TxIn);
629631
impl_vec!(Vec<u8>);
630632
impl_vec!(u64);
631633
impl_vec!(TapLeafHash);
634+
impl_vec!(VarInt);
635+
impl_vec!(ShortId);
636+
impl_vec!(PrefilledTransaction);
632637

633638
#[cfg(feature = "std")] impl_vec!(Inventory);
634639
#[cfg(feature = "std")] impl_vec!((u32, Address));

src/network/message.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::network::address::{Address, AddrV2Message};
1919
use crate::network::{message_network, message_bloom};
2020
use crate::network::message_blockdata;
2121
use crate::network::message_filter;
22+
use crate::network::message_compact_blocks;
2223
use crate::consensus::encode::{CheckedData, Decodable, Encodable, VarInt};
2324
use crate::consensus::{encode, serialize};
2425
use crate::util::merkleblock::MerkleBlock;
@@ -181,6 +182,14 @@ pub enum NetworkMessage {
181182
GetCFCheckpt(message_filter::GetCFCheckpt),
182183
/// BIP157 cfcheckpt
183184
CFCheckpt(message_filter::CFCheckpt),
185+
/// BIP152 sendcmpct
186+
SendCmpct(message_compact_blocks::SendCmpct),
187+
/// BIP152 cmpctblock
188+
CmpctBlock(message_compact_blocks::CmpctBlock),
189+
/// BIP152 getblocktxn
190+
GetBlockTxn(message_compact_blocks::GetBlockTxn),
191+
/// BIP152 blocktxn
192+
BlockTxn(message_compact_blocks::BlockTxn),
184193
/// `alert`
185194
Alert(Vec<u8>),
186195
/// `reject`
@@ -237,6 +246,10 @@ impl NetworkMessage {
237246
NetworkMessage::CFHeaders(_) => "cfheaders",
238247
NetworkMessage::GetCFCheckpt(_) => "getcfcheckpt",
239248
NetworkMessage::CFCheckpt(_) => "cfcheckpt",
249+
NetworkMessage::SendCmpct(_) => "sendcmpct",
250+
NetworkMessage::CmpctBlock(_) => "cmpctblock",
251+
NetworkMessage::GetBlockTxn(_) => "getblocktxn",
252+
NetworkMessage::BlockTxn(_) => "blocktxn",
240253
NetworkMessage::Alert(_) => "alert",
241254
NetworkMessage::Reject(_) => "reject",
242255
NetworkMessage::FeeFilter(_) => "feefilter",
@@ -314,6 +327,10 @@ impl Encodable for RawNetworkMessage {
314327
NetworkMessage::CFHeaders(ref dat) => serialize(dat),
315328
NetworkMessage::GetCFCheckpt(ref dat) => serialize(dat),
316329
NetworkMessage::CFCheckpt(ref dat) => serialize(dat),
330+
NetworkMessage::SendCmpct(ref dat) => serialize(dat),
331+
NetworkMessage::CmpctBlock(ref dat) => serialize(dat),
332+
NetworkMessage::GetBlockTxn(ref dat) => serialize(dat),
333+
NetworkMessage::BlockTxn(ref dat) => serialize(dat),
317334
NetworkMessage::Alert(ref dat) => serialize(dat),
318335
NetworkMessage::Reject(ref dat) => serialize(dat),
319336
NetworkMessage::FeeFilter(ref data) => serialize(data),
@@ -394,6 +411,10 @@ impl Decodable for RawNetworkMessage {
394411
"reject" => NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
395412
"alert" => NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
396413
"feefilter" => NetworkMessage::FeeFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
414+
"sendcmpct" => NetworkMessage::SendCmpct(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
415+
"cmpctblock" => NetworkMessage::CmpctBlock(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
416+
"getblocktxn" => NetworkMessage::GetBlockTxn(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
417+
"blocktxn" => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
397418
"wtxidrelay" => NetworkMessage::WtxidRelay,
398419
"addrv2" => NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?),
399420
"sendaddrv2" => NetworkMessage::SendAddrV2,
@@ -432,6 +453,8 @@ mod test {
432453
use crate::blockdata::script::Script;
433454
use crate::network::message_bloom::{FilterAdd, FilterLoad, BloomFlags};
434455
use crate::MerkleBlock;
456+
use crate::network::message_compact_blocks::{GetBlockTxn, SendCmpct};
457+
use crate::util::bip152::BlockTransactionsRequest;
435458

436459
fn hash(slice: [u8;32]) -> Hash {
437460
Hash::from_slice(&slice).unwrap()
@@ -446,6 +469,9 @@ mod test {
446469
let header: BlockHeader = deserialize(&Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap();
447470
let script: Script = deserialize(&Vec::from_hex("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac").unwrap()).unwrap();
448471
let merkle_block: MerkleBlock = deserialize(&Vec::from_hex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101").unwrap()).unwrap();
472+
let cmptblock = deserialize(&Vec::from_hex("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000").unwrap()).unwrap();
473+
let blocktxn = deserialize(&Vec::from_hex("2e93c0cff39ff605020072d96bc3a8d20b8447e294d08092351c8583e08d9b5a01020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402dc0000ffffffff0200f90295000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()).unwrap();
474+
449475

450476
let msgs = vec![
451477
NetworkMessage::Version(version_msg),
@@ -481,6 +507,10 @@ mod test {
481507
NetworkMessage::WtxidRelay,
482508
NetworkMessage::AddrV2(vec![AddrV2Message{ addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), port: 0, services: ServiceFlags::NONE, time: 0 }]),
483509
NetworkMessage::SendAddrV2,
510+
NetworkMessage::CmpctBlock(cmptblock),
511+
NetworkMessage::GetBlockTxn(GetBlockTxn { txs_request: BlockTransactionsRequest { block_hash: hash([11u8; 32]).into(), indexes: vec![0, 1, 2, 3, 10, 3002] } }),
512+
NetworkMessage::BlockTxn(blocktxn),
513+
NetworkMessage::SendCmpct(SendCmpct{send_compact: true, version: 8333}),
484514
];
485515

486516
for msg in msgs {

src/network/message_blockdata.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ pub enum Inventory {
2727
Transaction(Txid),
2828
/// Block
2929
Block(BlockHash),
30+
/// Compact Block
31+
CompactBlock(BlockHash),
3032
/// Witness Transaction by Wtxid
3133
WTx(Wtxid),
3234
/// Witness Transaction
@@ -54,6 +56,7 @@ impl Encodable for Inventory {
5456
Inventory::Error => encode_inv!(0, sha256d::Hash::all_zeros()),
5557
Inventory::Transaction(ref t) => encode_inv!(1, t),
5658
Inventory::Block(ref b) => encode_inv!(2, b),
59+
Inventory::CompactBlock(ref b) => encode_inv!(4, b),
5760
Inventory::WTx(w) => encode_inv!(5, w),
5861
Inventory::WitnessTransaction(ref t) => encode_inv!(0x40000001, t),
5962
Inventory::WitnessBlock(ref b) => encode_inv!(0x40000002, b),
@@ -70,6 +73,7 @@ impl Decodable for Inventory {
7073
0 => Inventory::Error,
7174
1 => Inventory::Transaction(Decodable::consensus_decode(r)?),
7275
2 => Inventory::Block(Decodable::consensus_decode(r)?),
76+
4 => Inventory::CompactBlock(Decodable::consensus_decode(r)?),
7377
5 => Inventory::WTx(Decodable::consensus_decode(r)?),
7478
0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(r)?),
7579
0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(r)?),

src/network/message_compact_blocks.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//!
2+
//! BIP152 Compact Blocks network messages
3+
//!
4+
5+
use crate::internal_macros::impl_consensus_encoding;
6+
use crate::util::bip152;
7+
8+
/// sendcmpct message
9+
#[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord, Hash)]
10+
pub struct SendCmpct {
11+
/// Request to be send compact blocks.
12+
pub send_compact: bool,
13+
/// Compact Blocks protocol version number.
14+
pub version: u64,
15+
}
16+
impl_consensus_encoding!(SendCmpct, send_compact, version);
17+
18+
/// cmpctblock message
19+
///
20+
/// Note that the rules for validation before relaying compact blocks is
21+
/// different from headers and regular block messages. Thus, you shouldn't use
22+
/// compact blocks when relying on an upstream full node to have validated data
23+
/// being forwarded to you.
24+
#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
25+
pub struct CmpctBlock {
26+
/// The Compact Block.
27+
pub compact_block: bip152::HeaderAndShortIds,
28+
}
29+
impl_consensus_encoding!(CmpctBlock, compact_block);
30+
31+
/// getblocktxn message
32+
#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
33+
pub struct GetBlockTxn {
34+
/// The block transactions request.
35+
pub txs_request: bip152::BlockTransactionsRequest,
36+
}
37+
impl_consensus_encoding!(GetBlockTxn, txs_request);
38+
39+
/// blocktxn message
40+
#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
41+
pub struct BlockTxn {
42+
/// The requested block transactions.
43+
pub transactions: bip152::BlockTransactions,
44+
}
45+
impl_consensus_encoding!(BlockTxn, transactions);

src/network/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ pub mod message_blockdata;
2626
pub mod message_bloom;
2727
#[cfg(feature = "std")]
2828
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
29+
pub mod message_compact_blocks;
30+
#[cfg(feature = "std")]
31+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
2932
pub mod message_network;
3033
#[cfg(feature = "std")]
3134
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]

0 commit comments

Comments
 (0)