Skip to content

Commit

Permalink
protocols/gossipsub/src/protocol: Use quickcheck to test signing (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxinden committed Jun 1, 2020
1 parent e9afd95 commit 3d1a025
Showing 1 changed file with 82 additions and 41 deletions.
123 changes: 82 additions & 41 deletions protocols/gossipsub/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,53 +583,94 @@ pub enum GossipsubControlAction {
#[cfg(test)]
mod tests {
use super::*;
use crate::topic::Topic;
use quickcheck::*;
use rand::Rng;

#[derive(Clone, Debug)]
struct Message(GossipsubMessage);

impl Arbitrary for Message {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Message(GossipsubMessage {
source: PeerId::random(),
data: (0..g.gen_range(1, 1024)).map(|_| g.gen()).collect(),
sequence_number: g.gen(),
topics: Vec::arbitrary(g).into_iter().map(|id: TopicId| id.0).collect(),
signature: None,
key: None,
})
}
}

#[test]
fn sign_and_verify_message_peer_inline() {
let source_key = Keypair::generate_secp256k1();
let peer_id = source_key.public().into_peer_id();
let mut message = rpc_proto::Message {
from: Some(peer_id.clone().into_bytes()),
data: Some(vec![1, 2, 3, 4, 5, 6]),
seqno: Some(10u64.to_be_bytes().to_vec()),
topic_ids: vec!["test1".into(), "test2".into()],
signature: None,
key: None,
};
#[derive(Clone, Debug)]
struct TopicId(TopicHash);

impl Arbitrary for TopicId {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
TopicId(Topic::new((0..g.gen_range(0, 1024)).map(|_| g.gen::<char>()).collect()).sha256_hash())
}
}

#[derive(Clone)]
struct TestKeypair(Keypair);

impl Arbitrary for TestKeypair {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
let keypair = if g.gen() {
// Small enough to be inlined.
Keypair::generate_secp256k1()
} else {
// Too large to be inlined.
let mut rsa_key = hex::decode("308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100ef930f41a71288b643c1cbecbf5f72ab53992249e2b00835bf07390b6745419f3848cbcc5b030faa127bc88cdcda1c1d6f3ff699f0524c15ab9d2c9d8015f5d4bd09881069aad4e9f91b8b0d2964d215cdbbae83ddd31a7622a8228acee07079f6e501aea95508fa26c6122816ef7b00ac526d422bd12aed347c37fff6c1c307f3ba57bb28a7f28609e0bdcc839da4eedca39f5d2fa855ba4b0f9c763e9764937db929a1839054642175312a3de2d3405c9d27bdf6505ef471ce85c5e015eee85bf7874b3d512f715de58d0794fd8afe021c197fbd385bb88a930342fac8da31c27166e2edab00fa55dc1c3814448ba38363077f4e8fe2bdea1c081f85f1aa6f02030100010282010028ff427a1aac1a470e7b4879601a6656193d3857ea79f33db74df61e14730e92bf9ffd78200efb0c40937c3356cbe049cd32e5f15be5c96d5febcaa9bd3484d7fded76a25062d282a3856a1b3b7d2c525cdd8434beae147628e21adf241dd64198d5819f310d033743915ba40ea0b6acdbd0533022ad6daa1ff42de51885f9e8bab2306c6ef1181902d1cd7709006eba1ab0587842b724e0519f295c24f6d848907f772ae9a0953fc931f4af16a07df450fb8bfa94572562437056613647818c238a6ff3f606cffa0533e4b8755da33418dfbc64a85110b1a036623c947400a536bb8df65e5ebe46f2dfd0cfc86e7aeeddd7574c253e8fbf755562b3669525d902818100f9fff30c6677b78dd31ec7a634361438457e80be7a7faf390903067ea8355faa78a1204a82b6e99cb7d9058d23c1ecf6cfe4a900137a00cecc0113fd68c5931602980267ea9a95d182d48ba0a6b4d5dd32fdac685cb2e5d8b42509b2eb59c9579ea6a67ccc7547427e2bd1fb1f23b0ccb4dd6ba7d206c8dd93253d70a451701302818100f5530dfef678d73ce6a401ae47043af10a2e3f224c71ae933035ecd68ccbc4df52d72bc6ca2b17e8faf3e548b483a2506c0369ab80df3b137b54d53fac98f95547c2bc245b416e650ce617e0d29db36066f1335a9ba02ad3e0edf9dc3d58fd835835042663edebce81803972696c789012847cb1f854ab2ac0a1bd3867ac7fb502818029c53010d456105f2bf52a9a8482bca2224a5eac74bf3cc1a4d5d291fafcdffd15a6a6448cce8efdd661f6617ca5fc37c8c885cc3374e109ac6049bcbf72b37eabf44602a2da2d4a1237fd145c863e6d75059976de762d9d258c42b0984e2a2befa01c95217c3ee9c736ff209c355466ff99375194eff943bc402ea1d172a1ed02818027175bf493bbbfb8719c12b47d967bf9eac061c90a5b5711172e9095c38bb8cc493c063abffe4bea110b0a2f22ac9311b3947ba31b7ef6bfecf8209eebd6d86c316a2366bbafda7279b2b47d5bb24b6202254f249205dcad347b574433f6593733b806f84316276c1990a016ce1bbdbe5f650325acc7791aefe515ecc60063bd02818100b6a2077f4adcf15a17092d9c4a346d6022ac48f3861b73cf714f84c440a07419a7ce75a73b9cbff4597c53c128bf81e87b272d70428a272d99f90cd9b9ea1033298e108f919c6477400145a102df3fb5601ffc4588203cf710002517bfa24e6ad32f4d09c6b1a995fa28a3104131bedd9072f3b4fb4a5c2056232643d310453f").unwrap();
Keypair::rsa_from_pkcs8(&mut rsa_key).unwrap()
};

TestKeypair(keypair)
}
}

let codec = GossipsubCodec::new(codec::UviBytes::default(), Some(source_key), peer_id);

// sign the message
codec.sign_message(&mut message).unwrap();
// verify the signed message
assert!(GossipsubCodec::verify_message(&message));
impl std::fmt::Debug for TestKeypair {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TestKeypair")
.field("public", &self.0.public())
.finish()
}
}

