diff --git a/Cargo.lock b/Cargo.lock index caf3adad23..5ff6f96f31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -684,6 +684,7 @@ version = "0.16.0-pre" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "ckb-core 0.16.0-pre", + "ckb-crypto 0.16.0-pre", "ckb-jsonrpc-types 0.16.0-pre", "ckb-logger 0.16.0-pre", "ckb-multisig 0.16.0-pre", diff --git a/util/crypto/src/secp/mod.rs b/util/crypto/src/secp/mod.rs index b77220fdee..fe6788dd46 100644 --- a/util/crypto/src/secp/mod.rs +++ b/util/crypto/src/secp/mod.rs @@ -33,12 +33,20 @@ mod tests { message } + #[test] + fn test_gen_keypair() { + let gen = Generator::new(); + let (privkey, pubkey) = gen.random_keypair().expect("gen keypair"); + assert_eq!(privkey.pubkey().expect("pubkey"), pubkey); + } + #[test] fn test_sign_verify() { let gen = Generator::new(); let (privkey, pubkey) = gen.random_keypair().unwrap(); let message = random_message(); let signature = privkey.sign_recoverable(&message).unwrap(); + assert!(signature.is_valid()); assert!(pubkey.verify(&message, &signature).is_ok()); } @@ -51,4 +59,25 @@ mod tests { assert_eq!(pubkey, signature.recover(&message).unwrap()); } + #[test] + fn test_serialize() { + let gen = Generator::new(); + let (privkey, pubkey) = gen.random_keypair().expect("gen keypair"); + let ser_pubkey = privkey.pubkey().expect("pubkey").serialize(); + assert_eq!(ser_pubkey.len(), 33); + let deser_pubkey = Pubkey::from_slice(&ser_pubkey).expect("deserialize pubkey"); + assert_eq!(deser_pubkey, pubkey); + + let deser_privkey = Privkey::from_slice(privkey.as_ref()); + assert_eq!(deser_privkey, privkey); + + let msg = random_message(); + let signature = privkey.sign_recoverable(&msg).expect("sign"); + let ser_signature = signature.serialize(); + assert_eq!(ser_signature.len(), 65); + let deser_signature = Signature::from_slice(&ser_signature).expect("deserialize"); + assert!(deser_signature.is_valid()); + assert_eq!(ser_signature, deser_signature.serialize()); + } + } diff --git a/util/crypto/src/secp/privkey.rs b/util/crypto/src/secp/privkey.rs index d8957affbf..4fc66fbe68 100644 --- a/util/crypto/src/secp/privkey.rs +++ b/util/crypto/src/secp/privkey.rs @@ -53,6 +53,12 @@ impl Into for Privkey { } } +impl AsRef<[u8]> for Privkey { + fn as_ref(&self) -> &[u8] { + self.inner.as_bytes() + } +} + impl FromStr for Privkey { type Err = Error; diff --git a/util/network-alert/Cargo.toml b/util/network-alert/Cargo.toml index 619969f803..4bf49a7f7d 100644 --- a/util/network-alert/Cargo.toml +++ b/util/network-alert/Cargo.toml @@ -23,3 +23,6 @@ serde = "1.0" serde_derive = "1.0" flatbuffers = "0.6.0" +[dev-dependencies] +ckb-crypto = { path = "../crypto" } + diff --git a/util/network-alert/src/lib.rs b/util/network-alert/src/lib.rs index 58023f4c5c..8513def523 100644 --- a/util/network-alert/src/lib.rs +++ b/util/network-alert/src/lib.rs @@ -10,6 +10,8 @@ pub mod alert_relayer; pub mod config; pub mod notifier; +#[cfg(test)] +mod tests; pub mod verifier; use std::time::Duration; diff --git a/util/network-alert/src/tests/mod.rs b/util/network-alert/src/tests/mod.rs new file mode 100644 index 0000000000..5efd82745f --- /dev/null +++ b/util/network-alert/src/tests/mod.rs @@ -0,0 +1,2 @@ +mod test_notifier; +mod test_verifier; diff --git a/util/network-alert/src/tests/test_notifier.rs b/util/network-alert/src/tests/test_notifier.rs new file mode 100644 index 0000000000..01d54616ee --- /dev/null +++ b/util/network-alert/src/tests/test_notifier.rs @@ -0,0 +1,88 @@ +use crate::notifier::Notifier; +use ckb_core::alert::AlertBuilder; +use std::sync::Arc; + +#[test] +fn test_notice_alerts_by_version() { + let mut notifier = Notifier::new("0.1.0".into()); + let alert1 = Arc::new( + AlertBuilder::default() + .id(1) + .max_version(Some("0.2.0".into())) + .min_version(Some("0.1.0".into())) + .build(), + ); + let alert2 = Arc::new( + AlertBuilder::default() + .id(2) + .max_version(Some("0.0.2".into())) + .build(), + ); + notifier.add(alert1); + notifier.add(alert2); + assert_eq!(notifier.received_alerts().len(), 2); + assert_eq!(notifier.noticed_alerts().len(), 1); + assert_eq!(notifier.noticed_alerts()[0].id, 1); +} + +#[test] +fn test_received_alerts() { + let mut notifier = Notifier::new("0.1.0".into()); + let alert1 = Arc::new( + AlertBuilder::default() + .id(1) + .max_version(Some("0.2.0".into())) + .min_version(Some("0.1.0".into())) + .build(), + ); + let dup_alert1 = Arc::new(AlertBuilder::default().id(1).build()); + notifier.add(Arc::clone(&alert1)); + assert!(notifier.has_received(1)); + notifier.add(dup_alert1); + assert_eq!(notifier.received_alerts().len(), 1); + assert_eq!(notifier.received_alerts()[0].hash(), alert1.hash()); +} + +#[test] +fn test_cancel_alert() { + let mut notifier = Notifier::new("0.1.0".into()); + let alert1 = Arc::new( + AlertBuilder::default() + .id(1) + .max_version(Some("0.2.0".into())) + .min_version(Some("0.1.0".into())) + .build(), + ); + let cancel_alert1 = Arc::new(AlertBuilder::default().id(2).cancel(1).build()); + notifier.add(Arc::clone(&alert1)); + assert!(notifier.has_received(1)); + notifier.add(Arc::clone(&cancel_alert1)); + assert!(notifier.has_received(1)); + assert!(notifier.has_received(2)); + assert_eq!(notifier.received_alerts().len(), 1); + assert_eq!(notifier.noticed_alerts().len(), 1); + assert_eq!(notifier.received_alerts()[0].hash(), cancel_alert1.hash()); +} + +#[test] +fn test_clear_expired_alerts() { + let mut notifier = Notifier::new("0.1.0".into()); + let notice_until = 1_561_084_974_000; + let before_expired_time = notice_until - 1000; + let after_expired_time = notice_until + 1000; + let alert1 = Arc::new( + AlertBuilder::default() + .id(1) + .notice_until(notice_until) + .build(), + ); + notifier.add(Arc::clone(&alert1)); + notifier.clear_expired_alerts(before_expired_time); + assert!(notifier.has_received(1)); + assert_eq!(notifier.received_alerts().len(), 1); + assert_eq!(notifier.noticed_alerts().len(), 1); + notifier.clear_expired_alerts(after_expired_time); + assert!(!notifier.has_received(1)); + assert_eq!(notifier.received_alerts().len(), 0); + assert_eq!(notifier.noticed_alerts().len(), 0); +} diff --git a/util/network-alert/src/tests/test_verifier.rs b/util/network-alert/src/tests/test_verifier.rs new file mode 100644 index 0000000000..f115588865 --- /dev/null +++ b/util/network-alert/src/tests/test_verifier.rs @@ -0,0 +1,33 @@ +use crate::config::Config; +use crate::verifier::Verifier; +use ckb_core::alert::AlertBuilder; +use ckb_crypto::secp::Generator; +use ckb_jsonrpc_types::JsonBytes; + +#[test] +fn test_veirifer() { + let keypairs: Vec<_> = (0..3) + .map(move |_| Generator::new().random_keypair()) + .collect::, _>>() + .expect("random keypair"); + let config = Config { + signatures_threshold: 2, + public_keys: keypairs + .iter() + .map(|(_, pubkey)| JsonBytes::from_vec(pubkey.serialize())) + .collect(), + }; + let verifier = Verifier::new(config); + let mut alert = AlertBuilder::default().id(1).build(); + let hash = alert.hash(); + let signatures = keypairs + .iter() + .map(|(privkey, _)| privkey.sign_recoverable(&hash)) + .collect::, _>>() + .expect("sign alert"); + alert.signatures = signatures + .into_iter() + .map(|s| s.serialize().into()) + .collect(); + assert!(verifier.verify_signatures(&alert).is_ok()); +}