diff --git a/Cargo.lock b/Cargo.lock index 0456dbe6ff2723..c9112fa2b7bc4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7112,6 +7112,7 @@ version = "2.2.0" dependencies = [ "assert_matches", "bincode", + "bs58", "bv", "clap 2.33.3", "crossbeam-channel", @@ -7122,7 +7123,9 @@ dependencies = [ "lru", "num-traits", "num_cpus", + "rand 0.7.3", "rand 0.8.5", + "rand_chacha 0.2.2", "rand_chacha 0.3.1", "rayon", "serde", diff --git a/Cargo.toml b/Cargo.toml index d769f182b5c3f3..ffa5c00431cc13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -377,6 +377,7 @@ quote = "1.0" rand = "0.8.5" rand0-7 = { package = "rand", version = "0.7" } rand_chacha = "0.3.1" +rand_chacha0-2 = { package = "rand_chacha", version = "0.2.2" } rayon = "1.10.0" reed-solomon-erasure = "6.0.0" regex = "1.11.1" diff --git a/gossip/Cargo.toml b/gossip/Cargo.toml index 3d533db3016429..126d0bbe7efc4d 100644 --- a/gossip/Cargo.toml +++ b/gossip/Cargo.toml @@ -61,7 +61,10 @@ static_assertions = { workspace = true } thiserror = { workspace = true } [dev-dependencies] +bs58 = { workspace = true } num_cpus = { workspace = true } +rand0-7 = { workspace = true } +rand_chacha0-2 = { workspace = true } serial_test = { workspace = true } solana-perf = { workspace = true, features = ["dev-context-only-utils"] } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } diff --git a/gossip/src/crds_value.rs b/gossip/src/crds_value.rs index fb3061d1499f85..c05d79ec5e95cf 100644 --- a/gossip/src/crds_value.rs +++ b/gossip/src/crds_value.rs @@ -243,11 +243,16 @@ mod test { super::*, crate::crds_data::{LowestSlot, NodeInstance, Vote}, bincode::deserialize, + rand0_7::{Rng, SeedableRng}, + rand_chacha0_2::ChaChaRng, solana_perf::test_tx::new_test_vote_tx, solana_sdk::{ signature::{Keypair, Signer}, timing::timestamp, + vote::state::TowerSync, }, + solana_vote_program::{vote_state::Lockout, vote_transaction::new_tower_sync_transaction}, + std::str::FromStr, }; #[test] @@ -348,4 +353,89 @@ mod test { assert!(node.should_force_push(&pubkey)); assert!(!node.should_force_push(&Pubkey::new_unique())); } + + #[test] + fn test_serialize_round_trip() { + let mut rng = ChaChaRng::from_seed( + bs58::decode("4nHgVgCvVaHnsrg4dYggtvWYYgV3JbeyiRBWupPMt3EG") + .into_vec() + .map(<[u8; 32]>::try_from) + .unwrap() + .unwrap(), + ); + let values: Vec = vec![ + { + let keypair = Keypair::generate(&mut rng); + let lockouts: [Lockout; 4] = [ + Lockout::new_with_confirmation_count(302_388_991, 11), + Lockout::new_with_confirmation_count(302_388_995, 7), + Lockout::new_with_confirmation_count(302_389_001, 3), + Lockout::new_with_confirmation_count(302_389_005, 1), + ]; + let tower_sync = TowerSync { + lockouts: lockouts.into_iter().collect(), + root: Some(302_388_989), + hash: Hash::new_from_array(rng.gen()), + timestamp: Some(1_732_044_716_167), + block_id: Hash::new_from_array(rng.gen()), + }; + let vote = new_tower_sync_transaction( + tower_sync, + Hash::new_from_array(rng.gen()), // blockhash + &keypair, // node_keypair + &Keypair::generate(&mut rng), // vote_keypair + &Keypair::generate(&mut rng), // authorized_voter_keypair + None, // switch_proof_hash + ); + let vote = Vote::new( + keypair.pubkey(), + vote, + 1_732_045_236_371, // wallclock + ) + .unwrap(); + CrdsValue::new(CrdsData::Vote(5, vote), &keypair) + }, + { + let keypair = Keypair::generate(&mut rng); + let lockouts: [Lockout; 3] = [ + Lockout::new_with_confirmation_count(302_410_500, 9), + Lockout::new_with_confirmation_count(302_410_505, 5), + Lockout::new_with_confirmation_count(302_410_517, 1), + ]; + let tower_sync = TowerSync { + lockouts: lockouts.into_iter().collect(), + root: Some(302_410_499), + hash: Hash::new_from_array(rng.gen()), + timestamp: Some(1_732_053_615_237), + block_id: Hash::new_from_array(rng.gen()), + }; + let vote = new_tower_sync_transaction( + tower_sync, + Hash::new_from_array(rng.gen()), // blockhash + &keypair, // node_keypair + &Keypair::generate(&mut rng), // vote_keypair + &Keypair::generate(&mut rng), // authorized_voter_keypair + None, // switch_proof_hash + ); + let vote = Vote::new( + keypair.pubkey(), + vote, + 1_732_053_639_350, // wallclock + ) + .unwrap(); + CrdsValue::new(CrdsData::Vote(5, vote), &keypair) + }, + ]; + let bytes = bincode::serialize(&values).unwrap(); + // Serialized bytes are fixed and should never change. + assert_eq!( + solana_sdk::hash::hash(&bytes), + Hash::from_str("7gtcoafccWE964njbs2bA1QuVFeV34RaoY781yLx2A8N").unwrap() + ); + // serialize -> deserialize should round trip. + assert_eq!( + bincode::deserialize::>(&bytes).unwrap(), + values + ); + } }