Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit bbd15c4

Browse files
tomusdrwgavofyork
authored andcommitted
Handle AccountIndices in transaction pool (#225)
* Merge remote-tracking branch 'origin/master' into gav-xts-dont-panic * Update wasm. * consensus, session and staking all panic-safe. * Democracy doesn't panic in apply. * Fix tests. * Extra helper macro, council depanicked. * Fix one test. * Fix up all council tests. No panics! * Council voting depanicked. * Dispatch returns result. * session & staking tests updated * Fix democracy tests. * Fix council tests. * Fix up polkadot parachains in runtime * Fix borked merge * More Slicable support Support general `Option` and array types. * Basic storage types. * Existential deposit for contract creation * Basic implemnetation along with removals * Fix tests. * externalities builder fix. * Tests. * Fix up the runtime. * Fix tests. * Add generic `Address` type. * Initial function integration of Address into Extrinsic. * Fix build * All tests compile. * Fix (some) tests. * Fix signing. * Push error. * transfer can accept Address * Make Address generic over AccountIndex * Fix test * Make Council use Address for dispatch. * Fix build * Bend over backwards to support braindead derive. * Repot some files. * Fix tests. * Fix grumbles * Remove Default bound * Fix build for new nightly. * Make `apply_extrinsic` never panic, return useful Result. * More merge hell * Doesn't build, but might do soon * Serde woes * get substrate-runtime-staking compiling * Polkadot builds again! * Fix all build. * Fix tests & binaries. * Reserve some extra initial byte values of address for future format changes * Make semantic of `ReservedBalance` clear. * Fix panic handler. * Integrate other balance transformations into the new model Fix up staking tests. * Fix runtime tests. * Fix panic build. * Tests for demonstrating interaction between balance types. * Repot some runtime code * Fix checkedblock in non-std builds * Get rid of `DoLookup` phantom. * Attempt to make transaction_pool work with lookups. * Remove vscode settings * New attempt at making transaction pool work. * It builds again! * --all builds * Fix tests. * New build. * Test account nonce reset. * polkadot transaction pool tests/framework. * Address grumbles. * Pool support non-verified transactions. * Revert bad `map_or` * Rebuild binaries, workaround. * Avoid casting to usize early. * Make verification use provided block_id. * Fix tests. * Alter tests to use retry. * Fix tests & add call to re-verify. * Semi-refactor. * Integrate new queue with the rest of the code. * Fix tests. * Add reverify_transaction method. * Use result.
1 parent bb8ef97 commit bbd15c4

File tree

20 files changed

+508
-359
lines changed

20 files changed

+508
-359
lines changed

demo/cli/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ pub mod error;
5050
use std::sync::Arc;
5151
use demo_primitives::Hash;
5252
use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
53-
SessionConfig, StakingConfig, BuildStorage};
54-
use demo_runtime::{Block, UncheckedExtrinsic};
53+
SessionConfig, StakingConfig};
54+
use demo_runtime::{Block, BlockId, UncheckedExtrinsic, BuildStorage};
5555
use futures::{Future, Sink, Stream};
5656

