Skip to content

Commit

Permalink
[decoupled-execution] Integration Part 4 - More tests
Browse files Browse the repository at this point in the history
Add unit tests for ordering_state_computer and execution_phase.

Closes: diem#8784
  • Loading branch information
Yu Xia authored and bors-libra committed Jul 21, 2021
1 parent 9b36530 commit 516b1d9
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 38 deletions.
14 changes: 2 additions & 12 deletions consensus/src/experimental/ordering_state_computer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{error::StateSyncError, state_replication::StateComputer};
use anyhow::Result;
use channel::Sender;
use consensus_types::{block::Block, executed_block::ExecutedBlock};
use diem_crypto::{hash::ACCUMULATOR_PLACEHOLDER_HASH, HashValue};
use diem_crypto::HashValue;
use diem_types::ledger_info::LedgerInfoWithSignatures;
use executor_types::{Error as ExecutionError, StateComputeResult};
use fail::fail_point;
Expand Down Expand Up @@ -40,17 +40,7 @@ impl StateComputer for OrderingStateComputer {
// This will break the e2e smoke test (for now because
// no one is actually handling the next phase) if the
// decoupled execution feature is turned on.
Ok(StateComputeResult::new(
*ACCUMULATOR_PLACEHOLDER_HASH,
vec![],
0,
vec![],
0,
None,
vec![],
vec![],
vec![],
))
Ok(StateComputeResult::new_dummy())
}

/// Send ordered blocks to the real execution phase through the channel.
Expand Down
71 changes: 70 additions & 1 deletion consensus/src/experimental/tests/execution_phase_tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,73 @@
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

// Placeholder
use crate::experimental::{
execution_phase::ExecutionPhase, tests::ordering_state_computer_tests::random_empty_block,
};
use consensus_types::{block::Block, executed_block::ExecutedBlock};
use diem_types::ledger_info::{LedgerInfo, LedgerInfoWithSignatures};

use crate::test_utils::{consensus_runtime, timed_block_on, RandomComputeResultStateComputer};
use consensus_types::block::block_test_utils::certificate_for_genesis;
use diem_crypto::{ed25519::Ed25519Signature, hash::ACCUMULATOR_PLACEHOLDER_HASH};
use diem_types::{account_address::AccountAddress, validator_verifier::random_validator_verifier};
use executor_types::StateComputeResult;
use futures::{SinkExt, StreamExt};
use std::{collections::BTreeMap, sync::Arc};

#[test]
fn test_execution_phase() {
let num_nodes = 1;
let channel_size = 30;
let mut runtime = consensus_runtime();

let (mut execution_phase_tx, execution_phase_rx) =
channel::new_test::<(Vec<Block>, LedgerInfoWithSignatures)>(channel_size);

let (commit_phase_tx, mut commit_phase_rx) =
channel::new_test::<(Vec<ExecutedBlock>, LedgerInfoWithSignatures)>(channel_size);

let random_state_computer = RandomComputeResultStateComputer::new();
let random_execute_result_root_hash = random_state_computer.get_root_hash();

let execution_phase = ExecutionPhase::new(
execution_phase_rx,
Arc::new(random_state_computer),
commit_phase_tx,
);

runtime.spawn(execution_phase.start());

let (signers, _) = random_validator_verifier(num_nodes, None, false);
let signer = &signers[0];
let genesis_qc = certificate_for_genesis();
let block = random_empty_block(signer, genesis_qc);

let dummy_state_compute_result = StateComputeResult::new_dummy();

let li = LedgerInfo::new(
block.gen_block_info(
dummy_state_compute_result.root_hash(),
dummy_state_compute_result.version(),
dummy_state_compute_result.epoch_state().clone(),
),
*ACCUMULATOR_PLACEHOLDER_HASH,
);

let li_sig =
LedgerInfoWithSignatures::new(li, BTreeMap::<AccountAddress, Ed25519Signature>::new());

let blocks = vec![block.clone()];

timed_block_on(&mut runtime, async move {
execution_phase_tx.send((blocks, li_sig.clone())).await.ok();
let (executed_blocks, executed_finality_proof) = commit_phase_rx.next().await.unwrap();
assert_eq!(executed_blocks.len(), 1);
assert_eq!(
executed_blocks[0].compute_result(),
&StateComputeResult::new_dummy_with_root_hash(random_execute_result_root_hash)
);
assert_eq!(executed_blocks[0].block(), &block);
assert_eq!(executed_finality_proof, li_sig);
});
}
2 changes: 2 additions & 0 deletions consensus/src/experimental/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
// SPDX-License-Identifier: Apache-2.0

