From c4581c640e91b9c1cc895bc8291ef1154f6039c8 Mon Sep 17 00:00:00 2001 From: Link Date: Tue, 3 Aug 2021 11:46:53 +0800 Subject: [PATCH 1/4] feat: support super lock to mint accounts --- Cargo.lock | 1 + contracts/pre-account-cell-type/Cargo.toml | 1 + contracts/pre-account-cell-type/src/entry.rs | 90 +++++++++++++++----- contracts/proposal-cell-type/src/entry.rs | 6 -- libs/das-core/src/error.rs | 2 +- libs/das-core/src/util.rs | 54 ------------ 6 files changed, 74 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94457676..44aa20b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2128,6 +2128,7 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" name = "pre-account-cell-type" version = "1.0.0" dependencies = [ + "chrono", "ckb-std", "das-core", "das-types", diff --git a/contracts/pre-account-cell-type/Cargo.toml b/contracts/pre-account-cell-type/Cargo.toml index 5ee48d8d..40f903f5 100644 --- a/contracts/pre-account-cell-type/Cargo.toml +++ b/contracts/pre-account-cell-type/Cargo.toml @@ -14,3 +14,4 @@ ckb-std = "0.7.1" hex = { default-features = false, version = "0.4.2"} das-core = { path = "../../libs/das-core", default-features = false } das-types = { path = "../../../das-types/rust", default-features = false } +chrono = { version = "0.4", default-features = false } diff --git a/contracts/pre-account-cell-type/src/entry.rs b/contracts/pre-account-cell-type/src/entry.rs index af5e49ec..3bbf4120 100644 --- a/contracts/pre-account-cell-type/src/entry.rs +++ b/contracts/pre-account-cell-type/src/entry.rs @@ -137,6 +137,8 @@ pub fn main() -> Result<(), Error> { apply_register_hash, )?; + debug!("Verify various fields of PreAccountCell ..."); + verify_owner_lock_args(pre_account_cell_witness_reader)?; verify_quote(pre_account_cell_witness_reader)?; let config_price = parser.configs.price()?; @@ -148,24 +150,49 @@ pub fn main() -> Result<(), Error> { pre_account_cell_witness_reader, capacity, )?; - verify_account_id(pre_account_cell_witness_reader, account_id)?; - let timestamp = util::load_oracle_data(OracleCellType::Time)?; verify_created_at(timestamp, pre_account_cell_witness_reader)?; - util::verify_account_length_and_years( - pre_account_cell_witness_reader.account().len(), - timestamp, - None, - )?; - verify_account_release_status( - pre_account_cell_witness_reader.account().len(), - pre_account_cell_witness_reader, - )?; - verify_account_length(config_account, pre_account_cell_witness_reader)?; + debug!("Verify if account is available for registration for now ..."); + verify_account_max_length(config_account, pre_account_cell_witness_reader)?; + + let cells_with_super_lock = + util::find_cells_by_script(ScriptType::Lock, super_lock().as_reader(), Source::Input)?; + + match verify_account_length_and_years(pre_account_cell_witness_reader, timestamp) { + Ok(_) => {} + Err(code) => { + if !(code == Error::AccountStillCanNotBeRegister && cells_with_super_lock.len() > 0) + { + return Err(code); + } + debug!("Skip Error::AccountStillCanNotBeRegister because of super lock."); + } + } + + match verify_account_release_status(pre_account_cell_witness_reader) { + Ok(_) => {} + Err(code) => { + if !(code == Error::AccountStillCanNotBeRegister && cells_with_super_lock.len() > 0) + { + return Err(code); + } + debug!("Skip Error::AccountStillCanNotBeRegister because of super lock."); + } + } + + match verify_preserved_accounts(&mut parser, pre_account_cell_witness_reader) { + Ok(_) => {} + Err(code) => { + if !(code == Error::AccountIsPreserved && cells_with_super_lock.len() > 0) { + return Err(code); + } + debug!("Skip Error::AccountIsPreserved because of super lock."); + } + } + verify_account_chars(&mut parser, pre_account_cell_witness_reader)?; - verify_preserved_accounts(&mut parser, pre_account_cell_witness_reader)?; } else { return Err(Error::ActionNotSupported); } @@ -408,7 +435,7 @@ fn verify_price_and_capacity( Ok(()) } -fn verify_account_length( +fn verify_account_max_length( config: ConfigCellAccountReader, reader: PreAccountCellDataReader, ) -> Result<(), Error> { @@ -559,10 +586,35 @@ fn verify_preserved_accounts( Ok(()) } -fn verify_account_release_status( - account_length: usize, +fn verify_account_length_and_years( reader: PreAccountCellDataReader, + current_timestamp: u64, ) -> Result<(), Error> { + use chrono::{DateTime, NaiveDateTime, Utc}; + + let account_length = reader.account().len(); + let current = DateTime::::from_utc( + NaiveDateTime::from_timestamp(current_timestamp as i64, 0), + Utc, + ); + + debug!( + "Check if the account is available for registration now. (length: {}, current: {:#?})", + account_length, current + ); + + // On CKB main net, AKA Lina, accounts of less lengths can be registered only after a specific number of years. + // TODO Trible check. + assert!( + account_length >= 5, + Error::AccountStillCanNotBeRegister, + "The account less than 5 characters can not be registered now." + ); + + Ok(()) +} + +fn verify_account_release_status(reader: PreAccountCellDataReader) -> Result<(), Error> { debug!("Check if account is released for registration."); let account: Vec = [ @@ -574,7 +626,7 @@ fn verify_account_release_status( let lucky_num = hash[0]; if cfg!(feature = "mainnet") { - if account_length < 10 { + if reader.account().len() < 10 { // TODO Trible check. assert!( lucky_num <= 12, @@ -584,11 +636,11 @@ fn verify_account_release_status( ); } } else { - if account_length < 10 { + if reader.account().len() < 10 { assert!( lucky_num <= 200, Error::AccountStillCanNotBeRegister, - "The registration is still not started.(lucky_num: {}, required: <= 254)", + "The registration is still not started.(lucky_num: {}, required: <= 200)", lucky_num ); } diff --git a/contracts/proposal-cell-type/src/entry.rs b/contracts/proposal-cell-type/src/entry.rs index 83ceaf7a..ea907baa 100644 --- a/contracts/proposal-cell-type/src/entry.rs +++ b/contracts/proposal-cell-type/src/entry.rs @@ -850,12 +850,6 @@ fn verify_proposal_execution_result( item_index, profit, total_capacity, storage_capacity ); - util::verify_account_length_and_years( - input_cell_witness_reader.account().len(), - timestamp, - Some(item_index), - )?; - is_cell_capacity_correct(item_index, output_account_cells[i], storage_capacity)?; is_new_account_cell_lock_correct( item_index, diff --git a/libs/das-core/src/error.rs b/libs/das-core/src/error.rs index 3098bd6d..0af618b8 100644 --- a/libs/das-core/src/error.rs +++ b/libs/das-core/src/error.rs @@ -1,7 +1,7 @@ use ckb_std::error::SysError; /// Error -#[derive(Debug)] +#[derive(Debug, PartialEq)] #[repr(i8)] pub enum Error { IndexOutOfBound = 1, diff --git a/libs/das-core/src/util.rs b/libs/das-core/src/util.rs index c9d4dcb7..46686a67 100644 --- a/libs/das-core/src/util.rs +++ b/libs/das-core/src/util.rs @@ -669,60 +669,6 @@ pub fn is_init_day(current_timestamp: u64) -> Result<(), Error> { Ok(()) } -pub fn verify_account_length_and_years( - account_length: usize, - current_timestamp: u64, - item_index: Option, -) -> Result<(), Error> { - use chrono::{DateTime, NaiveDateTime, TimeZone, Utc}; - - let current = DateTime::::from_utc( - NaiveDateTime::from_timestamp(current_timestamp as i64, 0), - Utc, - ); - - if item_index.is_some() { - debug!( - " Item[{}] Check if the account is available for registration now. (length: {}, current: {:#?})", - item_index.unwrap(), account_length, current - ); - } else { - debug!( - "Check if the account is available for registration now. (length: {}, current: {:#?})", - account_length, current - ); - } - - // On CKB main net, AKA Lina, accounts of less lengths can be registered only after a specific number of years. - if cfg!(feature = "mainnet") { - // TODO Trible check. - // ⚠️ Before year 2 means the first year. - assert!( - account_length >= 5, - Error::AccountStillCanNotBeRegister, - "The account less than 10 characters can not be registered now." - ); - } else if cfg!(feature = "testnet") { - assert!( - account_length >= 2, - Error::AccountStillCanNotBeRegister, - "The account less than 2 characters can not be registered now." - ); - } else { - let year_n = Utc.ymd(4444, 4, 4).and_hms(4, 4, 4); - if current < year_n { - assert!( - account_length >= 2, - Error::AccountStillCanNotBeRegister, - "The account less than 2 characters can not be registered now. (available_for_register: {:?})", - year_n - ); - } - } - - Ok(()) -} - pub fn calc_account_storage_capacity( config_account: das_packed::ConfigCellAccountReader, account_name_storage: u64, From f59a9fce7a23b23378de432bd115b8733f4d50f2 Mon Sep 17 00:00:00 2001 From: Link Date: Thu, 5 Aug 2021 11:18:37 +0800 Subject: [PATCH 2/4] fix: remove some useless verifications --- contracts/apply-register-cell-type/src/entry.rs | 2 -- contracts/pre-account-cell-type/src/entry.rs | 7 ------- 2 files changed, 9 deletions(-) diff --git a/contracts/apply-register-cell-type/src/entry.rs b/contracts/apply-register-cell-type/src/entry.rs index d89feeee..5d130663 100644 --- a/contracts/apply-register-cell-type/src/entry.rs +++ b/contracts/apply-register-cell-type/src/entry.rs @@ -35,8 +35,6 @@ pub fn main() -> Result<(), Error> { "There should be none ApplyRegisterCell in inputs and one in outputs." ); - util::is_cell_use_signall_lock(output_cells[0], Source::Output)?; - // Verify the outputs_data of ApplyRegisterCell. let index = &output_cells[0]; let data = util::load_cell_data(index.to_owned(), Source::Output)?; diff --git a/contracts/pre-account-cell-type/src/entry.rs b/contracts/pre-account-cell-type/src/entry.rs index 3bbf4120..c5362382 100644 --- a/contracts/pre-account-cell-type/src/entry.rs +++ b/contracts/pre-account-cell-type/src/entry.rs @@ -314,13 +314,6 @@ fn verify_owner_lock_args(reader: PreAccountCellDataReader) -> Result<(), Error> owner_lock_args.len() ); - assert!( - owner_lock_args[0] <= 10, - Error::PreRegisterOwnerLockArgsIsInvalid, - "The first of owner_lock_args should between 0 and 10, but {} found.", - owner_lock_args[0] - ); - Ok(()) } From 955578f36d33e4e7d6c0dbff5d49bbd09bd64c2e Mon Sep 17 00:00:00 2001 From: Link Date: Thu, 5 Aug 2021 16:31:07 +0800 Subject: [PATCH 3/4] test: refactor and add tons of new tests for pre-account-cell-type --- tests/src/account_cell_type.rs | 2 +- .../income_cell_type/income_consolidate.rs | 7 +- tests/src/pre_account_cell_type.rs | 238 --------- .../pre_account_cell_type/account_release.rs | 205 ++++++++ tests/src/pre_account_cell_type/char_set.rs | 59 +++ tests/src/pre_account_cell_type/common.rs | 44 ++ tests/src/pre_account_cell_type/mod.rs | 5 + .../preserved_accounts.rs | 124 +++++ tests/src/pre_account_cell_type/simple.rs | 468 ++++++++++++++++++ tests/src/util/constants.rs | 8 + tests/src/util/template_generator.rs | 97 +++- tests/src/util/util.rs | 24 + 12 files changed, 1015 insertions(+), 266 deletions(-) delete mode 100644 tests/src/pre_account_cell_type.rs create mode 100644 tests/src/pre_account_cell_type/account_release.rs create mode 100644 tests/src/pre_account_cell_type/char_set.rs create mode 100644 tests/src/pre_account_cell_type/common.rs create mode 100644 tests/src/pre_account_cell_type/mod.rs create mode 100644 tests/src/pre_account_cell_type/preserved_accounts.rs create mode 100644 tests/src/pre_account_cell_type/simple.rs diff --git a/tests/src/account_cell_type.rs b/tests/src/account_cell_type.rs index 979632b1..d95431ef 100644 --- a/tests/src/account_cell_type.rs +++ b/tests/src/account_cell_type.rs @@ -626,7 +626,7 @@ fn gen_account_renew() { template.write_template("account_renew_account.json"); } -test_with_template!(test_account_renew, "account_renew_account.json"); +// test_with_template!(test_account_renew, "account_renew_account.json"); #[test] fn gen_account_recycle_expired_account_by_keeper() { diff --git a/tests/src/income_cell_type/income_consolidate.rs b/tests/src/income_cell_type/income_consolidate.rs index ee3cfd0b..5b322a1c 100644 --- a/tests/src/income_cell_type/income_consolidate.rs +++ b/tests/src/income_cell_type/income_consolidate.rs @@ -14,7 +14,7 @@ fn init(action: &str) -> TemplateGenerator { } #[test] -fn gen_income_consolidate_need_pad() { +fn gen_income_consolidate_need_pad_1() { let mut template = init("consolidate_income"); let capacity_of_10 = 20_000_000_000; @@ -114,7 +114,10 @@ fn gen_income_consolidate_need_pad() { template.write_template("income_consolidate.json"); } -test_with_template!(test_income_consolidate_need_pad, "income_consolidate.json"); +test_with_template!( + test_income_consolidate_need_pad_1, + "income_consolidate.json" +); test_with_generator!(test_income_consolidate_need_pad_2, || { let mut template = init("consolidate_income"); diff --git a/tests/src/pre_account_cell_type.rs b/tests/src/pre_account_cell_type.rs deleted file mode 100644 index c6951ef2..00000000 --- a/tests/src/pre_account_cell_type.rs +++ /dev/null @@ -1,238 +0,0 @@ -use super::util::{constants::*, template_generator::*, template_parser::TemplateParser}; -use chrono::{TimeZone, Utc}; -use ckb_testtool::context::Context; -use das_core::error::Error; -use das_types::constants::*; - -fn init(account: &str) -> (TemplateGenerator, &str, u64) { - let mut template = TemplateGenerator::new("pre_register", None); - - let timestamp = Utc.ymd(2021, 7, 7).and_hms(14, 0, 0).timestamp() as u64; - let height = 1000u64; - - template.push_contract_cell("always_success", true); - template.push_contract_cell("apply-register-cell-type", false); - template.push_contract_cell("pre-account-cell-type", false); - - template.push_oracle_cell(1, OracleCellType::Height, height); - template.push_oracle_cell(1, OracleCellType::Time, timestamp); - template.push_oracle_cell(1, OracleCellType::Quote, 1000); - - template.push_config_cell(DataType::ConfigCellAccount, true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellApply, true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellCharSetEmoji, true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellCharSetDigit, true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellCharSetEn, true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellMain, true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellPrice, true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellRelease, true, 0, Source::CellDep); - - template.push_apply_register_cell( - "0x9af92f5e690f4669ca543deb99af8385b12624cc", - account, - height - 4, - timestamp - 60, - 0, - Source::Input, - ); - - (template, account, timestamp) -} - -#[test] -fn gen_pre_register_simple() { - let (mut template, account, timestamp) = init("✨das🎉001.bit"); - template.push_config_cell_derived_by_account("✨das🎉001", true, 0, Source::CellDep); - - let (cell_data, entity) = template.gen_pre_account_cell_data( - account, - "0x000000000000000000000000000000000000FFFF", - "0x0000000000000000000000000000000000001100", - "0x0000000000000000000000000000000000001111", - "0x0000000000000000000000000000000000002222", - 1000, - 500, - timestamp, - ); - template.push_pre_account_cell( - cell_data, - Some((1, 0, entity)), - 476_200_000_000 + ACCOUNT_BASIC_CAPACITY + ACCOUNT_PREPARED_FEE_CAPACITY, - Source::Output, - ); - - template.write_template("pre_register.json"); -} - -test_with_template!(test_pre_register_simple, "pre_register.json"); - -test_with_generator!(test_pre_register_char_set, || { - let (mut template, account, timestamp) = init("✨咐桑糯0001.bit"); - template.push_config_cell_derived_by_account("✨咐桑糯0001", true, 0, Source::CellDep); - template.push_config_cell(DataType::ConfigCellCharSetZhHans, true, 0, Source::CellDep); - - let (cell_data, entity) = template.gen_pre_account_cell_data( - account, - "0x000000000000000000000000000000000000FFFF", - "0x0000000000000000000000000000000000001100", - "0x0000000000000000000000000000000000001111", - "0x0000000000000000000000000000000000002222", - 1000, - 500, - timestamp, - ); - template.push_pre_account_cell( - cell_data, - Some((1, 0, entity)), - 476_200_000_000 + ACCOUNT_BASIC_CAPACITY + ACCOUNT_PREPARED_FEE_CAPACITY, - Source::Output, - ); - - template.as_json() -}); - -challenge_with_generator!( - challenge_pre_register_invalid_char, - Error::PreRegisterAccountCharIsInvalid, - || { - // ⚠️ Need to delete the emoji from char_set_emoji.txt first, otherwise the test can not pass. - let (mut template, account, timestamp) = init("✨das🎱001.bit"); - template.push_config_cell_derived_by_account("✨das🎱001", true, 0, Source::CellDep); - - let (cell_data, entity) = template.gen_pre_account_cell_data( - account, - "0x0000000000000000000000000000000000002222", - "0x000000000000000000000000000000000000FFFF", - "0x0000000000000000000000000000000000001111", - "0x0000000000000000000000000000000000002222", - 1000, - 500, - timestamp, - ); - template.push_pre_account_cell( - cell_data, - Some((1, 0, entity)), - 476_300_000_000 + ACCOUNT_BASIC_CAPACITY + ACCOUNT_PREPARED_FEE_CAPACITY, - Source::Output, - ); - - template.as_json() - } -); - -challenge_with_generator!( - challenge_pre_register_preserved_account, - Error::AccountIsPreserved, - || { - let (mut template, account, timestamp) = init("microsoft.bit"); - template.push_config_cell_derived_by_account("microsoft", true, 0, Source::CellDep); - - let (cell_data, entity) = template.gen_pre_account_cell_data( - account, - "0x0000000000000000000000000000000000002222", - "0x000000000000000000000000000000000000FFFF", - "0x0000000000000000000000000000000000001111", - "0x0000000000000000000000000000000000002222", - 1000, - 500, - timestamp, - ); - template.push_pre_account_cell( - cell_data, - Some((1, 0, entity)), - 476_300_000_000 + ACCOUNT_BASIC_CAPACITY + ACCOUNT_PREPARED_FEE_CAPACITY, - Source::Output, - ); - - template.as_json() - } -); - -challenge_with_generator!( - challenge_pre_register_account_can_not_register, - Error::AccountStillCanNotBeRegister, - || { - let (mut template, account, timestamp) = init("a.bit"); - template.push_config_cell_derived_by_account("a", true, 0, Source::CellDep); - - let (cell_data, entity) = template.gen_pre_account_cell_data( - account, - "0x0000000000000000000000000000000000002222", - "0x000000000000000000000000000000000000FFFF", - "0x0000000000000000000000000000000000001111", - "0x0000000000000000000000000000000000002222", - 1000, - 500, - timestamp, - ); - template.push_pre_account_cell( - cell_data, - Some((1, 0, entity)), - 1_140_500_000_000 + ACCOUNT_BASIC_CAPACITY + ACCOUNT_PREPARED_FEE_CAPACITY, - Source::Output, - ); - - template.as_json() - } -); - -challenge_with_generator!( - challenge_pre_register_account_not_released, - Error::AccountStillCanNotBeRegister, - || { - let (mut template, account, timestamp) = init("yw3l1n.bit"); - template.push_config_cell_derived_by_account("yw3l1n", true, 0, Source::CellDep); - - let (cell_data, entity) = template.gen_pre_account_cell_data( - account, - "0x0000000000000000000000000000000000002222", - "0x000000000000000000000000000000000000FFFF", - "0x0000000000000000000000000000000000001111", - "0x0000000000000000000000000000000000002222", - 1000, - 500, - timestamp, - ); - template.push_pre_account_cell( - cell_data, - Some((1, 0, entity)), - 1_140_500_000_000 + ACCOUNT_BASIC_CAPACITY + ACCOUNT_PREPARED_FEE_CAPACITY, - Source::Output, - ); - - template.as_json() - } -); - -challenge_with_generator!( - challenge_pre_register_account_length, - Error::PreRegisterAccountIsTooLong, - || { - let (mut template, account, timestamp) = init("123456789012345678901.bit"); - template.push_config_cell_derived_by_account( - "123456789012345678901", - true, - 0, - Source::CellDep, - ); - - let (cell_data, entity) = template.gen_pre_account_cell_data( - account, - "0x0000000000000000000000000000000000002222", - "0x000000000000000000000000000000000000FFFF", - "0x0000000000000000000000000000000000001111", - "0x0000000000000000000000000000000000002222", - 1000, - 500, - timestamp, - ); - template.push_pre_account_cell( - cell_data, - Some((1, 0, entity)), - 500_000_000_000 + ACCOUNT_BASIC_CAPACITY + ACCOUNT_PREPARED_FEE_CAPACITY, - Source::Output, - ); - - template.as_json() - } -); diff --git a/tests/src/pre_account_cell_type/account_release.rs b/tests/src/pre_account_cell_type/account_release.rs new file mode 100644 index 00000000..500afe1d --- /dev/null +++ b/tests/src/pre_account_cell_type/account_release.rs @@ -0,0 +1,205 @@ +use super::common::init; +use crate::util; +use crate::util::{constants::*, template_parser::TemplateParser}; +use ckb_testtool::context::Context; +use das_core::error::Error; + +test_with_generator!(test_pre_register_account_registrable, || { + // This is one of the shortest registrable accounts for now, it only contains 5 chars. + let (mut template, account, timestamp) = init("1qoqm.bit"); + template.push_config_cell_derived_by_account("1qoqm", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(5, true), + Source::Output, + ); + + template.as_json() +}); + +test_with_generator!( + test_pre_register_account_not_registrable_with_super_lock, + || { + // This is not a registrable account, it only contains 4 chars. + let (mut template, account, timestamp) = init("nsn2.bit"); + template.push_config_cell_derived_by_account("nsn2", true, 0, Source::CellDep); + + // 0x0000000000000000000000000000000000000000 is the super lock in dev environment. + template.push_signall_cell( + "0x0000000000000000000000000000000000000000", + 0, + Source::Input, + ); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(4, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_account_not_registrable, + Error::AccountStillCanNotBeRegister, + || { + // This is not a registrable account, it only contains 4 chars. + let (mut template, account, timestamp) = init("e3bn.bit"); + template.push_config_cell_derived_by_account("e3bn", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(1, true), + Source::Output, + ); + + template.as_json() + } +); + +test_with_generator!(test_pre_register_account_released, || { + // The first byte of hash is 200, it just equal to threshold 200. + let (mut template, account, timestamp) = init("dh5vyto8.bit"); + template.push_config_cell_derived_by_account("dh5vyto8", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(8, true), + Source::Output, + ); + + template.as_json() +}); + +test_with_generator!(test_pre_register_account_released_2, || { + // The length of account is 10, it should skip the release status check. + let (mut template, account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() +}); + +test_with_generator!(test_pre_register_account_unreleased_with_super_lock, || { + // The first byte of hash is 201, it just bigger than threshold 200. + let (mut template, account, timestamp) = init("4lorcguq.bit"); + template.push_config_cell_derived_by_account("4lorcguq", true, 0, Source::CellDep); + + // 0x0000000000000000000000000000000000000000 is the super lock in dev environment. + template.push_signall_cell( + "0x0000000000000000000000000000000000000000", + 0, + Source::Input, + ); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(8, true), + Source::Output, + ); + + template.as_json() +}); + +challenge_with_generator!( + challenge_pre_register_account_unreleased, + Error::AccountStillCanNotBeRegister, + || { + // The first byte of hash is 201, it just bigger than threshold 200. + let (mut template, account, timestamp) = init("kaecieg1.bit"); + template.push_config_cell_derived_by_account("kaecieg1", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(8, true), + Source::Output, + ); + + template.as_json() + } +); diff --git a/tests/src/pre_account_cell_type/char_set.rs b/tests/src/pre_account_cell_type/char_set.rs new file mode 100644 index 00000000..301fd63b --- /dev/null +++ b/tests/src/pre_account_cell_type/char_set.rs @@ -0,0 +1,59 @@ +use super::common::init; +use crate::util::{constants::*, template_parser::TemplateParser}; +use ckb_testtool::context::Context; +use das_core::error::Error; +use das_types::constants::*; + +test_with_generator!(test_pre_register_char_set, || { + let (mut template, account, timestamp) = init("✨咐桑糯0001.bit"); + template.push_config_cell_derived_by_account("✨咐桑糯0001", true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellCharSetZhHans, true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001100", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(8, true), + Source::Output, + ); + + template.as_json() +}); + +challenge_with_generator!( + challenge_pre_register_invalid_char, + Error::PreRegisterAccountCharIsInvalid, + || { + // ⚠️ Need to delete the emoji from char_set_emoji.txt first, otherwise the test can not pass. + let (mut template, account, timestamp) = init("✨das🎱001.bit"); + template.push_config_cell_derived_by_account("✨das🎱001", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(8, true), + Source::Output, + ); + + template.as_json() + } +); diff --git a/tests/src/pre_account_cell_type/common.rs b/tests/src/pre_account_cell_type/common.rs new file mode 100644 index 00000000..3f1d03c5 --- /dev/null +++ b/tests/src/pre_account_cell_type/common.rs @@ -0,0 +1,44 @@ +use crate::util::{constants::*, template_generator::*}; +use chrono::{TimeZone, Utc}; +use das_types::constants::*; + +pub fn init_without_apply(account: &str) -> (TemplateGenerator, &str, u64, u64) { + let mut template = TemplateGenerator::new("pre_register", None); + + let timestamp = Utc.ymd(2021, 7, 7).and_hms(14, 0, 0).timestamp() as u64; + let height = 1000000u64; + + template.push_contract_cell("always_success", true); + template.push_contract_cell("apply-register-cell-type", false); + template.push_contract_cell("pre-account-cell-type", false); + + template.push_oracle_cell(1, OracleCellType::Height, height); + template.push_oracle_cell(1, OracleCellType::Time, timestamp); + template.push_oracle_cell(1, OracleCellType::Quote, 1000); + + template.push_config_cell(DataType::ConfigCellAccount, true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellApply, true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellCharSetEmoji, true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellCharSetDigit, true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellCharSetEn, true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellMain, true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellPrice, true, 0, Source::CellDep); + template.push_config_cell(DataType::ConfigCellRelease, true, 0, Source::CellDep); + + (template, account, timestamp, height) +} + +pub fn init(account: &str) -> (TemplateGenerator, &str, u64) { + let (mut template, account, timestamp, height) = init_without_apply(account); + + template.push_apply_register_cell( + "0x9af92f5e690f4669ca543deb99af8385b12624cc", + account, + height - 4, + timestamp - 60, + 0, + Source::Input, + ); + + (template, account, timestamp) +} diff --git a/tests/src/pre_account_cell_type/mod.rs b/tests/src/pre_account_cell_type/mod.rs new file mode 100644 index 00000000..50bdac5c --- /dev/null +++ b/tests/src/pre_account_cell_type/mod.rs @@ -0,0 +1,5 @@ +mod account_release; +mod char_set; +mod common; +mod preserved_accounts; +mod simple; diff --git a/tests/src/pre_account_cell_type/preserved_accounts.rs b/tests/src/pre_account_cell_type/preserved_accounts.rs new file mode 100644 index 00000000..624b7dba --- /dev/null +++ b/tests/src/pre_account_cell_type/preserved_accounts.rs @@ -0,0 +1,124 @@ +use super::common::init; +use crate::util; +use crate::util::{constants::*, template_parser::TemplateParser}; +use ckb_testtool::context::Context; +use das_core::error::Error; + +challenge_with_generator!( + challenge_pre_register_preserved_account, + Error::AccountIsPreserved, + || { + let (mut template, account, timestamp) = init("microsoft.bit"); + template.push_config_cell_derived_by_account("microsoft", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(9, true), + Source::Output, + ); + + template.as_json() + } +); + +test_with_generator!(test_pre_register_preserved_account_with_super_lock, || { + let (mut template, account, timestamp) = init("microsoft.bit"); + template.push_config_cell_derived_by_account("microsoft", true, 0, Source::CellDep); + + // 0x0000000000000000000000000000000000000000 is the super lock in dev environment. + template.push_signall_cell( + "0x0000000000000000000000000000000000000000", + 0, + Source::Input, + ); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(9, true), + Source::Output, + ); + + template.as_json() +}); + +// TODO Need optimize with release version. +// #[test] +// fn challenge_pre_register_preserved_account() { +// let lines = util::read_lines("preserved_accounts.txt") +// .expect("Expect file ./data/preserved_accounts.txt exist."); +// for line in lines { +// if let Ok(account) = line { +// let account_length = account.chars().count(); +// if !account.is_empty() && account_length > ACCOUNT_RELEASED_LENGTH { +// let account_with_suffix = account.clone() + ".bit"; +// let (mut template, _, timestamp) = init(&account_with_suffix); +// template.push_config_cell_derived_by_account(&account, true, 0, Source::CellDep); +// +// let (cell_data, entity) = template.gen_pre_account_cell_data( +// &account_with_suffix, +// "0x0000000000000000000000000000000000002222", +// "0x000000000000000000000000000000000000FFFF", +// "0x0000000000000000000000000000000000001111", +// "0x0000000000000000000000000000000000002222", +// 1000, +// 500, +// timestamp, +// ); +// template.push_pre_account_cell( +// cell_data, +// Some((1, 0, entity)), +// util::gen_register_fee(account_length, true), +// Source::Output, +// ); +// +// let mut parser = TemplateParser::from_data(Context::default(), template.as_json()); +// parser.parse(); +// +// let ret = parser.execute_tx_directly(); +// match ret { +// Ok(_) => { +// // println!("{}", serde_json::to_string_pretty(&template).unwrap()); +// panic!( +// "The test should failed with error code: {}, but it returns Ok.", +// Error::AccountIsPreserved as i8 +// ) +// } +// Err(err) => { +// let msg = err.to_string(); +// println!("Error message: {}", msg); +// +// let search = +// format!("ValidationFailure({})", Error::AccountIsPreserved as i8); +// assert!( +// msg.contains(search.as_str()), +// "The test should failed with error code: {}", +// Error::AccountIsPreserved as i8 +// ); +// } +// } +// } +// } +// } +// } diff --git a/tests/src/pre_account_cell_type/simple.rs b/tests/src/pre_account_cell_type/simple.rs new file mode 100644 index 00000000..5c8c5ab8 --- /dev/null +++ b/tests/src/pre_account_cell_type/simple.rs @@ -0,0 +1,468 @@ +use super::common::{init, init_without_apply}; +use crate::util; +use crate::util::{ + constants::*, + template_generator::{gen_account_chars, gen_always_success_lock, gen_das_lock_args}, + template_parser::TemplateParser, +}; +use ckb_testtool::context::Context; +use ckb_tool::ckb_hash::blake2b_256; +use das_core::error::Error; +use das_types::{packed::*, prelude::*}; +use std::convert::TryFrom; + +#[test] +fn gen_pre_register_simple() { + let (mut template, account, timestamp) = init("✨das🎉001.bit"); + template.push_config_cell_derived_by_account("✨das🎉001", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001100", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(8, true), + Source::Output, + ); + + template.write_template("pre_register.json"); +} + +test_with_template!(test_pre_register_simple, "pre_register.json"); + +challenge_with_generator!( + challenge_pre_register_apply_still_need_wait, + Error::ApplyRegisterNeedWaitLonger, + || { + let (mut template, account, timestamp, height) = init_without_apply("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + template.push_apply_register_cell( + "0x9af92f5e690f4669ca543deb99af8385b12624cc", + account, + height, + timestamp - 60, + 0, + Source::Input, + ); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp - 1, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_apply_timeout, + Error::ApplyRegisterHasTimeout, + || { + let (mut template, account, timestamp, height) = init_without_apply("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + template.push_apply_register_cell( + "0x9af92f5e690f4669ca543deb99af8385b12624cc", + account, + height - 5761, + timestamp - 60, + 0, + Source::Input, + ); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp - 1, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_apply_hash_is_invalid, + Error::PreRegisterApplyHashIsInvalid, + || { + let (mut template, account, timestamp, height) = init_without_apply("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + template.push_apply_register_cell( + "0x9af92f5e690f4669ca543deb99af8385b12624cc", + "000000000", // Different from the account in PreAccountCell, this will cause assertion of hash failure. + height - 1, + timestamp - 60, + 0, + Source::Input, + ); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp - 1, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_invalid_account_id, + Error::PreRegisterAccountIdIsInvalid, + || { + let (mut template, _account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let refund_lock_args = "0x0000000000000000000000000000000000002222"; + let owner_lock_args = "0x000000000000000000000000000000000000FFFF"; + let inviter_lock_args = "0x0000000000000000000000000000000000001111"; + let channel_lock_args = "0x0000000000000000000000000000000000002222"; + let quote = CKB_QUOTE; + let invited_discount = INVITED_DISCOUNT; + let created_at = timestamp - 1; + + let account_chars_raw = "1234567890" + .chars() + .map(|c| c.to_string()) + .collect::>(); + let account_chars = gen_account_chars(account_chars_raw); + let price = template.get_price(account_chars.len()); + let mut tmp = util::hex_to_bytes(&gen_das_lock_args(owner_lock_args, None)); + tmp.append(&mut tmp.clone()); + let owner_lock_args = Bytes::from(tmp); + + let entity = PreAccountCellData::new_builder() + .account(account_chars.to_owned()) + .owner_lock_args(owner_lock_args) + .refund_lock(gen_always_success_lock(refund_lock_args)) + .inviter_id(Bytes::from(vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ])) + .inviter_lock(ScriptOpt::from(gen_always_success_lock(inviter_lock_args))) + .channel_lock(ScriptOpt::from(gen_always_success_lock(channel_lock_args))) + .price(price.to_owned()) + .quote(Uint64::from(quote)) + .invited_discount(Uint32::from(invited_discount as u32)) + .created_at(Timestamp::from(created_at)) + .build(); + + // The account ID calculated from other account expected to be denied correctly. + let id = util::account_to_id("0000000000"); + + let hash = Hash::try_from(blake2b_256(entity.as_slice()).to_vec()).unwrap(); + let raw = [hash.as_reader().raw_data(), id.as_slice()].concat(); + let cell_data = Bytes::from(raw); + + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_created_at_mismatch, + Error::PreRegisterCreateAtIsInvalid, + || { + let (mut template, account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp - 1, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_invalid_owner_lock_args, + Error::PreRegisterOwnerLockArgsIsInvalid, + || { + let (mut template, account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_quote_mismatch, + Error::PreRegisterQuoteIsInvalid, + || { + let (mut template, account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE - 1, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_exceed_account_max_length, + Error::PreRegisterAccountIsTooLong, + || { + let (mut template, account, timestamp) = + init("1234567890123456789012345678901234567890123.bit"); + template.push_config_cell_derived_by_account( + "1234567890123456789012345678901234567890123", + true, + 0, + Source::CellDep, + ); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(43, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_discount_not_zero_when_no_inviter, + Error::PreRegisterDiscountIsInvalid, + || { + let (mut template, account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_discount_incorrect, + Error::PreRegisterDiscountIsInvalid, + || { + let (mut template, account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT - 1, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_incorrect_price, + Error::PreRegisterPriceInvalid, + || { + let (mut template, _account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let refund_lock_args = "0x0000000000000000000000000000000000002222"; + let owner_lock_args = "0x000000000000000000000000000000000000FFFF"; + let inviter_lock_args = "0x0000000000000000000000000000000000001111"; + let channel_lock_args = "0x0000000000000000000000000000000000002222"; + let quote = CKB_QUOTE; + let invited_discount = INVITED_DISCOUNT; + let created_at = timestamp - 1; + + let account_chars_raw = "1234567890" + .chars() + .map(|c| c.to_string()) + .collect::>(); + let account_chars = gen_account_chars(account_chars_raw); + let price = template.get_price(4); + let mut tmp = util::hex_to_bytes(&gen_das_lock_args(owner_lock_args, None)); + tmp.append(&mut tmp.clone()); + let owner_lock_args = Bytes::from(tmp); + + let entity = PreAccountCellData::new_builder() + .account(account_chars.to_owned()) + .owner_lock_args(owner_lock_args) + .refund_lock(gen_always_success_lock(refund_lock_args)) + .inviter_id(Bytes::from(vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ])) + .inviter_lock(ScriptOpt::from(gen_always_success_lock(inviter_lock_args))) + .channel_lock(ScriptOpt::from(gen_always_success_lock(channel_lock_args))) + .price(price.to_owned()) + .quote(Uint64::from(quote)) + .invited_discount(Uint32::from(invited_discount as u32)) + .created_at(Timestamp::from(created_at)) + .build(); + + // The account ID calculated from other account expected to be denied correctly. + let id = util::account_to_id("0000000000"); + + let hash = Hash::try_from(blake2b_256(entity.as_slice()).to_vec()).unwrap(); + let raw = [hash.as_reader().raw_data(), id.as_slice()].concat(); + let cell_data = Bytes::from(raw); + + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true), + Source::Output, + ); + + template.as_json() + } +); + +challenge_with_generator!( + challenge_pre_register_incorrect_capacity, + Error::PreRegisterCKBInsufficient, + || { + let (mut template, account, timestamp) = init("1234567890.bit"); + template.push_config_cell_derived_by_account("1234567890", true, 0, Source::CellDep); + + let (cell_data, entity) = template.gen_pre_account_cell_data( + account, + "0x0000000000000000000000000000000000002222", + "0x000000000000000000000000000000000000FFFF", + "0x0000000000000000000000000000000000001111", + "0x0000000000000000000000000000000000002222", + CKB_QUOTE, + INVITED_DISCOUNT, + timestamp, + ); + template.push_pre_account_cell( + cell_data, + Some((1, 0, entity)), + util::gen_register_fee(10, true) - 1, + Source::Output, + ); + + template.as_json() + } +); diff --git a/tests/src/util/constants.rs b/tests/src/util/constants.rs index b24cc587..bb56c1e5 100644 --- a/tests/src/util/constants.rs +++ b/tests/src/util/constants.rs @@ -7,8 +7,16 @@ pub const ACCOUNT_ID_LENGTH: usize = 20; pub const ACCOUNT_BASIC_CAPACITY: u64 = 20_600_000_000; pub const ACCOUNT_PREPARED_FEE_CAPACITY: u64 = 100_000_000; pub const ACCOUNT_OPERATE_FEE: u64 = 10_000; +pub const ACCOUNT_RELEASED_LENGTH: usize = 5; +pub const ACCOUNT_PRICE_1_CHAR: u64 = 2000_000_000; +pub const ACCOUNT_PRICE_2_CHAR: u64 = 1000_000_000; +pub const ACCOUNT_PRICE_3_CHAR: u64 = 700_000_000; +pub const ACCOUNT_PRICE_4_CHAR: u64 = 170_000_000; +pub const ACCOUNT_PRICE_5_CHAR: u64 = 5_000_000; +pub const INVITED_DISCOUNT: u64 = 500; pub const CONSOLIDATING_FEE: u64 = 100; +pub const CKB_QUOTE: u64 = 1000; pub const RATE_BASE: u64 = 10_000; diff --git a/tests/src/util/template_generator.rs b/tests/src/util/template_generator.rs index fda02e99..23f13c08 100644 --- a/tests/src/util/template_generator.rs +++ b/tests/src/util/template_generator.rs @@ -7,7 +7,7 @@ use regex::Regex; use serde_json::{json, Value}; use std::{collections::HashMap, convert::TryFrom, env, fs::OpenOptions, io::Write, str}; -fn gen_always_success_lock(lock_args: &str) -> Script { +pub fn gen_always_success_lock(lock_args: &str) -> Script { Script::new_builder() .code_hash(Hash::try_from(ALWAYS_SUCCESS_CODE_HASH.to_vec()).unwrap()) .hash_type(Byte::new(1)) @@ -15,7 +15,7 @@ fn gen_always_success_lock(lock_args: &str) -> Script { .build() } -fn gen_das_lock_args(owner_pubkey_hash: &str, manager_pubkey_hash_opt: Option<&str>) -> String { +pub fn gen_das_lock_args(owner_pubkey_hash: &str, manager_pubkey_hash_opt: Option<&str>) -> String { if let Some(manager_pubkey_hash) = manager_pubkey_hash_opt { format!( "0x00{}00{}", @@ -319,14 +319,38 @@ impl TemplateGenerator { let witness = das_util::wrap_action_witness(action, params_opt); let mut prices = HashMap::new(); - prices.insert(1u8, gen_price_config(1, 12_000_000, 1_200_000)); - prices.insert(2u8, gen_price_config(2, 11_000_000, 1_100_000)); - prices.insert(3u8, gen_price_config(3, 10_000_000, 1_000_000)); - prices.insert(4u8, gen_price_config(4, 9_000_000, 900_000)); - prices.insert(5u8, gen_price_config(5, 8_000_000, 800_000)); - prices.insert(6u8, gen_price_config(6, 7_000_000, 700_000)); - prices.insert(7u8, gen_price_config(7, 6_000_000, 600_000)); - prices.insert(8u8, gen_price_config(8, 5_000_000, 500_000)); + prices.insert( + 1u8, + gen_price_config(1, ACCOUNT_PRICE_1_CHAR, ACCOUNT_PRICE_1_CHAR), + ); + prices.insert( + 2u8, + gen_price_config(2, ACCOUNT_PRICE_2_CHAR, ACCOUNT_PRICE_2_CHAR), + ); + prices.insert( + 3u8, + gen_price_config(3, ACCOUNT_PRICE_3_CHAR, ACCOUNT_PRICE_3_CHAR), + ); + prices.insert( + 4u8, + gen_price_config(4, ACCOUNT_PRICE_4_CHAR, ACCOUNT_PRICE_4_CHAR), + ); + prices.insert( + 5u8, + gen_price_config(5, ACCOUNT_PRICE_5_CHAR, ACCOUNT_PRICE_5_CHAR), + ); + prices.insert( + 6u8, + gen_price_config(6, ACCOUNT_PRICE_5_CHAR, ACCOUNT_PRICE_5_CHAR), + ); + prices.insert( + 7u8, + gen_price_config(7, ACCOUNT_PRICE_5_CHAR, ACCOUNT_PRICE_5_CHAR), + ); + prices.insert( + 8u8, + gen_price_config(8, ACCOUNT_PRICE_5_CHAR, ACCOUNT_PRICE_5_CHAR), + ); TemplateGenerator { header_deps: Vec::new(), @@ -340,6 +364,15 @@ impl TemplateGenerator { } } + pub fn get_price(&self, account_length: usize) -> &PriceConfig { + let key = if account_length > 8 { + 8u8 + } else { + account_length as u8 + }; + self.prices.get(&key).unwrap() + } + pub fn push_witness( &mut self, data_type: DataType, @@ -492,7 +525,7 @@ impl TemplateGenerator { fn gen_config_cell_account(&mut self) -> (Bytes, ConfigCellAccount) { let entity = ConfigCellAccount::new_builder() - .max_length(Uint32::from(20)) + .max_length(Uint32::from(42)) .basic_capacity(Uint64::from(ACCOUNT_BASIC_CAPACITY)) .prepared_fee_capacity(Uint64::from(ACCOUNT_PREPARED_FEE_CAPACITY)) .expiration_grace_period(Uint32::from(2_592_000)) @@ -548,7 +581,7 @@ impl TemplateGenerator { fn gen_config_cell_price(&mut self) -> (Bytes, ConfigCellPrice) { let discount_config = DiscountConfig::new_builder() - .invited_discount(Uint32::from(500)) + .invited_discount(Uint32::from(INVITED_DISCOUNT as u32)) .build(); let mut prices = PriceConfigList::new_builder(); @@ -881,10 +914,10 @@ impl TemplateGenerator { let index = (first_byte_of_account_hash % PRESERVED_ACCOUNT_CELL_COUNT) as usize; let config_type = das_util::preserved_accounts_group_to_data_type(index); - println!( - "The first byte of account hash is {:?}, so {:?} will be chosen.", - first_byte_of_account_hash, config_type - ); + // println!( + // "The first byte of account hash is {:?}, so {:?} will be chosen.", + // first_byte_of_account_hash, config_type + // ); let (cell_data, witness) = match self.gen_config_cell_preserved_account(config_type) { Some((cell_data, raw)) => (cell_data, das_util::wrap_raw_witness(config_type, raw)), @@ -917,7 +950,7 @@ impl TemplateGenerator { inviter_lock_args: &str, channel_lock_args: &str, quote: u64, - invited_discount: u32, + invited_discount: u64, created_at: u64, ) -> (Bytes, PreAccountCellData) { let account_chars_raw = account[..account.len() - 4] @@ -935,21 +968,35 @@ impl TemplateGenerator { let mut tmp = util::hex_to_bytes(&gen_das_lock_args(owner_lock_args, None)); tmp.append(&mut tmp.clone()); let owner_lock_args = Bytes::from(tmp); - let entity = PreAccountCellData::new_builder() + let mut entity_builder = PreAccountCellData::new_builder() .account(account_chars.to_owned()) .owner_lock_args(owner_lock_args) .refund_lock(gen_always_success_lock(refund_lock_args)) - .inviter_id(Bytes::from(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ])) - .inviter_lock(ScriptOpt::from(gen_always_success_lock(inviter_lock_args))) .channel_lock(ScriptOpt::from(gen_always_success_lock(channel_lock_args))) .price(price.to_owned()) .quote(Uint64::from(quote)) - .invited_discount(Uint32::from(invited_discount)) - .created_at(Timestamp::from(created_at)) - .build(); + .invited_discount(Uint32::from(invited_discount as u32)) + .created_at(Timestamp::from(created_at)); + + if inviter_lock_args.is_empty() { + entity_builder = entity_builder.inviter_lock(ScriptOpt::default()); + entity_builder = entity_builder.inviter_id(Bytes::default()); + } else { + entity_builder = entity_builder + .inviter_lock(ScriptOpt::from(gen_always_success_lock(inviter_lock_args))); + entity_builder = entity_builder.inviter_id(Bytes::from(vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ])) + } + + if channel_lock_args.is_empty() { + entity_builder = entity_builder.channel_lock(ScriptOpt::default()); + } else { + entity_builder = entity_builder + .channel_lock(ScriptOpt::from(gen_always_success_lock(channel_lock_args))); + } + let entity = entity_builder.build(); let id = util::account_to_id(account); let hash = Hash::try_from(blake2b_256(entity.as_slice()).to_vec()).unwrap(); diff --git a/tests/src/util/util.rs b/tests/src/util/util.rs index edbd2bb8..ec0fbd25 100644 --- a/tests/src/util/util.rs +++ b/tests/src/util/util.rs @@ -345,3 +345,27 @@ pub fn gen_timestamp(datetime: &str) -> u64 { let datetime = DateTime::::from_utc(navie_datetime, Utc); datetime.timestamp() as u64 } + +pub fn gen_register_fee(account_length: usize, has_inviter: bool) -> u64 { + let price_in_usd = match account_length { + 1 => ACCOUNT_PRICE_1_CHAR, + 2 => ACCOUNT_PRICE_2_CHAR, + 3 => ACCOUNT_PRICE_3_CHAR, + 4 => ACCOUNT_PRICE_4_CHAR, + _ => ACCOUNT_PRICE_5_CHAR, + }; + + let price_in_ckb = price_in_usd / CKB_QUOTE * 100_000_000; + + if has_inviter { + price_in_ckb * (RATE_BASE - INVITED_DISCOUNT) / RATE_BASE + + ACCOUNT_BASIC_CAPACITY + + ACCOUNT_PREPARED_FEE_CAPACITY + + (account_length as u64 + 4) * 100_000_000 + } else { + price_in_ckb + + ACCOUNT_BASIC_CAPACITY + + ACCOUNT_PREPARED_FEE_CAPACITY + + (account_length as u64 + 4) * 100_000_000 + } +} From 18195d21f2617b9893897d803216114280a3cd42 Mon Sep 17 00:00:00 2001 From: Link Date: Thu, 5 Aug 2021 16:57:44 +0800 Subject: [PATCH 4/4] chore: bump version --- Cargo.lock | 6 +++--- contracts/apply-register-cell-type/Cargo.toml | 2 +- contracts/pre-account-cell-type/Cargo.toml | 2 +- contracts/proposal-cell-type/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44aa20b6..f8f6c37c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,7 +66,7 @@ checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" [[package]] name = "apply-register-cell-type" -version = "1.0.0" +version = "1.0.1" dependencies = [ "ckb-std", "das-core", @@ -2126,7 +2126,7 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "pre-account-cell-type" -version = "1.0.0" +version = "1.1.0" dependencies = [ "chrono", "ckb-std", @@ -2182,7 +2182,7 @@ dependencies = [ [[package]] name = "proposal-cell-type" -version = "1.0.1" +version = "1.0.2" dependencies = [ "chrono", "ckb-std", diff --git a/contracts/apply-register-cell-type/Cargo.toml b/contracts/apply-register-cell-type/Cargo.toml index 9f01fc41..07adb2a3 100644 --- a/contracts/apply-register-cell-type/Cargo.toml +++ b/contracts/apply-register-cell-type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "apply-register-cell-type" -version = "1.0.0" +version = "1.0.1" edition = "2018" [features] diff --git a/contracts/pre-account-cell-type/Cargo.toml b/contracts/pre-account-cell-type/Cargo.toml index 40f903f5..ba5a3f84 100644 --- a/contracts/pre-account-cell-type/Cargo.toml +++ b/contracts/pre-account-cell-type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pre-account-cell-type" -version = "1.0.0" +version = "1.1.0" edition = "2018" [features] diff --git a/contracts/proposal-cell-type/Cargo.toml b/contracts/proposal-cell-type/Cargo.toml index 20fc8270..eb15323f 100644 --- a/contracts/proposal-cell-type/Cargo.toml +++ b/contracts/proposal-cell-type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "proposal-cell-type" -version = "1.0.1" +version = "1.0.2" edition = "2018" [features]