Skip to content

Commit

Permalink
The first version
Browse files Browse the repository at this point in the history
  • Loading branch information
boundless-forest committed Aug 3, 2023
1 parent 7e4fe3f commit c714948
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 58 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "
sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" }
fp-account = { git = "https://github.com/paritytech/frontier", branch = "polkadot-v1.0.0" }
fp-account = { git = "https://github.com/boundless-forest/frontier", branch = "bear-polkadot-v1.0.0" }
1 change: 1 addition & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub enum RpcError {
JsonRpseeError(Error),
InvalidCommandParams,
DecodeError,
StorageKeyFailed,
}

impl From<RpcError> for AppError {
Expand Down
72 changes: 21 additions & 51 deletions src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
app::{AccountCommand, AppCommand, ChainCommand, RpcCommand, StateCommand},
errors::{AppError, RpcError},
networks::{ChainInfo, Network},
rpc::{print_format_json, ChainApi, RpcClient, StateApi, SystemApi},
rpc::{map_storage_key, print_format_json, ChainApi, RpcClient, StateApi, SystemApi},
};

/// The APP's command execution result.
Expand Down Expand Up @@ -104,16 +104,11 @@ pub async fn handle_commands<CI: ChainInfo>(
},
AppCommand::Account(sub_command) => match sub_command {
AccountCommand::Balances { account_id, at_block } => {
const pallet_name: &'static str = "System";
const storage_name: &'static str = "Account";
// TODO: FIX ME
let encoded_key = <CI as ChainInfo>::AccountId::from_str(account_id.as_str())
let metadata = client.runtime_metadata().await?;
let key = <CI as ChainInfo>::AccountId::from_str(account_id.as_str())
.map_err(|_| RpcError::InvalidCommandParams)?;

let module_prefix = pallet_name.as_bytes().to_vec();
let storage_prefix = storage_name.as_bytes().to_vec();
let mut storage_key = sp_core::twox_128(&module_prefix).to_vec();
storage_key.extend(&sp_core::twox_128(&storage_prefix)[..]);
let storage_key = map_storage_key(&metadata, "System", "Account", key)
.map_err(|_| RpcError::StorageKeyFailed)?;

let hash = if let Some(hash) = at_block {
Some(
Expand All @@ -124,49 +119,24 @@ pub async fn handle_commands<CI: ChainInfo>(
None
};

let metadata = client.runtime_metadata().await?;
match metadata.1 {
RuntimeMetadata::V14(metadata) => {
if let Some(p) =
metadata.pallets.into_iter().find(|p| p.name == pallet_name)
{
if let Some(entry_metadata) =
p.storage.map(|s| s.entries).and_then(|entries| {
entries.clone().into_iter().find(|e| e.name == storage_name)
}) {
match entry_metadata.ty {
StorageEntryType::Map { hashers, key, value } => {
let hasher = hashers.get(0).expect("Failed to get hasher");
match hasher {
StorageHasher::Blake2_128Concat => {
let x: &[u8] = encoded_key;
let key = sp_core::blake2_128(x)
.iter()
.chain(x.iter())
.cloned()
.collect::<Vec<_>>();
storage_key.extend(key);
},
_ => {
todo!();
},
}
let res: Option<AccountData<CI::Balance>> =
client.get_storage(storage_key, hash).await?;
if let Some(account) = res {
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct AccountData<Balance> {
pub free: Balance,
pub reserved: Balance,
pub frozen: Balance,
}
let res = AccountData {
free: account.free,
reserved: account.reserved,
frozen: account.frozen,
};

todo!()
},
_ => todo!(),
}
}
}
},
_ => {
todo!();
},
print_format_json(res);
}

let res: Option<AccountData<CI::Balance>> =
client.get_storage(sp_storage::StorageKey(storage_key), hash).await?;
print_format_json(res);
},
},
}
Expand Down
5 changes: 3 additions & 2 deletions src/networks/darwinia.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use sp_runtime::{
// this crate
use super::{ChainInfo, Network};

pub type Signature = fp_account::EthereumSignature;
pub type AccountId = <<Signature as sp_runtime::traits::Verify>::Signer as sp_runtime::traits::IdentifyAccount>::AccountId;
type Signature = fp_account::EthereumSignature;
type AccountPublic = <Signature as sp_runtime::traits::Verify>::Signer;
pub type AccountId = <AccountPublic as sp_runtime::traits::IdentifyAccount>::AccountId;

/// Pangolin Chain information
pub struct PangolinChain;
Expand Down
4 changes: 2 additions & 2 deletions src/networks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::{marker::Sync, str::FromStr};
// crates.io
use clap::Subcommand;
use serde::{Deserialize, Serialize};
use sp_core::Encode;
use sp_core::{Decode, Encode};
use sp_runtime::DeserializeOwned;

/// The ChainInfo API
Expand All @@ -24,7 +24,7 @@ pub trait ChainInfo: Sync + Send {
// The account id type of the chain
type AccountId: Serialize + DeserializeOwned + Encode + FromStr + AsRef<[u8]>;
/// The balance type of the chain
type Balance: Serialize + DeserializeOwned;
type Balance: Serialize + DeserializeOwned + Decode;
/// The block type of the chain
type Block: Serialize + DeserializeOwned;
/// The block number type of the chain
Expand Down
4 changes: 2 additions & 2 deletions src/networks/polkadot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use sp_runtime::{
// this crate
use super::{ChainInfo, Network};

pub type Signature = MultiSignature;
pub type AccountPublic = <Signature as Verify>::Signer;
type Signature = MultiSignature;
type AccountPublic = <Signature as Verify>::Signer;
pub type AccountId = <AccountPublic as IdentifyAccount>::AccountId;

/// Polkadot Chain information
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod api;
mod client;
mod storage;
mod types;

pub use api::{ChainApi, StateApi, SystemApi};
pub use client::{print_format_json, RpcClient, RpcResult};
pub use storage::map_storage_key;
pub use types::{ChainType, Health, Properties};
64 changes: 64 additions & 0 deletions src/rpc/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use frame_metadata::{
v14::{StorageEntryType, StorageHasher},
RuntimeMetadata, RuntimeMetadataPrefixed,
};
use sp_core::Encode;
use sp_storage::StorageKey;

pub fn map_storage_key<K: Encode>(
runtime_metadata: &RuntimeMetadataPrefixed,
pallet_name: &str,
storage_name: &str,
key: K,
) -> Result<StorageKey, String> {
let mut storage_key = sp_core::twox_128(pallet_name.as_bytes()).to_vec();
storage_key.extend(&sp_core::twox_128(&storage_name.as_bytes()));

match &runtime_metadata.1 {
RuntimeMetadata::V14(metadata) => {
if let Some(p) = metadata.pallets.iter().find(|p| p.name == pallet_name) {
if let Some(entry) = p.storage.clone().map(|s| s.entries).and_then(|entries| {
entries.clone().into_iter().find(|e| e.name == storage_name)
}) {
match entry.ty {
StorageEntryType::Map { hashers, key, value } => {
let hasher = hashers.get(0).expect("Failed to get hasher");
let key = key_hash(&key, hasher);
storage_key.extend(key);
},
_ =>
return Err("Only support single map entry in this function".to_string()),
}
} else {
return Err("Did not find the storage item.".to_string());
}
} else {
return Err("Did not find the pallet.".to_string());
}
},
_ => {
return Err("Only support the runtime metadata V14 now.".to_string());
},
}

Ok(StorageKey(storage_key))
}

/// generates the key's hash depending on the StorageHasher selected
fn key_hash<K: Encode>(key: &K, hasher: &StorageHasher) -> Vec<u8> {
let encoded_key = key.encode();
match hasher {
StorageHasher::Identity => encoded_key.to_vec(),
StorageHasher::Blake2_128 => sp_core::blake2_128(&encoded_key).to_vec(),
StorageHasher::Blake2_128Concat => {
// copied from substrate Blake2_128Concat::hash since StorageHasher is not public
let x: &[u8] = encoded_key.as_slice();
sp_core::blake2_128(x).iter().chain(x.iter()).cloned().collect::<Vec<_>>()
},
StorageHasher::Blake2_256 => sp_core::blake2_256(&encoded_key).to_vec(),
StorageHasher::Twox128 => sp_core::twox_128(&encoded_key).to_vec(),
StorageHasher::Twox256 => sp_core::twox_256(&encoded_key).to_vec(),
StorageHasher::Twox64Concat =>
sp_core::twox_64(&encoded_key).iter().chain(&encoded_key).cloned().collect(),
}
}

0 comments on commit c714948

Please sign in to comment.