do not cache ACL storage contract
This commit is contained in:
parent
3fb8a85f83
commit
18582d7b65
@ -20,6 +20,7 @@ use parking_lot::Mutex;
|
|||||||
use ethkey::public_to_address;
|
use ethkey::public_to_address;
|
||||||
use ethcore::client::{Client, BlockChainClient, BlockId};
|
use ethcore::client::{Client, BlockChainClient, BlockId};
|
||||||
use native_contracts::SecretStoreAclStorage;
|
use native_contracts::SecretStoreAclStorage;
|
||||||
|
use util::{H256, Address};
|
||||||
use types::all::{Error, ServerKeyId, Public};
|
use types::all::{Error, ServerKeyId, Public};
|
||||||
|
|
||||||
const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker";
|
const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker";
|
||||||
@ -32,33 +33,64 @@ pub trait AclStorage: Send + Sync {
|
|||||||
|
|
||||||
/// On-chain ACL storage implementation.
|
/// On-chain ACL storage implementation.
|
||||||
pub struct OnChainAclStorage {
|
pub struct OnChainAclStorage {
|
||||||
|
/// Cached on-chain contract.
|
||||||
|
contract: Mutex<CachedContract>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cached on-chain ACL storage contract.
|
||||||
|
struct CachedContract {
|
||||||
/// Blockchain client.
|
/// Blockchain client.
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
/// On-chain contract.
|
/// Hash of best block, when contract address has been read.
|
||||||
contract: Mutex<Option<SecretStoreAclStorage>>,
|
best_block_hash: Option<H256>,
|
||||||
|
/// Contract address.
|
||||||
|
contract_addr: Option<Address>,
|
||||||
|
/// Contract at given address.
|
||||||
|
contract: Option<SecretStoreAclStorage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OnChainAclStorage {
|
impl OnChainAclStorage {
|
||||||
pub fn new(client: Arc<Client>) -> Self {
|
pub fn new(client: Arc<Client>) -> Self {
|
||||||
OnChainAclStorage {
|
OnChainAclStorage {
|
||||||
client: client,
|
contract: Mutex::new(CachedContract::new(client)),
|
||||||
contract: Mutex::new(None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AclStorage for OnChainAclStorage {
|
impl AclStorage for OnChainAclStorage {
|
||||||
fn check(&self, public: &Public, document: &ServerKeyId) -> Result<bool, Error> {
|
fn check(&self, public: &Public, document: &ServerKeyId) -> Result<bool, Error> {
|
||||||
let mut contract = self.contract.lock();
|
self.contract.lock().check(public, document)
|
||||||
if !contract.is_some() {
|
}
|
||||||
*contract = self.client.registry_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.to_owned())
|
}
|
||||||
.and_then(|contract_addr| {
|
|
||||||
|
impl CachedContract {
|
||||||
|
pub fn new(client: Arc<Client>) -> Self {
|
||||||
|
CachedContract {
|
||||||
|
client: client,
|
||||||
|
best_block_hash: None,
|
||||||
|
contract_addr: None,
|
||||||
|
contract: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check(&mut self, public: &Public, document: &ServerKeyId) -> Result<bool, Error> {
|
||||||
|
let new_best_block_hash = self.client.best_block_header().hash();
|
||||||
|
if self.best_block_hash.as_ref() != Some(&new_best_block_hash) {
|
||||||
|
let new_contract_addr = self.client.registry_address(ACL_CHECKER_CONTRACT_REGISTRY_NAME.to_owned());
|
||||||
|
if self.contract_addr.as_ref() != new_contract_addr.as_ref() {
|
||||||
|
self.contract = new_contract_addr.map(|contract_addr| {
|
||||||
trace!(target: "secretstore", "Configuring for ACL checker contract from {}", contract_addr);
|
trace!(target: "secretstore", "Configuring for ACL checker contract from {}", contract_addr);
|
||||||
|
|
||||||
Some(SecretStoreAclStorage::new(contract_addr))
|
SecretStoreAclStorage::new(contract_addr)
|
||||||
})
|
});
|
||||||
|
|
||||||
|
self.contract_addr = new_contract_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.best_block_hash = Some(new_best_block_hash);
|
||||||
}
|
}
|
||||||
if let Some(ref contract) = *contract {
|
|
||||||
|
if let Some(contract) = self.contract.as_ref() {
|
||||||
let address = public_to_address(&public);
|
let address = public_to_address(&public);
|
||||||
let do_call = |a, d| future::done(self.client.call_contract(BlockId::Latest, a, d));
|
let do_call = |a, d| future::done(self.client.call_contract(BlockId::Latest, a, d));
|
||||||
contract.check_permissions(do_call, address, document.clone())
|
contract.check_permissions(do_call, address, document.clone())
|
||||||
|
Loading…
Reference in New Issue
Block a user