Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Synchronize optimization into parallel processing, and replace the calculation of ghost data with validation methods during synchronization to improve efficiency #4192

Merged
merged 32 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ee7104f
add parallel code
jackzhhuang Aug 28, 2024
85b9b45
use try recv to avoid blocking
jackzhhuang Aug 28, 2024
2d672b4
parallel execution
jackzhhuang Aug 28, 2024
e575d6d
create chain when the parents are ready in parallel execution
jackzhhuang Aug 28, 2024
959995e
set executing state in sender
jackzhhuang Aug 28, 2024
8e1744a
check the parents when dispatching
jackzhhuang Aug 28, 2024
03f8b8d
add 10000 buffer for parallel execution
jackzhhuang Aug 29, 2024
b9e34d0
save the block in local store to buffer the block
jackzhhuang Aug 29, 2024
689a478
add log for saving time
jackzhhuang Aug 29, 2024
b086d13
check local store for the absent block
jackzhhuang Aug 29, 2024
1fa8f94
add test case
jackzhhuang Sep 2, 2024
4f26278
add some fix
jackzhhuang Sep 2, 2024
cb4abfe
add some test
jackzhhuang Sep 2, 2024
bcac3fa
add false testing case
jackzhhuang Sep 2, 2024
ccfe95d
add more testing code
jackzhhuang Sep 2, 2024
4e50d66
add check data
jackzhhuang Sep 3, 2024
30ecb99
add verify blue block in verifier
jackzhhuang Sep 3, 2024
a2f64bc
add some code
jackzhhuang Sep 4, 2024
763f1d3
add verification
jackzhhuang Sep 4, 2024
be34e3b
fix some bugs
jackzhhuang Sep 4, 2024
4299894
add yeilding after execution for processing the main chain in other s…
jackzhhuang Sep 4, 2024
8437fe8
finish debug, it works
jackzhhuang Sep 4, 2024
ef84a9b
fmt and clippy
jackzhhuang Sep 5, 2024
d1edfb7
rebase master
jackzhhuang Sep 5, 2024
532d9b6
remove some commented code
jackzhhuang Sep 5, 2024
d46c9ad
fix: return continue if the dag block is ready
jackzhhuang Sep 5, 2024
7d535d6
add loop if the connection of the workers are not closed
jackzhhuang Sep 5, 2024
58fa314
3300000 will be version 1 in vega
jackzhhuang Sep 6, 2024
03981e3
use selected parent to get he parent
jackzhhuang Sep 7, 2024
c5a4093
remove comments
jackzhhuang Sep 7, 2024
6d27f2c
remove bracket
jackzhhuang Sep 7, 2024
96df6fc
fix fmt
jackzhhuang Sep 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion chain/api/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use anyhow::Result;
use starcoin_crypto::HashValue;
use starcoin_dag::types::ghostdata::GhostdagData;
use starcoin_state_api::ChainStateReader;
use starcoin_statedb::ChainStateDB;
use starcoin_time_service::TimeService;
Expand All @@ -22,7 +23,10 @@ pub use starcoin_types::block::ExecutedBlock;
use starcoin_vm_types::access_path::AccessPath;
use starcoin_vm_types::contract_event::ContractEvent;

pub struct VerifiedBlock(pub Block);
pub struct VerifiedBlock {
pub block: Block,
pub ghostdata: Option<GhostdagData>,
}
pub type MintedUncleNumber = u64;

