Deduplicate registrar contract & calling logic (#11110)
* Rename RegistryInfo -> RegistryInfoDeprecated * Add BlockId parameter to Registrar::get_address and RegistrarClient::call_contract * Remove RegistrarClient::Call (use async for now); add RegistrarClient::get_address * Remove Registrar type in favour of naked trait * Use CallContract trait bound instead of separate call_contract method * Make RegistrarClient::get_address and URLHint::resolve synchronous * RegistrarClient::get_address: return check if address is zero * Modify RegistryInfo::registry_address to take &str * return Result from RegistryInfo::registry_address * Replace RegistryInfo with RegistrarClient - Modifed RegistrarClient::registrar_address to return Option - Removed BlockChainClient::registrar_address * Fix other build configs * Fix unit test builds * Remove local RegistrarClient type from run::execute_impl * Remove registrar.json from ethcore * Formatting/line breaks * Update RegistrarClient docs, remove explicit lifetime * Weak ref to ethcore client from hash fetch client * Fix unit tests
This commit is contained in:
parent
0c0f965354
commit
79a17dedd0
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -510,6 +510,7 @@ dependencies = [
|
|||||||
"ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"registrar 0.0.1",
|
||||||
"stats 0.1.0",
|
"stats 0.1.0",
|
||||||
"trace 0.1.0",
|
"trace 0.1.0",
|
||||||
"vm 0.1.0",
|
"vm 0.1.0",
|
||||||
@ -1014,9 +1015,6 @@ dependencies = [
|
|||||||
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"engine 0.1.0",
|
"engine 0.1.0",
|
||||||
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"ethabi-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"ethash 1.12.0",
|
"ethash 1.12.0",
|
||||||
"ethcore-accounts 0.1.0",
|
"ethcore-accounts 0.1.0",
|
||||||
"ethcore-blockchain 0.1.0",
|
"ethcore-blockchain 0.1.0",
|
||||||
@ -1052,6 +1050,7 @@ dependencies = [
|
|||||||
"pod 0.1.0",
|
"pod 0.1.0",
|
||||||
"rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"registrar 0.0.1",
|
||||||
"rlp 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rlp 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1270,6 +1269,7 @@ dependencies = [
|
|||||||
"parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"price-info 1.12.0",
|
"price-info 1.12.0",
|
||||||
|
"registrar 0.0.1",
|
||||||
"rlp 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rlp 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1368,6 +1368,7 @@ dependencies = [
|
|||||||
"parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"patricia-trie-ethereum 0.1.0",
|
"patricia-trie-ethereum 0.1.0",
|
||||||
|
"registrar 0.0.1",
|
||||||
"rlp 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rlp 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rlp_derive 0.1.0",
|
"rlp_derive 0.1.0",
|
||||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1415,6 +1416,7 @@ dependencies = [
|
|||||||
"parity-runtime 0.1.0",
|
"parity-runtime 0.1.0",
|
||||||
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"registrar 0.0.1",
|
||||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2966,7 +2968,6 @@ dependencies = [
|
|||||||
"ethcore 1.12.0",
|
"ethcore 1.12.0",
|
||||||
"ethcore-accounts 0.1.0",
|
"ethcore-accounts 0.1.0",
|
||||||
"ethcore-blockchain 0.1.0",
|
"ethcore-blockchain 0.1.0",
|
||||||
"ethcore-call-contract 0.1.0",
|
|
||||||
"ethcore-db 0.1.0",
|
"ethcore-db 0.1.0",
|
||||||
"ethcore-io 1.12.0",
|
"ethcore-io 1.12.0",
|
||||||
"ethcore-light 1.12.0",
|
"ethcore-light 1.12.0",
|
||||||
@ -3032,9 +3033,11 @@ dependencies = [
|
|||||||
name = "parity-hash-fetch"
|
name = "parity-hash-fetch"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"common-types 0.1.0",
|
||||||
"ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethabi-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ethcore-call-contract 0.1.0",
|
||||||
"ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fake-fetch 0.0.1",
|
"fake-fetch 0.0.1",
|
||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
@ -3854,10 +3857,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
name = "registrar"
|
name = "registrar"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"common-types 0.1.0",
|
||||||
"ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethabi-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi-derive 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethcore-call-contract 0.1.0",
|
||||||
"keccak-hash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"keccak-hash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ engine = { path = "ethcore/engine" }
|
|||||||
ethcore = { path = "ethcore", features = ["parity"] }
|
ethcore = { path = "ethcore", features = ["parity"] }
|
||||||
ethcore-accounts = { path = "accounts", optional = true }
|
ethcore-accounts = { path = "accounts", optional = true }
|
||||||
ethcore-blockchain = { path = "ethcore/blockchain" }
|
ethcore-blockchain = { path = "ethcore/blockchain" }
|
||||||
ethcore-call-contract = { path = "ethcore/call-contract"}
|
|
||||||
ethcore-db = { path = "ethcore/db" }
|
ethcore-db = { path = "ethcore/db" }
|
||||||
ethcore-io = { path = "util/io" }
|
ethcore-io = { path = "util/io" }
|
||||||
ethcore-light = { path = "ethcore/light" }
|
ethcore-light = { path = "ethcore/light" }
|
||||||
|
@ -15,9 +15,6 @@ client-traits = { path = "./client-traits" }
|
|||||||
common-types = { path = "types" }
|
common-types = { path = "types" }
|
||||||
engine = { path = "./engine" }
|
engine = { path = "./engine" }
|
||||||
env_logger = { version = "0.5", optional = true }
|
env_logger = { version = "0.5", optional = true }
|
||||||
ethabi = "8.0"
|
|
||||||
ethabi-contract = "8.0"
|
|
||||||
ethabi-derive = "8.0"
|
|
||||||
ethash = { path = "../ethash", optional = true }
|
ethash = { path = "../ethash", optional = true }
|
||||||
ethjson = { path = "../json", optional = true }
|
ethjson = { path = "../json", optional = true }
|
||||||
ethkey = { path = "../accounts/ethkey", optional = true }
|
ethkey = { path = "../accounts/ethkey", optional = true }
|
||||||
@ -50,6 +47,7 @@ trie-db = "0.15.0"
|
|||||||
patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" }
|
patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" }
|
||||||
rand = "0.6"
|
rand = "0.6"
|
||||||
rayon = "1.1"
|
rayon = "1.1"
|
||||||
|
registrar = { path = "../util/registrar" }
|
||||||
rlp = "0.4.0"
|
rlp = "0.4.0"
|
||||||
rustc-hex = "2"
|
rustc-hex = "2"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Provides CallContract and RegistryInfo traits
|
//! Provides CallContract trait
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use ethereum_types::Address;
|
use ethereum_types::Address;
|
||||||
@ -23,11 +23,10 @@ use types::ids::BlockId;
|
|||||||
/// Provides `call_contract` method
|
/// Provides `call_contract` method
|
||||||
pub trait CallContract {
|
pub trait CallContract {
|
||||||
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
|
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
|
||||||
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
|
fn call_contract(
|
||||||
}
|
&self,
|
||||||
|
block_id: BlockId,
|
||||||
/// Provides information on a blockchain service and it's registry
|
address: Address,
|
||||||
pub trait RegistryInfo {
|
data: Bytes
|
||||||
/// Get the address of a particular blockchain service, if available.
|
) -> Result<Bytes, String>;
|
||||||
fn registry_address(&self, name: String, block: BlockId) -> Option<Address>;
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ ethcore-db = { path = "../db" }
|
|||||||
ethcore-miner = { path = "../../miner" }
|
ethcore-miner = { path = "../../miner" }
|
||||||
ethereum-types = "0.6.0"
|
ethereum-types = "0.6.0"
|
||||||
kvdb = "0.1"
|
kvdb = "0.1"
|
||||||
|
registrar = { path = "../../util/registrar" }
|
||||||
stats = { path = "../../util/stats" }
|
stats = { path = "../../util/stats" }
|
||||||
trace = { path = "../trace" }
|
trace = { path = "../trace" }
|
||||||
vm = { path = "../vm" }
|
vm = { path = "../vm" }
|
||||||
|
@ -22,7 +22,8 @@ use std::{
|
|||||||
use account_state::state::StateInfo;
|
use account_state::state::StateInfo;
|
||||||
use blockchain::BlockProvider;
|
use blockchain::BlockProvider;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use call_contract::{CallContract, RegistryInfo};
|
use call_contract::CallContract;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
use common_types::{
|
use common_types::{
|
||||||
basic_account::BasicAccount,
|
basic_account::BasicAccount,
|
||||||
block_status::BlockStatus,
|
block_status::BlockStatus,
|
||||||
@ -218,8 +219,10 @@ pub trait BadBlocks {
|
|||||||
|
|
||||||
|
|
||||||
/// Blockchain database client. Owns and manages a blockchain and a block queue.
|
/// Blockchain database client. Owns and manages a blockchain and a block queue.
|
||||||
pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock
|
pub trait BlockChainClient:
|
||||||
+ IoClient + BadBlocks {
|
Sync + Send + AccountData + BlockChain + CallContract + RegistrarClient
|
||||||
|
+ ImportBlock + IoClient + BadBlocks
|
||||||
|
{
|
||||||
/// Look up the block number for the given block ID.
|
/// Look up the block number for the given block ID.
|
||||||
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
|
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
|
||||||
|
|
||||||
@ -393,9 +396,6 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
|
|||||||
|
|
||||||
/// Schedule state-altering transaction to be executed on the next pending block.
|
/// Schedule state-altering transaction to be executed on the next pending block.
|
||||||
fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error>;
|
fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error>;
|
||||||
|
|
||||||
/// Get the address of the registry itself.
|
|
||||||
fn registrar_address(&self) -> Option<Address>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resets the blockchain
|
/// resets the blockchain
|
||||||
|
@ -36,6 +36,7 @@ parity-crypto = "0.4.0"
|
|||||||
parking_lot = "0.9"
|
parking_lot = "0.9"
|
||||||
trie-db = "0.15.0"
|
trie-db = "0.15.0"
|
||||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
||||||
|
registrar = { path = "../../util/registrar" }
|
||||||
rlp = "0.4.0"
|
rlp = "0.4.0"
|
||||||
rlp_derive = { path = "../../util/rlp-derive" }
|
rlp_derive = { path = "../../util/rlp-derive" }
|
||||||
rustc-hex = "1.0"
|
rustc-hex = "1.0"
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use ethereum_types::{H256, Address};
|
use ethereum_types::{H256, Address};
|
||||||
use call_contract::{CallContract, RegistryInfo};
|
use call_contract::CallContract;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
use types::ids::BlockId;
|
use types::ids::BlockId;
|
||||||
use ethabi::FunctionOutputDecoder;
|
use ethabi::FunctionOutputDecoder;
|
||||||
|
|
||||||
@ -53,13 +54,13 @@ pub trait KeyProvider: Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Secret Store keys provider
|
/// Secret Store keys provider
|
||||||
pub struct SecretStoreKeys<C> where C: CallContract + RegistryInfo + Send + Sync + 'static {
|
pub struct SecretStoreKeys<C> where C: CallContract + RegistrarClient + Send + Sync + 'static {
|
||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
key_server_account: Option<Address>,
|
key_server_account: Option<Address>,
|
||||||
keys_acl_contract: RwLock<Option<Address>>,
|
keys_acl_contract: RwLock<Option<Address>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> SecretStoreKeys<C> where C: CallContract + RegistryInfo + Send + Sync + 'static {
|
impl<C> SecretStoreKeys<C> where C: CallContract + RegistrarClient + Send + Sync + 'static {
|
||||||
/// Create provider
|
/// Create provider
|
||||||
pub fn new(client: Arc<C>, key_server_account: Option<Address>) -> Self {
|
pub fn new(client: Arc<C>, key_server_account: Option<Address>) -> Self {
|
||||||
SecretStoreKeys {
|
SecretStoreKeys {
|
||||||
@ -70,7 +71,9 @@ impl<C> SecretStoreKeys<C> where C: CallContract + RegistryInfo + Send + Sync +
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> KeyProvider for SecretStoreKeys<C> where C: CallContract + RegistryInfo + Send + Sync + 'static {
|
impl<C> KeyProvider for SecretStoreKeys<C>
|
||||||
|
where C: CallContract + RegistrarClient + Send + Sync + 'static
|
||||||
|
{
|
||||||
fn key_server_account(&self) -> Option<Address> {
|
fn key_server_account(&self) -> Option<Address> {
|
||||||
self.key_server_account
|
self.key_server_account
|
||||||
}
|
}
|
||||||
@ -92,7 +95,11 @@ impl<C> KeyProvider for SecretStoreKeys<C> where C: CallContract + RegistryInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_acl_contract(&self) {
|
fn update_acl_contract(&self) {
|
||||||
let contract_address = self.client.registry_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.into(), BlockId::Latest);
|
let contract_address = self.client.get_address(
|
||||||
|
ACL_CHECKER_CONTRACT_REGISTRY_NAME,
|
||||||
|
BlockId::Latest
|
||||||
|
).unwrap_or(None);
|
||||||
|
|
||||||
if *self.keys_acl_contract.read() != contract_address {
|
if *self.keys_acl_contract.read() != contract_address {
|
||||||
trace!(target: "privatetx", "Configuring for ACL checker contract from address {:?}",
|
trace!(target: "privatetx", "Configuring for ACL checker contract from address {:?}",
|
||||||
contract_address);
|
contract_address);
|
||||||
@ -141,6 +148,7 @@ mod tests {
|
|||||||
use ethkey::{Secret, KeyPair};
|
use ethkey::{Secret, KeyPair};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
|
|
||||||
struct DummyRegistryClient {
|
struct DummyRegistryClient {
|
||||||
registry_address: Option<Address>,
|
registry_address: Option<Address>,
|
||||||
@ -154,12 +162,25 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegistryInfo for DummyRegistryClient {
|
impl RegistrarClient for DummyRegistryClient {
|
||||||
fn registry_address(&self, _name: String, _block: BlockId) -> Option<Address> { self.registry_address }
|
fn registrar_address(&self) -> Option<Address> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_address(&self, _name: &str, _block: BlockId) -> Result<Option<Address>, String> {
|
||||||
|
Ok(self.registry_address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallContract for DummyRegistryClient {
|
impl CallContract for DummyRegistryClient {
|
||||||
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
|
fn call_contract(
|
||||||
|
&self,
|
||||||
|
_block_id: BlockId,
|
||||||
|
_address: Address,
|
||||||
|
_data: Bytes
|
||||||
|
) -> Result<Bytes, String> {
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -51,6 +51,7 @@ extern crate parity_crypto as crypto;
|
|||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate trie_db as trie;
|
extern crate trie_db as trie;
|
||||||
extern crate patricia_trie_ethereum as ethtrie;
|
extern crate patricia_trie_ethereum as ethtrie;
|
||||||
|
extern crate registrar;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
[
|
|
||||||
{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"set","outputs":[{"name":"success","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},
|
|
||||||
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[],"name":"drain","outputs":[],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"type":"function"},
|
|
||||||
{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"type":"function"},
|
|
||||||
{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"type":"function"},
|
|
||||||
{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"type":"function"},
|
|
||||||
{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Drained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"oldOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Dropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"key","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}
|
|
||||||
]
|
|
@ -51,7 +51,7 @@ use blockchain::{
|
|||||||
TransactionAddress,
|
TransactionAddress,
|
||||||
TreeRoute
|
TreeRoute
|
||||||
};
|
};
|
||||||
use call_contract::{CallContract, RegistryInfo};
|
use call_contract::CallContract;
|
||||||
use client::{
|
use client::{
|
||||||
bad_blocks, BlockProducer, BroadcastProposalBlock, Call,
|
bad_blocks, BlockProducer, BroadcastProposalBlock, Call,
|
||||||
ClientConfig, EngineInfo, ImportSealedBlock, PrepareOpenBlock,
|
ClientConfig, EngineInfo, ImportSealedBlock, PrepareOpenBlock,
|
||||||
@ -95,6 +95,7 @@ use machine::{
|
|||||||
transaction_ext::Transaction,
|
transaction_ext::Transaction,
|
||||||
};
|
};
|
||||||
use miner::{Miner, MinerService, PendingOrdering};
|
use miner::{Miner, MinerService, PendingOrdering};
|
||||||
|
use registrar::RegistrarClient;
|
||||||
use snapshot::{self, SnapshotClient, SnapshotWriter};
|
use snapshot::{self, SnapshotClient, SnapshotWriter};
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use state_db::StateDB;
|
use state_db::StateDB;
|
||||||
@ -138,8 +139,6 @@ use verification;
|
|||||||
use verification::queue::kind::BlockLike;
|
use verification::queue::kind::BlockLike;
|
||||||
use vm::{CreateContractAddress, EnvInfo, LastHashes};
|
use vm::{CreateContractAddress, EnvInfo, LastHashes};
|
||||||
|
|
||||||
use_contract!(registry, "res/contracts/registrar.json");
|
|
||||||
|
|
||||||
const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096;
|
const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096;
|
||||||
// Max number of blocks imported at once.
|
// Max number of blocks imported at once.
|
||||||
const MAX_ANCIENT_BLOCKS_TO_IMPORT: usize = 4;
|
const MAX_ANCIENT_BLOCKS_TO_IMPORT: usize = 4;
|
||||||
@ -1415,22 +1414,6 @@ impl TransactionInfo for Client {
|
|||||||
|
|
||||||
impl BlockChainTrait for Client {}
|
impl BlockChainTrait for Client {}
|
||||||
|
|
||||||
impl RegistryInfo for Client {
|
|
||||||
fn registry_address(&self, name: String, block: BlockId) -> Option<Address> {
|
|
||||||
use ethabi::FunctionOutputDecoder;
|
|
||||||
|
|
||||||
let address = self.registrar_address?;
|
|
||||||
|
|
||||||
let (data, decoder) = registry::functions::get_address::call(keccak(name.as_bytes()), "A");
|
|
||||||
let value = decoder.decode(&self.call_contract(block, address, data).ok()?).ok()?;
|
|
||||||
if value.is_zero() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CallContract for Client {
|
impl CallContract for Client {
|
||||||
fn call_contract(&self, block_id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String> {
|
fn call_contract(&self, block_id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String> {
|
||||||
let state_pruned = || CallError::StatePruned.to_string();
|
let state_pruned = || CallError::StatePruned.to_string();
|
||||||
@ -1445,6 +1428,12 @@ impl CallContract for Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RegistrarClient for Client {
|
||||||
|
fn registrar_address(&self) -> Option<Address> {
|
||||||
|
self.registrar_address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ImportBlock for Client {
|
impl ImportBlock for Client {
|
||||||
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
|
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
|
||||||
if self.chain.read().is_known(&unverified.hash()) {
|
if self.chain.read().is_known(&unverified.hash()) {
|
||||||
@ -2178,10 +2167,6 @@ impl BlockChainClient for Client {
|
|||||||
let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?;
|
let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?;
|
||||||
self.importer.miner.import_own_transaction(self, signed.into())
|
self.importer.miner.import_own_transaction(self, signed.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn registrar_address(&self) -> Option<Address> {
|
|
||||||
self.registrar_address.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IoClient for Client {
|
impl IoClient for Client {
|
||||||
|
@ -23,7 +23,6 @@ extern crate ansi_term;
|
|||||||
extern crate client_traits;
|
extern crate client_traits;
|
||||||
extern crate common_types as types;
|
extern crate common_types as types;
|
||||||
extern crate engine;
|
extern crate engine;
|
||||||
extern crate ethabi;
|
|
||||||
extern crate ethcore_blockchain as blockchain;
|
extern crate ethcore_blockchain as blockchain;
|
||||||
extern crate ethcore_call_contract as call_contract;
|
extern crate ethcore_call_contract as call_contract;
|
||||||
extern crate ethcore_db as db;
|
extern crate ethcore_db as db;
|
||||||
@ -45,6 +44,7 @@ extern crate trie_db as trie;
|
|||||||
extern crate patricia_trie_ethereum as ethtrie;
|
extern crate patricia_trie_ethereum as ethtrie;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate rayon;
|
extern crate rayon;
|
||||||
|
extern crate registrar;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
@ -97,8 +97,6 @@ extern crate serde_json;
|
|||||||
#[cfg(any(test, feature = "tempdir"))]
|
#[cfg(any(test, feature = "tempdir"))]
|
||||||
extern crate tempdir;
|
extern crate tempdir;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate ethabi_contract;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -46,7 +46,8 @@ use types::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use block::SealedBlock;
|
use block::SealedBlock;
|
||||||
use call_contract::{CallContract, RegistryInfo};
|
use call_contract::CallContract;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
use client::{BlockProducer, SealedBlockImporter};
|
use client::{BlockProducer, SealedBlockImporter};
|
||||||
use client_traits::{BlockChain, ChainInfo, AccountData, Nonce, ScheduleInfo};
|
use client_traits::{BlockChain, ChainInfo, AccountData, Nonce, ScheduleInfo};
|
||||||
use account_state::state::StateInfo;
|
use account_state::state::StateInfo;
|
||||||
@ -54,7 +55,7 @@ use account_state::state::StateInfo;
|
|||||||
/// Provides methods to verify incoming external transactions
|
/// Provides methods to verify incoming external transactions
|
||||||
pub trait TransactionVerifierClient: Send + Sync
|
pub trait TransactionVerifierClient: Send + Sync
|
||||||
// Required for ServiceTransactionChecker
|
// Required for ServiceTransactionChecker
|
||||||
+ CallContract + RegistryInfo
|
+ CallContract + RegistrarClient
|
||||||
// Required for verifiying transactions
|
// Required for verifiying transactions
|
||||||
+ BlockChain + ScheduleInfo + AccountData
|
+ BlockChain + ScheduleInfo + AccountData
|
||||||
{}
|
{}
|
||||||
|
@ -63,7 +63,8 @@ use types::{
|
|||||||
use vm::{Schedule, LastHashes};
|
use vm::{Schedule, LastHashes};
|
||||||
|
|
||||||
use block::{OpenBlock, SealedBlock, ClosedBlock};
|
use block::{OpenBlock, SealedBlock, ClosedBlock};
|
||||||
use call_contract::{CallContract, RegistryInfo};
|
use call_contract::CallContract;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
use client::{
|
use client::{
|
||||||
ReopenBlock, PrepareOpenBlock, ImportSealedBlock, BroadcastProposalBlock, Call,
|
ReopenBlock, PrepareOpenBlock, ImportSealedBlock, BroadcastProposalBlock, Call,
|
||||||
EngineInfo, BlockProducer, SealedBlockImporter,
|
EngineInfo, BlockProducer, SealedBlockImporter,
|
||||||
@ -532,7 +533,20 @@ impl BlockInfo for TestBlockChainClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CallContract for TestBlockChainClient {
|
impl CallContract for TestBlockChainClient {
|
||||||
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
|
fn call_contract(
|
||||||
|
&self,
|
||||||
|
_block_id: BlockId,
|
||||||
|
_address: Address,
|
||||||
|
_data: Bytes
|
||||||
|
) -> Result<Bytes, String> {
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegistrarClient for TestBlockChainClient {
|
||||||
|
fn registrar_address(&self) -> Option<Address> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TransactionInfo for TestBlockChainClient {
|
impl TransactionInfo for TestBlockChainClient {
|
||||||
@ -543,10 +557,6 @@ impl TransactionInfo for TestBlockChainClient {
|
|||||||
|
|
||||||
impl BlockChain for TestBlockChainClient {}
|
impl BlockChain for TestBlockChainClient {}
|
||||||
|
|
||||||
impl RegistryInfo for TestBlockChainClient {
|
|
||||||
fn registry_address(&self, _name: String, _block: BlockId) -> Option<Address> { None }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImportBlock for TestBlockChainClient {
|
impl ImportBlock for TestBlockChainClient {
|
||||||
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
|
fn import_block(&self, unverified: Unverified) -> EthcoreResult<H256> {
|
||||||
let header = unverified.header;
|
let header = unverified.header;
|
||||||
@ -916,8 +926,6 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
let signed = SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap();
|
let signed = SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap();
|
||||||
self.miner.import_own_transaction(self, signed.into())
|
self.miner.import_own_transaction(self, signed.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn registrar_address(&self) -> Option<Address> { None }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IoClient for TestBlockChainClient {
|
impl IoClient for TestBlockChainClient {
|
||||||
|
@ -48,6 +48,7 @@ use test_helpers::{
|
|||||||
generate_dummy_client_with_data, get_good_dummy_block, get_bad_state_dummy_block
|
generate_dummy_client_with_data, get_good_dummy_block, get_bad_state_dummy_block
|
||||||
};
|
};
|
||||||
use rustc_hex::ToHex;
|
use rustc_hex::ToHex;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn imports_from_empty() {
|
fn imports_from_empty() {
|
||||||
|
@ -29,6 +29,7 @@ log = "0.4"
|
|||||||
parity-runtime = { path = "../util/runtime" }
|
parity-runtime = { path = "../util/runtime" }
|
||||||
parking_lot = "0.9"
|
parking_lot = "0.9"
|
||||||
price-info = { path = "./price-info", optional = true }
|
price-info = { path = "./price-info", optional = true }
|
||||||
|
registrar = { path = "../util/registrar" }
|
||||||
rlp = "0.4.0"
|
rlp = "0.4.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
@ -33,6 +33,7 @@ extern crate parity_runtime;
|
|||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
#[cfg(feature = "price-info")]
|
#[cfg(feature = "price-info")]
|
||||||
extern crate price_info;
|
extern crate price_info;
|
||||||
|
extern crate registrar;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate transaction_pool as txpool;
|
extern crate transaction_pool as txpool;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use call_contract::{RegistryInfo, CallContract};
|
use call_contract::CallContract;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
use types::ids::BlockId;
|
use types::ids::BlockId;
|
||||||
use types::transaction::SignedTransaction;
|
use types::transaction::SignedTransaction;
|
||||||
use ethabi::FunctionOutputDecoder;
|
use ethabi::FunctionOutputDecoder;
|
||||||
@ -37,9 +38,12 @@ pub struct ServiceTransactionChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceTransactionChecker {
|
impl ServiceTransactionChecker {
|
||||||
|
|
||||||
/// Checks if given address in tx is whitelisted to send service transactions.
|
/// Checks if given address in tx is whitelisted to send service transactions.
|
||||||
pub fn check<C: CallContract + RegistryInfo>(&self, client: &C, tx: &SignedTransaction) -> Result<bool, String> {
|
pub fn check<C: CallContract + RegistrarClient>(
|
||||||
|
&self,
|
||||||
|
client: &C,
|
||||||
|
tx: &SignedTransaction
|
||||||
|
) -> Result<bool, String> {
|
||||||
let sender = tx.sender();
|
let sender = tx.sender();
|
||||||
// Skip checking the contract if the transaction does not have zero gas price
|
// Skip checking the contract if the transaction does not have zero gas price
|
||||||
if !tx.gas_price.is_zero() {
|
if !tx.gas_price.is_zero() {
|
||||||
@ -50,13 +54,28 @@ impl ServiceTransactionChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if given address is whitelisted to send service transactions.
|
/// Checks if given address is whitelisted to send service transactions.
|
||||||
pub fn check_address<C: CallContract + RegistryInfo>(&self, client: &C, sender: Address) -> Result<bool, String> {
|
pub fn check_address<C>(&self, client: &C, sender: Address) -> Result<bool, String>
|
||||||
|
where C: CallContract + RegistrarClient
|
||||||
|
{
|
||||||
trace!(target: "txqueue", "Checking service transaction checker contract from {}", sender);
|
trace!(target: "txqueue", "Checking service transaction checker contract from {}", sender);
|
||||||
if let Some(allowed) = self.certified_addresses_cache.try_read().as_ref().and_then(|c| c.get(&sender)) {
|
if let Some(allowed) = self
|
||||||
|
.certified_addresses_cache
|
||||||
|
.try_read()
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| c.get(&sender))
|
||||||
|
{
|
||||||
return Ok(*allowed);
|
return Ok(*allowed);
|
||||||
}
|
}
|
||||||
let contract_address = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest)
|
|
||||||
.ok_or_else(|| "contract is not configured")?;
|
let contract_address = match client.get_address(
|
||||||
|
SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME,
|
||||||
|
BlockId::Latest
|
||||||
|
) {
|
||||||
|
Ok(Some(addr)) => addr,
|
||||||
|
Ok(None) => return Err("contract is not configured".to_owned()),
|
||||||
|
Err(e) => return Err(e)
|
||||||
|
};
|
||||||
|
|
||||||
self.call_contract(client, contract_address, sender).and_then(|allowed| {
|
self.call_contract(client, contract_address, sender).and_then(|allowed| {
|
||||||
if let Some(mut cache) = self.certified_addresses_cache.try_write() {
|
if let Some(mut cache) = self.certified_addresses_cache.try_write() {
|
||||||
cache.insert(sender, allowed);
|
cache.insert(sender, allowed);
|
||||||
@ -66,13 +85,20 @@ impl ServiceTransactionChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Refresh certified addresses cache
|
/// Refresh certified addresses cache
|
||||||
pub fn refresh_cache<C: CallContract + RegistryInfo>(&self, client: &C) -> Result<bool, String> {
|
pub fn refresh_cache<C>(&self, client: &C) -> Result<bool, String>
|
||||||
|
where C: CallContract + RegistrarClient
|
||||||
|
{
|
||||||
trace!(target: "txqueue", "Refreshing certified addresses cache");
|
trace!(target: "txqueue", "Refreshing certified addresses cache");
|
||||||
// replace the cache with an empty list,
|
// replace the cache with an empty list,
|
||||||
// since it's not recent it won't be used anyway.
|
// since it's not recent it won't be used anyway.
|
||||||
let cache = mem::replace(&mut *self.certified_addresses_cache.write(), HashMap::default());
|
let cache = mem::replace(&mut *self.certified_addresses_cache.write(), HashMap::default());
|
||||||
|
|
||||||
if let Some(contract_address) = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest) {
|
let contract_address_fetch = client.get_address(
|
||||||
|
SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME,
|
||||||
|
BlockId::Latest
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if let Some(contract_address) = contract_address_fetch {
|
||||||
let addresses: Vec<_> = cache.keys().collect();
|
let addresses: Vec<_> = cache.keys().collect();
|
||||||
let mut cache: HashMap<Address, bool> = HashMap::default();
|
let mut cache: HashMap<Address, bool> = HashMap::default();
|
||||||
for address in addresses {
|
for address in addresses {
|
||||||
@ -86,7 +112,14 @@ impl ServiceTransactionChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_contract<C: CallContract + RegistryInfo>(&self, client: &C, contract_address: Address, sender: Address) -> Result<bool, String> {
|
fn call_contract<C>(
|
||||||
|
&self,
|
||||||
|
client: &C,
|
||||||
|
contract_address: Address,
|
||||||
|
sender: Address
|
||||||
|
) -> Result<bool, String>
|
||||||
|
where C: CallContract + RegistrarClient
|
||||||
|
{
|
||||||
let (data, decoder) = service_transaction::functions::certified::call(sender);
|
let (data, decoder) = service_transaction::functions::certified::call(sender);
|
||||||
let value = client.call_contract(BlockId::Latest, contract_address, data)?;
|
let value = client.call_contract(BlockId::Latest, contract_address, data)?;
|
||||||
decoder.decode(&value).map_err(|e| e.to_string())
|
decoder.decode(&value).map_err(|e| e.to_string())
|
||||||
|
@ -46,7 +46,6 @@ extern crate client_traits;
|
|||||||
extern crate common_types as types;
|
extern crate common_types as types;
|
||||||
extern crate engine;
|
extern crate engine;
|
||||||
extern crate ethcore;
|
extern crate ethcore;
|
||||||
extern crate ethcore_call_contract as call_contract;
|
|
||||||
extern crate ethcore_db;
|
extern crate ethcore_db;
|
||||||
extern crate ethcore_io as io;
|
extern crate ethcore_io as io;
|
||||||
extern crate ethcore_light as light;
|
extern crate ethcore_light as light;
|
||||||
|
@ -20,8 +20,6 @@ use std::time::{Duration, Instant};
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use ansi_term::Colour;
|
use ansi_term::Colour;
|
||||||
use bytes::Bytes;
|
|
||||||
use call_contract::CallContract;
|
|
||||||
use client_traits::{BlockInfo, BlockChainClient};
|
use client_traits::{BlockInfo, BlockChainClient};
|
||||||
use ethcore::client::{Client, DatabaseCompactionProfile, VMType};
|
use ethcore::client::{Client, DatabaseCompactionProfile, VMType};
|
||||||
use ethcore::miner::{self, stratum, Miner, MinerService, MinerOptions};
|
use ethcore::miner::{self, stratum, Miner, MinerService, MinerOptions};
|
||||||
@ -30,8 +28,7 @@ use spec::SpecParams;
|
|||||||
use verification::queue::VerifierSettings;
|
use verification::queue::VerifierSettings;
|
||||||
use ethcore_logger::{Config as LogConfig, RotatingLogger};
|
use ethcore_logger::{Config as LogConfig, RotatingLogger};
|
||||||
use ethcore_service::ClientService;
|
use ethcore_service::ClientService;
|
||||||
use ethereum_types::Address;
|
use futures::Stream;
|
||||||
use futures::{IntoFuture, Stream};
|
|
||||||
use hash_fetch::{self, fetch};
|
use hash_fetch::{self, fetch};
|
||||||
use informant::{Informant, LightNodeInformantData, FullNodeInformantData};
|
use informant::{Informant, LightNodeInformantData, FullNodeInformantData};
|
||||||
use journaldb::Algorithm;
|
use journaldb::Algorithm;
|
||||||
@ -44,7 +41,6 @@ use sync::{self, SyncConfig, PrivateTxHandler};
|
|||||||
use types::{
|
use types::{
|
||||||
client_types::Mode,
|
client_types::Mode,
|
||||||
engines::OptimizeFor,
|
engines::OptimizeFor,
|
||||||
ids::BlockId,
|
|
||||||
snapshot::Snapshotting,
|
snapshot::Snapshotting,
|
||||||
};
|
};
|
||||||
use parity_rpc::{
|
use parity_rpc::{
|
||||||
@ -65,12 +61,12 @@ use user_defaults::UserDefaults;
|
|||||||
use ipfs;
|
use ipfs;
|
||||||
use jsonrpc_core;
|
use jsonrpc_core;
|
||||||
use modules;
|
use modules;
|
||||||
use registrar::{RegistrarClient, Asynchronous};
|
|
||||||
use rpc;
|
use rpc;
|
||||||
use rpc_apis;
|
use rpc_apis;
|
||||||
use secretstore;
|
use secretstore;
|
||||||
use signer;
|
use signer;
|
||||||
use db;
|
use db;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
|
|
||||||
// how often to take periodic snapshots.
|
// how often to take periodic snapshots.
|
||||||
const SNAPSHOT_PERIOD: u64 = 5000;
|
const SNAPSHOT_PERIOD: u64 = 5000;
|
||||||
@ -687,29 +683,18 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
|
|||||||
chain_notify.start();
|
chain_notify.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
let contract_client = {
|
let fetcher = hash_fetch::Client::with_fetch(
|
||||||
struct FullRegistrar { client: Arc<Client> }
|
Arc::downgrade(&(service.client() as Arc<dyn RegistrarClient>)),
|
||||||
impl RegistrarClient for FullRegistrar {
|
fetch.clone(),
|
||||||
type Call = Asynchronous;
|
runtime.executor()
|
||||||
fn registrar_address(&self) -> Result<Address, String> {
|
);
|
||||||
self.client.registrar_address()
|
|
||||||
.ok_or_else(|| "Registrar not defined.".into())
|
|
||||||
}
|
|
||||||
fn call_contract(&self, address: Address, data: Bytes) -> Self::Call {
|
|
||||||
Box::new(self.client.call_contract(BlockId::Latest, address, data).into_future())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Arc::new(FullRegistrar { client: client.clone() })
|
|
||||||
};
|
|
||||||
|
|
||||||
// the updater service
|
// the updater service
|
||||||
let updater_fetch = fetch.clone();
|
|
||||||
let updater = Updater::new(
|
let updater = Updater::new(
|
||||||
&Arc::downgrade(&(service.client() as Arc<dyn BlockChainClient>)),
|
&Arc::downgrade(&(service.client() as Arc<dyn BlockChainClient>)),
|
||||||
&Arc::downgrade(&sync_provider),
|
&Arc::downgrade(&sync_provider),
|
||||||
update_policy,
|
update_policy,
|
||||||
hash_fetch::Client::with_fetch(contract_client.clone(), updater_fetch, runtime.executor())
|
fetcher
|
||||||
);
|
);
|
||||||
service.add_notify(updater.clone());
|
service.add_notify(updater.clone());
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ parity-crypto = "0.4.0"
|
|||||||
parity-runtime = { path = "../util/runtime" }
|
parity-runtime = { path = "../util/runtime" }
|
||||||
parking_lot = "0.9"
|
parking_lot = "0.9"
|
||||||
percent-encoding = "2.1.0"
|
percent-encoding = "2.1.0"
|
||||||
|
registrar = { path = "../util/registrar" }
|
||||||
rustc-hex = "1.0"
|
rustc-hex = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
@ -100,7 +100,10 @@ impl CachedContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_contract_address(&mut self) {
|
pub fn update_contract_address(&mut self) {
|
||||||
let contract_address = self.client.read_contract_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.into(), &self.address_source);
|
let contract_address = self.client.read_contract_address(
|
||||||
|
ACL_CHECKER_CONTRACT_REGISTRY_NAME,
|
||||||
|
&self.address_source
|
||||||
|
);
|
||||||
if contract_address != self.contract_address {
|
if contract_address != self.contract_address {
|
||||||
trace!(target: "secretstore", "Configuring for ACL checker contract from address {:?}",
|
trace!(target: "secretstore", "Configuring for ACL checker contract from address {:?}",
|
||||||
contract_address);
|
contract_address);
|
||||||
|
@ -266,7 +266,10 @@ impl CachedContract {
|
|||||||
|
|
||||||
pub fn update_contract_address(&mut self) {
|
pub fn update_contract_address(&mut self) {
|
||||||
if let Some(ref contract_address_source) = self.contract_address_source {
|
if let Some(ref contract_address_source) = self.contract_address_source {
|
||||||
let contract_address = self.client.read_contract_address(KEY_SERVER_SET_CONTRACT_REGISTRY_NAME.into(), contract_address_source);
|
let contract_address = self.client.read_contract_address(
|
||||||
|
KEY_SERVER_SET_CONTRACT_REGISTRY_NAME,
|
||||||
|
contract_address_source
|
||||||
|
);
|
||||||
if contract_address != self.contract_address {
|
if contract_address != self.contract_address {
|
||||||
trace!(target: "secretstore", "{}: Configuring for key server set contract from address {:?}",
|
trace!(target: "secretstore", "{}: Configuring for key server set contract from address {:?}",
|
||||||
self.self_key_pair.public(), contract_address);
|
self.self_key_pair.public(), contract_address);
|
||||||
|
@ -31,6 +31,7 @@ extern crate parity_crypto as crypto;
|
|||||||
extern crate parity_runtime;
|
extern crate parity_runtime;
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate percent_encoding;
|
extern crate percent_encoding;
|
||||||
|
extern crate registrar;
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
@ -222,7 +222,7 @@ impl OnChainServiceContract {
|
|||||||
|
|
||||||
/// Update service contract address.
|
/// Update service contract address.
|
||||||
fn update_contract_address(&self) -> bool {
|
fn update_contract_address(&self) -> bool {
|
||||||
let contract_address = self.client.read_contract_address(self.name.clone(), &self.address_source);
|
let contract_address = self.client.read_contract_address(&self.name, &self.address_source);
|
||||||
let mut data = self.data.write();
|
let mut data = self.data.write();
|
||||||
if contract_address != data.contract_address {
|
if contract_address != data.contract_address {
|
||||||
trace!(target: "secretstore", "{}: installing {} service contract from address {:?}",
|
trace!(target: "secretstore", "{}: installing {} service contract from address {:?}",
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use call_contract::RegistryInfo;
|
|
||||||
use common_types::{
|
use common_types::{
|
||||||
ids::BlockId,
|
ids::BlockId,
|
||||||
transaction::{Transaction, SignedTransaction, Action},
|
transaction::{Transaction, SignedTransaction, Action},
|
||||||
@ -28,6 +27,7 @@ use ethcore::miner::{Miner, MinerService};
|
|||||||
use sync::SyncProvider;
|
use sync::SyncProvider;
|
||||||
use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED};
|
use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED};
|
||||||
use {Error, NodeKeyPair, ContractAddress};
|
use {Error, NodeKeyPair, ContractAddress};
|
||||||
|
use registrar::RegistrarClient;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
/// 'Trusted' client weak reference.
|
/// 'Trusted' client weak reference.
|
||||||
@ -95,12 +95,19 @@ impl TrustedClient {
|
|||||||
/// Read contract address. If address source is registry, address only returned if current client state is
|
/// Read contract address. If address source is registry, address only returned if current client state is
|
||||||
/// trusted. Address from registry is read from registry from block latest block with
|
/// trusted. Address from registry is read from registry from block latest block with
|
||||||
/// REQUEST_CONFIRMATIONS_REQUIRED confirmations.
|
/// REQUEST_CONFIRMATIONS_REQUIRED confirmations.
|
||||||
pub fn read_contract_address(&self, registry_name: String, address: &ContractAddress) -> Option<Address> {
|
pub fn read_contract_address(
|
||||||
|
&self,
|
||||||
|
registry_name: &str,
|
||||||
|
address: &ContractAddress
|
||||||
|
) -> Option<Address> {
|
||||||
match *address {
|
match *address {
|
||||||
ContractAddress::Address(ref address) => Some(address.clone()),
|
ContractAddress::Address(ref address) => Some(address.clone()),
|
||||||
ContractAddress::Registry => self.get().and_then(|client|
|
ContractAddress::Registry => self.get().and_then(|client|
|
||||||
get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED)
|
get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED)
|
||||||
.and_then(|block| client.registry_address(registry_name, BlockId::Hash(block)))
|
.and_then(|block| {
|
||||||
|
client.get_address(registry_name, BlockId::Hash(block))
|
||||||
|
.unwrap_or(None)
|
||||||
|
})
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ version = "1.12.0"
|
|||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
call-contract = { package = "ethcore-call-contract", path = "../../ethcore/call-contract" }
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
@ -19,6 +20,7 @@ ethereum-types = "0.6.0"
|
|||||||
parity-runtime = { path = "../../util/runtime" }
|
parity-runtime = { path = "../../util/runtime" }
|
||||||
keccak-hash = "0.2.0"
|
keccak-hash = "0.2.0"
|
||||||
registrar = { path = "../../util/registrar" }
|
registrar = { path = "../../util/registrar" }
|
||||||
|
types = { path = "../../ethcore/types", package = "common-types" }
|
||||||
|
|
||||||
ethabi = "8.0"
|
ethabi = "8.0"
|
||||||
ethabi-derive = "8.0"
|
ethabi-derive = "8.0"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use std::{io, fs};
|
use std::{io, fs};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Weak};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use hash::keccak_buffer;
|
use hash::keccak_buffer;
|
||||||
@ -26,7 +26,7 @@ use fetch::{self, Fetch};
|
|||||||
use futures::{Future, IntoFuture};
|
use futures::{Future, IntoFuture};
|
||||||
use parity_runtime::Executor;
|
use parity_runtime::Executor;
|
||||||
use urlhint::{URLHintContract, URLHint, URLHintResult};
|
use urlhint::{URLHintContract, URLHint, URLHintResult};
|
||||||
use registrar::{RegistrarClient, Asynchronous};
|
use registrar::RegistrarClient;
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
|
|
||||||
/// API for fetching by hash.
|
/// API for fetching by hash.
|
||||||
@ -116,7 +116,7 @@ pub struct Client<F: Fetch + 'static = fetch::Client> {
|
|||||||
|
|
||||||
impl<F: Fetch + 'static> Client<F> {
|
impl<F: Fetch + 'static> Client<F> {
|
||||||
/// Creates new instance of the `Client` given on-chain contract client, fetch service and task runner.
|
/// Creates new instance of the `Client` given on-chain contract client, fetch service and task runner.
|
||||||
pub fn with_fetch(contract: Arc<dyn RegistrarClient<Call=Asynchronous>>, fetch: F, executor: Executor) -> Self {
|
pub fn with_fetch(contract: Weak<dyn RegistrarClient>, fetch: F, executor: Executor) -> Self {
|
||||||
Client {
|
Client {
|
||||||
contract: URLHintContract::new(contract),
|
contract: URLHintContract::new(contract),
|
||||||
fetch: fetch,
|
fetch: fetch,
|
||||||
@ -133,6 +133,7 @@ impl<F: Fetch + 'static> HashFetch for Client<F> {
|
|||||||
let random_path = self.random_path.clone();
|
let random_path = self.random_path.clone();
|
||||||
let remote_fetch = self.fetch.clone();
|
let remote_fetch = self.fetch.clone();
|
||||||
let future = self.contract.resolve(hash)
|
let future = self.contract.resolve(hash)
|
||||||
|
.into_future()
|
||||||
.map_err(|e| { warn!("Error resolving URL: {}", e); Error::NoResolution })
|
.map_err(|e| { warn!("Error resolving URL: {}", e); Error::NoResolution })
|
||||||
.and_then(|maybe_url| maybe_url.ok_or(Error::NoResolution))
|
.and_then(|maybe_url| maybe_url.ok_or(Error::NoResolution))
|
||||||
.map(|content| match content {
|
.map(|content| match content {
|
||||||
@ -197,6 +198,7 @@ mod tests {
|
|||||||
use urlhint::tests::{FakeRegistrar, URLHINT};
|
use urlhint::tests::{FakeRegistrar, URLHINT};
|
||||||
use super::{Error, Client, HashFetch, random_temp_path, H256};
|
use super::{Error, Client, HashFetch, random_temp_path, H256};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use registrar::RegistrarClient;
|
||||||
|
|
||||||
fn registrar() -> FakeRegistrar {
|
fn registrar() -> FakeRegistrar {
|
||||||
let mut registrar = FakeRegistrar::new();
|
let mut registrar = FakeRegistrar::new();
|
||||||
@ -210,9 +212,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_return_error_if_hash_not_found() {
|
fn should_return_error_if_hash_not_found() {
|
||||||
// given
|
// given
|
||||||
let contract = Arc::new(FakeRegistrar::new());
|
let contract = Arc::new(FakeRegistrar::new()) as Arc<dyn RegistrarClient>;
|
||||||
let fetch = FakeFetch::new(None::<usize>);
|
let fetch = FakeFetch::new(None::<usize>);
|
||||||
let client = Client::with_fetch(contract.clone(), fetch, Executor::new_sync());
|
let client = Client::with_fetch(Arc::downgrade(&contract), fetch, Executor::new_sync());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
@ -228,9 +230,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_return_error_if_response_is_not_successful() {
|
fn should_return_error_if_response_is_not_successful() {
|
||||||
// given
|
// given
|
||||||
let registrar = Arc::new(registrar());
|
let registrar = Arc::new(registrar()) as Arc<dyn RegistrarClient>;
|
||||||
let fetch = FakeFetch::new(None::<usize>);
|
let fetch = FakeFetch::new(None::<usize>);
|
||||||
let client = Client::with_fetch(registrar.clone(), fetch, Executor::new_sync());
|
let client = Client::with_fetch(Arc::downgrade(®istrar), fetch, Executor::new_sync());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
@ -246,9 +248,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_return_hash_mismatch() {
|
fn should_return_hash_mismatch() {
|
||||||
// given
|
// given
|
||||||
let registrar = Arc::new(registrar());
|
let registrar = Arc::new(registrar()) as Arc<dyn RegistrarClient>;
|
||||||
let fetch = FakeFetch::new(Some(1));
|
let fetch = FakeFetch::new(Some(1));
|
||||||
let mut client = Client::with_fetch(registrar.clone(), fetch, Executor::new_sync());
|
let mut client = Client::with_fetch(Arc::downgrade(®istrar), fetch, Executor::new_sync());
|
||||||
let path = random_temp_path();
|
let path = random_temp_path();
|
||||||
let path2 = path.clone();
|
let path2 = path.clone();
|
||||||
client.random_path = Arc::new(move || path2.clone());
|
client.random_path = Arc::new(move || path2.clone());
|
||||||
@ -269,9 +271,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_return_path_if_hash_matches() {
|
fn should_return_path_if_hash_matches() {
|
||||||
// given
|
// given
|
||||||
let registrar = Arc::new(registrar());
|
let registrar = Arc::new(registrar()) as Arc<dyn RegistrarClient>;
|
||||||
let fetch = FakeFetch::new(Some(1));
|
let fetch = FakeFetch::new(Some(1));
|
||||||
let client = Client::with_fetch(registrar.clone(), fetch, Executor::new_sync());
|
let client = Client::with_fetch(Arc::downgrade(®istrar), fetch, Executor::new_sync());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
extern crate call_contract;
|
||||||
extern crate ethabi;
|
extern crate ethabi;
|
||||||
extern crate parity_bytes as bytes;
|
extern crate parity_bytes as bytes;
|
||||||
extern crate ethereum_types;
|
extern crate ethereum_types;
|
||||||
@ -32,6 +33,7 @@ extern crate parity_runtime;
|
|||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
extern crate registrar;
|
extern crate registrar;
|
||||||
|
extern crate types;
|
||||||
|
|
||||||
pub extern crate fetch;
|
pub extern crate fetch;
|
||||||
|
|
||||||
|
@ -16,15 +16,14 @@
|
|||||||
|
|
||||||
//! URLHint Contract
|
//! URLHint Contract
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Weak;
|
||||||
use rustc_hex::ToHex;
|
use rustc_hex::ToHex;
|
||||||
use mime::{self, Mime};
|
use mime::{self, Mime};
|
||||||
use mime_guess;
|
use mime_guess;
|
||||||
|
|
||||||
use futures::{future, Future};
|
|
||||||
use futures::future::Either;
|
|
||||||
use ethereum_types::{H256, Address};
|
use ethereum_types::{H256, Address};
|
||||||
use registrar::{Registrar, RegistrarClient, Asynchronous};
|
use registrar::RegistrarClient;
|
||||||
|
use types::ids::BlockId;
|
||||||
|
|
||||||
use_contract!(urlhint, "res/urlhint.json");
|
use_contract!(urlhint, "res/urlhint.json");
|
||||||
|
|
||||||
@ -95,20 +94,18 @@ pub enum URLHintResult {
|
|||||||
/// URLHint Contract interface
|
/// URLHint Contract interface
|
||||||
pub trait URLHint: Send + Sync {
|
pub trait URLHint: Send + Sync {
|
||||||
/// Resolves given id to registrar entry.
|
/// Resolves given id to registrar entry.
|
||||||
fn resolve(&self, id: H256) -> Box<dyn Future<Item = Option<URLHintResult>, Error = String> + Send>;
|
fn resolve(&self, id: H256) -> Result<Option<URLHintResult>, String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `URLHintContract` API
|
/// `URLHintContract` API
|
||||||
pub struct URLHintContract {
|
pub struct URLHintContract {
|
||||||
registrar: Registrar,
|
client: Weak<dyn RegistrarClient>,
|
||||||
client: Arc<dyn RegistrarClient<Call=Asynchronous>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl URLHintContract {
|
impl URLHintContract {
|
||||||
/// Creates new `URLHintContract`
|
/// Creates new `URLHintContract`
|
||||||
pub fn new(client: Arc<dyn RegistrarClient<Call=Asynchronous>>) -> Self {
|
pub fn new(client: Weak<dyn RegistrarClient>) -> Self {
|
||||||
URLHintContract {
|
URLHintContract {
|
||||||
registrar: Registrar::new(client.clone()),
|
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,9 +120,11 @@ fn get_urlhint_content(account_slash_repo: String, owner: Address) -> Content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_urlhint_output(output: (String, [u8; 20], Address)) -> Option<URLHintResult> {
|
fn decode_urlhint_output(
|
||||||
let (account_slash_repo, commit, owner) = output;
|
account_slash_repo: String,
|
||||||
|
commit: [u8; 20],
|
||||||
|
owner: Address
|
||||||
|
) -> Option<URLHintResult> {
|
||||||
if owner == Address::zero() {
|
if owner == Address::zero() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -159,20 +158,26 @@ fn decode_urlhint_output(output: (String, [u8; 20], Address)) -> Option<URLHintR
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl URLHint for URLHintContract {
|
impl URLHint for URLHintContract {
|
||||||
fn resolve(&self, id: H256) -> Box<dyn Future<Item = Option<URLHintResult>, Error = String> + Send> {
|
fn resolve(&self, id: H256) -> Result<Option<URLHintResult>, String> {
|
||||||
let client = self.client.clone();
|
use urlhint::urlhint::functions::entries::{encode_input, decode_output};
|
||||||
|
|
||||||
let future = self.registrar.get_address(GITHUB_HINT)
|
let client = self.client.clone().upgrade()
|
||||||
.and_then(move |addr| if !addr.is_zero() {
|
.ok_or_else(|| "Registrar/contract client unavailable".to_owned())?;
|
||||||
let data = urlhint::functions::entries::encode_input(id);
|
|
||||||
let result = client.call_contract(addr, data)
|
let returned_address = client.get_address(GITHUB_HINT, BlockId::Latest)?;
|
||||||
.and_then(move |output| urlhint::functions::entries::decode_output(&output).map_err(|e| e.to_string()))
|
|
||||||
.map(decode_urlhint_output);
|
if let Some(address) = returned_address {
|
||||||
Either::B(result)
|
let data = encode_input(id);
|
||||||
} else {
|
let output_bytes = client.call_contract(BlockId::Latest, address, data)?;
|
||||||
Either::A(future::ok(None))
|
let (account_slash_repo, commit, owner) = decode_output(&output_bytes)
|
||||||
});
|
.map_err(|e| e.to_string())?;
|
||||||
Box::new(future)
|
|
||||||
|
let url_hint = decode_urlhint_output(account_slash_repo, commit, owner);
|
||||||
|
|
||||||
|
Ok(url_hint)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,13 +210,12 @@ pub mod tests {
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use rustc_hex::FromHex;
|
use rustc_hex::FromHex;
|
||||||
|
|
||||||
use futures::{Future, IntoFuture};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::guess_mime_type;
|
use super::guess_mime_type;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use ethereum_types::Address;
|
use ethereum_types::Address;
|
||||||
use bytes::{Bytes, ToPretty};
|
use bytes::{Bytes, ToPretty};
|
||||||
|
use call_contract::CallContract;
|
||||||
|
|
||||||
pub struct FakeRegistrar {
|
pub struct FakeRegistrar {
|
||||||
pub calls: Arc<Mutex<Vec<(String, String)>>>,
|
pub calls: Arc<Mutex<Vec<(String, String)>>>,
|
||||||
@ -235,17 +239,23 @@ pub mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegistrarClient for FakeRegistrar {
|
impl CallContract for FakeRegistrar {
|
||||||
type Call = Asynchronous;
|
fn call_contract(
|
||||||
|
&self,
|
||||||
fn registrar_address(&self) -> Result<Address, String> {
|
_block: BlockId,
|
||||||
Ok(REGISTRAR.parse().unwrap())
|
address: Address,
|
||||||
}
|
data: Bytes
|
||||||
|
) -> Result<Bytes, String> {
|
||||||
fn call_contract(&self, address: Address, data: Bytes) -> Self::Call {
|
|
||||||
self.calls.lock().push((address.to_hex(), data.to_hex()));
|
self.calls.lock().push((address.to_hex(), data.to_hex()));
|
||||||
let res = self.responses.lock().remove(0);
|
let res = self.responses.lock().remove(0);
|
||||||
Box::new(res.into_future())
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegistrarClient for FakeRegistrar {
|
||||||
|
fn registrar_address(&self) -> Option<Address> {
|
||||||
|
Some(REGISTRAR.parse().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,10 +276,12 @@ pub mod tests {
|
|||||||
registrar.responses.lock()[1] = Ok(resolve_result);
|
registrar.responses.lock()[1] = Ok(resolve_result);
|
||||||
|
|
||||||
let calls = registrar.calls.clone();
|
let calls = registrar.calls.clone();
|
||||||
let urlhint = URLHintContract::new(Arc::new(registrar));
|
|
||||||
|
let registrar = Arc::new(registrar) as Arc<dyn RegistrarClient>;
|
||||||
|
let urlhint = URLHintContract::new(Arc::downgrade(®istrar));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res = urlhint.resolve(h256_from_short_str("test")).wait().unwrap();
|
let res = urlhint.resolve(h256_from_short_str("test")).unwrap();
|
||||||
let calls = calls.lock();
|
let calls = calls.lock();
|
||||||
let call0 = calls.get(0).expect("Registrar resolve called");
|
let call0 = calls.get(0).expect("Registrar resolve called");
|
||||||
let call1 = calls.get(1).expect("URLHint Resolve called");
|
let call1 = calls.get(1).expect("URLHint Resolve called");
|
||||||
@ -294,10 +306,12 @@ pub mod tests {
|
|||||||
Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()),
|
Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()),
|
||||||
Ok("0000000000000000000000000000000000000000000000000000000000000060ec4c1fe06c808fe3739858c347109b1f5f1ed4b5000000000000000000000000000000000000000000000000deadcafebeefbeefcafedeaddeedfeedffffffff0000000000000000000000000000000000000000000000000000000000000011657468636f72652f64616f2e636c61696d000000000000000000000000000000".from_hex().unwrap()),
|
Ok("0000000000000000000000000000000000000000000000000000000000000060ec4c1fe06c808fe3739858c347109b1f5f1ed4b5000000000000000000000000000000000000000000000000deadcafebeefbeefcafedeaddeedfeedffffffff0000000000000000000000000000000000000000000000000000000000000011657468636f72652f64616f2e636c61696d000000000000000000000000000000".from_hex().unwrap()),
|
||||||
]);
|
]);
|
||||||
let urlhint = URLHintContract::new(Arc::new(registrar));
|
|
||||||
|
let registrar = Arc::new(registrar) as Arc<dyn RegistrarClient>;
|
||||||
|
let urlhint = URLHintContract::new(Arc::downgrade(®istrar));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res = urlhint.resolve(h256_from_short_str("test")).wait().unwrap();
|
let res = urlhint.resolve(h256_from_short_str("test")).unwrap();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(res, Some(URLHintResult::Dapp(GithubApp {
|
assert_eq!(res, Some(URLHintResult::Dapp(GithubApp {
|
||||||
@ -316,10 +330,12 @@ pub mod tests {
|
|||||||
Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()),
|
Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()),
|
||||||
Ok("00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000deadcafebeefbeefcafedeaddeedfeedffffffff000000000000000000000000000000000000000000000000000000000000003c68747470733a2f2f7061726974792e696f2f6173736574732f696d616765732f657468636f72652d626c61636b2d686f72697a6f6e74616c2e706e6700000000".from_hex().unwrap()),
|
Ok("00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000deadcafebeefbeefcafedeaddeedfeedffffffff000000000000000000000000000000000000000000000000000000000000003c68747470733a2f2f7061726974792e696f2f6173736574732f696d616765732f657468636f72652d626c61636b2d686f72697a6f6e74616c2e706e6700000000".from_hex().unwrap()),
|
||||||
]);
|
]);
|
||||||
let urlhint = URLHintContract::new(Arc::new(registrar));
|
|
||||||
|
let registrar = Arc::new(registrar) as Arc<dyn RegistrarClient>;
|
||||||
|
let urlhint = URLHintContract::new(Arc::downgrade(®istrar));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res = urlhint.resolve(h256_from_short_str("test")).wait().unwrap();
|
let res = urlhint.resolve(h256_from_short_str("test")).unwrap();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(res, Some(URLHintResult::Content(Content {
|
assert_eq!(res, Some(URLHintResult::Content(Content {
|
||||||
|
@ -251,8 +251,11 @@ impl OperationsClient for OperationsContractClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let client = self.client.upgrade().ok_or_else(|| "Cannot obtain client")?;
|
let client = self.client.upgrade().ok_or_else(|| "Cannot obtain client")?;
|
||||||
let address = client.registry_address("operations".into(), BlockId::Latest).ok_or_else(|| "Cannot get operations contract address")?;
|
let address = client.get_address("operations", BlockId::Latest)?
|
||||||
let do_call = |data| client.call_contract(BlockId::Latest, address, data).map_err(|e| format!("{:?}", e));
|
.ok_or_else(|| "Cannot get operations contract address")?;
|
||||||
|
let do_call = |data| {
|
||||||
|
client.call_contract(BlockId::Latest, address, data).map_err(|e| format!("{:?}", e))
|
||||||
|
};
|
||||||
|
|
||||||
trace!(target: "updater", "Looking up this_fork for our release: {}/{:?}", CLIENT_ID, this.hash);
|
trace!(target: "updater", "Looking up this_fork for our release: {}/{:?}", CLIENT_ID, this.hash);
|
||||||
|
|
||||||
@ -304,7 +307,7 @@ impl OperationsClient for OperationsContractClient {
|
|||||||
|
|
||||||
fn release_block_number(&self, from: BlockNumber, release: &ReleaseInfo) -> Option<BlockNumber> {
|
fn release_block_number(&self, from: BlockNumber, release: &ReleaseInfo) -> Option<BlockNumber> {
|
||||||
let client = self.client.upgrade()?;
|
let client = self.client.upgrade()?;
|
||||||
let address = client.registry_address("operations".into(), BlockId::Latest)?;
|
let address = client.get_address("operations", BlockId::Latest).unwrap_or(None)?;
|
||||||
|
|
||||||
let topics = operations::events::release_added::filter(Some(*CLIENT_ID_HASH), Some(release.fork.into()), Some(release.is_critical));
|
let topics = operations::events::release_added::filter(Some(*CLIENT_ID_HASH), Some(release.fork.into()), Some(release.is_critical));
|
||||||
let topics = vec![topics.topic0, topics.topic1, topics.topic2, topics.topic3];
|
let topics = vec![topics.topic0, topics.topic1, topics.topic2, topics.topic3];
|
||||||
|
@ -6,8 +6,9 @@ license = "GPL-3.0"
|
|||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.1"
|
call-contract = { package = "ethcore-call-contract", path = "../../ethcore/call-contract" }
|
||||||
ethabi = "8.0"
|
ethabi = "8.0"
|
||||||
ethabi-derive = "8.0"
|
ethabi-derive = "8.0"
|
||||||
ethabi-contract = "8.0"
|
ethabi-contract = "8.0"
|
||||||
keccak-hash = "0.2.0"
|
keccak-hash = "0.2.0"
|
||||||
|
types = { path = "../../ethcore/types", package = "common-types" }
|
||||||
|
@ -14,13 +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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
extern crate futures;
|
extern crate call_contract;
|
||||||
extern crate ethabi;
|
extern crate ethabi;
|
||||||
extern crate ethabi_derive;
|
extern crate ethabi_derive;
|
||||||
extern crate keccak_hash;
|
extern crate keccak_hash;
|
||||||
|
extern crate types;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate ethabi_contract;
|
extern crate ethabi_contract;
|
||||||
|
|
||||||
mod registrar;
|
mod registrar;
|
||||||
pub use registrar::{Registrar, RegistrarClient, Synchronous, Asynchronous};
|
pub use registrar::RegistrarClient;
|
||||||
|
@ -14,59 +14,41 @@
|
|||||||
// 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use futures::{Future, future, IntoFuture};
|
use call_contract::CallContract;
|
||||||
use ethabi::{Address, Bytes};
|
use ethabi::Address;
|
||||||
use std::sync::Arc;
|
|
||||||
use keccak_hash::keccak;
|
use keccak_hash::keccak;
|
||||||
|
use types::ids::BlockId;
|
||||||
|
|
||||||
use_contract!(registrar, "res/registrar.json");
|
use_contract!(registrar, "res/registrar.json");
|
||||||
|
|
||||||
// Maps a domain name to an Ethereum address
|
// Maps a domain name to an Ethereum address
|
||||||
const DNS_A_RECORD: &'static str = "A";
|
const DNS_A_RECORD: &'static str = "A";
|
||||||
|
|
||||||
pub type Asynchronous = Box<dyn Future<Item=Bytes, Error=String> + Send>;
|
/// Registrar contract interface
|
||||||
pub type Synchronous = Result<Bytes, String>;
|
pub trait RegistrarClient: CallContract + Send + Sync {
|
||||||
|
/// Get address of the registrar itself
|
||||||
|
fn registrar_address(&self) -> Option<Address>;
|
||||||
|
|
||||||
/// Registrar is dedicated interface to access the registrar contract
|
/// Get address from registrar for the specified key.
|
||||||
/// which in turn generates an address when a client requests one
|
fn get_address(&self, key: &str, block: BlockId) -> Result<Option<Address>, String> {
|
||||||
pub struct Registrar {
|
use registrar::registrar::functions::get_address::{encode_input, decode_output};
|
||||||
client: Arc<dyn RegistrarClient<Call=Asynchronous>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Registrar {
|
let registrar_address = match self.registrar_address() {
|
||||||
/// Registrar constructor
|
Some(address) => address,
|
||||||
pub fn new(client: Arc<dyn RegistrarClient<Call=Asynchronous>>) -> Self {
|
None => return Err("Registrar address not defined.".to_owned())
|
||||||
Self {
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate an address for the given key
|
|
||||||
pub fn get_address<'a>(&self, key: &'a str) -> Box<dyn Future<Item = Address, Error = String> + Send> {
|
|
||||||
// Address of the registrar itself
|
|
||||||
let registrar_address = match self.client.registrar_address() {
|
|
||||||
Ok(a) => a,
|
|
||||||
Err(e) => return Box::new(future::err(e)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let hashed_key: [u8; 32] = keccak(key).into();
|
let hashed_key: [u8; 32] = keccak(key).into();
|
||||||
let id = registrar::functions::get_address::encode_input(hashed_key, DNS_A_RECORD);
|
let id = encode_input(hashed_key, DNS_A_RECORD);
|
||||||
|
|
||||||
let future = self.client.call_contract(registrar_address, id)
|
let address_bytes = self.call_contract(block, registrar_address, id)?;
|
||||||
.and_then(move |address| registrar::functions::get_address::decode_output(&address).map_err(|e| e.to_string()));
|
|
||||||
|
|
||||||
Box::new(future)
|
let address = decode_output(&address_bytes).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
if address.is_zero() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Ok(Some(address))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registrar contract interface
|
|
||||||
/// Should execute transaction using current blockchain state.
|
|
||||||
pub trait RegistrarClient: Send + Sync {
|
|
||||||
/// Specifies synchronous or asynchronous communication
|
|
||||||
type Call: IntoFuture<Item=Bytes, Error=String>;
|
|
||||||
|
|
||||||
/// Get registrar address
|
|
||||||
fn registrar_address(&self) -> Result<Address, String>;
|
|
||||||
/// Call Contract
|
|
||||||
fn call_contract(&self, address: Address, data: Bytes) -> Self::Call;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user