Skip to content
Permalink
Browse files

Merge pull request #1222 from keroro520/mock-median-time

test: Create a mock block_median_time
  • Loading branch information...
quake committed Jul 12, 2019
2 parents 429e158 + f708ae3 commit 80b51a9851b5d535625c5d144e1accd38c32876b

Some generated files are not rendered by default. Learn more.

@@ -12,6 +12,8 @@ ckb-hash = { path = "../hash" }
ckb-store = { path = "../../store" }
ckb-chain-spec = { path = "../../spec" }
ckb-dao-utils = { path = "../dao/utils" }
ckb-traits = { path = "../../traits" }
lazy_static = "1.3.0"
faketime = "0.2.0"
numext-fixed-uint = { version = "0.1", features = ["support_rand", "support_heapsize", "support_serde"] }
numext-fixed-hash = { version = "0.1", features = ["support_rand", "support_heapsize", "support_serde"] }
@@ -1,7 +1,9 @@
#[macro_use]
mod macros;
mod chain;
mod median_time;
mod mock_store;

pub use chain::{always_success_cell, always_success_cellbase, always_success_consensus};
pub use median_time::MockMedianTime;
pub use mock_store::MockStore;
@@ -0,0 +1,47 @@
use ckb_core::cell::BlockInfo;
use ckb_core::{BlockNumber, EpochNumber};
use ckb_traits::BlockMedianTimeContext;
use numext_fixed_hash::H256;

pub struct MockMedianTime {
timestamps: Vec<u64>,
}

impl BlockMedianTimeContext for MockMedianTime {
fn median_block_count(&self) -> u64 {
11
}

fn timestamp_and_parent(&self, block_hash: &H256) -> (u64, BlockNumber, H256) {
for i in 0..self.timestamps.len() {
if &Self::get_block_hash(i as u64) == block_hash {
if i == 0 {
return (self.timestamps[i], i as u64, H256::zero());
} else {
return (
self.timestamps[i],
i as u64,
Self::get_block_hash(i as u64 - 1),
);
}
}
}
unreachable!()
}
}

impl MockMedianTime {
pub fn new(timestamps: Vec<u64>) -> Self {
Self { timestamps }
}

pub fn get_block_hash(block_number: BlockNumber) -> H256 {
let vec: Vec<u8> = (0..32).map(|_| block_number as u8).collect();
H256::from_slice(vec.as_slice()).unwrap()
}

pub fn get_block_info(block_number: BlockNumber, epoch_number: EpochNumber) -> BlockInfo {
let block_hash = Self::get_block_hash(block_number);
BlockInfo::new(block_number, epoch_number, block_hash)
}
}
@@ -6,26 +6,15 @@ use crate::ALLOWED_FUTURE_BLOCKTIME;
use ckb_core::extras::EpochExt;
use ckb_core::header::{BlockNumber, Header, HeaderBuilder, HEADER_VERSION};
use ckb_pow::PowEngine;
use ckb_traits::BlockMedianTimeContext;
use ckb_test_chain_utils::MockMedianTime;
use faketime::unix_time_as_millis;
use numext_fixed_hash::H256;
use numext_fixed_uint::U256;
use std::sync::Arc;

pub(crate) struct FakeBlockMedianTimeContext;

impl BlockMedianTimeContext for FakeBlockMedianTimeContext {
fn median_block_count(&self) -> u64 {
unimplemented!();
}

fn timestamp_and_parent(&self, _block_hash: &H256) -> (u64, H256) {
unimplemented!();
}

fn block_median_time(&self, _block_number: BlockNumber, _block_hash: &H256) -> u64 {
unix_time_as_millis()
}
fn mock_median_time_context() -> MockMedianTime {
let now = unix_time_as_millis();
let timestamps = (0..100).map(|_| now).collect();
MockMedianTime::new(timestamps)
}

#[test]
@@ -41,7 +30,7 @@ pub fn test_version() {
fn test_timestamp() {
let faketime_file = faketime::millis_tempfile(100_000).expect("create faketime file");
faketime::enable(&faketime_file);
let fake_block_median_time_context = FakeBlockMedianTimeContext;
let fake_block_median_time_context = mock_median_time_context();

let timestamp = unix_time_as_millis() + 1;
let header = HeaderBuilder::default()
@@ -58,7 +47,7 @@ fn test_timestamp() {
fn test_timestamp_too_old() {
let faketime_file = faketime::millis_tempfile(100_000).expect("create faketime file");
faketime::enable(&faketime_file);
let fake_block_median_time_context = FakeBlockMedianTimeContext;
let fake_block_median_time_context = mock_median_time_context();

let min = unix_time_as_millis();
let timestamp = unix_time_as_millis() - 1;
@@ -82,7 +71,7 @@ fn test_timestamp_too_old() {
fn test_timestamp_too_new() {
let faketime_file = faketime::millis_tempfile(100_000).expect("create faketime file");
faketime::enable(&faketime_file);
let fake_block_median_time_context = FakeBlockMedianTimeContext;
let fake_block_median_time_context = mock_median_time_context();

let max = unix_time_as_millis() + ALLOWED_FUTURE_BLOCKTIME;
let timestamp = max + 1;
@@ -8,10 +8,11 @@ use ckb_core::script::{Script, ScriptHashType};
use ckb_core::transaction::{
CellInput, CellOutput, OutPoint, Transaction, TransactionBuilder, TX_VERSION,
};
use ckb_core::{capacity_bytes, BlockNumber, Bytes, Capacity, EpochNumber, Version};
use ckb_core::{capacity_bytes, BlockNumber, Bytes, Capacity, Version};
use ckb_db::MemoryKeyValueDB;
use ckb_resource::CODE_HASH_DAO;
use ckb_store::{ChainKVStore, COLUMNS};
use ckb_test_chain_utils::MockMedianTime;
use ckb_traits::BlockMedianTimeContext;
use numext_fixed_hash::{h256, H256};
use std::sync::Arc;
@@ -117,7 +118,7 @@ pub fn test_inputs_cellbase_maturity() {
resolved_deps: Vec::new(),
resolved_inputs: vec![ResolvedOutPoint::cell_only(
CellMetaBuilder::from_cell_output(output.clone())
.block_info(make_block_info(30, 0))
.block_info(MockMedianTime::get_block_info(30, 0))
.cellbase(true)
.build(),
)],
@@ -149,13 +150,13 @@ pub fn test_deps_cellbase_maturity() {
resolved_deps: vec![
ResolvedOutPoint::cell_only(
CellMetaBuilder::from_cell_output(output.clone())
.block_info(make_block_info(30, 0))
.block_info(MockMedianTime::get_block_info(30, 0))
.cellbase(true)
.build(),
),
ResolvedOutPoint::cell_only(
CellMetaBuilder::from_cell_output(output.clone())
.block_info(make_block_info(40, 0))
.block_info(MockMedianTime::get_block_info(40, 0))
.cellbase(false)
.build(),
),
@@ -241,39 +242,6 @@ pub fn test_duplicate_deps() {
);
}

struct FakeMedianTime {
timestamps: Vec<u64>,
}

impl BlockMedianTimeContext for FakeMedianTime {
fn median_block_count(&self) -> u64 {
11
}

fn timestamp_and_parent(&self, block_hash: &H256) -> (u64, BlockNumber, H256) {
for i in 0..self.timestamps.len() {
if &get_block_hash(i as u64) == block_hash {
if i == 0 {
return (self.timestamps[i], i as u64, H256::zero());
} else {
return (self.timestamps[i], i as u64, get_block_hash(i as u64 - 1));
}
}
}
unreachable!()
}
}

fn get_block_hash(block_number: BlockNumber) -> H256 {
let vec: Vec<u8> = (0..32).map(|_| block_number as u8).collect();
H256::from_slice(vec.as_slice()).unwrap()
}

fn make_block_info(block_number: BlockNumber, epoch_number: EpochNumber) -> BlockInfo {
let block_hash = get_block_hash(block_number);
BlockInfo::new(block_number, epoch_number, block_hash)
}

fn verify_since<'a, M>(
rtx: &'a ResolvedTransaction,
block_median_time_context: &'a M,
@@ -283,7 +251,7 @@ fn verify_since<'a, M>(
where
M: BlockMedianTimeContext,
{
let parent_hash = Arc::new(get_block_hash(block_number - 1));
let parent_hash = Arc::new(MockMedianTime::get_block_hash(block_number - 1));
SinceVerifier::new(
rtx,
block_median_time_context,
@@ -355,11 +323,9 @@ fn create_resolve_tx_with_block_info(
fn test_invalid_since_verify() {
// use remain flags
let tx = create_tx_with_lock(0x0100_0000_0000_0001);
let rtx = create_resolve_tx_with_block_info(&tx, make_block_info(1, 0));
let rtx = create_resolve_tx_with_block_info(&tx, MockMedianTime::get_block_info(1, 0));

let median_time_context = FakeMedianTime {
timestamps: vec![0; 11],
};
let median_time_context = MockMedianTime::new(vec![0; 11]);
assert_eq!(
verify_since(&rtx, &median_time_context, 5, 1).err(),
Some(TransactionError::InvalidSince)
@@ -370,10 +336,8 @@ fn test_invalid_since_verify() {
pub fn test_absolute_block_number_lock() {
// absolute lock until block number 0xa
let tx = create_tx_with_lock(0x0000_0000_0000_000a);
let rtx = create_resolve_tx_with_block_info(&tx, make_block_info(1, 0));
let median_time_context = FakeMedianTime {
timestamps: vec![0; 11],
};
let rtx = create_resolve_tx_with_block_info(&tx, MockMedianTime::get_block_info(1, 0));
let median_time_context = MockMedianTime::new(vec![0; 11]);

assert_eq!(
verify_since(&rtx, &median_time_context, 5, 1).err(),
@@ -387,11 +351,9 @@ pub fn test_absolute_block_number_lock() {
pub fn test_absolute_epoch_number_lock() {
// absolute lock until epoch number 0xa
let tx = create_tx_with_lock(0x2000_0000_0000_000a);
let rtx = create_resolve_tx_with_block_info(&tx, make_block_info(1, 0));
let rtx = create_resolve_tx_with_block_info(&tx, MockMedianTime::get_block_info(1, 0));

let median_time_context = FakeMedianTime {
timestamps: vec![0; 11],
};
let median_time_context = MockMedianTime::new(vec![0; 11]);
assert_eq!(
verify_since(&rtx, &median_time_context, 5, 1).err(),
Some(TransactionError::Immature)
@@ -404,33 +366,28 @@ pub fn test_absolute_epoch_number_lock() {
pub fn test_relative_timestamp_lock() {
// relative lock timestamp lock
let tx = create_tx_with_lock(0xc000_0000_0000_0002);
let rtx = create_resolve_tx_with_block_info(&tx, make_block_info(1, 0));
let rtx = create_resolve_tx_with_block_info(&tx, MockMedianTime::get_block_info(1, 0));

let median_time_context = FakeMedianTime {
timestamps: vec![0; 11],
};
let median_time_context = MockMedianTime::new(vec![0; 11]);
assert_eq!(
verify_since(&rtx, &median_time_context, 4, 1).err(),
Some(TransactionError::Immature)
);

// spent after 1024 seconds
// fake median time: 1124
let median_time_context = FakeMedianTime {
timestamps: vec![0, 100_000, 1_124_000, 2_000_000, 3_000_000],
};
let median_time_context =
MockMedianTime::new(vec![0, 100_000, 1_124_000, 2_000_000, 3_000_000]);
assert!(verify_since(&rtx, &median_time_context, 4, 1).is_ok());
}

#[test]
pub fn test_relative_epoch() {
// next epoch
let tx = create_tx_with_lock(0xa000_0000_0000_0001);
let rtx = create_resolve_tx_with_block_info(&tx, make_block_info(1, 1));
let rtx = create_resolve_tx_with_block_info(&tx, MockMedianTime::get_block_info(1, 1));

let median_time_context = FakeMedianTime {
timestamps: vec![0; 11],
};
let median_time_context = MockMedianTime::new(vec![0; 11]);

assert_eq!(
verify_since(&rtx, &median_time_context, 4, 1).err(),
@@ -453,24 +410,20 @@ pub fn test_since_both() {
])
.build();

let rtx = create_resolve_tx_with_block_info(&transaction, make_block_info(1, 0));
let rtx = create_resolve_tx_with_block_info(&transaction, MockMedianTime::get_block_info(1, 0));
// spent after 1024 seconds and 4 blocks (less than 10 blocks)
// fake median time: 1124
let median_time_context = FakeMedianTime {
timestamps: vec![0, 100_000, 1_124_000, 2_000_000, 3_000_000],
};
let median_time_context =
MockMedianTime::new(vec![0, 100_000, 1_124_000, 2_000_000, 3_000_000]);

assert_eq!(
verify_since(&rtx, &median_time_context, 4, 1).err(),
Some(TransactionError::Immature)
);
// spent after 1024 seconds and 10 blocks
// fake median time: 1124
let median_time_context = FakeMedianTime {
timestamps: vec![
0, 1, 2, 3, 4, 100_000, 1_124_000, 2_000_000, 3_000_000, 4_000_000, 5_000_000,
6_000_000,
],
};
let median_time_context = MockMedianTime::new(vec![
0, 1, 2, 3, 4, 100_000, 1_124_000, 2_000_000, 3_000_000, 4_000_000, 5_000_000, 6_000_000,
]);
assert!(verify_since(&rtx, &median_time_context, 10, 1).is_ok());
}

0 comments on commit 80b51a9

Please sign in to comment.
You can’t perform that action at this time.