Skip to content

Commit

Permalink
feat: first hardfork with contract limit
Browse files Browse the repository at this point in the history
  • Loading branch information
driftluo committed Sep 26, 2023
1 parent 83ea6f2 commit 344fe85
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 77 deletions.
3 changes: 1 addition & 2 deletions builtin-contract/metadata/contracts/metadata.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ contract MetadataManager {
uint64 tx_num_limit;
uint64 max_tx_size;
uint64 gas_limit;
uint64 gas_price;
uint64 interval;
uint64 max_contract_limit;
}

struct CkbRelatedInfo {
Expand Down Expand Up @@ -91,7 +91,6 @@ contract MetadataManager {
target.version = metadata.version;
target.epoch = metadata.epoch;
target.consensus_config.gas_limit = metadata.consensus_config.gas_limit;
target.consensus_config.gas_price = metadata.consensus_config.gas_price;
target.consensus_config.interval = metadata.consensus_config.interval;
target.consensus_config.propose_ratio = metadata
.consensus_config
Expand Down
25 changes: 19 additions & 6 deletions common/config-parser/src/types/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,18 @@ impl Genesis {
// genesis
extra_data: {
vec![ExtraData {
inner: Into::<HardforkInfoInner>::into(HardforkInput {
hardforks: self.hardforks.clone(),
block_number: 0,
})
.encode()
.unwrap(),
inner: {
let mut info = Into::<HardforkInfoInner>::into(HardforkInput {
hardforks: self.hardforks.clone(),
block_number: 0,
});

if info.flags.is_zero() {
info.flags = H256::from_low_u64_be(HardforkName::all().to_be());
}

info.encode().unwrap()
},
}]
},
base_fee_per_gas: self.base_fee_per_gas,
Expand Down Expand Up @@ -309,4 +315,11 @@ impl From<HardforkInput> for HardforkInfoInner {
#[derive(Clone, Debug, Serialize, Deserialize, Copy, ValueEnum, EnumIter, PartialEq, Eq, Hash)]
pub enum HardforkName {
None = 0b0,
Andromeda = 0b1,
}

impl HardforkName {
pub fn all() -> u64 {
HardforkName::None as u64 | HardforkName::Andromeda as u64
}
}
12 changes: 6 additions & 6 deletions core/executor/src/system_contract/metadata/abi/metadata_abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@
},
{
"internalType": "uint64",
"name": "gas_price",
"name": "interval",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "interval",
"name": "max_contract_limit",
"type": "uint64"
}
],
Expand Down Expand Up @@ -259,12 +259,12 @@
},
{
"internalType": "uint64",
"name": "gas_price",
"name": "interval",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "interval",
"name": "max_contract_limit",
"type": "uint64"
}
],
Expand Down Expand Up @@ -322,12 +322,12 @@
},
{
"internalType": "uint64",
"name": "gas_price",
"name": "interval",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "interval",
"name": "max_contract_limit",
"type": "uint64"
}
],
Expand Down
20 changes: 10 additions & 10 deletions core/executor/src/system_contract/metadata/abi/metadata_abi.rs

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions core/executor/src/system_contract/metadata/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,31 @@ impl From<Metadata> for metadata_abi::Metadata {
impl From<ConsensusConfig> 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,
gas_price: value.gas_price,
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,
}
}
}

impl From<metadata_abi::ConsensusConfig> 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,
gas_price: value.gas_price,
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,
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion core/executor/src/system_contract/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const METADATA_CACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(1
lazy_static::lazy_static! {
static ref EPOCH_SEGMENT_KEY: H256 = Hasher::digest("epoch_segment");
static ref CKB_RELATED_INFO_KEY: H256 = Hasher::digest("ckb_related_info");
static ref CONSENSUS_CONFIG: H256 = Hasher::digest("consensus_config");
static ref HARDFORK_KEY: H256 = Hasher::digest("hardfork");
static ref HARDFORK_INFO: ArcSwap<H256> = ArcSwap::new(Arc::new(H256::zero()));
static ref METADATA_CACHE: RwLock<LruCache<Epoch, Metadata>> = RwLock::new(LruCache::new(METADATA_CACHE_SIZE));
Expand Down Expand Up @@ -97,7 +98,7 @@ impl<Adapter: ExecutorAdapter + ApplyBackend> SystemContract<Adapter>
}
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"
);
Expand Down
101 changes: 86 additions & 15 deletions core/executor/src/system_contract/metadata/store.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
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;

pub struct MetadataStore {
pub trie: MPTTrie<RocksTrieDB>,
}
Expand Down Expand Up @@ -86,13 +89,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(inner.epoch.to_be_bytes().to_vec(), inner.encode()?.to_vec())?;
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);
Expand All @@ -105,7 +113,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()
Expand All @@ -130,11 +139,26 @@ impl MetadataStore {
}

