Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
+21 -24
View File
@@ -15,23 +15,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use futures::{
channel::{mpsc, oneshot},
compat::*,
future::{ok, ready, select},
prelude::*,
};
use futures01::sync::mpsc as mpsc01;
use libp2p_wasm_ext::{ffi, ExtTransport};
use log::{debug, info};
use sc_chain_spec::Extension;
use sc_network::config::TransportConfig;
use sc_service::{
RpcSession, Role, Configuration, TaskManager, RpcHandlers,
config::{DatabaseConfig, KeystoreConfig, NetworkConfiguration},
GenericChainSpec, RuntimeGenesis,
KeepBlocks, TransactionStorageMode,
Configuration, GenericChainSpec, KeepBlocks, Role, RpcHandlers, RpcSession, RuntimeGenesis,
TaskManager, TransactionStorageMode,
};
use sc_tracing::logging::LoggerBuilder;
use wasm_bindgen::prelude::*;
use futures::{
prelude::*, channel::{oneshot, mpsc}, compat::*, future::{ready, ok, select}
};
use std::pin::Pin;
use sc_chain_spec::Extension;
use libp2p_wasm_ext::{ExtTransport, ffi};
use wasm_bindgen::prelude::*;
pub use console_error_panic_hook::set_once as set_console_error_panic_hook;
@@ -73,7 +75,8 @@ where
task_executor: (|fut, _| {
wasm_bindgen_futures::spawn_local(fut);
async {}
}).into(),
})
.into(),
telemetry_external_transport: Some(transport),
role: Role::Light,
database: {
@@ -114,9 +117,7 @@ where
max_runtime_instances: 8,
announce_block: true,
base_path: None,
informant_output_format: sc_informant::OutputFormat {
enable_color: false,
},
informant_output_format: sc_informant::OutputFormat { enable_color: false },
disable_log_reloading: false,
};
@@ -153,12 +154,11 @@ pub fn start_client(mut task_manager: TaskManager, rpc_handlers: RpcHandlers) ->
Box::pin(async move {
let _ = task_manager.future().await;
}),
).map(drop)
)
.map(drop),
);
Client {
rpc_send_tx,
}
Client { rpc_send_tx }
}
#[wasm_bindgen]
@@ -175,12 +175,8 @@ impl Client {
});
wasm_bindgen_futures::future_to_promise(async {
match rx.await {
Ok(fut) => {
fut.await
.map(|s| JsValue::from_str(&s))
.ok_or_else(|| JsValue::NULL)
},
Err(_) => Err(JsValue::NULL)
Ok(fut) => fut.await.map(|s| JsValue::from_str(&s)).ok_or_else(|| JsValue::NULL),
Err(_) => Err(JsValue::NULL),
}
})
}
@@ -203,7 +199,8 @@ impl Client {
});
wasm_bindgen_futures::spawn_local(async move {
let _ = rx.compat()
let _ = rx
.compat()
.try_for_each(|s| {
let _ = callback.call1(&callback, &JsValue::from_str(&s));
ok(())
@@ -33,16 +33,16 @@ pub fn rerun_if_git_head_changed() {
Err(err) => {
eprintln!("cargo:warning=Unable to read the Git repository: {}", err);
return;
}
Ok(None) => {}
return
},
Ok(None) => {},
Ok(Some(paths)) => {
for p in paths {
println!("cargo:rerun-if-changed={}", p.display());
}
return;
}
return
},
}
manifest_dir.pop();
@@ -17,8 +17,8 @@
//! Crate with utility functions for `build.rs` scripts.
mod version;
mod git;
mod version;
pub use git::*;
pub use version::*;
@@ -20,15 +20,13 @@ use std::{borrow::Cow, process::Command};
/// Generate the `cargo:` key output
pub fn generate_cargo_keys() {
let output = Command::new("git")
.args(&["rev-parse", "--short", "HEAD"])
.output();
let output = Command::new("git").args(&["rev-parse", "--short", "HEAD"]).output();
let commit = match output {
Ok(o) if o.status.success() => {
let sha = String::from_utf8_lossy(&o.stdout).trim().to_owned();
Cow::from(sha)
}
},
Ok(o) => {
println!("cargo:warning=Git command failed with status: {}", o.status);
Cow::from("unknown")
+158 -284
View File
@@ -20,9 +20,8 @@
#![warn(missing_docs)]
use std::cmp::Reverse;
use std::fmt;
use codec::{Decode, Encode};
use std::{cmp::Reverse, fmt};
/// Error occurred when iterating with the tree.
#[derive(Clone, Debug, PartialEq)]
@@ -83,7 +82,8 @@ pub struct ForkTree<H, N, V> {
best_finalized_number: Option<N>,
}
impl<H, N, V> ForkTree<H, N, V> where
impl<H, N, V> ForkTree<H, N, V>
where
H: PartialEq + Clone,
N: Ord + Clone,
V: Clone,
@@ -102,17 +102,14 @@ impl<H, N, V> ForkTree<H, N, V> where
number: &N,
is_descendent_of: &F,
predicate: &P,
) -> Result<impl Iterator<Item=(H, N, V)>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
) -> Result<impl Iterator<Item = (H, N, V)>, Error<E>>
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
{
let new_root_index = self.find_node_index_where(
hash,
number,
is_descendent_of,
predicate,
)?;
let new_root_index =
self.find_node_index_where(hash, number, is_descendent_of, predicate)?;
let removed = if let Some(mut root_index) = new_root_index {
let mut old_roots = std::mem::take(&mut self.roots);
@@ -130,9 +127,10 @@ impl<H, N, V> ForkTree<H, N, V> where
}
}
let mut root = root
.expect("find_node_index_where will return array with at least one index; \
this results in at least one item in removed; qed");
let mut root = root.expect(
"find_node_index_where will return array with at least one index; \
this results in at least one item in removed; qed",
);
let mut removed = old_roots;
@@ -144,7 +142,7 @@ impl<H, N, V> ForkTree<H, N, V> where
for child in root_children {
if is_first &&
(child.number == *number && child.hash == *hash ||
child.number < *number && is_descendent_of(&child.hash, hash)?)
child.number < *number && is_descendent_of(&child.hash, hash)?)
{
root.children.push(child);
// assuming that the tree is well formed only one child should pass this requirement
@@ -168,16 +166,14 @@ impl<H, N, V> ForkTree<H, N, V> where
}
}
impl<H, N, V> ForkTree<H, N, V> where
impl<H, N, V> ForkTree<H, N, V>
where
H: PartialEq,
N: Ord,
{
/// Create a new empty tree.
pub fn new() -> ForkTree<H, N, V> {
ForkTree {
roots: Vec::new(),
best_finalized_number: None,
}
ForkTree { roots: Vec::new(), best_finalized_number: None }
}
/// Rebalance the tree, i.e. sort child nodes by max branch depth
@@ -209,18 +205,19 @@ impl<H, N, V> ForkTree<H, N, V> where
mut data: V,
is_descendent_of: &F,
) -> Result<bool, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
{
if let Some(ref best_finalized_number) = self.best_finalized_number {
if number <= *best_finalized_number {
return Err(Error::Revert);
return Err(Error::Revert)
}
}
for root in self.roots.iter_mut() {
if root.hash == hash {
return Err(Error::Duplicate);
return Err(Error::Duplicate)
}
match root.import(hash, number, data, is_descendent_of)? {
@@ -231,17 +228,12 @@ impl<H, N, V> ForkTree<H, N, V> where
},
None => {
self.rebalance();
return Ok(false);
return Ok(false)
},
}
}
self.roots.push(Node {
data,
hash: hash,
number: number,
children: Vec::new(),
});
self.roots.push(Node { data, hash, number, children: Vec::new() });
self.rebalance();
@@ -249,18 +241,18 @@ impl<H, N, V> ForkTree<H, N, V> where
}
/// Iterates over the existing roots in the tree.
pub fn roots(&self) -> impl Iterator<Item=(&H, &N, &V)> {
pub fn roots(&self) -> impl Iterator<Item = (&H, &N, &V)> {
self.roots.iter().map(|node| (&node.hash, &node.number, &node.data))
}
fn node_iter(&self) -> impl Iterator<Item=&Node<H, N, V>> {
fn node_iter(&self) -> impl Iterator<Item = &Node<H, N, V>> {
// we need to reverse the order of roots to maintain the expected
// ordering since the iterator uses a stack to track state.
ForkTreeIterator { stack: self.roots.iter().rev().collect() }
}
/// Iterates the nodes in the tree in pre-order.
pub fn iter(&self) -> impl Iterator<Item=(&H, &N, &V)> {
pub fn iter(&self) -> impl Iterator<Item = (&H, &N, &V)> {
self.node_iter().map(|node| (&node.hash, &node.number, &node.data))
}
@@ -274,7 +266,8 @@ impl<H, N, V> ForkTree<H, N, V> where
number: &N,
is_descendent_of: &F,
predicate: &P,
) -> Result<Option<&Node<H, N, V>>, Error<E>> where
) -> Result<Option<&Node<H, N, V>>, Error<E>>
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
@@ -285,7 +278,7 @@ impl<H, N, V> ForkTree<H, N, V> where
// found the node, early exit
if let FindOutcome::Found(node) = node {
return Ok(Some(node));
return Ok(Some(node))
}
}
@@ -293,23 +286,13 @@ impl<H, N, V> ForkTree<H, N, V> where
}
/// Map fork tree into values of new types.
pub fn map<VT, F>(
self,
f: &mut F,
) -> ForkTree<H, N, VT> where
pub fn map<VT, F>(self, f: &mut F) -> ForkTree<H, N, VT>
where
F: FnMut(&H, &N, V) -> VT,
{
let roots = self.roots
.into_iter()
.map(|root| {
root.map(f)
})
.collect();
let roots = self.roots.into_iter().map(|root| root.map(f)).collect();
ForkTree {
roots,
best_finalized_number: self.best_finalized_number,
}
ForkTree { roots, best_finalized_number: self.best_finalized_number }
}
/// Same as [`find_node_where`](ForkTree::find_node_where), but returns mutable reference.
@@ -319,7 +302,8 @@ impl<H, N, V> ForkTree<H, N, V> where
number: &N,
is_descendent_of: &F,
predicate: &P,
) -> Result<Option<&mut Node<H, N, V>>, Error<E>> where
) -> Result<Option<&mut Node<H, N, V>>, Error<E>>
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
@@ -330,7 +314,7 @@ impl<H, N, V> ForkTree<H, N, V> where
// found the node, early exit
if let FindOutcome::Found(node) = node {
return Ok(Some(node));
return Ok(Some(node))
}
}
@@ -344,7 +328,8 @@ impl<H, N, V> ForkTree<H, N, V> where
number: &N,
is_descendent_of: &F,
predicate: &P,
) -> Result<Option<Vec<usize>>, Error<E>> where
) -> Result<Option<Vec<usize>>, Error<E>>
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
@@ -356,7 +341,7 @@ impl<H, N, V> ForkTree<H, N, V> where
// found the node, early exit
if let FindOutcome::Found(mut node) = node {
node.push(index);
return Ok(Some(node));
return Ok(Some(node))
}
}
@@ -367,7 +352,9 @@ impl<H, N, V> ForkTree<H, N, V> where
/// with the given hash exists. All other roots are pruned, and the children
/// of the finalized node become the new roots.
pub fn finalize_root(&mut self, hash: &H) -> Option<V> {
self.roots.iter().position(|node| node.hash == *hash)
self.roots
.iter()
.position(|node| node.hash == *hash)
.map(|position| self.finalize_root_at(position))
}
@@ -376,7 +363,7 @@ impl<H, N, V> ForkTree<H, N, V> where
let node = self.roots.swap_remove(position);
self.roots = node.children;
self.best_finalized_number = Some(node.number);
return node.data;
return node.data
}
/// Finalize a node in the tree. This method will make sure that the node
@@ -390,24 +377,25 @@ impl<H, N, V> ForkTree<H, N, V> where
number: N,
is_descendent_of: &F,
) -> Result<FinalizationResult<V>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
{
if let Some(ref best_finalized_number) = self.best_finalized_number {
if number <= *best_finalized_number {
return Err(Error::Revert);
return Err(Error::Revert)
}
}
// check if one of the current roots is being finalized
if let Some(root) = self.finalize_root(hash) {
return Ok(FinalizationResult::Changed(Some(root)));
return Ok(FinalizationResult::Changed(Some(root)))
}
// make sure we're not finalizing a descendent of any root
for root in self.roots.iter() {
if number > root.number && is_descendent_of(&root.hash, hash)? {
return Err(Error::UnfinalizedAncestor);
return Err(Error::UnfinalizedAncestor)
}
}
@@ -443,18 +431,19 @@ impl<H, N, V> ForkTree<H, N, V> where
number: N,
is_descendent_of: &F,
) -> Result<FinalizationResult<V>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
{
if let Some(ref best_finalized_number) = self.best_finalized_number {
if number <= *best_finalized_number {
return Err(Error::Revert);
return Err(Error::Revert)
}
}
// check if one of the current roots is being finalized
if let Some(root) = self.finalize_root(hash) {
return Ok(FinalizationResult::Changed(Some(root)));
return Ok(FinalizationResult::Changed(Some(root)))
}
// we need to:
@@ -469,23 +458,21 @@ impl<H, N, V> ForkTree<H, N, V> where
let is_finalized = root.hash == *hash;
let is_descendant =
!is_finalized && root.number > number && is_descendent_of(hash, &root.hash)?;
let is_ancestor = !is_finalized
&& !is_descendant && root.number < number
&& is_descendent_of(&root.hash, hash)?;
let is_ancestor = !is_finalized &&
!is_descendant && root.number < number &&
is_descendent_of(&root.hash, hash)?;
(is_finalized, is_descendant, is_ancestor)
};
// if we have met finalized root - open it and return
if is_finalized {
return Ok(FinalizationResult::Changed(Some(
self.finalize_root_at(idx),
)));
return Ok(FinalizationResult::Changed(Some(self.finalize_root_at(idx))))
}
// if node is descendant of finalized block - just leave it as is
if is_descendant {
idx += 1;
continue;
continue
}
// if node is ancestor of finalized block - remove it and continue with children
@@ -493,7 +480,7 @@ impl<H, N, V> ForkTree<H, N, V> where
let root = self.roots.swap_remove(idx);
self.roots.extend(root.children);
changed = true;
continue;
continue
}
// if node is neither ancestor, nor descendant of the finalized block - remove it
@@ -526,13 +513,14 @@ impl<H, N, V> ForkTree<H, N, V> where
is_descendent_of: &F,
predicate: P,
) -> Result<Option<bool>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
{
if let Some(ref best_finalized_number) = self.best_finalized_number {
if number <= *best_finalized_number {
return Err(Error::Revert);
return Err(Error::Revert)
}
}
@@ -544,11 +532,11 @@ impl<H, N, V> ForkTree<H, N, V> where
if node.hash == *hash || is_descendent_of(&node.hash, hash)? {
for node in node.children.iter() {
if node.number <= number && is_descendent_of(&node.hash, &hash)? {
return Err(Error::UnfinalizedAncestor);
return Err(Error::UnfinalizedAncestor)
}
}
return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash)));
return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash)))
}
}
}
@@ -570,13 +558,14 @@ impl<H, N, V> ForkTree<H, N, V> where
is_descendent_of: &F,
predicate: P,
) -> Result<FinalizationResult<V>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
{
if let Some(ref best_finalized_number) = self.best_finalized_number {
if number <= *best_finalized_number {
return Err(Error::Revert);
return Err(Error::Revert)
}
}
@@ -589,12 +578,12 @@ impl<H, N, V> ForkTree<H, N, V> where
if root.hash == *hash || is_descendent_of(&root.hash, hash)? {
for node in root.children.iter() {
if node.number <= number && is_descendent_of(&node.hash, &hash)? {
return Err(Error::UnfinalizedAncestor);
return Err(Error::UnfinalizedAncestor)
}
}
position = Some(i);
break;
break
}
}
}
@@ -616,9 +605,9 @@ impl<H, N, V> ForkTree<H, N, V> where
let roots = std::mem::take(&mut self.roots);
for root in roots {
let retain = root.number > number && is_descendent_of(hash, &root.hash)?
|| root.number == number && root.hash == *hash
|| is_descendent_of(&root.hash, hash)?;
let retain = root.number > number && is_descendent_of(hash, &root.hash)? ||
root.number == number && root.hash == *hash ||
is_descendent_of(&root.hash, hash)?;
if retain {
self.roots.push(root);
@@ -681,26 +670,14 @@ mod node_implementation {
}
/// Map node data into values of new types.
pub fn map<VT, F>(
self,
f: &mut F,
) -> Node<H, N, VT> where
pub fn map<VT, F>(self, f: &mut F) -> Node<H, N, VT>
where
F: FnMut(&H, &N, V) -> VT,
{
let children = self.children
.into_iter()
.map(|node| {
node.map(f)
})
.collect();
let children = self.children.into_iter().map(|node| node.map(f)).collect();
let vt = f(&self.hash, &self.number, self.data);
Node {
hash: self.hash,
number: self.number,
data: vt,
children,
}
Node { hash: self.hash, number: self.number, data: vt, children }
}
pub fn import<F, E: std::error::Error>(
@@ -710,14 +687,17 @@ mod node_implementation {
mut data: V,
is_descendent_of: &F,
) -> Result<Option<(H, N, V)>, Error<E>>
where E: fmt::Debug,
F: Fn(&H, &H) -> Result<bool, E>,
where
E: fmt::Debug,
F: Fn(&H, &H) -> Result<bool, E>,
{
if self.hash == hash {
return Err(Error::Duplicate);
return Err(Error::Duplicate)
};
if number <= self.number { return Ok(Some((hash, number, data))); }
if number <= self.number {
return Ok(Some((hash, number, data)))
}
for node in self.children.iter_mut() {
match node.import(hash, number, data, is_descendent_of)? {
@@ -731,12 +711,7 @@ mod node_implementation {
}
if is_descendent_of(&self.hash, &hash)? {
self.children.push(Node {
data,
hash: hash,
number: number,
children: Vec::new(),
});
self.children.push(Node { data, hash, number, children: Vec::new() });
Ok(None)
} else {
@@ -760,13 +735,14 @@ mod node_implementation {
is_descendent_of: &F,
predicate: &P,
) -> Result<FindOutcome<Vec<usize>>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
{
// stop searching this branch
if *number < self.number {
return Ok(FindOutcome::Failure(false));
return Ok(FindOutcome::Failure(false))
}
let mut known_descendent_of = false;
@@ -785,7 +761,7 @@ mod node_implementation {
// then it cannot be a descendent of any others,
// so we don't search them.
known_descendent_of = true;
break;
break
},
FindOutcome::Failure(false) => {},
}
@@ -799,7 +775,7 @@ mod node_implementation {
if is_descendent_of {
// if the predicate passes we return the node
if predicate(&self.data) {
return Ok(FindOutcome::Found(Vec::new()));
return Ok(FindOutcome::Found(Vec::new()))
}
}
@@ -820,9 +796,10 @@ mod node_implementation {
is_descendent_of: &F,
predicate: &P,
) -> Result<FindOutcome<&Node<H, N, V>>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
{
let outcome = self.find_node_index_where(hash, number, is_descendent_of, predicate)?;
@@ -852,9 +829,10 @@ mod node_implementation {
is_descendent_of: &F,
predicate: &P,
) -> Result<FindOutcome<&mut Node<H, N, V>>, Error<E>>
where E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
where
E: std::error::Error,
F: Fn(&H, &H) -> Result<bool, E>,
P: Fn(&V) -> bool,
{
let outcome = self.find_node_index_where(hash, number, is_descendent_of, predicate)?;
@@ -875,7 +853,7 @@ mod node_implementation {
}
// Workaround for: https://github.com/rust-lang/rust/issues/34537
use node_implementation::{Node, FindOutcome};
use node_implementation::{FindOutcome, Node};
struct ForkTreeIterator<'a, H, N, V> {
stack: Vec<&'a Node<H, N, V>>,
@@ -917,7 +895,7 @@ impl<H, N, V> Iterator for RemovedIterator<H, N, V> {
#[cfg(test)]
mod test {
use super::{FinalizationResult, ForkTree, Error};
use super::{Error, FinalizationResult, ForkTree};
#[derive(Debug, PartialEq)]
struct TestError;
@@ -930,10 +908,10 @@ mod test {
impl std::error::Error for TestError {}
fn test_fork_tree<'a>() -> (ForkTree<&'a str, u64, ()>, impl Fn(&&str, &&str) -> Result<bool, TestError>) {
fn test_fork_tree<'a>(
) -> (ForkTree<&'a str, u64, ()>, impl Fn(&&str, &&str) -> Result<bool, TestError>) {
let mut tree = ForkTree::new();
//
// - B - C - D - E
// /
// / - G
@@ -959,7 +937,8 @@ mod test {
("C", b) => Ok(b == "D" || b == "E"),
("D", b) => Ok(b == "E"),
("E", _) => Ok(false),
("F", b) => Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "O"),
("F", b) =>
Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "O"),
("G", _) => Ok(false),
("H", b) => Ok(b == "I" || b == "L" || b == "M" || b == "O"),
("I", _) => Ok(false),
@@ -1001,40 +980,22 @@ mod test {
tree.finalize_root(&"A");
assert_eq!(
tree.best_finalized_number,
Some(1),
);
assert_eq!(tree.best_finalized_number, Some(1),);
assert_eq!(
tree.import("A", 1, (), &is_descendent_of),
Err(Error::Revert),
);
assert_eq!(tree.import("A", 1, (), &is_descendent_of), Err(Error::Revert),);
}
#[test]
fn import_doesnt_add_duplicates() {
let (mut tree, is_descendent_of) = test_fork_tree();
assert_eq!(
tree.import("A", 1, (), &is_descendent_of),
Err(Error::Duplicate),
);
assert_eq!(tree.import("A", 1, (), &is_descendent_of), Err(Error::Duplicate),);
assert_eq!(
tree.import("I", 4, (), &is_descendent_of),
Err(Error::Duplicate),
);
assert_eq!(tree.import("I", 4, (), &is_descendent_of), Err(Error::Duplicate),);
assert_eq!(
tree.import("G", 3, (), &is_descendent_of),
Err(Error::Duplicate),
);
assert_eq!(tree.import("G", 3, (), &is_descendent_of), Err(Error::Duplicate),);
assert_eq!(
tree.import("K", 3, (), &is_descendent_of),
Err(Error::Duplicate),
);
assert_eq!(tree.import("K", 3, (), &is_descendent_of), Err(Error::Duplicate),);
}
#[test]
@@ -1096,10 +1057,7 @@ mod test {
let original_roots = tree.roots.clone();
// finalizing a block prior to any in the node doesn't change the tree
assert_eq!(
tree.finalize(&"0", 0, &is_descendent_of),
Ok(FinalizationResult::Unchanged),
);
assert_eq!(tree.finalize(&"0", 0, &is_descendent_of), Ok(FinalizationResult::Unchanged),);
assert_eq!(tree.roots, original_roots);
@@ -1115,21 +1073,12 @@ mod test {
);
// finalizing anything lower than what we observed will fail
assert_eq!(
tree.best_finalized_number,
Some(1),
);
assert_eq!(tree.best_finalized_number, Some(1),);
assert_eq!(
tree.finalize(&"Z", 1, &is_descendent_of),
Err(Error::Revert),
);
assert_eq!(tree.finalize(&"Z", 1, &is_descendent_of), Err(Error::Revert),);
// trying to finalize a node without finalizing its ancestors first will fail
assert_eq!(
tree.finalize(&"H", 3, &is_descendent_of),
Err(Error::UnfinalizedAncestor),
);
assert_eq!(tree.finalize(&"H", 3, &is_descendent_of), Err(Error::UnfinalizedAncestor),);
// after finalizing "F" we can finalize "H"
assert_eq!(
@@ -1195,10 +1144,7 @@ mod test {
vec![("L", 4), ("I", 4)],
);
assert_eq!(
tree.best_finalized_number,
Some(3),
);
assert_eq!(tree.best_finalized_number, Some(3),);
// finalizing N (which is not a part of the tree):
// 1) removes roots that are not ancestors/descendants of N (I)
@@ -1215,23 +1161,20 @@ mod test {
vec![],
);
assert_eq!(
tree.best_finalized_number,
Some(6),
);
assert_eq!(tree.best_finalized_number, Some(6),);
}
#[test]
fn finalize_with_descendent_works() {
#[derive(Debug, PartialEq)]
struct Change { effective: u64 }
struct Change {
effective: u64,
}
let (mut tree, is_descendent_of) = {
let mut tree = ForkTree::new();
let is_descendent_of = |base: &&str, block: &&str| -> Result<bool, TestError> {
//
// A0 #1 - (B #2) - (C #5) - D #10 - E #15 - (F #100)
// \
// - (G #100)
@@ -1270,24 +1213,15 @@ mod test {
// finalizing "D" will finalize a block from the tree, but it can't be applied yet
// since it is not a root change
assert_eq!(
tree.finalizes_any_with_descendent_if(
&"D",
10,
&is_descendent_of,
|c| c.effective == 10,
),
tree.finalizes_any_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective ==
10,),
Ok(Some(false)),
);
// finalizing "B" doesn't finalize "A0" since the predicate doesn't pass,
// although it will clear out "A1" from the tree
assert_eq!(
tree.finalize_with_descendent_if(
&"B",
2,
&is_descendent_of,
|c| c.effective <= 2,
),
tree.finalize_with_descendent_if(&"B", 2, &is_descendent_of, |c| c.effective <= 2,),
Ok(FinalizationResult::Changed(None)),
);
@@ -1308,12 +1242,7 @@ mod test {
);
assert_eq!(
tree.finalize_with_descendent_if(
&"C",
5,
&is_descendent_of,
|c| c.effective <= 5,
),
tree.finalize_with_descendent_if(&"C", 5, &is_descendent_of, |c| c.effective <= 5,),
Ok(FinalizationResult::Changed(Some(Change { effective: 5 }))),
);
@@ -1324,33 +1253,20 @@ mod test {
// finalizing "F" will fail since it would finalize past "E" without finalizing "D" first
assert_eq!(
tree.finalizes_any_with_descendent_if(
&"F",
100,
&is_descendent_of,
|c| c.effective <= 100,
),
tree.finalizes_any_with_descendent_if(&"F", 100, &is_descendent_of, |c| c.effective <=
100,),
Err(Error::UnfinalizedAncestor),
);
// it will work with "G" though since it is not in the same branch as "E"
assert_eq!(
tree.finalizes_any_with_descendent_if(
&"G",
100,
&is_descendent_of,
|c| c.effective <= 100,
),
tree.finalizes_any_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <=
100,),
Ok(Some(true)),
);
assert_eq!(
tree.finalize_with_descendent_if(
&"G",
100,
&is_descendent_of,
|c| c.effective <= 100,
),
tree.finalize_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <= 100,),
Ok(FinalizationResult::Changed(Some(Change { effective: 10 }))),
);
@@ -1365,12 +1281,19 @@ mod test {
tree.iter().map(|(h, n, _)| (h.clone(), n.clone())).collect::<Vec<_>>(),
vec![
("A", 1),
("B", 2), ("C", 3), ("D", 4), ("E", 5),
("F", 2), ("H", 3), ("L", 4), ("M", 5),
("B", 2),
("C", 3),
("D", 4),
("E", 5),
("F", 2),
("H", 3),
("L", 4),
("M", 5),
("O", 5),
("I", 4),
("G", 3),
("J", 2), ("K", 3),
("J", 2),
("K", 3),
],
);
}
@@ -1400,19 +1323,11 @@ mod test {
// "L" is a descendent of "K", but the predicate will only pass for "K",
// therefore only one call to `is_descendent_of` should be made
assert_eq!(
tree.finalizes_any_with_descendent_if(
&"L",
11,
&is_descendent_of,
|i| *i == 10,
),
tree.finalizes_any_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,),
Ok(Some(false)),
);
assert_eq!(
n_is_descendent_of_calls.load(Ordering::SeqCst),
1,
);
assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1,);
}
n_is_descendent_of_calls.store(0, Ordering::SeqCst);
@@ -1431,19 +1346,11 @@ mod test {
// "L" is a descendent of "K", but the predicate will only pass for "K",
// therefore only one call to `is_descendent_of` should be made
assert_eq!(
tree.finalize_with_descendent_if(
&"L",
11,
&is_descendent_of,
|i| *i == 10,
),
tree.finalize_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,),
Ok(FinalizationResult::Changed(Some(10))),
);
assert_eq!(
n_is_descendent_of_calls.load(Ordering::SeqCst),
1,
);
assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1,);
}
}
@@ -1451,12 +1358,7 @@ mod test {
fn find_node_works() {
let (tree, is_descendent_of) = test_fork_tree();
let node = tree.find_node_where(
&"D",
&4,
&is_descendent_of,
&|_| true,
).unwrap().unwrap();
let node = tree.find_node_where(&"D", &4, &is_descendent_of, &|_| true).unwrap().unwrap();
assert_eq!(node.hash, "C");
assert_eq!(node.number, 3);
@@ -1473,17 +1375,9 @@ mod test {
fn prune_works() {
let (mut tree, is_descendent_of) = test_fork_tree();
let removed = tree.prune(
&"C",
&3,
&is_descendent_of,
&|_| true,
).unwrap();
let removed = tree.prune(&"C", &3, &is_descendent_of, &|_| true).unwrap();
assert_eq!(
tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(),
vec!["B"],
);
assert_eq!(tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(), vec!["B"],);
assert_eq!(
tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(),
@@ -1495,34 +1389,19 @@ mod test {
vec!["A", "F", "H", "L", "M", "O", "I", "G", "J", "K"]
);
let removed = tree.prune(
&"E",
&5,
&is_descendent_of,
&|_| true,
).unwrap();
let removed = tree.prune(&"E", &5, &is_descendent_of, &|_| true).unwrap();
assert_eq!(
tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(),
vec!["D"],
);
assert_eq!(tree.roots.iter().map(|node| node.hash).collect::<Vec<_>>(), vec!["D"],);
assert_eq!(
tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(),
vec!["D", "E"],
);
assert_eq!(tree.iter().map(|(hash, _, _)| *hash).collect::<Vec<_>>(), vec!["D", "E"],);
assert_eq!(
removed.map(|(hash, _, _)| hash).collect::<Vec<_>>(),
vec!["B", "C"]
);
assert_eq!(removed.map(|(hash, _, _)| hash).collect::<Vec<_>>(), vec!["B", "C"]);
}
#[test]
fn find_node_backtracks_after_finding_highest_descending_node() {
let mut tree = ForkTree::new();
//
// A - B
// \
// — C
@@ -1543,12 +1422,7 @@ mod test {
// when searching the tree we reach node `C`, but the
// predicate doesn't pass. we should backtrack to `B`, but not to `A`,
// since "B" fulfills the predicate.
let node = tree.find_node_where(
&"D",
&3,
&is_descendent_of,
&|data| *data < 3,
).unwrap();
let node = tree.find_node_where(&"D", &3, &is_descendent_of, &|data| *data < 3).unwrap();
assert_eq!(node.unwrap().hash, "B");
}
@@ -19,7 +19,7 @@ use crate::BenchmarkCmd;
use codec::{Decode, Encode};
use frame_benchmarking::{Analysis, BenchmarkBatch, BenchmarkSelector};
use frame_support::traits::StorageInfo;
use sc_cli::{SharedParams, CliConfiguration, ExecutionStrategy, Result};
use sc_cli::{CliConfiguration, ExecutionStrategy, Result, SharedParams};
use sc_client_db::BenchmarkingState;
use sc_executor::NativeExecutor;
use sc_service::{Configuration, NativeExecutionDispatch};
@@ -49,11 +49,15 @@ impl BenchmarkCmd {
}
if let Some(header_file) = &self.header {
if !header_file.is_file() { return Err("Header file is invalid!".into()) };
if !header_file.is_file() {
return Err("Header file is invalid!".into())
};
}
if let Some(handlebars_template_file) = &self.template {
if !handlebars_template_file.is_file() { return Err("Handlebars template file is invalid!".into()) };
if !handlebars_template_file.is_file() {
return Err("Handlebars template file is invalid!".into())
};
}
let spec = config.chain_spec;
@@ -93,7 +97,8 @@ impl BenchmarkCmd {
self.repeat,
!self.no_verify,
self.extra,
).encode(),
)
.encode(),
extensions,
&sp_state_machine::backend::BackendRuntimeCode::new(&state).runtime_code()?,
sp_core::testing::TaskExecutor::new(),
@@ -126,20 +131,25 @@ impl BenchmarkCmd {
);
// Skip raw data + analysis if there are no results
if batch.results.is_empty() { continue }
if batch.results.is_empty() {
continue
}
if self.raw_data {
// Print the table header
batch.results[0].components.iter().for_each(|param| print!("{:?},", param.0));
batch.results[0]
.components
.iter()
.for_each(|param| print!("{:?},", param.0));
print!("extrinsic_time_ns,storage_root_time_ns,reads,repeat_reads,writes,repeat_writes,proof_size_bytes\n");
// Print the values
batch.results.iter().for_each(|result| {
let parameters = &result.components;
parameters.iter().for_each(|param| print!("{:?},", param.1));
// Print extrinsic time and storage root time
print!("{:?},{:?},{:?},{:?},{:?},{:?},{:?}\n",
print!(
"{:?},{:?},{:?},{:?},{:?},{:?},{:?}\n",
result.extrinsic_time,
result.storage_root_time,
result.reads,
@@ -156,25 +166,39 @@ impl BenchmarkCmd {
// Conduct analysis.
if !self.no_median_slopes {
println!("Median Slopes Analysis\n========");
if let Some(analysis) = Analysis::median_slopes(&batch.results, BenchmarkSelector::ExtrinsicTime) {
if let Some(analysis) = Analysis::median_slopes(
&batch.results,
BenchmarkSelector::ExtrinsicTime,
) {
println!("-- Extrinsic Time --\n{}", analysis);
}
if let Some(analysis) = Analysis::median_slopes(&batch.results, BenchmarkSelector::Reads) {
if let Some(analysis) =
Analysis::median_slopes(&batch.results, BenchmarkSelector::Reads)
{
println!("Reads = {:?}", analysis);
}
if let Some(analysis) = Analysis::median_slopes(&batch.results, BenchmarkSelector::Writes) {
if let Some(analysis) =
Analysis::median_slopes(&batch.results, BenchmarkSelector::Writes)
{
println!("Writes = {:?}", analysis);
}
}
if !self.no_min_squares {
println!("Min Squares Analysis\n========");
if let Some(analysis) = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::ExtrinsicTime) {
if let Some(analysis) = Analysis::min_squares_iqr(
&batch.results,
BenchmarkSelector::ExtrinsicTime,
) {
println!("-- Extrinsic Time --\n{}", analysis);
}
if let Some(analysis) = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Reads) {
if let Some(analysis) =
Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Reads)
{
println!("Reads = {:?}", analysis);
}
if let Some(analysis) = Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Writes) {
if let Some(analysis) =
Analysis::min_squares_iqr(&batch.results, BenchmarkSelector::Writes)
{
println!("Writes = {:?}", analysis);
}
}
@@ -17,21 +17,23 @@
// Outputs benchmark results to Rust files that can be ingested by the runtime.
use std::collections::{HashMap, HashSet};
use std::fs;
use std::path::PathBuf;
use core::convert::TryInto;
use std::{
collections::{HashMap, HashSet},
fs,
path::PathBuf,
};
use serde::Serialize;
use inflector::Inflector;
use serde::Serialize;
use crate::BenchmarkCmd;
use frame_benchmarking::{
BenchmarkBatch, BenchmarkSelector, Analysis, AnalysisChoice, RegressionModel, BenchmarkResults,
Analysis, AnalysisChoice, BenchmarkBatch, BenchmarkResults, BenchmarkSelector, RegressionModel,
};
use frame_support::traits::StorageInfo;
use sp_core::hexdisplay::HexDisplay;
use sp_runtime::traits::Zero;
use frame_support::traits::StorageInfo;
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const TEMPLATE: &str = include_str!("./template.hbs");
@@ -117,7 +119,9 @@ fn map_results(
analysis_choice: &AnalysisChoice,
) -> Result<HashMap<(String, String), Vec<BenchmarkData>>, std::io::Error> {
// Skip if batches is empty.
if batches.is_empty() { return Err(io_error("empty batches")) }
if batches.is_empty() {
return Err(io_error("empty batches"))
}
let mut all_benchmarks = HashMap::new();
let mut pallet_benchmarks = Vec::new();
@@ -125,7 +129,9 @@ fn map_results(
let mut batches_iter = batches.iter().peekable();
while let Some(batch) = batches_iter.next() {
// Skip if there are no results
if batch.results.is_empty() { continue }
if batch.results.is_empty() {
continue
}
let pallet_string = String::from_utf8(batch.pallet.clone()).unwrap();
let instance_string = String::from_utf8(batch.instance.clone()).unwrap();
@@ -150,13 +156,11 @@ fn map_results(
}
// Get an iterator of errors from a model. If the model is `None` all errors are zero.
fn extract_errors(model: &Option<RegressionModel>) -> impl Iterator<Item=u128> + '_ {
fn extract_errors(model: &Option<RegressionModel>) -> impl Iterator<Item = u128> + '_ {
let mut errors = model.as_ref().map(|m| m.se.regressor_values.iter());
std::iter::from_fn(move || {
match &mut errors {
Some(model) => model.next().map(|val| *val as u128),
_ => Some(0),
}
std::iter::from_fn(move || match &mut errors {
Some(model) => model.next().map(|val| *val as u128),
_ => Some(0),
})
}
@@ -189,12 +193,16 @@ fn get_benchmark_data(
let mut used_reads = Vec::new();
let mut used_writes = Vec::new();
extrinsic_time.slopes.into_iter()
extrinsic_time
.slopes
.into_iter()
.zip(extrinsic_time.names.iter())
.zip(extract_errors(&extrinsic_time.model))
.for_each(|((slope, name), error)| {
if !slope.is_zero() {
if !used_components.contains(&name) { used_components.push(name); }
if !used_components.contains(&name) {
used_components.push(name);
}
used_extrinsic_time.push(ComponentSlope {
name: name.clone(),
slope: slope.saturating_mul(1000),
@@ -202,35 +210,36 @@ fn get_benchmark_data(
});
}
});
reads.slopes.into_iter()
reads
.slopes
.into_iter()
.zip(reads.names.iter())
.zip(extract_errors(&reads.model))
.for_each(|((slope, name), error)| {
if !slope.is_zero() {
if !used_components.contains(&name) { used_components.push(name); }
used_reads.push(ComponentSlope {
name: name.clone(),
slope,
error,
});
if !used_components.contains(&name) {
used_components.push(name);
}
used_reads.push(ComponentSlope { name: name.clone(), slope, error });
}
});
writes.slopes.into_iter()
writes
.slopes
.into_iter()
.zip(writes.names.iter())
.zip(extract_errors(&writes.model))
.for_each(|((slope, name), error)| {
if !slope.is_zero() {
if !used_components.contains(&name) { used_components.push(name); }
used_writes.push(ComponentSlope {
name: name.clone(),
slope,
error,
});
if !used_components.contains(&name) {
used_components.push(name);
}
used_writes.push(ComponentSlope { name: name.clone(), slope, error });
}
});
// This puts a marker on any component which is entirely unused in the weight formula.
let components = batch.results[0].components
let components = batch.results[0]
.components
.iter()
.map(|(name, _)| -> Component {
let name_string = name.to_string();
@@ -264,12 +273,8 @@ pub fn write_results(
) -> Result<(), std::io::Error> {
// Use custom template if provided.
let template: String = match &cmd.template {
Some(template_file) => {
fs::read_to_string(template_file)?
},
None => {
TEMPLATE.to_string()
},
Some(template_file) => fs::read_to_string(template_file)?,
None => TEMPLATE.to_string(),
};
// Use header if provided
@@ -288,9 +293,8 @@ pub fn write_results(
let args = std::env::args().collect::<Vec<String>>();
// Which analysis function should be used when outputting benchmarks
let analysis_choice: AnalysisChoice = cmd.output_analysis.clone()
.try_into()
.map_err(|e| io_error(e))?;
let analysis_choice: AnalysisChoice =
cmd.output_analysis.clone().try_into().map_err(|e| io_error(e))?;
// Capture individual args
let cmd_data = CmdData {
@@ -341,7 +345,8 @@ pub fn write_results(
};
let mut output_file = fs::File::create(file_path)?;
handlebars.render_template_to_write(&template, &hbs_data, &mut output_file)
handlebars
.render_template_to_write(&template, &hbs_data, &mut output_file)
.map_err(|e| io_error(&e.to_string()))?;
}
Ok(())
@@ -355,7 +360,9 @@ fn add_storage_comments(
results: &[BenchmarkResults],
storage_info: &[StorageInfo],
) {
let storage_info_map = storage_info.iter().map(|info| (info.prefix.clone(), info))
let storage_info_map = storage_info
.iter()
.map(|info| (info.prefix.clone(), info))
.collect::<HashMap<_, _>>();
// This tracks the keys we already identified, so we only generate a single comment.
let mut identified = HashSet::<Vec<u8>>::new();
@@ -363,12 +370,14 @@ fn add_storage_comments(
for result in results.clone() {
for (key, reads, writes, whitelisted) in &result.keys {
// skip keys which are whitelisted
if *whitelisted { continue; }
if *whitelisted {
continue
}
let prefix_length = key.len().min(32);
let prefix = key[0..prefix_length].to_vec();
if identified.contains(&prefix) {
// skip adding comments for keys we already identified
continue;
continue
} else {
// track newly identified keys
identified.insert(prefix.clone());
@@ -377,8 +386,10 @@ fn add_storage_comments(
Some(key_info) => {
let comment = format!(
"Storage: {} {} (r:{} w:{})",
String::from_utf8(key_info.pallet_name.clone()).expect("encoded from string"),
String::from_utf8(key_info.storage_name.clone()).expect("encoded from string"),
String::from_utf8(key_info.pallet_name.clone())
.expect("encoded from string"),
String::from_utf8(key_info.storage_name.clone())
.expect("encoded from string"),
reads,
writes,
);
@@ -392,7 +403,7 @@ fn add_storage_comments(
writes,
);
comments.push(comment)
}
},
}
}
}
@@ -400,7 +411,8 @@ fn add_storage_comments(
// Add an underscore after every 3rd character, i.e. a separator for large numbers.
fn underscore<Number>(i: Number) -> String
where Number: std::string::ToString
where
Number: std::string::ToString,
{
let mut s = String::new();
let i_str = i.to_string();
@@ -420,11 +432,12 @@ fn underscore<Number>(i: Number) -> String
struct UnderscoreHelper;
impl handlebars::HelperDef for UnderscoreHelper {
fn call<'reg: 'rc, 'rc>(
&self, h: &handlebars::Helper,
&self,
h: &handlebars::Helper,
_: &handlebars::Handlebars,
_: &handlebars::Context,
_rc: &mut handlebars::RenderContext,
out: &mut dyn handlebars::Output
out: &mut dyn handlebars::Output,
) -> handlebars::HelperResult {
use handlebars::JsonRender;
let param = h.param(0).unwrap();
@@ -439,17 +452,20 @@ impl handlebars::HelperDef for UnderscoreHelper {
struct JoinHelper;
impl handlebars::HelperDef for JoinHelper {
fn call<'reg: 'rc, 'rc>(
&self, h: &handlebars::Helper,
&self,
h: &handlebars::Helper,
_: &handlebars::Handlebars,
_: &handlebars::Context,
_rc: &mut handlebars::RenderContext,
out: &mut dyn handlebars::Output
out: &mut dyn handlebars::Output,
) -> handlebars::HelperResult {
use handlebars::JsonRender;
let param = h.param(0).unwrap();
let value = param.value();
let joined = if value.is_array() {
value.as_array().unwrap()
value
.as_array()
.unwrap()
.iter()
.map(|v| v.render())
.collect::<Vec<String>>()
@@ -465,9 +481,9 @@ impl handlebars::HelperDef for JoinHelper {
// u128 does not serialize well into JSON for `handlebars`, so we represent it as a string.
fn string_serialize<S>(x: &u128, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
S: serde::Serializer,
{
s.serialize_str(&x.to_string())
s.serialize_str(&x.to_string())
}
#[cfg(test)]
@@ -475,22 +491,26 @@ mod test {
use super::*;
use frame_benchmarking::{BenchmarkBatch, BenchmarkParameter, BenchmarkResults};
fn test_data(pallet: &[u8], benchmark: &[u8], param: BenchmarkParameter, base: u32, slope: u32) -> BenchmarkBatch {
fn test_data(
pallet: &[u8],
benchmark: &[u8],
param: BenchmarkParameter,
base: u32,
slope: u32,
) -> BenchmarkBatch {
let mut results = Vec::new();
for i in 0 .. 5 {
results.push(
BenchmarkResults {
components: vec![(param, i), (BenchmarkParameter::z, 0)],
extrinsic_time: (base + slope * i).into(),
storage_root_time: (base + slope * i).into(),
reads: (base + slope * i).into(),
repeat_reads: 0,
writes: (base + slope * i).into(),
repeat_writes: 0,
proof_size: 0,
keys: vec![],
}
)
for i in 0..5 {
results.push(BenchmarkResults {
components: vec![(param, i), (BenchmarkParameter::z, 0)],
extrinsic_time: (base + slope * i).into(),
storage_root_time: (base + slope * i).into(),
reads: (base + slope * i).into(),
repeat_reads: 0,
writes: (base + slope * i).into(),
repeat_writes: 0,
proof_size: 0,
keys: vec![],
})
}
return BenchmarkBatch {
@@ -506,37 +526,25 @@ mod test {
benchmark.components,
vec![
Component { name: component.to_string(), is_used: true },
Component { name: "z".to_string(), is_used: false},
Component { name: "z".to_string(), is_used: false },
],
);
// Weights multiplied by 1,000
assert_eq!(benchmark.base_weight, base * 1_000);
assert_eq!(
benchmark.component_weight,
vec![ComponentSlope {
name: component.to_string(),
slope: slope * 1_000,
error: 0,
}]
vec![ComponentSlope { name: component.to_string(), slope: slope * 1_000, error: 0 }]
);
// DB Reads/Writes are untouched
assert_eq!(benchmark.base_reads, base);
assert_eq!(
benchmark.component_reads,
vec![ComponentSlope {
name: component.to_string(),
slope,
error: 0,
}]
vec![ComponentSlope { name: component.to_string(), slope, error: 0 }]
);
assert_eq!(benchmark.base_writes, base);
assert_eq!(
benchmark.component_writes,
vec![ComponentSlope {
name: component.to_string(),
slope,
error: 0,
}]
vec![ComponentSlope { name: component.to_string(), slope, error: 0 }]
);
}
@@ -550,23 +558,24 @@ mod test {
],
&[],
&AnalysisChoice::default(),
).unwrap();
)
.unwrap();
let first_benchmark = &mapped_results.get(
&("first_pallet".to_string(), "instance".to_string())
).unwrap()[0];
let first_benchmark = &mapped_results
.get(&("first_pallet".to_string(), "instance".to_string()))
.unwrap()[0];
assert_eq!(first_benchmark.name, "first_benchmark");
check_data(first_benchmark, "a", 10, 3);
let second_benchmark = &mapped_results.get(
&("first_pallet".to_string(), "instance".to_string())
).unwrap()[1];
let second_benchmark = &mapped_results
.get(&("first_pallet".to_string(), "instance".to_string()))
.unwrap()[1];
assert_eq!(second_benchmark.name, "second_benchmark");
check_data(second_benchmark, "b", 9, 2);
let second_pallet_benchmark = &mapped_results.get(
&("second_pallet".to_string(), "instance".to_string())
).unwrap()[0];
let second_pallet_benchmark = &mapped_results
.get(&("second_pallet".to_string(), "instance".to_string()))
.unwrap()[0];
assert_eq!(second_pallet_benchmark.name, "first_benchmark");
check_data(second_pallet_benchmark, "c", 3, 4);
}
@@ -20,4 +20,3 @@
mod pallet_id;
pub use pallet_id::PalletIdCmd;
@@ -17,22 +17,19 @@
//! Implementation of the `palletid` subcommand
use sc_cli::{
Error, utils::print_from_uri, CryptoSchemeFlag,
OutputTypeFlag, KeystoreParams, with_crypto_scheme,
};
use sp_runtime::traits::AccountIdConversion;
use sp_core::crypto::{Ss58Codec, Ss58AddressFormat};
use std::convert::{TryInto, TryFrom};
use structopt::StructOpt;
use frame_support::PalletId;
use sc_cli::{
utils::print_from_uri, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams,
OutputTypeFlag,
};
use sp_core::crypto::{Ss58AddressFormat, Ss58Codec};
use sp_runtime::traits::AccountIdConversion;
use std::convert::{TryFrom, TryInto};
use structopt::StructOpt;
/// The `palletid` command
#[derive(Debug, StructOpt)]
#[structopt(
name = "palletid",
about = "Inspect a module ID address"
)]
#[structopt(name = "palletid", about = "Inspect a module ID address")]
pub struct PalletIdCmd {
/// The module ID used to derive the account
id: String,
@@ -63,18 +60,18 @@ pub struct PalletIdCmd {
impl PalletIdCmd {
/// runs the command
pub fn run<R>(&self) -> Result<(), Error>
where
R: frame_system::Config,
R::AccountId: Ss58Codec,
where
R: frame_system::Config,
R::AccountId: Ss58Codec,
{
if self.id.len() != 8 {
Err("a module id must be a string of 8 characters")?
}
let password = self.keystore_params.read_password()?;
let id_fixed_array: [u8; 8] = self.id.as_bytes()
.try_into()
.map_err(|_| "Cannot convert argument to palletid: argument should be 8-character string")?;
let id_fixed_array: [u8; 8] = self.id.as_bytes().try_into().map_err(|_| {
"Cannot convert argument to palletid: argument should be 8-character string"
})?;
let account_id: R::AccountId = PalletId(id_fixed_array).into_account();
@@ -91,4 +88,3 @@ impl PalletIdCmd {
Ok(())
}
}
@@ -20,22 +20,20 @@
//! An equivalent of `sp_io::TestExternalities` that can load its state from a remote substrate
//! based chain, or a local state snapshot file.
use codec::{Decode, Encode};
use jsonrpsee_ws_client::{types::v2::params::JsonRpcParams, WsClient, WsClientBuilder};
use log::*;
use sp_core::{
hashing::twox_128,
hexdisplay::HexDisplay,
storage::{StorageData, StorageKey},
};
pub use sp_io::TestExternalities;
use sp_runtime::traits::Block as BlockT;
use std::{
fs,
path::{Path, PathBuf},
};
use log::*;
use sp_core::hashing::twox_128;
pub use sp_io::TestExternalities;
use sp_core::{
hexdisplay::HexDisplay,
storage::{StorageKey, StorageData},
};
use codec::{Encode, Decode};
use sp_runtime::traits::Block as BlockT;
use jsonrpsee_ws_client::{
WsClientBuilder, WsClient, types::v2::params::JsonRpcParams,
};
pub mod rpc_api;
@@ -122,7 +120,10 @@ pub struct OnlineConfig<B: BlockT> {
impl<B: BlockT> OnlineConfig<B> {
/// Return rpc (ws) client.
fn rpc_client(&self) -> &WsClient {
self.transport.client.as_ref().expect("ws client must have been initialized by now; qed.")
self.transport
.client
.as_ref()
.expect("ws client must have been initialized by now; qed.")
}
}
@@ -137,7 +138,6 @@ impl<B: BlockT> Default for OnlineConfig<B> {
}
}
/// Configuration of the state snapshot.
#[derive(Clone)]
pub struct SnapshotConfig {
@@ -208,10 +208,12 @@ impl<B: BlockT> Builder<B> {
maybe_at: Option<B::Hash>,
) -> Result<StorageData, &'static str> {
trace!(target: LOG_TARGET, "rpc: get_storage");
RpcApi::<B>::get_storage(self.as_online().rpc_client(), key, maybe_at).await.map_err(|e| {
error!("Error = {:?}", e);
"rpc get_storage failed."
})
RpcApi::<B>::get_storage(self.as_online().rpc_client(), key, maybe_at)
.await
.map_err(|e| {
error!("Error = {:?}", e);
"rpc get_storage failed."
})
}
/// Get the latest finalized head.
async fn rpc_get_head(&self) -> Result<B::Hash, &'static str> {
@@ -249,7 +251,7 @@ impl<B: BlockT> Builder<B> {
if page_len < PAGE as usize {
debug!(target: LOG_TARGET, "last page received: {}", page_len);
break all_keys;
break all_keys
} else {
let new_last_key =
all_keys.last().expect("all_keys is populated; has .last(); qed");
@@ -290,21 +292,22 @@ impl<B: BlockT> Builder<B> {
.map(|key| {
(
"state_getStorage",
JsonRpcParams::Array(
vec![
to_value(key).expect("json serialization will work; qed."),
to_value(at).expect("json serialization will work; qed."),
]
),
JsonRpcParams::Array(vec![
to_value(key).expect("json serialization will work; qed."),
to_value(at).expect("json serialization will work; qed."),
]),
)
})
.collect::<Vec<_>>();
let values = client.batch_request::<Option<StorageData>>(batch)
.await
.map_err(|e| {
log::error!(target: LOG_TARGET, "failed to execute batch: {:?}. Error: {:?}", chunk_keys, e);
"batch failed."
})?;
let values = client.batch_request::<Option<StorageData>>(batch).await.map_err(|e| {
log::error!(
target: LOG_TARGET,
"failed to execute batch: {:?}. Error: {:?}",
chunk_keys,
e
);
"batch failed."
})?;
assert_eq!(chunk_keys.len(), values.len());
for (idx, key) in chunk_keys.into_iter().enumerate() {
let maybe_value = values[idx].clone();
@@ -428,7 +431,7 @@ impl<B: BlockT> Builder<B> {
self.save_state_snapshot(&kp, &c.path)?;
}
kp
}
},
};
info!(
@@ -497,7 +500,7 @@ impl<B: BlockT> Builder<B> {
#[cfg(test)]
mod test_prelude {
pub(crate) use super::*;
pub(crate) use sp_runtime::testing::{H256 as Hash, Block as RawBlock, ExtrinsicWrapper};
pub(crate) use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256 as Hash};
pub(crate) type Block = RawBlock<ExtrinsicWrapper<Hash>>;
@@ -551,7 +554,11 @@ mod remote_tests {
init_logger();
Builder::<Block>::new()
.mode(Mode::Online(OnlineConfig {
modules: vec!["Proxy".to_owned(), "Multisig".to_owned(), "PhragmenElection".to_owned()],
modules: vec![
"Proxy".to_owned(),
"Multisig".to_owned(),
"PhragmenElection".to_owned(),
],
..Default::default()
}))
.build()
@@ -18,14 +18,13 @@
//! WS RPC API for one off RPC calls to a substrate node.
// TODO: Consolidate one off RPC calls https://github.com/paritytech/substrate/issues/8988
use sp_runtime::{generic::SignedBlock, traits::{Block as BlockT, Header as HeaderT}};
use jsonrpsee_ws_client::{
WsClientBuilder,
WsClient,
types::{
v2::params::JsonRpcParams,
traits::Client
},
types::{traits::Client, v2::params::JsonRpcParams},
WsClient, WsClientBuilder,
};
use sp_runtime::{
generic::SignedBlock,
traits::{Block as BlockT, Header as HeaderT},
};
/// Get the header of the block identified by `at`
@@ -38,7 +37,8 @@ where
let params = vec![hash_to_json::<Block>(at)?];
let client = build_client(from).await?;
client.request::<Block::Header>("chain_getHeader", JsonRpcParams::Array(params))
client
.request::<Block::Header>("chain_getHeader", JsonRpcParams::Array(params))
.await
.map_err(|e| format!("chain_getHeader request failed: {:?}", e))
}
@@ -51,7 +51,8 @@ where
{
let client = build_client(from).await?;
client.request::<Block::Hash>("chain_getFinalizedHead", JsonRpcParams::NoParams)
client
.request::<Block::Hash>("chain_getFinalizedHead", JsonRpcParams::NoParams)
.await
.map_err(|e| format!("chain_getFinalizedHead request failed: {:?}", e))
}
@@ -81,7 +82,7 @@ fn hash_to_json<Block: BlockT>(hash: Block::Hash) -> Result<serde_json::Value, S
/// Build a website client that connects to `from`.
async fn build_client<S: AsRef<str>>(from: S) -> Result<WsClient, String> {
WsClientBuilder::default()
WsClientBuilder::default()
.max_request_body_size(u32::MAX)
.build(from.as_ref())
.await
+8 -19
View File
@@ -20,16 +20,14 @@
#![warn(missing_docs)]
use codec::{DecodeAll, FullCodec, FullEncode};
use core::marker::PhantomData;
use frame_support::storage::generator::{StorageDoubleMap, StorageMap, StorageValue};
use futures::compat::Future01CompatExt;
use jsonrpc_client_transports::RpcError;
use codec::{DecodeAll, FullCodec, FullEncode};
use serde::{de::DeserializeOwned, Serialize};
use frame_support::storage::generator::{
StorageDoubleMap, StorageMap, StorageValue
};
use sp_storage::{StorageData, StorageKey};
use sc_rpc_api::state::StateClient;
use serde::{de::DeserializeOwned, Serialize};
use sp_storage::{StorageData, StorageKey};
/// A typed query on chain state usable from an RPC client.
///
@@ -54,7 +52,7 @@ use sc_rpc_api::state::StateClient;
/// # struct TestRuntime;
/// #
/// # decl_module! {
/// # pub struct Module<T: Config> for enum Call where origin: T::Origin {}
/// # pub struct Module<T: Config> for enum Call where origin: T::Origin {}
/// # }
/// #
/// pub type Loc = (i64, i64, i64);
@@ -98,18 +96,12 @@ pub struct StorageQuery<V> {
impl<V: FullCodec> StorageQuery<V> {
/// Create a storage query for a StorageValue.
pub fn value<St: StorageValue<V>>() -> Self {
Self {
key: StorageKey(St::storage_value_final_key().to_vec()),
_spook: PhantomData,
}
Self { key: StorageKey(St::storage_value_final_key().to_vec()), _spook: PhantomData }
}
/// Create a storage query for a value in a StorageMap.
pub fn map<St: StorageMap<K, V>, K: FullEncode>(key: K) -> Self {
Self {
key: StorageKey(St::storage_map_final_key(key)),
_spook: PhantomData,
}
Self { key: StorageKey(St::storage_map_final_key(key)), _spook: PhantomData }
}
/// Create a storage query for a value in a StorageDoubleMap.
@@ -117,10 +109,7 @@ impl<V: FullCodec> StorageQuery<V> {
key1: K1,
key2: K2,
) -> Self {
Self {
key: StorageKey(St::storage_double_map_final_key(key1, key2)),
_spook: PhantomData,
}
Self { key: StorageKey(St::storage_double_map_final_key(key1, key2)), _spook: PhantomData }
}
/// Send this query over RPC, await the typed result.
+71 -93
View File
@@ -20,28 +20,22 @@
use std::sync::Arc;
use codec::{self, Codec, Decode, Encode};
use sc_client_api::light::{future_header, RemoteBlockchain, Fetcher, RemoteCallRequest};
use futures::future::{ready, TryFutureExt};
use jsonrpc_core::{
futures::future::{self as rpc_future, result, Future},
Error as RpcError, ErrorCode,
futures::future::{self as rpc_future,result, Future},
};
use jsonrpc_derive::rpc;
use futures::future::{ready, TryFutureExt};
use sp_blockchain::{
HeaderBackend,
Error as ClientError
};
use sp_runtime::{
generic::BlockId,
traits,
};
use sp_core::{hexdisplay::HexDisplay, Bytes};
use sc_transaction_pool_api::{TransactionPool, InPoolTransaction};
use sp_block_builder::BlockBuilder;
use sc_client_api::light::{future_header, Fetcher, RemoteBlockchain, RemoteCallRequest};
use sc_rpc_api::DenyUnsafe;
use sc_transaction_pool_api::{InPoolTransaction, TransactionPool};
use sp_block_builder::BlockBuilder;
use sp_blockchain::{Error as ClientError, HeaderBackend};
use sp_core::{hexdisplay::HexDisplay, Bytes};
use sp_runtime::{generic::BlockId, traits};
pub use frame_system_rpc_runtime_api::AccountNonceApi;
pub use self::gen_client::Client as SystemClient;
pub use frame_system_rpc_runtime_api::AccountNonceApi;
/// Future that resolves to account nonce.
pub type FutureResult<T> = Box<dyn Future<Item = T, Error = RpcError> + Send>;
@@ -89,13 +83,8 @@ pub struct FullSystem<P: TransactionPool, C, B> {
impl<P: TransactionPool, C, B> FullSystem<P, C, B> {
/// Create new `FullSystem` given client and transaction pool.
pub fn new(client: Arc<C>, pool: Arc<P>, deny_unsafe: DenyUnsafe,) -> Self {
FullSystem {
client,
pool,
deny_unsafe,
_marker: Default::default(),
}
pub fn new(client: Arc<C>, pool: Arc<P>, deny_unsafe: DenyUnsafe) -> Self {
FullSystem { client, pool, deny_unsafe, _marker: Default::default() }
}
}
@@ -130,35 +119,37 @@ where
Box::new(result(get_nonce()))
}
fn dry_run(&self, extrinsic: Bytes, at: Option<<Block as traits::Block>::Hash>) -> FutureResult<Bytes> {
fn dry_run(
&self,
extrinsic: Bytes,
at: Option<<Block as traits::Block>::Hash>,
) -> FutureResult<Bytes> {
if let Err(err) = self.deny_unsafe.check_if_safe() {
return Box::new(rpc_future::err(err.into()));
return Box::new(rpc_future::err(err.into()))
}
let dry_run = || {
let api = self.client.runtime_api();
let at = BlockId::<Block>::hash(at.unwrap_or_else(||
// If the block hash is not supplied assume the best block.
self.client.info().best_hash
));
self.client.info().best_hash));
let uxt: <Block as traits::Block>::Extrinsic = Decode::decode(&mut &*extrinsic).map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::DecodeError.into()),
message: "Unable to dry run extrinsic.".into(),
data: Some(format!("{:?}", e).into()),
})?;
let result = api.apply_extrinsic(&at, uxt)
let uxt: <Block as traits::Block>::Extrinsic = Decode::decode(&mut &*extrinsic)
.map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::RuntimeError.into()),
code: ErrorCode::ServerError(Error::DecodeError.into()),
message: "Unable to dry run extrinsic.".into(),
data: Some(format!("{:?}", e).into()),
})?;
let result = api.apply_extrinsic(&at, uxt).map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::RuntimeError.into()),
message: "Unable to dry run extrinsic.".into(),
data: Some(format!("{:?}", e).into()),
})?;
Ok(Encode::encode(&result).into())
};
Box::new(result(dry_run()))
}
}
@@ -179,12 +170,7 @@ impl<P: TransactionPool, C, F, Block> LightSystem<P, C, F, Block> {
fetcher: Arc<F>,
pool: Arc<P>,
) -> Self {
LightSystem {
client,
remote_blockchain,
fetcher,
pool,
}
LightSystem { client, remote_blockchain, fetcher, pool }
}
}
@@ -205,21 +191,27 @@ where
let future_best_header = future_header(&*self.remote_blockchain, &*self.fetcher, best_id);
let fetcher = self.fetcher.clone();
let call_data = account.encode();
let future_best_header = future_best_header
.and_then(move |maybe_best_header| ready(
maybe_best_header.ok_or_else(|| { ClientError::UnknownBlock(format!("{}", best_hash)) })
));
let future_nonce = future_best_header.and_then(move |best_header|
fetcher.remote_call(RemoteCallRequest {
block: best_hash,
header: best_header,
method: "AccountNonceApi_account_nonce".into(),
call_data,
retry_count: None,
let future_best_header = future_best_header.and_then(move |maybe_best_header| {
ready(
maybe_best_header
.ok_or_else(|| ClientError::UnknownBlock(format!("{}", best_hash))),
)
});
let future_nonce = future_best_header
.and_then(move |best_header| {
fetcher.remote_call(RemoteCallRequest {
block: best_hash,
header: best_header,
method: "AccountNonceApi_account_nonce".into(),
call_data,
retry_count: None,
})
})
).compat();
let future_nonce = future_nonce.and_then(|nonce| Decode::decode(&mut &nonce[..])
.map_err(|e| ClientError::CallResultDecode("Cannot decode account nonce", e)));
.compat();
let future_nonce = future_nonce.and_then(|nonce| {
Decode::decode(&mut &nonce[..])
.map_err(|e| ClientError::CallResultDecode("Cannot decode account nonce", e))
});
let future_nonce = future_nonce.map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::RuntimeError.into()),
message: "Unable to query nonce.".into(),
@@ -232,7 +224,11 @@ where
Box::new(future_nonce)
}
fn dry_run(&self, _extrinsic: Bytes, _at: Option<<Block as traits::Block>::Hash>) -> FutureResult<Bytes> {
fn dry_run(
&self,
_extrinsic: Bytes,
_at: Option<<Block as traits::Block>::Hash>,
) -> FutureResult<Bytes> {
Box::new(result(Err(RpcError {
code: ErrorCode::MethodNotFound,
message: "Unable to dry run extrinsic.".into(),
@@ -243,11 +239,8 @@ where
/// Adjust account nonce from state, so that tx with the nonce will be
/// placed after all ready txpool transactions.
fn adjust_nonce<P, AccountId, Index>(
pool: &P,
account: AccountId,
nonce: Index,
) -> Index where
fn adjust_nonce<P, AccountId, Index>(pool: &P, account: AccountId, nonce: Index) -> Index
where
P: TransactionPool,
AccountId: Clone + std::fmt::Display + Encode,
Index: Clone + std::fmt::Display + Encode + traits::AtLeast32Bit + 'static,
@@ -285,9 +278,12 @@ mod tests {
use super::*;
use futures::executor::block_on;
use substrate_test_runtime_client::{runtime::Transfer, AccountKeyring};
use sc_transaction_pool::BasicPool;
use sp_runtime::{ApplyExtrinsicResult, transaction_validity::{TransactionValidityError, InvalidTransaction}};
use sp_runtime::{
transaction_validity::{InvalidTransaction, TransactionValidityError},
ApplyExtrinsicResult,
};
use substrate_test_runtime_client::{runtime::Transfer, AccountKeyring};
#[test]
fn should_return_next_nonce_for_some_account() {
@@ -296,13 +292,8 @@ mod tests {
// given
let client = Arc::new(substrate_test_runtime_client::new());
let spawner = sp_core::testing::TaskExecutor::new();
let pool = BasicPool::new_full(
Default::default(),
true.into(),
None,
spawner,
client.clone(),
);
let pool =
BasicPool::new_full(Default::default(), true.into(), None, spawner, client.clone());
let source = sp_runtime::transaction_validity::TransactionSource::External;
let new_transaction = |nonce: u64| {
@@ -336,13 +327,8 @@ mod tests {
// given
let client = Arc::new(substrate_test_runtime_client::new());
let spawner = sp_core::testing::TaskExecutor::new();
let pool = BasicPool::new_full(
Default::default(),
true.into(),
None,
spawner,
client.clone(),
);
let pool =
BasicPool::new_full(Default::default(), true.into(), None, spawner, client.clone());
let accounts = FullSystem::new(client, pool, DenyUnsafe::Yes);
@@ -360,13 +346,8 @@ mod tests {
// given
let client = Arc::new(substrate_test_runtime_client::new());
let spawner = sp_core::testing::TaskExecutor::new();
let pool = BasicPool::new_full(
Default::default(),
true.into(),
None,
spawner,
client.clone(),
);
let pool =
BasicPool::new_full(Default::default(), true.into(), None, spawner, client.clone());
let accounts = FullSystem::new(client, pool, DenyUnsafe::No);
@@ -375,7 +356,8 @@ mod tests {
to: AccountKeyring::Bob.into(),
amount: 5,
nonce: 0,
}.into_signed_tx();
}
.into_signed_tx();
// when
let res = accounts.dry_run(tx.encode().into(), None);
@@ -393,13 +375,8 @@ mod tests {
// given
let client = Arc::new(substrate_test_runtime_client::new());
let spawner = sp_core::testing::TaskExecutor::new();
let pool = BasicPool::new_full(
Default::default(),
true.into(),
None,
spawner,
client.clone(),
);
let pool =
BasicPool::new_full(Default::default(), true.into(), None, spawner, client.clone());
let accounts = FullSystem::new(client, pool, DenyUnsafe::No);
@@ -408,7 +385,8 @@ mod tests {
to: AccountKeyring::Bob.into(),
amount: 5,
nonce: 100,
}.into_signed_tx();
}
.into_signed_tx();
// when
let res = accounts.dry_run(tx.encode().into(), None);
@@ -18,24 +18,23 @@
//! `Structopt`-ready structs for `try-runtime`.
use parity_scale_codec::{Decode, Encode};
use std::{fmt::Debug, path::PathBuf, str::FromStr, sync::Arc};
use sc_service::Configuration;
use remote_externalities::{rpc_api, Builder, Mode, OfflineConfig, OnlineConfig, SnapshotConfig};
use sc_chain_spec::ChainSpec;
use sc_cli::{CliConfiguration, ExecutionStrategy, WasmExecutionMethod};
use sc_executor::NativeExecutor;
use sc_service::NativeExecutionDispatch;
use sc_chain_spec::ChainSpec;
use sp_state_machine::StateMachine;
use sp_runtime::traits::{Block as BlockT, NumberFor, Header as HeaderT};
use sc_service::{Configuration, NativeExecutionDispatch};
use sp_core::{
offchain::{
OffchainWorkerExt, OffchainDbExt, TransactionPoolExt,
testing::{TestOffchainExt, TestTransactionPoolExt},
},
storage::{StorageData, StorageKey, well_known_keys},
hashing::twox_128,
offchain::{
testing::{TestOffchainExt, TestTransactionPoolExt},
OffchainDbExt, OffchainWorkerExt, TransactionPoolExt,
},
storage::{well_known_keys, StorageData, StorageKey},
};
use sp_keystore::{KeystoreExt, testing::KeyStore};
use remote_externalities::{Builder, Mode, SnapshotConfig, OfflineConfig, OnlineConfig, rpc_api};
use sp_keystore::{testing::KeyStore, KeystoreExt};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
use sp_state_machine::StateMachine;
use std::{fmt::Debug, path::PathBuf, str::FromStr, sync::Arc};
mod parse;
@@ -170,7 +169,7 @@ pub enum State {
/// The modules to scrape. If empty, entire chain state will be scraped.
#[structopt(short, long, require_delimiter = true)]
modules: Option<Vec<String>>,
}
},
}
async fn on_runtime_upgrade<Block, ExecDispatch>(
@@ -192,36 +191,31 @@ where
let mut changes = Default::default();
let max_runtime_instances = config.max_runtime_instances;
let executor = NativeExecutor::<ExecDispatch>::new(
wasm_method.into(),
heap_pages,
max_runtime_instances,
);
let executor =
NativeExecutor::<ExecDispatch>::new(wasm_method.into(), heap_pages, max_runtime_instances);
let ext = {
let builder = match command.state {
State::Snap { snapshot_path } => {
State::Snap { snapshot_path } =>
Builder::<Block>::new().mode(Mode::Offline(OfflineConfig {
state_snapshot: SnapshotConfig::new(snapshot_path),
}))
},
State::Live {
snapshot_path,
modules
} => Builder::<Block>::new().mode(Mode::Online(OnlineConfig {
transport: shared.url.to_owned().into(),
state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new),
modules: modules.to_owned().unwrap_or_default(),
at: Some(shared.block_at::<Block>()?),
..Default::default()
})),
})),
State::Live { snapshot_path, modules } =>
Builder::<Block>::new().mode(Mode::Online(OnlineConfig {
transport: shared.url.to_owned().into(),
state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new),
modules: modules.to_owned().unwrap_or_default(),
at: Some(shared.block_at::<Block>()?),
..Default::default()
})),
};
let (code_key, code) = extract_code(config.chain_spec)?;
builder
.inject_key_value(&[(code_key, code)])
.inject_hashed_key(&[twox_128(b"System"), twox_128(b"LastRuntimeUpgrade")].concat())
.build().await?
.build()
.await?
};
let encoded_result = StateMachine::<_, _, NumberFor<Block>, _>::new(
@@ -232,8 +226,7 @@ where
"TryRuntime_on_runtime_upgrade",
&[],
ext.extensions,
&sp_state_machine::backend::BackendRuntimeCode::new(&ext.backend)
.runtime_code()?,
&sp_state_machine::backend::BackendRuntimeCode::new(&ext.backend).runtime_code()?,
sp_core::testing::TaskExecutor::new(),
)
.execute(execution.into())
@@ -271,35 +264,28 @@ where
let mut changes = Default::default();
let max_runtime_instances = config.max_runtime_instances;
let executor = NativeExecutor::<ExecDispatch>::new(
wasm_method.into(),
heap_pages,
max_runtime_instances,
);
let executor =
NativeExecutor::<ExecDispatch>::new(wasm_method.into(), heap_pages, max_runtime_instances);
let mode = match command.state {
State::Live {
snapshot_path,
modules
} => {
let at = shared.block_at::<Block>()?;
let online_config = OnlineConfig {
transport: shared.url.to_owned().into(),
state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new),
modules: modules.to_owned().unwrap_or_default(),
at: Some(at),
..Default::default()
};
State::Live { snapshot_path, modules } => {
let at = shared.block_at::<Block>()?;
let online_config = OnlineConfig {
transport: shared.url.to_owned().into(),
state_snapshot: snapshot_path.as_ref().map(SnapshotConfig::new),
modules: modules.to_owned().unwrap_or_default(),
at: Some(at),
..Default::default()
};
Mode::Online(online_config)
},
State::Snap { snapshot_path } => {
let mode = Mode::Offline(OfflineConfig {
state_snapshot: SnapshotConfig::new(snapshot_path),
});
Mode::Online(online_config)
},
State::Snap { snapshot_path } => {
let mode =
Mode::Offline(OfflineConfig { state_snapshot: SnapshotConfig::new(snapshot_path) });
mode
}
mode
},
};
let builder = Builder::<Block>::new()
.mode(mode)
@@ -308,10 +294,7 @@ where
let (code_key, code) = extract_code(config.chain_spec)?;
builder.inject_key_value(&[(code_key, code)]).build().await?
} else {
builder
.inject_hashed_key(well_known_keys::CODE)
.build()
.await?
builder.inject_hashed_key(well_known_keys::CODE).build().await?
};
let (offchain, _offchain_state) = TestOffchainExt::new();
@@ -332,8 +315,7 @@ where
"OffchainWorkerApi_offchain_worker",
header.encode().as_ref(),
ext.extensions,
&sp_state_machine::backend::BackendRuntimeCode::new(&ext.backend)
.runtime_code()?,
&sp_state_machine::backend::BackendRuntimeCode::new(&ext.backend).runtime_code()?,
sp_core::testing::TaskExecutor::new(),
)
.execute(execution.into())
@@ -363,20 +345,16 @@ where
let mut changes = Default::default();
let max_runtime_instances = config.max_runtime_instances;
let executor = NativeExecutor::<ExecDispatch>::new(
wasm_method.into(),
heap_pages,
max_runtime_instances,
);
let executor =
NativeExecutor::<ExecDispatch>::new(wasm_method.into(), heap_pages, max_runtime_instances);
let block_hash = shared.block_at::<Block>()?;
let block: Block = rpc_api::get_block::<Block, _>(shared.url.clone(), block_hash).await?;
let mode = match command.state {
State::Snap { snapshot_path } => {
let mode = Mode::Offline(OfflineConfig {
state_snapshot: SnapshotConfig::new(snapshot_path),
});
let mode =
Mode::Offline(OfflineConfig { state_snapshot: SnapshotConfig::new(snapshot_path) });
mode
},
@@ -392,7 +370,7 @@ where
});
mode
}
},
};
let ext = {
@@ -403,10 +381,7 @@ where
let (code_key, code) = extract_code(config.chain_spec)?;
builder.inject_key_value(&[(code_key, code)]).build().await?
} else {
builder
.inject_hashed_key(well_known_keys::CODE)
.build()
.await?
builder.inject_hashed_key(well_known_keys::CODE).build().await?
};
// register externality extensions in order to provide host interface for OCW to the
@@ -459,15 +434,14 @@ impl TryRuntimeCmd {
ExecDispatch: NativeExecutionDispatch + 'static,
{
match &self.command {
Command::OnRuntimeUpgrade(ref cmd) => {
on_runtime_upgrade::<Block, ExecDispatch>(self.shared.clone(), cmd.clone(), config).await
}
Command::OffchainWorker(cmd) => {
offchain_worker::<Block, ExecDispatch>(self.shared.clone(), cmd.clone(), config).await
}
Command::ExecuteBlock(cmd) => {
execute_block::<Block, ExecDispatch>(self.shared.clone(), cmd.clone(), config).await
}
Command::OnRuntimeUpgrade(ref cmd) =>
on_runtime_upgrade::<Block, ExecDispatch>(self.shared.clone(), cmd.clone(), config)
.await,
Command::OffchainWorker(cmd) =>
offchain_worker::<Block, ExecDispatch>(self.shared.clone(), cmd.clone(), config)
.await,
Command::ExecuteBlock(cmd) =>
execute_block::<Block, ExecDispatch>(self.shared.clone(), cmd.clone(), config).await,
}
}
}
@@ -18,11 +18,8 @@
//! Utils for parsing user input
pub(crate) fn hash(block_hash: &str) -> Result<String, String> {
let (block_hash, offset) = if block_hash.starts_with("0x") {
(&block_hash[2..], 2)
} else {
(block_hash, 0)
};
let (block_hash, offset) =
if block_hash.starts_with("0x") { (&block_hash[2..], 2) } else { (block_hash, 0) };
if let Some(pos) = block_hash.chars().position(|c| !c.is_ascii_hexdigit()) {
Err(format!(
+33 -22
View File
@@ -15,33 +15,34 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use futures_util::{FutureExt, future::Future};
use futures_util::{future::Future, FutureExt};
pub use prometheus::{
self,
Registry, Error as PrometheusError, Opts,
Histogram, HistogramOpts, HistogramVec,
exponential_buckets,
core::{
GenericGauge as Gauge, GenericCounter as Counter,
GenericGaugeVec as GaugeVec, GenericCounterVec as CounterVec,
AtomicF64 as F64, AtomicI64 as I64, AtomicU64 as U64,
}
AtomicF64 as F64, AtomicI64 as I64, AtomicU64 as U64, GenericCounter as Counter,
GenericCounterVec as CounterVec, GenericGauge as Gauge, GenericGaugeVec as GaugeVec,
},
exponential_buckets, Error as PrometheusError, Histogram, HistogramOpts, HistogramVec, Opts,
Registry,
};
use prometheus::{Encoder, TextEncoder, core::Collector};
use prometheus::{core::Collector, Encoder, TextEncoder};
use std::net::SocketAddr;
#[cfg(not(target_os = "unknown"))]
mod networking;
mod sourced;
pub use sourced::{SourcedCounter, SourcedGauge, MetricSource, SourcedMetric};
pub use sourced::{MetricSource, SourcedCounter, SourcedGauge, SourcedMetric};
#[cfg(target_os = "unknown")]
pub use unknown_os::init_prometheus;
#[cfg(not(target_os = "unknown"))]
pub use known_os::init_prometheus;
#[cfg(target_os = "unknown")]
pub use unknown_os::init_prometheus;
pub fn register<T: Clone + Collector + 'static>(metric: T, registry: &Registry) -> Result<T, PrometheusError> {
pub fn register<T: Clone + Collector + 'static>(
metric: T,
registry: &Registry,
) -> Result<T, PrometheusError> {
registry.register(Box::new(metric.clone()))?;
Ok(metric)
}
@@ -61,8 +62,11 @@ mod unknown_os {
#[cfg(not(target_os = "unknown"))]
mod known_os {
use super::*;
use hyper::http::StatusCode;
use hyper::{Server, Body, Request, Response, service::{service_fn, make_service_fn}};
use hyper::{
http::StatusCode,
service::{make_service_fn, service_fn},
Body, Request, Response, Server,
};
#[derive(Debug, derive_more::Display, derive_more::From)]
pub enum Error {
@@ -73,7 +77,7 @@ mod known_os {
/// i/o error.
Io(std::io::Error),
#[display(fmt = "Prometheus port {} already in use.", _0)]
PortInUse(SocketAddr)
PortInUse(SocketAddr),
}
impl std::error::Error for Error {
@@ -82,28 +86,32 @@ mod known_os {
Error::Hyper(error) => Some(error),
Error::Http(error) => Some(error),
Error::Io(error) => Some(error),
Error::PortInUse(_) => None
Error::PortInUse(_) => None,
}
}
}
async fn request_metrics(req: Request<Body>, registry: Registry) -> Result<Response<Body>, Error> {
async fn request_metrics(
req: Request<Body>,
registry: Registry,
) -> Result<Response<Body>, Error> {
if req.uri().path() == "/metrics" {
let metric_families = registry.gather();
let mut buffer = vec![];
let encoder = TextEncoder::new();
encoder.encode(&metric_families, &mut buffer).unwrap();
Response::builder().status(StatusCode::OK)
Response::builder()
.status(StatusCode::OK)
.header("Content-Type", encoder.format_type())
.body(Body::from(buffer))
.map_err(Error::Http)
} else {
Response::builder().status(StatusCode::NOT_FOUND)
Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("Not found."))
.map_err(Error::Http)
}
}
#[derive(Clone)]
@@ -121,7 +129,10 @@ mod known_os {
/// Initializes the metrics context, and starts an HTTP server
/// to serve metrics.
pub async fn init_prometheus(prometheus_addr: SocketAddr, registry: Registry) -> Result<(), Error>{
pub async fn init_prometheus(
prometheus_addr: SocketAddr,
registry: Registry,
) -> Result<(), Error> {
use networking::Incoming;
let listener = async_std::net::TcpListener::bind(&prometheus_addr)
.await
+15 -13
View File
@@ -16,8 +16,11 @@
// limitations under the License.
use async_std::pin::Pin;
use std::task::{Poll, Context};
use futures_util::{stream::Stream, io::{AsyncRead, AsyncWrite}};
use futures_util::{
io::{AsyncRead, AsyncWrite},
stream::Stream,
};
use std::task::{Context, Poll};
pub struct Incoming<'a>(pub async_std::net::Incoming<'a>);
@@ -25,7 +28,10 @@ impl hyper::server::accept::Accept for Incoming<'_> {
type Conn = TcpStream;
type Error = async_std::io::Error;
fn poll_accept(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
fn poll_accept(
self: Pin<&mut Self>,
cx: &mut Context,
) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
Pin::new(&mut Pin::into_inner(self).0)
.poll_next(cx)
.map(|opt| opt.map(|res| res.map(TcpStream)))
@@ -38,10 +44,9 @@ impl tokio::io::AsyncRead for TcpStream {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context,
buf: &mut [u8]
buf: &mut [u8],
) -> Poll<Result<usize, std::io::Error>> {
Pin::new(&mut Pin::into_inner(self).0)
.poll_read(cx, buf)
Pin::new(&mut Pin::into_inner(self).0).poll_read(cx, buf)
}
}
@@ -49,19 +54,16 @@ impl tokio::io::AsyncWrite for TcpStream {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context,
buf: &[u8]
buf: &[u8],
) -> Poll<Result<usize, std::io::Error>> {
Pin::new(&mut Pin::into_inner(self).0)
.poll_write(cx, buf)
Pin::new(&mut Pin::into_inner(self).0).poll_write(cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), std::io::Error>> {
Pin::new(&mut Pin::into_inner(self).0)
.poll_flush(cx)
Pin::new(&mut Pin::into_inner(self).0).poll_flush(cx)
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), std::io::Error>> {
Pin::new(&mut Pin::into_inner(self).0)
.poll_close(cx)
Pin::new(&mut Pin::into_inner(self).0).poll_close(cx)
}
}
+28 -17
View File
@@ -17,8 +17,10 @@
//! Metrics that are collected from existing sources.
use prometheus::core::{Collector, Desc, Describer, Number, Opts};
use prometheus::proto;
use prometheus::{
core::{Collector, Desc, Describer, Number, Opts},
proto,
};
use std::{cmp::Ordering, marker::PhantomData};
/// A counter whose values are obtained from an existing source.
@@ -80,15 +82,15 @@ impl<T: SourcedType, S: MetricSource> Collector for SourcedMetric<T, S> {
let mut c = proto::Counter::default();
c.set_value(value.into_f64());
m.set_counter(c);
}
},
proto::MetricType::GAUGE => {
let mut g = proto::Gauge::default();
g.set_value(value.into_f64());
m.set_gauge(g);
}
},
t => {
log::error!("Unsupported sourced metric type: {:?}", t);
}
},
}
debug_assert_eq!(self.desc.variable_labels.len(), label_values.len());
@@ -97,18 +99,23 @@ impl<T: SourcedType, S: MetricSource> Collector for SourcedMetric<T, S> {
log::warn!("Missing label values for sourced metric {}", self.desc.fq_name),
Ordering::Less =>
log::warn!("Too many label values for sourced metric {}", self.desc.fq_name),
Ordering::Equal => {}
Ordering::Equal => {},
}
m.set_label(self.desc.variable_labels.iter().zip(label_values)
.map(|(l_name, l_value)| {
let mut l = proto::LabelPair::default();
l.set_name(l_name.to_string());
l.set_value(l_value.to_string());
l
})
.chain(self.desc.const_label_pairs.iter().cloned())
.collect::<Vec<_>>());
m.set_label(
self.desc
.variable_labels
.iter()
.zip(label_values)
.map(|(l_name, l_value)| {
let mut l = proto::LabelPair::default();
l.set_name(l_name.to_string());
l.set_value(l_value.to_string());
l
})
.chain(self.desc.const_label_pairs.iter().cloned())
.collect::<Vec<_>>(),
);
counters.push(m);
});
@@ -130,11 +137,15 @@ pub trait SourcedType: private::Sealed + Sync + Send {
}
impl SourcedType for Counter {
fn proto() -> proto::MetricType { proto::MetricType::COUNTER }
fn proto() -> proto::MetricType {
proto::MetricType::COUNTER
}
}
impl SourcedType for Gauge {
fn proto() -> proto::MetricType { proto::MetricType::GAUGE }
fn proto() -> proto::MetricType {
proto::MetricType::GAUGE
}
}
mod private {
+18 -22
View File
@@ -15,7 +15,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{env, path::{PathBuf, Path}, process};
use std::{
env,
path::{Path, PathBuf},
process,
};
/// Returns the manifest dir from the `CARGO_MANIFEST_DIR` env.
fn get_manifest_dir() -> PathBuf {
@@ -50,10 +54,7 @@ impl WasmBuilderSelectProject {
/// Use the given `path` as project for building the WASM binary.
///
/// Returns an error if the given `path` does not points to a `Cargo.toml`.
pub fn with_project(
self,
path: impl Into<PathBuf>,
) -> Result<WasmBuilder, &'static str> {
pub fn with_project(self, path: impl Into<PathBuf>) -> Result<WasmBuilder, &'static str> {
let path = path.into();
if path.ends_with("Cargo.toml") && path.exists() {
@@ -97,9 +98,7 @@ pub struct WasmBuilder {
impl WasmBuilder {
/// Create a new instance of the builder.
pub fn new() -> WasmBuilderSelectProject {
WasmBuilderSelectProject {
_ignore: (),
}
WasmBuilderSelectProject { _ignore: () }
}
/// Enable exporting `__heap_base` as global variable in the WASM binary.
@@ -147,9 +146,8 @@ impl WasmBuilder {
/// Build the WASM binary.
pub fn build(self) {
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` is set by cargo!"));
let file_path = out_dir.join(
self.file_name.clone().unwrap_or_else(|| "wasm_binary.rs".into()),
);
let file_path =
out_dir.join(self.file_name.clone().unwrap_or_else(|| "wasm_binary.rs".into()));
if check_skip_build() {
// If we skip the build, we still want to make sure to be called when an env variable
@@ -158,7 +156,7 @@ impl WasmBuilder {
provide_dummy_wasm_binary_if_not_exist(&file_path);
return;
return
}
build_project(
@@ -179,13 +177,17 @@ impl WasmBuilder {
fn generate_crate_skip_build_env_name() -> String {
format!(
"SKIP_{}_WASM_BUILD",
env::var("CARGO_PKG_NAME").expect("Package name is set").to_uppercase().replace('-', "_"),
env::var("CARGO_PKG_NAME")
.expect("Package name is set")
.to_uppercase()
.replace('-', "_"),
)
}
/// Checks if the build of the WASM binary should be skipped.
fn check_skip_build() -> bool {
env::var(crate::SKIP_BUILD_ENV).is_ok() || env::var(generate_crate_skip_build_env_name()).is_ok()
env::var(crate::SKIP_BUILD_ENV).is_ok() ||
env::var(generate_crate_skip_build_env_name()).is_ok()
}
/// Provide a dummy WASM binary if there doesn't exist one.
@@ -243,15 +245,9 @@ fn build_project(
);
let (wasm_binary, wasm_binary_bloaty) = if let Some(wasm_binary) = wasm_binary {
(
wasm_binary.wasm_binary_path_escaped(),
bloaty.wasm_binary_bloaty_path_escaped(),
)
(wasm_binary.wasm_binary_path_escaped(), bloaty.wasm_binary_bloaty_path_escaped())
} else {
(
bloaty.wasm_binary_bloaty_path_escaped(),
bloaty.wasm_binary_bloaty_path_escaped(),
)
(bloaty.wasm_binary_bloaty_path_escaped(), bloaty.wasm_binary_bloaty_path_escaped())
};
crate::write_file_if_changed(
+13 -13
View File
@@ -96,7 +96,12 @@
//! as well. For example if installing the rust nightly from 20.02.2020 using `rustup install nightly-2020-02-20`,
//! the wasm target needs to be installed as well `rustup target add wasm32-unknown-unknown --toolchain nightly-2020-02-20`.
use std::{env, fs, path::{PathBuf, Path}, process::Command, io::BufRead};
use std::{
env, fs,
io::BufRead,
path::{Path, PathBuf},
process::Command,
};
mod builder;
mod prerequisites;
@@ -144,18 +149,16 @@ fn copy_file_if_changed(src: PathBuf, dst: PathBuf) {
let dst_file = fs::read_to_string(&dst).ok();
if src_file != dst_file {
fs::copy(&src, &dst)
.unwrap_or_else(
|_| panic!("Copying `{}` to `{}` can not fail; qed", src.display(), dst.display())
);
fs::copy(&src, &dst).unwrap_or_else(|_| {
panic!("Copying `{}` to `{}` can not fail; qed", src.display(), dst.display())
});
}
}
/// Get a cargo command that compiles with nightly
fn get_nightly_cargo() -> CargoCommand {
let env_cargo = CargoCommand::new(
&env::var("CARGO").expect("`CARGO` env variable is always set by cargo"),
);
let env_cargo =
CargoCommand::new(&env::var("CARGO").expect("`CARGO` env variable is always set by cargo"));
let default_cargo = CargoCommand::new("cargo");
let rustup_run_nightly = CargoCommand::new_with_args("rustup", &["run", "nightly", "cargo"]);
let wasm_toolchain = env::var(WASM_BUILD_TOOLCHAIN).ok();
@@ -197,7 +200,7 @@ fn get_rustup_nightly(selected: Option<String>) -> Option<CargoCommand> {
}
latest_nightly?.trim_end_matches(&host).into()
}
},
};
Some(CargoCommand::new_with_args("rustup", &["run", &version, "cargo"]))
@@ -253,10 +256,7 @@ struct CargoCommandVersioned {
impl CargoCommandVersioned {
fn new(command: CargoCommand, version: String) -> Self {
Self {
command,
version,
}
Self { command, version }
}
/// Returns the `rustc` version.
@@ -15,12 +15,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::{CargoCommandVersioned, CargoCommand, write_file_if_changed};
use crate::{write_file_if_changed, CargoCommand, CargoCommandVersioned};
use std::{fs, path::Path};
use tempfile::tempdir;
use ansi_term::Color;
use tempfile::tempdir;
/// Print an error message.
fn print_error_message(message: &str) -> String {
@@ -95,7 +95,7 @@ fn create_check_toolchain_project(project_dir: &Path) {
rustc_version.unwrap_or_else(|| "unknown rustc version".into()),
);
}
"#
"#,
);
// Just prints the `RURSTC_VERSION` environment variable that is being created by the
// `build.rs` script.
@@ -105,7 +105,7 @@ fn create_check_toolchain_project(project_dir: &Path) {
fn main() {
println!("{}", env!("RUSTC_VERSION"));
}
"#
"#,
);
}
@@ -120,7 +120,12 @@ fn check_wasm_toolchain_installed(
let manifest_path = temp.path().join("Cargo.toml").display().to_string();
let mut build_cmd = cargo_command.command();
build_cmd.args(&["build", "--target=wasm32-unknown-unknown", "--manifest-path", &manifest_path]);
build_cmd.args(&[
"build",
"--target=wasm32-unknown-unknown",
"--manifest-path",
&manifest_path,
]);
if super::color_output_enabled() {
build_cmd.arg("--color=always");
@@ -133,33 +138,27 @@ fn check_wasm_toolchain_installed(
build_cmd.env_remove("CARGO_TARGET_DIR");
run_cmd.env_remove("CARGO_TARGET_DIR");
build_cmd
.output()
.map_err(|_| err_msg.clone())
.and_then(|s|
if s.status.success() {
let version = run_cmd.output().ok().and_then(|o| String::from_utf8(o.stdout).ok());
Ok(CargoCommandVersioned::new(
cargo_command,
version.unwrap_or_else(|| "unknown rustc version".into()),
))
} else {
match String::from_utf8(s.stderr) {
Ok(ref err) if err.contains("linker `rust-lld` not found") => {
Err(print_error_message("`rust-lld` not found, please install it!"))
},
Ok(ref err) => Err(
format!(
"{}\n\n{}\n{}\n{}{}\n",
err_msg,
Color::Yellow.bold().paint("Further error information:"),
Color::Yellow.bold().paint("-".repeat(60)),
err,
Color::Yellow.bold().paint("-".repeat(60)),
)
),
Err(_) => Err(err_msg),
}
build_cmd.output().map_err(|_| err_msg.clone()).and_then(|s| {
if s.status.success() {
let version = run_cmd.output().ok().and_then(|o| String::from_utf8(o.stdout).ok());
Ok(CargoCommandVersioned::new(
cargo_command,
version.unwrap_or_else(|| "unknown rustc version".into()),
))
} else {
match String::from_utf8(s.stderr) {
Ok(ref err) if err.contains("linker `rust-lld` not found") =>
Err(print_error_message("`rust-lld` not found, please install it!")),
Ok(ref err) => Err(format!(
"{}\n\n{}\n{}\n{}{}\n",
err_msg,
Color::Yellow.bold().paint("Further error information:"),
Color::Yellow.bold().paint("-".repeat(60)),
err,
Color::Yellow.bold().paint("-".repeat(60)),
)),
Err(_) => Err(err_msg),
}
)
}
})
}
@@ -18,15 +18,20 @@
use crate::{write_file_if_changed, CargoCommandVersioned};
use std::{
fs, path::{Path, PathBuf}, borrow::ToOwned, process, env, collections::HashSet,
hash::{Hash, Hasher}, ops::Deref,
borrow::ToOwned,
collections::HashSet,
env, fs,
hash::{Hash, Hasher},
ops::Deref,
path::{Path, PathBuf},
process,
};
use toml::value::Table;
use build_helper::rerun_if_changed;
use cargo_metadata::{MetadataCommand, Metadata};
use cargo_metadata::{Metadata, MetadataCommand};
use walkdir::WalkDir;
@@ -114,19 +119,16 @@ pub(crate) fn create_and_compile(
);
build_project(&project, default_rustflags, cargo_cmd);
let (wasm_binary, wasm_binary_compressed, bloaty) = compact_wasm_file(
&project,
project_cargo_toml,
wasm_binary_name,
);
let (wasm_binary, wasm_binary_compressed, bloaty) =
compact_wasm_file(&project, project_cargo_toml, wasm_binary_name);
wasm_binary.as_ref().map(|wasm_binary|
copy_wasm_to_target_directory(project_cargo_toml, wasm_binary)
);
wasm_binary
.as_ref()
.map(|wasm_binary| copy_wasm_to_target_directory(project_cargo_toml, wasm_binary));
wasm_binary_compressed.as_ref().map(|wasm_binary_compressed|
wasm_binary_compressed.as_ref().map(|wasm_binary_compressed| {
copy_wasm_to_target_directory(project_cargo_toml, wasm_binary_compressed)
);
});
generate_rerun_if_changed_instructions(project_cargo_toml, &project, &wasm_workspace);
@@ -144,17 +146,17 @@ fn find_cargo_lock(cargo_manifest: &Path) -> Option<PathBuf> {
}
if !path.pop() {
return None;
return None
}
}
}
if let Some(path) = find_impl(build_helper::out_dir()) {
return Some(path);
return Some(path)
}
if let Some(path) = find_impl(cargo_manifest.to_path_buf()) {
return Some(path);
return Some(path)
}
build_helper::warning!(
@@ -169,15 +171,20 @@ fn find_cargo_lock(cargo_manifest: &Path) -> Option<PathBuf> {
/// Extract the crate name from the given `Cargo.toml`.
fn get_crate_name(cargo_manifest: &Path) -> String {
let cargo_toml: Table = toml::from_str(
&fs::read_to_string(cargo_manifest).expect("File exists as checked before; qed")
).expect("Cargo manifest is a valid toml file; qed");
&fs::read_to_string(cargo_manifest).expect("File exists as checked before; qed"),
)
.expect("Cargo manifest is a valid toml file; qed");
let package = cargo_toml
.get("package")
.and_then(|t| t.as_table())
.expect("`package` key exists in valid `Cargo.toml`; qed");
package.get("name").and_then(|p| p.as_str()).map(ToOwned::to_owned).expect("Package name exists; qed")
package
.get("name")
.and_then(|p| p.as_str())
.map(ToOwned::to_owned)
.expect("Package name exists; qed")
}
/// Returns the name for the wasm binary.
@@ -192,9 +199,10 @@ fn get_wasm_workspace_root() -> PathBuf {
loop {
match out_dir.parent() {
Some(parent) if out_dir.ends_with("build") => return parent.to_path_buf(),
_ => if !out_dir.pop() {
break;
}
_ =>
if !out_dir.pop() {
break
},
}
}
@@ -210,10 +218,10 @@ fn create_project_cargo_toml(
enabled_features: impl Iterator<Item = String>,
) {
let mut workspace_toml: Table = toml::from_str(
&fs::read_to_string(
workspace_root_path.join("Cargo.toml"),
).expect("Workspace root `Cargo.toml` exists; qed")
).expect("Workspace root `Cargo.toml` is a valid toml file; qed");
&fs::read_to_string(workspace_root_path.join("Cargo.toml"))
.expect("Workspace root `Cargo.toml` exists; qed"),
)
.expect("Workspace root `Cargo.toml` is a valid toml file; qed");
let mut wasm_workspace_toml = Table::new();
@@ -232,25 +240,25 @@ fn create_project_cargo_toml(
wasm_workspace_toml.insert("profile".into(), profile.into());
// Add patch section from the project root `Cargo.toml`
while let Some(mut patch) = workspace_toml.remove("patch")
.and_then(|p| p.try_into::<Table>().ok()) {
while let Some(mut patch) =
workspace_toml.remove("patch").and_then(|p| p.try_into::<Table>().ok())
{
// Iterate over all patches and make the patch path absolute from the workspace root path.
patch.iter_mut()
.filter_map(|p|
patch
.iter_mut()
.filter_map(|p| {
p.1.as_table_mut().map(|t| t.iter_mut().filter_map(|t| t.1.as_table_mut()))
)
})
.flatten()
.for_each(|p|
p.iter_mut()
.filter(|(k, _)| k == &"path")
.for_each(|(_, v)| {
if let Some(path) = v.as_str().map(PathBuf::from) {
if path.is_relative() {
*v = workspace_root_path.join(path).display().to_string().into();
}
.for_each(|p| {
p.iter_mut().filter(|(k, _)| k == &"path").for_each(|(_, v)| {
if let Some(path) = v.as_str().map(PathBuf::from) {
if path.is_relative() {
*v = workspace_root_path.join(path).display().to_string().into();
}
})
);
}
})
});
wasm_workspace_toml.insert("patch".into(), patch.into());
}
@@ -296,7 +304,8 @@ fn find_package_by_manifest_path<'a>(
manifest_path: &Path,
crate_metadata: &'a cargo_metadata::Metadata,
) -> &'a cargo_metadata::Package {
crate_metadata.packages
crate_metadata
.packages
.iter()
.find(|p| p.manifest_path == manifest_path)
.expect("Wasm project exists in its own metadata; qed")
@@ -309,18 +318,19 @@ fn project_enabled_features(
) -> Vec<String> {
let package = find_package_by_manifest_path(cargo_manifest, crate_metadata);
let mut enabled_features = package.features.keys()
let mut enabled_features = package
.features
.keys()
.filter(|f| {
let mut feature_env = f.replace("-", "_");
feature_env.make_ascii_uppercase();
// We don't want to enable the `std`/`default` feature for the wasm build and
// we need to check if the feature is enabled by checking the env variable.
*f != "std"
&& *f != "default"
&& env::var(format!("CARGO_FEATURE_{}", feature_env))
.map(|v| v == "1")
.unwrap_or_default()
*f != "std" &&
*f != "default" && env::var(format!("CARGO_FEATURE_{}", feature_env))
.map(|v| v == "1")
.unwrap_or_default()
})
.cloned()
.collect::<Vec<_>>();
@@ -418,7 +428,8 @@ fn build_project(project: &Path, default_rustflags: &str, cargo_cmd: CargoComman
env::var(crate::WASM_BUILD_RUSTFLAGS_ENV).unwrap_or_default(),
);
build_cmd.args(&["rustc", "--target=wasm32-unknown-unknown"])
build_cmd
.args(&["rustc", "--target=wasm32-unknown-unknown"])
.arg(format!("--manifest-path={}", manifest_path.display()))
.env("RUSTFLAGS", rustflags)
// Unset the `CARGO_TARGET_DIR` to prevent a cargo deadlock (cargo locks a target dir exclusive).
@@ -456,17 +467,16 @@ fn compact_wasm_file(
let is_release_build = is_release_build();
let target = if is_release_build { "release" } else { "debug" };
let default_wasm_binary_name = get_wasm_binary_name(cargo_manifest);
let wasm_file = project.join("target/wasm32-unknown-unknown")
let wasm_file = project
.join("target/wasm32-unknown-unknown")
.join(target)
.join(format!("{}.wasm", default_wasm_binary_name));
let wasm_compact_file = if is_release_build {
let wasm_compact_file = project.join(
format!(
"{}.compact.wasm",
wasm_binary_name.clone().unwrap_or_else(|| default_wasm_binary_name.clone()),
)
);
let wasm_compact_file = project.join(format!(
"{}.compact.wasm",
wasm_binary_name.clone().unwrap_or_else(|| default_wasm_binary_name.clone()),
));
wasm_gc::garbage_collect_file(&wasm_file, &wasm_compact_file)
.expect("Failed to compact generated WASM binary.");
Some(WasmBinary(wasm_compact_file))
@@ -474,24 +484,19 @@ fn compact_wasm_file(
None
};
let wasm_compact_compressed_file = wasm_compact_file.as_ref()
.and_then(|compact_binary| {
let file_name = wasm_binary_name.clone()
.unwrap_or_else(|| default_wasm_binary_name.clone());
let wasm_compact_compressed_file = wasm_compact_file.as_ref().and_then(|compact_binary| {
let file_name =
wasm_binary_name.clone().unwrap_or_else(|| default_wasm_binary_name.clone());
let wasm_compact_compressed_file = project.join(
format!(
"{}.compact.compressed.wasm",
file_name,
)
);
let wasm_compact_compressed_file =
project.join(format!("{}.compact.compressed.wasm", file_name,));
if compress_wasm(&compact_binary.0, &wasm_compact_compressed_file) {
Some(WasmBinary(wasm_compact_compressed_file))
} else {
None
}
});
if compress_wasm(&compact_binary.0, &wasm_compact_compressed_file) {
Some(WasmBinary(wasm_compact_compressed_file))
} else {
None
}
});
let bloaty_file_name = if let Some(name) = wasm_binary_name {
format!("{}.wasm", name)
@@ -502,24 +507,14 @@ fn compact_wasm_file(
let bloaty_file = project.join(bloaty_file_name);
fs::copy(wasm_file, &bloaty_file).expect("Copying the bloaty file to the project dir.");
(
wasm_compact_file,
wasm_compact_compressed_file,
WasmBinaryBloaty(bloaty_file),
)
(wasm_compact_file, wasm_compact_compressed_file, WasmBinaryBloaty(bloaty_file))
}
fn compress_wasm(
wasm_binary_path: &Path,
compressed_binary_out_path: &Path,
) -> bool {
fn compress_wasm(wasm_binary_path: &Path, compressed_binary_out_path: &Path) -> bool {
use sp_maybe_compressed_blob::CODE_BLOB_BOMB_LIMIT;
let data = fs::read(wasm_binary_path).expect("Failed to read WASM binary");
if let Some(compressed) = sp_maybe_compressed_blob::compress(
&data,
CODE_BLOB_BOMB_LIMIT,
) {
if let Some(compressed) = sp_maybe_compressed_blob::compress(&data, CODE_BLOB_BOMB_LIMIT) {
fs::write(compressed_binary_out_path, &compressed[..])
.expect("Failed to write WASM binary");
@@ -590,7 +585,8 @@ fn generate_rerun_if_changed_instructions(
.exec()
.expect("`cargo metadata` can not fail!");
let package = metadata.packages
let package = metadata
.packages
.iter()
.find(|p| p.manifest_path == cargo_manifest)
.expect("The crate package is contained in its own metadata; qed");
@@ -603,12 +599,11 @@ fn generate_rerun_if_changed_instructions(
packages.insert(DeduplicatePackage::from(package));
while let Some(dependency) = dependencies.pop() {
let path_or_git_dep = dependency.source
.as_ref()
.map(|s| s.starts_with("git+"))
.unwrap_or(true);
let path_or_git_dep =
dependency.source.as_ref().map(|s| s.starts_with("git+")).unwrap_or(true);
let package = metadata.packages
let package = metadata
.packages
.iter()
.filter(|p| !p.manifest_path.starts_with(wasm_workspace))
.find(|p| {
@@ -649,9 +644,7 @@ fn package_rerun_if_changed(package: &DeduplicatePackage) {
// Ignore this entry if it is a directory that contains a `Cargo.toml` that is not the
// `Cargo.toml` related to the current package. This is done to ignore sub-crates of a crate.
// If such a sub-crate is a dependency, it will be processed independently anyway.
p.path() == manifest_path
|| !p.path().is_dir()
|| !p.path().join("Cargo.toml").exists()
p.path() == manifest_path || !p.path().is_dir() || !p.path().join("Cargo.toml").exists()
})
.filter_map(|p| p.ok().map(|p| p.into_path()))
.filter(|p| {
@@ -681,5 +674,6 @@ fn copy_wasm_to_target_directory(cargo_manifest: &Path, wasm_binary: &WasmBinary
fs::copy(
wasm_binary.wasm_binary_path(),
target_dir.join(format!("{}.wasm", get_wasm_binary_name(cargo_manifest))),
).expect("Copies WASM binary to `WASM_TARGET_DIRECTORY`.");
)
.expect("Copies WASM binary to `WASM_TARGET_DIRECTORY`.");
}