Skip to content

Commit

Permalink
test(chain): add unit test to ensure internal_process_block works as …
Browse files Browse the repository at this point in the history
…expect when switch is Switch::DISABLE_ALL
  • Loading branch information
eval-exec committed Mar 29, 2023
1 parent 263ed5c commit 64314d3
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions chain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ ckb-launcher = { path = "../util/launcher", version = "= 0.109.0-pre" }
lazy_static = "1.4"
tempfile.workspace = true
ckb-systemtime = { path = "../util/systemtime", version = "= 0.109.0-pre" ,features = ["enable_faketime"]}
rand = "0.7"

[features]
default = []
Expand Down
201 changes: 194 additions & 7 deletions chain/src/tests/basic.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
use crate::chain::ChainController;
use crate::tests::util::{
create_always_success_tx, create_cellbase, create_multi_outputs_transaction,
create_transaction, create_transaction_with_out_point, dao_data, start_chain, MockChain,
MockStore,
calculate_reward, create_always_success_tx, create_cellbase, create_multi_outputs_transaction,
create_transaction, create_transaction_with_input,
create_transaction_with_input_and_output_capacity, dao_data, start_chain, MockChain, MockStore,
};
use ckb_chain_spec::consensus::{Consensus, ConsensusBuilder};
use ckb_dao_utils::genesis_dao_data;
use ckb_error::assert_error_eq;
use ckb_shared::shared::Shared;
use ckb_store::ChainStore;
use ckb_test_chain_utils::always_success_cell;
use ckb_types::core::error::OutPointError;
use ckb_types::prelude::*;
use ckb_types::{
bytes::Bytes,
core::{
capacity_bytes,
cell::{CellMeta, CellProvider, CellStatus},
BlockBuilder, BlockView, Capacity, HeaderView, TransactionBuilder, TransactionInfo,
BlockBuilder, BlockView, Capacity, EpochNumberWithFraction, HeaderView, TransactionBuilder,
TransactionInfo,
},
packed::{CellInput, CellOutputBuilder, OutPoint, Script},
utilities::{compact_to_difficulty, difficulty_to_compact},
utilities::{compact_to_difficulty, difficulty_to_compact, DIFF_TWO},
U256,
};
use ckb_verification_traits::Switch;
use rand::random;
use std::sync::Arc;

#[test]
Expand Down Expand Up @@ -296,7 +299,7 @@ fn test_invalid_out_point_index_in_same_block() {
let tx1_hash = tx1.hash();
let tx2 = create_transaction(&tx1_hash, 2);
// create an invalid OutPoint index
let tx3 = create_transaction_with_out_point(OutPoint::new(tx1_hash.clone(), 1), 3);
let tx3 = create_transaction_with_input(OutPoint::new(tx1_hash.clone(), 1), 3);
let txs = vec![tx1, tx2, tx3];
// proposal txs
chain.gen_block_with_proposal_txs(txs.clone(), &mock_store);
Expand Down Expand Up @@ -330,7 +333,7 @@ fn test_invalid_out_point_index_in_different_blocks() {
let tx1_hash = tx1.hash();
let tx2 = create_transaction(&tx1_hash, 2);
// create an invalid OutPoint index
let tx3 = create_transaction_with_out_point(OutPoint::new(tx1_hash.clone(), 1), 3);
let tx3 = create_transaction_with_input(OutPoint::new(tx1_hash.clone(), 1), 3);
// proposal txs
chain.gen_block_with_proposal_txs(vec![tx1.clone(), tx2.clone(), tx3.clone()], &mock_store);
// empty N+1 block
Expand Down Expand Up @@ -870,3 +873,187 @@ fn test_next_epoch_ext() {
);
}
}

