Skip to content

Commit

Permalink
test: add cases for unlock_to_owner
Browse files Browse the repository at this point in the history
  • Loading branch information
keroro520 committed Dec 12, 2022
1 parent 3719abe commit 4d92e19
Showing 1 changed file with 243 additions and 7 deletions.
250 changes: 243 additions & 7 deletions crates/block-producer/src/withdrawal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ pub fn revert(
}))
}

#[derive(Debug)]
pub struct UnlockedWithdrawals {
pub deps: Vec<CellDep>,
pub inputs: Vec<InputCellInfo>,
Expand Down Expand Up @@ -322,7 +323,7 @@ pub fn unlock_to_owner(
}

fn is_v1_withdrawal_cell(withdrawal_cell: &CellInfo) -> bool {
let withdrawal_lock_args = parse_lock_args(&withdrawal_cell.output.lock().args().as_bytes())
let withdrawal_lock_args = parse_lock_args(&withdrawal_cell.output.lock().args().raw_data())
.expect("parse withdrawal lock args");
match Timepoint::from_full_value(
withdrawal_lock_args
Expand All @@ -340,21 +341,22 @@ mod test {
use std::collections::HashMap;
use std::iter::FromIterator;

use crate::utils::global_state_last_finalized_timepoint_to_since;
use crate::withdrawal::generate;
use gw_common::{h256_ext::H256Ext, H256};
use gw_config::ContractsCellDep;
use gw_config::{ContractsCellDep, ForkConfig};
use gw_types::core::{DepType, ScriptHashType, Timepoint};
use gw_types::offchain::{
CellInfo, CollectedCustodianCells, CompatibleFinalizedTimepoint, InputCellInfo,
};
use gw_types::packed::{
CellDep, CellInput, CellOutput, GlobalState, L2Block, OutPoint, RawL2Block,
RawWithdrawalRequest, RollupConfig, Script, UnlockWithdrawalViaFinalize,
BlockMerkleState, CellDep, CellInput, CellOutput, GlobalState, L2Block, OutPoint,
RawL2Block, RawWithdrawalRequest, RollupConfig, Script, UnlockWithdrawalViaFinalize,
UnlockWithdrawalWitness, UnlockWithdrawalWitnessUnion, WithdrawalLockArgs,
WithdrawalRequest, WithdrawalRequestExtra, WitnessArgs,
};
use gw_types::prelude::{Builder, Entity, Pack, PackVec, Unpack};
use gw_utils::RollupContext;
use gw_utils::{global_state_finalized_timepoint, RollupContext};

use super::unlock_to_owner;

Expand Down Expand Up @@ -564,7 +566,7 @@ mod test {
}
};

let withdrawal_input_since = 0;
let global_state_since = global_state_last_finalized_timepoint_to_since(&global_state);
let unlocked = unlock_to_owner(
rollup_cell.clone(),
&rollup_context.rollup_config,
Expand All @@ -573,7 +575,7 @@ mod test {
withdrawal_without_owner_lock,
withdrawal_with_owner_lock.clone(),
],
withdrawal_input_since,
global_state_since,
)
.expect("unlock")
.expect("some unlocked");
Expand Down Expand Up @@ -649,4 +651,238 @@ mod test {
CellDep::from(contracts_dep.l1_sudt_type).as_slice(),
);
}

#[test]
fn test_unlock_to_owner_finality() {
const FINALITY_BLOCKS: u64 = 10;
const UPGRADE_GLOBAL_STATE_VERSION_TO_V2: u64 = 100;
const BLOCK_TIMESTAMP: u64 = 1670000000000;

let cases = vec![
CaseParam {
// v1 withdrawal, v1 global state, not finalized
id: 0,
finality_blocks: FINALITY_BLOCKS,
upgrade_global_state_version_to_v2: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
block_timestamp: BLOCK_TIMESTAMP,
block_number: UPGRADE_GLOBAL_STATE_VERSION_TO_V2 - 1,
withdrawal_block_timepoint: Timepoint::BlockNumber(
UPGRADE_GLOBAL_STATE_VERSION_TO_V2 - FINALITY_BLOCKS,
),
expected_result: Err(()),
},
CaseParam {
// v1 withdrawal, v1 global state, finalized
id: 1,
finality_blocks: FINALITY_BLOCKS,
upgrade_global_state_version_to_v2: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
block_timestamp: BLOCK_TIMESTAMP,
block_number: UPGRADE_GLOBAL_STATE_VERSION_TO_V2 - 1,
withdrawal_block_timepoint: Timepoint::BlockNumber(
UPGRADE_GLOBAL_STATE_VERSION_TO_V2 - 1 - FINALITY_BLOCKS,
),
expected_result: Ok(()),
},
CaseParam {
// v1 withdrawal, v2 global state, not finalized
id: 2,
finality_blocks: FINALITY_BLOCKS,
upgrade_global_state_version_to_v2: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
block_timestamp: BLOCK_TIMESTAMP,
block_number: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
withdrawal_block_timepoint: Timepoint::BlockNumber(
UPGRADE_GLOBAL_STATE_VERSION_TO_V2 + 1 - FINALITY_BLOCKS,
),
expected_result: Err(()),
},
CaseParam {
// v1 withdrawal, v2 global state, finalized
id: 3,
finality_blocks: FINALITY_BLOCKS,
upgrade_global_state_version_to_v2: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
block_timestamp: BLOCK_TIMESTAMP,
block_number: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
withdrawal_block_timepoint: Timepoint::BlockNumber(
UPGRADE_GLOBAL_STATE_VERSION_TO_V2 - FINALITY_BLOCKS,
),
expected_result: Ok(()),
},
CaseParam {
// v2 withdrawal, v2 global state, not finalized
id: 4,
finality_blocks: FINALITY_BLOCKS,
upgrade_global_state_version_to_v2: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
block_timestamp: BLOCK_TIMESTAMP,
block_number: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
withdrawal_block_timepoint: Timepoint::Timestamp(BLOCK_TIMESTAMP + 1),
expected_result: Err(()),
},
CaseParam {
// v2 withdrawal, v2 global state, finalized
id: 5,
finality_blocks: FINALITY_BLOCKS,
upgrade_global_state_version_to_v2: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
block_timestamp: BLOCK_TIMESTAMP,
block_number: UPGRADE_GLOBAL_STATE_VERSION_TO_V2,
withdrawal_block_timepoint: Timepoint::Timestamp(BLOCK_TIMESTAMP),
expected_result: Ok(()),
},
];
for case in cases {
run_case(case);
}

#[derive(Debug)]
struct CaseParam {
#[allow(dead_code)]
id: usize,
finality_blocks: u64,
upgrade_global_state_version_to_v2: u64,
block_timestamp: u64,
block_number: u64,
withdrawal_block_timepoint: Timepoint,
expected_result: Result<(), ()>,
}

fn run_case(case_param: CaseParam) {
println!("case: {:?}", case_param);
let CaseParam {
id: _,
finality_blocks,
upgrade_global_state_version_to_v2,
block_number,
block_timestamp,
withdrawal_block_timepoint,
expected_result,
} = case_param;

let sudt_script = Script::new_builder()
.code_hash(H256::from_u32(3).pack())
.hash_type(ScriptHashType::Type.into())
.args(vec![4u8; 32].pack())
.build();
let rollup_config = RollupConfig::new_builder()
.l1_sudt_script_type_hash(sudt_script.code_hash())
.finality_blocks(finality_blocks.pack())
.build();
let fork_config = ForkConfig {
upgrade_global_state_version_to_v2: Some(upgrade_global_state_version_to_v2),
..Default::default()
};
let global_state = GlobalState::new_builder()
.rollup_config_hash(rollup_config.hash().pack())
.last_finalized_timepoint(
global_state_finalized_timepoint(
&rollup_config,
&fork_config,
block_number,
block_timestamp,
)
.full_value()
.pack(),
)
.block(
BlockMerkleState::new_builder()
.count((block_number + 1).pack())
.build(),
)
.build();
let rollup_state_script = Script::new_builder()
.code_hash(H256::from_u32(1).pack())
.build();
let rollup_state_cell = CellInfo {
data: global_state.as_bytes(),
out_point: OutPoint::new_builder()
.tx_hash(H256::from_u32(2).pack())
.build(),
output: CellOutput::new_builder()
.type_(Some(rollup_state_script.clone()).pack())
.build(),
};
let rollup_context = RollupContext {
rollup_script_hash: rollup_state_script.hash().into(),
rollup_config: rollup_config.clone(),
fork_config,
};
let contracts_dep = {
ContractsCellDep {
withdrawal_cell_lock: CellDep::new_builder()
.out_point(
OutPoint::new_builder()
.tx_hash(H256::from_u32(6).pack())
.build(),
)
.build()
.into(),
l1_sudt_type: CellDep::new_builder()
.out_point(
OutPoint::new_builder()
.tx_hash(H256::from_u32(7).pack())
.build(),
)
.build()
.into(),
..Default::default()
}
};

// Build owner's lock script and withdrawal cell
let owner_lock_script = Script::new_builder()
.code_hash(H256::from_u32(8).pack())
.hash_type(ScriptHashType::Type.into())
.args(vec![9u8; 32].pack())
.build();
let withdrawal_lock_args = WithdrawalLockArgs::new_builder()
.owner_lock_hash(owner_lock_script.hash().pack())
.withdrawal_block_timepoint(withdrawal_block_timepoint.full_value().pack())
.build();
let withdrawal_cell = CellInfo {
output: CellOutput::new_builder()
.type_(Some(sudt_script).pack())
.lock(
Script::new_builder()
.code_hash(rollup_config.withdrawal_script_type_hash())
.hash_type(ScriptHashType::Type.into())
.args({
let mut args = rollup_state_script.hash().to_vec();
args.extend_from_slice(&withdrawal_lock_args.as_bytes());
args.extend_from_slice(
&(owner_lock_script.as_bytes().len() as u32).to_be_bytes(),
);
args.extend_from_slice(&owner_lock_script.as_bytes());
args.pack()
})
.build(),
)
.build(),
data: 100u128.pack().as_bytes(),
..Default::default()
};

let unlocked = unlock_to_owner(
rollup_state_cell,
&rollup_context.rollup_config,
&contracts_dep,
vec![withdrawal_cell],
global_state_last_finalized_timepoint_to_since(&global_state),
)
.expect("unlock");

match expected_result {
Ok(()) => {
assert!(unlocked.is_some());
let unlocked = unlocked.unwrap();
for input in unlocked.inputs.iter() {
assert_eq!(
input.input.since().unpack(),
global_state_last_finalized_timepoint_to_since(&global_state),
);
}
}
Err(()) => {
assert!(unlocked.is_none(), "actual unlocked: {:?}", unlocked);
}
}
}
}
}

0 comments on commit 4d92e19

Please sign in to comment.