mod commit_phase_tests;
mod execution_phase_tests;
mod ordering_state_computer_tests;
Original file line number Diff line number Diff line change
@@ -1,4 +1,89 @@
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

// Placeholder
use crate::{
experimental::ordering_state_computer::OrderingStateComputer, state_replication::StateComputer,
};
use channel::Receiver;
use consensus_types::block::{block_test_utils::certificate_for_genesis, Block};
use diem_crypto::hash::ACCUMULATOR_PLACEHOLDER_HASH;
use diem_types::{
ledger_info::{LedgerInfo, LedgerInfoWithSignatures},
validator_verifier::random_validator_verifier,
};
use executor_types::StateComputeResult;
use std::sync::Arc;

use crate::test_utils::{consensus_runtime, timed_block_on};
use consensus_types::{executed_block::ExecutedBlock, quorum_cert::QuorumCert};
use diem_crypto::ed25519::Ed25519Signature;
use diem_types::{account_address::AccountAddress, validator_signer::ValidatorSigner};
use futures::StreamExt;
use rand::Rng;
use std::collections::BTreeMap;

pub fn prepare_ordering_state_computer(
channel_size: usize,
) -> (
Arc<OrderingStateComputer>,
Receiver<(Vec<Block>, LedgerInfoWithSignatures)>,
) {
let (commit_result_tx, commit_result_rx) =
channel::new_test::<(Vec<Block>, LedgerInfoWithSignatures)>(channel_size);
let state_computer = Arc::new(OrderingStateComputer::new(commit_result_tx));

(state_computer, commit_result_rx)
}

pub fn random_empty_block(signer: &ValidatorSigner, qc: QuorumCert) -> Block {
let mut rng = rand::thread_rng();
Block::new_proposal(vec![], rng.gen::<u64>(), rng.gen::<u64>(), qc, signer)
}

#[test]
fn test_ordering_state_computer() {
let num_nodes = 1;
let channel_size = 30;
let mut runtime = consensus_runtime();

let (state_computer, mut commit_result_rx) = prepare_ordering_state_computer(channel_size);

let (signers, _) = random_validator_verifier(num_nodes, None, false);
let signer = &signers[0];
let genesis_qc = certificate_for_genesis();
let block = random_empty_block(signer, genesis_qc);

// test compute
let dummy_state_compute_result = state_computer
.compute(&block, *ACCUMULATOR_PLACEHOLDER_HASH)
.unwrap();
assert_eq!(dummy_state_compute_result, StateComputeResult::new_dummy());

// test commit
let li = LedgerInfo::new(
block.gen_block_info(
dummy_state_compute_result.root_hash(),
dummy_state_compute_result.version(),
dummy_state_compute_result.epoch_state().clone(),
),
*ACCUMULATOR_PLACEHOLDER_HASH,
);

let blocks = vec![Arc::new(ExecutedBlock::new(
block.clone(),
dummy_state_compute_result,
))];

let li_sig =
LedgerInfoWithSignatures::new(li, BTreeMap::<AccountAddress, Ed25519Signature>::new());

// ordering_state_computer should send the same block and finality proof to the channel
timed_block_on(&mut runtime, async move {
state_computer.commit(&blocks, li_sig.clone()).await.ok();

let (ordered_block, finality_proof) = commit_result_rx.next().await.unwrap();
assert_eq!(ordered_block.len(), 1);
assert_eq!(ordered_block[0], block);
assert_eq!(finality_proof, li_sig);
});
}
65 changes: 43 additions & 22 deletions consensus/src/test_utils/mock_state_computer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};
use anyhow::{format_err, Result};
use consensus_types::{block::Block, common::Payload, executed_block::ExecutedBlock};
use diem_crypto::{hash::ACCUMULATOR_PLACEHOLDER_HASH, HashValue};
use diem_crypto::HashValue;
use diem_infallible::Mutex;
use diem_logger::prelude::*;
use diem_types::ledger_info::LedgerInfoWithSignatures;
Expand Down Expand Up @@ -47,17 +47,7 @@ impl StateComputer for MockStateComputer {
self.block_cache
.lock()
.insert(block.id(), block.payload().unwrap_or(&vec![]).clone());
let result = StateComputeResult::new(
*ACCUMULATOR_PLACEHOLDER_HASH,
vec![],
0,
vec![],
0,
None,
vec![],
vec![],
vec![],
);
let result = StateComputeResult::new_dummy();
Ok(result)
}