pub trait ChainReader {
Expand Down Expand Up @@ -105,6 +109,11 @@ pub trait ChainReader {
fn current_tips_hash(&self) -> 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>;
}

pub trait ChainWriter {
Expand All @@ -115,6 +124,9 @@ pub trait ChainWriter {
/// Verify, Execute and Connect block to current chain.
fn apply(&mut self, block: Block) -> Result<ExecutedBlock>;

/// Verify, Execute and Connect block to current chain.
fn apply_for_sync(&mut self, block: Block) -> Result<ExecutedBlock>;

fn chain_state(&mut self) -> &ChainStateDB;
}

Expand Down
41 changes: 28 additions & 13 deletions chain/src/chain.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) The Starcoin Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::verifier::{BlockVerifier, DagVerifier, FullVerifier};
use crate::verifier::{BlockVerifier, DagVerifier, DagVerifierWithGhostData, FullVerifier};
use anyhow::{bail, ensure, format_err, Ok, Result};
use sp_utils::stop_watch::{watch, CHAIN_WATCH_NAME};
use starcoin_accumulator::inmemory::InMemoryAccumulator;
Expand Down Expand Up @@ -458,8 +458,8 @@ impl BlockChain {
}

fn execute_dag_block(&mut self, verified_block: VerifiedBlock) -> Result<ExecutedBlock> {
info!("execute dag block:{:?}", verified_block.0);
let block = verified_block.0;
info!("execute dag block:{:?}", verified_block.block);
let block = verified_block.block;
let selected_parent = block.parent_hash();
let block_info_past = self
.storage
Expand Down Expand Up @@ -645,9 +645,16 @@ impl BlockChain {
.storage
.get_block_header_by_hash(self.genesis_hash)?
.ok_or_else(|| format_err!("failed to get genesis because it is none"))?;
let result = self
.dag
.commit(header.to_owned(), genesis_header.parent_hash());
let result = match verified_block.ghostdata {
Some(trusted_ghostdata) => self.dag.commit_trusted_block(
header.to_owned(),
genesis_header.parent_hash(),
Arc::new(trusted_ghostdata),
),
None => self
.dag
.commit(header.to_owned(), genesis_header.parent_hash()),
};
match result {
anyhow::Result::Ok(_) => info!("finish to commit dag block: {:?}", block_id),
Err(e) => {
Expand Down Expand Up @@ -1210,8 +1217,7 @@ impl ChainReader for BlockChain {
}

fn verify(&self, block: Block) -> Result<VerifiedBlock> {
DagVerifier::verify_header(self, block.header())?;
Ok(VerifiedBlock(block))
DagVerifier::verify_block(self, block)
}

fn execute(&mut self, verified_block: VerifiedBlock) -> Result<ExecutedBlock> {
Expand All @@ -1225,7 +1231,7 @@ impl ChainReader for BlockChain {
self.block_accumulator.fork(None),
&self.epoch,
Some(self.status.status.clone()),
verified_block.0,
verified_block.block,
self.vm_metrics.clone(),
)
}
Expand Down Expand Up @@ -1348,6 +1354,14 @@ impl ChainReader for BlockChain {
fn check_chain_type(&self) -> Result<ChainType> {
Ok(ChainType::Dag)
}

fn verify_and_ghostdata(
&self,
uncles: &[BlockHeader],
header: &BlockHeader,
) -> Result<starcoin_dag::types::ghostdata::GhostdagData> {
self.dag().verify_and_ghostdata(uncles, header)
}
Comment on lines +1358 to +1364
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New method for verifying blocks with ghost data.

The addition of verify_and_ghostdata method is a significant enhancement that allows for the verification of blocks along with their ghost data. This method directly supports the PR's objectives by integrating ghost data handling into the block verification process, which is expected to improve the integrity and efficiency of block synchronization.

Consider adding detailed documentation for this method to explain its parameters, expected behavior, and any potential side effects or exceptions it might handle.

Would you like me to help draft the documentation for this new method?

}

impl BlockChain {
Expand Down Expand Up @@ -1467,10 +1481,7 @@ impl BlockChain {
}
// Caculate the ghostdata of the virutal node created by all tips.
// And the ghostdata.selected of the tips will be the latest head.
let block_hash = {
let ghost_of_tips = dag.ghostdata(tips.as_slice())?;
ghost_of_tips.selected_parent
};
let block_hash = dag.ghost_dag_manager().find_selected_parent(tips.iter().copied())?;
let (block, block_info) = {
let block = self
.storage
Expand Down Expand Up @@ -1532,6 +1543,10 @@ impl ChainWriter for BlockChain {
fn chain_state(&mut self) -> &ChainStateDB {
&self.statedb
}

fn apply_for_sync(&mut self, block: Block) -> Result<ExecutedBlock> {
self.apply_with_verifier::<DagVerifierWithGhostData>(block)
}
}

pub(crate) fn info_2_accumulator(
Expand Down
114 changes: 65 additions & 49 deletions chain/src/verifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use starcoin_chain_api::{
verify_block, ChainReader, ConnectBlockError, VerifiedBlock, VerifyBlockField,
};
use starcoin_consensus::{Consensus, ConsensusVerifyError};
use starcoin_dag::types::ghostdata::GhostdagData;
use starcoin_logger::prelude::debug;
use starcoin_open_block::AddressFilter;
use starcoin_types::block::{Block, BlockHeader, ALLOWED_FUTURE_BLOCKTIME};
Expand Down Expand Up @@ -76,13 +77,16 @@ pub trait BlockVerifier {
StaticVerifier::verify_body_hash(&new_block)?;
watch(CHAIN_WATCH_NAME, "n13");
//verify uncles
Self::verify_uncles(
let ghostdata = Self::verify_uncles(
current_chain,
new_block.uncles().unwrap_or_default(),
new_block_header,
)?;
watch(CHAIN_WATCH_NAME, "n14");
Ok(VerifiedBlock(new_block))
Ok(VerifiedBlock {
block: new_block,
ghostdata,
})
Comment on lines +80 to +89
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor suggestion: Consider handling the case where uncles is None.

The method verify_uncles is called with new_block.uncles().unwrap_or_default(), which will default to an empty slice if uncles is None. This could potentially mask issues where uncles data is expected but not present. Consider adding explicit handling or logging to indicate when uncles data is missing.

}

fn verify_blacklisted_txns(new_block: &Block) -> Result<()> {
Expand All @@ -101,7 +105,7 @@ pub trait BlockVerifier {
current_chain: &R,
uncles: &[BlockHeader],
header: &BlockHeader,
) -> Result<()>
) -> Result<Option<GhostdagData>>
where
R: ChainReader,
{
Expand All @@ -118,7 +122,7 @@ pub trait BlockVerifier {
}

if uncles.is_empty() {
return Ok(());
return Ok(None);
}
verify_block!(
VerifyBlockField::Uncle,
Expand Down Expand Up @@ -163,7 +167,7 @@ pub trait BlockVerifier {
Self::verify_header(&uncle_branch, uncle)?;
uncle_ids.insert(uncle_id);
}
Ok(())
Ok(None)
}

fn can_be_uncle<R>(current_chain: &R, block_header: &BlockHeader) -> Result<bool>
Expand Down Expand Up @@ -318,25 +322,27 @@ impl BlockVerifier for NoneVerifier {
where
R: ChainReader,
{
Ok(VerifiedBlock(new_block))
Ok(VerifiedBlock {
block: new_block,
ghostdata: None,
})
}

fn verify_uncles<R>(
_current_chain: &R,
_uncles: &[BlockHeader],
_header: &BlockHeader,
) -> Result<()>
) -> Result<Option<GhostdagData>>
where
R: ChainReader,
{
Ok(())
Ok(None)
}
}

//TODO: Implement it.
pub struct DagVerifier;
impl BlockVerifier for DagVerifier {
fn verify_header<R>(current_chain: &R, new_block_header: &BlockHeader) -> Result<()>
struct BasicDagVerifier;
impl BasicDagVerifier {
pub fn verify_header<R>(current_chain: &R, new_block_header: &BlockHeader) -> Result<()>
where
R: ChainReader,
{
Expand Down Expand Up @@ -380,50 +386,60 @@ impl BlockVerifier for DagVerifier {
ConsensusVerifier::verify_header(current_chain, new_block_header)
}

fn verify_blue_blocks<R>(
current_chain: &R,
uncles: &[BlockHeader],
header: &BlockHeader,
) -> Result<GhostdagData>
where
R: ChainReader,
{
current_chain.verify_and_ghostdata(uncles, header)
}
}
//TODO: Implement it.
pub struct DagVerifier;
impl BlockVerifier for DagVerifier {
fn verify_header<R>(current_chain: &R, new_block_header: &BlockHeader) -> Result<()>
where
R: ChainReader,
{
BasicDagVerifier::verify_header(current_chain, new_block_header)
}

fn verify_uncles<R>(
_current_chain: &R,
_uncles: &[BlockHeader],
_header: &BlockHeader,
) -> Result<()>
) -> Result<Option<GhostdagData>>
where
R: ChainReader,
{
// let mut uncle_ids = HashSet::new();
// for uncle in uncles {
// let uncle_id = uncle.id();
// verify_block!(
// VerifyBlockField::Uncle,
// !uncle_ids.contains(&uncle.id()),
// "repeat uncle {:?} in current block {:?}",
// uncle_id,
// header.id()
// );

// if !header.is_dag() {
// verify_block!(
// VerifyBlockField::Uncle,
// uncle.number() < header.number() ,
// "uncle block number bigger than or equal to current block ,uncle block number is {} , current block number is {}", uncle.number(), header.number()
// );
// }

// verify_block!(
// VerifyBlockField::Uncle,
// current_chain.get_block_info(Some(uncle_id))?.is_some(),
// "Invalid block: uncle {} does not exist",
// uncle_id
// );

// debug!(
// "verify_uncle header number {} hash {:?} uncle number {} hash {:?}",
// header.number(),
// header.id(),
// uncle.number(),
// uncle.id()
// );
// uncle_ids.insert(uncle_id);
// }
Ok(None)
}
}

Ok(())
pub struct DagVerifierWithGhostData;
impl BlockVerifier for DagVerifierWithGhostData {
fn verify_header<R>(current_chain: &R, new_block_header: &BlockHeader) -> Result<()>
where
R: ChainReader,
{
BasicDagVerifier::verify_header(current_chain, new_block_header)
}

fn verify_uncles<R>(
current_chain: &R,
uncles: &[BlockHeader],
header: &BlockHeader,
) -> Result<Option<GhostdagData>>
where
R: ChainReader,
{
Ok(Some(BasicDagVerifier::verify_blue_blocks(
current_chain,
uncles,
header,
)?))
}
}
Loading
Loading