#[test]
fn sign_and_verify_message() {
let mut rsa_key = hex::decode("308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100ef930f41a71288b643c1cbecbf5f72ab53992249e2b00835bf07390b6745419f3848cbcc5b030faa127bc88cdcda1c1d6f3ff699f0524c15ab9d2c9d8015f5d4bd09881069aad4e9f91b8b0d2964d215cdbbae83ddd31a7622a8228acee07079f6e501aea95508fa26c6122816ef7b00ac526d422bd12aed347c37fff6c1c307f3ba57bb28a7f28609e0bdcc839da4eedca39f5d2fa855ba4b0f9c763e9764937db929a1839054642175312a3de2d3405c9d27bdf6505ef471ce85c5e015eee85bf7874b3d512f715de58d0794fd8afe021c197fbd385bb88a930342fac8da31c27166e2edab00fa55dc1c3814448ba38363077f4e8fe2bdea1c081f85f1aa6f02030100010282010028ff427a1aac1a470e7b4879601a6656193d3857ea79f33db74df61e14730e92bf9ffd78200efb0c40937c3356cbe049cd32e5f15be5c96d5febcaa9bd3484d7fded76a25062d282a3856a1b3b7d2c525cdd8434beae147628e21adf241dd64198d5819f310d033743915ba40ea0b6acdbd0533022ad6daa1ff42de51885f9e8bab2306c6ef1181902d1cd7709006eba1ab0587842b724e0519f295c24f6d848907f772ae9a0953fc931f4af16a07df450fb8bfa94572562437056613647818c238a6ff3f606cffa0533e4b8755da33418dfbc64a85110b1a036623c947400a536bb8df65e5ebe46f2dfd0cfc86e7aeeddd7574c253e8fbf755562b3669525d902818100f9fff30c6677b78dd31ec7a634361438457e80be7a7faf390903067ea8355faa78a1204a82b6e99cb7d9058d23c1ecf6cfe4a900137a00cecc0113fd68c5931602980267ea9a95d182d48ba0a6b4d5dd32fdac685cb2e5d8b42509b2eb59c9579ea6a67ccc7547427e2bd1fb1f23b0ccb4dd6ba7d206c8dd93253d70a451701302818100f5530dfef678d73ce6a401ae47043af10a2e3f224c71ae933035ecd68ccbc4df52d72bc6ca2b17e8faf3e548b483a2506c0369ab80df3b137b54d53fac98f95547c2bc245b416e650ce617e0d29db36066f1335a9ba02ad3e0edf9dc3d58fd835835042663edebce81803972696c789012847cb1f854ab2ac0a1bd3867ac7fb502818029c53010d456105f2bf52a9a8482bca2224a5eac74bf3cc1a4d5d291fafcdffd15a6a6448cce8efdd661f6617ca5fc37c8c885cc3374e109ac6049bcbf72b37eabf44602a2da2d4a1237fd145c863e6d75059976de762d9d258c42b0984e2a2befa01c95217c3ee9c736ff209c355466ff99375194eff943bc402ea1d172a1ed02818027175bf493bbbfb8719c12b47d967bf9eac061c90a5b5711172e9095c38bb8cc493c063abffe4bea110b0a2f22ac9311b3947ba31b7ef6bfecf8209eebd6d86c316a2366bbafda7279b2b47d5bb24b6202254f249205dcad347b574433f6593733b806f84316276c1990a016ce1bbdbe5f650325acc7791aefe515ecc60063bd02818100b6a2077f4adcf15a17092d9c4a346d6022ac48f3861b73cf714f84c440a07419a7ce75a73b9cbff4597c53c128bf81e87b272d70428a272d99f90cd9b9ea1033298e108f919c6477400145a102df3fb5601ffc4588203cf710002517bfa24e6ad32f4d09c6b1a995fa28a3104131bedd9072f3b4fb4a5c2056232643d310453f").unwrap();
let source_key = Keypair::rsa_from_pkcs8(&mut rsa_key).unwrap();
let peer_id = source_key.public().into_peer_id();
let mut message = rpc_proto::Message {
from: Some(peer_id.clone().into_bytes()),
data: Some(vec![1, 2, 3, 4, 5, 6]),
seqno: Some(10u64.to_be_bytes().to_vec()),
topic_ids: vec!["test1".into(), "test2".into()],
signature: None,
key: None,
};
fn encode_decode() {
fn prop(message: Message, source_key: TestKeypair) {
let mut message = message.0;
let source_key = source_key.0;

let peer_id = source_key.public().into_peer_id();
message.source = peer_id.clone();

let rpc = GossipsubRpc {
messages: vec![message],
subscriptions: vec![],
control_msgs: vec![],
};

let mut codec = GossipsubCodec::new(
codec::UviBytes::default(),
Some(source_key.clone()),
peer_id,
);

let mut buf = BytesMut::new();

codec.encode(rpc.clone(), &mut buf).unwrap();
let mut decoded_rpc = codec.decode(&mut buf).unwrap().unwrap();

decoded_rpc.messages[0].signature = None;
decoded_rpc.messages[0].key = None;

assert_eq!(rpc, decoded_rpc);
}

let codec = GossipsubCodec::new(
codec::UviBytes::default(),
Some(source_key.clone()),
peer_id,
);
// sign the message
codec.sign_message(&mut message).unwrap();
// key is not inlined
message.key = Some(source_key.public().into_protobuf_encoding());

// verify the signed message
assert!(GossipsubCodec::verify_message(&message));
QuickCheck::new().quickcheck(prop as fn(_, _) -> _)
}
}

0 comments on commit 3d1a025

Please sign in to comment.