mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-04 22:07:25 +00:00
transaction-pool: drop unpropagable txs if local node cant author blocks (#8048)
* transaction-pool: drop unpropagable txs if local node cant author blocks * fix test compilation * transaction-pool: remove unnecessary static bound on CanAuthor Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * rpc-api: add translation for PoolError::Unactionable * transaction-pool: add test for rejecting unactionable transactions * basic-authorship: fix doc test * transaction-pool: fix benchmark compilation * transaction-pool: rename CanAuthor to IsValidator * transaction-pool: nit in error message Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
@@ -36,7 +36,7 @@ use wasm_timer::Instant;
|
||||
use futures::channel::mpsc::Receiver;
|
||||
|
||||
use crate::validated_pool::ValidatedPool;
|
||||
pub use crate::validated_pool::ValidatedTransaction;
|
||||
pub use crate::validated_pool::{IsValidator, ValidatedTransaction};
|
||||
|
||||
/// Modification notification event stream type;
|
||||
pub type EventStream<H> = Receiver<H>;
|
||||
@@ -150,9 +150,9 @@ where
|
||||
|
||||
impl<B: ChainApi> Pool<B> {
|
||||
/// Create a new transaction pool.
|
||||
pub fn new(options: Options, api: Arc<B>) -> Self {
|
||||
pub fn new(options: Options, is_validator: IsValidator, api: Arc<B>) -> Self {
|
||||
Pool {
|
||||
validated_pool: Arc::new(ValidatedPool::new(options, api)),
|
||||
validated_pool: Arc::new(ValidatedPool::new(options, is_validator, api)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,43 +497,58 @@ mod tests {
|
||||
) -> Self::ValidationFuture {
|
||||
let hash = self.hash_and_length(&uxt).0;
|
||||
let block_number = self.block_id_to_number(at).unwrap().unwrap();
|
||||
let nonce = uxt.transfer().nonce;
|
||||
|
||||
// This is used to control the test flow.
|
||||
if nonce > 0 {
|
||||
let opt = self.delay.lock().take();
|
||||
if let Some(delay) = opt {
|
||||
if delay.recv().is_err() {
|
||||
println!("Error waiting for delay!");
|
||||
let res = match uxt {
|
||||
Extrinsic::Transfer { transfer, .. } => {
|
||||
let nonce = transfer.nonce;
|
||||
|
||||
// This is used to control the test flow.
|
||||
if nonce > 0 {
|
||||
let opt = self.delay.lock().take();
|
||||
if let Some(delay) = opt {
|
||||
if delay.recv().is_err() {
|
||||
println!("Error waiting for delay!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.invalidate.lock().contains(&hash) {
|
||||
return futures::future::ready(Ok(InvalidTransaction::Custom(0).into()));
|
||||
}
|
||||
if self.invalidate.lock().contains(&hash) {
|
||||
InvalidTransaction::Custom(0).into()
|
||||
} else if nonce < block_number {
|
||||
InvalidTransaction::Stale.into()
|
||||
} else {
|
||||
let mut transaction = ValidTransaction {
|
||||
priority: 4,
|
||||
requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] },
|
||||
provides: if nonce == INVALID_NONCE { vec![] } else { vec![vec![nonce as u8]] },
|
||||
longevity: 3,
|
||||
propagate: true,
|
||||
};
|
||||
|
||||
futures::future::ready(if nonce < block_number {
|
||||
Ok(InvalidTransaction::Stale.into())
|
||||
} else {
|
||||
let mut transaction = ValidTransaction {
|
||||
priority: 4,
|
||||
requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] },
|
||||
provides: if nonce == INVALID_NONCE { vec![] } else { vec![vec![nonce as u8]] },
|
||||
longevity: 3,
|
||||
propagate: true,
|
||||
};
|
||||
if self.clear_requirements.lock().contains(&hash) {
|
||||
transaction.requires.clear();
|
||||
}
|
||||
|
||||
if self.clear_requirements.lock().contains(&hash) {
|
||||
transaction.requires.clear();
|
||||
}
|
||||
if self.add_requirements.lock().contains(&hash) {
|
||||
transaction.requires.push(vec![128]);
|
||||
}
|
||||
|
||||
if self.add_requirements.lock().contains(&hash) {
|
||||
transaction.requires.push(vec![128]);
|
||||
}
|
||||
Ok(transaction)
|
||||
}
|
||||
},
|
||||
Extrinsic::IncludeData(_) => {
|
||||
Ok(ValidTransaction {
|
||||
priority: 9001,
|
||||
requires: vec![],
|
||||
provides: vec![vec![42]],
|
||||
longevity: 9001,
|
||||
propagate: false,
|
||||
})
|
||||
},
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
Ok(Ok(transaction))
|
||||
})
|
||||
futures::future::ready(Ok(res))
|
||||
}
|
||||
|
||||
/// Returns a block number given the block id.
|
||||
@@ -579,7 +594,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn pool() -> Pool<TestApi> {
|
||||
Pool::new(Default::default(), TestApi::default().into())
|
||||
Pool::new(Default::default(), true.into(), TestApi::default().into())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -620,6 +635,26 @@ mod tests {
|
||||
assert_matches!(res.unwrap_err(), error::Error::TemporarilyBanned);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_reject_unactionable_transactions() {
|
||||
// given
|
||||
let pool = Pool::new(
|
||||
Default::default(),
|
||||
// the node does not author blocks
|
||||
false.into(),
|
||||
TestApi::default().into(),
|
||||
);
|
||||
|
||||
// after validation `IncludeData` will be set to non-propagable
|
||||
let uxt = Extrinsic::IncludeData(vec![42]);
|
||||
|
||||
// when
|
||||
let res = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt));
|
||||
|
||||
// then
|
||||
assert_matches!(res.unwrap_err(), error::Error::Unactionable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_notify_about_pool_events() {
|
||||
let (stream, hash0, hash1) = {
|
||||
@@ -722,11 +757,14 @@ mod tests {
|
||||
count: 100,
|
||||
total_bytes: 200,
|
||||
};
|
||||
let pool = Pool::new(Options {
|
||||
|
||||
let options = Options {
|
||||
ready: limit.clone(),
|
||||
future: limit.clone(),
|
||||
..Default::default()
|
||||
}, TestApi::default().into());
|
||||
};
|
||||
|
||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
||||
|
||||
let hash1 = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
@@ -757,11 +795,14 @@ mod tests {
|
||||
count: 100,
|
||||
total_bytes: 10,
|
||||
};
|
||||
let pool = Pool::new(Options {
|
||||
|
||||
let options = Options {
|
||||
ready: limit.clone(),
|
||||
future: limit.clone(),
|
||||
..Default::default()
|
||||
}, TestApi::default().into());
|
||||
};
|
||||
|
||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
||||
|
||||
// when
|
||||
block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Transfer {
|
||||
@@ -939,11 +980,13 @@ mod tests {
|
||||
count: 1,
|
||||
total_bytes: 1000,
|
||||
};
|
||||
let pool = Pool::new(Options {
|
||||
let options = Options {
|
||||
ready: limit.clone(),
|
||||
future: limit.clone(),
|
||||
..Default::default()
|
||||
}, TestApi::default().into());
|
||||
};
|
||||
|
||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
||||
|
||||
let xt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
@@ -977,7 +1020,7 @@ mod tests {
|
||||
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
||||
let mut api = TestApi::default();
|
||||
api.delay = Arc::new(Mutex::new(rx.into()));
|
||||
let pool = Arc::new(Pool::new(Default::default(), api.into()));
|
||||
let pool = Arc::new(Pool::new(Default::default(), true.into(), api.into()));
|
||||
|
||||
// when
|
||||
let xt = uxt(Transfer {
|
||||
|
||||
Reference in New Issue
Block a user