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]