SecretStore: ACL checker now requires blockchain to be fully synchronized

This commit is contained in:
Svyatoslav Nikolsky 2017-11-24 13:17:08 +03:00
parent 14686f2652
commit 009e350fc7
2 changed files with 27 additions and 16 deletions

View File

@ -20,6 +20,7 @@ use futures::{future, Future};
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use ethkey::public_to_address; use ethkey::public_to_address;
use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify}; use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify};
use ethsync::SyncProvider;
use native_contracts::SecretStoreAclStorage; use native_contracts::SecretStoreAclStorage;
use bigint::hash::H256; use bigint::hash::H256;
use util::Address; use util::Address;
@ -44,6 +45,8 @@ pub struct OnChainAclStorage {
struct CachedContract { struct CachedContract {
/// Blockchain client. /// Blockchain client.
client: Weak<Client>, client: Weak<Client>,
/// Sync provider.
sync: Weak<SyncProvider>,
/// Contract address. /// Contract address.
contract_addr: Option<Address>, contract_addr: Option<Address>,
/// Contract at given address. /// Contract at given address.
@ -57,9 +60,9 @@ pub struct DummyAclStorage {
} }
impl OnChainAclStorage { impl OnChainAclStorage {
pub fn new(client: &Arc<Client>) -> Arc<Self> { pub fn new(client: &Arc<Client>, sync: &Arc<SyncProvider>) -> Arc<Self> {
let acl_storage = Arc::new(OnChainAclStorage { 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()); client.add_notify(acl_storage.clone());
acl_storage acl_storage
@ -81,9 +84,10 @@ impl ChainNotify for OnChainAclStorage {
} }
impl CachedContract { impl CachedContract {
pub fn new(client: &Arc<Client>) -> Self { pub fn new(client: &Arc<Client>, sync: &Arc<SyncProvider>) -> Self {
CachedContract { CachedContract {
client: Arc::downgrade(client), client: Arc::downgrade(client),
sync: Arc::downgrade(sync),
contract_addr: None, contract_addr: None,
contract: None, contract: None,
} }
@ -105,20 +109,27 @@ impl CachedContract {
} }
pub fn check(&mut self, public: &Public, document: &ServerKeyId) -> Result<bool, Error> { pub fn check(&mut self, public: &Public, document: &ServerKeyId) -> Result<bool, Error> {
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() { match self.contract.as_ref() {
Some(contract) => { Some(contract) => {
let address = public_to_address(&public); let address = public_to_address(&public);
let do_call = |a, d| future::done( let do_call = |a, d| future::done(client.call_contract(BlockId::Latest, a, d));
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()) contract.check_permissions(do_call, address, document.clone())
.map_err(|err| Error::Internal(err)) .map_err(|err| Error::Internal(err))
.wait() .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())),
}
} }
} }

View File

@ -73,7 +73,7 @@ pub use self::node_key_pair::{PlainNodeKeyPair, KeyStoreNodeKeyPair};
/// Start new key server instance /// Start new key server instance
pub fn start(client: Arc<Client>, sync: Arc<SyncProvider>, self_key_pair: Arc<NodeKeyPair>, config: ServiceConfiguration) -> Result<Box<KeyServer>, Error> { pub fn start(client: Arc<Client>, sync: Arc<SyncProvider>, self_key_pair: Arc<NodeKeyPair>, config: ServiceConfiguration) -> Result<Box<KeyServer>, Error> {
let acl_storage: Arc<acl_storage::AclStorage> = if config.acl_check_enabled { let acl_storage: Arc<acl_storage::AclStorage> = if config.acl_check_enabled {
acl_storage::OnChainAclStorage::new(&client/*, &sync*/) // TODO: return false until fully synced acl_storage::OnChainAclStorage::new(&client, &sync)
} else { } else {
Arc::new(acl_storage::DummyAclStorage::default()) Arc::new(acl_storage::DummyAclStorage::default())
}; };