Remove all dapp permissions related settings (#9120)
* Completely remove all dapps struct from rpc * Remove unused pub use * Remove dapp policy/permission func in ethcore * Remove all dapps settings from rpc * Fix rpc tests * Use both origin and user_agent * Address grumbles * Address grumbles * Fix tests
This commit is contained in:
parent
0d8001adea
commit
1f18dbb17c
@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
mod stores;
|
mod stores;
|
||||||
|
|
||||||
use self::stores::{AddressBook, DappsSettingsStore, NewDappsPolicy};
|
use self::stores::AddressBook;
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
|
|
||||||
@ -96,20 +96,6 @@ impl From<SSError> for SignError {
|
|||||||
/// `AccountProvider` errors.
|
/// `AccountProvider` errors.
|
||||||
pub type Error = SSError;
|
pub type Error = SSError;
|
||||||
|
|
||||||
/// Dapp identifier
|
|
||||||
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
|
||||||
pub struct DappId(String);
|
|
||||||
|
|
||||||
impl From<DappId> for String {
|
|
||||||
fn from(id: DappId) -> String { id.0 }
|
|
||||||
}
|
|
||||||
impl From<String> for DappId {
|
|
||||||
fn from(id: String) -> DappId { DappId(id) }
|
|
||||||
}
|
|
||||||
impl<'a> From<&'a str> for DappId {
|
|
||||||
fn from(id: &'a str) -> DappId { DappId(id.to_owned()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transient_sstore() -> EthMultiStore {
|
fn transient_sstore() -> EthMultiStore {
|
||||||
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
|
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
|
||||||
}
|
}
|
||||||
@ -125,8 +111,6 @@ pub struct AccountProvider {
|
|||||||
unlocked: RwLock<HashMap<StoreAccountRef, AccountData>>,
|
unlocked: RwLock<HashMap<StoreAccountRef, AccountData>>,
|
||||||
/// Address book.
|
/// Address book.
|
||||||
address_book: RwLock<AddressBook>,
|
address_book: RwLock<AddressBook>,
|
||||||
/// Dapps settings.
|
|
||||||
dapps_settings: RwLock<DappsSettingsStore>,
|
|
||||||
/// Accounts on disk
|
/// Accounts on disk
|
||||||
sstore: Box<SecretStore>,
|
sstore: Box<SecretStore>,
|
||||||
/// Accounts unlocked with rolling tokens
|
/// Accounts unlocked with rolling tokens
|
||||||
@ -195,7 +179,6 @@ impl AccountProvider {
|
|||||||
unlocked_secrets: RwLock::new(HashMap::new()),
|
unlocked_secrets: RwLock::new(HashMap::new()),
|
||||||
unlocked: RwLock::new(HashMap::new()),
|
unlocked: RwLock::new(HashMap::new()),
|
||||||
address_book: RwLock::new(address_book),
|
address_book: RwLock::new(address_book),
|
||||||
dapps_settings: RwLock::new(DappsSettingsStore::new(&sstore.local_path())),
|
|
||||||
sstore: sstore,
|
sstore: sstore,
|
||||||
transient_sstore: transient_sstore(),
|
transient_sstore: transient_sstore(),
|
||||||
hardware_store: hardware_store,
|
hardware_store: hardware_store,
|
||||||
@ -210,7 +193,6 @@ impl AccountProvider {
|
|||||||
unlocked_secrets: RwLock::new(HashMap::new()),
|
unlocked_secrets: RwLock::new(HashMap::new()),
|
||||||
unlocked: RwLock::new(HashMap::new()),
|
unlocked: RwLock::new(HashMap::new()),
|
||||||
address_book: RwLock::new(AddressBook::transient()),
|
address_book: RwLock::new(AddressBook::transient()),
|
||||||
dapps_settings: RwLock::new(DappsSettingsStore::transient()),
|
|
||||||
sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")),
|
sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")),
|
||||||
transient_sstore: transient_sstore(),
|
transient_sstore: transient_sstore(),
|
||||||
hardware_store: None,
|
hardware_store: None,
|
||||||
@ -290,6 +272,11 @@ impl AccountProvider {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the address of default account.
|
||||||
|
pub fn default_account(&self) -> Result<Address, Error> {
|
||||||
|
Ok(self.accounts()?.first().cloned().unwrap_or_default())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns addresses of hardware accounts.
|
/// Returns addresses of hardware accounts.
|
||||||
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> {
|
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> {
|
||||||
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
|
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
|
||||||
@ -318,175 +305,6 @@ impl AccountProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets addresses of accounts exposed for unknown dapps.
|
|
||||||
/// `None` means that all accounts will be visible.
|
|
||||||
/// If not `None` or empty it will also override default account.
|
|
||||||
pub fn set_new_dapps_addresses(&self, accounts: Option<Vec<Address>>) -> Result<(), Error> {
|
|
||||||
let current_default = self.new_dapps_default_address()?;
|
|
||||||
|
|
||||||
self.dapps_settings.write().set_policy(match accounts {
|
|
||||||
None => NewDappsPolicy::AllAccounts {
|
|
||||||
default: current_default,
|
|
||||||
},
|
|
||||||
Some(accounts) => NewDappsPolicy::Whitelist(accounts),
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets addresses of accounts exposed for unknown dapps.
|
|
||||||
/// `None` means that all accounts will be visible.
|
|
||||||
pub fn new_dapps_addresses(&self) -> Result<Option<Vec<Address>>, Error> {
|
|
||||||
Ok(match self.dapps_settings.read().policy() {
|
|
||||||
NewDappsPolicy::AllAccounts { .. } => None,
|
|
||||||
NewDappsPolicy::Whitelist(accounts) => Some(accounts),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets a default account for unknown dapps.
|
|
||||||
/// This account will always be returned as the first one.
|
|
||||||
pub fn set_new_dapps_default_address(&self, address: Address) -> Result<(), Error> {
|
|
||||||
if !self.valid_addresses()?.contains(&address) {
|
|
||||||
return Err(SSError::InvalidAccount.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut settings = self.dapps_settings.write();
|
|
||||||
let new_policy = match settings.policy() {
|
|
||||||
NewDappsPolicy::AllAccounts { .. } => NewDappsPolicy::AllAccounts { default: address },
|
|
||||||
NewDappsPolicy::Whitelist(list) => NewDappsPolicy::Whitelist(Self::insert_default(list, address)),
|
|
||||||
};
|
|
||||||
settings.set_policy(new_policy);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Inserts given address as first in the vector, preventing duplicates.
|
|
||||||
fn insert_default(mut addresses: Vec<Address>, default: Address) -> Vec<Address> {
|
|
||||||
if let Some(position) = addresses.iter().position(|address| address == &default) {
|
|
||||||
addresses.swap(0, position);
|
|
||||||
} else {
|
|
||||||
addresses.insert(0, default);
|
|
||||||
}
|
|
||||||
|
|
||||||
addresses
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a list of accounts that new dapp should see.
|
|
||||||
/// First account is always the default account.
|
|
||||||
fn new_dapps_addresses_list(&self) -> Result<Vec<Address>, Error> {
|
|
||||||
match self.dapps_settings.read().policy() {
|
|
||||||
NewDappsPolicy::AllAccounts { default } => if default.is_zero() {
|
|
||||||
self.accounts()
|
|
||||||
} else {
|
|
||||||
Ok(Self::insert_default(self.accounts()?, default))
|
|
||||||
},
|
|
||||||
NewDappsPolicy::Whitelist(accounts) => {
|
|
||||||
let addresses = self.filter_addresses(accounts)?;
|
|
||||||
if addresses.is_empty() {
|
|
||||||
Ok(vec![self.accounts()?.get(0).cloned().unwrap_or(0.into())])
|
|
||||||
} else {
|
|
||||||
Ok(addresses)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a default account for new dapps
|
|
||||||
/// Will return zero address in case the default is not set and there are no accounts configured.
|
|
||||||
pub fn new_dapps_default_address(&self) -> Result<Address, Error> {
|
|
||||||
Ok(self.new_dapps_addresses_list()?
|
|
||||||
.get(0)
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(0.into())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a list of dapps recently requesting accounts.
|
|
||||||
pub fn recent_dapps(&self) -> Result<HashMap<DappId, u64>, Error> {
|
|
||||||
Ok(self.dapps_settings.read().recent_dapps())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Marks dapp as recently used.
|
|
||||||
pub fn note_dapp_used(&self, dapp: DappId) -> Result<(), Error> {
|
|
||||||
let mut dapps = self.dapps_settings.write();
|
|
||||||
dapps.mark_dapp_used(dapp.clone());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets addresses visible for given dapp.
|
|
||||||
pub fn dapp_addresses(&self, dapp: DappId) -> Result<Vec<Address>, Error> {
|
|
||||||
let accounts = self.dapps_settings.read().settings().get(&dapp).map(|settings| {
|
|
||||||
(settings.accounts.clone(), settings.default.clone())
|
|
||||||
});
|
|
||||||
|
|
||||||
match accounts {
|
|
||||||
Some((Some(accounts), Some(default))) => self.filter_addresses(Self::insert_default(accounts, default)),
|
|
||||||
Some((Some(accounts), None)) => self.filter_addresses(accounts),
|
|
||||||
Some((None, Some(default))) => self.filter_addresses(Self::insert_default(self.new_dapps_addresses_list()?, default)),
|
|
||||||
_ => self.new_dapps_addresses_list(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns default account for particular dapp falling back to other allowed accounts if necessary.
|
|
||||||
pub fn dapp_default_address(&self, dapp: DappId) -> Result<Address, Error> {
|
|
||||||
let dapp_default = self.dapp_addresses(dapp)?
|
|
||||||
.get(0)
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
match dapp_default {
|
|
||||||
Some(default) => Ok(default),
|
|
||||||
None => self.new_dapps_default_address(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets default address for given dapp.
|
|
||||||
/// Does not alter dapp addresses, but this account will always be returned as the first one.
|
|
||||||
pub fn set_dapp_default_address(&self, dapp: DappId, address: Address) -> Result<(), Error> {
|
|
||||||
if !self.valid_addresses()?.contains(&address) {
|
|
||||||
return Err(SSError::InvalidAccount.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.dapps_settings.write().set_default(dapp, address);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets addresses visible for given dapp.
|
|
||||||
/// If `None` - falls back to dapps addresses
|
|
||||||
/// If not `None` and not empty it will also override default account.
|
|
||||||
pub fn set_dapp_addresses(&self, dapp: DappId, addresses: Option<Vec<Address>>) -> Result<(), Error> {
|
|
||||||
let (addresses, default) = match addresses {
|
|
||||||
Some(addresses) => {
|
|
||||||
let addresses = self.filter_addresses(addresses)?;
|
|
||||||
let default = addresses.get(0).cloned();
|
|
||||||
(Some(addresses), default)
|
|
||||||
},
|
|
||||||
None => (None, None),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut settings = self.dapps_settings.write();
|
|
||||||
if let Some(default) = default {
|
|
||||||
settings.set_default(dapp.clone(), default);
|
|
||||||
}
|
|
||||||
settings.set_accounts(dapp, addresses);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn valid_addresses(&self) -> Result<HashSet<Address>, Error> {
|
|
||||||
Ok(self.addresses_info().into_iter()
|
|
||||||
.map(|(address, _)| address)
|
|
||||||
.chain(self.accounts()?)
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Removes addresses that are neither accounts nor in address book.
|
|
||||||
fn filter_addresses(&self, addresses: Vec<Address>) -> Result<Vec<Address>, Error> {
|
|
||||||
let valid = self.valid_addresses()?;
|
|
||||||
|
|
||||||
Ok(addresses.into_iter()
|
|
||||||
.filter(|a| valid.contains(&a))
|
|
||||||
.collect()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns each address along with metadata.
|
/// Returns each address along with metadata.
|
||||||
pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> {
|
pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> {
|
||||||
self.address_book.read().get()
|
self.address_book.read().get()
|
||||||
@ -849,7 +667,7 @@ impl AccountProvider {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{AccountProvider, Unlock, DappId};
|
use super::{AccountProvider, Unlock};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use ethstore::ethkey::{Generator, Random, Address};
|
use ethstore::ethkey::{Generator, Random, Address};
|
||||||
use ethstore::{StoreAccountRef, Derivation};
|
use ethstore::{StoreAccountRef, Derivation};
|
||||||
@ -977,96 +795,6 @@ mod tests {
|
|||||||
assert!(ap.sign_with_token(kp.address(), token, Default::default()).is_err(), "Second usage of the same token should fail.");
|
assert!(ap.sign_with_token(kp.address(), token, Default::default()).is_err(), "Second usage of the same token should fail.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_reset_dapp_addresses_to_default() {
|
|
||||||
// given
|
|
||||||
let ap = AccountProvider::transient_provider();
|
|
||||||
let app = DappId("app1".into());
|
|
||||||
// add accounts to address book
|
|
||||||
ap.set_address_name(1.into(), "1".into());
|
|
||||||
ap.set_address_name(2.into(), "2".into());
|
|
||||||
// set `AllAccounts` policy
|
|
||||||
ap.set_new_dapps_addresses(Some(vec![1.into(), 2.into()])).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
|
||||||
|
|
||||||
// Alter and check
|
|
||||||
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 3.into()])).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
|
|
||||||
|
|
||||||
// Reset back to default
|
|
||||||
ap.set_dapp_addresses(app.clone(), None).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_set_dapps_default_address() {
|
|
||||||
// given
|
|
||||||
let ap = AccountProvider::transient_provider();
|
|
||||||
let app = DappId("app1".into());
|
|
||||||
// set `AllAccounts` policy
|
|
||||||
ap.set_new_dapps_addresses(None).unwrap();
|
|
||||||
// add accounts to address book
|
|
||||||
ap.set_address_name(1.into(), "1".into());
|
|
||||||
ap.set_address_name(2.into(), "2".into());
|
|
||||||
|
|
||||||
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 2.into(), 3.into()])).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
|
||||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
|
||||||
|
|
||||||
// when setting empty list
|
|
||||||
ap.set_dapp_addresses(app.clone(), Some(vec![])).unwrap();
|
|
||||||
|
|
||||||
// then default account is intact
|
|
||||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
|
|
||||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
|
||||||
|
|
||||||
// alter default account
|
|
||||||
ap.set_dapp_default_address("app1".into(), 2.into()).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![2.into()]);
|
|
||||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 2.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_set_dapps_policy_and_default_account() {
|
|
||||||
// given
|
|
||||||
let ap = AccountProvider::transient_provider();
|
|
||||||
|
|
||||||
// default_account should be always available
|
|
||||||
assert_eq!(ap.new_dapps_default_address().unwrap(), 0.into());
|
|
||||||
|
|
||||||
let address = ap.new_account(&"test".into()).unwrap();
|
|
||||||
ap.set_address_name(1.into(), "1".into());
|
|
||||||
|
|
||||||
// Default account set to first account by default
|
|
||||||
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
|
|
||||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
|
|
||||||
|
|
||||||
// Even when returning nothing
|
|
||||||
ap.set_new_dapps_addresses(Some(vec![])).unwrap();
|
|
||||||
// Default account is still returned
|
|
||||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
|
||||||
|
|
||||||
// change to all
|
|
||||||
ap.set_new_dapps_addresses(None).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
|
||||||
|
|
||||||
// change to non-existent account
|
|
||||||
ap.set_new_dapps_addresses(Some(vec![2.into()])).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
|
||||||
|
|
||||||
// change to a addresses
|
|
||||||
ap.set_new_dapps_addresses(Some(vec![1.into()])).unwrap();
|
|
||||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![1.into()]);
|
|
||||||
|
|
||||||
// it overrides default account
|
|
||||||
assert_eq!(ap.new_dapps_default_address().unwrap(), 1.into());
|
|
||||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
|
||||||
|
|
||||||
ap.set_new_dapps_default_address(address).unwrap();
|
|
||||||
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
|
|
||||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_not_return_blacklisted_account() {
|
fn should_not_return_blacklisted_account() {
|
||||||
// given
|
// given
|
||||||
|
@ -14,21 +14,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Address Book and Dapps Settings Store
|
//! Address Book Store
|
||||||
|
|
||||||
use std::{fs, fmt, hash, ops};
|
use std::{fs, fmt, hash, ops};
|
||||||
use std::sync::atomic::{self, AtomicUsize};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use ethstore::ethkey::Address;
|
use ethstore::ethkey::Address;
|
||||||
use ethjson::misc::{
|
use ethjson::misc::AccountMeta;
|
||||||
AccountMeta,
|
|
||||||
DappsSettings as JsonSettings,
|
|
||||||
DappsHistory as JsonDappsHistory,
|
|
||||||
NewDappsPolicy as JsonNewDappsPolicy,
|
|
||||||
};
|
|
||||||
use account_provider::DappId;
|
|
||||||
|
|
||||||
/// Disk-backed map from Address to String. Uses JSON.
|
/// Disk-backed map from Address to String. Uses JSON.
|
||||||
pub struct AddressBook {
|
pub struct AddressBook {
|
||||||
@ -88,214 +81,6 @@ impl AddressBook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dapps user settings
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq)]
|
|
||||||
pub struct DappsSettings {
|
|
||||||
/// A list of visible accounts
|
|
||||||
pub accounts: Option<Vec<Address>>,
|
|
||||||
/// Default account
|
|
||||||
pub default: Option<Address>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<JsonSettings> for DappsSettings {
|
|
||||||
fn from(s: JsonSettings) -> Self {
|
|
||||||
DappsSettings {
|
|
||||||
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
|
|
||||||
default: s.default.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DappsSettings> for JsonSettings {
|
|
||||||
fn from(s: DappsSettings) -> Self {
|
|
||||||
JsonSettings {
|
|
||||||
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
|
|
||||||
default: s.default.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dapps user settings
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
||||||
pub enum NewDappsPolicy {
|
|
||||||
AllAccounts {
|
|
||||||
default: Address,
|
|
||||||
},
|
|
||||||
Whitelist(Vec<Address>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<JsonNewDappsPolicy> for NewDappsPolicy {
|
|
||||||
fn from(s: JsonNewDappsPolicy) -> Self {
|
|
||||||
match s {
|
|
||||||
JsonNewDappsPolicy::AllAccounts { default } => NewDappsPolicy::AllAccounts {
|
|
||||||
default: default.into(),
|
|
||||||
},
|
|
||||||
JsonNewDappsPolicy::Whitelist(accounts) => NewDappsPolicy::Whitelist(
|
|
||||||
accounts.into_iter().map(Into::into).collect()
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NewDappsPolicy> for JsonNewDappsPolicy {
|
|
||||||
fn from(s: NewDappsPolicy) -> Self {
|
|
||||||
match s {
|
|
||||||
NewDappsPolicy::AllAccounts { default } => JsonNewDappsPolicy::AllAccounts {
|
|
||||||
default: default.into(),
|
|
||||||
},
|
|
||||||
NewDappsPolicy::Whitelist(accounts) => JsonNewDappsPolicy::Whitelist(
|
|
||||||
accounts.into_iter().map(Into::into).collect()
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transient dapps data
|
|
||||||
#[derive(Default, Debug, Clone, Eq, PartialEq)]
|
|
||||||
pub struct TransientDappsData {
|
|
||||||
/// Timestamp of last access
|
|
||||||
pub last_accessed: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<JsonDappsHistory> for TransientDappsData {
|
|
||||||
fn from(s: JsonDappsHistory) -> Self {
|
|
||||||
TransientDappsData {
|
|
||||||
last_accessed: s.last_accessed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<TransientDappsData> for JsonDappsHistory {
|
|
||||||
fn from(s: TransientDappsData) -> Self {
|
|
||||||
JsonDappsHistory {
|
|
||||||
last_accessed: s.last_accessed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TimeProvider {
|
|
||||||
Clock,
|
|
||||||
Incremenetal(AtomicUsize)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TimeProvider {
|
|
||||||
fn get(&self) -> u64 {
|
|
||||||
match *self {
|
|
||||||
TimeProvider::Clock => {
|
|
||||||
::std::time::UNIX_EPOCH.elapsed()
|
|
||||||
.expect("Correct time is required to be set")
|
|
||||||
.as_secs()
|
|
||||||
|
|
||||||
},
|
|
||||||
TimeProvider::Incremenetal(ref time) => {
|
|
||||||
time.fetch_add(1, atomic::Ordering::SeqCst) as u64
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAX_RECENT_DAPPS: usize = 50;
|
|
||||||
|
|
||||||
/// Disk-backed map from DappId to Settings. Uses JSON.
|
|
||||||
pub struct DappsSettingsStore {
|
|
||||||
/// Dapps Settings
|
|
||||||
settings: DiskMap<DappId, DappsSettings>,
|
|
||||||
/// New Dapps Policy
|
|
||||||
policy: DiskMap<String, NewDappsPolicy>,
|
|
||||||
/// Transient Data of recently Accessed Dapps
|
|
||||||
history: DiskMap<DappId, TransientDappsData>,
|
|
||||||
/// Time
|
|
||||||
time: TimeProvider,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DappsSettingsStore {
|
|
||||||
/// Creates new store at given directory path.
|
|
||||||
pub fn new(path: &Path) -> Self {
|
|
||||||
let mut r = DappsSettingsStore {
|
|
||||||
settings: DiskMap::new(path, "dapps_accounts.json".into()),
|
|
||||||
policy: DiskMap::new(path, "dapps_policy.json".into()),
|
|
||||||
history: DiskMap::new(path, "dapps_history.json".into()),
|
|
||||||
time: TimeProvider::Clock,
|
|
||||||
};
|
|
||||||
r.settings.revert(JsonSettings::read);
|
|
||||||
r.policy.revert(JsonNewDappsPolicy::read);
|
|
||||||
r.history.revert(JsonDappsHistory::read);
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates transient store (no changes are saved to disk).
|
|
||||||
pub fn transient() -> Self {
|
|
||||||
DappsSettingsStore {
|
|
||||||
settings: DiskMap::transient(),
|
|
||||||
policy: DiskMap::transient(),
|
|
||||||
history: DiskMap::transient(),
|
|
||||||
time: TimeProvider::Incremenetal(AtomicUsize::new(1)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get copy of the dapps settings
|
|
||||||
pub fn settings(&self) -> HashMap<DappId, DappsSettings> {
|
|
||||||
self.settings.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns current new dapps policy
|
|
||||||
pub fn policy(&self) -> NewDappsPolicy {
|
|
||||||
self.policy.get("default").cloned().unwrap_or(NewDappsPolicy::AllAccounts {
|
|
||||||
default: 0.into(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns recent dapps with last accessed timestamp
|
|
||||||
pub fn recent_dapps(&self) -> HashMap<DappId, u64> {
|
|
||||||
self.history.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Marks recent dapp as used
|
|
||||||
pub fn mark_dapp_used(&mut self, dapp: DappId) {
|
|
||||||
{
|
|
||||||
let entry = self.history.entry(dapp).or_insert_with(|| Default::default());
|
|
||||||
entry.last_accessed = self.time.get();
|
|
||||||
}
|
|
||||||
// Clear extraneous entries
|
|
||||||
while self.history.len() > MAX_RECENT_DAPPS {
|
|
||||||
let min = self.history.iter()
|
|
||||||
.min_by_key(|&(_, ref v)| v.last_accessed)
|
|
||||||
.map(|(ref k, _)| k.clone())
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
match min {
|
|
||||||
Some(k) => self.history.remove(&k),
|
|
||||||
None => break,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
self.history.save(JsonDappsHistory::write);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets current new dapps policy
|
|
||||||
pub fn set_policy(&mut self, policy: NewDappsPolicy) {
|
|
||||||
self.policy.insert("default".into(), policy);
|
|
||||||
self.policy.save(JsonNewDappsPolicy::write);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets accounts for specific dapp.
|
|
||||||
pub fn set_accounts(&mut self, id: DappId, accounts: Option<Vec<Address>>) {
|
|
||||||
{
|
|
||||||
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
|
|
||||||
settings.accounts = accounts;
|
|
||||||
}
|
|
||||||
self.settings.save(JsonSettings::write);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets a default account for specific dapp.
|
|
||||||
pub fn set_default(&mut self, id: DappId, default: Address) {
|
|
||||||
{
|
|
||||||
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
|
|
||||||
settings.default = Some(default);
|
|
||||||
}
|
|
||||||
self.settings.save(JsonSettings::write);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Disk-serializable HashMap
|
/// Disk-serializable HashMap
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DiskMap<K: hash::Hash + Eq, V> {
|
struct DiskMap<K: hash::Hash + Eq, V> {
|
||||||
@ -366,8 +151,7 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{AddressBook, DappsSettingsStore, DappsSettings, NewDappsPolicy};
|
use super::AddressBook;
|
||||||
use account_provider::DappId;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use ethjson::misc::AccountMeta;
|
use ethjson::misc::AccountMeta;
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
@ -398,63 +182,4 @@ mod tests {
|
|||||||
3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}
|
3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_save_and_reload_dapps_settings() {
|
|
||||||
// given
|
|
||||||
let tempdir = TempDir::new("").unwrap();
|
|
||||||
let mut b = DappsSettingsStore::new(tempdir.path());
|
|
||||||
|
|
||||||
// when
|
|
||||||
b.set_accounts("dappOne".into(), Some(vec![1.into(), 2.into()]));
|
|
||||||
|
|
||||||
// then
|
|
||||||
let b = DappsSettingsStore::new(tempdir.path());
|
|
||||||
assert_eq!(b.settings(), hash_map![
|
|
||||||
"dappOne".into() => DappsSettings {
|
|
||||||
accounts: Some(vec![1.into(), 2.into()]),
|
|
||||||
default: None,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_maintain_a_map_of_recent_dapps() {
|
|
||||||
let mut store = DappsSettingsStore::transient();
|
|
||||||
assert!(store.recent_dapps().is_empty(), "Initially recent dapps should be empty.");
|
|
||||||
|
|
||||||
let dapp1: DappId = "dapp1".into();
|
|
||||||
let dapp2: DappId = "dapp2".into();
|
|
||||||
store.mark_dapp_used(dapp1.clone());
|
|
||||||
let recent = store.recent_dapps();
|
|
||||||
assert_eq!(recent.len(), 1);
|
|
||||||
assert_eq!(recent.get(&dapp1), Some(&1));
|
|
||||||
|
|
||||||
store.mark_dapp_used(dapp2.clone());
|
|
||||||
let recent = store.recent_dapps();
|
|
||||||
assert_eq!(recent.len(), 2);
|
|
||||||
assert_eq!(recent.get(&dapp1), Some(&1));
|
|
||||||
assert_eq!(recent.get(&dapp2), Some(&2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_store_dapps_policy() {
|
|
||||||
// given
|
|
||||||
let tempdir = TempDir::new("").unwrap();
|
|
||||||
let mut store = DappsSettingsStore::new(tempdir.path());
|
|
||||||
|
|
||||||
// Test default policy
|
|
||||||
assert_eq!(store.policy(), NewDappsPolicy::AllAccounts {
|
|
||||||
default: 0.into(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// when
|
|
||||||
store.set_policy(NewDappsPolicy::Whitelist(vec![1.into(), 2.into()]));
|
|
||||||
|
|
||||||
// then
|
|
||||||
let store = DappsSettingsStore::new(tempdir.path());
|
|
||||||
assert_eq!(store.policy.clone(), hash_map![
|
|
||||||
"default".into() => NewDappsPolicy::Whitelist(vec![1.into(), 2.into()])
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity 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.
|
|
||||||
|
|
||||||
// Parity 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 Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Dapps settings de/serialization.
|
|
||||||
|
|
||||||
use hash;
|
|
||||||
|
|
||||||
/// Settings for specific dapp.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct DappsSettings {
|
|
||||||
/// A list of accounts this Dapp can see.
|
|
||||||
pub accounts: Option<Vec<hash::Address>>,
|
|
||||||
/// Default account
|
|
||||||
pub default: Option<hash::Address>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_serialization!(String => DappsSettings);
|
|
||||||
|
|
||||||
/// History for specific dapp.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub struct DappsHistory {
|
|
||||||
/// Last accessed timestamp
|
|
||||||
pub last_accessed: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_serialization!(String => DappsHistory);
|
|
||||||
|
|
||||||
/// Accounts policy for new dapps.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
pub enum NewDappsPolicy {
|
|
||||||
/// All accounts are exposed by default.
|
|
||||||
AllAccounts {
|
|
||||||
/// Default account, which should be returned as the first one.
|
|
||||||
default: hash::Address,
|
|
||||||
},
|
|
||||||
/// Only accounts listed here are exposed by default for new dapps.
|
|
||||||
Whitelist(Vec<hash::Address>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_serialization!(String => NewDappsPolicy);
|
|
@ -48,7 +48,5 @@ macro_rules! impl_serialization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod account_meta;
|
mod account_meta;
|
||||||
mod dapps_settings;
|
|
||||||
|
|
||||||
pub use self::dapps_settings::{DappsSettings, DappsHistory, NewDappsPolicy};
|
|
||||||
pub use self::account_meta::AccountMeta;
|
pub use self::account_meta::AccountMeta;
|
||||||
|
@ -79,9 +79,6 @@ extern crate log as rlog;
|
|||||||
#[cfg(feature = "secretstore")]
|
#[cfg(feature = "secretstore")]
|
||||||
extern crate ethcore_secretstore;
|
extern crate ethcore_secretstore;
|
||||||
|
|
||||||
#[cfg(feature = "dapps")]
|
|
||||||
extern crate parity_dapps;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate pretty_assertions;
|
extern crate pretty_assertions;
|
||||||
|
@ -25,7 +25,7 @@ pub trait HttpMetaExtractor: Send + Sync + 'static {
|
|||||||
/// Type of Metadata
|
/// Type of Metadata
|
||||||
type Metadata: jsonrpc_core::Metadata;
|
type Metadata: jsonrpc_core::Metadata;
|
||||||
/// Extracts metadata from given params.
|
/// Extracts metadata from given params.
|
||||||
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>, dapps_origin: Option<String>) -> Self::Metadata;
|
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>) -> Self::Metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MetaExtractor<T> {
|
pub struct MetaExtractor<T> {
|
||||||
@ -49,7 +49,6 @@ impl<M, T> http::MetaExtractor<M> for MetaExtractor<T> where
|
|||||||
|
|
||||||
let origin = as_string(req.headers().get_raw("origin"));
|
let origin = as_string(req.headers().get_raw("origin"));
|
||||||
let user_agent = as_string(req.headers().get_raw("user-agent"));
|
let user_agent = as_string(req.headers().get_raw("user-agent"));
|
||||||
let dapps_origin = as_string(req.headers().get_raw("x-parity-origin"));
|
self.extractor.read_metadata(origin, user_agent)
|
||||||
self.extractor.read_metadata(origin, user_agent, dapps_origin)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ mod testsing {
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
||||||
let expected = "34\n{\"jsonrpc\":\"2.0\",\"result\":\"unknown via RPC\",\"id\":1}\n\n0\n\n";
|
let expected = "4B\n{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / unknown agent via RPC\",\"id\":1}\n\n0\n\n";
|
||||||
let res = request(server,
|
let res = request(server,
|
||||||
&format!("\
|
&format!("\
|
||||||
POST / HTTP/1.1\r\n\
|
POST / HTTP/1.1\r\n\
|
||||||
@ -98,7 +98,7 @@ mod testsing {
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
||||||
let expected = "38\n{\"jsonrpc\":\"2.0\",\"result\":\"curl/7.16.3 via RPC\",\"id\":1}\n\n0\n\n";
|
let expected = "49\n{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / curl/7.16.3 via RPC\",\"id\":1}\n\n0\n\n";
|
||||||
let res = request(server,
|
let res = request(server,
|
||||||
&format!("\
|
&format!("\
|
||||||
POST / HTTP/1.1\r\n\
|
POST / HTTP/1.1\r\n\
|
||||||
@ -116,59 +116,4 @@ mod testsing {
|
|||||||
res.assert_status("HTTP/1.1 200 OK");
|
res.assert_status("HTTP/1.1 200 OK");
|
||||||
assert_eq!(res.body, expected);
|
assert_eq!(res.body, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_extract_dapp_origin() {
|
|
||||||
// given
|
|
||||||
let (server, address) = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
|
||||||
let expected = "3A\n{\"jsonrpc\":\"2.0\",\"result\":\"Dapp http://parity.io\",\"id\":1}\n\n0\n\n";
|
|
||||||
let res = request(server,
|
|
||||||
&format!("\
|
|
||||||
POST / HTTP/1.1\r\n\
|
|
||||||
Host: {}\r\n\
|
|
||||||
Content-Type: application/json\r\n\
|
|
||||||
Content-Length: {}\r\n\
|
|
||||||
Origin: http://parity.io\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
User-Agent: curl/7.16.3\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
", address, req.len(), req)
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
res.assert_status("HTTP/1.1 200 OK");
|
|
||||||
assert_eq!(res.body, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_extract_dapp_origin_from_extension() {
|
|
||||||
// given
|
|
||||||
let (server, address) = serve();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
|
|
||||||
let expected = "44\n{\"jsonrpc\":\"2.0\",\"result\":\"Dapp http://wallet.ethereum.org\",\"id\":1}\n\n0\n\n";
|
|
||||||
let res = request(server,
|
|
||||||
&format!("\
|
|
||||||
POST / HTTP/1.1\r\n\
|
|
||||||
Host: {}\r\n\
|
|
||||||
Content-Type: application/json\r\n\
|
|
||||||
Content-Length: {}\r\n\
|
|
||||||
Origin: null\r\n\
|
|
||||||
X-Parity-Origin: http://wallet.ethereum.org\r\n\
|
|
||||||
Connection: close\r\n\
|
|
||||||
User-Agent: curl/7.16.3\r\n\
|
|
||||||
\r\n\
|
|
||||||
{}
|
|
||||||
", address, req.len(), req)
|
|
||||||
);
|
|
||||||
|
|
||||||
// then
|
|
||||||
res.assert_status("HTTP/1.1 200 OK");
|
|
||||||
assert_eq!(res.body, expected);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -36,14 +36,13 @@ pub struct RpcExtractor;
|
|||||||
impl HttpMetaExtractor for RpcExtractor {
|
impl HttpMetaExtractor for RpcExtractor {
|
||||||
type Metadata = Metadata;
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>, dapps_origin: Option<String>) -> Metadata {
|
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>) -> Metadata {
|
||||||
Metadata {
|
Metadata {
|
||||||
origin: match (origin.as_ref().map(|s| s.as_str()), user_agent, dapps_origin) {
|
origin: Origin::Rpc(
|
||||||
(Some("null"), _, Some(dapp)) => Origin::Dapps(dapp.into()),
|
format!("{} / {}",
|
||||||
(Some(dapp), _, _) => Origin::Dapps(dapp.to_owned().into()),
|
origin.unwrap_or("unknown origin".to_string()),
|
||||||
(None, Some(service), _) => Origin::Rpc(service.into()),
|
user_agent.unwrap_or("unknown agent".to_string()))
|
||||||
(None, _, _) => Origin::Rpc("unknown".into()),
|
),
|
||||||
},
|
|
||||||
session: None,
|
session: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,16 +75,15 @@ impl ws::MetaExtractor<Metadata> for WsExtractor {
|
|||||||
fn extract(&self, req: &ws::RequestContext) -> Metadata {
|
fn extract(&self, req: &ws::RequestContext) -> Metadata {
|
||||||
let id = req.session_id as u64;
|
let id = req.session_id as u64;
|
||||||
|
|
||||||
let dapp = req.origin.as_ref().map(|origin| (&**origin).into()).unwrap_or_default();
|
|
||||||
let origin = match self.authcodes_path {
|
let origin = match self.authcodes_path {
|
||||||
Some(ref path) => {
|
Some(ref path) => {
|
||||||
let authorization = req.protocols.get(0).and_then(|p| auth_token_hash(&path, p, true));
|
let authorization = req.protocols.get(0).and_then(|p| auth_token_hash(&path, p, true));
|
||||||
match authorization {
|
match authorization {
|
||||||
Some(id) => Origin::Signer { session: id.into(), dapp: dapp },
|
Some(id) => Origin::Signer { session: id.into() },
|
||||||
None => Origin::Ws { session: id.into(), dapp: dapp },
|
None => Origin::Ws { session: id.into() },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => Origin::Ws { session: id.into(), dapp: dapp },
|
None => Origin::Ws { session: id.into() },
|
||||||
};
|
};
|
||||||
let session = Some(Arc::new(Session::new(req.sender())));
|
let session = Some(Arc::new(Session::new(req.sender())));
|
||||||
Metadata {
|
Metadata {
|
||||||
@ -253,26 +251,13 @@ mod tests {
|
|||||||
let extractor = RpcExtractor;
|
let extractor = RpcExtractor;
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let meta1 = extractor.read_metadata(None, None, None);
|
let meta1 = extractor.read_metadata(None, None);
|
||||||
let meta2 = extractor.read_metadata(None, Some("http://parity.io".to_owned()), None);
|
let meta2 = extractor.read_metadata(None, Some("http://parity.io".to_owned()));
|
||||||
let meta3 = extractor.read_metadata(None, Some("http://parity.io".to_owned()), Some("ignored".into()));
|
let meta3 = extractor.read_metadata(None, Some("http://parity.io".to_owned()));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(meta1.origin, Origin::Rpc("unknown".into()));
|
assert_eq!(meta1.origin, Origin::Rpc("unknown origin / unknown agent".into()));
|
||||||
assert_eq!(meta2.origin, Origin::Rpc("http://parity.io".into()));
|
assert_eq!(meta2.origin, Origin::Rpc("unknown origin / http://parity.io".into()));
|
||||||
assert_eq!(meta3.origin, Origin::Rpc("http://parity.io".into()));
|
assert_eq!(meta3.origin, Origin::Rpc("unknown origin / http://parity.io".into()));
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_dapps_origin() {
|
|
||||||
// given
|
|
||||||
let extractor = RpcExtractor;
|
|
||||||
let dapp = "https://wallet.ethereum.org".to_owned();
|
|
||||||
|
|
||||||
// when
|
|
||||||
let meta = extractor.read_metadata(Some("null".into()), None, Some(dapp.clone()));
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(meta.origin, Origin::Dapps(dapp.into()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,18 +16,14 @@
|
|||||||
|
|
||||||
use transaction::{Transaction, SignedTransaction, Action};
|
use transaction::{Transaction, SignedTransaction, Action};
|
||||||
|
|
||||||
|
use ethereum_types::U256;
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use v1::helpers::CallRequest;
|
use v1::helpers::CallRequest;
|
||||||
|
|
||||||
pub fn sign_call(request: CallRequest, gas_cap: bool) -> Result<SignedTransaction, Error> {
|
pub fn sign_call(request: CallRequest) -> Result<SignedTransaction, Error> {
|
||||||
let max_gas = 50_000_000.into();
|
let max_gas = U256::from(50_000_000);
|
||||||
let gas = match request.gas {
|
let gas = match request.gas {
|
||||||
Some(gas) if gas_cap && gas > max_gas => {
|
|
||||||
warn!("Gas limit capped to {} (from {})", max_gas, gas);
|
|
||||||
max_gas
|
|
||||||
}
|
|
||||||
Some(gas) => gas,
|
Some(gas) => gas,
|
||||||
None if gas_cap => max_gas,
|
|
||||||
None => max_gas * 10,
|
None => max_gas * 10,
|
||||||
};
|
};
|
||||||
let from = request.from.unwrap_or(0.into());
|
let from = request.from.unwrap_or(0.into());
|
||||||
|
@ -17,9 +17,8 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use ethereum_types::{U256, Address};
|
use ethereum_types::{U256, Address};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use ethcore::account_provider::DappId;
|
|
||||||
use v1::helpers::{ConfirmationRequest, ConfirmationPayload, oneshot, errors};
|
use v1::helpers::{ConfirmationRequest, ConfirmationPayload, oneshot, errors};
|
||||||
use v1::types::{ConfirmationResponse, H160 as RpcH160, Origin, DappId as RpcDappId};
|
use v1::types::{ConfirmationResponse, H160 as RpcH160, Origin};
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
|
|
||||||
@ -30,14 +29,6 @@ pub type ConfirmationResult = Result<ConfirmationResponse, Error>;
|
|||||||
pub enum DefaultAccount {
|
pub enum DefaultAccount {
|
||||||
/// Default account is known
|
/// Default account is known
|
||||||
Provided(Address),
|
Provided(Address),
|
||||||
/// Should use default account for dapp
|
|
||||||
ForDapp(DappId),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<RpcDappId> for DefaultAccount {
|
|
||||||
fn from(dapp_id: RpcDappId) -> Self {
|
|
||||||
DefaultAccount::ForDapp(dapp_id.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RpcH160> for DefaultAccount {
|
impl From<RpcH160> for DefaultAccount {
|
||||||
|
@ -21,11 +21,11 @@ use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rlp::{self, Rlp};
|
use rlp::{self, Rlp};
|
||||||
use ethereum_types::{U256, H64, H160, H256, Address};
|
use ethereum_types::{U256, H64, H256, Address};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use ethash::SeedHashCompute;
|
use ethash::SeedHashCompute;
|
||||||
use ethcore::account_provider::{AccountProvider, DappId};
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::client::{BlockChainClient, BlockId, TransactionId, UncleId, StateOrBlock, StateClient, StateInfo, Call, EngineInfo};
|
use ethcore::client::{BlockChainClient, BlockId, TransactionId, UncleId, StateOrBlock, StateClient, StateInfo, Call, EngineInfo};
|
||||||
use ethcore::ethereum::Ethash;
|
use ethcore::ethereum::Ethash;
|
||||||
use ethcore::filter::Filter as EthcoreFilter;
|
use ethcore::filter::Filter as EthcoreFilter;
|
||||||
@ -398,13 +398,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
|
|||||||
Ok(Some(block))
|
Ok(Some(block))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dapp_accounts(&self, dapp: DappId) -> Result<Vec<H160>> {
|
|
||||||
self.accounts
|
|
||||||
.note_dapp_used(dapp.clone())
|
|
||||||
.and_then(|_| self.accounts.dapp_addresses(dapp))
|
|
||||||
.map_err(|e| errors::account("Could not fetch accounts.", e))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_state(&self, number: BlockNumber) -> StateOrBlock {
|
fn get_state(&self, number: BlockNumber) -> StateOrBlock {
|
||||||
match number {
|
match number {
|
||||||
BlockNumber::Num(num) => BlockId::Number(num).into(),
|
BlockNumber::Num(num) => BlockId::Number(num).into(),
|
||||||
@ -507,12 +500,10 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn author(&self, meta: Metadata) -> Result<RpcH160> {
|
fn author(&self) -> Result<RpcH160> {
|
||||||
let dapp = meta.dapp_id();
|
|
||||||
|
|
||||||
let mut miner = self.miner.authoring_params().author;
|
let mut miner = self.miner.authoring_params().author;
|
||||||
if miner == 0.into() {
|
if miner == 0.into() {
|
||||||
miner = self.dapp_accounts(dapp.into())?.get(0).cloned().unwrap_or_default();
|
miner = self.accounts.accounts().ok().and_then(|a| a.get(0).cloned()).unwrap_or_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(RpcH160::from(miner))
|
Ok(RpcH160::from(miner))
|
||||||
@ -530,10 +521,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
|||||||
Ok(RpcU256::from(default_gas_price(&*self.client, &*self.miner, self.options.gas_price_percentile)))
|
Ok(RpcU256::from(default_gas_price(&*self.client, &*self.miner, self.options.gas_price_percentile)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accounts(&self, meta: Metadata) -> Result<Vec<RpcH160>> {
|
fn accounts(&self) -> Result<Vec<RpcH160>> {
|
||||||
let dapp = meta.dapp_id();
|
let accounts = self.accounts.accounts()
|
||||||
|
.map_err(|e| errors::account("Could not fetch accounts.", e))?;
|
||||||
let accounts = self.dapp_accounts(dapp.into())?;
|
|
||||||
Ok(accounts.into_iter().map(Into::into).collect())
|
Ok(accounts.into_iter().map(Into::into).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -835,9 +825,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
|||||||
self.send_raw_transaction(raw)
|
self.send_raw_transaction(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, meta: Self::Metadata, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
|
fn call(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
|
||||||
let request = CallRequest::into(request);
|
let request = CallRequest::into(request);
|
||||||
let signed = try_bf!(fake_sign::sign_call(request, meta.is_dapp()));
|
let signed = try_bf!(fake_sign::sign_call(request));
|
||||||
|
|
||||||
let num = num.unwrap_or_default();
|
let num = num.unwrap_or_default();
|
||||||
|
|
||||||
@ -875,9 +865,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_gas(&self, meta: Self::Metadata, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
|
fn estimate_gas(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
|
||||||
let request = CallRequest::into(request);
|
let request = CallRequest::into(request);
|
||||||
let signed = try_bf!(fake_sign::sign_call(request, meta.is_dapp()));
|
let signed = try_bf!(fake_sign::sign_call(request));
|
||||||
let num = num.unwrap_or_default();
|
let num = num.unwrap_or_default();
|
||||||
|
|
||||||
let (state, header) = if num == BlockNumber::Pending {
|
let (state, header) = if num == BlockNumber::Pending {
|
||||||
|
@ -29,7 +29,7 @@ use light::client::LightChainClient;
|
|||||||
use light::{cht, TransactionQueue};
|
use light::{cht, TransactionQueue};
|
||||||
use light::on_demand::{request, OnDemand};
|
use light::on_demand::{request, OnDemand};
|
||||||
|
|
||||||
use ethcore::account_provider::{AccountProvider, DappId};
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
use ethcore::filter::Filter as EthcoreFilter;
|
use ethcore::filter::Filter as EthcoreFilter;
|
||||||
use ethcore::ids::BlockId;
|
use ethcore::ids::BlockId;
|
||||||
@ -251,7 +251,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn author(&self, _meta: Self::Metadata) -> Result<RpcH160> {
|
fn author(&self) -> Result<RpcH160> {
|
||||||
Ok(Default::default())
|
Ok(Default::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,12 +270,8 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
|||||||
.unwrap_or_else(Default::default))
|
.unwrap_or_else(Default::default))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accounts(&self, meta: Metadata) -> Result<Vec<RpcH160>> {
|
fn accounts(&self) -> Result<Vec<RpcH160>> {
|
||||||
let dapp: DappId = meta.dapp_id().into();
|
self.accounts.accounts()
|
||||||
|
|
||||||
self.accounts
|
|
||||||
.note_dapp_used(dapp.clone())
|
|
||||||
.and_then(|_| self.accounts.dapp_addresses(dapp))
|
|
||||||
.map_err(|e| errors::account("Could not fetch accounts.", e))
|
.map_err(|e| errors::account("Could not fetch accounts.", e))
|
||||||
.map(|accs| accs.into_iter().map(Into::<RpcH160>::into).collect())
|
.map(|accs| accs.into_iter().map(Into::<RpcH160>::into).collect())
|
||||||
}
|
}
|
||||||
@ -397,7 +393,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
|||||||
self.send_raw_transaction(raw)
|
self.send_raw_transaction(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, _meta: Self::Metadata, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
|
fn call(&self, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
|
||||||
Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
|
Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
|
||||||
match res {
|
match res {
|
||||||
Ok(exec) => Ok(exec.output.into()),
|
Ok(exec) => Ok(exec.output.into()),
|
||||||
@ -406,7 +402,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn estimate_gas(&self, _meta: Self::Metadata, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
|
fn estimate_gas(&self, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
|
||||||
// TODO: binary chop for more accurate estimates.
|
// TODO: binary chop for more accurate estimates.
|
||||||
Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
|
Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
|
||||||
match res {
|
match res {
|
||||||
|
@ -43,7 +43,7 @@ use v1::types::{
|
|||||||
Peers, Transaction, RpcSettings, Histogram,
|
Peers, Transaction, RpcSettings, Histogram,
|
||||||
TransactionStats, LocalTransactionStatus,
|
TransactionStats, LocalTransactionStatus,
|
||||||
BlockNumber, ConsensusCapability, VersionInfo,
|
BlockNumber, ConsensusCapability, VersionInfo,
|
||||||
OperationsInfo, DappId, ChainStatus,
|
OperationsInfo, ChainStatus,
|
||||||
AccountInfo, HwAccountInfo, Header, RichHeader,
|
AccountInfo, HwAccountInfo, Header, RichHeader,
|
||||||
};
|
};
|
||||||
use Host;
|
use Host;
|
||||||
@ -99,13 +99,10 @@ impl ParityClient {
|
|||||||
impl Parity for ParityClient {
|
impl Parity for ParityClient {
|
||||||
type Metadata = Metadata;
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>> {
|
fn accounts_info(&self) -> Result<BTreeMap<H160, AccountInfo>> {
|
||||||
let dapp = dapp.unwrap_or_default();
|
|
||||||
|
|
||||||
let store = &self.accounts;
|
let store = &self.accounts;
|
||||||
let dapp_accounts = store
|
let dapp_accounts = store
|
||||||
.note_dapp_used(dapp.clone().into())
|
.accounts()
|
||||||
.and_then(|_| store.dapp_addresses(dapp.into()))
|
|
||||||
.map_err(|e| errors::account("Could not fetch accounts.", e))?
|
.map_err(|e| errors::account("Could not fetch accounts.", e))?
|
||||||
.into_iter().collect::<HashSet<_>>();
|
.into_iter().collect::<HashSet<_>>();
|
||||||
|
|
||||||
@ -136,10 +133,9 @@ impl Parity for ParityClient {
|
|||||||
Ok(store.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))?)
|
Ok(store.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_account(&self, meta: Self::Metadata) -> Result<H160> {
|
fn default_account(&self) -> Result<H160> {
|
||||||
let dapp_id = meta.dapp_id();
|
|
||||||
Ok(self.accounts
|
Ok(self.accounts
|
||||||
.dapp_addresses(dapp_id.into())
|
.accounts()
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|accounts| accounts.get(0).cloned())
|
.and_then(|accounts| accounts.get(0).cloned())
|
||||||
.map(|acc| acc.into())
|
.map(|acc| acc.into())
|
||||||
@ -423,7 +419,7 @@ impl Parity for ParityClient {
|
|||||||
ipfs::cid(content)
|
ipfs::cid(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, _meta: Self::Metadata, _requests: Vec<CallRequest>, _block: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
|
fn call(&self, _requests: Vec<CallRequest>, _block: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
|
||||||
Err(errors::light_unimplemented(None))
|
Err(errors::light_unimplemented(None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,11 @@ impl Traces for TracesClient {
|
|||||||
Err(errors::light_unimplemented(None))
|
Err(errors::light_unimplemented(None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, _meta: Self::Metadata, _request: CallRequest, _flags: TraceOptions, _block: Trailing<BlockNumber>) -> Result<TraceResults> {
|
fn call(&self, _request: CallRequest, _flags: TraceOptions, _block: Trailing<BlockNumber>) -> Result<TraceResults> {
|
||||||
Err(errors::light_unimplemented(None))
|
Err(errors::light_unimplemented(None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_many(&self, _meta: Self::Metadata, _request: Vec<(CallRequest, TraceOptions)>, _block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
|
fn call_many(&self, _request: Vec<(CallRequest, TraceOptions)>, _block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
|
||||||
Err(errors::light_unimplemented(None))
|
Err(errors::light_unimplemented(None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ use v1::types::{
|
|||||||
Peers, Transaction, RpcSettings, Histogram,
|
Peers, Transaction, RpcSettings, Histogram,
|
||||||
TransactionStats, LocalTransactionStatus,
|
TransactionStats, LocalTransactionStatus,
|
||||||
BlockNumber, ConsensusCapability, VersionInfo,
|
BlockNumber, ConsensusCapability, VersionInfo,
|
||||||
OperationsInfo, DappId, ChainStatus,
|
OperationsInfo, ChainStatus,
|
||||||
AccountInfo, HwAccountInfo, RichHeader,
|
AccountInfo, HwAccountInfo, RichHeader,
|
||||||
block_number_to_id
|
block_number_to_id
|
||||||
};
|
};
|
||||||
@ -103,12 +103,8 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
|||||||
{
|
{
|
||||||
type Metadata = Metadata;
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>> {
|
fn accounts_info(&self) -> Result<BTreeMap<H160, AccountInfo>> {
|
||||||
let dapp = dapp.unwrap_or_default();
|
let dapp_accounts = self.accounts.accounts()
|
||||||
|
|
||||||
let dapp_accounts = self.accounts
|
|
||||||
.note_dapp_used(dapp.clone().into())
|
|
||||||
.and_then(|_| self.accounts.dapp_addresses(dapp.into()))
|
|
||||||
.map_err(|e| errors::account("Could not fetch accounts.", e))?
|
.map_err(|e| errors::account("Could not fetch accounts.", e))?
|
||||||
.into_iter().collect::<HashSet<_>>();
|
.into_iter().collect::<HashSet<_>>();
|
||||||
|
|
||||||
@ -137,11 +133,8 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
|||||||
self.accounts.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))
|
self.accounts.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_account(&self, meta: Self::Metadata) -> Result<H160> {
|
fn default_account(&self) -> Result<H160> {
|
||||||
let dapp_id = meta.dapp_id();
|
Ok(self.accounts.default_account()
|
||||||
|
|
||||||
Ok(self.accounts
|
|
||||||
.dapp_default_address(dapp_id.into())
|
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.ok()
|
.ok()
|
||||||
.unwrap_or_default())
|
.unwrap_or_default())
|
||||||
@ -421,11 +414,11 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
|||||||
ipfs::cid(content)
|
ipfs::cid(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, meta: Self::Metadata, requests: Vec<CallRequest>, num: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
|
fn call(&self, requests: Vec<CallRequest>, num: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
|
||||||
let requests = requests
|
let requests = requests
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|request| Ok((
|
.map(|request| Ok((
|
||||||
fake_sign::sign_call(request.into(), meta.is_dapp())?,
|
fake_sign::sign_call(request.into())?,
|
||||||
Default::default()
|
Default::default()
|
||||||
)))
|
)))
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
@ -25,7 +25,7 @@ use ethcore::account_provider::AccountProvider;
|
|||||||
use jsonrpc_core::Result;
|
use jsonrpc_core::Result;
|
||||||
use v1::helpers::errors;
|
use v1::helpers::errors;
|
||||||
use v1::traits::ParityAccounts;
|
use v1::traits::ParityAccounts;
|
||||||
use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, DappId, Derive, DeriveHierarchical, DeriveHash, ExtAccountInfo};
|
use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, Derive, DeriveHierarchical, DeriveHash, ExtAccountInfo};
|
||||||
use ethkey::Password;
|
use ethkey::Password;
|
||||||
|
|
||||||
/// Account management (personal) rpc implementation.
|
/// Account management (personal) rpc implementation.
|
||||||
@ -143,61 +143,6 @@ impl ParityAccounts for ParityAccountsClient {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_dapp_addresses(&self, dapp: DappId, addresses: Option<Vec<RpcH160>>) -> Result<bool> {
|
|
||||||
self.accounts.set_dapp_addresses(dapp.into(), addresses.map(into_vec))
|
|
||||||
.map_err(|e| errors::account("Couldn't set dapp addresses.", e))
|
|
||||||
.map(|_| true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dapp_addresses(&self, dapp: DappId) -> Result<Vec<RpcH160>> {
|
|
||||||
self.accounts.dapp_addresses(dapp.into())
|
|
||||||
.map_err(|e| errors::account("Couldn't get dapp addresses.", e))
|
|
||||||
.map(into_vec)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_dapp_default_address(&self, dapp: DappId, address: RpcH160) -> Result<bool> {
|
|
||||||
self.accounts.set_dapp_default_address(dapp.into(), address.into())
|
|
||||||
.map_err(|e| errors::account("Couldn't set dapp default address.", e))
|
|
||||||
.map(|_| true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dapp_default_address(&self, dapp: DappId) -> Result<RpcH160> {
|
|
||||||
self.accounts.dapp_default_address(dapp.into())
|
|
||||||
.map_err(|e| errors::account("Couldn't get dapp default address.", e))
|
|
||||||
.map(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_new_dapps_addresses(&self, addresses: Option<Vec<RpcH160>>) -> Result<bool> {
|
|
||||||
self.accounts
|
|
||||||
.set_new_dapps_addresses(addresses.map(into_vec))
|
|
||||||
.map_err(|e| errors::account("Couldn't set dapps addresses.", e))
|
|
||||||
.map(|_| true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_dapps_addresses(&self) -> Result<Option<Vec<RpcH160>>> {
|
|
||||||
self.accounts.new_dapps_addresses()
|
|
||||||
.map_err(|e| errors::account("Couldn't get dapps addresses.", e))
|
|
||||||
.map(|accounts| accounts.map(into_vec))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_new_dapps_default_address(&self, address: RpcH160) -> Result<bool> {
|
|
||||||
self.accounts.set_new_dapps_default_address(address.into())
|
|
||||||
.map_err(|e| errors::account("Couldn't set new dapps default address.", e))
|
|
||||||
.map(|_| true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_dapps_default_address(&self) -> Result<RpcH160> {
|
|
||||||
self.accounts.new_dapps_default_address()
|
|
||||||
.map_err(|e| errors::account("Couldn't get new dapps default address.", e))
|
|
||||||
.map(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recent_dapps(&self) -> Result<BTreeMap<DappId, u64>> {
|
|
||||||
self.accounts.recent_dapps()
|
|
||||||
.map_err(|e| errors::account("Couldn't get recent dapps.", e))
|
|
||||||
.map(|map| map.into_iter().map(|(k, v)| (k.into(), v)).collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>> {
|
fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>> {
|
||||||
self.accounts
|
self.accounts
|
||||||
.import_geth_accounts(into_vec(addresses), false)
|
.import_geth_accounts(into_vec(addresses), false)
|
||||||
|
@ -58,14 +58,14 @@ impl<D: Dispatcher> PersonalClient<D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Dispatcher + 'static> PersonalClient<D> {
|
impl<D: Dispatcher + 'static> PersonalClient<D> {
|
||||||
fn do_sign_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<(PendingTransaction, D)> {
|
fn do_sign_transaction(&self, _meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<(PendingTransaction, D)> {
|
||||||
let dispatcher = self.dispatcher.clone();
|
let dispatcher = self.dispatcher.clone();
|
||||||
let accounts = self.accounts.clone();
|
let accounts = self.accounts.clone();
|
||||||
|
|
||||||
let default = match request.from.as_ref() {
|
let default = match request.from.as_ref() {
|
||||||
Some(account) => Ok(account.clone().into()),
|
Some(account) => Ok(account.clone().into()),
|
||||||
None => accounts
|
None => accounts
|
||||||
.dapp_default_address(meta.dapp_id().into())
|
.default_account()
|
||||||
.map_err(|e| errors::account("Cannot find default account.", e)),
|
.map_err(|e| errors::account("Cannot find default account.", e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,14 +100,14 @@ impl Private for PrivateClient {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn private_call(&self, meta: Self::Metadata, block_number: BlockNumber, request: CallRequest) -> Result<Bytes, Error> {
|
fn private_call(&self, block_number: BlockNumber, request: CallRequest) -> Result<Bytes, Error> {
|
||||||
let id = match block_number {
|
let id = match block_number {
|
||||||
BlockNumber::Pending => return Err(errors::private_message_block_id_not_supported()),
|
BlockNumber::Pending => return Err(errors::private_message_block_id_not_supported()),
|
||||||
num => block_number_to_id(num)
|
num => block_number_to_id(num)
|
||||||
};
|
};
|
||||||
|
|
||||||
let request = CallRequest::into(request);
|
let request = CallRequest::into(request);
|
||||||
let signed = fake_sign::sign_call(request, meta.is_dapp())?;
|
let signed = fake_sign::sign_call(request)?;
|
||||||
let client = self.unwrap_manager()?;
|
let client = self.unwrap_manager()?;
|
||||||
let executed_result = client.private_call(id, &signed).map_err(|e| errors::private_message(e))?;
|
let executed_result = client.private_call(id, &signed).map_err(|e| errors::private_message(e))?;
|
||||||
Ok(executed_result.output.into())
|
Ok(executed_result.output.into())
|
||||||
|
@ -112,7 +112,6 @@ impl<D: Dispatcher + 'static> SigningQueueClient<D> {
|
|||||||
let accounts = self.accounts.clone();
|
let accounts = self.accounts.clone();
|
||||||
let default_account = match default_account {
|
let default_account = match default_account {
|
||||||
DefaultAccount::Provided(acc) => acc,
|
DefaultAccount::Provided(acc) => acc,
|
||||||
DefaultAccount::ForDapp(dapp) => accounts.dapp_default_address(dapp).ok().unwrap_or_default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let dispatcher = self.dispatcher.clone();
|
let dispatcher = self.dispatcher.clone();
|
||||||
@ -138,8 +137,8 @@ impl<D: Dispatcher + 'static> SigningQueueClient<D> {
|
|||||||
impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
|
impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
|
||||||
type Metadata = Metadata;
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn compose_transaction(&self, meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
|
fn compose_transaction(&self, _meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
|
||||||
let default_account = self.accounts.dapp_default_address(meta.dapp_id().into()).ok().unwrap_or_default();
|
let default_account = self.accounts.default_account().ok().unwrap_or_default();
|
||||||
Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into))
|
Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +163,7 @@ impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
|
|||||||
let remote = self.remote.clone();
|
let remote = self.remote.clone();
|
||||||
let confirmations = self.confirmations.clone();
|
let confirmations = self.confirmations.clone();
|
||||||
|
|
||||||
Box::new(self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.dapp_id().into(), meta.origin)
|
Box::new(self.dispatch(RpcConfirmationPayload::SendTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()), meta.origin)
|
||||||
.map(|result| match result {
|
.map(|result| match result {
|
||||||
DispatchResult::Value(v) => RpcEither::Or(v),
|
DispatchResult::Value(v) => RpcEither::Or(v),
|
||||||
DispatchResult::Future(id, future) => {
|
DispatchResult::Future(id, future) => {
|
||||||
@ -221,7 +220,7 @@ impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
|
|||||||
fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256> {
|
fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256> {
|
||||||
let res = self.dispatch(
|
let res = self.dispatch(
|
||||||
RpcConfirmationPayload::SendTransaction(request),
|
RpcConfirmationPayload::SendTransaction(request),
|
||||||
meta.dapp_id().into(),
|
DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()),
|
||||||
meta.origin,
|
meta.origin,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -236,7 +235,7 @@ impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
|
|||||||
fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction> {
|
fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction> {
|
||||||
let res = self.dispatch(
|
let res = self.dispatch(
|
||||||
RpcConfirmationPayload::SignTransaction(request),
|
RpcConfirmationPayload::SignTransaction(request),
|
||||||
meta.dapp_id().into(),
|
DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()),
|
||||||
meta.origin,
|
meta.origin,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ impl<D: Dispatcher + 'static> SigningUnsafeClient<D> {
|
|||||||
let accounts = self.accounts.clone();
|
let accounts = self.accounts.clone();
|
||||||
let default = match account {
|
let default = match account {
|
||||||
DefaultAccount::Provided(acc) => acc,
|
DefaultAccount::Provided(acc) => acc,
|
||||||
DefaultAccount::ForDapp(dapp) => accounts.dapp_default_address(dapp).ok().unwrap_or_default(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let dis = self.dispatcher.clone();
|
let dis = self.dispatcher.clone();
|
||||||
@ -80,8 +79,8 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256> {
|
fn send_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256> {
|
||||||
Box::new(self.handle(RpcConfirmationPayload::SendTransaction(request), meta.dapp_id().into())
|
Box::new(self.handle(RpcConfirmationPayload::SendTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()))
|
||||||
.then(|res| match res {
|
.then(|res| match res {
|
||||||
Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
|
Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
@ -89,8 +88,8 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction> {
|
fn sign_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction> {
|
||||||
Box::new(self.handle(RpcConfirmationPayload::SignTransaction(request), meta.dapp_id().into())
|
Box::new(self.handle(RpcConfirmationPayload::SignTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()))
|
||||||
.then(|res| match res {
|
.then(|res| match res {
|
||||||
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
|
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
@ -102,9 +101,9 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
|
|||||||
impl<D: Dispatcher + 'static> ParitySigning for SigningUnsafeClient<D> {
|
impl<D: Dispatcher + 'static> ParitySigning for SigningUnsafeClient<D> {
|
||||||
type Metadata = Metadata;
|
type Metadata = Metadata;
|
||||||
|
|
||||||
fn compose_transaction(&self, meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
|
fn compose_transaction(&self, _meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
|
||||||
let accounts = self.accounts.clone();
|
let accounts = self.accounts.clone();
|
||||||
let default_account = accounts.dapp_default_address(meta.dapp_id().into()).ok().unwrap_or_default();
|
let default_account = accounts.default_account().ok().unwrap_or_default();
|
||||||
Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into))
|
Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,11 +87,11 @@ impl<C, S> Traces for TracesClient<C> where
|
|||||||
.map(LocalizedTrace::from))
|
.map(LocalizedTrace::from))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&self, meta: Self::Metadata, request: CallRequest, flags: TraceOptions, block: Trailing<BlockNumber>) -> Result<TraceResults> {
|
fn call(&self, request: CallRequest, flags: TraceOptions, block: Trailing<BlockNumber>) -> Result<TraceResults> {
|
||||||
let block = block.unwrap_or_default();
|
let block = block.unwrap_or_default();
|
||||||
|
|
||||||
let request = CallRequest::into(request);
|
let request = CallRequest::into(request);
|
||||||
let signed = fake_sign::sign_call(request, meta.is_dapp())?;
|
let signed = fake_sign::sign_call(request)?;
|
||||||
|
|
||||||
let id = match block {
|
let id = match block {
|
||||||
BlockNumber::Num(num) => BlockId::Number(num),
|
BlockNumber::Num(num) => BlockId::Number(num),
|
||||||
@ -109,13 +109,13 @@ impl<C, S> Traces for TracesClient<C> where
|
|||||||
.map_err(errors::call)
|
.map_err(errors::call)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_many(&self, meta: Self::Metadata, requests: Vec<(CallRequest, TraceOptions)>, block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
|
fn call_many(&self, requests: Vec<(CallRequest, TraceOptions)>, block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
|
||||||
let block = block.unwrap_or_default();
|
let block = block.unwrap_or_default();
|
||||||
|
|
||||||
let requests = requests.into_iter()
|
let requests = requests.into_iter()
|
||||||
.map(|(request, flags)| {
|
.map(|(request, flags)| {
|
||||||
let request = CallRequest::into(request);
|
let request = CallRequest::into(request);
|
||||||
let signed = fake_sign::sign_call(request, meta.is_dapp())?;
|
let signed = fake_sign::sign_call(request)?;
|
||||||
Ok((signed, to_call_analytics(flags)))
|
Ok((signed, to_call_analytics(flags)))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
@ -20,7 +20,7 @@ use std::sync::Arc;
|
|||||||
use jsonrpc_core;
|
use jsonrpc_core;
|
||||||
use jsonrpc_pubsub::{Session, PubSubMetadata};
|
use jsonrpc_pubsub::{Session, PubSubMetadata};
|
||||||
|
|
||||||
use v1::types::{DappId, Origin};
|
use v1::types::Origin;
|
||||||
|
|
||||||
/// RPC methods metadata.
|
/// RPC methods metadata.
|
||||||
#[derive(Clone, Default, Debug)]
|
#[derive(Clone, Default, Debug)]
|
||||||
@ -31,28 +31,6 @@ pub struct Metadata {
|
|||||||
pub session: Option<Arc<Session>>,
|
pub session: Option<Arc<Session>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Metadata {
|
|
||||||
/// Returns dapp id if this request is coming from a Dapp or default `DappId` otherwise.
|
|
||||||
pub fn dapp_id(&self) -> DappId {
|
|
||||||
// TODO [ToDr] Extract dapp info from Ws connections.
|
|
||||||
match self.origin {
|
|
||||||
Origin::Dapps(ref dapp) => dapp.clone(),
|
|
||||||
Origin::Ws { ref dapp, .. } => dapp.clone(),
|
|
||||||
Origin::Signer { ref dapp, .. } => dapp.clone(),
|
|
||||||
_ => DappId::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the request originates from a Dapp.
|
|
||||||
pub fn is_dapp(&self) -> bool {
|
|
||||||
if let Origin::Dapps(_) = self.origin {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl jsonrpc_core::Metadata for Metadata {}
|
impl jsonrpc_core::Metadata for Metadata {}
|
||||||
impl PubSubMetadata for Metadata {
|
impl PubSubMetadata for Metadata {
|
||||||
fn session(&self) -> Option<Arc<Session>> {
|
fn session(&self) -> Option<Arc<Session>> {
|
||||||
|
@ -39,7 +39,6 @@ use v1::helpers::nonce;
|
|||||||
use v1::helpers::dispatch::FullDispatcher;
|
use v1::helpers::dispatch::FullDispatcher;
|
||||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
|
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
|
||||||
use v1::metadata::Metadata;
|
use v1::metadata::Metadata;
|
||||||
use v1::types::Origin;
|
|
||||||
|
|
||||||
fn blockchain_client() -> Arc<TestBlockChainClient> {
|
fn blockchain_client() -> Arc<TestBlockChainClient> {
|
||||||
let client = TestBlockChainClient::new();
|
let client = TestBlockChainClient::new();
|
||||||
@ -395,7 +394,6 @@ fn rpc_eth_gas_price() {
|
|||||||
fn rpc_eth_accounts() {
|
fn rpc_eth_accounts() {
|
||||||
let tester = EthTester::default();
|
let tester = EthTester::default();
|
||||||
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
|
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
|
||||||
tester.accounts_provider.set_new_dapps_addresses(None).unwrap();
|
|
||||||
tester.accounts_provider.set_address_name(1.into(), "1".into());
|
tester.accounts_provider.set_address_name(1.into(), "1".into());
|
||||||
tester.accounts_provider.set_address_name(10.into(), "10".into());
|
tester.accounts_provider.set_address_name(10.into(), "10".into());
|
||||||
|
|
||||||
@ -403,20 +401,6 @@ fn rpc_eth_accounts() {
|
|||||||
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:x}", address) + r#""],"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:x}", address) + r#""],"id":1}"#;
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
|
|
||||||
tester.accounts_provider.set_new_dapps_addresses(Some(vec![1.into()])).unwrap();
|
|
||||||
// even with some account it should return empty list (no dapp detected)
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
|
|
||||||
// when we add visible address it should return that.
|
|
||||||
tester.accounts_provider.set_dapp_addresses("app1".into(), Some(vec![10.into()])).unwrap();
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
|
|
||||||
let mut meta = Metadata::default();
|
|
||||||
meta.origin = Origin::Dapps("app1".into());
|
|
||||||
assert_eq!((*tester.io).handle_request_sync(request, meta), Some(response.to_owned()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -115,13 +115,6 @@ fn rpc_parity_accounts_info() {
|
|||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
|
||||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address);
|
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address);
|
||||||
assert_eq!(io.handle_request_sync(request), Some(response));
|
assert_eq!(io.handle_request_sync(request), Some(response));
|
||||||
|
|
||||||
// Change the whitelist
|
|
||||||
let address = Address::from(1);
|
|
||||||
deps.accounts.set_new_dapps_addresses(Some(vec![address.clone()])).unwrap();
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
|
|
||||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"XX\"}}}},\"id\":1}}", address);
|
|
||||||
assert_eq!(io.handle_request_sync(request), Some(response));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -121,106 +121,6 @@ fn should_be_able_to_set_meta() {
|
|||||||
assert_eq!(res, Some(response));
|
assert_eq!(res, Some(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rpc_parity_set_and_get_dapps_accounts() {
|
|
||||||
// given
|
|
||||||
let tester = setup();
|
|
||||||
tester.accounts.set_address_name(10.into(), "10".into());
|
|
||||||
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![]);
|
|
||||||
|
|
||||||
// when
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setDappAddresses","params":["app1",["0x000000000000000000000000000000000000000a","0x0000000000000000000000000000000000000001"]], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![10.into()]);
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getDappAddresses","params":["app1"], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rpc_parity_set_and_get_dapp_default_address() {
|
|
||||||
// given
|
|
||||||
let tester = setup();
|
|
||||||
tester.accounts.set_address_name(10.into(), "10".into());
|
|
||||||
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![]);
|
|
||||||
|
|
||||||
// when
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setDappDefaultAddress","params":["app1", "0x000000000000000000000000000000000000000a"], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![10.into()]);
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getDappDefaultAddress","params":["app1"], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000a","id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rpc_parity_set_and_get_new_dapps_whitelist() {
|
|
||||||
// given
|
|
||||||
let tester = setup();
|
|
||||||
|
|
||||||
// when set to whitelist
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsAddresses","params":[["0x000000000000000000000000000000000000000a"]], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(tester.accounts.new_dapps_addresses().unwrap(), Some(vec![10.into()]));
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsAddresses","params":[], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
|
|
||||||
// when set to empty
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsAddresses","params":[null], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(tester.accounts.new_dapps_addresses().unwrap(), None);
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsAddresses","params":[], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rpc_parity_set_and_get_new_dapps_default_address() {
|
|
||||||
// given
|
|
||||||
let tester = setup();
|
|
||||||
tester.accounts.set_address_name(10.into(), "10".into());
|
|
||||||
assert_eq!(tester.accounts.new_dapps_default_address().unwrap(), 0.into());
|
|
||||||
|
|
||||||
// when
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsDefaultAddress","params":["0x000000000000000000000000000000000000000a"], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(tester.accounts.new_dapps_default_address().unwrap(), 10.into());
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsDefaultAddress","params":[], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000a","id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rpc_parity_recent_dapps() {
|
|
||||||
// given
|
|
||||||
let tester = setup();
|
|
||||||
|
|
||||||
// when
|
|
||||||
// trigger dapp usage
|
|
||||||
tester.accounts.note_dapp_used("dapp1".into()).unwrap();
|
|
||||||
|
|
||||||
// then
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_listRecentDapps","params":[], "id": 1}"#;
|
|
||||||
let response = r#"{"jsonrpc":"2.0","result":{"dapp1":1},"id":1}"#;
|
|
||||||
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_be_able_to_kill_account() {
|
fn should_be_able_to_kill_account() {
|
||||||
let tester = setup();
|
let tester = setup();
|
||||||
|
@ -89,14 +89,14 @@ fn should_return_list_of_items_to_confirm() {
|
|||||||
data: vec![],
|
data: vec![],
|
||||||
nonce: None,
|
nonce: None,
|
||||||
condition: None,
|
condition: None,
|
||||||
}), Origin::Dapps("http://parity.io".into())).unwrap();
|
}), Origin::Unknown).unwrap();
|
||||||
let _sign_future = tester.signer.add_request(ConfirmationPayload::EthSignMessage(1.into(), vec![5].into()), Origin::Unknown).unwrap();
|
let _sign_future = tester.signer.add_request(ConfirmationPayload::EthSignMessage(1.into(), vec![5].into()), Origin::Unknown).unwrap();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
|
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
|
||||||
let response = concat!(
|
let response = concat!(
|
||||||
r#"{"jsonrpc":"2.0","result":["#,
|
r#"{"jsonrpc":"2.0","result":["#,
|
||||||
r#"{"id":"0x1","origin":{"dapp":"http://parity.io"},"payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
|
r#"{"id":"0x1","origin":"unknown","payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
|
||||||
r#"{"id":"0x2","origin":"unknown","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","data":"0x05"}}}"#,
|
r#"{"id":"0x2","origin":"unknown","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","data":"0x05"}}}"#,
|
||||||
r#"],"id":1}"#
|
r#"],"id":1}"#
|
||||||
);
|
);
|
||||||
|
@ -40,8 +40,8 @@ build_rpc_trait! {
|
|||||||
fn hashrate(&self) -> Result<U256>;
|
fn hashrate(&self) -> Result<U256>;
|
||||||
|
|
||||||
/// Returns block author.
|
/// Returns block author.
|
||||||
#[rpc(meta, name = "eth_coinbase")]
|
#[rpc(name = "eth_coinbase")]
|
||||||
fn author(&self, Self::Metadata) -> Result<H160>;
|
fn author(&self) -> Result<H160>;
|
||||||
|
|
||||||
/// Returns true if client is actively mining new blocks.
|
/// Returns true if client is actively mining new blocks.
|
||||||
#[rpc(name = "eth_mining")]
|
#[rpc(name = "eth_mining")]
|
||||||
@ -52,8 +52,8 @@ build_rpc_trait! {
|
|||||||
fn gas_price(&self) -> Result<U256>;
|
fn gas_price(&self) -> Result<U256>;
|
||||||
|
|
||||||
/// Returns accounts list.
|
/// Returns accounts list.
|
||||||
#[rpc(meta, name = "eth_accounts")]
|
#[rpc(name = "eth_accounts")]
|
||||||
fn accounts(&self, Self::Metadata) -> Result<Vec<H160>>;
|
fn accounts(&self) -> Result<Vec<H160>>;
|
||||||
|
|
||||||
/// Returns highest block number.
|
/// Returns highest block number.
|
||||||
#[rpc(name = "eth_blockNumber")]
|
#[rpc(name = "eth_blockNumber")]
|
||||||
@ -108,12 +108,12 @@ build_rpc_trait! {
|
|||||||
fn submit_transaction(&self, Bytes) -> Result<H256>;
|
fn submit_transaction(&self, Bytes) -> Result<H256>;
|
||||||
|
|
||||||
/// Call contract, returning the output data.
|
/// Call contract, returning the output data.
|
||||||
#[rpc(meta, name = "eth_call")]
|
#[rpc(name = "eth_call")]
|
||||||
fn call(&self, Self::Metadata, CallRequest, Trailing<BlockNumber>) -> BoxFuture<Bytes>;
|
fn call(&self, CallRequest, Trailing<BlockNumber>) -> BoxFuture<Bytes>;
|
||||||
|
|
||||||
/// Estimate gas needed for execution of given contract.
|
/// Estimate gas needed for execution of given contract.
|
||||||
#[rpc(meta, name = "eth_estimateGas")]
|
#[rpc(name = "eth_estimateGas")]
|
||||||
fn estimate_gas(&self, Self::Metadata, CallRequest, Trailing<BlockNumber>) -> BoxFuture<U256>;
|
fn estimate_gas(&self, CallRequest, Trailing<BlockNumber>) -> BoxFuture<U256>;
|
||||||
|
|
||||||
/// Get transaction by its hash.
|
/// Get transaction by its hash.
|
||||||
#[rpc(name = "eth_getTransactionByHash")]
|
#[rpc(name = "eth_getTransactionByHash")]
|
||||||
|
@ -26,7 +26,7 @@ use v1::types::{
|
|||||||
Peers, Transaction, RpcSettings, Histogram,
|
Peers, Transaction, RpcSettings, Histogram,
|
||||||
TransactionStats, LocalTransactionStatus,
|
TransactionStats, LocalTransactionStatus,
|
||||||
BlockNumber, ConsensusCapability, VersionInfo,
|
BlockNumber, ConsensusCapability, VersionInfo,
|
||||||
OperationsInfo, DappId, ChainStatus,
|
OperationsInfo, ChainStatus,
|
||||||
AccountInfo, HwAccountInfo, RichHeader,
|
AccountInfo, HwAccountInfo, RichHeader,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ build_rpc_trait! {
|
|||||||
|
|
||||||
/// Returns accounts information.
|
/// Returns accounts information.
|
||||||
#[rpc(name = "parity_accountsInfo")]
|
#[rpc(name = "parity_accountsInfo")]
|
||||||
fn accounts_info(&self, Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>>;
|
fn accounts_info(&self) -> Result<BTreeMap<H160, AccountInfo>>;
|
||||||
|
|
||||||
/// Returns hardware accounts information.
|
/// Returns hardware accounts information.
|
||||||
#[rpc(name = "parity_hardwareAccountsInfo")]
|
#[rpc(name = "parity_hardwareAccountsInfo")]
|
||||||
@ -48,8 +48,8 @@ build_rpc_trait! {
|
|||||||
fn locked_hardware_accounts_info(&self) -> Result<Vec<String>>;
|
fn locked_hardware_accounts_info(&self) -> Result<Vec<String>>;
|
||||||
|
|
||||||
/// Returns default account for dapp.
|
/// Returns default account for dapp.
|
||||||
#[rpc(meta, name = "parity_defaultAccount")]
|
#[rpc(name = "parity_defaultAccount")]
|
||||||
fn default_account(&self, Self::Metadata) -> Result<H160>;
|
fn default_account(&self) -> Result<H160>;
|
||||||
|
|
||||||
/// Returns current transactions limit.
|
/// Returns current transactions limit.
|
||||||
#[rpc(name = "parity_transactionsLimit")]
|
#[rpc(name = "parity_transactionsLimit")]
|
||||||
@ -216,7 +216,7 @@ build_rpc_trait! {
|
|||||||
fn ipfs_cid(&self, Bytes) -> Result<String>;
|
fn ipfs_cid(&self, Bytes) -> Result<String>;
|
||||||
|
|
||||||
/// Call contract, returning the output data.
|
/// Call contract, returning the output data.
|
||||||
#[rpc(meta, name = "parity_call")]
|
#[rpc(name = "parity_call")]
|
||||||
fn call(&self, Self::Metadata, Vec<CallRequest>, Trailing<BlockNumber>) -> Result<Vec<Bytes>>;
|
fn call(&self, Vec<CallRequest>, Trailing<BlockNumber>) -> Result<Vec<Bytes>>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use std::collections::BTreeMap;
|
|||||||
use jsonrpc_core::Result;
|
use jsonrpc_core::Result;
|
||||||
use ethkey::Password;
|
use ethkey::Password;
|
||||||
use ethstore::KeyFile;
|
use ethstore::KeyFile;
|
||||||
use v1::types::{H160, H256, H520, DappId, DeriveHash, DeriveHierarchical, ExtAccountInfo};
|
use v1::types::{H160, H256, H520, DeriveHash, DeriveHierarchical, ExtAccountInfo};
|
||||||
|
|
||||||
build_rpc_trait! {
|
build_rpc_trait! {
|
||||||
/// Personal Parity rpc interface.
|
/// Personal Parity rpc interface.
|
||||||
@ -72,57 +72,6 @@ build_rpc_trait! {
|
|||||||
#[rpc(name = "parity_setAccountMeta")]
|
#[rpc(name = "parity_setAccountMeta")]
|
||||||
fn set_account_meta(&self, H160, String) -> Result<bool>;
|
fn set_account_meta(&self, H160, String) -> Result<bool>;
|
||||||
|
|
||||||
/// Sets addresses exposed for particular dapp.
|
|
||||||
/// Setting a non-empty list will also override default account.
|
|
||||||
/// Setting `None` will resets visible account to what's visible for new dapps
|
|
||||||
/// (does not affect default account though)
|
|
||||||
#[rpc(name = "parity_setDappAddresses")]
|
|
||||||
fn set_dapp_addresses(&self, DappId, Option<Vec<H160>>) -> Result<bool>;
|
|
||||||
|
|
||||||
/// Gets accounts exposed for particular dapp.
|
|
||||||
#[rpc(name = "parity_getDappAddresses")]
|
|
||||||
fn dapp_addresses(&self, DappId) -> Result<Vec<H160>>;
|
|
||||||
|
|
||||||
/// Changes dapp default address.
|
|
||||||
/// Does not affect other accounts exposed for this dapp, but
|
|
||||||
/// default account will always be retured as the first one.
|
|
||||||
#[rpc(name = "parity_setDappDefaultAddress")]
|
|
||||||
fn set_dapp_default_address(&self, DappId, H160) -> Result<bool>;
|
|
||||||
|
|
||||||
/// Returns current dapp default address.
|
|
||||||
/// If not set explicite for the dapp will return global default.
|
|
||||||
#[rpc(name = "parity_getDappDefaultAddress")]
|
|
||||||
fn dapp_default_address(&self, DappId) -> Result<H160>;
|
|
||||||
|
|
||||||
/// Sets accounts exposed for new dapps.
|
|
||||||
/// Setting a non-empty list will also override default account.
|
|
||||||
/// Setting `None` exposes all internal-managed accounts.
|
|
||||||
/// (does not affect default account though)
|
|
||||||
#[rpc(name = "parity_setNewDappsAddresses")]
|
|
||||||
fn set_new_dapps_addresses(&self, Option<Vec<H160>>) -> Result<bool>;
|
|
||||||
|
|
||||||
/// Gets accounts exposed for new dapps.
|
|
||||||
/// `None` means that all accounts are exposes.
|
|
||||||
#[rpc(name = "parity_getNewDappsAddresses")]
|
|
||||||
fn new_dapps_addresses(&self) -> Result<Option<Vec<H160>>>;
|
|
||||||
|
|
||||||
/// Changes default address for new dapps (global default address)
|
|
||||||
/// Does not affect other accounts exposed for new dapps, but
|
|
||||||
/// default account will always be retured as the first one.
|
|
||||||
#[rpc(name = "parity_setNewDappsDefaultAddress")]
|
|
||||||
fn set_new_dapps_default_address(&self, H160) -> Result<bool>;
|
|
||||||
|
|
||||||
/// Returns current default address for new dapps (global default address)
|
|
||||||
/// In case it's not set explicite will return first available account.
|
|
||||||
/// If no accounts are available will return `0x0`
|
|
||||||
#[rpc(name = "parity_getNewDappsDefaultAddress")]
|
|
||||||
fn new_dapps_default_address(&self) -> Result<H160>;
|
|
||||||
|
|
||||||
/// Returns identified dapps that recently used RPC
|
|
||||||
/// Includes last usage timestamp.
|
|
||||||
#[rpc(name = "parity_listRecentDapps")]
|
|
||||||
fn recent_dapps(&self) -> Result<BTreeMap<DappId, u64>>;
|
|
||||||
|
|
||||||
/// Imports a number of Geth accounts, with the list provided as the argument.
|
/// Imports a number of Geth accounts, with the list provided as the argument.
|
||||||
#[rpc(name = "parity_importGethAccounts")]
|
#[rpc(name = "parity_importGethAccounts")]
|
||||||
fn import_geth_accounts(&self, Vec<H160>) -> Result<Vec<H160>>;
|
fn import_geth_accounts(&self, Vec<H160>) -> Result<Vec<H160>>;
|
||||||
|
@ -35,8 +35,8 @@ build_rpc_trait! {
|
|||||||
fn compose_deployment_transaction(&self, BlockNumber, Bytes, Vec<H160>, U256) -> Result<PrivateTransactionReceiptAndTransaction, Error>;
|
fn compose_deployment_transaction(&self, BlockNumber, Bytes, Vec<H160>, U256) -> Result<PrivateTransactionReceiptAndTransaction, Error>;
|
||||||
|
|
||||||
/// Make a call to the private contract
|
/// Make a call to the private contract
|
||||||
#[rpc(meta, name = "private_call")]
|
#[rpc(name = "private_call")]
|
||||||
fn private_call(&self, Self::Metadata, BlockNumber, CallRequest) -> Result<Bytes, Error>;
|
fn private_call(&self, BlockNumber, CallRequest) -> Result<Bytes, Error>;
|
||||||
|
|
||||||
/// Retrieve the id of the key associated with the contract
|
/// Retrieve the id of the key associated with the contract
|
||||||
#[rpc(name = "private_contractKey")]
|
#[rpc(name = "private_contractKey")]
|
||||||
|
@ -42,12 +42,12 @@ build_rpc_trait! {
|
|||||||
fn block_traces(&self, BlockNumber) -> Result<Option<Vec<LocalizedTrace>>>;
|
fn block_traces(&self, BlockNumber) -> Result<Option<Vec<LocalizedTrace>>>;
|
||||||
|
|
||||||
/// Executes the given call and returns a number of possible traces for it.
|
/// Executes the given call and returns a number of possible traces for it.
|
||||||
#[rpc(meta, name = "trace_call")]
|
#[rpc(name = "trace_call")]
|
||||||
fn call(&self, Self::Metadata, CallRequest, TraceOptions, Trailing<BlockNumber>) -> Result<TraceResults>;
|
fn call(&self, CallRequest, TraceOptions, Trailing<BlockNumber>) -> Result<TraceResults>;
|
||||||
|
|
||||||
/// Executes all given calls and returns a number of possible traces for each of it.
|
/// Executes all given calls and returns a number of possible traces for each of it.
|
||||||
#[rpc(meta, name = "trace_callMany")]
|
#[rpc(name = "trace_callMany")]
|
||||||
fn call_many(&self, Self::Metadata, Vec<(CallRequest, TraceOptions)>, Trailing<BlockNumber>) -> Result<Vec<TraceResults>>;
|
fn call_many(&self, Vec<(CallRequest, TraceOptions)>, Trailing<BlockNumber>) -> Result<Vec<TraceResults>>;
|
||||||
|
|
||||||
/// Executes the given raw transaction and returns a number of possible traces for it.
|
/// Executes the given raw transaction and returns a number of possible traces for it.
|
||||||
#[rpc(name = "trace_rawTransaction")]
|
#[rpc(name = "trace_rawTransaction")]
|
||||||
|
@ -285,14 +285,13 @@ mod tests {
|
|||||||
condition: None,
|
condition: None,
|
||||||
}),
|
}),
|
||||||
origin: Origin::Signer {
|
origin: Origin::Signer {
|
||||||
dapp: "http://parity.io".into(),
|
|
||||||
session: 5.into(),
|
session: 5.into(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res = serde_json::to_string(&ConfirmationRequest::from(request));
|
let res = serde_json::to_string(&ConfirmationRequest::from(request));
|
||||||
let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"dapp":"http://parity.io","session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#;
|
let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#;
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(res.unwrap(), expected.to_owned());
|
assert_eq!(res.unwrap(), expected.to_owned());
|
||||||
@ -314,12 +313,12 @@ mod tests {
|
|||||||
nonce: Some(1.into()),
|
nonce: Some(1.into()),
|
||||||
condition: None,
|
condition: None,
|
||||||
}),
|
}),
|
||||||
origin: Origin::Dapps("http://parity.io".into()),
|
origin: Origin::Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res = serde_json::to_string(&ConfirmationRequest::from(request));
|
let res = serde_json::to_string(&ConfirmationRequest::from(request));
|
||||||
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"dapp":"http://parity.io"}}"#;
|
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":"unknown"}"#;
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(res.unwrap(), expected.to_owned());
|
assert_eq!(res.unwrap(), expected.to_owned());
|
||||||
|
@ -63,7 +63,7 @@ pub use self::histogram::Histogram;
|
|||||||
pub use self::index::Index;
|
pub use self::index::Index;
|
||||||
pub use self::log::Log;
|
pub use self::log::Log;
|
||||||
pub use self::node_kind::{NodeKind, Availability, Capability};
|
pub use self::node_kind::{NodeKind, Availability, Capability};
|
||||||
pub use self::provenance::{Origin, DappId};
|
pub use self::provenance::Origin;
|
||||||
pub use self::receipt::Receipt;
|
pub use self::receipt::Receipt;
|
||||||
pub use self::rpc_settings::RpcSettings;
|
pub use self::rpc_settings::RpcSettings;
|
||||||
pub use self::secretstore::EncryptedDocumentKey;
|
pub use self::secretstore::EncryptedDocumentKey;
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
//! Request Provenance
|
//! Request Provenance
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use ethcore::account_provider::DappId as EthDappId;
|
|
||||||
use v1::types::H256;
|
use v1::types::H256;
|
||||||
|
|
||||||
/// RPC request origin
|
/// RPC request origin
|
||||||
@ -27,25 +26,18 @@ pub enum Origin {
|
|||||||
/// RPC server (includes request origin)
|
/// RPC server (includes request origin)
|
||||||
#[serde(rename="rpc")]
|
#[serde(rename="rpc")]
|
||||||
Rpc(String),
|
Rpc(String),
|
||||||
/// Dapps server (includes DappId)
|
|
||||||
#[serde(rename="dapp")]
|
|
||||||
Dapps(DappId),
|
|
||||||
/// IPC server (includes session hash)
|
/// IPC server (includes session hash)
|
||||||
#[serde(rename="ipc")]
|
#[serde(rename="ipc")]
|
||||||
Ipc(H256),
|
Ipc(H256),
|
||||||
/// WS server
|
/// WS server
|
||||||
#[serde(rename="ws")]
|
#[serde(rename="ws")]
|
||||||
Ws {
|
Ws {
|
||||||
/// Dapp id
|
|
||||||
dapp: DappId,
|
|
||||||
/// Session id
|
/// Session id
|
||||||
session: H256,
|
session: H256,
|
||||||
},
|
},
|
||||||
/// Signer (authorized WS server)
|
/// Signer (authorized WS server)
|
||||||
#[serde(rename="signer")]
|
#[serde(rename="signer")]
|
||||||
Signer {
|
Signer {
|
||||||
/// Dapp id
|
|
||||||
dapp: DappId,
|
|
||||||
/// Session id
|
/// Session id
|
||||||
session: H256
|
session: H256
|
||||||
},
|
},
|
||||||
@ -67,80 +59,35 @@ impl fmt::Display for Origin {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Origin::Rpc(ref origin) => write!(f, "{} via RPC", origin),
|
Origin::Rpc(ref origin) => write!(f, "{} via RPC", origin),
|
||||||
Origin::Dapps(ref origin) => write!(f, "Dapp {}", origin),
|
|
||||||
Origin::Ipc(ref session) => write!(f, "IPC (session: {})", session),
|
Origin::Ipc(ref session) => write!(f, "IPC (session: {})", session),
|
||||||
Origin::Ws { ref session, ref dapp } => write!(f, "{} via WebSocket (session: {})", dapp, session),
|
Origin::Ws { ref session } => write!(f, "WebSocket (session: {})", session),
|
||||||
Origin::Signer { ref session, ref dapp } => write!(f, "{} via UI (session: {})", dapp, session),
|
Origin::Signer { ref session } => write!(f, "Secure Session (session: {})", session),
|
||||||
Origin::CApi => write!(f, "C API"),
|
Origin::CApi => write!(f, "C API"),
|
||||||
Origin::Unknown => write!(f, "unknown origin"),
|
Origin::Unknown => write!(f, "unknown origin"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dapplication Internal Id
|
|
||||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
|
|
||||||
pub struct DappId(pub String);
|
|
||||||
|
|
||||||
impl fmt::Display for DappId {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<String> for DappId {
|
|
||||||
fn into(self) -> String {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for DappId {
|
|
||||||
fn from(s: String) -> Self {
|
|
||||||
DappId(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a str> for DappId {
|
|
||||||
fn from(s: &'a str) -> Self {
|
|
||||||
DappId(s.to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<EthDappId> for DappId {
|
|
||||||
fn from(id: EthDappId) -> Self {
|
|
||||||
DappId(id.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<EthDappId> for DappId {
|
|
||||||
fn into(self) -> EthDappId {
|
|
||||||
Into::<String>::into(self).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use super::{DappId, Origin};
|
use super::Origin;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_serialize_origin() {
|
fn should_serialize_origin() {
|
||||||
// given
|
// given
|
||||||
let o1 = Origin::Rpc("test service".into());
|
let o1 = Origin::Rpc("test service".into());
|
||||||
let o2 = Origin::Dapps("http://parity.io".into());
|
|
||||||
let o3 = Origin::Ipc(5.into());
|
let o3 = Origin::Ipc(5.into());
|
||||||
let o4 = Origin::Signer {
|
let o4 = Origin::Signer {
|
||||||
dapp: "http://parity.io".into(),
|
|
||||||
session: 10.into(),
|
session: 10.into(),
|
||||||
};
|
};
|
||||||
let o5 = Origin::Unknown;
|
let o5 = Origin::Unknown;
|
||||||
let o6 = Origin::Ws {
|
let o6 = Origin::Ws {
|
||||||
dapp: "http://parity.io".into(),
|
|
||||||
session: 5.into(),
|
session: 5.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res1 = serde_json::to_string(&o1).unwrap();
|
let res1 = serde_json::to_string(&o1).unwrap();
|
||||||
let res2 = serde_json::to_string(&o2).unwrap();
|
|
||||||
let res3 = serde_json::to_string(&o3).unwrap();
|
let res3 = serde_json::to_string(&o3).unwrap();
|
||||||
let res4 = serde_json::to_string(&o4).unwrap();
|
let res4 = serde_json::to_string(&o4).unwrap();
|
||||||
let res5 = serde_json::to_string(&o5).unwrap();
|
let res5 = serde_json::to_string(&o5).unwrap();
|
||||||
@ -148,34 +95,9 @@ mod tests {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(res1, r#"{"rpc":"test service"}"#);
|
assert_eq!(res1, r#"{"rpc":"test service"}"#);
|
||||||
assert_eq!(res2, r#"{"dapp":"http://parity.io"}"#);
|
|
||||||
assert_eq!(res3, r#"{"ipc":"0x0000000000000000000000000000000000000000000000000000000000000005"}"#);
|
assert_eq!(res3, r#"{"ipc":"0x0000000000000000000000000000000000000000000000000000000000000005"}"#);
|
||||||
assert_eq!(res4, r#"{"signer":{"dapp":"http://parity.io","session":"0x000000000000000000000000000000000000000000000000000000000000000a"}}"#);
|
assert_eq!(res4, r#"{"signer":{"session":"0x000000000000000000000000000000000000000000000000000000000000000a"}}"#);
|
||||||
assert_eq!(res5, r#""unknown""#);
|
assert_eq!(res5, r#""unknown""#);
|
||||||
assert_eq!(res6, r#"{"ws":{"dapp":"http://parity.io","session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}"#);
|
assert_eq!(res6, r#"{"ws":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}"#);
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_serialize_dapp_id() {
|
|
||||||
// given
|
|
||||||
let id = DappId("testapp".into());
|
|
||||||
|
|
||||||
// when
|
|
||||||
let res = serde_json::to_string(&id).unwrap();
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(res, r#""testapp""#);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn should_deserialize_dapp_id() {
|
|
||||||
// given
|
|
||||||
let id = r#""testapp""#;
|
|
||||||
|
|
||||||
// when
|
|
||||||
let res: DappId = serde_json::from_str(id).unwrap();
|
|
||||||
|
|
||||||
// then
|
|
||||||
assert_eq!(res, DappId("testapp".into()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user