From fc572aba86a86c4c5e5b682e361ee778f692ec60 Mon Sep 17 00:00:00 2001 From: 0xb10c <0xb10c@gmail.com> Date: Mon, 4 Apr 2022 11:09:53 +0200 Subject: [PATCH 1/2] fix: use var_str in 'reject' msgs CommandString is (de)serialized as 12 bytes. However, BIP-61 defines the 'response-to-msg' (message that triggered the reject) field to be a var_str [1]. [1]: https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki#common-payload --- src/network/message.rs | 2 +- src/network/message_network.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/network/message.rs b/src/network/message.rs index 49aa7c01..39e4a5c8 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -472,7 +472,7 @@ mod test { NetworkMessage::GetCFCheckpt(GetCFCheckpt{filter_type: 17, stop_hash: hash([25u8; 32]).into()}), NetworkMessage::CFCheckpt(CFCheckpt{filter_type: 27, stop_hash: hash([77u8; 32]).into(), filter_headers: vec![hash([3u8; 32]).into(), hash([99u8; 32]).into()]}), NetworkMessage::Alert(vec![45,66,3,2,6,8,9,12,3,130]), - NetworkMessage::Reject(Reject{message: CommandString::try_from("Test reject").unwrap(), ccode: RejectReason::Duplicate, reason: "Cause".into(), hash: hash([255u8; 32])}), + NetworkMessage::Reject(Reject{message: "Test reject".into(), ccode: RejectReason::Duplicate, reason: "Cause".into(), hash: hash([255u8; 32])}), NetworkMessage::FeeFilter(1000), NetworkMessage::WtxidRelay, NetworkMessage::AddrV2(vec![AddrV2Message{ addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), port: 0, services: ServiceFlags::NONE, time: 0 }]), diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 4422ad0c..9f6bd805 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -26,7 +26,6 @@ use network::address::Address; use network::constants::{self, ServiceFlags}; use consensus::{Encodable, Decodable, ReadExt}; use consensus::encode; -use network::message::CommandString; use hashes::sha256d; /// Some simple messages @@ -133,7 +132,7 @@ impl Decodable for RejectReason { #[derive(PartialEq, Eq, Clone, Debug)] pub struct Reject { /// message type rejected - pub message: CommandString, + pub message: Cow<'static, str>, /// reason of rejection as code pub ccode: RejectReason, /// reason of rejectection From 548725c5fb5fb5af156667f8cbd992d1aee6ead9 Mon Sep 17 00:00:00 2001 From: 0xb10c <0xb10c@gmail.com> Date: Mon, 4 Apr 2022 11:03:08 +0200 Subject: [PATCH 2/2] test: reject message (de)serialization This adds tests for the previously untested reject message (de)serialization. The two reject messages were received from an older Bitcoin Core peer that still sends reject messages. --- src/network/message_network.rs | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/network/message_network.rs b/src/network/message_network.rs index 9f6bd805..5bad463b 100644 --- a/src/network/message_network.rs +++ b/src/network/message_network.rs @@ -146,8 +146,11 @@ impl_consensus_encoding!(Reject, message, ccode, reason, hash); #[cfg(test)] mod tests { use super::VersionMessage; + use super::Reject; + use super::RejectReason; use hashes::hex::FromHex; + use hashes::sha256d::Hash; use network::constants::ServiceFlags; use consensus::encode::{deserialize, serialize}; @@ -171,4 +174,37 @@ mod tests { assert_eq!(serialize(&real_decode), from_sat); } + + #[test] + fn reject_message_test() { + let reject_tx_conflict = Vec::from_hex("027478121474786e2d6d656d706f6f6c2d636f6e666c69637405df54d3860b3c41806a3546ab48279300affacf4b88591b229141dcf2f47004").unwrap(); + let reject_tx_nonfinal = Vec::from_hex("02747840096e6f6e2d66696e616c259bbe6c83db8bbdfca7ca303b19413dc245d9f2371b344ede5f8b1339a5460b").unwrap(); + + let decode_result_conflict: Result = deserialize(&reject_tx_conflict); + let decode_result_nonfinal: Result = deserialize(&reject_tx_nonfinal); + + assert!(decode_result_conflict.is_ok()); + assert!(decode_result_nonfinal.is_ok()); + + let conflict = decode_result_conflict.unwrap(); + assert_eq!("tx", conflict.message); + assert_eq!(RejectReason::Duplicate, conflict.ccode); + assert_eq!("txn-mempool-conflict", conflict.reason); + assert_eq!( + Hash::from_hex("0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05").unwrap(), + conflict.hash + ); + + let nonfinal = decode_result_nonfinal.unwrap(); + assert_eq!("tx", nonfinal.message); + assert_eq!(RejectReason::NonStandard, nonfinal.ccode); + assert_eq!("non-final", nonfinal.reason); + assert_eq!( + Hash::from_hex("0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25").unwrap(), + nonfinal.hash + ); + + assert_eq!(serialize(&conflict), reject_tx_conflict); + assert_eq!(serialize(&nonfinal), reject_tx_nonfinal); + } }