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

Commit

Permalink
Merge remote-tracking branch 'origin/master' into v0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
gavofyork committed Dec 20, 2018
2 parents 9dfe006 + 873e8c7 commit 7fe2dd9
Show file tree
Hide file tree
Showing 31 changed files with 603 additions and 232 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Now with this new chainspec file, you can build a "raw" chain definition for you

[source, shell]
----
substrate build-spec --chain ~/chainspec.json --raw > ~/mychain.json
substrate --chain ~/chainspec.json build-spec --raw > ~/mychain.json
----

This can be fed into Substrate:
Expand Down
32 changes: 25 additions & 7 deletions core/network/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,11 @@ impl<B: BlockT> ChainSync<B> {
self.best_queued_hash = *hash;
}
// Update common blocks
for (_, peer) in self.peers.iter_mut() {
trace!(target: "sync", "Updating peer info ours={}, theirs={}", number, peer.best_number);
for (n, peer) in self.peers.iter_mut() {
if let PeerSyncState::AncestorSearch(_) = peer.state {
continue;
}
trace!(target: "sync", "Updating peer {} info, ours={}, common={}, their best={}", n, number, peer.common_number, peer.best_number);
if peer.best_number >= number {
peer.common_number = number;
peer.common_hash = *hash;
Expand All @@ -301,22 +304,34 @@ impl<B: BlockT> ChainSync<B> {

pub(crate) fn on_block_announce(&mut self, protocol: &mut Context<B>, who: NodeIndex, hash: B::Hash, header: &B::Header) {
let number = *header.number();
if number <= As::sa(0) {
trace!(target: "sync", "Ignored invalid block announcement from {}: {}", who, hash);
return;
}
let known_parent = self.is_known(protocol, &header.parent_hash());
let known = self.is_known(protocol, &hash);
if let Some(ref mut peer) = self.peers.get_mut(&who) {
if number > peer.best_number {
// update their best block
peer.best_number = number;
peer.best_hash = hash;
}
if number <= self.best_queued_number && number > peer.common_number {
if let PeerSyncState::AncestorSearch(_) = peer.state {
return;
}
if header.parent_hash() == &self.best_queued_hash || known_parent {
peer.common_number = number - As::sa(1);
} else if known {
peer.common_number = number
}
} else {
return;
}

if !self.is_known_or_already_downloading(protocol, &hash) {
if !(known || self.is_already_downloading(&hash)) {
let stale = number <= self.best_queued_number;
if stale {
if !self.is_known_or_already_downloading(protocol, header.parent_hash()) {
if !(known_parent || self.is_already_downloading(header.parent_hash())) {
trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", who, hash, header);
} else {
trace!(target: "sync", "Considering new stale block announced from {}: {} {:?}", who, hash, header);
Expand All @@ -331,9 +346,12 @@ impl<B: BlockT> ChainSync<B> {
}
}

fn is_known_or_already_downloading(&self, protocol: &mut Context<B>, hash: &B::Hash) -> bool {
fn is_already_downloading(&self, hash: &B::Hash) -> bool {
self.peers.iter().any(|(_, p)| p.state == PeerSyncState::DownloadingStale(*hash))
|| block_status(&*protocol.client(), &*self.import_queue, *hash).ok().map_or(false, |s| s != BlockStatus::Unknown)
}

fn is_known(&self, protocol: &mut Context<B>, hash: &B::Hash) -> bool {
block_status(&*protocol.client(), &*self.import_queue, *hash).ok().map_or(false, |s| s != BlockStatus::Unknown)
}

pub(crate) fn peer_disconnected(&mut self, protocol: &mut Context<B>, who: NodeIndex) {
Expand Down
3 changes: 3 additions & 0 deletions core/service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ substrate-executor = { path = "../../core/executor" }
substrate-transaction-pool = { path = "../../core/transaction-pool" }
substrate-rpc-servers = { path = "../../core/rpc-servers" }
substrate-telemetry = { path = "../../core/telemetry" }

[dev-dependencies]
substrate-test-client = { path = "../test-client" }
122 changes: 96 additions & 26 deletions core/service/src/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,51 @@ pub trait MaintainTransactionPool<C: Components> {
) -> error::Result<()>;
}

fn on_block_imported<Api, Backend, Block, Executor, PoolApi>(
id: &BlockId<Block>,
client: &Client<Backend, Executor, Block, Api>,
transaction_pool: &TransactionPool<PoolApi>,
) -> error::Result<()> where
Api: TaggedTransactionQueue<Block>,
Block: BlockT<Hash = <Blake2Hasher as ::primitives::Hasher>::Out>,
Backend: client::backend::Backend<Block, Blake2Hasher>,
Client<Backend, Executor, Block, Api>: ProvideRuntimeApi<Api = Api>,
Executor: client::CallExecutor<Block, Blake2Hasher>,
PoolApi: txpool::ChainApi<Hash = Block::Hash, Block = Block>,
{
use runtime_primitives::transaction_validity::TransactionValidity;

// Avoid calling into runtime if there is nothing to prune from the pool anyway.
if transaction_pool.status().is_empty() {
return Ok(())
}

let block = client.block(id)?;
let tags = match block {
None => return Ok(()),
Some(block) => {
let parent_id = BlockId::hash(*block.block.header().parent_hash());
let mut tags = vec![];
for tx in block.block.extrinsics() {
let tx = client.runtime_api().validate_transaction(&parent_id, &tx)?;
match tx {
TransactionValidity::Valid { mut provides, .. } => {
tags.append(&mut provides);
},
// silently ignore invalid extrinsics,
// cause they might just be inherent
_ => {}
}

}
tags
}
};

transaction_pool.prune_tags(id, tags).map_err(|e| format!("{:?}", e))?;
Ok(())
}

impl<C: Components> MaintainTransactionPool<Self> for C where
ComponentClient<C>: ProvideRuntimeApi<Api = C::RuntimeApi>,
C::RuntimeApi: TaggedTransactionQueue<ComponentBlock<C>>,
Expand All @@ -194,35 +239,10 @@ impl<C: Components> MaintainTransactionPool<Self> for C where
client: &ComponentClient<C>,
transaction_pool: &TransactionPool<C::TransactionPoolApi>,
) -> error::Result<()> {
use runtime_primitives::transaction_validity::TransactionValidity;

let block = client.block(id)?;
let tags = match block {
None => return Ok(()),
Some(block) => {
let mut tags = vec![];
for tx in block.block.extrinsics() {
let tx = client.runtime_api().validate_transaction(id, &tx)?;
match tx {
TransactionValidity::Valid { mut provides, .. } => {
tags.append(&mut provides);
},
// silently ignore invalid extrinsics,
// cause they might just be inherent
_ => {}
}

}
tags
}
};

transaction_pool.prune_tags(id, tags).map_err(|e| format!("{:?}", e))?;
Ok(())
on_block_imported(id, client, transaction_pool)
}
}


/// The super trait that combines all required traits a `Service` needs to implement.
pub trait ServiceTrait<C: Components>:
Deref<Target = Service<C>>
Expand Down Expand Up @@ -516,3 +536,53 @@ impl<Factory: ServiceFactory> Components for LightComponents<Factory> {
Factory::build_light_import_queue(config, client)
}
}

#[cfg(test)]
mod tests {
use super::*;
use codec::Encode;
use consensus_common::BlockOrigin;
use substrate_test_client::{
self,
TestClient,
keyring::Keyring,
runtime::{Extrinsic, Transfer},
};

#[test]
fn should_remove_transactions_from_the_pool() {
let client = Arc::new(substrate_test_client::new());
let pool = TransactionPool::new(Default::default(), ::transaction_pool::ChainApi::new(client.clone()));
let transaction = {
let transfer = Transfer {
amount: 5,
nonce: 0,
from: Keyring::Alice.to_raw_public().into(),
to: Default::default(),
};
let signature = Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&transfer.encode()).into();
Extrinsic { transfer, signature }
};
// store the transaction in the pool
pool.submit_one(&BlockId::hash(client.best_block_header().unwrap().hash()), transaction.clone()).unwrap();

// import the block
let mut builder = client.new_block().unwrap();
builder.push(transaction.clone()).unwrap();
let block = builder.bake().unwrap();
let id = BlockId::hash(block.header().hash());
client.import(BlockOrigin::Own, block).unwrap();

// fire notification - this should clean up the queue
assert_eq!(pool.status().ready, 1);
on_block_imported(
&id,
&client,
&pool,
).unwrap();

// then
assert_eq!(pool.status().ready, 0);
assert_eq!(pool.status().future, 0);
}
}
3 changes: 3 additions & 0 deletions core/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ extern crate log;
#[macro_use]
extern crate serde_derive;

#[cfg(test)]
extern crate substrate_test_client;

mod components;
mod error;
mod chain_spec;
Expand Down
4 changes: 2 additions & 2 deletions core/test-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ serde_derive = { version = "1.0", optional = true }
parity-codec = { version = "2.1", default-features = false }
parity-codec-derive = { version = "2.1", default-features = false }
substrate-keyring = { path = "../keyring", optional = true }
substrate-client = { path = "../client", optional = true }
substrate-client = { path = "../client", default-features = false }
substrate-primitives = { path = "../primitives", default-features = false }
substrate-consensus-aura-primitives = { path = "../consensus/aura/primitives", default-features = false }
sr-std = { path = "../sr-std", default-features = false }
Expand All @@ -27,7 +27,7 @@ std = [
"hex-literal",
"serde",
"serde_derive",
"substrate-client",
"substrate-client/std",
"substrate-keyring",
"parity-codec/std",
"sr-std/std",
Expand Down
17 changes: 17 additions & 0 deletions core/test-runtime/wasm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 7fe2dd9

Please sign in to comment.