From 84d4bf95a37ecda4eddf17237922845bc6ec6c5e Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Fri, 11 Aug 2023 16:43:50 +0800 Subject: [PATCH 1/8] Consensus: let `epoch_duration_target` affect epoch length Signed-off-by: Eval EXEC --- spec/src/consensus.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/src/consensus.rs b/spec/src/consensus.rs index 4f39d87a77..0bbf219b33 100644 --- a/spec/src/consensus.rs +++ b/spec/src/consensus.rs @@ -804,6 +804,13 @@ impl Consensus { let remainder_reward = Capacity::shannons(primary_epoch_reward % epoch.length()); + let mut next_epoch_length = epoch.length(); + let epoch_length_from_param = + cmp::max(self.epoch_duration_target() / MIN_BLOCK_INTERVAL, 1); + if next_epoch_length != epoch_length_from_param { + next_epoch_length = self.epoch_duration_target() / MIN_BLOCK_INTERVAL; + } + let dummy_epoch_ext = epoch .clone() .into_builder() @@ -812,6 +819,7 @@ impl Consensus { .number(epoch.number() + 1) .last_block_hash_in_previous_epoch(header.hash()) .start_number(header.number() + 1) + .length(next_epoch_length) .build(); NextBlockEpoch::HeadBlock(dummy_epoch_ext) } else { From c07182f718579599f9d511ea8d2fdaf04ce0a4fe Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Fri, 11 Aug 2023 17:38:46 +0800 Subject: [PATCH 2/8] Consensus: neat epoch_length calculation in permanent difficulty mode Co-authored-by: Quake Wang --- spec/src/consensus.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/spec/src/consensus.rs b/spec/src/consensus.rs index 0bbf219b33..b3e1e3b9b2 100644 --- a/spec/src/consensus.rs +++ b/spec/src/consensus.rs @@ -804,12 +804,7 @@ impl Consensus { let remainder_reward = Capacity::shannons(primary_epoch_reward % epoch.length()); - let mut next_epoch_length = epoch.length(); - let epoch_length_from_param = - cmp::max(self.epoch_duration_target() / MIN_BLOCK_INTERVAL, 1); - if next_epoch_length != epoch_length_from_param { - next_epoch_length = self.epoch_duration_target() / MIN_BLOCK_INTERVAL; - } +let next_epoch_length = (self.epoch_duration_target() + MIN_BLOCK_INTERVAL - 1) / MIN_BLOCK_INTERVAL let dummy_epoch_ext = epoch .clone() From 6e572ef0f4ae890a6faa8574fd4a0033aca4403b Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Fri, 11 Aug 2023 17:39:26 +0800 Subject: [PATCH 3/8] Fix fmt --- spec/src/consensus.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/src/consensus.rs b/spec/src/consensus.rs index b3e1e3b9b2..776447aef0 100644 --- a/spec/src/consensus.rs +++ b/spec/src/consensus.rs @@ -804,7 +804,9 @@ impl Consensus { let remainder_reward = Capacity::shannons(primary_epoch_reward % epoch.length()); -let next_epoch_length = (self.epoch_duration_target() + MIN_BLOCK_INTERVAL - 1) / MIN_BLOCK_INTERVAL + let next_epoch_length = (self.epoch_duration_target() + MIN_BLOCK_INTERVAL + - 1) + / MIN_BLOCK_INTERVAL; let dummy_epoch_ext = epoch .clone() From 7364dfbc382236a7fa0c47d89736881944b7b2d6 Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Thu, 10 Aug 2023 20:44:05 +0800 Subject: [PATCH 4/8] Test: Add bats test for `epoch_length_in_dummy` param Signed-off-by: Eval EXEC --- util/app-config/src/tests/cli_test.sh | 9 +- .../tests/later_bats_job/change_epoch.bats | 118 ++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 util/app-config/src/tests/later_bats_job/change_epoch.bats diff --git a/util/app-config/src/tests/cli_test.sh b/util/app-config/src/tests/cli_test.sh index 707b2b1dea..967e5c60e4 100755 --- a/util/app-config/src/tests/cli_test.sh +++ b/util/app-config/src/tests/cli_test.sh @@ -13,6 +13,7 @@ trap cleanup EXIT cp target/release/ckb ${CKB_BATS_TESTBED} cp util/app-config/src/tests/*.bats ${CKB_BATS_TESTBED} +cp -r util/app-config/src/tests/later_bats_job ${CKB_BATS_TESTBED} cp util/app-config/src/tests/*.sh ${CKB_BATS_TESTBED} if [ ! -d "/tmp/ckb_bats_assets/" ]; then @@ -47,9 +48,15 @@ export TMP_DIR=${CKB_BATS_TESTBED}/tmp_dir mkdir ${TMP_DIR} for bats_cases in *.bats; do - bats "$bats_cases" + bats --verbose-run --print-output-on-failure --show-output-of-passing-tests "$bats_cases" ret=$? if [ "$ret" -ne "0" ]; then exit "$ret" fi done + +bats --verbose-run --print-output-on-failure --show-output-of-passing-tests ./later_bats_job/change_epoch.bats +ret=$? +if [ "$ret" -ne "0" ]; then + exit "$ret" +fi diff --git a/util/app-config/src/tests/later_bats_job/change_epoch.bats b/util/app-config/src/tests/later_bats_job/change_epoch.bats new file mode 100644 index 0000000000..87cca69126 --- /dev/null +++ b/util/app-config/src/tests/later_bats_job/change_epoch.bats @@ -0,0 +1,118 @@ +#!/usr/bin/env bats +set -e + +bats_load_library 'bats-assert' +bats_load_library 'bats-support' + +NUMBER_OFFSET=0 +NUMBER_BITS=24 +NUMBER_MAXIMUM_VALUE=$((1 << NUMBER_BITS)) +NUMBER_MASK=$((NUMBER_MAXIMUM_VALUE - 1)) + +INDEX_OFFSET=$((NUMBER_BITS)) +INDEX_BITS=16 +INDEX_MAXIMUM_VALUE=$((1 << INDEX_BITS)) +INDEX_MASK=$((INDEX_MAXIMUM_VALUE - 1)) + +LENGTH_OFFSET=$((NUMBER_BITS + INDEX_BITS)) +LENGTH_BITS=16 +LENGTH_MAXIMUM_VALUE=$((1 << LENGTH_BITS)) +LENGTH_MASK=$((LENGTH_MAXIMUM_VALUE - 1)) + +function extract_epoch_number() { + local value=$1 + echo $(( (value >> NUMBER_OFFSET) & NUMBER_MASK )) +} + +function extract_epoch_index() { + local value=$1 + echo $(( (value >> INDEX_OFFSET) & INDEX_MASK )) +} + +function extract_epoch_length() { + local value=$1 + echo $(( (value >> LENGTH_OFFSET) & LENGTH_MASK )) +} + +function tip_header_epoch() { + curl -s -X POST http://127.0.0.1:8114 \ + -H 'Content-Type: application/json' \ + -d '{ "id": 42, "jsonrpc": "2.0", "method": "get_tip_header", "params": [ ] }' \ + | jq .result.epoch | xargs -I{} printf "%d\n" {} +} + +function tip_header_number() { + curl -s -X POST http://127.0.0.1:8114 \ + -H 'Content-Type: application/json' \ + -d '{ "id": 42, "jsonrpc": "2.0", "method": "get_tip_header", "params": [ ] }' \ + | jq .result.number | xargs -I{} printf "%d\n" {} +} + +function block_kill() { + kill $1 + while kill -0 $1; do + echo "waiting for $1 to exit" + sleep 1 + done +} + +function ckb_change_epoch_length_for_dumm_mode { #@test + ckb run -C ${CKB_DIRNAME} &> /dev/null & + + CKB_NODE_PID=$! + sleep 5 + + + TIP_EPOCH=$(tip_header_epoch) + + TIP_EPOCH_NUMBER=$(extract_epoch_number ${TIP_EPOCH}) + TIP_EPOCH_INDEX=$(extract_epoch_index ${TIP_EPOCH}) + TIP_EPOCH_LENGTH=$(extract_epoch_length ${TIP_EPOCH}) + TIP_NUMBER=$(tip_header_number) + + echo tip_number is ${TIP_NUMBER} + echo tip_epoch_number is ${TIP_EPOCH_NUMBER}, tip_epoch_index is ${TIP_EPOCH_INDEX}, tip_epoch_length is ${TIP_EPOCH_LENGTH} + + block_kill ${CKB_NODE_PID} + + wget https://raw.githubusercontent.com/nervosnetwork/ckb/develop/resource/specs/mainnet.toml + + ckb init -c dev --import-spec mainnet.toml --force + + sed -i 's/Eaglesong/Dummy/g' specs/dev.toml + sed -i '/genesis_epoch_length = 1743/a permanent_difficulty_in_dummy = true\nepoch_duration_target = 80\n' specs/dev.toml + + sed -i 's/poll_interval = 1000/poll_interval = 1/g' ckb-miner.toml + sed -i 's/value = 5000/value = 1/g' ckb-miner.toml + + sed -i 's/# \[block_assembler\]/\[block_assembler\]/g' ckb.toml + sed -i 's/# code_hash =/code_hash =/g' ckb.toml + sed -i 's/# args = "ckb-cli util blake2b --prefix-160 "/args = "0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7"/g' ckb.toml + sed -i 's/# hash_type =/hash_type =/g' ckb.toml + sed -i 's/# message = "A 0x-prefixed hex string"/message = "0x"/g' ckb.toml + + + + ckb run --skip-spec-check --overwrite-spec -C ${CKB_DIRNAME} &> /dev/null & + CKB_NODE_PID=$! + + ckb miner -C ${CKB_DIRNAME} &> /dev/null & + CKB_MINER_PID=$! + + sleep 5 + + while [ $(tip_header_number) -lt $(( ${TIP_NUMBER} + ${TIP_EPOCH_LENGTH} )) ]; do + echo waiting for tip_number to be $(( ${TIP_NUMBER} + ${TIP_EPOCH_LENGTH} )) + sleep 1 + done + + echo latest tip_header_number is $(tip_header_number) + echo latest tip_header_epoch length is $(extract_epoch_length $(tip_header_epoch)) + echo latest tip_header_epoch number is $(extract_epoch_number $(tip_header_epoch)) + + # we specified epoch_duration_target = 80 in dev.toml, so the epoch length should be 10 + assert [ $(extract_epoch_length $(tip_header_epoch)) -eq 10 ] + + block_kill ${CKB_NODE_PID} + block_kill ${CKB_MINER_PID} +} From 219eb75ae49d28a2d9036da4707fba5a7855ce30 Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Thu, 10 Aug 2023 20:52:30 +0800 Subject: [PATCH 5/8] chore: bats test should use `make prod` --- .github/workflows/ci_integration_tests_ubuntu.yaml | 2 +- Makefile | 2 +- util/app-config/src/tests/cli_test.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_integration_tests_ubuntu.yaml b/.github/workflows/ci_integration_tests_ubuntu.yaml index 4af026b40b..467ea84cbc 100644 --- a/.github/workflows/ci_integration_tests_ubuntu.yaml +++ b/.github/workflows/ci_integration_tests_ubuntu.yaml @@ -93,7 +93,7 @@ jobs: - uses: actions/checkout@v3 - name: build ckb and run bats cli test run: | - make build + make prod make cli-test shell: bash env: diff --git a/Makefile b/Makefile index 7d7adb98fb..199a045172 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ doc-test: ## Run doc tests cargo test --all --doc .PHONY: cli-test -cli-test: build # Run ckb command line usage bats test +cli-test: prod # Run ckb command line usage bats test ./util/app-config/src/tests/cli_test.sh .PHONY: test diff --git a/util/app-config/src/tests/cli_test.sh b/util/app-config/src/tests/cli_test.sh index 967e5c60e4..fb592bc5b6 100755 --- a/util/app-config/src/tests/cli_test.sh +++ b/util/app-config/src/tests/cli_test.sh @@ -11,7 +11,7 @@ function cleanup { trap cleanup EXIT -cp target/release/ckb ${CKB_BATS_TESTBED} +cp target/prod/ckb ${CKB_BATS_TESTBED} cp util/app-config/src/tests/*.bats ${CKB_BATS_TESTBED} cp -r util/app-config/src/tests/later_bats_job ${CKB_BATS_TESTBED} cp util/app-config/src/tests/*.sh ${CKB_BATS_TESTBED} From c9068ab02f930b970c26250632a4fa33cc7b87ec Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Mon, 14 Aug 2023 11:10:56 +0800 Subject: [PATCH 6/8] Fix `WithdrawDAO` usage of `epoch_duration_target` --- test/src/specs/dao/dao_tx.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/specs/dao/dao_tx.rs b/test/src/specs/dao/dao_tx.rs index ac4c8d1f4b..1026866542 100644 --- a/test/src/specs/dao/dao_tx.rs +++ b/test/src/specs/dao/dao_tx.rs @@ -12,7 +12,7 @@ pub struct WithdrawDAO; impl Spec for WithdrawDAO { fn modify_chain_spec(&self, spec: &mut ckb_chain_spec::ChainSpec) { spec.params.genesis_epoch_length = Some(2); - spec.params.epoch_duration_target = Some(2); + spec.params.epoch_duration_target = Some(16); spec.params.permanent_difficulty_in_dummy = Some(true); } From 459e9fff1546b42db2cc7e628151431aeebf7dfd Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Mon, 14 Aug 2023 11:11:32 +0800 Subject: [PATCH 7/8] Fix `epoch_duration_target` usages in integration tests --- test/src/specs/dao/dao_tx.rs | 2 +- test/src/specs/dao/satoshi_dao_occupied.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/src/specs/dao/dao_tx.rs b/test/src/specs/dao/dao_tx.rs index 1026866542..64eec88332 100644 --- a/test/src/specs/dao/dao_tx.rs +++ b/test/src/specs/dao/dao_tx.rs @@ -40,7 +40,7 @@ pub struct WithdrawDAOWithOverflowCapacity; impl Spec for WithdrawDAOWithOverflowCapacity { fn modify_chain_spec(&self, spec: &mut ckb_chain_spec::ChainSpec) { spec.params.genesis_epoch_length = Some(2); - spec.params.epoch_duration_target = Some(2); + spec.params.epoch_duration_target = Some(16); spec.params.permanent_difficulty_in_dummy = Some(true); } diff --git a/test/src/specs/dao/satoshi_dao_occupied.rs b/test/src/specs/dao/satoshi_dao_occupied.rs index d56d83b2c4..5756d25ceb 100644 --- a/test/src/specs/dao/satoshi_dao_occupied.rs +++ b/test/src/specs/dao/satoshi_dao_occupied.rs @@ -46,7 +46,7 @@ impl Spec for DAOWithSatoshiCellOccupied { let satoshi_cell = issue_satoshi_cell(); spec.genesis.issued_cells.push(satoshi_cell); spec.params.genesis_epoch_length = Some(2); - spec.params.epoch_duration_target = Some(2); + spec.params.epoch_duration_target = Some(16); spec.params.permanent_difficulty_in_dummy = Some(true); } } @@ -142,7 +142,7 @@ impl Spec for SpendSatoshiCell { spec.genesis.issued_cells.push(issue_satoshi_cell()); spec.genesis.satoshi_gift.satoshi_cell_occupied_ratio = satoshi_cell_occupied_ratio; spec.params.genesis_epoch_length = Some(2); - spec.params.epoch_duration_target = Some(2); + spec.params.epoch_duration_target = Some(16); spec.params.permanent_difficulty_in_dummy = Some(true); } } From f0ab0a168342d3961c3cb65cd51257613f040f2f Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Tue, 15 Aug 2023 14:20:10 +0800 Subject: [PATCH 8/8] Fix integration test for `epoch_duration_target` --- test/src/specs/hardfork/v2021/since.rs | 2 ++ test/src/specs/hardfork/v2023/vm_version2.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/test/src/specs/hardfork/v2021/since.rs b/test/src/specs/hardfork/v2021/since.rs index 2953c11fa8..527c599ba4 100644 --- a/test/src/specs/hardfork/v2021/since.rs +++ b/test/src/specs/hardfork/v2021/since.rs @@ -78,6 +78,7 @@ impl Spec for CheckAbsoluteEpochSince { fn modify_chain_spec(&self, spec: &mut ckb_chain_spec::ChainSpec) { spec.params.permanent_difficulty_in_dummy = Some(true); spec.params.genesis_epoch_length = Some(GENESIS_EPOCH_LENGTH); + spec.params.epoch_duration_target = Some(8 * GENESIS_EPOCH_LENGTH); } } @@ -113,6 +114,7 @@ impl Spec for CheckRelativeEpochSince { fn modify_chain_spec(&self, spec: &mut ckb_chain_spec::ChainSpec) { spec.params.permanent_difficulty_in_dummy = Some(true); spec.params.genesis_epoch_length = Some(GENESIS_EPOCH_LENGTH); + spec.params.epoch_duration_target = Some(8 * GENESIS_EPOCH_LENGTH); } } diff --git a/test/src/specs/hardfork/v2023/vm_version2.rs b/test/src/specs/hardfork/v2023/vm_version2.rs index adbc3258c5..43d5406b39 100644 --- a/test/src/specs/hardfork/v2023/vm_version2.rs +++ b/test/src/specs/hardfork/v2023/vm_version2.rs @@ -97,6 +97,7 @@ impl Spec for CheckVmVersion2 { fn modify_chain_spec(&self, spec: &mut ckb_chain_spec::ChainSpec) { spec.params.permanent_difficulty_in_dummy = Some(true); spec.params.genesis_epoch_length = Some(GENESIS_EPOCH_LENGTH); + spec.params.epoch_duration_target = Some(8 * GENESIS_EPOCH_LENGTH); if spec.params.hardfork.is_none() { spec.params.hardfork = Some(Default::default()); }