Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

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

13 changes: 13 additions & 0 deletions demo/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,22 @@ pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Index, Call>;
pub type Executive = executive::Executive<Runtime, Block, Balances, Balances,
(((((), Council), Democracy), Staking), Session)>;

impl_json_metadata!(
for Runtime with modules
system::Module with Storage,
balances::Module with Storage,
consensus::Module with Storage,
timestamp::Module with Storage,
session::Module with Storage,
staking::Module with Storage,
democracy::Module with Storage,
council::Module with Storage
);

pub mod api {
impl_stubs!(
version => |()| super::VERSION,
json_metadata => |()| super::Runtime::json_metadata(),
authorities => |()| super::Consensus::authorities(),
events => |()| super::System::events(),
initialise_block => |header| super::Executive::initialise_block(&header),
Expand Down
48 changes: 48 additions & 0 deletions substrate/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use primitives::AuthorityId;
use runtime_primitives::{bft::Justification, generic::{BlockId, SignedBlock, Block as RuntimeBlock}};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, One, As, NumberFor};
use runtime_primitives::BuildStorage;
use runtime_support::metadata::JSONMetadataDecodable;
use primitives::{KeccakHasher, RlpCodec};
use primitives::storage::{StorageKey, StorageData};
use codec::Decode;
Expand Down Expand Up @@ -251,6 +252,28 @@ impl<B, E, Block> Client<B, E, Block> where
&self.executor
}

