Skip to content

Commit

Permalink
Merge pull request #17 from KILTprotocol/feature/bk_test_delegation
Browse files Browse the repository at this point in the history
Feature/bk test delegation
  • Loading branch information
bekolb committed Mar 22, 2019
2 parents 973c11b + 260e122 commit 6a9d39f
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 22 deletions.
5 changes: 4 additions & 1 deletion runtime/src/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ mod tests {
impl delegation::Trait for Test {
type Signature = Ed25519Signature;
type DelegationNodeId = H256;
}
fn print_hash(hash: Self::Hash) {
::runtime_io::print(&hash.as_bytes()[..]);
}
}

impl Trait for Test {
}
Expand Down
210 changes: 195 additions & 15 deletions runtime/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl Permissions {
let b2 : u8 = ((x >> 16) & 0xff) as u8;
let b3 : u8 = ((x >> 8) & 0xff) as u8;
let b4 : u8 = (x & 0xff) as u8;
return [b1, b2, b3, b4];
return [b4, b3, b2, b1];
}
}

Expand All @@ -41,6 +41,8 @@ pub trait Trait: ctype::Trait + system::Trait {
type Signature: Verify<Signer = Self::AccountId> + Member + Codec + Default;
type DelegationNodeId: Parameter + Member + Codec + MaybeDisplay + SimpleBitOps
+ Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]> + AsMut<[u8]>;

fn print_hash(hash: Self::Hash);
}

decl_module! {
Expand All @@ -67,21 +69,12 @@ decl_module! {
return Err("delegation already exist")
}

let mut hashed_values : Vec<Vec<u8>> = Vec::new();
hashed_values.push(delegation_id.as_ref().to_vec());
hashed_values.push(root_id.as_ref().to_vec());
match parent_id {
Some(p) => hashed_values.push(p.as_ref().to_vec()),
None => {}
}
let p = permissions.as_u8();
hashed_values.push((&p).to_vec());
let hashed_value_array = hashed_values.iter().map(Vec::as_slice).collect::<Vec<_>>();
let hash_root = T::Hashing::enumerated_trie_root(&hashed_value_array);
if !verify_encoded_lazy(&delegate_signature, &hash_root, &delegate) {
let hash_root = Self::calculate_hash(delegation_id, root_id, parent_id, permissions);
if !verify_encoded_lazy(&delegate_signature, &&hash_root, &delegate) {
// TODO: abort on signature error
::runtime_io::print("WARNING: SIGNATURE DOES NOT MATCH!");
// return Err("bad delegate signature")
::runtime_io::print("Error: signature does not match, hash:");
T::print_hash(hash_root);
return Err("bad delegate signature")
}

if <Root<T>>::exists(root_id) {
Expand Down Expand Up @@ -149,6 +142,21 @@ decl_module! {
}

impl<T: Trait> Module<T> {

fn calculate_hash(delegation_id: T::DelegationNodeId,
root_id: T::DelegationNodeId, parent_id: Option<T::DelegationNodeId>,
permissions: Permissions) -> T::Hash {
let mut hashed_values : Vec<u8> = delegation_id.as_ref().to_vec();
hashed_values.extend_from_slice(root_id.as_ref());
match parent_id {
Some(p) => hashed_values.extend_from_slice(p.as_ref()),
None => {}
}
hashed_values.extend_from_slice(permissions.as_u8().as_ref());
let hash_root = T::Hashing::hash(&hashed_values);
return hash_root;
}

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")
Expand Down Expand Up @@ -204,3 +212,175 @@ decl_storage! {
pub Children get(children): map T::DelegationNodeId => Vec<T::DelegationNodeId>;
}
}



#[cfg(test)]
mod tests {
use super::*;
use system;
use runtime_io::with_externalities;
use primitives::{H256, H512, Blake2Hasher};
use runtime_primitives::Ed25519Signature;
use primitives::*;
use support::{impl_outer_origin, assert_ok, assert_err};
use parity_codec::Encode;

use runtime_primitives::{
BuildStorage, traits::{BlakeTwo256, IdentityLookup}, testing::{Digest, DigestItem, Header}
};

impl_outer_origin! {
pub enum Origin for Test {}
}

#[derive(Clone, Eq, PartialEq)]
pub struct Test;
impl system::Trait for Test {
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type Digest = Digest;
type AccountId = H256;
type Header = Header;
type Event = ();
type Log = DigestItem;
type Lookup = IdentityLookup<H256>;
}

impl ctype::Trait for Test {
}

impl Trait for Test {
type Signature = Ed25519Signature;
type DelegationNodeId = H256;

fn print_hash(hash: Self::Hash) {
::runtime_io::print(&hash.as_bytes()[..]);
}
}

type Ctype = ctype::Module<Test>;
type Delegation = Module<Test>;

fn hash_to_u8<T : Encode> (hash : T) -> Vec<u8>{
return hash.encode();
}

fn new_test_ext() -> runtime_io::TestExternalities<Blake2Hasher> {
system::GenesisConfig::<Test>::default().build_storage().unwrap().0.into()
}

#[test]
fn check_add_and_revoke_delegations() {
with_externalities(&mut new_test_ext(), || {
let pair_alice = ed25519::Pair::from_seed(b"Alice ");
let account_hash_alice = H256::from(pair_alice.public().0);
let pair_bob = ed25519::Pair::from_seed(b"Bob ");
let account_hash_bob = H256::from(pair_bob.public().0);
let pair_charlie = ed25519::Pair::from_seed(b"Charlie ");
let account_hash_charlie = H256::from(pair_charlie.public().0);

let ctype_hash = H256::from_low_u64_be(1);
let id_level_0 = H256::from_low_u64_be(1);
let id_level_1 = H256::from_low_u64_be(2);
let id_level_2_1 = H256::from_low_u64_be(21);
let id_level_2_2 = H256::from_low_u64_be(22);

assert_ok!(Ctype::add(Origin::signed(account_hash_alice.clone()), ctype_hash.clone()));

assert_ok!(Delegation::create_root(Origin::signed(account_hash_alice.clone()), id_level_0.clone(), ctype_hash.clone()));
assert_err!(Delegation::create_root(Origin::signed(account_hash_alice.clone()), id_level_0.clone(), ctype_hash.clone()),
"root already exist");
assert_err!(Delegation::create_root(Origin::signed(account_hash_alice.clone()), id_level_1.clone(), H256::from_low_u64_be(2)),
"CTYPE does not exist");

assert_ok!(Delegation::add_delegation(Origin::signed(account_hash_alice.clone()), id_level_1.clone(), id_level_0.clone(),
None, account_hash_bob.clone(), Permissions::DELEGATE,
Ed25519Signature::from(pair_bob.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_1.clone(), id_level_0.clone(), None, Permissions::DELEGATE))))));
assert_err!(Delegation::add_delegation(Origin::signed(account_hash_alice.clone()), id_level_1.clone(), id_level_0.clone(),
None, account_hash_bob.clone(), Permissions::DELEGATE,
Ed25519Signature::from(pair_bob.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_1.clone(), id_level_0.clone(), None, Permissions::DELEGATE))))),
"delegation already exist");
assert_err!(Delegation::add_delegation(Origin::signed(account_hash_bob.clone()), id_level_2_1.clone(), id_level_0.clone(),
Some(id_level_1.clone()), account_hash_charlie.clone(), Permissions::ATTEST, Ed25519Signature::from(H512::from_low_u64_be(0))),
"bad delegate signature");
assert_err!(Delegation::add_delegation(Origin::signed(account_hash_charlie.clone()), id_level_2_1.clone(), id_level_0.clone(),
None, account_hash_bob.clone(), Permissions::DELEGATE,
Ed25519Signature::from(pair_bob.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_2_1.clone(), id_level_0.clone(), None, Permissions::DELEGATE))))),
"not owner of root");
assert_err!(Delegation::add_delegation(Origin::signed(account_hash_alice.clone()), id_level_2_1.clone(), id_level_1.clone(),
None, account_hash_bob.clone(), Permissions::DELEGATE,
Ed25519Signature::from(pair_bob.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_2_1.clone(), id_level_1.clone(), None, Permissions::DELEGATE))))),
"root not found");


