Skip to content

Commit

Permalink
Merge 2d3745e into a6f499b
Browse files Browse the repository at this point in the history
  • Loading branch information
jackzhhuang authored Sep 25, 2024
2 parents a6f499b + 2d3745e commit ff8aaf3
Show file tree
Hide file tree
Showing 41 changed files with 1,153 additions and 306 deletions.
4 changes: 3 additions & 1 deletion chain/api/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,16 @@ pub trait ChainReader {
access_path: Option<AccessPath>,
) -> Result<Option<TransactionInfoWithProof>>;

fn current_tips_hash(&self) -> Result<Vec<HashValue>>;
fn current_tips_hash(&self, pruning_point: HashValue) -> Result<Vec<HashValue>>;
fn has_dag_block(&self, header_id: HashValue) -> Result<bool>;
fn check_chain_type(&self) -> Result<ChainType>;
fn verify_and_ghostdata(
&self,
uncles: &[BlockHeader],
header: &BlockHeader,
) -> Result<GhostdagData>;
fn is_dag_ancestor_of(&self, ancestor: HashValue, descendants: Vec<HashValue>) -> Result<bool>;
fn get_pruning_height(&self) -> BlockNumber;
}

pub trait ChainWriter {
Expand Down
7 changes: 6 additions & 1 deletion chain/api/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::{ChainType, TransactionInfoWithProof};
use anyhow::Result;
use starcoin_crypto::HashValue;
use starcoin_dag::consensusdb::consenses_state::DagStateView;
use starcoin_dag::consensusdb::consenses_state::{DagStateView, ReachabilityView};
use starcoin_dag::types::ghostdata::GhostdagData;
use starcoin_service_registry::ServiceRequest;
use starcoin_types::transaction::RichTransactionInfo;
Expand Down Expand Up @@ -68,6 +68,10 @@ pub enum ChainRequest {
GetDagStateView,
CheckChainType,
GetGhostdagData(HashValue),
IsAncestorOfCommand {
ancestor: HashValue,
descendants: Vec<HashValue>,
},
}

impl ServiceRequest for ChainRequest {
Expand Down Expand Up @@ -99,4 +103,5 @@ pub enum ChainResponse {
DagStateView(Box<DagStateView>),
CheckChainType(ChainType),
GhostdagDataOption(Box<Option<GhostdagData>>),
IsAncestorOfCommand { reachability_view: ReachabilityView },
}
24 changes: 23 additions & 1 deletion chain/api/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::message::{ChainRequest, ChainResponse};
use crate::{ChainType, TransactionInfoWithProof};
use anyhow::{bail, Result};
use starcoin_crypto::HashValue;
use starcoin_dag::consensusdb::consenses_state::DagStateView;
use starcoin_dag::consensusdb::consenses_state::{DagStateView, ReachabilityView};
use starcoin_dag::types::ghostdata::GhostdagData;
use starcoin_service_registry::{ActorService, ServiceHandler, ServiceRef};
use starcoin_types::contract_event::{ContractEvent, ContractEventInfo};
Expand Down Expand Up @@ -149,6 +149,11 @@ pub trait ChainAsyncService:
async fn get_dag_state(&self) -> Result<DagStateView>;
async fn check_chain_type(&self) -> Result<ChainType>;
async fn get_ghostdagdata(&self, id: HashValue) -> Result<Option<GhostdagData>>;
async fn is_ancestor_of(
&self,
ancestor: HashValue,
descendants: Vec<HashValue>,
) -> Result<starcoin_dag::consensusdb::consenses_state::ReachabilityView>;
}

#[async_trait::async_trait]
Expand Down Expand Up @@ -486,4 +491,21 @@ where
bail!("failed to get ghostdag data")
}
}
async fn is_ancestor_of(
&self,
ancestor: HashValue,
descendants: Vec<HashValue>,
) -> Result<ReachabilityView> {
let response = self
.send(ChainRequest::IsAncestorOfCommand {
ancestor,
descendants,
})
.await??;
if let ChainResponse::IsAncestorOfCommand { reachability_view } = response {
Ok(reachability_view)
} else {
bail!("failed to get ghostdag data")
}
}
}
89 changes: 87 additions & 2 deletions chain/mock/src/mock_chain.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
// Copyright (c) The Starcoin Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use anyhow::{format_err, Result};
use starcoin_account_api::AccountInfo;
use starcoin_chain::{BlockChain, ChainReader, ChainWriter};
use starcoin_config::ChainNetwork;
use starcoin_consensus::Consensus;
use starcoin_crypto::HashValue;
use starcoin_dag::blockdag::BlockDAG;
use starcoin_dag::blockdag::{BlockDAG, MineNewDagBlockInfo};
use starcoin_genesis::Genesis;
use starcoin_logger::prelude::*;
use starcoin_storage::Storage;
use starcoin_types::block::{Block, BlockHeader};
use starcoin_types::blockhash::KType;
use starcoin_types::startup_info::ChainInfo;
use std::sync::Arc;
use std::vec;
Expand Down Expand Up @@ -39,6 +40,27 @@ impl MockChain {
Ok(Self::new_inner(net, chain, miner, storage))
}

