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 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<Client>,
/// Sync provider.
sync: Weak<SyncProvider>,
/// Contract address.
contract_addr: Option<Address>,
/// Contract at given address.
@ -57,9 +60,9 @@ pub struct DummyAclStorage {
}
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 {
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<Client>) -> Self {
pub fn new(client: &Arc<Client>, sync: &Arc<SyncProvider>) -> Self {
CachedContract {
client: Arc::downgrade(client),
sync: Arc::downgrade(sync),
contract_addr: None,
contract: None,
}
@ -105,20 +109,27 @@ impl CachedContract {
}
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() {
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)));
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())),
}
},
_ => 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
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 {
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())
};