diff --git a/protocols/gossipsub/CHANGELOG.md b/protocols/gossipsub/CHANGELOG.md index c06c268d..b3accf6e 100644 --- a/protocols/gossipsub/CHANGELOG.md +++ b/protocols/gossipsub/CHANGELOG.md @@ -1,3 +1,10 @@ +# 0.44.2 - unreleased + +- Signed messages now use sequential integers in the sequence number field. + See [PR 3551]. + +[PR 3551]: https://github.com/libp2p/rust-libp2p/pull/3551 + # 0.44.1 - Migrate from `prost` to `quick-protobuf`. This removes `protoc` dependency. See [PR 3312]. diff --git a/protocols/gossipsub/src/behaviour.rs b/protocols/gossipsub/src/behaviour.rs index be28285f..13ef81b3 100644 --- a/protocols/gossipsub/src/behaviour.rs +++ b/protocols/gossipsub/src/behaviour.rs @@ -80,7 +80,7 @@ mod tests; #[derive(Clone)] pub enum MessageAuthenticity { /// Message signing is enabled. The author will be the owner of the key and the sequence number - /// will be a random number. + /// will be linearly increasing. Signed(Keypair), /// Message signing is disabled. /// @@ -155,6 +155,8 @@ enum PublishConfig { keypair: Keypair, author: PeerId, inline_key: Option>, + last_seq_no: u64, // This starts from a random number and increases then overflows (if + // required) }, Author(PeerId), RandomAuthor, @@ -190,6 +192,7 @@ impl From for PublishConfig { keypair, author: public_key.to_peer_id(), inline_key: key, + last_seq_no: rand::random(), } } MessageAuthenticity::Author(peer_id) => PublishConfig::Author(peer_id), @@ -2749,18 +2752,21 @@ where /// Constructs a [`RawMessage`] performing message signing if required. pub(crate) fn build_raw_message( - &self, + &mut self, topic: TopicHash, data: Vec, ) -> Result { - match &self.publish_config { + match &mut self.publish_config { PublishConfig::Signing { ref keypair, author, inline_key, + mut last_seq_no, } => { - // Build and sign the message - let sequence_number: u64 = rand::random(); + // Increment the last sequence number + last_seq_no = last_seq_no.wrapping_add(1); + + let sequence_number = last_seq_no; let signature = { let message = proto::Message { diff --git a/protocols/gossipsub/src/lib.rs b/protocols/gossipsub/src/lib.rs index 39d36241..222a2f34 100644 --- a/protocols/gossipsub/src/lib.rs +++ b/protocols/gossipsub/src/lib.rs @@ -50,8 +50,9 @@ //! - **Sequence Numbers** - A message on the gossipsub network is identified by the source //! [`libp2p_core::PeerId`] and a nonce (sequence number) of the message. The sequence numbers in //! this implementation are sent as raw bytes across the wire. They are 64-bit big-endian unsigned -//! integers. They are chosen at random in this implementation of gossipsub, but are sequential in -//! the current go implementation. +//! integers. When messages are signed, they are monotonically increasing integers starting from a +//! random value and wrapping around u64::MAX. When messages are unsigned, they are chosen at random. +//! NOTE: These numbers are sequential in the current go implementation. //! //! # Peer Discovery //! diff --git a/protocols/gossipsub/src/protocol.rs b/protocols/gossipsub/src/protocol.rs index cdd50037..f7b04269 100644 --- a/protocols/gossipsub/src/protocol.rs +++ b/protocols/gossipsub/src/protocol.rs @@ -573,7 +573,7 @@ mod tests { // generate an arbitrary GossipsubMessage using the behaviour signing functionality let config = Config::default(); - let gs: Behaviour = + let mut gs: Behaviour = Behaviour::new(crate::MessageAuthenticity::Signed(keypair.0), config).unwrap(); let data = (0..g.gen_range(10..10024u32)) .map(|_| u8::arbitrary(g))