diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 481ab31b59..3330fa0e7c 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -28,6 +28,7 @@ use starcoin_time_service::TimeService; use starcoin_types::block::BlockIdAndNumber; use starcoin_types::contract_event::ContractEventInfo; use starcoin_types::filter::Filter; +use starcoin_types::header::DagHeader; use starcoin_types::startup_info::{ChainInfo, ChainStatus}; use starcoin_types::transaction::RichTransactionInfo; use starcoin_types::{ @@ -72,13 +73,13 @@ impl BlockChain { time_service: Arc, head_block_hash: HashValue, storage: Arc, - dag_store: FlexiDagStorage, vm_metrics: Option, + dag: BlockDAG, ) -> Result { let head = storage .get_block_by_hash(head_block_hash)? .ok_or_else(|| format_err!("Can not find block by hash {:?}", head_block_hash))?; - Self::new_with_uncles(time_service, head, None, storage, vm_metrics, dag_store) + Self::new_with_uncles(time_service, head, None, storage, vm_metrics, dag) } fn new_with_uncles( @@ -87,7 +88,7 @@ impl BlockChain { uncles: Option>, storage: Arc, vm_metrics: Option, - dag_store: FlexiDagStorage, + dag: BlockDAG, ) -> Result { let block_info = storage .get_block_info(head_block.id())? @@ -115,7 +116,6 @@ impl BlockChain { .get_accumulator_snapshot_storage() .get(head_id)? .map(|snapshot| snapshot.child_hashes); - let dag = BlockDAG::new(genesis,16,dag_store), let mut chain = Self { genesis_hash: genesis, time_service, @@ -155,6 +155,7 @@ impl BlockChain { storage: Arc, genesis_epoch: Epoch, genesis_block: Block, + dag_store: FlexiDagStorage, ) -> Result { debug_assert!(genesis_block.header().is_genesis()); let txn_accumulator = MerkleAccumulator::new_empty( @@ -164,7 +165,7 @@ impl BlockChain { storage.get_accumulator_store(AccumulatorStoreType::Block), ); let statedb = ChainStateDB::new(storage.clone().into_super_arc(), None); - + let genesis_header = genesis_block.header.clone(); let genesis_id = genesis_block.header.id(); let executed_block = Self::execute_block_and_save( storage.as_ref(), @@ -190,8 +191,9 @@ impl BlockChain { new_tips, dag_accumulator.get_info(), )?; - - Self::new(time_service, executed_block.block.id(), storage, None) + let mut dag = BlockDAG::new(genesis_id, 16, dag_store); + dag.init_with_genesis(DagHeader::new_genesis(genesis_header))?; + Self::new(time_service, executed_block.block.id(), storage, None, dag) } pub fn current_epoch_uncles_size(&self) -> u64 { @@ -884,6 +886,8 @@ impl ChainReader for BlockChain { uncles, self.storage.clone(), self.vm_metrics.clone(), + //TODO: check missing blocks need to be clean + self.dag.clone(), ) } @@ -1155,7 +1159,6 @@ impl ChainWriter for BlockChain { == executed_block.block().header().parent_hash(); } } - fn connect( &mut self, executed_block: ExecutedBlock, diff --git a/consensus/src/consensusdb/consensus_header.rs b/consensus/src/consensusdb/consensus_header.rs index 3c512afa00..6a9c06fbdc 100644 --- a/consensus/src/consensusdb/consensus_header.rs +++ b/consensus/src/consensusdb/consensus_header.rs @@ -10,7 +10,7 @@ use rocksdb::WriteBatch; use starcoin_crypto::HashValue as Hash; use starcoin_types::{ blockhash::BlockLevel, - header::{CompactHeaderData, ConsensusHeader, Header, HeaderWithBlockLevel}, + header::{CompactHeaderData, ConsensusHeader, DagHeader, HeaderWithBlockLevel}, U256, }; use std::sync::Arc; @@ -20,7 +20,7 @@ pub trait HeaderStoreReader { fn get_blue_score(&self, hash: Hash) -> Result; fn get_timestamp(&self, hash: Hash) -> Result; fn get_difficulty(&self, hash: Hash) -> Result; - fn get_header(&self, hash: Hash) -> Result, StoreError>; + fn get_header(&self, hash: Hash) -> Result, StoreError>; fn get_header_with_block_level(&self, hash: Hash) -> Result; fn get_compact_header_data(&self, hash: Hash) -> Result; } @@ -30,7 +30,7 @@ pub trait HeaderStore: HeaderStoreReader { fn insert( &self, hash: Hash, - header: Arc
, + header: Arc, block_level: BlockLevel, ) -> Result<(), StoreError>; } @@ -108,7 +108,7 @@ impl DbHeadersStore { self.headers_access.has(hash) } - pub fn get_header(&self, hash: Hash) -> Result { + pub fn get_header(&self, hash: Hash) -> Result { let result = self.headers_access.read(hash)?; Ok((*result.header).clone()) } @@ -117,7 +117,7 @@ impl DbHeadersStore { &self, batch: &mut WriteBatch, hash: Hash, - header: Arc
, + header: Arc, block_level: BlockLevel, ) -> Result<(), StoreError> { if self.headers_access.has(hash)? { @@ -166,7 +166,7 @@ impl HeaderStoreReader for DbHeadersStore { Ok(self.compact_headers_access.read(hash)?.difficulty) } - fn get_header(&self, hash: Hash) -> Result, StoreError> { + fn get_header(&self, hash: Hash) -> Result, StoreError> { Ok(self.headers_access.read(hash)?.header) } @@ -186,7 +186,12 @@ impl HeaderStoreReader for DbHeadersStore { } impl HeaderStore for DbHeadersStore { - fn insert(&self, hash: Hash, header: Arc
, block_level: u8) -> Result<(), StoreError> { + fn insert( + &self, + hash: Hash, + header: Arc, + block_level: u8, + ) -> Result<(), StoreError> { if self.headers_access.has(hash)? { return Err(StoreError::KeyAlreadyExists(hash.to_string())); } diff --git a/consensus/src/dag/blockdag.rs b/consensus/src/dag/blockdag.rs index 847dcc2d8a..60bb1a1f74 100644 --- a/consensus/src/dag/blockdag.rs +++ b/consensus/src/dag/blockdag.rs @@ -9,12 +9,12 @@ use crate::consensusdb::{ HeaderStore, ReachabilityStoreReader, RelationsStore, RelationsStoreReader, }, }; -use anyhow::{bail, Ok}; +use anyhow::{anyhow, bail, Ok}; use parking_lot::RwLock; use starcoin_crypto::HashValue as Hash; use starcoin_types::{ blockhash::{BlockHashes, KType, ORIGIN}, - header::{ConsensusHeader, Header}, + header::{ConsensusHeader, DagHeader}, }; use std::collections::HashMap; use std::collections::HashSet; @@ -26,19 +26,21 @@ pub type DbGhostdagManager = GhostdagManager< MTReachabilityService, DbHeadersStore, >; + +#[derive(Clone)] pub struct BlockDAG { - genesis: Header, + genesis_hash: Hash, ghostdag_manager: DbGhostdagManager, relations_store: DbRelationsStore, reachability_store: DbReachabilityStore, ghostdag_store: DbGhostdagStore, header_store: DbHeadersStore, /// orphan blocks, parent hash -> orphan block - missing_blocks: HashMap>, + missing_blocks: HashMap>, } impl BlockDAG { - pub fn new(genesis: Header, k: KType, db: FlexiDagStorage) -> Self { + pub fn new(genesis_hash: Hash, k: KType, db: FlexiDagStorage) -> Self { let ghostdag_store = db.ghost_dag_store.clone(); let header_store = db.header_store.clone(); let relations_store = db.relations_store.clone(); @@ -47,7 +49,7 @@ impl BlockDAG { let reachability_service = MTReachabilityService::new(Arc::new(RwLock::new(reachability_store.clone()))); let ghostdag_manager = DbGhostdagManager::new( - genesis.hash(), + genesis_hash, k, ghostdag_store.clone(), relations_store.clone(), @@ -56,7 +58,7 @@ impl BlockDAG { ); let mut dag = Self { - genesis, + genesis_hash, ghostdag_manager, relations_store, reachability_store, @@ -64,7 +66,6 @@ impl BlockDAG { header_store, missing_blocks: HashMap::new(), }; - dag.init_with_genesis(); dag } @@ -72,22 +73,21 @@ impl BlockDAG { self.missing_blocks.clear(); } - pub fn init_with_genesis(&mut self) -> anyhow::Result<()> { - let exits = self.relations_store.has(Hash::new(ORIGIN))?; - if exits { - return Ok(()); - } + pub fn init_with_genesis(&mut self, genesis: DagHeader) -> anyhow::Result<()> { + if self.relations_store.has(Hash::new(ORIGIN))? { + return Err(anyhow!("Already init with genesis")); + }; self.relations_store .insert(Hash::new(ORIGIN), BlockHashes::new(vec![])) .unwrap(); - self.commit_header(&self.genesis.clone())?; - Ok(()) + self.commit_header(genesis) } - pub fn commit_header(&mut self, header: &Header) -> anyhow::Result<()> { + pub fn commit_header(&mut self, header: DagHeader) -> anyhow::Result<()> { + //TODO:check genesis // Generate ghostdag data let parents_hash = header.parents_hash(); - let ghostdag_data = if header.hash() != self.genesis.hash() { + let ghostdag_data = if header.hash() != self.genesis_hash { self.ghostdag_manager.ghostdag(parents_hash) } else { self.ghostdag_manager.genesis_ghostdag_data() @@ -114,43 +114,43 @@ impl BlockDAG { self.relations_store .insert(header.hash(), BlockHashes::new(parents_hash.to_vec()))?; // Store header store - self.header_store + let _ = self + .header_store .insert(header.hash(), Arc::new(header.to_owned()), 0)?; - Ok(()) } fn is_in_dag(&self, _hash: Hash) -> anyhow::Result { return Ok(true); } - pub fn verify_header(&self, _header: &Header) -> anyhow::Result<()> { + pub fn verify_header(&self, _header: &DagHeader) -> anyhow::Result<()> { //TODO: implemented it Ok(()) } - pub fn connect_block(&mut self, header: &Header) -> anyhow::Result<()> { - let _ = self.verify_header(header)?; - let is_orphan_block = self.update_orphans(header)?; + pub fn connect_block(&mut self, header: DagHeader) -> anyhow::Result<()> { + let _ = self.verify_header(&header)?; + let is_orphan_block = self.update_orphans(&header)?; if is_orphan_block { return Ok(()); } - self.commit_header(header); + self.commit_header(header.clone()); self.check_missing_block(header)?; Ok(()) } - pub fn check_missing_block(&mut self, header: &Header) -> anyhow::Result<()> { + pub fn check_missing_block(&mut self, header: DagHeader) -> anyhow::Result<()> { if let Some(orphans) = self.missing_blocks.remove(&header.hash()) { for orphan in orphans.iter() { let is_orphan = self.is_orphan(&orphan)?; if !is_orphan { - self.commit_header(header); + self.commit_header(header.clone()); } } } Ok(()) } - fn is_orphan(&self, header: &Header) -> anyhow::Result { + fn is_orphan(&self, header: &DagHeader) -> anyhow::Result { for parent in header.parents_hash() { if !self.is_in_dag(parent.to_owned())? { return Ok(false); @@ -159,7 +159,7 @@ impl BlockDAG { return Ok(true); } - fn update_orphans(&mut self, block_header: &Header) -> anyhow::Result { + fn update_orphans(&mut self, block_header: &DagHeader) -> anyhow::Result { let mut is_orphan = false; for parent in block_header.parents_hash() { if self.is_in_dag(parent.to_owned())? { @@ -178,7 +178,7 @@ impl BlockDAG { Ok(is_orphan) } - pub fn get_block_header(&self, hash: Hash) -> anyhow::Result
{ + pub fn get_block_header(&self, hash: Hash) -> anyhow::Result { match self.header_store.get_header(hash) { anyhow::Result::Ok(header) => anyhow::Result::Ok(header), Err(error) => { @@ -218,7 +218,7 @@ impl BlockDAG { } pub fn get_genesis_hash(&self) -> Hash { - self.genesis.hash() + self.genesis_hash } } @@ -228,9 +228,10 @@ mod tests { use crate::consensusdb::prelude::{FlexiDagStorage, FlexiDagStorageConfig}; use starcoin_types::block::BlockHeader; use std::{env, fs}; + #[test] fn base_test() { - let genesis = Header::new(BlockHeader::random(), vec![Hash::new(ORIGIN)]); + let genesis = DagHeader::new_genesis(BlockHeader::random()); let genesis_hash = genesis.hash(); let k = 16; let db_path = env::temp_dir().join("smolstc"); @@ -245,9 +246,9 @@ mod tests { let config = FlexiDagStorageConfig::create_with_params(1, 0, 1024); let db = FlexiDagStorage::create_from_path(db_path, config) .expect("Failed to create flexidag storage"); - let mut dag = BlockDAG::new(genesis, k, db); - - let block = Header::new(BlockHeader::random(), vec![genesis_hash]); - dag.commit_header(&block); + let mut dag = BlockDAG::new(genesis_hash, k, db); + dag.init_with_genesis(genesis); + let block = DagHeader::new(BlockHeader::random(), vec![genesis_hash]); + dag.commit_header(block); } } diff --git a/node/src/node.rs b/node/src/node.rs index d2cf1e13cb..832507bd8e 100644 --- a/node/src/node.rs +++ b/node/src/node.rs @@ -56,7 +56,7 @@ use starcoin_sync::txn_sync::TxnSyncService; use starcoin_sync::verified_rpc_client::VerifiedRpcClient; use starcoin_txpool::TxPoolActorService; use starcoin_types::blockhash::ORIGIN; -use starcoin_types::header::Header; +use starcoin_types::header::DagHeader; use starcoin_types::system_events::{SystemShutdown, SystemStarted}; use starcoin_vm_runtime::metrics::VMMetrics; use std::sync::{Arc, Mutex}; @@ -368,7 +368,7 @@ impl NodeService { .expect("Failed to create flexidag storage"); let dag = BlockDAG::new( - Header::new( + DagHeader::new( genesis.block().header().clone(), vec![HashValue::new(ORIGIN)], ), diff --git a/sync/src/block_connector/test_write_block_chain.rs b/sync/src/block_connector/test_write_block_chain.rs index c995026bb4..389bbf5804 100644 --- a/sync/src/block_connector/test_write_block_chain.rs +++ b/sync/src/block_connector/test_write_block_chain.rs @@ -16,7 +16,7 @@ use starcoin_time_service::TimeService; use starcoin_txpool_mock_service::MockTxPoolService; use starcoin_types::block::Block; use starcoin_types::blockhash::ORIGIN; -use starcoin_types::header::Header; +use starcoin_types::header::DagHeader; use starcoin_types::startup_info::StartupInfo; use std::sync::{Arc, Mutex}; @@ -48,7 +48,7 @@ pub async fn create_writeable_block_chain() -> ( .expect("Failed to create flexidag storage"); let dag = BlockDAG::new( - Header::new( + DagHeader::new( genesis.block().header().clone(), vec![HashValue::new(ORIGIN)], ), diff --git a/sync/src/block_connector/test_write_dag_block_chain.rs b/sync/src/block_connector/test_write_dag_block_chain.rs index c74c9aef83..8381bb6965 100644 --- a/sync/src/block_connector/test_write_dag_block_chain.rs +++ b/sync/src/block_connector/test_write_dag_block_chain.rs @@ -17,7 +17,7 @@ use starcoin_time_service::TimeService; use starcoin_txpool_mock_service::MockTxPoolService; use starcoin_types::block::Block; use starcoin_types::blockhash::ORIGIN; -use starcoin_types::header::Header; +use starcoin_types::header::DagHeader; use starcoin_types::startup_info::StartupInfo; use std::sync::{Arc, Mutex}; diff --git a/types/src/header.rs b/types/src/header.rs index 8c5dcb591b..438bef47f0 100644 --- a/types/src/header.rs +++ b/types/src/header.rs @@ -13,25 +13,33 @@ pub trait ConsensusHeader { } #[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] -pub struct Header { +pub struct DagHeader { block_header: BlockHeader, parents_hash: Vec, } -impl Header { +impl DagHeader { pub fn new(block_header: BlockHeader, parents_hash: Vec) -> Self { Self { block_header, parents_hash, } } + pub fn new_genesis(genesis_header: BlockHeader) -> DagHeader { + Self { + block_header: genesis_header, + parents_hash: vec![Hash::new(ORIGIN)], + } + } +} - pub fn genesis_hash(&self) -> Hash { - Hash::new(ORIGIN) +impl Into for DagHeader { + fn into(self) -> BlockHeader { + self.block_header } } -impl ConsensusHeader for Header { +impl ConsensusHeader for DagHeader { fn parents_hash(&self) -> &[Hash] { &self.parents_hash } @@ -49,7 +57,7 @@ impl ConsensusHeader for Header { #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct HeaderWithBlockLevel { - pub header: Arc
, + pub header: Arc, pub block_level: BlockLevel, }