Merge rust-bitcoin/rust-bitcoin#939: fix: reject message (de)serialization

548725c5fb test: reject message (de)serialization (0xb10c)
fc572aba86 fix: use var_str in 'reject' msgs (0xb10c)

Pull request description:

  [BIP-61 defines `response-to-msg`][bip61] (`Reject::message` in rust-bitcoin; the message that triggered the reject) to be a `var_str`. However, by using the `CommandString` it was (de)serialized as 12 byte string. A test is added that de- and serializes two reject messages received from an older Bitcoin Core peer.

  Reject message sending has been removed from Bitcoin Core, I'm still receiving them from older peers from time to time.

  [bip61]: https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki#common-payload

  gh-ref: https://github.com/rust-bitcoin/rust-bitcoin/pull/323

ACKs for top commit:
  apoelstra:
    ACK 548725c5fb

Tree-SHA512: e5cbf215a471f113b4dd7f7fada162686fc6e8c7b1e2e9e641667208a36d3db610e57e8b549756ffe597656fee5444fe95466f1b88f45366595766f7c4640eea
This commit is contained in:
Andrew Poelstra 2022-04-20 20:51:10 +00:00
commit 954b8a9b95
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
2 changed files with 38 additions and 3 deletions

View File

@ -472,7 +472,7 @@ mod test {
NetworkMessage::GetCFCheckpt(GetCFCheckpt{filter_type: 17, stop_hash: hash([25u8; 32]).into()}), 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::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::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::FeeFilter(1000),
NetworkMessage::WtxidRelay, NetworkMessage::WtxidRelay,
NetworkMessage::AddrV2(vec![AddrV2Message{ addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), port: 0, services: ServiceFlags::NONE, time: 0 }]), NetworkMessage::AddrV2(vec![AddrV2Message{ addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), port: 0, services: ServiceFlags::NONE, time: 0 }]),

View File

@ -26,7 +26,6 @@ use network::address::Address;
use network::constants::{self, ServiceFlags}; use network::constants::{self, ServiceFlags};
use consensus::{Encodable, Decodable, ReadExt}; use consensus::{Encodable, Decodable, ReadExt};
use consensus::encode; use consensus::encode;
use network::message::CommandString;
use hashes::sha256d; use hashes::sha256d;
/// Some simple messages /// Some simple messages
@ -133,7 +132,7 @@ impl Decodable for RejectReason {
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub struct Reject { pub struct Reject {
/// message type rejected /// message type rejected
pub message: CommandString, pub message: Cow<'static, str>,
/// reason of rejection as code /// reason of rejection as code
pub ccode: RejectReason, pub ccode: RejectReason,
/// reason of rejectection /// reason of rejectection
@ -147,8 +146,11 @@ impl_consensus_encoding!(Reject, message, ccode, reason, hash);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::VersionMessage; use super::VersionMessage;
use super::Reject;
use super::RejectReason;
use hashes::hex::FromHex; use hashes::hex::FromHex;
use hashes::sha256d::Hash;
use network::constants::ServiceFlags; use network::constants::ServiceFlags;
use consensus::encode::{deserialize, serialize}; use consensus::encode::{deserialize, serialize};
@ -172,4 +174,37 @@ mod tests {
assert_eq!(serialize(&real_decode), from_sat); 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<Reject, _> = deserialize(&reject_tx_conflict);
let decode_result_nonfinal: Result<Reject, _> = 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);
}
} }