Expand Down Expand Up @@ -111,16 +101,47 @@ impl StateComputer for EmptyStateComputer {
_block: &Block,
_parent_block_id: HashValue,
) -> Result<StateComputeResult, Error> {
Ok(StateComputeResult::new(
*ACCUMULATOR_PLACEHOLDER_HASH,
vec![],
0,
vec![],
0,
None,
vec![],
vec![],
vec![],
Ok(StateComputeResult::new_dummy())
}

async fn commit(
&self,
_blocks: &[Arc<ExecutedBlock>],
_commit: LedgerInfoWithSignatures,
) -> Result<(), Error> {
Ok(())
}

async fn sync_to(&self, _commit: LedgerInfoWithSignatures) -> Result<(), StateSyncError> {
Ok(())
}
}

pub struct RandomComputeResultStateComputer {
random_compute_result_root_hash: HashValue,
}

impl RandomComputeResultStateComputer {
pub fn new() -> Self {
Self {
random_compute_result_root_hash: HashValue::random(),
}
}

pub fn get_root_hash(&self) -> HashValue {
self.random_compute_result_root_hash
}
}

#[async_trait::async_trait]
impl StateComputer for RandomComputeResultStateComputer {
fn compute(
&self,
_block: &Block,
_parent_block_id: HashValue,
) -> Result<StateComputeResult, Error> {
Ok(StateComputeResult::new_dummy_with_root_hash(
self.random_compute_result_root_hash,
))
}

Expand Down
4 changes: 3 additions & 1 deletion consensus/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ mod mock_txn_manager;
use crate::util::mock_time_service::SimulatedTimeService;
use consensus_types::{block::block_test_utils::gen_test_certificate, common::Payload};
use diem_types::block_info::BlockInfo;
pub use mock_state_computer::{EmptyStateComputer, MockStateComputer};
pub use mock_state_computer::{
EmptyStateComputer, MockStateComputer, RandomComputeResultStateComputer,
};
pub use mock_storage::{EmptyStorage, MockSharedStorage, MockStorage};
pub use mock_txn_manager::MockTransactionManager;

Expand Down
30 changes: 29 additions & 1 deletion execution/executor-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ pub use error::Error;
use anyhow::Result;
use diem_crypto::{
ed25519::Ed25519Signature,
hash::{TransactionAccumulatorHasher, SPARSE_MERKLE_PLACEHOLDER_HASH},
hash::{
TransactionAccumulatorHasher, ACCUMULATOR_PLACEHOLDER_HASH, SPARSE_MERKLE_PLACEHOLDER_HASH,
},
HashValue,
};
use diem_types::{
Expand Down Expand Up @@ -153,6 +155,32 @@ impl StateComputeResult {
signature: None,
}
}

/// generate a new dummy state compute result with a given root hash.
/// this function is used in RandomComputeResultStateComputer to assert that the compute
/// function is really called.
pub fn new_dummy_with_root_hash(root_hash: HashValue) -> Self {
Self {
root_hash,
frozen_subtree_roots: vec![],
num_leaves: 0,
parent_frozen_subtree_roots: vec![],
parent_num_leaves: 0,
epoch_state: None,
compute_status: vec![],
transaction_info_hashes: vec![],
reconfig_events: vec![],
signature: None,
}
}

/// generate a new dummy state compute result with ACCUMULATOR_PLACEHOLDER_HASH as the root hash.
/// this function is used in ordering_state_computer as a dummy state compute result,
/// where the real compute result is generated after ordering_state_computer.commit pushes
/// the blocks and the finality proof to the execution phase.
pub fn new_dummy() -> Self {
StateComputeResult::new_dummy_with_root_hash(*ACCUMULATOR_PLACEHOLDER_HASH)
}
}

impl StateComputeResult {
Expand Down

0 comments on commit 516b1d9

Please sign in to comment.