mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 19:17:58 +00:00
cargo +nightly fmt (#3540)
* cargo +nightly fmt * add cargo-fmt check to ci * update ci * fmt * fmt * skip macro * ignore bridges
This commit is contained in:
@@ -25,7 +25,7 @@ use polkadot_primitives::v1::{BlockNumber, Hash};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{Error, LeafEntrySet, BlockEntry, Timestamp};
|
||||
use crate::{BlockEntry, Error, LeafEntrySet, Timestamp};
|
||||
|
||||
pub(super) enum BackendWriteOp {
|
||||
WriteBlockEntry(BlockEntry),
|
||||
@@ -47,8 +47,10 @@ pub(super) trait Backend {
|
||||
fn load_stagnant_at(&self, timestamp: Timestamp) -> Result<Vec<Hash>, Error>;
|
||||
/// Load all stagnant lists up to and including the given Unix timestamp
|
||||
/// in ascending order.
|
||||
fn load_stagnant_at_up_to(&self, up_to: Timestamp)
|
||||
-> Result<Vec<(Timestamp, Vec<Hash>)>, Error>;
|
||||
fn load_stagnant_at_up_to(
|
||||
&self,
|
||||
up_to: Timestamp,
|
||||
) -> Result<Vec<(Timestamp, Vec<Hash>)>, Error>;
|
||||
/// Load the earliest kept block number.
|
||||
fn load_first_block_number(&self) -> Result<Option<BlockNumber>, Error>;
|
||||
/// Load blocks by number.
|
||||
@@ -56,7 +58,8 @@ pub(super) trait Backend {
|
||||
|
||||
/// Atomically write the list of operations, with later operations taking precedence over prior.
|
||||
fn write<I>(&mut self, ops: I) -> Result<(), Error>
|
||||
where I: IntoIterator<Item = BackendWriteOp>;
|
||||
where
|
||||
I: IntoIterator<Item = BackendWriteOp>;
|
||||
}
|
||||
|
||||
/// An in-memory overlay over the backend.
|
||||
@@ -98,7 +101,7 @@ impl<'a, B: 'a + Backend> OverlayedBackend<'a, B> {
|
||||
|
||||
pub(super) fn load_blocks_by_number(&self, number: BlockNumber) -> Result<Vec<Hash>, Error> {
|
||||
if let Some(val) = self.blocks_by_number.get(&number) {
|
||||
return Ok(val.as_ref().map_or(Vec::new(), Clone::clone));
|
||||
return Ok(val.as_ref().map_or(Vec::new(), Clone::clone))
|
||||
}
|
||||
|
||||
self.inner.load_blocks_by_number(number)
|
||||
@@ -114,7 +117,7 @@ impl<'a, B: 'a + Backend> OverlayedBackend<'a, B> {
|
||||
|
||||
pub(super) fn load_stagnant_at(&self, timestamp: Timestamp) -> Result<Vec<Hash>, Error> {
|
||||
if let Some(val) = self.stagnant_at.get(×tamp) {
|
||||
return Ok(val.as_ref().map_or(Vec::new(), Clone::clone));
|
||||
return Ok(val.as_ref().map_or(Vec::new(), Clone::clone))
|
||||
}
|
||||
|
||||
self.inner.load_stagnant_at(timestamp)
|
||||
@@ -188,17 +191,15 @@ impl<'a, B: 'a + Backend> OverlayedBackend<'a, B> {
|
||||
/// return true if `ancestor` is in `head`'s chain.
|
||||
///
|
||||
/// If the ancestor is an older finalized block, this will return `false`.
|
||||
fn contains_ancestor(
|
||||
backend: &impl Backend,
|
||||
head: Hash,
|
||||
ancestor: Hash,
|
||||
) -> Result<bool, Error> {
|
||||
fn contains_ancestor(backend: &impl Backend, head: Hash, ancestor: Hash) -> Result<bool, Error> {
|
||||
let mut current_hash = head;
|
||||
loop {
|
||||
if current_hash == ancestor { return Ok(true) }
|
||||
if current_hash == ancestor {
|
||||
return Ok(true)
|
||||
}
|
||||
match backend.load_block_entry(¤t_hash)? {
|
||||
Some(e) => { current_hash = e.parent_hash }
|
||||
None => break
|
||||
Some(e) => current_hash = e.parent_hash,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,14 +32,16 @@
|
||||
//! The `Vec`s stored are always non-empty. Empty `Vec`s are not stored on disk so there is no
|
||||
//! semantic difference between `None` and an empty `Vec`.
|
||||
|
||||
use crate::backend::{Backend, BackendWriteOp};
|
||||
use crate::Error;
|
||||
use crate::{
|
||||
backend::{Backend, BackendWriteOp},
|
||||
Error,
|
||||
};
|
||||
|
||||
use polkadot_primitives::v1::{BlockNumber, Hash};
|
||||
use polkadot_node_primitives::BlockWeight;
|
||||
use polkadot_primitives::v1::{BlockNumber, Hash};
|
||||
|
||||
use kvdb::{DBTransaction, KeyValueDB};
|
||||
use parity_scale_codec::{Encode, Decode};
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -116,11 +118,7 @@ struct LeafEntry {
|
||||
|
||||
impl From<crate::LeafEntry> for LeafEntry {
|
||||
fn from(x: crate::LeafEntry) -> Self {
|
||||
LeafEntry {
|
||||
weight: x.weight,
|
||||
block_number: x.block_number,
|
||||
block_hash: x.block_hash,
|
||||
}
|
||||
LeafEntry { weight: x.weight, block_number: x.block_number, block_hash: x.block_hash }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,17 +139,13 @@ struct LeafEntrySet {
|
||||
|
||||
impl From<crate::LeafEntrySet> for LeafEntrySet {
|
||||
fn from(x: crate::LeafEntrySet) -> Self {
|
||||
LeafEntrySet {
|
||||
inner: x.inner.into_iter().map(Into::into).collect(),
|
||||
}
|
||||
LeafEntrySet { inner: x.inner.into_iter().map(Into::into).collect() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LeafEntrySet> for crate::LeafEntrySet {
|
||||
fn from(x: LeafEntrySet) -> crate::LeafEntrySet {
|
||||
crate::LeafEntrySet {
|
||||
inner: x.inner.into_iter().map(Into::into).collect(),
|
||||
}
|
||||
crate::LeafEntrySet { inner: x.inner.into_iter().map(Into::into).collect() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,28 +202,19 @@ impl DbBackend {
|
||||
/// Create a new [`DbBackend`] with the supplied key-value store and
|
||||
/// config.
|
||||
pub fn new(db: Arc<dyn KeyValueDB>, config: Config) -> Self {
|
||||
DbBackend {
|
||||
inner: db,
|
||||
config,
|
||||
}
|
||||
DbBackend { inner: db, config }
|
||||
}
|
||||
}
|
||||
|
||||
impl Backend for DbBackend {
|
||||
fn load_block_entry(&self, hash: &Hash) -> Result<Option<crate::BlockEntry>, Error> {
|
||||
load_decode::<BlockEntry>(
|
||||
&*self.inner,
|
||||
self.config.col_data,
|
||||
&block_entry_key(hash),
|
||||
).map(|o| o.map(Into::into))
|
||||
load_decode::<BlockEntry>(&*self.inner, self.config.col_data, &block_entry_key(hash))
|
||||
.map(|o| o.map(Into::into))
|
||||
}
|
||||
|
||||
fn load_leaves(&self) -> Result<crate::LeafEntrySet, Error> {
|
||||
load_decode::<LeafEntrySet>(
|
||||
&*self.inner,
|
||||
self.config.col_data,
|
||||
LEAVES_KEY,
|
||||
).map(|o| o.map(Into::into).unwrap_or_default())
|
||||
load_decode::<LeafEntrySet>(&*self.inner, self.config.col_data, LEAVES_KEY)
|
||||
.map(|o| o.map(Into::into).unwrap_or_default())
|
||||
}
|
||||
|
||||
fn load_stagnant_at(&self, timestamp: crate::Timestamp) -> Result<Vec<Hash>, Error> {
|
||||
@@ -237,16 +222,16 @@ impl Backend for DbBackend {
|
||||
&*self.inner,
|
||||
self.config.col_data,
|
||||
&stagnant_at_key(timestamp.into()),
|
||||
).map(|o| o.unwrap_or_default())
|
||||
)
|
||||
.map(|o| o.unwrap_or_default())
|
||||
}
|
||||
|
||||
fn load_stagnant_at_up_to(&self, up_to: crate::Timestamp)
|
||||
-> Result<Vec<(crate::Timestamp, Vec<Hash>)>, Error>
|
||||
{
|
||||
let stagnant_at_iter = self.inner.iter_with_prefix(
|
||||
self.config.col_data,
|
||||
&STAGNANT_AT_PREFIX[..],
|
||||
);
|
||||
fn load_stagnant_at_up_to(
|
||||
&self,
|
||||
up_to: crate::Timestamp,
|
||||
) -> Result<Vec<(crate::Timestamp, Vec<Hash>)>, Error> {
|
||||
let stagnant_at_iter =
|
||||
self.inner.iter_with_prefix(self.config.col_data, &STAGNANT_AT_PREFIX[..]);
|
||||
|
||||
let val = stagnant_at_iter
|
||||
.filter_map(|(k, v)| {
|
||||
@@ -262,10 +247,8 @@ impl Backend for DbBackend {
|
||||
}
|
||||
|
||||
fn load_first_block_number(&self) -> Result<Option<BlockNumber>, Error> {
|
||||
let blocks_at_height_iter = self.inner.iter_with_prefix(
|
||||
self.config.col_data,
|
||||
&BLOCK_HEIGHT_PREFIX[..],
|
||||
);
|
||||
let blocks_at_height_iter =
|
||||
self.inner.iter_with_prefix(self.config.col_data, &BLOCK_HEIGHT_PREFIX[..]);
|
||||
|
||||
let val = blocks_at_height_iter
|
||||
.filter_map(|(k, _)| decode_block_height_key(&k[..]))
|
||||
@@ -275,16 +258,14 @@ impl Backend for DbBackend {
|
||||
}
|
||||
|
||||
fn load_blocks_by_number(&self, number: BlockNumber) -> Result<Vec<Hash>, Error> {
|
||||
load_decode::<Vec<Hash>>(
|
||||
&*self.inner,
|
||||
self.config.col_data,
|
||||
&block_height_key(number),
|
||||
).map(|o| o.unwrap_or_default())
|
||||
load_decode::<Vec<Hash>>(&*self.inner, self.config.col_data, &block_height_key(number))
|
||||
.map(|o| o.unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Atomically write the list of operations, with later operations taking precedence over prior.
|
||||
fn write<I>(&mut self, ops: I) -> Result<(), Error>
|
||||
where I: IntoIterator<Item = BackendWriteOp>
|
||||
where
|
||||
I: IntoIterator<Item = BackendWriteOp>,
|
||||
{
|
||||
let mut tx = DBTransaction::new();
|
||||
for op in ops {
|
||||
@@ -296,43 +277,29 @@ impl Backend for DbBackend {
|
||||
&block_entry_key(&block_entry.block_hash),
|
||||
block_entry.encode(),
|
||||
);
|
||||
}
|
||||
BackendWriteOp::WriteBlocksByNumber(block_number, v) => {
|
||||
},
|
||||
BackendWriteOp::WriteBlocksByNumber(block_number, v) =>
|
||||
if v.is_empty() {
|
||||
tx.delete(
|
||||
self.config.col_data,
|
||||
&block_height_key(block_number),
|
||||
);
|
||||
tx.delete(self.config.col_data, &block_height_key(block_number));
|
||||
} else {
|
||||
tx.put_vec(
|
||||
self.config.col_data,
|
||||
&block_height_key(block_number),
|
||||
v.encode(),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
BackendWriteOp::WriteViableLeaves(leaves) => {
|
||||
let leaves: LeafEntrySet = leaves.into();
|
||||
if leaves.inner.is_empty() {
|
||||
tx.delete(
|
||||
self.config.col_data,
|
||||
&LEAVES_KEY[..],
|
||||
);
|
||||
tx.delete(self.config.col_data, &LEAVES_KEY[..]);
|
||||
} else {
|
||||
tx.put_vec(
|
||||
self.config.col_data,
|
||||
&LEAVES_KEY[..],
|
||||
leaves.encode(),
|
||||
);
|
||||
tx.put_vec(self.config.col_data, &LEAVES_KEY[..], leaves.encode());
|
||||
}
|
||||
}
|
||||
},
|
||||
BackendWriteOp::WriteStagnantAt(timestamp, stagnant_at) => {
|
||||
let timestamp: Timestamp = timestamp.into();
|
||||
if stagnant_at.is_empty() {
|
||||
tx.delete(
|
||||
self.config.col_data,
|
||||
&stagnant_at_key(timestamp),
|
||||
);
|
||||
tx.delete(self.config.col_data, &stagnant_at_key(timestamp));
|
||||
} else {
|
||||
tx.put_vec(
|
||||
self.config.col_data,
|
||||
@@ -340,26 +307,17 @@ impl Backend for DbBackend {
|
||||
stagnant_at.encode(),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
BackendWriteOp::DeleteBlocksByNumber(block_number) => {
|
||||
tx.delete(
|
||||
self.config.col_data,
|
||||
&block_height_key(block_number),
|
||||
);
|
||||
}
|
||||
tx.delete(self.config.col_data, &block_height_key(block_number));
|
||||
},
|
||||
BackendWriteOp::DeleteBlockEntry(hash) => {
|
||||
tx.delete(
|
||||
self.config.col_data,
|
||||
&block_entry_key(&hash),
|
||||
);
|
||||
}
|
||||
tx.delete(self.config.col_data, &block_entry_key(&hash));
|
||||
},
|
||||
BackendWriteOp::DeleteStagnantAt(timestamp) => {
|
||||
let timestamp: Timestamp = timestamp.into();
|
||||
tx.delete(
|
||||
self.config.col_data,
|
||||
&stagnant_at_key(timestamp),
|
||||
);
|
||||
}
|
||||
tx.delete(self.config.col_data, &stagnant_at_key(timestamp));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,9 +332,7 @@ fn load_decode<D: Decode>(
|
||||
) -> Result<Option<D>, Error> {
|
||||
match db.get(col_data, key)? {
|
||||
None => Ok(None),
|
||||
Some(raw) => D::decode(&mut &raw[..])
|
||||
.map(Some)
|
||||
.map_err(Into::into),
|
||||
Some(raw) => D::decode(&mut &raw[..]).map(Some).map_err(Into::into),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,8 +358,12 @@ fn stagnant_at_key(timestamp: Timestamp) -> [u8; 14 + 8] {
|
||||
}
|
||||
|
||||
fn decode_block_height_key(key: &[u8]) -> Option<BlockNumber> {
|
||||
if key.len() != 15 + 4 { return None }
|
||||
if !key.starts_with(BLOCK_HEIGHT_PREFIX) { return None }
|
||||
if key.len() != 15 + 4 {
|
||||
return None
|
||||
}
|
||||
if !key.starts_with(BLOCK_HEIGHT_PREFIX) {
|
||||
return None
|
||||
}
|
||||
|
||||
let mut bytes = [0; 4];
|
||||
bytes.copy_from_slice(&key[15..]);
|
||||
@@ -411,8 +371,12 @@ fn decode_block_height_key(key: &[u8]) -> Option<BlockNumber> {
|
||||
}
|
||||
|
||||
fn decode_stagnant_at_key(key: &[u8]) -> Option<Timestamp> {
|
||||
if key.len() != 14 + 8 { return None }
|
||||
if !key.starts_with(STAGNANT_AT_PREFIX) { return None }
|
||||
if key.len() != 14 + 8 {
|
||||
return None
|
||||
}
|
||||
if !key.starts_with(STAGNANT_AT_PREFIX) {
|
||||
return None
|
||||
}
|
||||
|
||||
let mut bytes = [0; 8];
|
||||
bytes.copy_from_slice(&key[14..]);
|
||||
@@ -479,9 +443,9 @@ mod tests {
|
||||
weight: 100,
|
||||
};
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteBlockEntry(block_entry.clone().into())
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![BackendWriteOp::WriteBlockEntry(block_entry.clone().into())])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_block_entry(&block_entry.block_hash).unwrap().map(BlockEntry::from),
|
||||
@@ -509,17 +473,15 @@ mod tests {
|
||||
weight: 100,
|
||||
};
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteBlockEntry(block_entry.clone().into())
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![BackendWriteOp::WriteBlockEntry(block_entry.clone().into())])
|
||||
.unwrap();
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::DeleteBlockEntry(block_entry.block_hash),
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![BackendWriteOp::DeleteBlockEntry(block_entry.block_hash)])
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
backend.load_block_entry(&block_entry.block_hash).unwrap().is_none(),
|
||||
);
|
||||
assert!(backend.load_block_entry(&block_entry.block_hash).unwrap().is_none(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -529,30 +491,26 @@ mod tests {
|
||||
|
||||
let mut backend = DbBackend::new(db, config);
|
||||
|
||||
assert!(
|
||||
backend.load_first_block_number().unwrap().is_none(),
|
||||
);
|
||||
assert!(backend.load_first_block_number().unwrap().is_none(),);
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![Hash::repeat_byte(0)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(5, vec![Hash::repeat_byte(0)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(10, vec![Hash::repeat_byte(0)]),
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![Hash::repeat_byte(0)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(5, vec![Hash::repeat_byte(0)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(10, vec![Hash::repeat_byte(0)]),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_first_block_number().unwrap(),
|
||||
Some(2),
|
||||
);
|
||||
assert_eq!(backend.load_first_block_number().unwrap(), Some(2),);
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![]),
|
||||
BackendWriteOp::DeleteBlocksByNumber(5),
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![]),
|
||||
BackendWriteOp::DeleteBlocksByNumber(5),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_first_block_number().unwrap(),
|
||||
Some(10),
|
||||
);
|
||||
assert_eq!(backend.load_first_block_number().unwrap(), Some(10),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -563,15 +521,15 @@ mod tests {
|
||||
let mut backend = DbBackend::new(db, config);
|
||||
|
||||
// Prove that it's cheap
|
||||
assert!(
|
||||
backend.load_stagnant_at_up_to(Timestamp::max_value()).unwrap().is_empty(),
|
||||
);
|
||||
assert!(backend.load_stagnant_at_up_to(Timestamp::max_value()).unwrap().is_empty(),);
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteStagnantAt(2, vec![Hash::repeat_byte(1)]),
|
||||
BackendWriteOp::WriteStagnantAt(5, vec![Hash::repeat_byte(2)]),
|
||||
BackendWriteOp::WriteStagnantAt(10, vec![Hash::repeat_byte(3)]),
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![
|
||||
BackendWriteOp::WriteStagnantAt(2, vec![Hash::repeat_byte(1)]),
|
||||
BackendWriteOp::WriteStagnantAt(5, vec![Hash::repeat_byte(2)]),
|
||||
BackendWriteOp::WriteStagnantAt(10, vec![Hash::repeat_byte(3)]),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_stagnant_at_up_to(Timestamp::max_value()).unwrap(),
|
||||
@@ -593,32 +551,21 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
backend.load_stagnant_at_up_to(9).unwrap(),
|
||||
vec![
|
||||
(2, vec![Hash::repeat_byte(1)]),
|
||||
(5, vec![Hash::repeat_byte(2)]),
|
||||
]
|
||||
vec![(2, vec![Hash::repeat_byte(1)]), (5, vec![Hash::repeat_byte(2)]),]
|
||||
);
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::DeleteStagnantAt(2),
|
||||
]).unwrap();
|
||||
backend.write(vec![BackendWriteOp::DeleteStagnantAt(2)]).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_stagnant_at_up_to(5).unwrap(),
|
||||
vec![
|
||||
(5, vec![Hash::repeat_byte(2)]),
|
||||
]
|
||||
vec![(5, vec![Hash::repeat_byte(2)]),]
|
||||
);
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteStagnantAt(5, vec![]),
|
||||
]).unwrap();
|
||||
backend.write(vec![BackendWriteOp::WriteStagnantAt(5, vec![])]).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_stagnant_at_up_to(10).unwrap(),
|
||||
vec![
|
||||
(10, vec![Hash::repeat_byte(3)]),
|
||||
]
|
||||
vec![(10, vec![Hash::repeat_byte(3)]),]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -629,40 +576,29 @@ mod tests {
|
||||
|
||||
let mut backend = DbBackend::new(db, config);
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![Hash::repeat_byte(1)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(5, vec![Hash::repeat_byte(2)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(10, vec![Hash::repeat_byte(3)]),
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![Hash::repeat_byte(1)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(5, vec![Hash::repeat_byte(2)]),
|
||||
BackendWriteOp::WriteBlocksByNumber(10, vec![Hash::repeat_byte(3)]),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_blocks_by_number(2).unwrap(),
|
||||
vec![Hash::repeat_byte(1)],
|
||||
);
|
||||
assert_eq!(backend.load_blocks_by_number(2).unwrap(), vec![Hash::repeat_byte(1)],);
|
||||
|
||||
assert_eq!(
|
||||
backend.load_blocks_by_number(3).unwrap(),
|
||||
vec![],
|
||||
);
|
||||
assert_eq!(backend.load_blocks_by_number(3).unwrap(), vec![],);
|
||||
|
||||
backend.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![]),
|
||||
BackendWriteOp::DeleteBlocksByNumber(5),
|
||||
]).unwrap();
|
||||
backend
|
||||
.write(vec![
|
||||
BackendWriteOp::WriteBlocksByNumber(2, vec![]),
|
||||
BackendWriteOp::DeleteBlocksByNumber(5),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
backend.load_blocks_by_number(2).unwrap(),
|
||||
vec![],
|
||||
);
|
||||
assert_eq!(backend.load_blocks_by_number(2).unwrap(), vec![],);
|
||||
|
||||
assert_eq!(
|
||||
backend.load_blocks_by_number(5).unwrap(),
|
||||
vec![],
|
||||
);
|
||||
assert_eq!(backend.load_blocks_by_number(5).unwrap(), vec![],);
|
||||
|
||||
assert_eq!(
|
||||
backend.load_blocks_by_number(10).unwrap(),
|
||||
vec![Hash::repeat_byte(3)],
|
||||
);
|
||||
assert_eq!(backend.load_blocks_by_number(10).unwrap(), vec![Hash::repeat_byte(3)],);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,25 +16,24 @@
|
||||
|
||||
//! Implements the Chain Selection Subsystem.
|
||||
|
||||
use polkadot_primitives::v1::{BlockNumber, Hash, Header, ConsensusLog};
|
||||
use polkadot_node_primitives::BlockWeight;
|
||||
use polkadot_node_subsystem::{
|
||||
overseer, SubsystemContext, SubsystemError, SpawnedSubsystem,
|
||||
OverseerSignal, FromOverseer,
|
||||
messages::{ChainSelectionMessage, ChainApiMessage},
|
||||
errors::ChainApiError,
|
||||
messages::{ChainApiMessage, ChainSelectionMessage},
|
||||
overseer, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemContext, SubsystemError,
|
||||
};
|
||||
use polkadot_primitives::v1::{BlockNumber, ConsensusLog, Hash, Header};
|
||||
|
||||
use futures::{channel::oneshot, future::Either, prelude::*};
|
||||
use kvdb::KeyValueDB;
|
||||
use parity_scale_codec::Error as CodecError;
|
||||
use futures::channel::oneshot;
|
||||
use futures::future::Either;
|
||||
use futures::prelude::*;
|
||||
|
||||
use std::time::{UNIX_EPOCH, Duration,SystemTime};
|
||||
use std::sync::Arc;
|
||||
use std::{
|
||||
sync::Arc,
|
||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use crate::backend::{Backend, OverlayedBackend, BackendWriteOp};
|
||||
use crate::backend::{Backend, BackendWriteOp, OverlayedBackend};
|
||||
|
||||
mod backend;
|
||||
mod db_backend;
|
||||
@@ -108,16 +107,19 @@ struct LeafEntry {
|
||||
|
||||
impl PartialOrd for LeafEntry {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
let ord = self.weight.cmp(&other.weight)
|
||||
.then(self.block_number.cmp(&other.block_number));
|
||||
let ord = self.weight.cmp(&other.weight).then(self.block_number.cmp(&other.block_number));
|
||||
|
||||
if !matches!(ord, std::cmp::Ordering::Equal) { Some(ord) } else { None }
|
||||
if !matches!(ord, std::cmp::Ordering::Equal) {
|
||||
Some(ord)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
struct LeafEntrySet {
|
||||
inner: Vec<LeafEntry>
|
||||
inner: Vec<LeafEntry>,
|
||||
}
|
||||
|
||||
impl LeafEntrySet {
|
||||
@@ -127,14 +129,16 @@ impl LeafEntrySet {
|
||||
Some(i) => {
|
||||
self.inner.remove(i);
|
||||
true
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, new: LeafEntry) {
|
||||
let mut pos = None;
|
||||
for (i, e) in self.inner.iter().enumerate() {
|
||||
if e == &new { return }
|
||||
if e == &new {
|
||||
return
|
||||
}
|
||||
if e < &new {
|
||||
pos = Some(i);
|
||||
break
|
||||
@@ -238,7 +242,7 @@ impl Clock for SystemClock {
|
||||
);
|
||||
|
||||
0
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,10 +313,7 @@ impl ChainSelectionSubsystem {
|
||||
/// Create a new instance of the subsystem with the given config
|
||||
/// and key-value store.
|
||||
pub fn new(config: Config, db: Arc<dyn KeyValueDB>) -> Self {
|
||||
ChainSelectionSubsystem {
|
||||
config,
|
||||
db,
|
||||
}
|
||||
ChainSelectionSubsystem { config, db }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,12 +329,7 @@ where
|
||||
);
|
||||
|
||||
SpawnedSubsystem {
|
||||
future: run(
|
||||
ctx,
|
||||
backend,
|
||||
self.config.stagnant_check_interval,
|
||||
Box::new(SystemClock),
|
||||
)
|
||||
future: run(ctx, backend, self.config.stagnant_check_interval, Box::new(SystemClock))
|
||||
.map(Ok)
|
||||
.boxed(),
|
||||
name: "chain-selection-subsystem",
|
||||
@@ -346,31 +342,25 @@ async fn run<Context, B>(
|
||||
mut backend: B,
|
||||
stagnant_check_interval: StagnantCheckInterval,
|
||||
clock: Box<dyn Clock + Send + Sync>,
|
||||
)
|
||||
where
|
||||
Context: SubsystemContext<Message = ChainSelectionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainSelectionMessage>,
|
||||
B: Backend,
|
||||
) where
|
||||
Context: SubsystemContext<Message = ChainSelectionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainSelectionMessage>,
|
||||
B: Backend,
|
||||
{
|
||||
loop {
|
||||
let res = run_iteration(
|
||||
&mut ctx,
|
||||
&mut backend,
|
||||
&stagnant_check_interval,
|
||||
&*clock,
|
||||
).await;
|
||||
let res = run_iteration(&mut ctx, &mut backend, &stagnant_check_interval, &*clock).await;
|
||||
match res {
|
||||
Err(e) => {
|
||||
e.trace();
|
||||
|
||||
if let Error::Subsystem(SubsystemError::Context(_)) = e {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
Ok(()) => {
|
||||
tracing::info!(target: LOG_TARGET, "received `Conclude` signal, exiting");
|
||||
break;
|
||||
}
|
||||
break
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,12 +375,11 @@ async fn run_iteration<Context, B>(
|
||||
backend: &mut B,
|
||||
stagnant_check_interval: &StagnantCheckInterval,
|
||||
clock: &(dyn Clock + Sync),
|
||||
)
|
||||
-> Result<(), Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = ChainSelectionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainSelectionMessage>,
|
||||
B: Backend,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = ChainSelectionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainSelectionMessage>,
|
||||
B: Backend,
|
||||
{
|
||||
let mut stagnant_check_stream = stagnant_check_interval.timeout_stream();
|
||||
loop {
|
||||
@@ -461,15 +450,11 @@ async fn fetch_finalized(
|
||||
|
||||
match hash_rx.await?? {
|
||||
None => {
|
||||
tracing::warn!(
|
||||
target: LOG_TARGET,
|
||||
number,
|
||||
"Missing hash for finalized block number"
|
||||
);
|
||||
tracing::warn!(target: LOG_TARGET, number, "Missing hash for finalized block number");
|
||||
|
||||
return Ok(None)
|
||||
}
|
||||
Some(h) => Ok(Some((h, number)))
|
||||
},
|
||||
Some(h) => Ok(Some((h, number))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,13 +497,9 @@ async fn handle_active_leaf(
|
||||
|
||||
let header = match fetch_header(ctx, hash).await? {
|
||||
None => {
|
||||
tracing::warn!(
|
||||
target: LOG_TARGET,
|
||||
?hash,
|
||||
"Missing header for new head",
|
||||
);
|
||||
tracing::warn!(target: LOG_TARGET, ?hash, "Missing header for new head",);
|
||||
return Ok(Vec::new())
|
||||
}
|
||||
},
|
||||
Some(h) => h,
|
||||
};
|
||||
|
||||
@@ -528,7 +509,8 @@ async fn handle_active_leaf(
|
||||
hash,
|
||||
&header,
|
||||
lower_bound,
|
||||
).await?;
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut overlay = OverlayedBackend::new(backend);
|
||||
|
||||
@@ -545,8 +527,8 @@ async fn handle_active_leaf(
|
||||
|
||||
// If we don't know the weight, we can't import the block.
|
||||
// And none of its descendants either.
|
||||
break;
|
||||
}
|
||||
break
|
||||
},
|
||||
Some(w) => w,
|
||||
};
|
||||
|
||||
@@ -570,7 +552,9 @@ async fn handle_active_leaf(
|
||||
// Ignores logs with number >= the block header number.
|
||||
fn extract_reversion_logs(header: &Header) -> Vec<BlockNumber> {
|
||||
let number = header.number;
|
||||
let mut logs = header.digest.logs()
|
||||
let mut logs = header
|
||||
.digest
|
||||
.logs()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, d)| match ConsensusLog::from_digest_item(d) {
|
||||
@@ -584,7 +568,7 @@ fn extract_reversion_logs(header: &Header) -> Vec<BlockNumber> {
|
||||
);
|
||||
|
||||
None
|
||||
}
|
||||
},
|
||||
Ok(Some(ConsensusLog::Revert(b))) if b < number => Some(b),
|
||||
Ok(Some(ConsensusLog::Revert(b))) => {
|
||||
tracing::warn!(
|
||||
@@ -596,7 +580,7 @@ fn extract_reversion_logs(header: &Header) -> Vec<BlockNumber> {
|
||||
);
|
||||
|
||||
None
|
||||
}
|
||||
},
|
||||
Ok(_) => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -612,27 +596,18 @@ fn handle_finalized_block(
|
||||
finalized_hash: Hash,
|
||||
finalized_number: BlockNumber,
|
||||
) -> Result<(), Error> {
|
||||
let ops = crate::tree::finalize_block(
|
||||
&*backend,
|
||||
finalized_hash,
|
||||
finalized_number,
|
||||
)?.into_write_ops();
|
||||
let ops =
|
||||
crate::tree::finalize_block(&*backend, finalized_hash, finalized_number)?.into_write_ops();
|
||||
|
||||
backend.write(ops)
|
||||
}
|
||||
|
||||
// Handle an approved block event.
|
||||
fn handle_approved_block(
|
||||
backend: &mut impl Backend,
|
||||
approved_block: Hash,
|
||||
) -> Result<(), Error> {
|
||||
fn handle_approved_block(backend: &mut impl Backend, approved_block: Hash) -> Result<(), Error> {
|
||||
let ops = {
|
||||
let mut overlay = OverlayedBackend::new(&*backend);
|
||||
|
||||
crate::tree::approve_block(
|
||||
&mut overlay,
|
||||
approved_block,
|
||||
)?;
|
||||
crate::tree::approve_block(&mut overlay, approved_block)?;
|
||||
|
||||
overlay.into_write_ops()
|
||||
};
|
||||
@@ -640,15 +615,9 @@ fn handle_approved_block(
|
||||
backend.write(ops)
|
||||
}
|
||||
|
||||
fn detect_stagnant(
|
||||
backend: &mut impl Backend,
|
||||
now: Timestamp,
|
||||
) -> Result<(), Error> {
|
||||
fn detect_stagnant(backend: &mut impl Backend, now: Timestamp) -> Result<(), Error> {
|
||||
let ops = {
|
||||
let overlay = crate::tree::detect_stagnant(
|
||||
&*backend,
|
||||
now,
|
||||
)?;
|
||||
let overlay = crate::tree::detect_stagnant(&*backend, now)?;
|
||||
|
||||
overlay.into_write_ops()
|
||||
};
|
||||
@@ -662,9 +631,7 @@ async fn load_leaves(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
backend: &impl Backend,
|
||||
) -> Result<Vec<Hash>, Error> {
|
||||
let leaves: Vec<_> = backend.load_leaves()?
|
||||
.into_hashes_descending()
|
||||
.collect();
|
||||
let leaves: Vec<_> = backend.load_leaves()?.into_hashes_descending().collect();
|
||||
|
||||
if leaves.is_empty() {
|
||||
Ok(fetch_finalized(ctx).await?.map_or(Vec::new(), |(h, _)| vec![h]))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,17 +23,12 @@
|
||||
//! Each direct descendant of the finalized block acts as its own sub-tree,
|
||||
//! and as the finalized block advances, orphaned sub-trees are entirely pruned.
|
||||
|
||||
use polkadot_primitives::v1::{BlockNumber, Hash};
|
||||
use polkadot_node_primitives::BlockWeight;
|
||||
|
||||
use polkadot_primitives::v1::{BlockNumber, Hash};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{
|
||||
LOG_TARGET,
|
||||
Approval, BlockEntry, Error, LeafEntry, ViabilityCriteria,
|
||||
Timestamp,
|
||||
};
|
||||
use super::{Approval, BlockEntry, Error, LeafEntry, Timestamp, ViabilityCriteria, LOG_TARGET};
|
||||
use crate::backend::{Backend, OverlayedBackend};
|
||||
|
||||
// A viability update to be applied to a block.
|
||||
@@ -43,10 +38,7 @@ impl ViabilityUpdate {
|
||||
// Apply the viability update to a single block, yielding the updated
|
||||
// block entry along with a vector of children and the updates to apply
|
||||
// to them.
|
||||
fn apply(self, mut entry: BlockEntry) -> (
|
||||
BlockEntry,
|
||||
Vec<(Hash, ViabilityUpdate)>
|
||||
) {
|
||||
fn apply(self, mut entry: BlockEntry) -> (BlockEntry, Vec<(Hash, ViabilityUpdate)>) {
|
||||
// 1. When an ancestor has changed from unviable to viable,
|
||||
// we erase the `earliest_unviable_ancestor` of all descendants
|
||||
// until encountering a explicitly unviable descendant D.
|
||||
@@ -81,7 +73,9 @@ impl ViabilityUpdate {
|
||||
};
|
||||
entry.viability.earliest_unviable_ancestor = maybe_earliest_unviable;
|
||||
|
||||
let recurse = entry.children.iter()
|
||||
let recurse = entry
|
||||
.children
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(move |c| (c, ViabilityUpdate(next_earliest_unviable)))
|
||||
.collect();
|
||||
@@ -152,10 +146,10 @@ fn propagate_viability_update(
|
||||
"Missing expected block entry"
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
Some(entry) => entry,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let (new_entry, children) = update.apply(entry);
|
||||
@@ -184,9 +178,8 @@ fn propagate_viability_update(
|
||||
|
||||
backend.write_block_entry(new_entry);
|
||||
|
||||
tree_frontier.extend(
|
||||
children.into_iter().map(|(h, update)| (BlockEntryRef::Hash(h), update))
|
||||
);
|
||||
tree_frontier
|
||||
.extend(children.into_iter().map(|(h, update)| (BlockEntryRef::Hash(h), update)));
|
||||
}
|
||||
|
||||
// Revisit the viability pivots now that we've traversed the entire subtree.
|
||||
@@ -229,12 +222,11 @@ fn propagate_viability_update(
|
||||
// Furthermore, if the set of viable leaves is empty, the
|
||||
// finalized block is implicitly the viable leaf.
|
||||
continue
|
||||
}
|
||||
Some(entry) => {
|
||||
},
|
||||
Some(entry) =>
|
||||
if entry.children.len() == pivot_count {
|
||||
viable_leaves.insert(entry.leaf_entry());
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,12 +246,7 @@ pub(crate) fn import_block(
|
||||
stagnant_at: Timestamp,
|
||||
) -> Result<(), Error> {
|
||||
add_block(backend, block_hash, block_number, parent_hash, weight, stagnant_at)?;
|
||||
apply_reversions(
|
||||
backend,
|
||||
block_hash,
|
||||
block_number,
|
||||
reversion_logs,
|
||||
)?;
|
||||
apply_reversions(backend, block_hash, block_number, reversion_logs)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -276,7 +263,9 @@ fn load_ancestor(
|
||||
block_number: BlockNumber,
|
||||
ancestor_number: BlockNumber,
|
||||
) -> Result<Option<BlockEntry>, Error> {
|
||||
if block_number <= ancestor_number { return Ok(None) }
|
||||
if block_number <= ancestor_number {
|
||||
return Ok(None)
|
||||
}
|
||||
|
||||
let mut current_hash = block_hash;
|
||||
let mut current_entry = None;
|
||||
@@ -289,7 +278,7 @@ fn load_ancestor(
|
||||
let parent_hash = entry.parent_hash;
|
||||
current_entry = Some(entry);
|
||||
current_hash = parent_hash;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,24 +303,22 @@ fn add_block(
|
||||
let mut leaves = backend.load_leaves()?;
|
||||
let parent_entry = backend.load_block_entry(&parent_hash)?;
|
||||
|
||||
let inherited_viability = parent_entry.as_ref()
|
||||
.and_then(|parent| parent.non_viable_ancestor_for_child());
|
||||
let inherited_viability =
|
||||
parent_entry.as_ref().and_then(|parent| parent.non_viable_ancestor_for_child());
|
||||
|
||||
// 1. Add the block to the DB assuming it's not reverted.
|
||||
backend.write_block_entry(
|
||||
BlockEntry {
|
||||
block_hash,
|
||||
block_number,
|
||||
parent_hash,
|
||||
children: Vec::new(),
|
||||
viability: ViabilityCriteria {
|
||||
earliest_unviable_ancestor: inherited_viability,
|
||||
explicitly_reverted: false,
|
||||
approval: Approval::Unapproved,
|
||||
},
|
||||
weight,
|
||||
}
|
||||
);
|
||||
backend.write_block_entry(BlockEntry {
|
||||
block_hash,
|
||||
block_number,
|
||||
parent_hash,
|
||||
children: Vec::new(),
|
||||
viability: ViabilityCriteria {
|
||||
earliest_unviable_ancestor: inherited_viability,
|
||||
explicitly_reverted: false,
|
||||
approval: Approval::Unapproved,
|
||||
},
|
||||
weight,
|
||||
});
|
||||
|
||||
// 2. Update leaves if inherited viability is fine.
|
||||
if inherited_viability.is_none() {
|
||||
@@ -370,38 +357,34 @@ fn apply_reversions(
|
||||
// Note: since revert numbers are in ascending order, the expensive propagation
|
||||
// of unviability is only heavy on the first log.
|
||||
for revert_number in reversions {
|
||||
let mut ancestor_entry = match load_ancestor(
|
||||
backend,
|
||||
block_hash,
|
||||
block_number,
|
||||
revert_number,
|
||||
)? {
|
||||
None => {
|
||||
tracing::warn!(
|
||||
target: LOG_TARGET,
|
||||
?block_hash,
|
||||
block_number,
|
||||
revert_target = revert_number,
|
||||
"The hammer has dropped. \
|
||||
let mut ancestor_entry =
|
||||
match load_ancestor(backend, block_hash, block_number, revert_number)? {
|
||||
None => {
|
||||
tracing::warn!(
|
||||
target: LOG_TARGET,
|
||||
?block_hash,
|
||||
block_number,
|
||||
revert_target = revert_number,
|
||||
"The hammer has dropped. \
|
||||
A block has indicated that its finalized ancestor be reverted. \
|
||||
Please inform an adult.",
|
||||
);
|
||||
);
|
||||
|
||||
continue
|
||||
}
|
||||
Some(ancestor_entry) => {
|
||||
tracing::info!(
|
||||
target: LOG_TARGET,
|
||||
?block_hash,
|
||||
block_number,
|
||||
revert_target = revert_number,
|
||||
revert_hash = ?ancestor_entry.block_hash,
|
||||
"A block has signaled that its ancestor be reverted due to a bad parachain block.",
|
||||
);
|
||||
continue
|
||||
},
|
||||
Some(ancestor_entry) => {
|
||||
tracing::info!(
|
||||
target: LOG_TARGET,
|
||||
?block_hash,
|
||||
block_number,
|
||||
revert_target = revert_number,
|
||||
revert_hash = ?ancestor_entry.block_hash,
|
||||
"A block has signaled that its ancestor be reverted due to a bad parachain block.",
|
||||
);
|
||||
|
||||
ancestor_entry
|
||||
}
|
||||
};
|
||||
ancestor_entry
|
||||
},
|
||||
};
|
||||
|
||||
ancestor_entry.viability.explicitly_reverted = true;
|
||||
propagate_viability_update(backend, ancestor_entry)?;
|
||||
@@ -431,8 +414,8 @@ pub(super) fn finalize_block<'a, B: Backend + 'a>(
|
||||
None => {
|
||||
// This implies that there are no unfinalized blocks and hence nothing
|
||||
// to update.
|
||||
return Ok(backend);
|
||||
}
|
||||
return Ok(backend)
|
||||
},
|
||||
Some(e) => e,
|
||||
};
|
||||
|
||||
@@ -474,9 +457,7 @@ pub(super) fn finalize_block<'a, B: Backend + 'a>(
|
||||
|
||||
// Add all children to the frontier.
|
||||
let next_height = dead_number + 1;
|
||||
frontier.extend(
|
||||
entry.into_iter().flat_map(|e| e.children).map(|h| (h, next_height))
|
||||
);
|
||||
frontier.extend(entry.into_iter().flat_map(|e| e.children).map(|h| (h, next_height)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,7 +514,6 @@ pub(super) fn approve_block(
|
||||
} else {
|
||||
backend.write_block_entry(entry);
|
||||
}
|
||||
|
||||
} else {
|
||||
tracing::debug!(
|
||||
target: LOG_TARGET,
|
||||
|
||||
Reference in New Issue
Block a user