diff --git a/devnet/singularity/cluster_config.json b/devnet/singularity/cluster_config.json index 1c02c60a..0f0cb0ae 100644 --- a/devnet/singularity/cluster_config.json +++ b/devnet/singularity/cluster_config.json @@ -33,10 +33,10 @@ "ENABLE_GENERAL_NATIVE_TOKEN_TIMESTAMP": 0, "ROOT": { "MAX_STALE_ROOT_BLOCK_HEIGHT_DIFF": 22500, - "CONSENSUS_TYPE": "POW_SIMULATE", + "CONSENSUS_TYPE": "POW_ETHASH", "CONSENSUS_CONFIG": { "TARGET_BLOCK_TIME": 60, - "REMOTE_MINE": false + "REMOTE_MINE": true }, "GENESIS": { "VERSION": 0, @@ -44,15 +44,24 @@ "HASH_PREV_BLOCK": "0000000000000000000000000000000000000000000000000000000000000000", "HASH_MERKLE_ROOT": "0000000000000000000000000000000000000000000000000000000000000000", "TIMESTAMP": 1556639999, - "DIFFICULTY": 10000000000000, + "DIFFICULTY": 100000, "NONCE": 0 }, - "COINBASE_ADDRESS": "000000000000000000000000000000000000000000000000", + "COINBASE_ADDRESS": "a92885095A33E45A3C018Df7Aa6242B62Acb971800000000", "COINBASE_AMOUNT": 156000000000000000000, "DIFFICULTY_ADJUSTMENT_CUTOFF_TIME": 40, "DIFFICULTY_ADJUSTMENT_FACTOR": 1024, "EPOCH_INTERVAL": 525600, "POSW_CONFIG": { + "ENABLED": true, + "ENABLE_TIMESTAMP": 1646668800, + "DIFF_DIVIDER": 100, + "WINDOW_SIZE": 512, + "TOTAL_STAKE_PER_BLOCK": 10000000000000000000000, + "BOOST_TIMESTAMP": 1646978400, + "BOOST_MULTIPLIER_PER_STEP": 2, + "BOOST_STEPS": 10, + "BOOST_STEP_INTERVAL": 3600 } }, "CHAINS": [ @@ -81,6 +90,11 @@ "balances": { "QKC": 600000000000000000000000000 } + }, + "5C935469C5592Aeeac3372e922d9bCEabDF8830d00000000": { + "balances": { + "QKC": 600000000000000000000000000 + } } } }, @@ -351,7 +365,8 @@ } ], "REWARD_TAX_RATE": 0.5, - "BLOCK_REWARD_DECAY_FACTOR": 0.88 + "BLOCK_REWARD_DECAY_FACTOR": 0.88, + "ROOT_CHAIN_POSW_CONTRACT_BYTECODE_HASH": "ee90e568da573f251d63256e843add8bd7a27cec1f4c2a06ef20380be68df0a3" }, "MASTER": { "MASTER_TO_SLAVE_CONNECT_RETRY_DELAY": 1.0 diff --git a/mainnet/singularity/cluster_config_template.json b/mainnet/singularity/cluster_config_template.json index 4a93b795..698938f3 100644 --- a/mainnet/singularity/cluster_config_template.json +++ b/mainnet/singularity/cluster_config_template.json @@ -89,7 +89,11 @@ "ENABLE_TIMESTAMP": 1569567600, "DIFF_DIVIDER": 10000, "WINDOW_SIZE": 512, - "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000 + "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000, + "BOOST_TIMESTAMP": 1646064000, + "BOOST_MULTIPLIER_PER_STEP": 2, + "BOOST_STEPS": 10, + "BOOST_STEP_INTERVAL": 172800 } }, "CHAINS": [ diff --git a/quarkchain/cluster/master.py b/quarkchain/cluster/master.py index da26ac12..e4ce6527 100644 --- a/quarkchain/cluster/master.py +++ b/quarkchain/cluster/master.py @@ -1459,7 +1459,7 @@ async def get_stats(self): shard["poswEnabled"] = config.ENABLED shard["poswMinStake"] = config.TOTAL_STAKE_PER_BLOCK shard["poswWindowSize"] = config.WINDOW_SIZE - shard["difficultyDivider"] = config.DIFF_DIVIDER + shard["difficultyDivider"] = config.get_diff_divider(shard_stats.timestamp) shards.append(shard) shards.sort(key=lambda x: x["fullShardId"]) @@ -1685,7 +1685,7 @@ async def get_work( check(isinstance(block, RootBlock)) posw_mineable = await self.posw_mineable(block) config = self.env.quark_chain_config.ROOT.POSW_CONFIG - return work, config.DIFF_DIVIDER if posw_mineable else None + return work, config.get_diff_divider(block.header.create_time) if posw_mineable else None if branch.value not in self.branch_to_slaves: return None, None diff --git a/quarkchain/cluster/posw.py b/quarkchain/cluster/posw.py index f0d3edac..109bac83 100644 --- a/quarkchain/cluster/posw.py +++ b/quarkchain/cluster/posw.py @@ -82,7 +82,7 @@ def get_posw_info( diff = header.difficulty ret = lambda success: PoSWInfo( - diff // config.DIFF_DIVIDER if success else diff, + diff // config.get_diff_divider(header.create_time) if success else diff, block_threshold, # mined blocks should include current one, assuming success posw_mined_blocks=cnt + 1, diff --git a/quarkchain/cluster/shard.py b/quarkchain/cluster/shard.py index c203cd20..feb85435 100644 --- a/quarkchain/cluster/shard.py +++ b/quarkchain/cluster/shard.py @@ -406,7 +406,7 @@ def __validate_block_headers(self, block_header_list: List[MinorBlockHeader]): consensus_type = shard_config.CONSENSUS_TYPE diff = header.difficulty if shard_config.POSW_CONFIG.ENABLED: - diff //= shard_config.POSW_CONFIG.DIFF_DIVIDER + diff //= shard_config.POSW_CONFIG.get_diff_divider(header.create_time) validate_seal( header, consensus_type, diff --git a/quarkchain/cluster/tests/test_cluster.py b/quarkchain/cluster/tests/test_cluster.py index 2f23005f..eb76458e 100644 --- a/quarkchain/cluster/tests/test_cluster.py +++ b/quarkchain/cluster/tests/test_cluster.py @@ -2502,6 +2502,7 @@ def add_root_block(addr, sign=False): qkc_config.ROOT.POSW_CONFIG.WINDOW_SIZE = 2 # should always pass pow check if posw is applied qkc_config.ROOT.POSW_CONFIG.DIFF_DIVIDER = 1000000 + qkc_config.ROOT.POSW_CONFIG.BOOST_TIMESTAMP = 0 shard = next(iter(clusters[0].slave_list[0].shards.values())) # monkey patch staking results diff --git a/quarkchain/config.py b/quarkchain/config.py index 2e4054be..c67ca71b 100644 --- a/quarkchain/config.py +++ b/quarkchain/config.py @@ -118,6 +118,21 @@ class POSWConfig(BaseConfig): # TODO: needs better tuning / estimating # = total stakes / alpha TOTAL_STAKE_PER_BLOCK = (10 ** 9) * QUARKSH_TO_JIAOZI + BOOST_TIMESTAMP = 0 # 0 mean Disable + BOOST_MULTIPLIER_PER_STEP = 2 + BOOST_STEPS = 10 + BOOST_STEP_INTERVAL = 43200 + + def get_diff_divider(self, block_timestamp): + diff_divider = self.DIFF_DIVIDER + if 0 < self.BOOST_TIMESTAMP < block_timestamp: + steps = (block_timestamp - self.BOOST_TIMESTAMP) // self.BOOST_STEP_INTERVAL + 1 + if steps > self.BOOST_STEPS: + steps = self.BOOST_STEPS + + diff_divider = self.DIFF_DIVIDER * pow(self.BOOST_MULTIPLIER_PER_STEP, steps) + + return diff_divider class ChainConfig(BaseConfig): @@ -251,6 +266,10 @@ def __init__(self): self.POSW_CONFIG.WINDOW_SIZE = 4320 # 72 hours self.POSW_CONFIG.DIFF_DIVIDER = 1000 self.POSW_CONFIG.TOTAL_STAKE_PER_BLOCK = 240000 * QUARKSH_TO_JIAOZI + self.POSW_CONFIG.BOOST_TIMESTAMP = 0 + self.POSW_CONFIG.BOOST_MULTIPLIER_PER_STEP = 2 + self.POSW_CONFIG.BOOST_STEPS = 10 + self.POSW_CONFIG.BOOST_STEP_INTERVAL = 172800 def to_dict(self): ret = super().to_dict() diff --git a/quarkchain/tests/test_config.py b/quarkchain/tests/test_config.py index f82b7837..4b195a61 100644 --- a/quarkchain/tests/test_config.py +++ b/quarkchain/tests/test_config.py @@ -77,7 +77,11 @@ def test_serialization(self): "ENABLE_TIMESTAMP": 0, "DIFF_DIVIDER": 1000, "WINDOW_SIZE": 4320, - "TOTAL_STAKE_PER_BLOCK": 240000000000000000000000 + "TOTAL_STAKE_PER_BLOCK": 240000000000000000000000, + "BOOST_TIMESTAMP": 0, + "BOOST_MULTIPLIER_PER_STEP": 2, + "BOOST_STEPS": 10, + "BOOST_STEP_INTERVAL": 172800 } }, "CHAINS": [ @@ -115,7 +119,11 @@ def test_serialization(self): "ENABLE_TIMESTAMP": 0, "DIFF_DIVIDER": 20, "WINDOW_SIZE": 256, - "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000000 + "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000000, + "BOOST_TIMESTAMP": 0, + "BOOST_MULTIPLIER_PER_STEP": 2, + "BOOST_STEPS": 10, + "BOOST_STEP_INTERVAL": 43200 }, "MAX_MINOR_BLOCKS_IN_MEMORY": 1536 }, @@ -153,7 +161,11 @@ def test_serialization(self): "ENABLE_TIMESTAMP": 0, "DIFF_DIVIDER": 20, "WINDOW_SIZE": 256, - "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000000 + "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000000, + "BOOST_TIMESTAMP": 0, + "BOOST_MULTIPLIER_PER_STEP": 2, + "BOOST_STEPS": 10, + "BOOST_STEP_INTERVAL": 43200 }, "MAX_MINOR_BLOCKS_IN_MEMORY": 1536 }, @@ -191,7 +203,11 @@ def test_serialization(self): "ENABLE_TIMESTAMP": 0, "DIFF_DIVIDER": 20, "WINDOW_SIZE": 256, - "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000000 + "TOTAL_STAKE_PER_BLOCK": 1000000000000000000000000000, + "BOOST_TIMESTAMP": 0, + "BOOST_MULTIPLIER_PER_STEP": 2, + "BOOST_STEPS": 10, + "BOOST_STEP_INTERVAL": 43200 }, "MAX_MINOR_BLOCKS_IN_MEMORY": 1536 } @@ -323,3 +339,21 @@ def test_special_contract_enable_ts(self): env.cluster_config = cluster_config for addr in PRECOMPILED_CONTRACTS_AFTER_EVM_ENABLED: self.assertEqual(specials[addr][1], 123) + + def test_get_diff_divider(self): + block_timestamp = 1646064000 + config = QuarkChainConfig().ROOT.POSW_CONFIG + config.BOOST_TIMESTAMP = 0 + self.assertEqual(config.DIFF_DIVIDER, config.get_diff_divider(block_timestamp)) + config.BOOST_TIMESTAMP = block_timestamp + 1 + self.assertEqual(config.DIFF_DIVIDER, config.get_diff_divider(block_timestamp)) + config.BOOST_TIMESTAMP = block_timestamp - 1 + self.assertEqual(config.DIFF_DIVIDER * config.BOOST_MULTIPLIER_PER_STEP, + config.get_diff_divider(block_timestamp)) + config.BOOST_TIMESTAMP = block_timestamp - config.BOOST_STEP_INTERVAL * config.BOOST_STEPS + 1 + self.assertEqual(config.DIFF_DIVIDER * pow(config.BOOST_MULTIPLIER_PER_STEP, config.BOOST_STEPS), + config.get_diff_divider(block_timestamp)) + config.BOOST_TIMESTAMP = block_timestamp - config.BOOST_STEP_INTERVAL * config.BOOST_STEPS - 1 + self.assertEqual(config.DIFF_DIVIDER * pow(config.BOOST_MULTIPLIER_PER_STEP, config.BOOST_STEPS), + config.get_diff_divider(block_timestamp)) +