-
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 11 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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -181,7 +181,7 @@ impl< | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
!parents.is_empty(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"genesis must be added via a call to init" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let selected_parent = self.find_selected_parent(header.parents_hash().into_iter())?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let selected_parent = self.find_selected_parent(header.parents_hash().into_iter())?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Initialize new GHOSTDAG block data with the selected parent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let mut new_block_data = GhostdagData::new_with_selected_parent(selected_parent, self.k); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let ordered_mergeset = self.sort_blocks( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -210,22 +210,29 @@ impl< | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let remote_blue_set = blue_blocks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.iter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.map(|header| header.id()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.collect::<HashSet<_>>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if new_block_data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.mergeset_blues | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.iter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.skip(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.cloned() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.collect::<HashSet<_>>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
!= blue_blocks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
!= remote_blue_set | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
warn!("The data of blue set is not equal when executing the block: {:?}, for {:?}, checking data: {:?}", header.id(), blue_blocks.iter().map(|header| header.id()).collect::<Vec<_>>(), new_block_data.mergeset_blues); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let ghostdata = self.ghostdag(&header.parents_hash())?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ghostdata | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.mergeset_blues | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.iter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.map(|header| header.id()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.skip(1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.cloned() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.collect::<HashSet<_>>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if header.number() < 10000000 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// no bail before 10000000 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
warn!("The data of blue set is not equal when executing the block: {:?}, for {:?}, checking data: {:?}", header.id(), blue_blocks.iter().map(|header| header.id()).collect::<Vec<_>>(), new_block_data.mergeset_blues); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bail!("The data of blue set is not equal when executing the block: {:?}, for {:?}, checking data: {:?}", header.id(), blue_blocks.iter().map(|header| header.id()).collect::<Vec<_>>(), new_block_data.mergeset_blues); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
!= remote_blue_set | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bail!("The ghost data of blue set is not equal when executing the block: {:?}, for {:?}, checking data: {:?}", header.id(), blue_blocks.iter().map(|header| header.id()).collect::<Vec<_>>(), ghostdata.mergeset_blues); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+213
to
+235
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 Improve blue set verification logic and error handling The current implementation has several issues:
Consider this improved implementation: let remote_blue_set = blue_blocks
.iter()
.map(|header| header.id())
.collect::<HashSet<_>>();
- if new_block_data
+ let calculated_blue_set = new_block_data
.mergeset_blues
.iter()
.skip(1)
.cloned()
- .collect::<HashSet<_>>()
- != remote_blue_set
- {
- warn!("The data of blue set is not equal when executing the block: {:?}, for {:?}, checking data: {:?}", header.id(), blue_blocks.iter().map(|header| header.id()).collect::<Vec<_>>(), new_block_data.mergeset_blues);
- let ghostdata = self.ghostdag(&header.parents_hash())?;
- if ghostdata
- .mergeset_blues
- .iter()
- .skip(1)
- .cloned()
- .collect::<HashSet<_>>()
- != remote_blue_set
- {
- bail!("The ghost data of blue set is not equal when executing the block: {:?}, for {:?}, checking data: {:?}", header.id(), blue_blocks.iter().map(|header| header.id()).collect::<Vec<_>>(), ghostdata.mergeset_blues);
- }
- }
+ .collect::<HashSet<_>>();
+
+ if calculated_blue_set != remote_blue_set {
+ let missing_blues: Vec<_> = remote_blue_set.difference(&calculated_blue_set).collect();
+ let extra_blues: Vec<_> = calculated_blue_set.difference(&remote_blue_set).collect();
+
+ bail!(
+ "Blue set mismatch for block {:?}:\nExpected blues: {:?}\nCalculated blues: {:?}\nMissing blues: {:?}\nExtra blues: {:?}",
+ header.id(),
+ remote_blue_set,
+ calculated_blue_set,
+ missing_blues,
+ extra_blues
+ );
+ } This change:
📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -383,6 +390,10 @@ impl< | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if *candidate_blues_anticone_sizes.get(&block).unwrap() == self.k { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// k-cluster violation: A block in candidate's blue anticone already | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// has k blue blocks in its own anticone | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
info!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Checking blue candidate: {} failed, block {} has k blue blocks in its anticone", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
blue_candidate, block | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Ok(ColoringState::Red); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -431,6 +442,7 @@ impl< | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// The maximum length of new_block_data.mergeset_blues can be K+1 because | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// it contains the selected parent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if new_block_data.mergeset_blues.len() as KType == self.k.checked_add(1).unwrap() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
info!("Checking blue candidate: {} failed, mergeset blues size is K+1", blue_candidate); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Ok(ColoringOutput::Red); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,12 +17,11 @@ use starcoin_dag::{ | |
}; | ||
use starcoin_logger::prelude::debug; | ||
use starcoin_types::{ | ||
block::{BlockHeader, BlockHeaderBuilder, BlockNumber}, | ||
blockhash::{BlockHashMap, HashKTypeMap, KType}, | ||
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 +736,39 @@ fn add_and_print_with_ghostdata( | |
Ok(header) | ||
} | ||
|
||
fn add_and_print_with_difficulty( | ||
number: BlockNumber, | ||
parent: Hash, | ||
parents: Vec<Hash>, | ||
origin: Hash, | ||
difficulty: U256, | ||
dag: &mut BlockDAG, | ||
) -> 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(); | ||
// dag.commit(header.to_owned(), origin)?; | ||
let duration = start.elapsed(); | ||
println!( | ||
"commit header: {:?}, number: {:?}, duration: {:?}", | ||
header.id(), | ||
header.number(), | ||
duration | ||
); | ||
// let ghostdata = dag.ghostdata(&[header.id()])?; | ||
// let ghostdata = dag.ghostdata_by_hash(header.id())?.unwrap(); | ||
// println!( | ||
// "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) | ||
} | ||
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. Uncomment the block commit to ensure blocks are added to the DAG In the // dag.commit(header.to_owned(), origin)?; This means the block header is created but not actually committed, which could lead to inconsistent DAG state or missing blocks during tests. Apply this diff to fix the issue: -// dag.commit(header.to_owned(), origin)?;
+dag.commit(header.to_owned(), origin)?; |
||
|
||
fn add_and_print_with_pruning_point( | ||
number: BlockNumber, | ||
parent: Hash, | ||
|
@@ -751,6 +783,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 +794,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 +1103,150 @@ 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()], | ||
genesis.parent_hash(), | ||
U256::from(10), | ||
&mut dag, | ||
)?; | ||
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()], | ||
genesis.parent_hash(), | ||
U256::from(10), | ||
&mut dag, | ||
)?; | ||
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()], | ||
genesis.parent_hash(), | ||
U256::from(10), | ||
&mut dag, | ||
)?; | ||
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()], | ||
genesis.parent_hash(), | ||
U256::from(10), | ||
&mut dag, | ||
)?; | ||
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 = top.clone(); | ||
iter = bottom.iter().peekable(); | ||
top.clear(); | ||
} | ||
} | ||
} | ||
|
||
let block1_1 = add_and_print_with_difficulty( | ||
1, | ||
genesis.id(), | ||
vec![last.id(), block1.id()], | ||
genesis.parent_hash(), | ||
U256::from(99999999), | ||
&mut dag, | ||
)?; | ||
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()], | ||
genesis.parent_hash(), | ||
U256::from(10), | ||
&mut dag, | ||
)?; | ||
|
||
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.
Critical: Incorrect parent selection logic
The change bypasses the GHOSTDAG parent selection algorithm by directly using
header.parents_hash()
instead of finding the parent with the highest blue work. This violates the GHOSTDAG protocol specification and could lead to consensus issues.Apply this fix: