mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 10:31:04 +00:00
Allow to build_upon skipped entries, but don't walk back (#635)
* Allow to build_upon skipped entries, but don't walk back * Use existing calculated version
This commit is contained in:
committed by
Robert Habermeier
parent
8281618e50
commit
e1d64b1fc7
@@ -446,7 +446,7 @@ impl Drop for AgreementHandle {
|
|||||||
/// This assumes that it is being run in the context of a tokio runtime.
|
/// This assumes that it is being run in the context of a tokio runtime.
|
||||||
pub struct BftService<B: Block, P, I> {
|
pub struct BftService<B: Block, P, I> {
|
||||||
client: Arc<I>,
|
client: Arc<I>,
|
||||||
live_agreement: Mutex<Option<(B::Hash, AgreementHandle)>>,
|
live_agreement: Mutex<Option<(B::Header, AgreementHandle)>>,
|
||||||
round_cache: Arc<Mutex<RoundCache<B::Hash>>>,
|
round_cache: Arc<Mutex<RoundCache<B::Hash>>>,
|
||||||
round_timeout_multiplier: u64,
|
round_timeout_multiplier: u64,
|
||||||
key: Arc<ed25519::Pair>, // TODO: key changing over time.
|
key: Arc<ed25519::Pair>, // TODO: key changing over time.
|
||||||
@@ -565,7 +565,7 @@ impl<B, P, I> BftService<B, P, I>
|
|||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
// cancel current agreement.
|
// cancel current agreement.
|
||||||
*live_agreement = Some((hash, AgreementHandle {
|
*live_agreement = Some((header.clone(), AgreementHandle {
|
||||||
send_cancel: Some(tx),
|
send_cancel: Some(tx),
|
||||||
status: status.clone(),
|
status: status.clone(),
|
||||||
}));
|
}));
|
||||||
@@ -592,12 +592,12 @@ impl<B, P, I> BftService<B, P, I>
|
|||||||
/// Get a reference to the underyling client.
|
/// Get a reference to the underyling client.
|
||||||
pub fn client(&self) -> &I { &*self.client }
|
pub fn client(&self) -> &I { &*self.client }
|
||||||
|
|
||||||
fn can_build_on_inner(&self, header: &B::Header, live: &(B::Hash, AgreementHandle)) -> bool {
|
fn can_build_on_inner(&self, header: &B::Header, live: &(B::Header, AgreementHandle)) -> bool {
|
||||||
let hash = header.hash();
|
let hash = header.hash();
|
||||||
let &(ref live_hash, ref handle) = live;
|
let &(ref live_header, ref handle) = live;
|
||||||
match handle.status() {
|
match handle.status() {
|
||||||
_ if *header.parent_hash() == *live_hash => true, // can always follow with next block.
|
_ if *header != *live_header && *live_header.parent_hash() != hash => true, // can always follow with next block.
|
||||||
status::BAD => hash == *live_hash, // bad block can be re-agreed on.
|
status::BAD => hash == live_header.hash(), // bad block can be re-agreed on.
|
||||||
_ => false, // canceled won't appear since we overwrite the handle before returning.
|
_ => false, // canceled won't appear since we overwrite the handle before returning.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -911,11 +911,11 @@ mod tests {
|
|||||||
let second_hash = second.hash();
|
let second_hash = second.hash();
|
||||||
|
|
||||||
let mut first_bft = service.build_upon(&first).unwrap().unwrap();
|
let mut first_bft = service.build_upon(&first).unwrap().unwrap();
|
||||||
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash);
|
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first);
|
||||||
|
|
||||||
let _second_bft = service.build_upon(&second).unwrap();
|
let _second_bft = service.build_upon(&second).unwrap();
|
||||||
assert!(service.live_agreement.lock().as_ref().unwrap().0 != first_hash);
|
assert!(service.live_agreement.lock().as_ref().unwrap().0 != first);
|
||||||
assert!(service.live_agreement.lock().as_ref().unwrap().0 == second_hash);
|
assert!(service.live_agreement.lock().as_ref().unwrap().0 == second);
|
||||||
|
|
||||||
// first_bft has been cancelled. need to swap out so we can check it.
|
// first_bft has been cancelled. need to swap out so we can check it.
|
||||||
let (_tx, mut rx) = oneshot::channel();
|
let (_tx, mut rx) = oneshot::channel();
|
||||||
@@ -1082,7 +1082,41 @@ mod tests {
|
|||||||
second.parent_hash = first_hash;
|
second.parent_hash = first_hash;
|
||||||
|
|
||||||
let _ = service.build_upon(&first).unwrap();
|
let _ = service.build_upon(&first).unwrap();
|
||||||
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash);
|
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first);
|
||||||
service.live_agreement.lock().take();
|
service.live_agreement.lock().take();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bft_can_build_though_skipped() {
|
||||||
|
let client = FakeClient {
|
||||||
|
authorities: vec![
|
||||||
|
Keyring::One.to_raw_public().into(),
|
||||||
|
Keyring::Two.to_raw_public().into(),
|
||||||
|
Keyring::Alice.to_raw_public().into(),
|
||||||
|
Keyring::Eve.to_raw_public().into(),
|
||||||
|
],
|
||||||
|
imported_heights: Mutex::new(HashSet::new()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let service = make_service(client);
|
||||||
|
|
||||||
|
let first = from_block_number(2);
|
||||||
|
let first_hash = first.hash();
|
||||||
|
|
||||||
|
let mut second = from_block_number(3);
|
||||||
|
second.parent_hash = first_hash;
|
||||||
|
|
||||||
|
let mut third = from_block_number(4);
|
||||||
|
third.parent_hash = second.hash();
|
||||||
|
|
||||||
|
let _ = service.build_upon(&first).unwrap();
|
||||||
|
assert!(service.live_agreement.lock().as_ref().unwrap().0 == first);
|
||||||
|
// BFT has not seen second, but will move forward on third
|
||||||
|
service.build_upon(&third).unwrap();
|
||||||
|
assert!(service.live_agreement.lock().as_ref().unwrap().0 == third);
|
||||||
|
|
||||||
|
// but we are not walking backwards
|
||||||
|
service.build_upon(&second).unwrap();
|
||||||
|
assert!(service.live_agreement.lock().as_ref().unwrap().0 == third);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user