Skip to content
This repository has been archived by the owner on Nov 9, 2022. It is now read-only.

Commit

Permalink
test: add testcases for finality
Browse files Browse the repository at this point in the history
  • Loading branch information
keroro520 committed Sep 29, 2022
1 parent 7f3674c commit e61136e
Show file tree
Hide file tree
Showing 20 changed files with 1,049 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use super::utils::{build_context, ROLLUP_STATE_LAST_FINALIZED_BLOCK_NUMBER};
use crate::script_tests::utils::init_env_log;
use crate::script_tests::utils::layer1::{build_simple_tx_with_out_point, random_out_point};
use ckb_error::assert_error_eq;
use ckb_script::ScriptError;
use ckb_types::{
core::{Cycle, ScriptHashType},
packed::{CellDep, CellInput, CellOutput, Script},
prelude::*,
};
use gw_types::packed::CustodianLockArgs;

// Transaction structure:
//
// ```
// CellDeps:
// rollup_config_cell:
// rollup_code_cell:
// custodian_code_cell:
//
// Inputs:
// rollup_state_cell:
// custodian_state_cell:
//
// Outputs:
// <user defined>:
// ```

// deposit_block_number <= rollup_state_cell.last_finalized_block_number
#[test]
fn test_success_to_unlock_custodian_via_finalize_based_on_block_number() {
init_env_log();
let (_, result) = unlock_custodian_via_finalize_based_on_block_number(
ROLLUP_STATE_LAST_FINALIZED_BLOCK_NUMBER,
);
result.expect("success");
}

// deposit_block_number > rollup_state_cell.last_finalized_block_number
#[test]
fn test_fail_to_unlock_custodian_via_finalize_based_on_block_number() {
init_env_log();
let (custodian_state_cell, result) = unlock_custodian_via_finalize_based_on_block_number(
ROLLUP_STATE_LAST_FINALIZED_BLOCK_NUMBER + 1,
);
let custodian_code_type_hash: ckb_types::H256 =
custodian_state_cell.lock().code_hash().unpack();
let expected_err = ScriptError::ValidationFailure(
format!("by-type-hash/{}", custodian_code_type_hash),
1, // Error::IndexOutOfBound
)
.input_lock_script(0);
assert_error_eq!(expected_err, result.unwrap_err());
}

fn unlock_custodian_via_finalize_based_on_block_number(
deposit_block_number: u64,
) -> (CellOutput, Result<Cycle, ckb_error::Error>) {
let (
mut ctx,
rollup_state_out_point,
rollup_state_type_script,
custodian_code_out_point,
custodian_code_type_script,
) = build_context();
let rollup_state_type_hash = rollup_state_type_script.calc_script_hash();
let custodian_code_type_hash = custodian_code_type_script.calc_script_hash();

// Build a finalized custodian_state_cell
let custodian_state_out_point = random_out_point();
let custodian_state_cell = CellOutput::new_builder()
.lock(
Script::new_builder()
.code_hash(custodian_code_type_hash.clone())
.hash_type(ScriptHashType::Type.into())
.args({
let custodian_lock_args = CustodianLockArgs::new_builder()
.deposit_block_number(gw_types::prelude::Pack::pack(&deposit_block_number))
.build();
let mut args = Vec::new();
args.extend_from_slice(&rollup_state_type_hash.as_slice());
args.extend_from_slice(&custodian_lock_args.as_slice());
args.pack()
})
.build(),
)
.build();

// Build transaction
let tx = build_simple_tx_with_out_point(
&mut ctx.inner,
(custodian_state_cell.clone(), Default::default()),
custodian_state_out_point,
(CellOutput::new_builder().build(), Default::default()),
)
.as_advanced_builder()
.input(CellInput::new(rollup_state_out_point, 0))
.cell_dep(
CellDep::new_builder()
.out_point(custodian_code_out_point)
.build(),
)
.cell_dep(ctx.rollup_config_dep.clone())
.cell_dep(ctx.always_success_dep.clone())
.build();
let result = ctx.verify_tx(tx);
(custodian_state_cell, result)
}
132 changes: 132 additions & 0 deletions tests/src/script_tests/custodian_lock/finalize_based_on_timestamp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use super::utils::{
build_context, ROLLUP_CONFIG_FINALITY_DURATION_MS, ROLLUP_STATE_CELL_TIMESTAMP,
};
use crate::script_tests::utils::init_env_log;
use crate::script_tests::utils::layer1::{build_simple_tx_with_out_point, random_out_point};
use ckb_error::assert_error_eq;
use ckb_script::ScriptError;
use ckb_types::{
core::{Cycle, HeaderBuilder, ScriptHashType, TransactionInfo},
packed::{CellDep, CellInput, CellOutput, Script},
prelude::*,
};
use gw_types::packed::CustodianLockArgs;

