mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 15:51:12 +00:00
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:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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`.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user