Skip to content

Commit

Permalink
feat: first hardfork with contract size limit (#1451)
Browse files Browse the repository at this point in the history
* feat: first hardfork with contract limit

* feat: enable contract size limit change with evm

* refactor: insert genesis hardfork to DB directly

* feat: if hardforks only one and eq None, it will be no hardfork enable in genesis

* chore: impl review comment

---------

Co-authored-by: Eason <[email protected]>
  • Loading branch information
driftluo and Eason authored Oct 12, 2023
1 parent a6fffed commit d858602
Show file tree
Hide file tree
Showing 16 changed files with 449 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ library MetadataType {
uint64 max_tx_size;
uint64 gas_limit;
uint64 interval;
uint64 max_contract_limit;
}

struct CkbRelatedInfo {
Expand All @@ -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;
}
55 changes: 38 additions & 17 deletions common/config-parser/src/types/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
};

Expand Down Expand Up @@ -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::<HardforkInfoInner>::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::<HardforkInfoInner>::into(HardforkInput {
hardforks: self.hardforks.clone(),
block_number: 0,
})
}
}

#[derive(Clone, Debug, Deserialize, Args)]
Expand All @@ -242,20 +237,46 @@ pub struct HardforkInput {

impl From<HardforkInput> 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<HardforkName>| -> 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,
}
}
}

/// 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
}
}
6 changes: 3 additions & 3 deletions core/api/src/jsonrpc/impl/axon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
Expand Down
27 changes: 24 additions & 3 deletions core/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ 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;
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;

Expand Down Expand Up @@ -69,7 +73,7 @@ impl Executor for AxonExecutor {
value: U256,
data: Vec<u8>,
) -> 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();
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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<Adapter: ExecutorAdapter>(
&self,
Expand Down
10 changes: 10 additions & 0 deletions core/executor/src/system_contract/metadata/abi/metadata_abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
"internalType": "uint64",
"name": "interval",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "max_contract_limit",
"type": "uint64"
}
],
"internalType": "struct MetadataType.ConsensusConfig",
Expand Down Expand Up @@ -220,6 +225,11 @@
"internalType": "uint64",
"name": "interval",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "max_contract_limit",
"type": "uint64"
}
],
"internalType": "struct MetadataType.ConsensusConfig",
Expand Down
Loading

0 comments on commit d858602

Please sign in to comment.