// Transaction structure:
//
// ```
// HeaderDeps:
// <L1 header that includes the rollup_state_cell>
//
// CellDeps:
// rollup_config_cell:
// rollup_code_cell:
// custodian_code_cell:
//
// Inputs:
// rollup_state_cell:
// custodian_state_cell:
//
// Outputs:
// <user defined>:
// ```

// deposit_block_timestamp <= rollup_state_cell's L1 timestamp
#[test]
fn test_success_to_unlock_custodian_via_finalize_based_on_timestamp() {
init_env_log();
let (_, result) = unlock_custodian_via_finalize_based_on_timestamp(
ROLLUP_STATE_CELL_TIMESTAMP - ROLLUP_CONFIG_FINALITY_DURATION_MS,
);
result.expect("success");
}

// deposit_block_timestamp > rollup_state_cell's header timestamp
#[test]
fn test_fail_to_unlock_custodian_via_finalize_based_on_timestamp() {
init_env_log();
let (custodian_state_cell, result) = unlock_custodian_via_finalize_based_on_timestamp(
ROLLUP_STATE_CELL_TIMESTAMP - ROLLUP_CONFIG_FINALITY_DURATION_MS + 1,
);
let custodian_code_type_hash: ckb_types::H256 =
custodian_state_cell.lock().code_hash().unpack();
let expected_err = ScriptError::ValidationFailure(
format!("by-type-hash/{}", custodian_code_type_hash),
1, // Error::IndexOutOfBound
)
.input_lock_script(0);
assert_error_eq!(expected_err, result.unwrap_err());
}

fn unlock_custodian_via_finalize_based_on_timestamp(
deposit_block_timestamp: u64,
) -> (CellOutput, Result<Cycle, ckb_error::Error>) {
let (
mut ctx,
rollup_state_out_point,
rollup_state_type_script,
custodian_code_out_point,
custodian_code_type_script,
) = build_context();
let rollup_state_type_hash = rollup_state_type_script.calc_script_hash();
let custodian_code_type_hash = custodian_code_type_script.calc_script_hash();

// Build rollup_state_cell's header_dep
let rollup_state_header = HeaderBuilder::default()
.timestamp(ROLLUP_STATE_CELL_TIMESTAMP.pack())
.build();
let rollup_state_tx_info = TransactionInfo {
block_hash: rollup_state_header.hash(),
block_number: rollup_state_header.number(),
block_epoch: rollup_state_header.epoch(),
index: 1,
};
ctx.inner
.transaction_infos
.insert(rollup_state_out_point.clone(), rollup_state_tx_info);
ctx.inner
.headers
.insert(rollup_state_header.hash(), rollup_state_header.clone());

// Build a finalized custodian_state_cell
let custodian_state_out_point = random_out_point();
let custodian_state_cell = CellOutput::new_builder()
.lock(
Script::new_builder()
.code_hash(custodian_code_type_hash.clone())
.hash_type(ScriptHashType::Type.into())
.args({
let timepoint = deposit_block_timestamp | (1 << 63);
let custodian_lock_args = CustodianLockArgs::new_builder()
.deposit_block_number(gw_types::prelude::Pack::pack(&timepoint))
.build();
let mut args = Vec::new();
args.extend_from_slice(&rollup_state_type_hash.as_slice());
args.extend_from_slice(&custodian_lock_args.as_slice());
args.pack()
})
.build(),
)
.build();

// Build transaction
let tx = build_simple_tx_with_out_point(
&mut ctx.inner,
(custodian_state_cell.clone(), Default::default()),
custodian_state_out_point,
(CellOutput::new_builder().build(), Default::default()),
)
.as_advanced_builder()
.input(CellInput::new(rollup_state_out_point, 0))
.cell_dep(
CellDep::new_builder()
.out_point(custodian_code_out_point)
.build(),
)
.cell_dep(ctx.rollup_config_dep.clone())
.cell_dep(ctx.always_success_dep.clone())
.header_dep(rollup_state_header.hash())
.build();

(custodian_state_cell, ctx.verify_tx(tx))
}
3 changes: 3 additions & 0 deletions tests/src/script_tests/custodian_lock/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod finalize_based_on_block_number;
pub mod finalize_based_on_timestamp;
pub mod utils;
71 changes: 71 additions & 0 deletions tests/src/script_tests/custodian_lock/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::script_tests::utils::rollup::{random_always_success_script, CellContext};
use crate::testing_tool::programs::CUSTODIAN_LOCK_PROGRAM;
use ckb_types::{
packed::{CellOutput, OutPoint, Script},
prelude::*,
};
use gw_types::packed::{GlobalState, RollupConfig};