#[test]
fn test_sync_based_on_disable_all_chain() {
const GENESIS_CAPACITY: u64 = 10000000000;
let (_, _, always_success_script) = always_success_cell();
let always_success_tx = create_always_success_tx();
let genesis_tx = TransactionBuilder::default()
.input(CellInput::new(OutPoint::null(), 0))
.output(
CellOutputBuilder::default()
.capacity(GENESIS_CAPACITY.pack())
.lock(always_success_script.clone())
.build(),
)
.output_data(Bytes::new().pack())
.build();

let dao = genesis_dao_data(vec![&always_success_tx, &genesis_tx]).unwrap();

let genesis_block = BlockBuilder::default()
.transaction(always_success_tx)
.transaction(genesis_tx.clone())
.compact_target(DIFF_TWO.pack())
.dao(dao)
.build();

let consensus = ConsensusBuilder::default()
.cellbase_maturity(EpochNumberWithFraction::new(0, 0, 1))
.genesis_block(genesis_block)
.build();

let (chain_controller, shared, parent) = start_chain(Some(consensus));

let mock_store = MockStore::new(&parent, shared.store());
let mut chain = MockChain::new(parent, shared.consensus());

let mut parent_tx = genesis_tx;

let mut txs = Vec::with_capacity(20);

/*
tx_fee for block 1 is 100;
tx_fee for block 2 is 200;
tx_fee for block 3 is 300;
...
tx_fee for block 20 is 2000;
*/
let fee_fn = |block_number: u64| -> Capacity { Capacity::shannons(100_u64 * block_number) };

for block_number in 1..=20 {
let parent_cap: Capacity = parent_tx.output(0).unwrap().as_reader().capacity().unpack();
let tx_fee = fee_fn(block_number);
let capacity = parent_cap.safe_sub(tx_fee).unwrap();
let tx = create_transaction_with_input_and_output_capacity(
OutPoint::new(parent_tx.hash().clone(), 0),
capacity.as_u64(),
random::<u8>(),
);
println!(
"created a transaction: {} in block: {}, tx_fee: {}",
tx.hash(),
block_number,
tx_fee
);
parent_tx = tx.clone();
txs.push(tx);
}

/*
In block 1, we propose txs[0]
In block 2, we propose txs[1]
In block 3, we propose txs[2], and commit txs[0]
In block 4, we propose txs[3], and commit txs[1]
In block 5, we propose txs[4], and commit txs[2]
In block 6, we propose txs[5], and commit txs[3]
In block 7, we propose txs[6], and commit txs[4]
...
In block 19, we propose txs[18], and commit txs[16]
In block 20, we propose txs[19], and commit txs[17]
In block 21, we don't propose any tx, and commit txs[18]
In block 22, we don't propose any tx, and commit txs[19]
*/
for block_number in 1..=22 {
assert_eq!(block_number, chain.tip_header().number() + 1);

let mut proposals_txs = Vec::new();
let mut commits_txs = Vec::new();
match block_number {
1..=2 => {
proposals_txs.push(txs[block_number as usize - 1].clone());
println!(
"In block {}, propose txs[{}]",
block_number,
block_number - 1
);
}
3..=20 => {
proposals_txs.push(txs[block_number as usize - 1].clone());
commits_txs.push(txs[block_number as usize - 1 - 2].clone());
println!(
"In block {}, propose txs[{}], and commit txs[{}]",
block_number,
block_number - 1,
block_number - 1 - 2
);
}
21..=22 => {
commits_txs.push(txs[block_number as usize - 1 - 2].clone());
println!(
"In block {}, commit txs[{}]",
block_number,
block_number - 1 - 2
);
}
_ => {
unreachable!("block_number should be in [1, 22]");
}
}

let reward: Capacity = {
let block_reward =
calculate_reward(&mock_store, shared.consensus(), &chain.tip_header());

let mut proposal_reward: Capacity = Capacity::zero();
if block_number >= 13 {
let tx_fee: Capacity = fee_fn(block_number - 11);
proposal_reward = tx_fee
.safe_mul_ratio(shared.consensus().proposer_reward_ratio())
.unwrap();
}

let mut commit_reward: Capacity = Capacity::zero();
if block_number >= 14 {
let tx_fee: Capacity = fee_fn(block_number - 13);

commit_reward = tx_fee
.safe_sub(
tx_fee
.safe_mul_ratio(shared.consensus().proposer_reward_ratio())
.unwrap(),
)
.unwrap();
}

let total_reward = block_reward
.safe_add(proposal_reward)
.unwrap()
.safe_add(commit_reward)
.unwrap();
println!(
"In block {}, calculate reward: block_reward + proposal + commit = total: {} + {} + {} = {}",
block_number, block_reward, proposal_reward, commit_reward, total_reward
);
total_reward
};

chain.gen_block_with_proposal_txs_and_commit_txs(
proposals_txs,
commits_txs,
&mock_store,
reward,
);
let block = chain.blocks().last().unwrap();

let mut switch = Switch::DISABLE_ALL;
if block_number >= 15 {
switch = Switch::NONE;
}
println!(
"\nChainService: processing block {}: with switch = {}",
block.number(),
{
match switch {
Switch::NONE => "Switch::NONE",
Switch::DISABLE_ALL => "Switch::DISABLE_ALL",
_ => unreachable!(),
}
}
);
chain_controller
.internal_process_block(Arc::new(block.clone()), switch)
.expect("process block ok");
}
}
34 changes: 34 additions & 0 deletions chain/src/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,40 @@ impl<'a> MockChain<'a> {
self.commit_block(store, new_block)
}

pub fn gen_block_with_proposal_txs_and_commit_txs(
&mut self,
proposals: Vec<TransactionView>,
commits: Vec<TransactionView>,
store: &MockStore,
reward: Capacity,
) {
let parent = self.tip_header();
let cellbase = create_cellbase_with_reward(self.consensus, &parent, reward);

let mut txs_to_resolve = vec![cellbase.clone()];
txs_to_resolve.extend_from_slice(&commits);
let dao = dao_data(self.consensus, &parent, &txs_to_resolve, store, false);

let epoch = self
.consensus
.next_epoch_ext(&parent, &store.store().borrow_as_data_loader())
.unwrap()
.epoch();

let new_block = BlockBuilder::default()
.parent_hash(parent.hash())
.number((parent.number() + 1).pack())
.compact_target(epoch.compact_target().pack())
.epoch(epoch.number_with_fraction(parent.number() + 1).pack())
.dao(dao)
.transaction(cellbase)
.transactions(commits)
.proposals(proposals.iter().map(TransactionView::proposal_short_id))
.build();

self.commit_block(store, new_block)
}

pub fn tip_header(&self) -> HeaderView {
self.blocks
.last()
Expand Down

0 comments on commit 64314d3

Please sign in to comment.