Skip to content

Quarkchain: Root chain support POSW stake DecayByHeightAndTime #959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mainnet/singularity/cluster_config_bootnodes.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"ENABLE_NON_RESERVED_NATIVE_TOKEN_TIMESTAMP": 1588291200,
"ENABLE_GENERAL_NATIVE_TOKEN_TIMESTAMP": 1588291200,
"ENABLE_POSW_STAKING_DECAY_TIMESTAMP": 1588291200,
"ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP": 1746060000,
"TX_WHITELIST_SENDERS": [
"b8C082828F51343299c9A4deEb2503AaC3bA074f",
"3391A1796cB98D79A2Fde326F375DF900C959Ed0",
Expand Down
1 change: 1 addition & 0 deletions mainnet/singularity/cluster_config_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"ENABLE_NON_RESERVED_NATIVE_TOKEN_TIMESTAMP": 1588291200,
"ENABLE_GENERAL_NATIVE_TOKEN_TIMESTAMP": 1588291200,
"ENABLE_POSW_STAKING_DECAY_TIMESTAMP": 1588291200,
"ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP": 1746060000,
"TX_WHITELIST_SENDERS": [
"b8C082828F51343299c9A4deEb2503AaC3bA074f",
"3391A1796cB98D79A2Fde326F375DF900C959Ed0",
Expand Down
1 change: 1 addition & 0 deletions mainnet/singularity/cluster_config_template_8nodes.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"ENABLE_NON_RESERVED_NATIVE_TOKEN_TIMESTAMP": 1588291200,
"ENABLE_GENERAL_NATIVE_TOKEN_TIMESTAMP": 1588291200,
"ENABLE_POSW_STAKING_DECAY_TIMESTAMP": 1588291200,
"ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP": 1746060000,
"TX_WHITELIST_SENDERS": [
"b8C082828F51343299c9A4deEb2503AaC3bA074f",
"3391A1796cB98D79A2Fde326F375DF900C959Ed0",
Expand Down
21 changes: 20 additions & 1 deletion quarkchain/cluster/root_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,10 +659,29 @@ def get_posw_info(
if block.header.height == 0: # genesis
return None
config = self.root_config.POSW_CONFIG # type: POSWConfig
stake_per_block = config.TOTAL_STAKE_PER_BLOCK
enable_decay_ts = (
self.env.quark_chain_config.ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP
)
if enable_decay_ts is not None and block.header.create_time > enable_decay_ts:
stake_per_block = self.__decay_by_epoch(stake_per_block, block.header.height)
block_cnt = get_posw_coinbase_blockcnt(
config.WINDOW_SIZE,
self.coinbase_addr_cache,
block.header.hash_prev_block,
self.db.get_root_block_header_by_hash,
)
return get_posw_info(config, block.header, stakes, block_cnt, signer=signer)
return get_posw_info(config, block.header, stakes, block_cnt, stake_per_block, signer=signer)

def __decay_by_epoch(self, value: int, block_height: int):
epoch = (
block_height
// self.env.quark_chain_config.ROOT.EPOCH_INTERVAL
)
decay_numerator = (
self.env.quark_chain_config.block_reward_decay_factor.numerator ** epoch
)
decay_denominator = (
self.env.quark_chain_config.block_reward_decay_factor.denominator ** epoch
)
return value * decay_numerator // decay_denominator
31 changes: 31 additions & 0 deletions quarkchain/cluster/tests/test_root_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from quarkchain.cluster.root_state import RootState
from quarkchain.cluster.shard_state import ShardState
from quarkchain.cluster.tests.test_utils import get_test_env
from quarkchain.config import ConsensusType
from quarkchain.core import Address
from quarkchain.core import CrossShardTransactionList
from quarkchain.diff import EthDifficultyCalculator
Expand Down Expand Up @@ -717,3 +718,33 @@ def test_root_coinbase_decay(self):
* env.quark_chain_config.BLOCK_REWARD_DECAY_FACTOR ** 2
},
)

def test_root_posw_stake_by_block_decay_by_epoch(self):
acc_byte = b"\x01" * 20
acc = Address(acc_byte, full_shard_key=0)
env = get_test_env(genesis_account=acc, genesis_minor_quarkash=200)
r_state, s_states = create_default_state(env)
env.quark_chain_config.ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP = 100

r_state.root_config.CONSENSUS_TYPE = ConsensusType.POW_DOUBLESHA256
r_state.root_config.EPOCH_INTERVAL = 525600
r_state.root_config.POSW_CONFIG.TOTAL_STAKE_PER_BLOCK = 100
r_state.root_config.POSW_CONFIG.WINDOW_SIZE = 512
r_state.root_config.POSW_CONFIG.ENABLED = True

# created time is greater than threshold
b1 = r_state.get_tip_block().create_block_to_append(create_time=101, address=acc)
posw_info = r_state.get_posw_info(b1, 200, acc_byte)
# 200 qkc with 100 required per block, should equal 2 mineable blocks
self.assertIsNotNone(posw_info)
self.assertEqual(posw_info.posw_mineable_blocks, 200 / 100)

# decay (factor = 0.5) should kick in and double mineable blocks
b1.header.height = r_state.root_config.EPOCH_INTERVAL
posw_info = r_state.get_posw_info(b1, 200, acc_byte)
self.assertEqual(posw_info.posw_mineable_blocks, 200 / (100 / 2))

# no effect before the enable timestamp
b1.header.create_time = 99
posw_info = r_state.get_posw_info(b1, 200, acc_byte)
self.assertEqual(posw_info.posw_mineable_blocks, 200 / 100)
1 change: 1 addition & 0 deletions quarkchain/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ class QuarkChainConfig(BaseConfig):
ENABLE_NON_RESERVED_NATIVE_TOKEN_TIMESTAMP = None
ENABLE_GENERAL_NATIVE_TOKEN_TIMESTAMP = None
ENABLE_POSW_STAKING_DECAY_TIMESTAMP = None
ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP = None

MIN_TX_POOL_GAS_PRICE = 10 ** 9 # lowest gas price to accept, default 1 Gwei
MIN_MINING_GAS_PRICE = 10 ** 9 # lowest gas price to pack tx for mining, 1 Gwei
Expand Down
1 change: 1 addition & 0 deletions quarkchain/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
MAINNET_ENABLE_NON_RESERVED_NATIVE_TOKEN_CONTRACT_TIMESTAMP = 1588291200
MAINNET_ENABLE_GENERAL_NATIVE_TOKEN_CONTRACT_TIMESTAMP = 1588291200
MAINNET_ENABLE_POSW_STAKING_DECAY_TIMESTAMP = 1588291200
MAINNET_ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP = 1746060000 # 2025-05-01 08:40:00
MAINNET_ENABLE_EIP155_SIGNER_TIMESTAMP = 1625097600
MAINNET_BASE_ETH_CHAIN_ID = 100000

Expand Down
8 changes: 8 additions & 0 deletions quarkchain/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
MAINNET_ENABLE_NON_RESERVED_NATIVE_TOKEN_CONTRACT_TIMESTAMP,
MAINNET_ENABLE_GENERAL_NATIVE_TOKEN_CONTRACT_TIMESTAMP,
MAINNET_ENABLE_POSW_STAKING_DECAY_TIMESTAMP,
MAINNET_ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP,
MAINNET_ENABLE_EIP155_SIGNER_TIMESTAMP,
MAINNET_BASE_ETH_CHAIN_ID,
)
Expand Down Expand Up @@ -96,6 +97,13 @@ def cluster_config(self, c):
c.QUARKCHAIN.ENABLE_POSW_STAKING_DECAY_TIMESTAMP = (
MAINNET_ENABLE_POSW_STAKING_DECAY_TIMESTAMP
)
if (
c.QUARKCHAIN.ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP is None
and c.QUARKCHAIN.NETWORK_ID == 1
):
c.QUARKCHAIN.ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP = (
MAINNET_ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP
)
if (
c.QUARKCHAIN.ENABLE_EIP155_SIGNER_TIMESTAMP is None
and c.QUARKCHAIN.NETWORK_ID == 1
Expand Down
1 change: 1 addition & 0 deletions quarkchain/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ def test_serialization(self):
"ENABLE_NON_RESERVED_NATIVE_TOKEN_TIMESTAMP": null,
"ENABLE_GENERAL_NATIVE_TOKEN_TIMESTAMP": null,
"ENABLE_POSW_STAKING_DECAY_TIMESTAMP": null,
"ENABLE_ROOT_POSW_STAKING_DECAY_TIMESTAMP": null,
"MIN_TX_POOL_GAS_PRICE": 1000000000,
"MIN_MINING_GAS_PRICE": 1000000000,
"XSHARD_GAS_DDOS_FIX_ROOT_HEIGHT": 90000,
Expand Down