pub fn get_metadata(&self, epoch: u64) -> ProtocolResult<Metadata> {
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<MetadataInner> {
let raw = self
.trie
.get(&epoch.to_be_bytes())?
.ok_or_else(|| SystemScriptError::MissingRecord(epoch))?;
Metadata::decode(raw)
MetadataInner::decode(raw)
}

fn get_consensus_config(&self) -> ProtocolResult<ConsensusConfig> {
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<Metadata> {
Expand All @@ -151,14 +175,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);
Expand Down Expand Up @@ -222,3 +242,54 @@ impl MetadataStore {
}
}
}

enum ConsensusConfigFlag {
V0 = 0b0,
V1 = 0b1,
}

impl From<u16> 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<u8>) -> ProtocolResult<ConsensusConfig> {
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..]),
}
}

fn encode_consensus_config(current_hardfork: H256, config: Vec<u8>) -> Vec<u8> {
let flag = ConsensusConfigFlag::new(current_hardfork);

let mut res = (flag as u16).to_be_bytes().to_vec();
res.extend(config);
res
}
18 changes: 9 additions & 9 deletions core/executor/src/tests/system_script/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,15 @@ fn prepare_metadata() -> Metadata {
verifier_list: vec![prepare_validator()],
propose_counter: vec![],
consensus_config: ConsensusConfig {
gas_limit: 1u64,
gas_price: 0u64,
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,
},
}
}
Expand Down
12 changes: 6 additions & 6 deletions core/run/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,26 @@ const TESTCASES: &[TestCase] = &[
config_file: "config.toml",
chain_spec_file: "specs/single_node/chain-spec.toml",
key_file: "debug.key",
input_genesis_hash: "0x4e06dc4a01178db42c029f7d65f65a5763702a21082cfcb626c6c41054a7a276",
genesis_state_root: "0xb6c51706f77a788606c8b932ad4f752c3f9a54008cd82e85f417d3a7e900d5c2",
input_genesis_hash: "0x7360659a70f5713a4cc30b51e819dacd421047faf3295371cccbd34f7e5536c3",
genesis_state_root: "0xa70f71c1be81bc8dbe1303a310bfdcb69924abaab7e96775891bb5871f10af2c",
genesis_receipts_root: "0x7e747618f612d08dfe54bcb67f58f13a49e8b1bafee9a8f19a3a0f7122f44d02",
},
TestCase {
chain_name: "multi_nodes",
config_file: "nodes/node_1.toml",
chain_spec_file: "specs/multi_nodes/chain-spec.toml",
key_file: "debug.key",
input_genesis_hash: "0xf16db25ca1a0cff5339d76e9802c75c43faac35ee4a9294a51234b167c69159f",
genesis_state_root: "0x9f76f02e823115e7b9887d07678f40b8ff50f82d4d09214fa481bdad68f5192a",
input_genesis_hash: "0x6b2214dc0bd93c64c234a99d996c90ccd97b0f89a888d50292dc34897486e30a",
genesis_state_root: "0x69f3ac6ea8149daa36a6e8d5d2f4f892efcf9a7ead31a1dcb0301a27db4d71a9",
genesis_receipts_root: "0x7e747618f612d08dfe54bcb67f58f13a49e8b1bafee9a8f19a3a0f7122f44d02",
},
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",
key_file: "debug.key",
input_genesis_hash: "0x4e06dc4a01178db42c029f7d65f65a5763702a21082cfcb626c6c41054a7a276",
genesis_state_root: "0x9dddf9df077b2bb98f72686256dae92fb975d416fa3093956151056b913a065d",
input_genesis_hash: "0x7360659a70f5713a4cc30b51e819dacd421047faf3295371cccbd34f7e5536c3",
genesis_state_root: "0xa19f1fad30421e499af8a296f228802da8d41ee45617fac253a41731f1255ecf",
genesis_receipts_root: "0x7e747618f612d08dfe54bcb67f58f13a49e8b1bafee9a8f19a3a0f7122f44d02",
},
];
Expand Down
2 changes: 1 addition & 1 deletion protocol/src/types/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,14 +362,14 @@ mod tests {
}],
consensus_config: ConsensusConfig {
gas_limit: 4294967295,
gas_price: 1,
interval: 3000,
propose_ratio: 15,
prevote_ratio: 10,
precommit_ratio: 10,
brake_ratio: 10,
tx_num_limit: 20000,
max_tx_size: 1024,
max_contract_limit: 0x6000
}
};

Expand Down
Loading

0 comments on commit 344fe85

Please sign in to comment.