Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion nodes/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ serde = {version = "1.0.137", features = ["derive"]}
# Runtime dependencies
kilt-support = {path = "../../support"}
public-credentials = {path = "../../pallets/public-credentials"}

public-credentials-rpc = {path = "../../rpc/public-credentials"}
runtime-common = {path = "../../runtimes/common"}

[features]
default = []
62 changes: 48 additions & 14 deletions nodes/common/src/public_credentials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,66 @@ use serde::{Deserialize, Serialize};
use kilt_support::deposit::Deposit;
use public_credentials::CredentialEntry;

use public_credentials_rpc::PublicCredentialsFilter;

#[derive(Serialize, Deserialize)]
#[serde(bound(
serialize = "
BlockNumber: Serialize,
Balance: std::fmt::Display,
AccountId: Serialize",
deserialize = "
BlockNumber: Deserialize<'de>,
Balance: std::str::FromStr,
AccountId: Deserialize<'de>",
))]
/// Thin wrapper around a runtime credential entry as specified in the
/// `public-credentials` pallet. This wrapper implements all the
/// (de-)serialization logic.
pub struct OuterCredentialEntry<BlockNumber, AccountId, Balance> {
pub struct OuterCredentialEntry<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId> {
pub ctype_hash: CTypeHash,
pub attester: Attester,
pub revoked: bool,
pub block_number: BlockNumber,
#[serde(bound(
serialize = "AccountId: Serialize, Balance: std::fmt::Display",
deserialize = "AccountId: Deserialize<'de>, Balance: std::str::FromStr"
))]
pub deposit: Deposit<AccountId, Balance>,
pub authorization_id: Option<AuthorizationId>,
}

impl<BlockNumber, AccountId, Balance> From<CredentialEntry<BlockNumber, AccountId, Balance>>
for OuterCredentialEntry<BlockNumber, AccountId, Balance>
impl<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId>
From<CredentialEntry<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId>>
for OuterCredentialEntry<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId>
{
fn from(value: CredentialEntry<BlockNumber, AccountId, Balance>) -> Self {
fn from(value: CredentialEntry<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId>) -> Self {
Self {
ctype_hash: value.ctype_hash,
attester: value.attester,
revoked: value.revoked,
block_number: value.block_number,
deposit: value.deposit,
authorization_id: value.authorization_id,
}
}
}

/// Filter for public credentials retrieved for a provided subject as specified
/// in the RPC interface.
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum PublicCredentialFilter<CTypeHash, Attester> {
/// Filter credentials that match a specified Ctype.
CtypeHash(CTypeHash),
/// Filter credentials that have been issued by the specified attester.
Attester(Attester),
}

impl<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId>
PublicCredentialsFilter<CredentialEntry<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId>>
for PublicCredentialFilter<CTypeHash, Attester>
where
CTypeHash: Eq,
Attester: Eq,
{
fn should_include(
&self,
credential: &CredentialEntry<CTypeHash, Attester, BlockNumber, AccountId, Balance, AuthorizationId>,
) -> bool {
match self {
Self::CtypeHash(ctype_hash) => ctype_hash == &credential.ctype_hash,
Self::Attester(attester) => attester == &credential.attester,
}
}
}
19 changes: 15 additions & 4 deletions nodes/parachain/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};

use pallet_did_lookup::linkable_account::LinkableAccountId;
use public_credentials::CredentialEntry;
use runtime_common::{AccountId, Balance, Block, BlockNumber, DidIdentifier, Hash, Index};
use runtime_common::{
authorization::AuthorizationId, AccountId, Balance, Block, BlockNumber, DidIdentifier, Hash, Index,
};

