Skip to content

Commit

Permalink
feat: allow users to configure hardfork information in chain spec, th…
Browse files Browse the repository at this point in the history
…e default is the latest version
  • Loading branch information
driftluo committed Sep 8, 2023
1 parent 5005294 commit 592e7ca
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 34 deletions.
38 changes: 34 additions & 4 deletions common/config-parser/src/types/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use clap::builder::{StringValueParser, TypedValueParser, ValueParserFactory};
use serde::Deserialize;

use protocol::{
codec::deserialize_address,
types::{Block, Bytes, Header, RichBlock, SignedTransaction, H160, U256},
codec::{deserialize_address, ProtocolCodec},
types::{Block, HardforkInfoInner, Header, RichBlock, SignedTransaction, H160, H256, U256},
};

use crate::parse_file;
Expand All @@ -27,7 +27,7 @@ pub struct ChainSpec {
#[derive(Clone, Debug, Deserialize)]
pub struct Genesis {
pub timestamp: u64,
pub extra_data: Bytes,
pub extra_data: HarforkInput,
pub base_fee_per_gas: U256,
pub chain_id: u64,

Expand Down Expand Up @@ -128,10 +128,40 @@ impl Genesis {
pub fn build_header(&self) -> Header {
Header {
timestamp: self.timestamp,
extra_data: self.extra_data.clone(),
// todo: if Hardforkinput is empty, it must change to latest hardfork info to init
// genesis
extra_data: Into::<HardforkInfoInner>::into(self.extra_data.clone())
.encode()
.unwrap(),
base_fee_per_gas: self.base_fee_per_gas,
chain_id: self.chain_id,
..Default::default()
}
}
}

#[derive(Clone, Debug, Deserialize)]
pub struct HarforkInput {
block_number: u64,
hardforks: Vec<HardforkType>,
}

impl From<HarforkInput> for HardforkInfoInner {
fn from(value: HarforkInput) -> Self {
let flags = {
let r = value.hardforks.into_iter().fold(0, |acc, s| acc | s as u64);

H256::from_low_u64_be(r.to_be())
};

HardforkInfoInner {
block_number: value.block_number,
flags,
}
}
}

#[derive(Clone, Debug, Deserialize, Copy)]
enum HardforkType {
None = 0b0,
}
14 changes: 14 additions & 0 deletions core/consensus/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,20 @@ where
.get_metadata_by_epoch(epoch)
}

async fn get_metadata_root(
&self,
state_root: Hash,
proposal: &Proposal,
) -> ProtocolResult<Hash> {
let backend = AxonExecutorApplyAdapter::from_root(
state_root,
Arc::clone(&self.trie_db),
Arc::clone(&self.storage),
proposal.clone().into(),
)?;
Ok(backend.get_metadata_root())
}

#[trace_span(kind = "consensus.adapter")]
async fn broadcast_number(&self, ctx: Context, number: u64) -> ProtocolResult<()> {
self.network
Expand Down
41 changes: 30 additions & 11 deletions core/consensus/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use common_apm_derive::trace_span;
use common_crypto::BlsPublicKey;
use common_logger::{json, log};
use common_merkle::TrieMerkle;
use core_executor::MetadataHandle;
use protocol::traits::{ConsensusAdapter, Context, MessageTarget, NodeInfo};
use protocol::types::{
Block, BlockVersion, Bytes, ExecResp, Hash, Hex, Metadata, Proof, Proposal, SignedTransaction,
Expand Down Expand Up @@ -81,6 +82,22 @@ impl<Adapter: ConsensusAdapter + 'static> Engine<Proposal> for ConsensusEngine<A
RLP_NULL
};

let extra_data_hardfork = {
let mut hardfork = self.node_info.hardfork_proposals.write().unwrap();
match &*hardfork {
Some(v) => {
// remove invalid proposal
if v.block_number <= next_number {
hardfork.take();
Default::default()
} else {
v.encode().unwrap()
}
}
None => Default::default(),
}
};

let proposal = Proposal {
version: BlockVersion::V0,
prev_hash: status.prev_hash,
Expand All @@ -91,15 +108,7 @@ impl<Adapter: ConsensusAdapter + 'static> Engine<Proposal> for ConsensusEngine<A
timestamp: time_now(),
number: next_number,
gas_limit: MAX_BLOCK_GAS_LIMIT.into(),
extra_data: {
self.node_info
.hardfork_proposals
.read()
.unwrap()
.as_ref()
.map(|v| v.encode().unwrap())
.unwrap_or_default()
},
extra_data: extra_data_hardfork,
base_fee_per_gas: BASE_FEE_PER_GAS.into(),
proof: status.proof,
chain_id: self.node_info.chain_id,
Expand Down Expand Up @@ -633,12 +642,22 @@ impl<Adapter: ConsensusAdapter + 'static> ConsensusEngine<Adapter> {
// Save the block
self.adapter.save_block(ctx.clone(), block.clone()).await?;

if let Ok(data) = HardforkInfoInner::decode(&block.header.extra_data) {
let root = self
.adapter
.get_metadata_root(
block.header.state_root,
&Proposal::new_without_state_root(&block.header),
)
.await?;
let handle = MetadataHandle::new(root);
let hardforks = handle.hardfork_infos()?;

if let Some(data) = hardforks.inner.last() {
let mut self_proposal = self.node_info.hardfork_proposals.write().unwrap();

if self_proposal
.as_ref()
.map(|v| v == &data)
.map(|v| data.flags & v.flags == v.flags)
.unwrap_or_default()
{
// remove self hardfork proposal
Expand Down
8 changes: 8 additions & 0 deletions core/consensus/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,14 @@ impl CommonConsensusAdapter for MockSyncAdapter {
Ok(Metadata::default())
}

async fn get_metadata_root(
&self,
state_root: Hash,
proposal: &Proposal,
) -> ProtocolResult<Hash> {
Ok(H256::zero())
}

async fn broadcast_number(&self, ctx: Context, height: u64) -> ProtocolResult<()> {
Ok(())
}
Expand Down
9 changes: 0 additions & 9 deletions core/executor/src/system_contract/metadata/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,4 @@ impl MetadataHandle {
HARDFORK_INFO.swap(Arc::new(hardfork));
Ok(())
}

// this function use to init an axon chain with genesis block
pub fn set_current_hardfork_info(&self, info: H256) -> ProtocolResult<()> {
let mut store = MetadataStore::new(self.root)?;

store.set_hardfork_info(0, info)?;

Ok(())
}
}
8 changes: 4 additions & 4 deletions core/executor/src/system_contract/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,6 @@ impl<Adapter: ExecutorAdapter + ApplyBackend> SystemContract<Adapter>

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();
Expand All @@ -134,6 +130,10 @@ impl<Adapter: ExecutorAdapter + ApplyBackend> SystemContract<Adapter>

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)
}
Expand Down
6 changes: 3 additions & 3 deletions core/run/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,23 @@ const TESTCASES: &[TestCase] = &[
chain_name: "single_node",
config_file: "config.toml",
chain_spec_file: "specs/single_node/chain-spec.toml",
input_genesis_hash: "0x2043f690fc6e086c6940a083072a82dee16c18a4c4afaf6f4e1c7a585fae2543",
input_genesis_hash: "0x800456ba35af2363e015d780521421ba263767d9089be95816f6f077aa48547a",
genesis_state_root: "0x601bd874d41eb9adb32021ee3ab934e0481065c58abfe7e757e33fb01be18dd5",
genesis_receipts_root: "0x8544b530238201f1620b139861a6841040b37f78f8bdae8736ef5cec474e979b",
},
TestCase {
chain_name: "multi_nodes",
config_file: "nodes/node_1.toml",
chain_spec_file: "specs/multi_nodes/chain-spec.toml",
input_genesis_hash: "0x5e5c47725bb1face59965a326b1d69e1ada1892da2e2f53c4520ed5da3d88d59",
input_genesis_hash: "0x9ef66e89ca4a36f98ea7ddc177dc37aae5b795c27c2e3e1fdf0a52ee1f439dc1",
genesis_state_root: "0xc36f75519a047fec6a34c7be5dfca783a40eafa0d7418ad7b3ba99ad9c2dc655",
genesis_receipts_root: "0x8544b530238201f1620b139861a6841040b37f78f8bdae8736ef5cec474e979b",
},
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: "0x2043f690fc6e086c6940a083072a82dee16c18a4c4afaf6f4e1c7a585fae2543",
input_genesis_hash: "0x800456ba35af2363e015d780521421ba263767d9089be95816f6f077aa48547a",
genesis_state_root: "0x42886558baab8a3c310d5a8313398e5f353cc4f8192838b578c857a329e9bb65",
genesis_receipts_root: "0x8544b530238201f1620b139861a6841040b37f78f8bdae8736ef5cec474e979b",
},
Expand Down
5 changes: 4 additions & 1 deletion devtools/chain/specs/multi_nodes/chain-spec.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

[genesis]
timestamp = 1680249207
extra_data = []
base_fee_per_gas = "0x539"
chain_id = 2022
# A JSON file which includes all transactions in the genesis block.
transactions = "genesis_transactions.json"

[genesis.extra_data]
block_number = 0
hardforks = []

#
# Accounts since the genesis block.
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

[genesis]
timestamp = 1679656015
extra_data = []
base_fee_per_gas = "0x539"
chain_id = 2022
# A JSON file which includes all transactions in the genesis block.
transactions = "genesis_transactions.json"

[genesis.extra_data]
block_number = 0
hardforks = []

#
# Accounts since the genesis block.
#
Expand Down
5 changes: 4 additions & 1 deletion devtools/chain/specs/single_node/chain-spec.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

[genesis]
timestamp = 1679656015
extra_data = []
base_fee_per_gas = "0x539"
chain_id = 2022
# A JSON file which includes all transactions in the genesis block.
transactions = "genesis_transactions.json"

[genesis.extra_data]
block_number = 0
hardforks = []

#
# Accounts since the genesis block.
#
Expand Down
6 changes: 6 additions & 0 deletions protocol/src/traits/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ pub trait CommonConsensusAdapter: Send + Sync {

async fn get_metadata_by_epoch(&self, epoch: u64) -> ProtocolResult<Metadata>;

async fn get_metadata_root(
&self,
state_root: Hash,
proposal: &Proposal,
) -> ProtocolResult<Hash>;

async fn broadcast_number(&self, ctx: Context, height: u64) -> ProtocolResult<()>;

fn set_args(&self, context: Context, state_root: MerkleRoot, gas_limit: u64, max_tx_size: u64);
Expand Down

0 comments on commit 592e7ca

Please sign in to comment.