From 72e97c637fa0916be75aef28ea8169ffbbe2c4f5 Mon Sep 17 00:00:00 2001 From: Nick Johnson Date: Wed, 18 Dec 2024 19:24:26 -0800 Subject: [PATCH] Add a hash value to Inventory's Error variant While the hash value of the Error variant is meaningless, the variant still conforms to all other Inventory messages and requires a 32 byte hash to be sent over the wire. This is how bitcoin core operates. This patch adds the 32 byte array to the Error variant in order to make its Encoding and Decoding paths symmetrical. This also allows a reader to discard the 32 bytes when decoding a message. The hash is still not exposed to the caller. This was never a problem before because the top level RawNetworkPackage pulls all the required bytes off a reader before decoding. But this is not as easy to do with the v2 p2p network messages. --- bitcoin/src/p2p/message.rs | 2 +- bitcoin/src/p2p/message_blockdata.rs | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/bitcoin/src/p2p/message.rs b/bitcoin/src/p2p/message.rs index 04eb15d618..f1315c34e0 100644 --- a/bitcoin/src/p2p/message.rs +++ b/bitcoin/src/p2p/message.rs @@ -583,7 +583,7 @@ mod test { )]), NetworkMessage::Inv(vec![Inventory::Block(hash([8u8; 32]).into())]), NetworkMessage::GetData(vec![Inventory::Transaction(hash([45u8; 32]).into())]), - NetworkMessage::NotFound(vec![Inventory::Error]), + NetworkMessage::NotFound(vec![Inventory::Error([0u8; 32])]), NetworkMessage::GetBlocks(GetBlocksMessage::new( vec![hash([1u8; 32]).into(), hash([4u8; 32]).into()], hash([5u8; 32]).into(), diff --git a/bitcoin/src/p2p/message_blockdata.rs b/bitcoin/src/p2p/message_blockdata.rs index 90b0bba72b..6ccff60d91 100644 --- a/bitcoin/src/p2p/message_blockdata.rs +++ b/bitcoin/src/p2p/message_blockdata.rs @@ -16,8 +16,9 @@ use crate::transaction::{Txid, Wtxid}; /// An inventory item. #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash, PartialOrd, Ord)] pub enum Inventory { - /// Error --- these inventories can be ignored - Error, + /// Error --- these inventories can be ignored. + /// While a 32 byte hash is expected over the wire, the value is meaningless. + Error([u8; 32]), /// Transaction Transaction(Txid), /// Block @@ -42,10 +43,10 @@ pub enum Inventory { impl Inventory { /// Return the item value represented as a SHA256-d hash. /// - /// Returns [None] only for [Inventory::Error]. + /// Returns [None] only for [Inventory::Error] who's hash value is meaningless. pub fn network_hash(&self) -> Option<[u8; 32]> { match self { - Inventory::Error => None, + Inventory::Error(_) => None, Inventory::Transaction(t) => Some(t.to_byte_array()), Inventory::Block(b) => Some(b.to_byte_array()), Inventory::CompactBlock(b) => Some(b.to_byte_array()), @@ -66,7 +67,7 @@ impl Encodable for Inventory { }; } Ok(match *self { - Inventory::Error => encode_inv!(0, [0; 32]), + Inventory::Error(_) => encode_inv!(0, [0; 32]), Inventory::Transaction(ref t) => encode_inv!(1, t), Inventory::Block(ref b) => encode_inv!(2, b), Inventory::CompactBlock(ref b) => encode_inv!(4, b), @@ -83,7 +84,7 @@ impl Decodable for Inventory { fn consensus_decode(r: &mut R) -> Result { let inv_type: u32 = Decodable::consensus_decode(r)?; Ok(match inv_type { - 0 => Inventory::Error, + 0 => Inventory::Error(Decodable::consensus_decode(r)?), 1 => Inventory::Transaction(Decodable::consensus_decode(r)?), 2 => Inventory::Block(Decodable::consensus_decode(r)?), 4 => Inventory::CompactBlock(Decodable::consensus_decode(r)?),