5757
struct DummyPool;
58-
impl extrinsic_pool::api::ExtrinsicPool<UncheckedExtrinsic, Hash> for DummyPool {
58+
impl extrinsic_pool::api::ExtrinsicPool<UncheckedExtrinsic, BlockId, Hash> for DummyPool {
5959
type Error = extrinsic_pool::txpool::Error;
6060

61-
fn submit(&self, _: Vec<UncheckedExtrinsic>)
61+
fn submit(&self, _block: BlockId, _: Vec<UncheckedExtrinsic>)
6262
-> Result<Vec<Hash>, Self::Error>
6363
{
6464
Err("unimplemented".into())
@@ -155,7 +155,8 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
155155
let _rpc_servers = {
156156
let handler = || {
157157
let chain = rpc::apis::chain::Chain::new(client.clone(), core.remote());
158-
rpc::rpc_handler::<Block, _, _, _, _>(client.clone(), chain, Arc::new(DummyPool), DummySystem)
158+
let author = rpc::apis::author::Author::new(client.clone(), Arc::new(DummyPool));
159+
rpc::rpc_handler::<Block, _, _, _, _>(client.clone(), chain, author, DummySystem)
159160
};
160161
let http_address = "127.0.0.1:9933".parse().unwrap();
161162
let ws_address = "127.0.0.1:9944".parse().unwrap();

demo/runtime/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ pub type Address = staking::Address<Concrete>;
162162
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
163163
/// Block type as expected by this runtime.
164164
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
165+
/// BlockId type as expected by this runtime.
166+
pub type BlockId = generic::BlockId<Block>;
165167
/// Unchecked extrinsic type as expected by this runtime.
166168
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Index, Call, Signature>;
167169
/// Extrinsic type as expected by this runtime. This is not the type that is signed.

polkadot/cli/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ parking_lot = "0.4"
2727
serde_json = "1.0"
2828
serde = "1.0"
2929
substrate-client = { path = "../../substrate/client" }
30-
substrate-state-machine = { path = "../../substrate/state-machine" }
31-
substrate-rpc = { path = "../../substrate/rpc" }
32-
substrate-rpc-servers = { path = "../../substrate/rpc-servers" }
3330
substrate-network = { path = "../../substrate/network" }
3431
substrate-primitives = { path = "../../substrate/primitives" }
32+
substrate-rpc = { path = "../../substrate/rpc" }
33+
substrate-rpc-servers = { path = "../../substrate/rpc-servers" }
3534
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives" }
35+
substrate-state-machine = { path = "../../substrate/state-machine" }
3636
substrate-telemetry = { path = "../../substrate/telemetry" }
3737
polkadot-primitives = { path = "../primitives" }
3838
polkadot-runtime = { path = "../runtime" }

polkadot/cli/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ extern crate parking_lot;
3434
extern crate serde;
3535
extern crate serde_json;
3636

37-
extern crate substrate_primitives;
38-
extern crate substrate_state_machine as state_machine;
3937
extern crate substrate_client as client;
4038
extern crate substrate_network as network;
39+
extern crate substrate_primitives;
4140
extern crate substrate_rpc;
4241
extern crate substrate_rpc_servers as rpc;
4342
extern crate substrate_runtime_primitives as runtime_primitives;
43+
extern crate substrate_state_machine as state_machine;
4444
extern crate polkadot_primitives;
4545
extern crate polkadot_runtime;
4646
extern crate polkadot_service as service;
@@ -192,12 +192,12 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
192192

193193
let (mut genesis_storage, boot_nodes) = PresetConfig::from_spec(chain_spec)
194194
.map(PresetConfig::deconstruct)
195-
.unwrap_or_else(|f| (Box::new(move ||
195+
.unwrap_or_else(|f| (Box::new(move ||
196196
read_storage_json(&f)
197197
.map(|s| { info!("{} storage items read from {}", s.len(), f); s })
198198
.unwrap_or_else(|| panic!("Bad genesis state file: {}", f))
199199
), vec![]));
200-
200+
201201
if matches.is_present("build-genesis") {
202202
info!("Building genesis");
203203
for (i, (k, v)) in genesis_storage().iter().enumerate() {
@@ -285,10 +285,11 @@ fn run_until_exit<C>(mut core: reactor::Core, service: service::Service<C>, matc
285285

286286
let handler = || {
287287
let chain = rpc::apis::chain::Chain::new(service.client(), core.remote());
288+
let author = rpc::apis::author::Author::new(service.client(), service.transaction_pool());
288289
rpc::rpc_handler::<Block, _, _, _, _>(
289290
service.client(),
290291
chain,
291-
service.transaction_pool(),
292+
author,
292293
sys_conf.clone(),
293294
)
294295
};

polkadot/consensus/src/lib.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ use polkadot_primitives::{Hash, Block, BlockId, BlockNumber, Header, Timestamp};
7474
use polkadot_primitives::parachain::{Id as ParaId, Chain, DutyRoster, BlockData, Extrinsic as ParachainExtrinsic, CandidateReceipt};
7575
use polkadot_runtime::BareExtrinsic;
7676
use primitives::AuthorityId;
77-
use transaction_pool::{Ready, TransactionPool};
77+
use transaction_pool::{TransactionPool};
7878
use tokio_core::reactor::{Handle, Timeout, Interval};
7979

8080
use futures::prelude::*;
@@ -226,7 +226,7 @@ pub struct ProposerFactory<C, N, P> {
226226
/// The client instance.
227227
pub client: Arc<C>,
228228
/// The transaction pool.
229-
pub transaction_pool: Arc<TransactionPool>,
229+
pub transaction_pool: Arc<TransactionPool<C>>,
230230
/// The backing network handle.
231231
pub network: N,
232232
/// Parachain collators.
@@ -239,7 +239,8 @@ pub struct ProposerFactory<C, N, P> {
239239

240240
impl<C, N, P> bft::ProposerFactory<Block> for ProposerFactory<C, N, P>
241241
where
242-
C: PolkadotApi,
242+
C: PolkadotApi + Send + Sync,
243+
C::CheckedBlockId: Sync,
243244
N: Network,
244245
P: Collators,
245246
{
@@ -319,12 +320,13 @@ pub struct Proposer<C: PolkadotApi, R, P> {
319320
random_seed: Hash,
320321
router: R,
321322
table: Arc<SharedTable>,
322-
transaction_pool: Arc<TransactionPool>,
323+
transaction_pool: Arc<TransactionPool<C>>,
323324
}
324325

325326
impl<C, R, P> bft::Proposer<Block> for Proposer<C, R, P>
326327
where
327-
C: PolkadotApi,
328+
C: PolkadotApi + Send + Sync,
329+
C::CheckedBlockId: Sync,
328330
R: TableRouter,
329331
P: Collators,
330332
{
@@ -501,16 +503,19 @@ impl<C, R, P> bft::Proposer<Block> for Proposer<C, R, P>
501503

502504
let local_id = self.local_key.public().0.into();
503505
let mut next_index = {
504-
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client);
505-
let cur_index = self.transaction_pool.cull_and_get_pending(readiness_evaluator, |pending| pending
506+
let cur_index = self.transaction_pool.cull_and_get_pending(BlockId::hash(self.parent_hash), |pending| pending
506507
.filter(|tx| tx.sender().map(|s| s == local_id).unwrap_or(false))
507508
.last()
508509
.map(|tx| Ok(tx.index()))
509510
.unwrap_or_else(|| self.client.index(&self.parent_id, local_id))
510511
);
511512

512513
match cur_index {
513-
Ok(cur_index) => cur_index + 1,
514+
Ok(Ok(cur_index)) => cur_index + 1,
515+
Ok(Err(e)) => {
516+
warn!(target: "consensus", "Error computing next transaction index: {}", e);
517+
return;
518+
}
514519
Err(e) => {
515520
warn!(target: "consensus", "Error computing next transaction index: {}", e);
516521
return;
@@ -549,7 +554,7 @@ impl<C, R, P> bft::Proposer<Block> for Proposer<C, R, P>
549554
};
550555
let uxt = UncheckedExtrinsic::new(extrinsic, signature);
551556

552-
self.transaction_pool.import_unchecked_extrinsic(uxt)
557+
self.transaction_pool.import_unchecked_extrinsic(BlockId::hash(self.parent_hash), uxt)
553558
.expect("locally signed extrinsic is valid; qed");
554559
}
555560
}
@@ -618,7 +623,7 @@ pub struct CreateProposal<C: PolkadotApi, R, P: Collators> {
618623
parent_number: BlockNumber,
619624
parent_id: C::CheckedBlockId,
620625
client: Arc<C>,
621-
transaction_pool: Arc<TransactionPool>,
626+
transaction_pool: Arc<TransactionPool<C>>,
622627
collation: CollationFetch<P, C>,
623628
router: R,
624629
table: Arc<SharedTable>,
@@ -640,9 +645,8 @@ impl<C, R, P> CreateProposal<C, R, P>
640645
let mut block_builder = self.client.build_block(&self.parent_id, timestamp, candidates)?;
641646

642647
{
643-
let readiness_evaluator = Ready::create(self.parent_id.clone(), &*self.client);
644648
let mut unqueue_invalid = Vec::new();
645-
self.transaction_pool.cull_and_get_pending(readiness_evaluator, |pending_iterator| {
649+
let result = self.transaction_pool.cull_and_get_pending(BlockId::hash(self.parent_hash), |pending_iterator| {
646650
let mut pending_size = 0;
647651
for pending in pending_iterator {
648652
// skip and cull transactions which are too large.
@@ -664,6 +668,9 @@ impl<C, R, P> CreateProposal<C, R, P>
664668
}
665669
}
666670
});
671+
if let Err(e) = result {
672+
warn!("Unable to get the pending set: {:?}", e);
673+
}
667674

668675
self.transaction_pool.remove(&unqueue_invalid, false);
669676
}

polkadot/consensus/src/service.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,13 +235,14 @@ impl Service {
235235
client: Arc<C>,
236236
api: Arc<A>,
237237
network: Arc<net::ConsensusService<Block>>,
238-
transaction_pool: Arc<TransactionPool>,
238+
transaction_pool: Arc<TransactionPool<A>>,
239239
parachain_empty_duration: Duration,
240240
key: ed25519::Pair,
241241
) -> Service
242242
where
243243
A: LocalPolkadotApi + Send + Sync + 'static,
244244
C: BlockchainEvents<Block> + ChainHead<Block> + bft::BlockImport<Block> + bft::Authorities<Block> + Send + Sync + 'static,
245+
A::CheckedBlockId: Sync,
245246
{
246247
let (signal, exit) = ::exit_future::signal();
247248
let thread = thread::spawn(move || {

polkadot/service/src/components.rs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ pub trait Components {
5555
fn build_api(&self, client: Arc<Client<Self::Backend, Self::Executor, Block>>) -> Arc<Self::Api>;
5656

5757
/// Create network transaction pool adapter.
58-
fn build_network_tx_pool(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, api: Arc<Self::Api>, tx_pool: Arc<TransactionPool>)
58+
fn build_network_tx_pool(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, tx_pool: Arc<TransactionPool<Self::Api>>)
5959
-> Arc<network::TransactionPool<Block>>;
6060

6161
/// Create consensus service.
62-
fn build_consensus(&self, client: Arc<Client<Self::Backend, Self::Executor, Block>>, network: Arc<network::Service<Block>>, tx_pool: Arc<TransactionPool>, keystore: &Keystore)
62+
fn build_consensus(&self, client: Arc<Client<Self::Backend, Self::Executor, Block>>, network: Arc<network::Service<Block>>, tx_pool: Arc<TransactionPool<Self::Api>>, keystore: &Keystore)
6363
-> Result<Option<consensus::Service>, error::Error>;
6464
}
6565

@@ -83,17 +83,16 @@ impl Components for FullComponents {
8383
client
8484
}
8585

86-
fn build_network_tx_pool(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, api: Arc<Self::Api>, pool: Arc<TransactionPool>)
86+
fn build_network_tx_pool(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, pool: Arc<TransactionPool<Self::Api>>)
8787
-> Arc<network::TransactionPool<Block>> {
8888
Arc::new(TransactionPoolAdapter {
8989
imports_external_transactions: true,
9090
pool,
9191
client,
92-
api,
9392
})
9493
}
9594

96-
fn build_consensus(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, network: Arc<network::Service<Block>>, tx_pool: Arc<TransactionPool>, keystore: &Keystore)
95+
fn build_consensus(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, network: Arc<network::Service<Block>>, tx_pool: Arc<TransactionPool<Self::Api>>, keystore: &Keystore)
9796
-> Result<Option<consensus::Service>, error::Error> {
9897
if !self.is_validator {
9998
return Ok(None);
@@ -134,17 +133,16 @@ impl Components for LightComponents {
134133
Arc::new(polkadot_api::light::RemotePolkadotApiWrapper(client.clone()))
135134
}
136135

137-
fn build_network_tx_pool(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, api: Arc<Self::Api>, pool: Arc<TransactionPool>)
136+
fn build_network_tx_pool(&self, client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, pool: Arc<TransactionPool<Self::Api>>)
138137
-> Arc<network::TransactionPool<Block>> {
139138
Arc::new(TransactionPoolAdapter {
140139
imports_external_transactions: false,
141140
pool,
142141
client,
143-
api,
144142
})
145143
}
146144

147-
fn build_consensus(&self, _client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, _network: Arc<network::Service<Block>>, _tx_pool: Arc<TransactionPool>, _keystore: &Keystore)
145+
fn build_consensus(&self, _client: Arc<client::Client<Self::Backend, Self::Executor, Block>>, _network: Arc<network::Service<Block>>, _tx_pool: Arc<TransactionPool<Self::Api>>, _keystore: &Keystore)
148146
-> Result<Option<consensus::Service>, error::Error> {
149147
Ok(None)
150148
}
@@ -153,9 +151,25 @@ impl Components for LightComponents {
153151
/// Transaction pool adapter.
154152
pub struct TransactionPoolAdapter<B, E, A> where A: Send + Sync, E: Send + Sync {
155153
imports_external_transactions: bool,
156-
pool: Arc<TransactionPool>,
154+
pool: Arc<TransactionPool<A>>,
157155
client: Arc<Client<B, E, Block>>,
158-
api: Arc<A>,
156+
}
157+
158+
impl<B, E, A> TransactionPoolAdapter<B, E, A>
159+
where
160+
A: Send + Sync,
161+
B: client::backend::Backend<Block> + Send + Sync,
162+
E: client::CallExecutor<Block> + Send + Sync,
163+
client::error::Error: From<<<B as client::backend::Backend<Block>>::State as state_machine::backend::Backend>::Error>,
164+
{
165+
fn best_block_id(&self) -> Option<BlockId> {
166+
self.client.info()
167+
.map(|info| BlockId::hash(info.chain.best_hash))
168+
.map_err(|e| {
169+
debug!("Error getting best block: {:?}", e);
170+
})
171+
.ok()
172+
}
159173
}
160174

161175
impl<B, E, A> network::TransactionPool<Block> for TransactionPoolAdapter<B, E, A>
@@ -166,28 +180,20 @@ impl<B, E, A> network::TransactionPool<Block> for TransactionPoolAdapter<B, E, A
166180
A: polkadot_api::PolkadotApi + Send + Sync,
167181
{
168182
fn transactions(&self) -> Vec<(Hash, Vec<u8>)> {
169-
let best_block = match self.client.info() {
170-
Ok(info) => info.chain.best_hash,
171-
Err(e) => {
172-
debug!("Error getting best block: {:?}", e);
173-
return Vec::new();
174-
}
175-
};
176-
177-
let id = match self.api.check_id(BlockId::hash(best_block)) {
178-
Ok(id) => id,
179-
Err(_) => return Vec::new(),
183+
let best_block_id = match self.best_block_id() {
184+
Some(id) => id,
185+
None => return vec![],
180186
};
181-
182-
let ready = transaction_pool::Ready::create(id, &*self.api);
183-
184-
self.pool.cull_and_get_pending(ready, |pending| pending
187+
self.pool.cull_and_get_pending(best_block_id, |pending| pending
185188
.map(|t| {
186189
let hash = t.hash().clone();
187190
(hash, t.primitive_extrinsic())
188191
})
189192
.collect()
190-
)
193+
).unwrap_or_else(|e| {
194+
warn!("Error retrieving pending set: {}", e);
195+
vec![]
196+
})
191197
}
192198

193199
fn import(&self, transaction: &Vec<u8>) -> Option<Hash> {
@@ -197,7 +203,8 @@ impl<B, E, A> network::TransactionPool<Block> for TransactionPoolAdapter<B, E, A
197203

198204
let encoded = transaction.encode();
199205
if let Some(uxt) = codec::Slicable::decode(&mut &encoded[..]) {
200-
match self.pool.import_unchecked_extrinsic(uxt) {
206+
let best_block_id = self.best_block_id()?;
207+
match self.pool.import_unchecked_extrinsic(best_block_id, uxt) {
201208
Ok(xt) => Some(*xt.hash()),
202209
Err(e) => match *e.kind() {
203210
transaction_pool::ErrorKind::AlreadyImported(hash) => Some(hash[..].into()),

0 commit comments

Comments
 (0)