-
Notifications
You must be signed in to change notification settings - Fork 290
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
Fix bug: no store the sync dag block #4259
base: dag-master
Are you sure you want to change the base?
Changes from 13 commits
a6403bc
c173559
48c9bac
c8b259a
1a6c851
264a5d6
3b2a145
197bc4f
adfcb23
e06797d
86ee296
8250159
573bc89
e3dca70
248b7fb
e4eff6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,10 +19,12 @@ use starcoin_logger::prelude::debug; | |
use starcoin_types::{ | ||
block::{BlockHeader, BlockHeaderBuilder, BlockNumber}, | ||
blockhash::{BlockHashMap, HashKTypeMap, KType}, | ||
consensus_header::ConsensusHeader, | ||
U256, | ||
}; | ||
|
||
use std::{ | ||
collections::HashSet, | ||
collections::{HashMap, HashSet}, | ||
ops::{Deref, DerefMut}, | ||
sync::Arc, | ||
time::Instant, | ||
|
@@ -737,6 +739,31 @@ fn add_and_print_with_ghostdata( | |
Ok(header) | ||
} | ||
|
||
fn add_and_print_with_difficulty( | ||
number: BlockNumber, | ||
parent: Hash, | ||
parents: Vec<Hash>, | ||
difficulty: U256, | ||
) -> anyhow::Result<BlockHeader> { | ||
let header_builder = BlockHeaderBuilder::random(); | ||
let header = header_builder | ||
.with_parent_hash(parent) | ||
.with_parents_hash(parents) | ||
.with_number(number) | ||
.with_difficulty(difficulty) | ||
.build(); | ||
let start = Instant::now(); | ||
let duration = start.elapsed(); | ||
println!( | ||
"commit header: {:?}, number: {:?}, duration: {:?}", | ||
header.id(), | ||
header.number(), | ||
duration | ||
); | ||
|
||
Ok(header) | ||
} | ||
Comment on lines
+784
to
+807
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix timing measurement or remove unused timing code. The function includes timing measurement code that doesn't measure any meaningful operation: let start = Instant::now();
let duration = start.elapsed(); Since no significant operation occurs between Apply this diff to fix: fn add_and_print_with_difficulty(
number: BlockNumber,
parent: Hash,
parents: Vec<Hash>,
difficulty: U256,
) -> anyhow::Result<BlockHeader> {
let header_builder = BlockHeaderBuilder::random();
let header = header_builder
.with_parent_hash(parent)
.with_parents_hash(parents)
.with_number(number)
.with_difficulty(difficulty)
.build();
- let start = Instant::now();
- let duration = start.elapsed();
println!(
"commit header: {:?}, number: {:?}, duration: {:?}",
header.id(),
header.number(),
- duration
+ Duration::from_secs(0)
);
Ok(header)
} |
||
|
||
fn add_and_print_with_pruning_point( | ||
number: BlockNumber, | ||
parent: Hash, | ||
|
@@ -751,6 +778,7 @@ fn add_and_print_with_pruning_point( | |
.with_parents_hash(parents) | ||
.with_number(number) | ||
.with_pruning_point(pruning_point) | ||
.with_difficulty(U256::from(10)) | ||
.build(); | ||
let start = Instant::now(); | ||
dag.commit(header.to_owned(), origin)?; | ||
|
@@ -761,10 +789,11 @@ fn add_and_print_with_pruning_point( | |
header.number(), | ||
duration | ||
); | ||
let _ghostdata = dag.ghostdata(&[header.id()])?; | ||
// let ghostdata = dag.ghostdata(&[header.id()])?; | ||
// let ghostdata = dag.ghostdata_by_hash(header.id())?.unwrap(); | ||
// println!( | ||
// "add a header: {:?}, blue set: {:?}, red set: {:?}, blue anticone size: {:?}", | ||
// header, ghostdata.mergeset_blues, ghostdata.mergeset_reds, ghostdata.blues_anticone_sizes | ||
// "add a header: {:?}, selected_parent: {:?}, blue set: {:?}, red set: {:?}, blue anticone size: {:?}", | ||
// header, ghostdata.selected_parent, ghostdata.mergeset_blues, ghostdata.mergeset_reds, ghostdata.blues_anticone_sizes | ||
// ); | ||
Ok(header) | ||
} | ||
|
@@ -1069,6 +1098,193 @@ fn test_prune() -> anyhow::Result<()> { | |
anyhow::Result::Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_verification_blue_block_inconsistent() -> anyhow::Result<()> { | ||
loop_to_blue()?; | ||
anyhow::Result::Ok(()) | ||
} | ||
Comment on lines
+1143
to
+1147
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test coverage with assertions The test function is a simple wrapper around Example improvement: #[test]
fn test_verification_blue_block_inconsistent() -> anyhow::Result<()> {
- loop_to_blue()?;
+ let (dag, last_block) = loop_to_blue()?;
+
+ // Add assertions to verify the expected state
+ let ghost_data = dag.ghostdata(&[last_block.id()])?;
+ assert!(ghost_data.blue_score > 0, "Blue score should be positive");
+ assert!(!ghost_data.mergeset_blues.is_empty(), "Blue set should not be empty");
+
anyhow::Result::Ok(())
}
|
||
|
||
fn loop_to_blue() -> anyhow::Result<()> { | ||
// initialzie the dag firstly | ||
let k = 2; | ||
|
||
let mut dag = BlockDAG::create_for_testing_with_parameters(k).unwrap(); | ||
|
||
let origin = BlockHeaderBuilder::random().with_number(0).build(); | ||
let genesis = BlockHeader::dag_genesis_random_with_parent(origin)?; | ||
|
||
dag.init_with_genesis(genesis.clone()).unwrap(); | ||
|
||
let mut storage = HashMap::new(); | ||
|
||
let block1 = | ||
add_and_print_with_difficulty(1, genesis.id(), vec![genesis.id()], U256::from(10))?; | ||
storage.insert(block1.id(), block1.clone()); | ||
let ghost = dag.ghostdata(&block1.parents())?; | ||
let verified_ghost = dag.verify_and_ghostdata( | ||
&ghost | ||
.mergeset_blues | ||
.iter() | ||
.skip(1) | ||
.cloned() | ||
.map(|x| storage.get(&x).unwrap().clone()) | ||
.collect::<Vec<_>>(), | ||
&block1, | ||
)?; | ||
dag.commit_trusted_block( | ||
block1.clone(), | ||
genesis.parent_hash(), | ||
Arc::new(verified_ghost), | ||
)?; | ||
|
||
let mut bottom = vec![]; | ||
let mut last = block1.clone(); | ||
for i in 0..500 { | ||
let block2 = | ||
add_and_print_with_difficulty(1 + i, last.id(), vec![last.id()], U256::from(10))?; | ||
last = block2.clone(); | ||
storage.insert(block2.id(), block2.clone()); | ||
let ghost = dag.ghostdata(&block2.parents())?; | ||
let verified_ghost = dag.verify_and_ghostdata( | ||
&ghost | ||
.mergeset_blues | ||
.iter() | ||
.skip(1) | ||
.cloned() | ||
.map(|x| storage.get(&x).unwrap().clone()) | ||
.collect::<Vec<_>>(), | ||
&block2, | ||
)?; | ||
dag.commit_trusted_block( | ||
block2.clone(), | ||
genesis.parent_hash(), | ||
Arc::new(verified_ghost), | ||
)?; | ||
bottom.push(block2); | ||
} | ||
|
||
let mut top = vec![]; | ||
let mut iter = bottom.iter().peekable(); | ||
while let Some(first) = iter.next() { | ||
if let Some(second) = iter.next() { | ||
let block = add_and_print_with_difficulty( | ||
3, | ||
first.id(), | ||
vec![first.id(), second.id()], | ||
U256::from(10), | ||
)?; | ||
storage.insert(block.id(), block.clone()); | ||
let ghost = dag.ghostdata(&block.parents())?; | ||
let verified_ghost = dag.verify_and_ghostdata( | ||
&ghost | ||
.mergeset_blues | ||
.iter() | ||
.skip(1) | ||
.cloned() | ||
.map(|x| storage.get(&x).unwrap().clone()) | ||
.collect::<Vec<_>>(), | ||
&block, | ||
)?; | ||
dag.commit_trusted_block( | ||
block.clone(), | ||
genesis.parent_hash(), | ||
Arc::new(verified_ghost), | ||
)?; | ||
|
||
last = block.clone(); | ||
top.push(block); | ||
} else { | ||
let block = add_and_print_with_difficulty( | ||
3, | ||
first.id(), | ||
vec![first.id(), last.id()], | ||
U256::from(10), | ||
)?; | ||
storage.insert(block.id(), block.clone()); | ||
let ghost = dag.ghostdata(&block.parents())?; | ||
let verified_ghost = dag.verify_and_ghostdata( | ||
&ghost | ||
.mergeset_blues | ||
.iter() | ||
.skip(1) | ||
.cloned() | ||
.map(|x| storage.get(&x).unwrap().clone()) | ||
.collect::<Vec<_>>(), | ||
&block, | ||
)?; | ||
dag.commit_trusted_block( | ||
block.clone(), | ||
genesis.parent_hash(), | ||
Arc::new(verified_ghost), | ||
)?; | ||
|
||
top.push(block); | ||
if top.len() == 1 { | ||
last = top[0].clone(); | ||
break; | ||
} else { | ||
bottom.clone_from(&top); | ||
iter = bottom.iter().peekable(); | ||
top.clear(); | ||
} | ||
} | ||
} | ||
|
||
let block1_1 = add_and_print_with_difficulty( | ||
1, | ||
genesis.id(), | ||
vec![last.id(), block1.id()], | ||
U256::from(99999999), | ||
)?; | ||
storage.insert(block1_1.id(), block1_1.clone()); | ||
let ghost = dag.ghostdata(&block1_1.parents())?; | ||
let verified_ghost = dag.verify_and_ghostdata( | ||
&ghost | ||
.mergeset_blues | ||
.iter() | ||
.skip(1) | ||
.cloned() | ||
.map(|x| storage.get(&x).unwrap().clone()) | ||
.collect::<Vec<_>>(), | ||
&block1_1, | ||
)?; | ||
dag.commit_trusted_block( | ||
block1_1.clone(), | ||
genesis.parent_hash(), | ||
Arc::new(verified_ghost), | ||
)?; | ||
|
||
let block3 = add_and_print_with_difficulty( | ||
3, | ||
block1_1.id(), | ||
vec![block1_1.id(), last.id()], | ||
U256::from(10), | ||
)?; | ||
|
||
let ghostdata = dag.ghostdata(&block3.parents())?; | ||
println!( | ||
"add a header: {:?}, selected_parent: {:?}, blue set: {:?}, red set: {:?}, blue anticone size: {:?}", | ||
block3, ghostdata.selected_parent, ghostdata.mergeset_blues, ghostdata.mergeset_reds, ghostdata.blues_anticone_sizes | ||
); | ||
let verified_ghostdata = dag.verify_and_ghostdata( | ||
&ghostdata | ||
.mergeset_blues | ||
.iter() | ||
.skip(1) | ||
.map(|x| dag.storage.header_store.get_header(*x).unwrap()) | ||
.collect::<Vec<_>>(), | ||
&block3, | ||
)?; | ||
println!( | ||
"after verification: selected_parent: {:?}, blue set: {:?}, red set: {:?}, blue anticone size: {:?}", | ||
verified_ghostdata.selected_parent, verified_ghostdata.mergeset_blues, verified_ghostdata.mergeset_reds, verified_ghostdata.blues_anticone_sizes | ||
); | ||
|
||
assert_eq!(ghostdata.mergeset_blues, verified_ghostdata.mergeset_blues); | ||
|
||
anyhow::Ok(()) | ||
} | ||
|
||
#[test] | ||
fn test_verification_blue_block() -> anyhow::Result<()> { | ||
// initialzie the dag firstly | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve blue set verification logic and error handling
The current implementation has several issues:
ghostdag
when blue sets don't match could mask underlying problemsConsider this improved implementation:
This change:
📝 Committable suggestion