assert_ok!(Delegation::add_delegation(Origin::signed(account_hash_bob.clone()), id_level_2_1.clone(), id_level_0.clone(),
Some(id_level_1.clone()), account_hash_charlie.clone(), Permissions::ATTEST,
Ed25519Signature::from(pair_charlie.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_2_1.clone(), id_level_0.clone(), Some(id_level_1.clone()), Permissions::ATTEST))))));
assert_err!(Delegation::add_delegation(Origin::signed(account_hash_alice.clone()), id_level_2_2.clone(), id_level_0.clone(),
Some(id_level_1.clone()), account_hash_charlie.clone(), Permissions::ATTEST,
Ed25519Signature::from(pair_charlie.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_2_2.clone(), id_level_0.clone(), Some(id_level_1.clone()), Permissions::ATTEST))))),
"not owner of parent");
assert_err!(Delegation::add_delegation(Origin::signed(account_hash_charlie.clone()), id_level_2_2.clone(), id_level_0.clone(),
Some(id_level_2_1.clone()), account_hash_alice.clone(), Permissions::ATTEST,
Ed25519Signature::from(pair_alice.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_2_2.clone(), id_level_0.clone(), Some(id_level_2_1.clone()), Permissions::ATTEST))))),
"not authorized to delegate");
assert_err!(Delegation::add_delegation(Origin::signed(account_hash_bob.clone()), id_level_2_2.clone(), id_level_0.clone(),
Some(id_level_0.clone()), account_hash_charlie.clone(), Permissions::ATTEST,
Ed25519Signature::from(pair_charlie.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_2_2.clone(), id_level_0.clone(), Some(id_level_0.clone()), Permissions::ATTEST))))),
"parent not found");

