diff --git a/secret_store/src/acl_storage.rs b/secret_store/src/acl_storage.rs index c06929e94..8d629f022 100644 --- a/secret_store/src/acl_storage.rs +++ b/secret_store/src/acl_storage.rs @@ -20,6 +20,7 @@ use futures::{future, Future}; use parking_lot::{Mutex, RwLock}; use ethkey::public_to_address; use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify}; +use ethsync::SyncProvider; use native_contracts::SecretStoreAclStorage; use bigint::hash::H256; use util::Address; @@ -44,6 +45,8 @@ pub struct OnChainAclStorage { struct CachedContract { /// Blockchain client. client: Weak, + /// Sync provider. + sync: Weak, /// Contract address. contract_addr: Option
, /// Contract at given address. @@ -57,9 +60,9 @@ pub struct DummyAclStorage { } impl OnChainAclStorage { - pub fn new(client: &Arc) -> Arc { + pub fn new(client: &Arc, sync: &Arc) -> Arc { let acl_storage = Arc::new(OnChainAclStorage { - contract: Mutex::new(CachedContract::new(client)), + contract: Mutex::new(CachedContract::new(client, sync)), }); client.add_notify(acl_storage.clone()); acl_storage @@ -81,9 +84,10 @@ impl ChainNotify for OnChainAclStorage { } impl CachedContract { - pub fn new(client: &Arc) -> Self { + pub fn new(client: &Arc, sync: &Arc) -> Self { CachedContract { client: Arc::downgrade(client), + sync: Arc::downgrade(sync), contract_addr: None, contract: None, } @@ -105,19 +109,26 @@ impl CachedContract { } pub fn check(&mut self, public: &Public, document: &ServerKeyId) -> Result { - match self.contract.as_ref() { - Some(contract) => { - let address = public_to_address(&public); - let do_call = |a, d| future::done( - self.client - .upgrade() - .ok_or("Calling contract without client".into()) - .and_then(|c| c.call_contract(BlockId::Latest, a, d))); - contract.check_permissions(do_call, address, document.clone()) - .map_err(|err| Error::Internal(err)) - .wait() + match (self.client.upgrade(), self.sync.upgrade()) { + (Some(client), Some(sync)) => { + // we can not tell if access to document is allowed until fully synchronized + if sync.status().is_syncing(client.queue_info()) { + return Err(Error::Internal("Trying to check access by non-synchronized client".to_owned())); + } + + // call contract to check accesss + match self.contract.as_ref() { + Some(contract) => { + let address = public_to_address(&public); + let do_call = |a, d| future::done(client.call_contract(BlockId::Latest, a, d)); + contract.check_permissions(do_call, address, document.clone()) + .map_err(|err| Error::Internal(err)) + .wait() + }, + None => Err(Error::Internal("ACL checker contract is not configured".to_owned())), + } }, - None => Err(Error::Internal("ACL checker contract is not configured".to_owned())), + _ => Err(Error::Internal("Calling ACL contract without client".into())), } } } diff --git a/secret_store/src/lib.rs b/secret_store/src/lib.rs index e996c8295..662495021 100644 --- a/secret_store/src/lib.rs +++ b/secret_store/src/lib.rs @@ -73,7 +73,7 @@ pub use self::node_key_pair::{PlainNodeKeyPair, KeyStoreNodeKeyPair}; /// Start new key server instance pub fn start(client: Arc, sync: Arc, self_key_pair: Arc, config: ServiceConfiguration) -> Result, Error> { let acl_storage: Arc = if config.acl_check_enabled { - acl_storage::OnChainAclStorage::new(&client/*, &sync*/) // TODO: return false until fully synced + acl_storage::OnChainAclStorage::new(&client, &sync) } else { Arc::new(acl_storage::DummyAclStorage::default()) };