/// Full client dependencies.
pub struct FullDeps<C, P> {
Expand All @@ -62,7 +64,7 @@ where
Block,
runtime_common::assets::AssetDid,
Hash,
CredentialEntry<BlockNumber, AccountId, Balance>,
CredentialEntry<Hash, DidIdentifier, BlockNumber, AccountId, Balance, AuthorizationId<Hash>>,
>,
P: TransactionPool + 'static,
{
Expand Down Expand Up @@ -99,9 +101,18 @@ where
// Runtime credential ID
Hash,
// Input/output credential entry
node_common::OuterCredentialEntry<BlockNumber, AccountId, Balance>,
node_common::OuterCredentialEntry<
Hash,
DidIdentifier,
BlockNumber,
AccountId,
Balance,
AuthorizationId<Hash>,
>,
// Runtime credential entry
CredentialEntry<BlockNumber, AccountId, Balance>,
CredentialEntry<Hash, DidIdentifier, BlockNumber, AccountId, Balance, AuthorizationId<Hash>>,
// Credential filter
node_common::PublicCredentialFilter<Hash, DidIdentifier>,
>::new(client)
.into_rpc(),
)?;
Expand Down
8 changes: 5 additions & 3 deletions nodes/parachain/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ use sp_runtime::traits::BlakeTwo256;

use pallet_did_lookup::linkable_account::LinkableAccountId;
use public_credentials::CredentialEntry;
use runtime_common::{AccountId, AuthorityId, Balance, BlockNumber, DidIdentifier, Index};
use runtime_common::{
authorization::AuthorizationId, AccountId, AuthorityId, Balance, BlockNumber, DidIdentifier, Index,
};

type Header = sp_runtime::generic::Header<BlockNumber, sp_runtime::traits::BlakeTwo256>;
pub type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
Expand Down Expand Up @@ -247,7 +249,7 @@ where
Block,
runtime_common::assets::AssetDid,
Hash,
CredentialEntry<BlockNumber, AccountId, Balance>,
CredentialEntry<Hash, DidIdentifier, BlockNumber, AccountId, Balance, AuthorizationId<Hash>>,
>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
Executor: sc_executor::NativeExecutionDispatch + 'static,
Expand Down Expand Up @@ -496,7 +498,7 @@ where
Block,
runtime_common::assets::AssetDid,
Hash,
CredentialEntry<BlockNumber, AccountId, Balance>,
CredentialEntry<Hash, DidIdentifier, BlockNumber, AccountId, Balance, AuthorizationId<Hash>>,
>,
sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,
{
Expand Down
19 changes: 15 additions & 4 deletions nodes/standalone/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};

use pallet_did_lookup::linkable_account::LinkableAccountId;
use public_credentials::CredentialEntry;
use runtime_common::{AccountId, Balance, Block, BlockNumber, DidIdentifier, Hash, Index};
use runtime_common::{
authorization::AuthorizationId, AccountId, Balance, Block, BlockNumber, DidIdentifier, Hash, Index,
};

/// Full client dependencies.
pub struct FullDeps<C, P> {
Expand All @@ -62,7 +64,7 @@ where
Block,
runtime_common::assets::AssetDid,
Hash,
CredentialEntry<BlockNumber, AccountId, Balance>,
CredentialEntry<Hash, DidIdentifier, BlockNumber, AccountId, Balance, AuthorizationId<Hash>>,
>,
P: TransactionPool + 'static,
{
Expand Down Expand Up @@ -100,9 +102,18 @@ where
// Runtime credential ID
Hash,
// Input/output credential entry
node_common::OuterCredentialEntry<BlockNumber, AccountId, Balance>,
node_common::OuterCredentialEntry<
Hash,
DidIdentifier,
BlockNumber,
AccountId,
Balance,
AuthorizationId<Hash>,
>,
// Runtime credential entry
CredentialEntry<BlockNumber, AccountId, Balance>,
CredentialEntry<Hash, DidIdentifier, BlockNumber, AccountId, Balance, AuthorizationId<Hash>>,
// Credential filter
node_common::PublicCredentialFilter<Hash, DidIdentifier>,
>::new(client)
.into_rpc(),
)?;
Expand Down
2 changes: 2 additions & 0 deletions pallets/delegation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ sp-keystore = {branch = "polkadot-v0.9.25", git = "https://github.com/paritytech
attestation = {default-features = false, path = "../attestation"}
ctype = {default-features = false, path = "../ctype"}
kilt-support = {default-features = false, path = "../../support"}
public-credentials = {default-features = false, path = "../public-credentials"}

#External dependencies
bitflags = {default-features = false, version = "1.3.2"}
Expand Down Expand Up @@ -77,6 +78,7 @@ std = [
"kilt-support/std",
"log/std",
"pallet-balances/std",
"public-credentials/std",
"scale-info/std",
"sp-core/std",
"sp-io/std",
Expand Down
93 changes: 93 additions & 0 deletions pallets/delegation/src/access_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use sp_runtime::DispatchError;

use attestation::ClaimHashOf;
use ctype::CtypeHashOf;
use public_credentials::CredentialIdOf;

use crate::{
default_weights::WeightInfo, Config, DelegationHierarchies, DelegationNodeIdOf, DelegationNodes, DelegatorIdOf,
Expand Down Expand Up @@ -120,6 +121,98 @@ impl<T: Config>
}
}

// Duplicates the same logic that exists for attestations, and uses the result
// of `can_revoke()` to define `can_unrevoke()`.
impl<T: Config + public_credentials::Config>
public_credentials::PublicCredentialsAccessControl<
DelegatorIdOf<T>,
DelegationNodeIdOf<T>,
CtypeHashOf<T>,
CredentialIdOf<T>,
> for DelegationAc<T>
{
fn can_issue(
&self,
who: &DelegatorIdOf<T>,
ctype: &CtypeHashOf<T>,
_credential_id: &CredentialIdOf<T>,
) -> Result<Weight, DispatchError> {
let delegation_node =
DelegationNodes::<T>::get(self.authorization_id()).ok_or(Error::<T>::DelegationNotFound)?;
let root =
DelegationHierarchies::<T>::get(delegation_node.hierarchy_root_id).ok_or(Error::<T>::DelegationNotFound)?;
ensure!(
// has permission
((delegation_node.details.permissions & Permissions::ATTEST) == Permissions::ATTEST)
// not revoked
&& !delegation_node.details.revoked
// is owner of delegation
&& &delegation_node.details.owner == who
// delegation matches the ctype
&& &root.ctype_hash == ctype,
Error::<T>::AccessDenied
);

Ok(<T as Config>::WeightInfo::can_attest())
}

fn can_revoke(
&self,
who: &DelegatorIdOf<T>,
_ctype: &CtypeHashOf<T>,
_credential_id: &CredentialIdOf<T>,
attester_node_id: &DelegationNodeIdOf<T>,
) -> Result<Weight, DispatchError> {
// NOTE: The node IDs of the sender (provided by the user through `who`) and
// attester (provided by the attestation pallet through on-chain storage) can be
// different!
match Pallet::<T>::is_delegating(who, attester_node_id, self.max_checks)? {
(true, checks) => Ok(<T as Config>::WeightInfo::can_revoke(checks)),
_ => Err(Error::<T>::AccessDenied.into()),
}
}

fn can_unrevoke(
&self,
who: &DelegatorIdOf<T>,
ctype: &CtypeHashOf<T>,
credential_id: &CredentialIdOf<T>,
attester_node_id: &DelegationNodeIdOf<T>,
) -> Result<Weight, DispatchError> {
self.can_revoke(who, ctype, credential_id, attester_node_id)
}

fn can_remove(
&self,
who: &DelegatorIdOf<T>,
ctype: &CtypeHashOf<T>,
credential_id: &CredentialIdOf<T>,
auth_id: &DelegationNodeIdOf<T>,
) -> Result<Weight, DispatchError> {
self.can_revoke(who, ctype, credential_id, auth_id)
}

fn authorization_id(&self) -> DelegationNodeIdOf<T> {
self.subject_node_id
}

fn can_issue_weight(&self) -> Weight {
<T as Config>::WeightInfo::can_attest()
}

fn can_revoke_weight(&self) -> Weight {
<T as Config>::WeightInfo::can_revoke(self.max_checks)
}

fn can_unrevoke_weight(&self) -> Weight {
<T as Config>::WeightInfo::can_revoke(self.max_checks)
}

fn can_remove_weight(&self) -> Weight {
<T as Config>::WeightInfo::can_remove(self.max_checks)
}
}

#[cfg(test)]
mod tests {
use frame_support::{assert_noop, assert_ok};
Expand Down
3 changes: 0 additions & 3 deletions pallets/public-credentials/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ repository = "https://github.com/KILTprotocol/kilt-node"
version = "1.7.0"

[dev-dependencies]
attestation = {features = ["mock"], path = "../attestation"}
ctype = {features = ["mock"], path = "../ctype"}
kilt-support = {features = ["mock"], path = "../../support"}

Expand All @@ -23,7 +22,6 @@ log = "0.4.17"
scale-info = {version = "2.1.1", default-features = false, features = ["derive"]}

# Internal dependencies
attestation = {default-features = false, path = "../attestation"}
ctype = {default-features = false, path = "../ctype"}
kilt-support = {default-features = false, path = "../../support"}

Expand Down Expand Up @@ -51,7 +49,6 @@ std = [
"log/std",
"scale-info/std",

"attestation/std",
"ctype/std",
"kilt-support/std",

Expand Down
Loading