assert_ok!(Delegation::add_delegation(Origin::signed(account_hash_bob.clone()), id_level_2_2.clone(), id_level_0.clone(),
Some(id_level_1.clone()), account_hash_charlie.clone(), Permissions::ATTEST | Permissions::DELEGATE,
Ed25519Signature::from(pair_charlie.sign(&hash_to_u8(
Delegation::calculate_hash(id_level_2_2.clone(), id_level_0.clone(), Some(id_level_1.clone()),
Permissions::ATTEST | Permissions::DELEGATE))))));

let root = Delegation::root(id_level_0.clone());
assert_eq!(root.0, ctype_hash.clone());
assert_eq!(root.1, account_hash_alice.clone());
assert_eq!(root.2, false);

let delegation_1 = Delegation::delegation(id_level_1.clone());
assert_eq!(delegation_1.0, id_level_0.clone());
assert_eq!(delegation_1.1, None);
assert_eq!(delegation_1.2, account_hash_bob.clone());
assert_eq!(delegation_1.3, Permissions::DELEGATE);
assert_eq!(delegation_1.4, false);

let delegation_2 = Delegation::delegation(id_level_2_2.clone());
assert_eq!(delegation_2.0, id_level_0.clone());
assert_eq!(delegation_2.1, Some(id_level_1.clone()));
assert_eq!(delegation_2.2, account_hash_charlie.clone());
assert_eq!(delegation_2.3, Permissions::ATTEST | Permissions::DELEGATE);
assert_eq!(delegation_2.4, false);

let children = Delegation::children(id_level_1.clone());
assert_eq!(children.len(), 2);
assert_eq!(children[0], id_level_2_1.clone());
assert_eq!(children[1], id_level_2_2.clone());

// check is_delgating
assert_eq!(Delegation::is_delegating(&account_hash_alice, &id_level_1), Ok(true));
assert_eq!(Delegation::is_delegating(&account_hash_alice, &id_level_2_1), Ok(true));
assert_eq!(Delegation::is_delegating(&account_hash_bob, &id_level_2_1), Ok(true));
assert_eq!(Delegation::is_delegating(&account_hash_charlie, &id_level_2_1), Ok(true));
assert_eq!(Delegation::is_delegating(&account_hash_charlie, &id_level_1), Ok(false));
assert_eq!(Delegation::is_delegating(&account_hash_charlie, &id_level_0), Err("delegation not found"));

// TODO: test revocation with state and errors
// TODO: test attestation based on delegation
});
}
}
22 changes: 16 additions & 6 deletions runtime/src/did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ decl_module! {

pub fn add(origin, sign_key: T::PublicSigningKey, box_key: T::PublicBoxKey, doc_ref: Option<Vec<u8>>) -> Result {
let sender = ensure_signed(origin)?;
<DID<T>>::insert(sender.clone(), (sign_key, box_key, doc_ref));
<DIDs<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());
<DIDs<T>>::remove(sender.clone());
Ok(())
}
}
}

decl_storage! {
trait Store for Module<T: Trait> as DID {
// DID: account-id -> (did-reference?)
DID get(dids): map T::AccountId => (T::PublicSigningKey, T::PublicBoxKey, Option<Vec<u8>>);
// DID: account-id -> (public-signing-key, public-encryption-key, did-reference?)
DIDs get(dids): map T::AccountId => (T::PublicSigningKey, T::PublicBoxKey, Option<Vec<u8>>);
}
}

Expand Down Expand Up @@ -84,10 +84,20 @@ mod tests {
fn check_add_did() {
with_externalities(&mut new_test_ext(), || {
let pair = ed25519::Pair::from_seed(b"Alice ");
let hash = H256::from_low_u64_be(1);
let signing_key = H256::from_low_u64_be(1);
let box_key = H256::from_low_u64_be(2);
let account_hash = H256::from(pair.public().0);
assert_ok!(DID::add(Origin::signed(account_hash.clone()),
hash.clone(), hash.clone(), Some(b"http://kilt.org/submit".to_vec())));
signing_key.clone(), box_key.clone(), Some(b"http://kilt.org/submit".to_vec())));

assert_eq!(<DIDs<Test>>::exists(account_hash), true);
let did = DID::dids(account_hash.clone());
assert_eq!(did.0, signing_key.clone());
assert_eq!(did.1, box_key.clone());
assert_eq!(did.2, Some(b"http://kilt.org/submit".to_vec()));

assert_ok!(DID::remove(Origin::signed(account_hash.clone())));
assert_eq!(<DIDs<Test>>::exists(account_hash), false);
});
}
}
5 changes: 5 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ impl ctype::Trait for Runtime {
impl delegation::Trait for Runtime {
type Signature = Ed25519Signature;
type DelegationNodeId = Hash;

fn print_hash(hash: Hash) {
::runtime_io::print(&hash.as_bytes()[..]);
}

}

impl did::Trait for Runtime {
Expand Down

0 comments on commit 6a9d39f

Please sign in to comment.