/// Returns the runtime metadata as JSON.
pub fn json_metadata(&self, id: &BlockId<Block>) -> error::Result<String> {
self.executor.call(id, "json_metadata",&[])
.and_then(|r| Vec::<JSONMetadataDecodable>::decode(&mut &r.return_data[..])
.ok_or("JSON Metadata decoding failed".into()))
.and_then(|metadata| {
let mut json = metadata.into_iter().enumerate().fold(String::from("{"),
|mut json, (i, m)| {
if i > 0 {
json.push_str(",");
}
let (mtype, val) = m.into_json_string();
json.push_str(&format!(r#" "{}": {}"#, mtype, val));
json
}
);
json.push_str(" }");

Ok(json)
})
}

/// Reads storage value at a given block + key, returning read proof.
pub fn read_proof(&self, id: &BlockId<Block>, key: &[u8]) -> error::Result<Vec<Vec<u8>>> {
self.state_at(id)
Expand Down Expand Up @@ -711,4 +734,29 @@ mod tests {
assert!(client.state_at(&BlockId::Number(1)).unwrap() != client.state_at(&BlockId::Number(0)).unwrap());
assert_eq!(client.body(&BlockId::Number(1)).unwrap().unwrap().len(), 1)
}

#[test]
fn json_metadata() {
let client = test_client::new();

let mut builder = client.new_block().unwrap();

builder.push_transfer(Transfer {
from: Keyring::Alice.to_raw_public().into(),
to: Keyring::Ferdie.to_raw_public().into(),
amount: 42,
nonce: 0,
}).unwrap();

assert!(builder.push_transfer(Transfer {
from: Keyring::Eve.to_raw_public().into(),
to: Keyring::Alice.to_raw_public().into(),
amount: 42,
nonce: 0,
}).is_err());

client.justify_and_import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();

assert_eq!(client.json_metadata(&BlockId::Number(1)).unwrap(), r#"{ "events": "events" }"#);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That just tests that the json_metadata function of the test-client is getting called.

}
}
1 change: 1 addition & 0 deletions substrate/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ substrate-runtime-primitives = { path = "../runtime/primitives" }
substrate-runtime-version = { path = "../runtime/version" }
substrate-state-machine = { path = "../state-machine" }
tokio = "0.1.7"
serde_json = "1.0"

[dev-dependencies]
assert_matches = "1.1"
Expand Down
1 change: 1 addition & 0 deletions substrate/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_state_machine as state_machine;
extern crate substrate_runtime_version as runtime_version;
extern crate tokio;
extern crate serde_json;

#[macro_use]
extern crate error_chain;
Expand Down
6 changes: 6 additions & 0 deletions substrate/rpc/src/state/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ use rpc;

use errors;

use serde_json;

error_chain! {
links {
Client(client::error::Error, client::error::ErrorKind) #[doc = "Client error"];
}

foreign_links {
Json(serde_json::Error);
}

errors {
/// Provided block range couldn't be resolved to a list of blocks.
InvalidBlockRange(from: String, to: String, details: String) {
Expand Down
11 changes: 11 additions & 0 deletions substrate/rpc/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use rpc::futures::{stream, Future, Sink, Stream};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header};
use tokio::runtime::TaskExecutor;
use serde_json;

use subscriptions::Subscriptions;

Expand Down Expand Up @@ -63,6 +64,10 @@ build_rpc_trait! {
#[rpc(name = "state_getStorageSize", alias = ["state_getStorageSizeAt", ])]
fn storage_size(&self, StorageKey, Trailing<Hash>) -> Result<Option<u64>>;

/// Returns the runtime metadata as JSON.
#[rpc(name = "state_metadata", alias = ["state_metadataAt", ])]
fn json_metadata(&self, Trailing<Hash>) -> Result<serde_json::Value>;

/// Query historical storage entries (by key) starting from a block given as the second parameter.
///
/// NOTE This first returned result contains the initial state of storage for all keys.
Expand Down Expand Up @@ -138,6 +143,12 @@ impl<B, E, Block> StateApi<Block::Hash> for State<B, E, Block> where
Ok(self.storage(key, block)?.map(|x| x.0.len() as u64))
}

fn json_metadata(&self, block: Trailing<Block::Hash>) -> Result<serde_json::Value> {
let block = self.unwrap_or_best(block)?;
let metadata = self.client.json_metadata(&BlockId::Hash(block))?;
serde_json::from_str(&metadata).map_err(Into::into)
}

fn query_storage(&self, keys: Vec<StorageKey>, from: Block::Hash, to: Trailing<Block::Hash>) -> Result<Vec<StorageChangeSet<Block::Hash>>> {
let to = self.unwrap_or_best(to)?;

Expand Down
18 changes: 9 additions & 9 deletions substrate/runtime-support/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ macro_rules! decl_module {
}
}

__impl_json_metadata! {
__dispatch_impl_json_metadata! {
$mod_type $trait_instance $trait_name $call_type $origin_type
{$( $(#[doc = $doc_attr])* fn $fn_name(origin $(, $param_name : $param )*) -> $result; )*}
}
Expand All @@ -240,7 +240,7 @@ macro_rules! __impl_decode {
)*
return Some($call_type:: $fn_name( $( $param_name ),* ));
}

__impl_decode!($input; $input_id; $fn_id + 1; $call_type; $($rest)*)
}
};
Expand Down Expand Up @@ -278,7 +278,7 @@ macro_rules! __impl_encode {
$param_name.encode_to($dest);
)*
}

__impl_encode!($dest; $self; $fn_id + 1; $call_type; $($rest)*)
}
};
Expand Down Expand Up @@ -368,15 +368,15 @@ macro_rules! __impl_outer_dispatch_common {
/// Implement the `json_metadata` function.
#[macro_export]
#[doc(hidden)]
macro_rules! __impl_json_metadata {
macro_rules! __dispatch_impl_json_metadata {
(
$mod_type:ident $trait_instance:ident $trait_name:ident
$($rest:tt)*
) => {
impl<$trait_instance: $trait_name> $mod_type<$trait_instance> {
pub fn json_metadata() -> &'static str {
concat!(r#"{ "name": ""#, stringify!($mod_type), r#"", "call": [ "#,
__call_to_json!($($rest)*), " ] }")
concat!(r#"{ "name": ""#, stringify!($mod_type), r#"", "call": "#,
__call_to_json!($($rest)*), " }")
}
}
}
Expand Down Expand Up @@ -536,7 +536,7 @@ mod tests {
}

const EXPECTED_METADATA: &str = concat!(
r#"{ "name": "Module", "call": [ "#,
r#"{ "name": "Module", "call": "#,
r#"{ "name": "Call", "functions": { "#,
r#""0": { "name": "aux_0", "params": [ "#,
r#"{ "name": "origin", "type": "T::Origin" }"#,
Expand All @@ -551,7 +551,7 @@ mod tests {
r#"{ "name": "data2", "type": "String" }"#,
r#" ], "description": [ ] }"#,
r#" } }"#,
r#" ] }"#,
r#" }"#,
);

impl<T: Trait> Module<T> {
Expand Down Expand Up @@ -581,4 +581,4 @@ mod tests {
let _: serde::de::IgnoredAny =
serde_json::from_str(metadata).expect("Is valid json syntax");
}
}
}
16 changes: 16 additions & 0 deletions substrate/runtime-support/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.

// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

#[macro_export]
macro_rules! impl_outer_event {
($(#[$attr:meta])* pub enum $name:ident for $runtime:ident { $( $module:ident ),* }) => {
Expand Down
15 changes: 14 additions & 1 deletion substrate/runtime-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
//! Support code for the runtime.

#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

#[cfg(not(feature = "std"))]
extern crate alloc;

#[cfg(feature = "std")]
extern crate serde;
Expand All @@ -41,12 +45,21 @@ extern crate substrate_codec_derive;
pub extern crate substrate_codec as codec;
pub use self::storage::generator::Storage as GenericStorage;

#[cfg(feature = "std")]
pub mod alloc {
pub use std::boxed;
pub use std::vec;
}

#[macro_use]
pub mod dispatch;
#[macro_use]
pub mod storage;
mod hashable;
#[macro_use]
mod event;
#[macro_use]
pub mod metadata;

pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap};
pub use self::hashable::Hashable;
Expand Down Expand Up @@ -169,7 +182,7 @@ macro_rules! impl_outer_origin {
impl_outer_origin! {
$(#[$attr])*
pub enum $name for $trait where system = system {
$( $module ),*
$( $module ),*
}
}
}
Expand Down
Loading