Skip to content

Commit 0d84add

Browse files
committed
Add execute dag
1 parent 48e1d72 commit 0d84add

File tree

7 files changed

+200
-21
lines changed

7 files changed

+200
-21
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chain/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ rand_core = { default-features = false, workspace = true }
1111
sp-utils = { workspace = true }
1212
starcoin-accumulator = { package = "starcoin-accumulator", workspace = true }
1313
starcoin-consensus = { workspace = true }
14+
flexidag = { workspace = true }
1415
starcoin-chain-api = { workspace = true }
1516
starcoin-config = { workspace = true }
1617
starcoin-executor = { package = "starcoin-executor", workspace = true }

chain/src/chain.rs

Lines changed: 193 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use starcoin_chain_api::{
1414
ExecutedBlock, MintedUncleNumber, TransactionInfoWithProof, VerifiedBlock, VerifyBlockField,
1515
};
1616
use starcoin_config::ChainNetworkID;
17-
use starcoin_consensus::dag::types::ghostdata::GhostdagData;
1817
use starcoin_consensus::{BlockDAG, Consensus, FlexiDagStorage};
1918
use starcoin_crypto::hash::PlainCryptoHash;
2019
use starcoin_crypto::HashValue;
@@ -48,6 +47,7 @@ use std::iter::Extend;
4847
use std::option::Option::{None, Some};
4948
use std::{collections::HashMap, sync::Arc};
5049

