diff --git a/builtin-contract/system-contract/contracts/metadata/Metadata.sol b/builtin-contract/system-contract/contracts/metadata/Metadata.sol index dc4d1b117..02c9e467f 100644 --- a/builtin-contract/system-contract/contracts/metadata/Metadata.sol +++ b/builtin-contract/system-contract/contracts/metadata/Metadata.sol @@ -38,6 +38,7 @@ library MetadataType { uint64 max_tx_size; uint64 gas_limit; uint64 interval; + uint64 max_contract_limit; } struct CkbRelatedInfo { @@ -56,7 +57,11 @@ library MetadataType { interface MetadataManager { function appendMetadata(MetadataType.Metadata memory metadata) external; - function updateConsensusConfig(MetadataType.ConsensusConfig memory config) external; + function updateConsensusConfig( + MetadataType.ConsensusConfig memory config + ) external; - function setCkbRelatedInfo(MetadataType.CkbRelatedInfo memory info) external; + function setCkbRelatedInfo( + MetadataType.CkbRelatedInfo memory info + ) external; } diff --git a/common/config-parser/src/types/spec.rs b/common/config-parser/src/types/spec.rs index 6991f77d1..310ad6668 100644 --- a/common/config-parser/src/types/spec.rs +++ b/common/config-parser/src/types/spec.rs @@ -5,14 +5,14 @@ use clap::{ Args, ValueEnum, }; use serde::{Deserialize, Serialize}; +use strum::IntoEnumIterator; use strum_macros::EnumIter; use common_crypto::Secp256k1RecoverablePrivateKey; use protocol::{ - codec::{decode_256bits_key, deserialize_address, ProtocolCodec}, + codec::{decode_256bits_key, deserialize_address}, types::{ - ExtraData, HardforkInfoInner, Header, Key256Bits, Metadata, H160, H256, RLP_EMPTY_LIST, - RLP_NULL, U256, + HardforkInfoInner, Header, Key256Bits, Metadata, H160, H256, RLP_EMPTY_LIST, RLP_NULL, U256, }, }; @@ -209,23 +209,18 @@ impl Genesis { transactions_root: RLP_NULL, signed_txs_hash: RLP_EMPTY_LIST, timestamp: self.timestamp, - // todo: if Hardforkinput is empty, it must change to latest hardfork info to init - // genesis - extra_data: { - vec![ExtraData { - inner: Into::::into(HardforkInput { - hardforks: self.hardforks.clone(), - block_number: 0, - }) - .encode() - .unwrap(), - }] - }, base_fee_per_gas: self.base_fee_per_gas, chain_id: self.chain_id, ..Default::default() } } + + pub fn generate_hardfork_info(&self) -> HardforkInfoInner { + Into::::into(HardforkInput { + hardforks: self.hardforks.clone(), + block_number: 0, + }) + } } #[derive(Clone, Debug, Deserialize, Args)] @@ -242,12 +237,24 @@ pub struct HardforkInput { impl From for HardforkInfoInner { fn from(value: HardforkInput) -> Self { - let flags = { - let r = value.hardforks.into_iter().fold(0, |acc, s| acc | s as u64); + let convert_fn = |hardforks: Vec| -> H256 { + let r = hardforks.into_iter().fold(0, |acc, s| acc | s as u64); H256::from_low_u64_be(r.to_be()) }; + let flags = if value.hardforks.is_empty() { + H256::from_low_u64_be(HardforkName::all().to_be()) + } else if value.hardforks.len() == 1 { + if value.hardforks[0] == HardforkName::None { + H256::zero() + } else { + convert_fn(value.hardforks) + } + } else { + convert_fn(value.hardforks) + }; + HardforkInfoInner { block_number: value.block_number, flags, @@ -255,7 +262,21 @@ impl From for HardforkInfoInner { } } +/// inspired by https://www.wikiwand.com/en/IAU_designated_constellations#List #[derive(Clone, Debug, Serialize, Deserialize, Copy, ValueEnum, EnumIter, PartialEq, Eq, Hash)] pub enum HardforkName { None = 0b0, + /// If this hardfork is activated, chain validators can modify the EVM + /// contract size limit. + Andromeda = 0b1, +} + +impl HardforkName { + pub fn all() -> u64 { + let mut res = 0u64; + for name in HardforkName::iter() { + res |= name as u64 + } + res + } } diff --git a/core/api/src/jsonrpc/impl/axon.rs b/core/api/src/jsonrpc/impl/axon.rs index f3be59282..54fd995ab 100644 --- a/core/api/src/jsonrpc/impl/axon.rs +++ b/core/api/src/jsonrpc/impl/axon.rs @@ -155,10 +155,10 @@ fn enabled_and_determined(iter: &[HardforkInfoInner], current_number: u64) -> (H if iter.len() < 2 { match iter.last() { Some(latest) => { - if latest.block_number >= current_number { - (latest.flags, H256::zero()) - } else { + if latest.block_number > current_number { (H256::zero(), latest.flags) + } else { + (latest.flags, H256::zero()) } } None => (H256::zero(), H256::zero()), diff --git a/core/executor/src/lib.rs b/core/executor/src/lib.rs index 82197e5a0..176a3beb4 100644 --- a/core/executor/src/lib.rs +++ b/core/executor/src/lib.rs @@ -10,7 +10,10 @@ mod utils; pub use crate::adapter::{ AxonExecutorApplyAdapter, AxonExecutorReadOnlyAdapter, MPTTrie, RocksTrieDB, }; -pub use crate::system_contract::{metadata::MetadataHandle, DataProvider}; +pub use crate::system_contract::{ + metadata::{MetadataHandle, HARDFORK_INFO}, + DataProvider, +}; pub use crate::utils::{code_address, decode_revert_msg, DefaultFeeAllocator, FeeInlet}; use std::cell::RefCell; @@ -18,6 +21,7 @@ use std::collections::BTreeMap; use std::iter::FromIterator; use arc_swap::ArcSwap; +use common_config_parser::types::spec::HardforkName; use evm::executor::stack::{MemoryStackState, PrecompileFn, StackExecutor, StackSubstateMetadata}; use evm::CreateScheme; @@ -69,7 +73,7 @@ impl Executor for AxonExecutor { value: U256, data: Vec, ) -> TxResp { - let config = Config::london(); + let config = self.config(); let metadata = StackSubstateMetadata::new(gas_limit, &config); let state = MemoryStackState::new(metadata, backend); let precompiles = build_precompile_set(); @@ -134,7 +138,7 @@ impl Executor for AxonExecutor { let mut hashes = Vec::with_capacity(txs_len); let (mut gas, mut fee) = (0u64, U256::zero()); let precompiles = build_precompile_set(); - let config = Config::london(); + let config = self.config(); self.init_local_system_contract_roots(adapter); @@ -316,6 +320,23 @@ impl AxonExecutor { }); } + fn config(&self) -> Config { + let mut config = Config::london(); + let create_contract_limit = { + let latest_hardfork_info = &**HARDFORK_INFO.load(); + let enable_contract_limit_flag = H256::from_low_u64_be(HardforkName::Andromeda as u64); + if latest_hardfork_info & &enable_contract_limit_flag == enable_contract_limit_flag { + let handle = MetadataHandle::new(CURRENT_METADATA_ROOT.with(|r| *r.borrow())); + let config = handle.get_consensus_config().unwrap(); + Some(config.max_contract_limit as usize) + } else { + None + } + }; + config.create_contract_limit = create_contract_limit; + config + } + #[cfg(test)] fn test_exec( &self, diff --git a/core/executor/src/system_contract/metadata/abi/metadata_abi.json b/core/executor/src/system_contract/metadata/abi/metadata_abi.json index 009d7c767..051e67d75 100644 --- a/core/executor/src/system_contract/metadata/abi/metadata_abi.json +++ b/core/executor/src/system_contract/metadata/abi/metadata_abi.json @@ -115,6 +115,11 @@ "internalType": "uint64", "name": "interval", "type": "uint64" + }, + { + "internalType": "uint64", + "name": "max_contract_limit", + "type": "uint64" } ], "internalType": "struct MetadataType.ConsensusConfig", @@ -220,6 +225,11 @@ "internalType": "uint64", "name": "interval", "type": "uint64" + }, + { + "internalType": "uint64", + "name": "max_contract_limit", + "type": "uint64" } ], "internalType": "struct MetadataType.ConsensusConfig", diff --git a/core/executor/src/system_contract/metadata/abi/metadata_abi.rs b/core/executor/src/system_contract/metadata/abi/metadata_abi.rs index 48b1c95cf..9a2f6e7c0 100644 --- a/core/executor/src/system_contract/metadata/abi/metadata_abi.rs +++ b/core/executor/src/system_contract/metadata/abi/metadata_abi.rs @@ -11,7 +11,7 @@ pub use metadata_contract::*; )] pub mod metadata_contract { #[rustfmt::skip] - const __ABI: &str = "[\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint64\",\n \"name\": \"start\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"end\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.MetadataVersion\",\n \"name\": \"version\",\n \"type\": \"tuple\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"epoch\",\n \"type\": \"uint64\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"bls_pub_key\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"pub_key\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"address_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint32\",\n \"name\": \"propose_weight\",\n \"type\": \"uint32\"\n },\n {\n \"internalType\": \"uint32\",\n \"name\": \"vote_weight\",\n \"type\": \"uint32\"\n }\n ],\n \"internalType\": \"struct MetadataType.ValidatorExtend[]\",\n \"name\": \"verifier_list\",\n \"type\": \"tuple[]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"address_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"count\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.ProposeCount[]\",\n \"name\": \"propose_counter\",\n \"type\": \"tuple[]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint64\",\n \"name\": \"propose_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"prevote_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"precommit_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"brake_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"tx_num_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"max_tx_size\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"gas_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"interval\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.ConsensusConfig\",\n \"name\": \"consensus_config\",\n \"type\": \"tuple\"\n }\n ],\n \"internalType\": \"struct MetadataType.Metadata\",\n \"name\": \"metadata\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"appendMetadata\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"metadata_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"checkpoint_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"xudt_args\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"stake_smt_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"delegate_smt_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"reward_smt_type_id\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct MetadataType.CkbRelatedInfo\",\n \"name\": \"info\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"setCkbRelatedInfo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint64\",\n \"name\": \"propose_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"prevote_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"precommit_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"brake_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"tx_num_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"max_tx_size\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"gas_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"interval\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.ConsensusConfig\",\n \"name\": \"config\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"updateConsensusConfig\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n]\n"; + const __ABI: &str = "[\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint64\",\n \"name\": \"start\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"end\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.MetadataVersion\",\n \"name\": \"version\",\n \"type\": \"tuple\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"epoch\",\n \"type\": \"uint64\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"bls_pub_key\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"pub_key\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"address_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint32\",\n \"name\": \"propose_weight\",\n \"type\": \"uint32\"\n },\n {\n \"internalType\": \"uint32\",\n \"name\": \"vote_weight\",\n \"type\": \"uint32\"\n }\n ],\n \"internalType\": \"struct MetadataType.ValidatorExtend[]\",\n \"name\": \"verifier_list\",\n \"type\": \"tuple[]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"address_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"count\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.ProposeCount[]\",\n \"name\": \"propose_counter\",\n \"type\": \"tuple[]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint64\",\n \"name\": \"propose_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"prevote_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"precommit_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"brake_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"tx_num_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"max_tx_size\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"gas_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"interval\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"max_contract_limit\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.ConsensusConfig\",\n \"name\": \"consensus_config\",\n \"type\": \"tuple\"\n }\n ],\n \"internalType\": \"struct MetadataType.Metadata\",\n \"name\": \"metadata\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"appendMetadata\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"metadata_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"checkpoint_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"xudt_args\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"stake_smt_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"delegate_smt_type_id\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"reward_smt_type_id\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct MetadataType.CkbRelatedInfo\",\n \"name\": \"info\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"setCkbRelatedInfo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint64\",\n \"name\": \"propose_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"prevote_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"precommit_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"brake_ratio\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"tx_num_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"max_tx_size\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"gas_limit\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"interval\",\n \"type\": \"uint64\"\n },\n {\n \"internalType\": \"uint64\",\n \"name\": \"max_contract_limit\",\n \"type\": \"uint64\"\n }\n ],\n \"internalType\": \"struct MetadataType.ConsensusConfig\",\n \"name\": \"config\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"updateConsensusConfig\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n]\n"; /// The parsed JSON ABI of the contract. pub static METADATACONTRACT_ABI: ::ethers::contract::Lazy<::ethers::core::abi::Abi> = ::ethers::contract::Lazy::new(|| { @@ -57,13 +57,13 @@ pub mod metadata_contract { )) } - /// Calls the contract's `appendMetadata` (0x4677ae59) function + /// Calls the contract's `appendMetadata` (0x53ec79e6) function pub fn append_metadata( &self, metadata: Metadata, ) -> ::ethers::contract::builders::ContractCall { self.0 - .method_hash([70, 119, 174, 89], (metadata,)) + .method_hash([83, 236, 121, 230], (metadata,)) .expect("method not found (this should never happen)") } @@ -77,13 +77,13 @@ pub mod metadata_contract { .expect("method not found (this should never happen)") } - /// Calls the contract's `updateConsensusConfig` (0x3b05ee4f) function + /// Calls the contract's `updateConsensusConfig` (0xb76fac01) function pub fn update_consensus_config( &self, config: ConsensusConfig, ) -> ::ethers::contract::builders::ContractCall { self.0 - .method_hash([59, 5, 238, 79], (config,)) + .method_hash([183, 111, 172, 1], (config,)) .expect("method not found (this should never happen)") } } @@ -98,7 +98,7 @@ pub mod metadata_contract { /// function with signature /// `appendMetadata(((uint64,uint64),uint64,(bytes,bytes,address,uint32, /// uint32)[],(address,uint64)[],(uint64,uint64,uint64,uint64,uint64,uint64, - /// uint64,uint64)))` and selector `0x4677ae59` + /// uint64,uint64,uint64)))` and selector `0x53ec79e6` #[derive( Clone, ::ethers::contract::EthCall, @@ -111,7 +111,7 @@ pub mod metadata_contract { )] #[ethcall( name = "appendMetadata", - abi = "appendMetadata(((uint64,uint64),uint64,(bytes,bytes,address,uint32,uint32)[],(address,uint64)[],(uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64)))" + abi = "appendMetadata(((uint64,uint64),uint64,(bytes,bytes,address,uint32,uint32)[],(address,uint64)[],(uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64)))" )] pub struct AppendMetadataCall { pub metadata: Metadata, @@ -140,7 +140,7 @@ pub mod metadata_contract { /// Container type for all input parameters for the `updateConsensusConfig` /// function with signature /// `updateConsensusConfig((uint64,uint64,uint64,uint64,uint64,uint64, - /// uint64,uint64))` and selector `0x3b05ee4f` + /// uint64,uint64,uint64))` and selector `0xb76fac01` #[derive( Clone, ::ethers::contract::EthCall, @@ -153,7 +153,7 @@ pub mod metadata_contract { )] #[ethcall( name = "updateConsensusConfig", - abi = "updateConsensusConfig((uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64))" + abi = "updateConsensusConfig((uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64,uint64))" )] pub struct UpdateConsensusConfigCall { pub config: ConsensusConfig, @@ -243,7 +243,7 @@ pub mod metadata_contract { pub reward_smt_type_id: [u8; 32], } /// `ConsensusConfig(uint64,uint64,uint64,uint64,uint64,uint64,uint64, - /// uint64)` + /// uint64,uint64)` #[derive( Clone, ::ethers::contract::EthAbiType, @@ -255,18 +255,19 @@ pub mod metadata_contract { Hash, )] pub struct ConsensusConfig { - pub propose_ratio: u64, - pub prevote_ratio: u64, - pub precommit_ratio: u64, - pub brake_ratio: u64, - pub tx_num_limit: u64, - pub max_tx_size: u64, - pub gas_limit: u64, - pub interval: u64, + pub propose_ratio: u64, + pub prevote_ratio: u64, + pub precommit_ratio: u64, + pub brake_ratio: u64, + pub tx_num_limit: u64, + pub max_tx_size: u64, + pub gas_limit: u64, + pub interval: u64, + pub max_contract_limit: u64, } /// `Metadata((uint64,uint64),uint64,(bytes,bytes,address,uint32,uint32)[], /// (address,uint64)[],(uint64,uint64,uint64,uint64,uint64,uint64,uint64, - /// uint64))` + /// uint64,uint64))` #[derive( Clone, ::ethers::contract::EthAbiType, diff --git a/core/executor/src/system_contract/metadata/abi/mod.rs b/core/executor/src/system_contract/metadata/abi/mod.rs index b215b872c..81d08b3b0 100644 --- a/core/executor/src/system_contract/metadata/abi/mod.rs +++ b/core/executor/src/system_contract/metadata/abi/mod.rs @@ -35,14 +35,15 @@ impl From for metadata_abi::Metadata { impl From for metadata_abi::ConsensusConfig { fn from(value: ConsensusConfig) -> Self { metadata_abi::ConsensusConfig { - propose_ratio: value.propose_ratio, - prevote_ratio: value.prevote_ratio, - precommit_ratio: value.precommit_ratio, - brake_ratio: value.brake_ratio, - tx_num_limit: value.tx_num_limit, - max_tx_size: value.max_tx_size, - gas_limit: value.gas_limit, - interval: value.interval, + propose_ratio: value.propose_ratio, + prevote_ratio: value.prevote_ratio, + precommit_ratio: value.precommit_ratio, + brake_ratio: value.brake_ratio, + tx_num_limit: value.tx_num_limit, + max_tx_size: value.max_tx_size, + gas_limit: value.gas_limit, + interval: value.interval, + max_contract_limit: value.max_contract_limit, } } } @@ -50,14 +51,15 @@ impl From for metadata_abi::ConsensusConfig { impl From for ConsensusConfig { fn from(value: metadata_abi::ConsensusConfig) -> Self { ConsensusConfig { - propose_ratio: value.propose_ratio, - prevote_ratio: value.prevote_ratio, - precommit_ratio: value.precommit_ratio, - brake_ratio: value.brake_ratio, - tx_num_limit: value.tx_num_limit, - max_tx_size: value.max_tx_size, - gas_limit: value.gas_limit, - interval: value.interval, + propose_ratio: value.propose_ratio, + prevote_ratio: value.prevote_ratio, + precommit_ratio: value.precommit_ratio, + brake_ratio: value.brake_ratio, + tx_num_limit: value.tx_num_limit, + max_tx_size: value.max_tx_size, + gas_limit: value.gas_limit, + interval: value.interval, + max_contract_limit: value.max_contract_limit, } } } diff --git a/core/executor/src/system_contract/metadata/handle.rs b/core/executor/src/system_contract/metadata/handle.rs index 3765f704a..edd3de3f2 100644 --- a/core/executor/src/system_contract/metadata/handle.rs +++ b/core/executor/src/system_contract/metadata/handle.rs @@ -1,4 +1,4 @@ -use protocol::types::{CkbRelatedInfo, HardforkInfo, Metadata, H160, H256}; +use protocol::types::{CkbRelatedInfo, ConsensusConfig, HardforkInfo, Metadata, H160, H256}; use protocol::ProtocolResult; use std::sync::Arc; @@ -62,4 +62,8 @@ impl MetadataHandle { HARDFORK_INFO.swap(Arc::new(hardfork)); Ok(()) } + + pub fn get_consensus_config(&self) -> ProtocolResult { + MetadataStore::new(self.root)?.get_consensus_config() + } } diff --git a/core/executor/src/system_contract/metadata/mod.rs b/core/executor/src/system_contract/metadata/mod.rs index 73c4f6964..78a40c329 100644 --- a/core/executor/src/system_contract/metadata/mod.rs +++ b/core/executor/src/system_contract/metadata/mod.rs @@ -5,7 +5,7 @@ mod store; pub use abi::metadata_abi; pub use handle::MetadataHandle; -pub use store::MetadataStore; +pub use store::{encode_consensus_config, MetadataStore}; use std::{num::NonZeroUsize, sync::Arc}; @@ -32,8 +32,9 @@ const METADATA_CACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(1 lazy_static::lazy_static! { pub static ref EPOCH_SEGMENT_KEY: H256 = Hasher::digest("epoch_segment"); static ref CKB_RELATED_INFO_KEY: H256 = Hasher::digest("ckb_related_info"); - static ref HARDFORK_KEY: H256 = Hasher::digest("hardfork"); - static ref HARDFORK_INFO: ArcSwap = ArcSwap::new(Arc::new(H256::zero())); + pub static ref CONSENSUS_CONFIG: H256 = Hasher::digest("consensus_config"); + pub static ref HARDFORK_KEY: H256 = Hasher::digest("hardfork"); + pub static ref HARDFORK_INFO: ArcSwap = ArcSwap::new(Arc::new(H256::zero())); static ref METADATA_CACHE: RwLock> = RwLock::new(LruCache::new(METADATA_CACHE_SIZE)); } @@ -97,7 +98,7 @@ impl SystemContract } metadata_abi::MetadataContractCalls::UpdateConsensusConfig(c) => { exec_try!( - store.update_consensus_config(c.config), + store.update_consensus_config(c.config.into()), gas_limit, "[metadata] update consensus config" ); @@ -111,6 +112,10 @@ impl SystemContract fn after_block_hook(&self, adapter: &mut Adapter) { let block_number = adapter.block_number(); + if block_number.is_zero() { + return; + } + let root = CURRENT_METADATA_ROOT.with(|r| *r.borrow()); let mut store = MetadataStore::new(root).unwrap(); @@ -127,10 +132,6 @@ impl SystemContract HARDFORK_INFO.swap(Arc::new(hardfork)); - if block_number.is_zero() { - return; - } - if let Err(e) = store.update_propose_count(block_number.as_u64(), &adapter.origin()) { panic!("Update propose count at {:?} failed: {:?}", block_number, e) } diff --git a/core/executor/src/system_contract/metadata/store.rs b/core/executor/src/system_contract/metadata/store.rs index 25a648cea..f8cbaef4b 100644 --- a/core/executor/src/system_contract/metadata/store.rs +++ b/core/executor/src/system_contract/metadata/store.rs @@ -1,27 +1,32 @@ use std::collections::BTreeMap; use std::sync::Arc; +use common_config_parser::types::spec::HardforkName; use protocol::trie::Trie as _; -use protocol::types::{CkbRelatedInfo, HardforkInfo, HardforkInfoInner, Metadata, H160, H256}; +use protocol::types::{ + CkbRelatedInfo, ConsensusConfig, ConsensusConfigV0, HardforkInfo, HardforkInfoInner, Metadata, + MetadataInner, H160, H256, +}; use protocol::{codec::ProtocolCodec, ProtocolResult}; use crate::system_contract::metadata::{ - segment::EpochSegment, CKB_RELATED_INFO_KEY, EPOCH_SEGMENT_KEY, HARDFORK_KEY, + segment::EpochSegment, CKB_RELATED_INFO_KEY, CONSENSUS_CONFIG, EPOCH_SEGMENT_KEY, + HARDFORK_INFO, HARDFORK_KEY, }; use crate::system_contract::{error::SystemScriptError, METADATA_DB}; use crate::{adapter::RocksTrieDB, MPTTrie, CURRENT_METADATA_ROOT}; -use super::metadata_abi::ConsensusConfig; - /// The metadata store does not follow the storage layout of EVM smart contract. /// It use MPT called Metadata MPT with the following layout: -/// | key | value | -/// | -------------------- | ------------------------ | -/// | EPOCH_SEGMENT_KEY | `EpochSegment.encode()` | -/// | CKB_RELATED_INFO_KEY | `CkbRelatedInfo.encode()`| -/// | epoch_0.be_bytes() | `Metadata.encode()` | -/// | epoch_1.be_bytes() | `Metadata.encode()` | -/// | ... | ... | +/// | key | value | +/// | -------------------- | ------------------------------------ | +/// | EPOCH_SEGMENT_KEY | `EpochSegment.encode()` | +/// | CKB_RELATED_INFO_KEY | `CkbRelatedInfo.encode()` | +/// | HARDFORK_KEY | `HardforkInfo.encode()` | +/// | epoch_0.be_bytes() | `Metadata.encode()` | +/// | epoch_1.be_bytes() | `Metadata.encode()` | +/// | CONSENSUS_CONFIG | `version + ConsensesConfig.encode()` | +/// | ... | ... | /// /// All these data are stored in a the `c9` column family of RocksDB, and the /// root of the Metadata MPT is stored in the storage MPT of the metadata @@ -108,14 +113,18 @@ impl MetadataStore { epoch_segment.append_endpoint(metadata.version.end)?; + let (inner, config) = metadata.into_part(); + let current_hardfork = **HARDFORK_INFO.load(); + self.trie.insert( EPOCH_SEGMENT_KEY.as_bytes().to_vec(), epoch_segment.as_bytes(), )?; - self.trie.insert( - metadata.epoch.to_be_bytes().to_vec(), - metadata.encode()?.to_vec(), - )?; + self.trie + .insert(inner.epoch.to_be_bytes().to_vec(), inner.encode()?.to_vec())?; + let config = encode_consensus_config(current_hardfork, config.encode()?.to_vec()); + self.trie + .insert(CONSENSUS_CONFIG.as_bytes().to_vec(), config)?; let new_root = self.trie.commit()?; CURRENT_METADATA_ROOT.with(|r| *r.borrow_mut() = new_root); @@ -127,7 +136,8 @@ impl MetadataStore { block_number: u64, proposer: &H160, ) -> ProtocolResult<()> { - let mut metadata = self.get_metadata_by_block_number(block_number)?; + let epoch = self.get_epoch_by_block_number(block_number)?; + let mut metadata = self.get_metadata_inner(epoch)?; if let Some(counter) = metadata .propose_counter .iter_mut() @@ -152,11 +162,26 @@ impl MetadataStore { } pub fn get_metadata(&self, epoch: u64) -> ProtocolResult { + let inner = self.get_metadata_inner(epoch)?; + let config = self.get_consensus_config()?; + Ok(Metadata::from_parts(inner, config)) + } + + fn get_metadata_inner(&self, epoch: u64) -> ProtocolResult { let raw = self .trie .get(&epoch.to_be_bytes())? .ok_or_else(|| SystemScriptError::MissingRecord(epoch))?; - Metadata::decode(raw) + MetadataInner::decode(raw) + } + + pub fn get_consensus_config(&self) -> ProtocolResult { + let raw = self + .trie + .get(CONSENSUS_CONFIG.as_bytes())? + .expect("Inner panic with can't find consensus config"); + + decode_consensus_config(raw) } pub fn get_metadata_by_block_number(&self, block_number: u64) -> ProtocolResult { @@ -173,14 +198,10 @@ impl MetadataStore { } pub fn update_consensus_config(&mut self, config: ConsensusConfig) -> ProtocolResult<()> { - let epoch_segment = self.get_epoch_segment()?; - let latest_epoch = epoch_segment.get_latest_epoch_number(); - let mut metadata = self.get_metadata(latest_epoch)?; - - metadata.consensus_config = config.into(); + let current_hardfork = **HARDFORK_INFO.load(); self.trie.insert( - metadata.epoch.to_be_bytes().to_vec(), - metadata.encode()?.to_vec(), + CONSENSUS_CONFIG.as_bytes().to_vec(), + encode_consensus_config(current_hardfork, config.encode()?.to_vec()), )?; let new_root = self.trie.commit()?; CURRENT_METADATA_ROOT.with(|r| *r.borrow_mut() = new_root); @@ -211,6 +232,7 @@ impl MetadataStore { }, } }; + self.trie.insert( HARDFORK_KEY.as_bytes().to_vec(), current_info.encode()?.to_vec(), @@ -244,3 +266,55 @@ impl MetadataStore { } } } + +#[derive(Debug)] +enum ConsensusConfigFlag { + V0 = 0b0, + V1 = 0b1, +} + +impl From for ConsensusConfigFlag { + fn from(value: u16) -> Self { + match value { + 0b0 => ConsensusConfigFlag::V0, + 0b1 => ConsensusConfigFlag::V1, + _ => unreachable!(), + } + } +} + +impl ConsensusConfigFlag { + fn new(flags: H256) -> Self { + let v1_name_flag = H256::from_low_u64_be((HardforkName::Andromeda as u64).to_be()); + let res = flags & v1_name_flag; + + if res & v1_name_flag == v1_name_flag { + ConsensusConfigFlag::V1 + } else { + ConsensusConfigFlag::V0 + } + } +} + +fn decode_consensus_config(raw: Vec) -> ProtocolResult { + let raw_flag = { + let mut a = [0u8; 2]; + a[0] = raw[0]; + a[1] = raw[1]; + a + }; + let flag = ConsensusConfigFlag::from(u16::from_be_bytes(raw_flag)); + + match flag { + ConsensusConfigFlag::V0 => ConsensusConfigV0::decode(&raw[2..]).map(Into::into), + ConsensusConfigFlag::V1 => ConsensusConfig::decode(&raw[2..]), + } +} + +pub fn encode_consensus_config(current_hardfork: H256, config: Vec) -> Vec { + let flag = ConsensusConfigFlag::new(current_hardfork); + + let mut res = (flag as u16).to_be_bytes().to_vec(); + res.extend(config); + res +} diff --git a/core/executor/src/system_contract/mod.rs b/core/executor/src/system_contract/mod.rs index e6bf19df7..201334a1f 100644 --- a/core/executor/src/system_contract/mod.rs +++ b/core/executor/src/system_contract/mod.rs @@ -28,7 +28,9 @@ use parking_lot::RwLock; use rocksdb::DB; use protocol::traits::{CkbDataProvider, ExecutorAdapter}; -use protocol::types::{Bytes, Hasher, Metadata, SignedTransaction, TxResp, H160, H256}; +use protocol::types::{ + Bytes, HardforkInfoInner, Hasher, Metadata, SignedTransaction, TxResp, H160, H256, +}; use protocol::{ckb_blake2b_256, ProtocolResult}; use crate::adapter::RocksTrieDB; @@ -115,9 +117,10 @@ pub fn init( db: Arc, adapter: &mut Adapter, metadata_list: &[Metadata], + hardfork: HardforkInfoInner, ) -> ProtocolResult<(H256, H256)> { let ret = init_system_contract_db(db, adapter); - init_metadata(adapter, ret.0, metadata_list)?; + init_metadata_and_hardfork(adapter, ret.0, metadata_list, hardfork)?; Ok(ret) } @@ -165,16 +168,18 @@ pub fn init_system_contract_db( /// This method is used for insert the first two metadata, so the /// `metadata_list.len()` should be equal to 2. -fn init_metadata( +fn init_metadata_and_hardfork( adapter: &mut Adapter, metadata_root: H256, metadata_list: &[Metadata], + hardfork: HardforkInfoInner, ) -> ProtocolResult<()> { debug_assert!(metadata_list.len() == 2); let mut store = MetadataStore::new(metadata_root)?; store.append_metadata(&metadata_list[0])?; store.append_metadata(&metadata_list[1])?; + store.set_hardfork_info(hardfork.block_number, hardfork.flags)?; let changes = generate_mpt_root_changes(adapter, METADATA_CONTRACT_ADDRESS); adapter.apply(changes, vec![], false); diff --git a/core/executor/src/tests/system_script/metadata.rs b/core/executor/src/tests/system_script/metadata.rs index 62fb66976..91d9ba91b 100644 --- a/core/executor/src/tests/system_script/metadata.rs +++ b/core/executor/src/tests/system_script/metadata.rs @@ -184,14 +184,15 @@ fn prepare_metadata() -> Metadata { verifier_list: vec![prepare_validator()], propose_counter: vec![], consensus_config: ConsensusConfig { - gas_limit: 1u64, - interval: 0u64, - propose_ratio: 1u64, - prevote_ratio: 1u64, - precommit_ratio: 1u64, - brake_ratio: 1u64, - tx_num_limit: 1u64, - max_tx_size: 1u64, + gas_limit: 1u64, + interval: 0u64, + propose_ratio: 1u64, + prevote_ratio: 1u64, + precommit_ratio: 1u64, + brake_ratio: 1u64, + tx_num_limit: 1u64, + max_tx_size: 1u64, + max_contract_limit: 0x6000u64, }, } } @@ -205,3 +206,61 @@ fn prepare_validator() -> ValidatorExtend { vote_weight: 1u32, } } + +// #[tokio::test] +// async fn update_consensus_config() { +// let config: +// crate::system_contract::metadata::metadata_abi::ConsensusConfig = +// ConsensusConfig { gas_limit: 0x3e7fffffc18, +// interval: 0xbb8, +// propose_ratio: 0xf, +// prevote_ratio: 0xa, +// precommit_ratio: 0xa, +// brake_ratio: 0xa, +// tx_num_limit: 0x4e20, +// max_tx_size: 0x186a0000, +// max_contract_limit: 0x8000u64, +// } +// .into(); + +// let tx_data = +// crate::system_contract::metadata::metadata_abi::UpdateConsensusConfigCall { config } +// .encode(); + +// send_eth_tx("http://127.0.0.1:8000", tx_data, METADATA_CONTRACT_ADDRESS).await +// } +// use ethers::prelude::*; +// use ethers::signers::{LocalWallet, Signer}; +// use ethers::types::transaction::eip2718::TypedTransaction::Legacy; +// use ethers::types::{Address, TransactionRequest}; + +// const ADDRESS: &str = "0x8ab0CF264DF99D83525e9E11c7e4db01558AE1b1"; +// const PRIVATE_KEY: &str = +// "37aa0f893d05914a4def0460c0a984d3611546cfb26924d7a7ca6e0db9950a2d"; pub async +// fn send_eth_tx(axon_url: &str, data: Vec, to: Address) { let provider +// = Provider::::try_from(axon_url).unwrap(); + +// let from: Address = ADDRESS.parse().unwrap(); +// let nonce = provider.get_transaction_count(from, None).await.unwrap(); + +// let transaction_request = TransactionRequest::new() +// .chain_id(0x41786f6e) +// .to(to) +// .data(data) +// .from(from) +// .gas_price(1) +// .gas(21000) +// .nonce(nonce); + +// let wallet = LocalWallet::from_str(PRIVATE_KEY).expect("failed to create +// wallet"); let tx = Legacy(transaction_request); +// let signature: Signature = wallet.sign_transaction(&tx).await.unwrap(); + +// provider +// .send_raw_transaction(tx.rlp_signed(&signature)) +// .await +// .unwrap() +// .await +// .unwrap() +// .expect("failed to send eth tx"); +// } diff --git a/core/run/src/lib.rs b/core/run/src/lib.rs index 30b84616e..8e0c62439 100644 --- a/core/run/src/lib.rs +++ b/core/run/src/lib.rs @@ -441,9 +441,13 @@ async fn execute_genesis( tmp }; - let resp = execute_genesis_transactions(&partial_genesis, db_group, &spec.accounts, &[ - metadata_0, metadata_1, - ])?; + let resp = execute_genesis_transactions( + &partial_genesis, + db_group, + &spec.accounts, + &[metadata_0, metadata_1], + spec.genesis.generate_hardfork_info(), + )?; partial_genesis.block.header.state_root = resp.state_root; partial_genesis.block.header.receipts_root = resp.receipt_root; @@ -473,6 +477,7 @@ fn execute_genesis_transactions( db_group: &DatabaseGroup, accounts: &[InitialAccount], metadata_list: &[Metadata], + hardfork: HardforkInfoInner, ) -> ProtocolResult { let state_root = MPTTrie::new(db_group.trie_db()) .insert_accounts(accounts) @@ -485,7 +490,7 @@ fn execute_genesis_transactions( Proposal::new_without_state_root(&rich.block.header).into(), )?; - system_contract::init(db_group.inner_db(), &mut backend, metadata_list)?; + system_contract::init(db_group.inner_db(), &mut backend, metadata_list, hardfork)?; let resp = AxonExecutor.exec(&mut backend, &rich.txs, &[]); diff --git a/core/run/src/tests.rs b/core/run/src/tests.rs index e3a4b87e3..a0e1305dc 100644 --- a/core/run/src/tests.rs +++ b/core/run/src/tests.rs @@ -12,11 +12,14 @@ use clap::{builder::TypedValueParser as _, Command}; use hasher::HasherKeccak; use common_config_parser::types::{ - spec::{ChainSpec, ChainSpecValueParser}, + spec::{ChainSpec, ChainSpecValueParser, HardforkName}, Config, ConfigValueParser, }; use core_executor::{ - system_contract::metadata::{segment::EpochSegment, EPOCH_SEGMENT_KEY}, + system_contract::metadata::{ + encode_consensus_config, segment::EpochSegment, CONSENSUS_CONFIG, EPOCH_SEGMENT_KEY, + HARDFORK_KEY, + }, AxonExecutorApplyAdapter, MetadataHandle, }; use protocol::{ @@ -24,7 +27,8 @@ use protocol::{ tokio, trie::{MemoryDB, PatriciaTrie, Trie as _}, types::{ - Bloom, BloomInput, Header, Metadata, Proposal, RichBlock, H256, RLP_EMPTY_LIST, RLP_NULL, + Bloom, BloomInput, HardforkInfo, HardforkInfoInner, Header, Metadata, Proposal, RichBlock, + H256, RLP_EMPTY_LIST, RLP_NULL, }, }; @@ -45,22 +49,22 @@ const TESTCASES: &[TestCase] = &[ chain_name: "single_node", config_file: "config.toml", chain_spec_file: "specs/single_node/chain-spec.toml", - input_genesis_hash: "0x274c0c52500c3978776d8836b8afe0999a946a010166c12a85a1c45b9cd2c5a2", - genesis_state_root: "0x940458498b6ac368ab17e9ede64d0cc1d321bc4ec835e09a333a4151c7785ea1", + input_genesis_hash: "0x766cd8e7a32f698eb1180cd736bad6d316ebd3c185326bf6be24ef34996f545a", + genesis_state_root: "0x2131e3b9b90adc4c5e2b5136f3789b982029ab43c610cee0b05d8d2759dbdac4", }, TestCase { chain_name: "multi_nodes", config_file: "nodes/node_1.toml", chain_spec_file: "specs/multi_nodes/chain-spec.toml", - input_genesis_hash: "0x70cc025ae586f054157f6d8a6558c39c359cde0eb4b9acbdf3f31a8e14a6a6fc", - genesis_state_root: "0x9976026c069e8d931d55f93637663e494caae772c2c274ad636de9bc7baf5191", + input_genesis_hash: "0x6e6160ffd1dcbcec8fa57a9a62479a9ace98f53bfd512fe946fe17f50c08def9", + genesis_state_root: "0x754e9d640f31758f44dbdb18b266dcfb87945d96d713f0a28a06bf6dfa665585", }, TestCase { chain_name: "multi_nodes_short_epoch_len", config_file: "nodes/node_1.toml", chain_spec_file: "specs/multi_nodes_short_epoch_len/chain-spec.toml", - input_genesis_hash: "0x4213963522f2d72fa8b33ab4a8b33d79f0d387999f97f38d5c93d9b047baa743", - genesis_state_root: "0x33a4f19a7d1bca010f6c3f17904e23f099dd2a022e1f1401fbffed27a1919370", + input_genesis_hash: "0x38814e4efa8ec97e659905208d808e5f7118bb039aa7aaee89937dad8bdee756", + genesis_state_root: "0xe2cb19b9ce6655838aa5e280d4f6fb06fcf367d454d4bc1c47f5bfd85d75432e", }, ]; @@ -260,27 +264,62 @@ fn generate_memory_mpt_root(metadata_0: Metadata, metadata_1: Metadata) -> Vec (MetadataInner, ConsensusConfig) { + ( + MetadataInner { + version: self.version, + epoch: self.epoch, + verifier_list: self.verifier_list, + propose_counter: self.propose_counter, + }, + self.consensus_config, + ) + } + + pub fn from_parts(inner: MetadataInner, config: ConsensusConfig) -> Self { + Metadata { + version: inner.version, + epoch: inner.epoch, + verifier_list: inner.verifier_list, + propose_counter: inner.propose_counter, + consensus_config: config, + } + } +} + +#[derive(RlpEncodable, RlpDecodable, Default, Clone, Debug, PartialEq, Eq)] +pub struct MetadataInner { + pub version: MetadataVersion, + pub epoch: u64, + pub verifier_list: Vec, + pub propose_counter: Vec, +} + #[derive( RlpEncodable, RlpDecodable, Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq, )] -pub struct ConsensusConfig { +pub struct ConsensusConfigV0 { #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] pub gas_limit: u64, #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] @@ -328,6 +360,51 @@ pub struct ConsensusConfig { pub max_tx_size: u64, } +impl From for ConsensusConfig { + fn from(value: ConsensusConfigV0) -> Self { + ConsensusConfig { + gas_limit: value.gas_limit, + interval: value.interval, + precommit_ratio: value.precommit_ratio, + propose_ratio: value.propose_ratio, + prevote_ratio: value.prevote_ratio, + brake_ratio: value.brake_ratio, + tx_num_limit: value.tx_num_limit, + max_tx_size: value.max_tx_size, + max_contract_limit: default_max_contract_limit(), + } + } +} + +#[derive( + RlpEncodable, RlpDecodable, Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq, +)] +pub struct ConsensusConfig { + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub gas_limit: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub interval: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub propose_ratio: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub prevote_ratio: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub precommit_ratio: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub brake_ratio: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub tx_num_limit: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + pub max_tx_size: u64, + #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))] + #[serde(default = "default_max_contract_limit")] + pub max_contract_limit: u64, +} + +pub fn default_max_contract_limit() -> u64 { + 0x6000 +} + impl From for DurationConfig { fn from(m: Metadata) -> Self { DurationConfig {