Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: revoke delegations #15

Merged
merged 2 commits into from Mar 15, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 37 additions & 6 deletions runtime/src/attestation.rs
@@ -1,3 +1,5 @@

use rstd::result;
use rstd::prelude::*;
use support::{dispatch::Result, StorageMap, decl_module, decl_storage};
use {system, super::delegation, super::ctype, system::ensure_signed};
Expand All @@ -19,13 +21,13 @@ decl_module! {
let delegation = <delegation::Delegations<T>>::get(d.clone());
if delegation.4 {
return Err("delegation revoked")
} else if delegation.2 != sender {
} else if !delegation.2.eq(&sender) {
return Err("not delegated to attester")
} else if delegation.3 & delegation::Permissions::ATTEST != delegation::Permissions::ATTEST {
} else if (delegation.3 & delegation::Permissions::ATTEST) != delegation::Permissions::ATTEST {
return Err("delegation not authorized to attest")
} else {
let root = <delegation::Root<T>>::get(delegation.0.clone());
if root.0 != ctype_hash {
if !root.0.eq(&ctype_hash) {
return Err("CTYPE of delegation does not match")
}
}
Expand All @@ -47,6 +49,14 @@ decl_module! {
::runtime_io::print("insert Attestation");
existing_attestations_for_claim.push((ctype_hash.clone(), sender.clone(), delegation_id.clone(), false));
<Attestations<T>>::insert(claim_hash.clone(), existing_attestations_for_claim);
match delegation_id {
Some(d) => {
let mut delegated_attestations = <DelegatedAttestations<T>>::get(d);
delegated_attestations.push(claim_hash.clone());
<DelegatedAttestations<T>>::insert(d.clone(), delegated_attestations);
},
None => {}
}
Ok(())
},
}
Expand All @@ -58,9 +68,22 @@ decl_module! {
let mut last_attested : bool = false;
let mut existing_attestations_for_claim = <Attestations<T>>::get(claim_hash.clone());
for v in existing_attestations_for_claim.iter_mut() {
if v.1.eq(&sender) && !v.3 {
last_attested = true;
v.3 = true;
if !v.3 {
if v.1.eq(&sender) && !v.3 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&& !v.3 redundant. Already checked.

last_attested = true;
v.3 = true;
} else {
// check delegator in case of delegation
match v.2 {
Some(d) => {
if Self::is_delegating(&sender, &d)? {
last_attested = true;
v.3 = true;
}
},
None => {}
}
}
}
}
if last_attested {
Expand All @@ -73,10 +96,18 @@ decl_module! {
}
}

impl<T: Trait> Module<T> {
fn is_delegating(account: &T::AccountId, delegation: &T::DelegationNodeId) -> result::Result<bool, &'static str> {
<delegation::Module<T>>::is_delegating(account, delegation)
}
}

decl_storage! {
trait Store for Module<T: Trait> as Attestation {
// Attestations: claim-hash -> [(ctype-hash, account, delegation-id?, revoked)]
Attestations get(attestations): map T::Hash => Vec<(T::Hash,T::AccountId,Option<T::DelegationNodeId>,bool)>;
// DelegatedAttestations: delegation-id -> [claim-hash]
DelegatedAttestations get(delegated_attestations): map T::DelegationNodeId => Vec<T::Hash>;
}
}

Expand Down
84 changes: 80 additions & 4 deletions runtime/src/delegation.rs
@@ -1,4 +1,5 @@

use rstd::result;
use rstd::prelude::*;
use runtime_primitives::traits::{Hash, CheckEqual, SimpleBitOps, Member, Verify, MaybeDisplay};
use support::{dispatch::Result, StorageMap, Parameter, decl_module, decl_storage};
Expand Down Expand Up @@ -89,32 +90,107 @@ decl_module! {
Some(p) => {
if <Delegations<T>>::exists(p) {
let parent = <Delegations<T>>::get(p.clone());
if parent.2 != sender {
if !parent.2.eq(&sender) {
return Err("not owner of parent")
} else if parent.3 & Permissions::DELEGATE != Permissions::DELEGATE {
} else if (parent.3 & Permissions::DELEGATE) != Permissions::DELEGATE {
return Err("not authorized to delegate")
} else {
// TODO: check for cycles
// TODO: check for cycles?
::runtime_io::print("insert Delegation with parent");
<Delegations<T>>::insert(delegation_id.clone(), (root_id.clone(), Some(p.clone()), delegate, permissions, false));
Self::add_child(delegation_id.clone(), p.clone());
}
} else {
return Err("parent not found")
}
},
None => {
if root.1 != sender {
if !root.1.eq(&sender) {
return Err("not owner of root")
}
::runtime_io::print("insert Delegation without parent");
<Delegations<T>>::insert(delegation_id.clone(), (root_id.clone(), None, delegate, permissions, false));
Self::add_child(delegation_id.clone(), root_id.clone());
}
}
} else {
return Err("root not found")
}
return Ok(());
}

pub fn revoke_root(origin, root_id: T::DelegationNodeId) -> Result {
let sender = ensure_signed(origin)?;
if !<Root<T>>::exists(root_id) {
return Err("root not found")
}
let mut r = <Root<T>>::get(root_id.clone());
if !r.1.eq(&sender) {
return Err("not permitted to revoke")
}
if !r.2 {
r.2 = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r.2 = true

<Root<T>>::insert(root_id.clone(), r);
Self::revoke_children(&root_id);
}

return Ok(());
}

pub fn revoke_delegation(origin, delegation_id: T::DelegationNodeId) -> Result {
let sender = ensure_signed(origin)?;
if !Self::is_delegating(&sender, &delegation_id)? {
return Err("not permitted to revoke")
}
Self::revoke(&delegation_id);
return Ok(());
}
}
}

impl<T: Trait> Module<T> {
pub fn is_delegating(account: &T::AccountId, delegation: &T::DelegationNodeId) -> result::Result<bool, &'static str> {
if !<Delegations<T>>::exists(delegation) {
return Err("delegation not found")
}
let d = <Delegations<T>>::get(delegation);
if d.2.eq(account) {
Ok(true)
} else {
match d.1 {
None => {
let r = <Root<T>>::get(d.0.clone());
Ok(r.1.eq(account))
},
Some(p) => {
return Self::is_delegating(account, &p)
}
}
}
}

fn revoke(delegation: &T::DelegationNodeId) {
let mut d = <Delegations<T>>::get(delegation.clone());
if !d.4 {
d.4 = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d.4 = true

<Delegations<T>>::insert(delegation.clone(), d);
Self::revoke_children(delegation);
}
}

fn revoke_children(delegation: &T::DelegationNodeId) {
if <Children<T>>::exists(delegation) {
let children = <Children<T>>::get(delegation);
for child in children {
Self::revoke(&child);
}
}
}

fn add_child(child: T::DelegationNodeId, parent: T::DelegationNodeId) {
let mut children = <Children<T>>::get(parent.clone());
children.push(child);
<Children<T>>::insert(parent, children);
}
}

Expand Down
6 changes: 6 additions & 0 deletions runtime/src/did.rs
Expand Up @@ -19,6 +19,12 @@ decl_module! {
<DID<T>>::insert(sender.clone(), (sign_key, box_key, doc_ref));
Ok(())
}

pub fn remove(origin) -> Result {
let sender = ensure_signed(origin)?;
<DID<T>>::remove(sender.clone());
Ok(())
}
}
}

Expand Down