use crate::{
block::{
block_test_utils::{certificate_for_genesis, *},
Block,
},
common::{Author, Payload},
quorum_cert::QuorumCert,
vote_data::VoteData,
};
use aptos_crypto::{hash::HashValue, test_utils::TestAptosCrypto};
use aptos_types::{
account_address::AccountAddress,
block_info::{BlockInfo, Round},
ledger_info::{LedgerInfo, LedgerInfoWithSignatures},
on_chain_config::ValidatorSet,
validator_signer::ValidatorSigner,
validator_verifier::{random_validator_verifier, ValidatorVerifier},
};
use std::{collections::BTreeMap, sync::Arc};
#[test]
fn test_genesis() {
let genesis_block = Block::make_genesis_block();
assert_eq!(genesis_block.parent_id(), HashValue::zero());
assert_ne!(genesis_block.id(), HashValue::zero());
assert!(genesis_block.is_genesis_block());
}
#[test]
fn test_nil_block() {
let genesis_block = Block::make_genesis_block();
let quorum_cert = certificate_for_genesis();
let nil_block = Block::new_nil(1, quorum_cert, vec![]);
assert_eq!(
nil_block.quorum_cert().certified_block().id(),
genesis_block.id()
);
assert_eq!(nil_block.round(), 1);
assert_eq!(nil_block.timestamp_usecs(), genesis_block.timestamp_usecs());
assert_eq!(nil_block.is_nil_block(), true);
assert!(nil_block.author().is_none());
let dummy_verifier = Arc::new(ValidatorVerifier::new(BTreeMap::new()));
assert!(nil_block
.validate_signature(dummy_verifier.as_ref())
.is_ok());
assert!(nil_block.verify_well_formed().is_ok());
let signer = ValidatorSigner::random(None);
let parent_block_info = nil_block.quorum_cert().certified_block();
let nil_block_qc = gen_test_certificate(
vec![&signer],
nil_block.gen_block_info(
parent_block_info.executed_state_id(),
parent_block_info.version(),
parent_block_info.next_epoch_state().cloned(),
),
nil_block.quorum_cert().certified_block().clone(),
None,
);
println!(
"{:?} {:?}",
nil_block.id(),
nil_block_qc.certified_block().id()
);
let nil_block_child = Block::new_proposal(
Payload::new_empty(),
2,
aptos_infallible::duration_since_epoch().as_micros() as u64,
nil_block_qc,
&signer,
Vec::new(),
);
assert_eq!(nil_block_child.is_nil_block(), false);
assert_eq!(nil_block_child.round(), 2);
assert_eq!(nil_block_child.parent_id(), nil_block.id());
}
#[test]
fn test_block_relation() {
let signer = ValidatorSigner::random(None);
let genesis_block = Block::make_genesis_block();
let quorum_cert = certificate_for_genesis();
let payload = Payload::new_empty();
let next_block = Block::new_proposal(
payload.clone(),
1,
aptos_infallible::duration_since_epoch().as_micros() as u64,
quorum_cert,
&signer,
Vec::new(),
);
assert_eq!(next_block.round(), 1);
assert_eq!(genesis_block.is_parent_of(&next_block), true);
assert_eq!(
next_block.quorum_cert().certified_block().id(),
genesis_block.id()
);
assert_eq!(next_block.payload(), Some(&payload));
let cloned_block = next_block.clone();
assert_eq!(cloned_block.round(), next_block.round());
}
#[test]
fn test_same_qc_different_authors() {
let signer = ValidatorSigner::random(None);
let genesis_qc = certificate_for_genesis();
let round = 1;
let payload = Payload::new_empty();
let current_timestamp = aptos_infallible::duration_since_epoch().as_micros() as u64;
let block_round_1 = Block::new_proposal(
payload.clone(),
round,
current_timestamp,
genesis_qc.clone(),
&signer,
Vec::new(),
);
let signature = signer.sign(genesis_qc.ledger_info().ledger_info());
let mut ledger_info_altered = genesis_qc.ledger_info().clone();
ledger_info_altered.add_signature(signer.author(), signature);
let genesis_qc_altered = QuorumCert::new(genesis_qc.vote_data().clone(), ledger_info_altered);
let block_round_1_altered = Block::new_proposal(
payload.clone(),
round,
current_timestamp,
genesis_qc_altered,
&signer,
Vec::new(),
);
let block_round_1_same = Block::new_proposal(
payload,
round,
current_timestamp,
genesis_qc,
&signer,
Vec::new(),
);
assert!(block_round_1.id() != block_round_1_altered.id());
assert_eq!(block_round_1.id(), block_round_1_same.id());
}
#[test]
fn test_block_metadata_bitmaps() {
let num_validators = 4;
let (signers, validator_verifier) = random_validator_verifier(num_validators, None, true);
let validator_set = ValidatorSet::from(&validator_verifier);
let validators: Vec<_> = validator_verifier
.get_ordered_account_addresses_iter()
.collect();
let ledger_info = LedgerInfo::mock_genesis(Some(validator_set));
let genesis_qc = QuorumCert::certificate_for_genesis_from_ledger_info(
&ledger_info,
Block::make_genesis_block_from_ledger_info(&ledger_info).id(),
);
let payload = Payload::new_empty();
let start_round = 1;
let start_timestamp = aptos_infallible::duration_since_epoch().as_micros() as u64;
let block_1 = Block::new_proposal(
payload.clone(),
start_round,
start_timestamp,
genesis_qc,
&signers[0],
Vec::new(),
);
let block_metadata_1 = block_1.new_block_metadata(&validators);
assert_eq!(signers[0].author(), block_metadata_1.proposer());
assert_eq!(
num_validators,
block_metadata_1.previous_block_votes().len()
);
let mut ledger_info_1 = LedgerInfoWithSignatures::new(ledger_info, BTreeMap::new());
let votes_1 = vec![true, false, true, true];
votes_1
.iter()
.zip(
validators.iter().zip(
signers
.iter()
.map(|signer| signer.sign(&TestAptosCrypto("msg".to_string()))),
),
)
.for_each(|(&voted, (&address, signature))| {
if voted {
ledger_info_1.add_signature(address, signature)
}
});
let qc_1 = QuorumCert::new(
VoteData::new(BlockInfo::empty(), BlockInfo::empty()),
ledger_info_1,
);
let block_2 = Block::new_proposal(
payload,
start_round + 1,
start_timestamp + 1,
qc_1,
&signers[1],
Vec::new(),
);
let block_metadata_2 = block_2.new_block_metadata(&validators);
assert_eq!(signers[1].author(), block_metadata_2.proposer());
assert_eq!(&votes_1, block_metadata_2.previous_block_votes());
}
#[test]
fn test_nil_block_metadata_bitmaps() {
let quorum_cert = certificate_for_genesis();
let nil_block = Block::new_nil(1, quorum_cert, vec![]);
let nil_block_metadata = nil_block.new_block_metadata(&Vec::new());
assert_eq!(AccountAddress::ZERO, nil_block_metadata.proposer());
assert_eq!(0, nil_block_metadata.previous_block_votes().len());
}
#[test]
fn test_failed_authors_well_formed() {
let signer = ValidatorSigner::random(None);
let other = Author::random();
let quorum_cert = certificate_for_genesis();
let payload = Payload::new_empty();
let create_block = |round: Round, failed_authors: Vec<(Round, Author)>| {
Block::new_proposal(
payload.clone(),
round,
1,
quorum_cert.clone(),
&signer,
failed_authors,
)
};
assert!(create_block(1, vec![]).verify_well_formed().is_ok());
assert!(create_block(2, vec![]).verify_well_formed().is_ok());
assert!(create_block(2, vec![(1, other)])
.verify_well_formed()
.is_ok());
assert!(create_block(3, vec![(1, other)])
.verify_well_formed()
.is_ok());
assert!(create_block(3, vec![(2, other)])
.verify_well_formed()
.is_ok());
assert!(create_block(3, vec![(1, other), (2, other)])
.verify_well_formed()
.is_ok());
assert!(create_block(1, vec![(0, other)])
.verify_well_formed()
.is_err());
assert!(create_block(2, vec![(0, other)])
.verify_well_formed()
.is_err());
assert!(create_block(2, vec![(2, other)])
.verify_well_formed()
.is_err());
assert!(create_block(2, vec![(1, other), (1, other)])
.verify_well_formed()
.is_err());
assert!(create_block(3, vec![(0, other)])
.verify_well_formed()
.is_err());
assert!(create_block(3, vec![(3, other)])
.verify_well_formed()
.is_err());
assert!(create_block(3, vec![(4, other)])
.verify_well_formed()
.is_err());
assert!(create_block(3, vec![(1, other), (1, other), (1, other)])
.verify_well_formed()
.is_err());
assert!(create_block(3, vec![(1, other), (1, other)])
.verify_well_formed()
.is_err());
assert!(create_block(3, vec![(2, other), (1, other)])
.verify_well_formed()
.is_err());
}