pub fn new_with_params(
net: ChainNetwork,
k: KType,
pruning_depth: u64,
pruning_finality: u64,
) -> Result<Self> {
let (storage, chain_info, _, dag) =
Genesis::init_storage_for_test_with_param(&net, k, pruning_depth, pruning_finality)
.expect("init storage by genesis fail.");

let chain = BlockChain::new(
net.time_service(),
chain_info.head().id(),
storage.clone(),
None,
dag,
)?;
let miner = AccountInfo::random();
Ok(Self::new_inner(net, chain, miner, storage))
}

pub fn new_with_storage(
net: ChainNetwork,
storage: Arc<Storage>,
Expand Down Expand Up @@ -197,6 +219,69 @@ impl MockChain {
.create_block(template, self.net.time_service().as_ref())
}

pub fn produce_block_for_pruning(&mut self) -> Result<Block> {
let tips = self.head.get_dag_state()?.tips;
let ghostdata = self.head.dag().ghost_dag_manager().ghostdag(&tips)?;
let selected_header = self
.head()
.get_storage()
.get_block_header_by_hash(ghostdata.selected_parent)?
.ok_or_else(|| {
format_err!(
"Cannot find block header by hash: {:?}",
ghostdata.selected_parent
)
})?;

let previous_pruning = if selected_header.pruning_point() == HashValue::zero() {
self.head().get_storage().get_genesis()?.unwrap()
} else {
selected_header.pruning_point()
};

let prevous_ghostdata = self
.head()
.dag()
.ghostdata_by_hash(previous_pruning)?
.ok_or_else(|| format_err!("Cannot find ghostdata by hash: {:?}", previous_pruning))?;

let MineNewDagBlockInfo {
tips: pruned_tips,
blue_blocks,
pruning_point,
} = self
.head
.dag()
.calc_mergeset_and_tips(previous_pruning, prevous_ghostdata.as_ref())?;

debug!(
"tips: {:?}, blue_blocks: {:?}, pruning_point: {:?}",
pruned_tips, blue_blocks, pruning_point
);

let (template, _) = self.head.create_block_template_by_header(
*self.miner.address(),
selected_header,
vec![],
blue_blocks[1..]
.iter()
.map(|block_id| {
self.head()
.get_storage()
.get_block_header_by_hash(*block_id)
.unwrap()
.unwrap()
})
.collect(),
None,
pruned_tips,
pruning_point,
)?;
self.head
.consensus()
.create_block(template, self.net.time_service().as_ref())
}

pub fn apply(&mut self, block: Block) -> Result<()> {
self.head.apply(block)?;
Ok(())
Expand Down
6 changes: 6 additions & 0 deletions chain/service/src/chain_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ impl ServiceHandler<Self, ChainRequest> for ChainReaderService {
ChainRequest::GetGhostdagData(id) => Ok(ChainResponse::GhostdagDataOption(Box::new(
self.inner.get_ghostdagdata(id)?,
))),
ChainRequest::IsAncestorOfCommand {
ancestor,
descendants,
} => Ok(ChainResponse::IsAncestorOfCommand {
reachability_view: self.inner.dag.is_ancestor_of(ancestor, descendants)?,
}),
}
}
}
Expand Down
Loading

0 comments on commit ff8aaf3

Please sign in to comment.