50+
5151
pub struct ChainStatusWithBlock {
5252
pub status: ChainStatus,
5353
pub head: Block,
@@ -79,6 +79,7 @@ pub struct BlockChain {
7979
vm_metrics: Option<VMMetrics>,
8080
dag_accumulator: Option<MerkleAccumulator>,
8181
net: ChainNetworkID,
82+
dag: BlockDAG,
8283
}
8384

8485
impl BlockChain {
@@ -88,11 +89,18 @@ impl BlockChain {
8889
storage: Arc<dyn Store>,
8990
net: ChainNetworkID,
9091
vm_metrics: Option<VMMetrics>,
92+
dag_store: FlexiDagStorage,
93+
dag_genesis: HashValue,
9194
) -> Result<Self> {
9295
let head = storage
9396
.get_block_by_hash(head_block_hash)?
9497
.ok_or_else(|| format_err!("Can not find block by hash {:?}", head_block_hash))?;
95-
Self::new_with_uncles(time_service, head, None, storage, net, vm_metrics)
98+
let dag_genesis_header = storage
99+
.get_block_header_by_hash(head_block_hash)?
100+
.ok_or_else(|| format_err!("Can not find block by hash {:?}", head_block_hash))?;
101+
let mut dag = BlockDAG::new(dag_genesis, 8, dag_store);
102+
dag.init_with_genesis(DagHeader::new_genesis(dag_genesis_header))?;
103+
Self::new_with_uncles(time_service, head, None, storage, net, vm_metrics, dag)
96104
}
97105

98106
fn get_dag_data(
@@ -124,6 +132,7 @@ impl BlockChain {
124132
storage: Arc<dyn Store>,
125133
net: ChainNetworkID,
126134
vm_metrics: Option<VMMetrics>,
135+
dag: BlockDAG,
127136
) -> Result<Self> {
128137
let block_info = storage
129138
.get_block_info(head_block.id())?
@@ -178,6 +187,7 @@ impl BlockChain {
178187
vm_metrics,
179188
dag_accumulator,
180189
net,
190+
dag,
181191
};
182192
watch(CHAIN_WATCH_NAME, "n1251");
183193
match uncles {
@@ -194,6 +204,8 @@ impl BlockChain {
194204
genesis_epoch: Epoch,
195205
genesis_block: Block,
196206
net: ChainNetworkID,
207+
dag_store: FlexiDagStorage,
208+
dag_genesis: HashValue,
197209
) -> Result<Self> {
198210
debug_assert!(genesis_block.header().is_genesis());
199211
let txn_accumulator = MerkleAccumulator::new_empty(
@@ -227,7 +239,7 @@ impl BlockChain {
227239
new_tips,
228240
dag_accumulator.get_info(),
229241
)?;
230-
Self::new(time_service, executed_block.block.id(), storage, net, None)
242+
Self::new(time_service, executed_block.block.id(), storage, net, None, dag_store, dag_genesis)
231243
}
232244

233245
pub fn current_epoch_uncles_size(&self) -> u64 {
@@ -405,15 +417,15 @@ impl BlockChain {
405417
}
406418

407419
pub fn verify_with_verifier<V>(&mut self, block: Block) -> Result<VerifiedBlock>
408-
where
409-
V: BlockVerifier,
420+
where
421+
V: BlockVerifier,
410422
{
411423
V::verify_block(self, block)
412424
}
413425

414426
pub fn apply_with_verifier<V>(&mut self, block: Block) -> Result<ExecutedBlock>
415-
where
416-
V: BlockVerifier,
427+
where
428+
V: BlockVerifier,
417429
{
418430
let verified_block = self.verify_with_verifier::<V>(block)?;
419431
watch(CHAIN_WATCH_NAME, "n1");
@@ -435,6 +447,166 @@ impl BlockChain {
435447
self.connect(ExecutedBlock { block, block_info })
436448
}
437449

450+
fn execute_dag_block(&self, verified_block: VerifiedBlock) -> Result<ExecutedBlock> {
451+
let block = verified_block.0;
452+
let blues = block.uncles().expect("Blue blocks must exist");
453+
let (selected_parent, blues) = blues.split_at(1);
454+
let selected_parent = selected_parent[0].clone();
455+
let block_info = self.storage.get_block_info(selected_parent.id())?.expect("selected parent must executed");
456+
let header = block.header();
457+
458+
let block_id = header.id();
459+
460+
let block_metadata = block.to_metadata(selected_parent.gas_used());
461+
let mut transaction = vec![Transaction::BlockMetadata(block_metadata)];
462+
for blue in blues {
463+
let blue_block = self.storage.get_block_by_hash(blue.parent_hash())?.expect("block blue need exist");
464+
transaction.extend(blue_block.transactions().iter().cloned().map(Transaction::UserTransaction))
465+
}
466+
transaction.extend(
467+
block.transactions().iter().cloned().map(Transaction::UserTransaction),
468+
);
469+
470+
watch(CHAIN_WATCH_NAME, "n21");
471+
let executed_data = starcoin_executor::block_execute(
472+
&self.statedb,
473+
transaction.clone(),
474+
self.epoch.block_gas_limit(), //TODO: Fix me
475+
self.vm_metrics.clone(),
476+
)?;
477+
watch(CHAIN_WATCH_NAME, "n22");
478+
let state_root = executed_data.state_root;
479+
let vec_transaction_info = &executed_data.txn_infos;
480+
verify_block!(
481+
VerifyBlockField::State,
482+
state_root == header.state_root(),
483+
"verify block:{:?} state_root fail",
484+
block_id,
485+
);
486+
let block_gas_used = vec_transaction_info
487+
.iter()
488+
.fold(0u64, |acc, i| acc.saturating_add(i.gas_used()));
489+
verify_block!(
490+
VerifyBlockField::State,
491+
block_gas_used == header.gas_used(),
492+
"invalid block: gas_used is not match"
493+
);
494+
495+
verify_block!(
496+
VerifyBlockField::State,
497+
vec_transaction_info.len() == transaction.len(),
498+
"invalid txn num in the block"
499+
);
500+
let txn_accumulator= info_2_accumulator(
501+
block_info.txn_accumulator_info,
502+
AccumulatorStoreType::Transaction,
503+
self.storage.as_ref(),
504+
);
505+
let block_accumulator= info_2_accumulator(
506+
block_info.block_accumulator_info,
507+
AccumulatorStoreType::Block,
508+
self.storage.as_ref(),
509+
);
510+
let transaction_global_index = txn_accumulator.num_leaves();
511+
512+
// txn accumulator verify.
513+
let executed_accumulator_root = {
514+
let included_txn_info_hashes: Vec<_> =
515+
vec_transaction_info.iter().map(|info| info.id()).collect();
516+
txn_accumulator.append(&included_txn_info_hashes)?
517+
};
518+
519+
520+
verify_block!(
521+
VerifyBlockField::State,
522+
executed_accumulator_root == header.txn_accumulator_root(),
523+
"verify block: txn accumulator root mismatch"
524+
);
525+
526+
watch(CHAIN_WATCH_NAME, "n23");
527+
self.statedb
528+
.flush()
529+
.map_err(BlockExecutorError::BlockChainStateErr)?;
530+
// If chain state is matched, and accumulator is matched,
531+
// then, we save flush states, and save block data.
532+
watch(CHAIN_WATCH_NAME, "n24");
533+
txn_accumulator
534+
.flush()
535+
.map_err(|_err| BlockExecutorError::BlockAccumulatorFlushErr)?;
536+
537+
let pre_total_difficulty = block_info.total_difficulty;
538+
let total_difficulty = pre_total_difficulty + header.difficulty();
539+
540+
block_accumulator.append(&[block_id])?;
541+
block_accumulator.flush()?;
542+
543+
let txn_accumulator_info: AccumulatorInfo = txn_accumulator.get_info();
544+
let block_accumulator_info: AccumulatorInfo = block_accumulator.get_info();
545+
let block_info = BlockInfo::new(
546+
block_id,
547+
total_difficulty,
548+
txn_accumulator_info,
549+
block_accumulator_info,
550+
);
551+
552+
watch(CHAIN_WATCH_NAME, "n25");
553+
554+
// save block's transaction relationship and save transaction
555+
556+
let block_id = block.id();
557+
let txn_infos = executed_data.txn_infos;
558+
let txn_events = executed_data.txn_events;
559+
let txn_table_infos = executed_data
560+
.txn_table_infos
561+
.into_iter()
562+
.collect::<Vec<_>>();
563+
564+
debug_assert!(
565+
txn_events.len() == txn_infos.len(),
566+
"events' length should be equal to txn infos' length"
567+
);
568+
let txn_info_ids: Vec<_> = txn_infos.iter().map(|info| info.id()).collect();
569+
for (info_id, events) in txn_info_ids.iter().zip(txn_events.into_iter()) {
570+
self.storage.save_contract_events(*info_id, events)?;
571+
}
572+
573+
self.storage.save_transaction_infos(
574+
txn_infos
575+
.into_iter()
576+
.enumerate()
577+
.map(|(transaction_index, info)| {
578+
RichTransactionInfo::new(
579+
block_id,
580+
block.header().number(),
581+
info,
582+
transaction_index as u32,
583+
transaction_global_index
584+
.checked_add(transaction_index as u64)
585+
.expect("transaction_global_index overflow."),
586+
)
587+
})
588+
.collect(),
589+
)?;
590+
591+
let txn_id_vec = transaction
592+
.iter()
593+
.map(|user_txn| user_txn.id())
594+
.collect::<Vec<HashValue>>();
595+
// save transactions
596+
self.storage.save_transaction_batch(transaction)?;
597+
598+
// save block's transactions
599+
self.storage.save_block_transaction_ids(block_id, txn_id_vec)?;
600+
self.storage.save_block_txn_info_ids(block_id, txn_info_ids)?;
601+
self.storage.commit_block(block.clone())?;
602+
self.storage.save_block_info(block_info.clone())?;
603+
604+
self.storage.save_table_infos(txn_table_infos)?;
605+
606+
watch(CHAIN_WATCH_NAME, "n26");
607+
Ok(ExecutedBlock { block, block_info })
608+
}
609+
438610
//TODO consider move this logic to BlockExecutor
439611
fn execute_block_and_save(
440612
storage: &dyn Store,
@@ -682,9 +854,9 @@ impl BlockChain {
682854

683855
return Ok(next_tips_info
684856
== self
685-
.dag_accumulator
686-
.as_ref()
687-
.map(|accumulator| accumulator.get_info()));
857+
.dag_accumulator
858+
.as_ref()
859+
.map(|accumulator| accumulator.get_info()));
688860
}
689861
}
690862

@@ -909,6 +1081,7 @@ impl ChainReader for BlockChain {
9091081
self.storage.clone(),
9101082
self.net.clone(),
9111083
self.vm_metrics.clone(),
1084+
self.dag.clone(),
9121085
//TODO: check missing blocks need to be clean
9131086
)
9141087
}
@@ -957,6 +1130,7 @@ impl ChainReader for BlockChain {
9571130
)
9581131
}
9591132

1133+
9601134
fn get_transaction_infos(
9611135
&self,
9621136
start_index: u64,
@@ -1157,6 +1331,12 @@ impl BlockChain {
11571331
}
11581332
Ok(event_with_infos)
11591333
}
1334+
1335+
fn connect_dag(&mut self, executed_block: ExecutedBlock) -> Result<ExecutedBlock> {
1336+
let (block, block_info) = (executed_block.block(), executed_block.block_info());
1337+
1338+
Ok(executed_block)
1339+
}
11601340
}
11611341

11621342
impl ChainWriter for BlockChain {
@@ -1172,10 +1352,12 @@ impl ChainWriter for BlockChain {
11721352
.expect("dag blocks must have tips")
11731353
.clone(),
11741354
)
1175-
.expect("failed to calculate the tips hash")
1355+
.expect("failed to calculate the tips hash")
11761356
== executed_block.block().header().parent_hash();
11771357
}
11781358
}
1359+
1360+
11791361
fn connect(&mut self, executed_block: ExecutedBlock) -> Result<ExecutedBlock> {
11801362
let (block, block_info) = (executed_block.block(), executed_block.block_info());
11811363
if self.status.status.tips_hash.is_some() {

flexidag/src/blockdag.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub struct BlockDAG {
3838
header_store: DbHeadersStore,
3939
/// orphan blocks, parent hash -> orphan block
4040
missing_blocks: HashMap<Hash, HashSet<DagHeader>>,
41-
4241
}
4342

4443
impl BlockDAG {

node/src/node.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -369,15 +369,10 @@ impl NodeService {
369369
let (chain_info, genesis) =
370370
Genesis::init_and_check_storage(config.net(), storage.clone(), config.data_dir())?;
371371

372-
let flex_dag_config = FlexiDagStorageConfig::create_with_params(1, 0, 1024);
373-
let flex_dag_db = FlexiDagStorage::create_from_path("./smolstc", flex_dag_config)
372+
let flexi_dag_config = FlexiDagStorageConfig::create_with_params(1, 0, 1024);
373+
let flexi_dag_db = FlexiDagStorage::create_from_path("./smolstc", flexi_dag_config)
374374
.expect("Failed to create flexidag storage");
375-
376-
let mut dag = BlockDAG::new(genesis.block().id(), 8, flex_dag_db);
377-
dag.init_with_genesis(DagHeader::new_genesis(genesis.block().header().clone()))
378-
.expect("dag init with genesis");
379-
registry.put_shared(Arc::new(Mutex::new(dag))).await?;
380-
375+
registry.put_shared(flexi_dag_db).await?;
381376
info!(
382377
"Start node with chain info: {}, number {} upgrade_time cost {} secs, ",
383378
chain_info,

types/src/block.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,7 @@ pub struct BlockBody {
620620
pub transactions: Vec<SignedUserTransaction>,
621621
/// uncles block header
622622
pub uncles: Option<Vec<BlockHeader>>,
623+
623624
}
624625

625626
impl BlockBody {

types/src/header.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub trait ConsensusHeader {
1111
fn hash(&self) -> Hash;
1212
fn timestamp(&self) -> u64;
1313
}
14-
14+
//TODO: Remove it and it's store
1515
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
1616
pub struct DagHeader {
1717
block_header: BlockHeader,

0 commit comments

Comments
 (0)