const BLOCK_INTERVAL_IN_MILLISECONDS: u64 = 36000;
pub(super) const ROLLUP_CONFIG_FINALITY_BLOCKS: u64 = 1;
pub(super) const ROLLUP_CONFIG_FINALITY_DURATION_MS: u64 =
ROLLUP_CONFIG_FINALITY_BLOCKS * BLOCK_INTERVAL_IN_MILLISECONDS;
pub(super) const ROLLUP_STATE_LAST_FINALIZED_BLOCK_NUMBER: u64 = 100;
pub(super) const ROLLUP_STATE_CELL_TIMESTAMP: u64 = 1555204979310;

// Build common-used cells for testing custodian-lock:
// - rollup_config_cell, finality_blocks = ROLLUP_CONFIG_FINALITY_BLOCKS
// - rollup_code_cell, is ALWAYS_SUCCESS_PROGRAM
// - rollup_state_cell, last_finalized_block_number = ROLLUP_STATE_LAST_FINALIZED_BLOCK_NUMBER
// - custodian_code_cell, is CUSTODIAN_LOCK_PROGRAM
//
// Return (ctx, rollup_state_out_point, rollup_state_type_script, custodian_code_out_point, custodian_code_type_script);
pub(super) fn build_context() -> (CellContext, OutPoint, Script, OutPoint, Script) {
let rollup_config = RollupConfig::new_builder()
.finality_blocks(gw_types::prelude::Pack::pack(
&ROLLUP_CONFIG_FINALITY_BLOCKS,
))
.build();
let mut ctx = CellContext::new(&rollup_config, Default::default());

// Build a always-success rollup_state_cell, because we are testing
// custodian-lock only
let rollup_state_data = GlobalState::new_builder()
.last_finalized_block_number(gw_types::prelude::Pack::pack(
&ROLLUP_STATE_LAST_FINALIZED_BLOCK_NUMBER,
))
.rollup_config_hash({
let rollup_config_data_hash = CellOutput::calc_data_hash(&rollup_config.as_bytes());
gw_types::packed::Byte32::new_unchecked(rollup_config_data_hash.as_bytes())
})
.build();
let rollup_state_cell = CellOutput::new_builder()
.lock(random_always_success_script())
.type_(Some(random_always_success_script()).pack())
.build();
let rollup_state_type_script = rollup_state_cell
.type_()
.to_opt()
.expect("should be always-success");
let rollup_state_out_point = ctx.insert_cell(rollup_state_cell, rollup_state_data.as_bytes());

// Build costodian_code_cell
let custodian_code_data = CUSTODIAN_LOCK_PROGRAM.clone();
let custodian_code_cell = CellOutput::new_builder()
.lock(random_always_success_script())
.type_(Some(random_always_success_script()).pack())
.build();
let custodian_code_type_script = custodian_code_cell
.type_()
.to_opt()
.expect("should be always-success");
let custodian_code_out_point = ctx.insert_cell(custodian_code_cell, custodian_code_data);

return (
ctx,
rollup_state_out_point,
rollup_state_type_script,
custodian_code_out_point,
custodian_code_type_script,
);
}
2 changes: 2 additions & 0 deletions tests/src/script_tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
mod account_lock_scripts;
mod custodian_lock;
mod l2_scripts;
mod l2_scripts_validator;
mod stake_lock;
mod state_validator;
pub mod utils;
mod withdrawal;
Loading

0 comments on commit e61136e

Please sign in to comment.