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: add DIP to Peregrine #594

Merged
merged 4 commits into from
Dec 12, 2023
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
3 changes: 3 additions & 0 deletions Cargo.lock

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

7 changes: 5 additions & 2 deletions dip-template/runtimes/dip-provider/src/dip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,11 @@ pub mod deposit {

/// The additional logic to execute whenever a deposit is removed by its
/// owner directly via the [`pallet_deposit_storage::Pallet`] pallet.
pub type DepositCollectorHooks =
FixedDepositCollectorViaDepositsPallet<DipProviderDepositNamespace, ConstU128<DEPOSIT_AMOUNT>>;
pub type DepositCollectorHooks = FixedDepositCollectorViaDepositsPallet<
DipProviderDepositNamespace,
ConstU128<DEPOSIT_AMOUNT>,
(DidIdentifier, IdentityCommitmentVersion),
>;

pub enum CommitmentDepositRemovalHookError {
DecodeKey,
Expand Down
2 changes: 1 addition & 1 deletion pallets/pallet-deposit-storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ std = [
"frame-benchmarking?/std",
"pallet-balances?/std",
]

runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
Expand All @@ -59,3 +58,4 @@ runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
]
try-runtime = []
28 changes: 16 additions & 12 deletions pallets/pallet-deposit-storage/src/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ pub struct DepositEntry<AccountId, Balance, Reason> {
/// Type implementing the [`DipProviderHooks`] hooks trait by taking a deposit
/// whenever an identity commitment is stored, and releasing the deposit
/// whenever an identity commitment is removed.
pub struct FixedDepositCollectorViaDepositsPallet<DepositsNamespace, FixedDepositAmount>(
PhantomData<(DepositsNamespace, FixedDepositAmount)>,
pub struct FixedDepositCollectorViaDepositsPallet<DepositsNamespace, FixedDepositAmount, DepositKey>(
PhantomData<(DepositsNamespace, FixedDepositAmount, DepositKey)>,
);

pub enum FixedDepositCollectorViaDepositsPalletError {
Expand All @@ -68,12 +68,13 @@ impl From<FixedDepositCollectorViaDepositsPalletError> for u16 {
}
}

impl<Runtime, DepositsNamespace, FixedDepositAmount> DipProviderHooks<Runtime>
for FixedDepositCollectorViaDepositsPallet<DepositsNamespace, FixedDepositAmount>
impl<Runtime, DepositsNamespace, FixedDepositAmount, DepositKey> DipProviderHooks<Runtime>
for FixedDepositCollectorViaDepositsPallet<DepositsNamespace, FixedDepositAmount, DepositKey>
where
Runtime: pallet_dip_provider::Config + Config,
DepositsNamespace: Get<Runtime::Namespace>,
FixedDepositAmount: Get<BalanceOf<Runtime>>,
DepositKey: From<(Runtime::Identifier, IdentityCommitmentVersion)> + Encode,
{
type Error = u16;

Expand All @@ -84,14 +85,17 @@ where
version: IdentityCommitmentVersion,
) -> Result<(), Self::Error> {
let namespace = DepositsNamespace::get();
let key = (identifier, version).encode().try_into().map_err(|_| {
log::error!(
"Failed to convert tuple ({:#?}, {version}) to BoundedVec with max length {}",
identifier,
Runtime::MaxKeyLength::get()
);
FixedDepositCollectorViaDepositsPalletError::Internal
})?;
let key = DepositKey::from((identifier.clone(), version))
.encode()
.try_into()
.map_err(|_| {
log::error!(
"Failed to convert tuple ({:#?}, {version}) to BoundedVec with max length {}",
identifier,
Runtime::MaxKeyLength::get()
);
FixedDepositCollectorViaDepositsPalletError::Internal
})?;
let deposit_entry = DepositEntry {
deposit: Deposit {
amount: FixedDepositAmount::get(),
Expand Down
2 changes: 2 additions & 0 deletions pallets/pallet-dip-consumer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ std = [
"frame-benchmarking?/std",
"sp-runtime?/std",
]

try-runtime = []
Copy link
Member

Choose a reason for hiding this comment

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

frame-system and other pallets are missing. Can be done in another PR I guess. Just afraid that the try-runtime tests are not working right now. Did you verify that?

Copy link
Member Author

Choose a reason for hiding this comment

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

The pallet does not have any support for try-runtime yet. It was required for clippy not to complain. I guess once we add support for try-runtime (e.g., once we have a migration), then we will import the required dependencies?

Copy link
Member Author

Choose a reason for hiding this comment

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

I mean for the runtime to compile, but in essence having the feature enabled has no effect on those pallets (yet).

1 change: 1 addition & 0 deletions pallets/pallet-relay-store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ runtime-benchmarks = [
"frame-benchmarking",
"sp-runtime/runtime-benchmarks",
]
try-runtime = []
16 changes: 16 additions & 0 deletions runtimes/common/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,22 @@ pub mod delegation {
}
}

pub mod deposit_storage {
// Keys is an enum with a single variant (DidIdentifier,
// IdentityCommitmentVersion) which is 32 + 2 = 34 bytes. Adding the
// discriminant byte, it totals to 35 bytes.
pub const MAX_DEPOSIT_PALLET_KEY_LENGTH: u32 = 35;
}

pub mod dip_provider {
use super::*;

pub const MAX_LINKED_ACCOUNTS: u32 = 10;
// Commitment are 32-byte hashes.
pub const MAX_COMMITMENT_BYTE_LENGTH: u32 = 32;
pub const COMMITMENT_DEPOSIT: Balance = deposit(1, MAX_COMMITMENT_BYTE_LENGTH);
}

pub mod staking {
use super::*;

Expand Down
10 changes: 10 additions & 0 deletions runtimes/peregrine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ attestation.workspace = true
ctype.workspace = true
delegation.workspace = true
did.workspace = true
kilt-runtime-api-dip-provider.workspace = true
kilt-support.workspace = true
pallet-configuration.workspace = true
pallet-deposit-storage.workspace = true
pallet-did-lookup.workspace = true
pallet-dip-provider.workspace = true
pallet-inflation.workspace = true
pallet-web3-names.workspace = true
pallet-migration.workspace = true
Expand Down Expand Up @@ -129,7 +132,9 @@ runtime-benchmarks = [
"pallet-collective/runtime-benchmarks",
"pallet-configuration/runtime-benchmarks",
"pallet-democracy/runtime-benchmarks",
"pallet-deposit-storage/runtime-benchmarks",
"pallet-did-lookup/runtime-benchmarks",
"pallet-dip-provider/runtime-benchmarks",
"pallet-indices/runtime-benchmarks",
"pallet-inflation/runtime-benchmarks",
"pallet-membership/runtime-benchmarks",
Expand Down Expand Up @@ -175,6 +180,7 @@ std = [
"frame-system/std",
"frame-try-runtime?/std",
"kilt-runtime-api-did/std",
"kilt-runtime-api-dip-provider/std",
"kilt-runtime-api-public-credentials/std",
"kilt-runtime-api-staking/std",
"kilt-support/std",
Expand All @@ -186,7 +192,9 @@ std = [
"pallet-collective/std",
"pallet-configuration/std",
"pallet-democracy/std",
"pallet-deposit-storage/std",
"pallet-did-lookup/std",
"pallet-dip-provider/std",
"pallet-indices/std",
"pallet-inflation/std",
"pallet-membership/std",
Expand Down Expand Up @@ -249,7 +257,9 @@ try-runtime = [
"pallet-collective/try-runtime",
"pallet-configuration/try-runtime",
"pallet-democracy/try-runtime",
"pallet-deposit-storage/try-runtime",
"pallet-did-lookup/try-runtime",
"pallet-dip-provider/try-runtime",
"pallet-indices/try-runtime",
"pallet-inflation/try-runtime",
"pallet-membership/try-runtime",
Expand Down
149 changes: 149 additions & 0 deletions runtimes/peregrine/src/dip/deposit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// KILT Blockchain – https://botlabs.org
// Copyright (C) 2019-2023 BOTLabs GmbH

// The KILT Blockchain is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The KILT Blockchain is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// If you feel like getting in touch with us, you can do so at info@botlabs.org

use crate::{DidIdentifier, Runtime};
use frame_support::traits::Get;
use pallet_deposit_storage::{
traits::DepositStorageHooks, DepositEntryOf, DepositKeyOf, FixedDepositCollectorViaDepositsPallet,
};
use pallet_dip_provider::IdentityCommitmentVersion;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use runtime_common::constants::dip_provider::COMMITMENT_DEPOSIT;
use scale_info::TypeInfo;
use sp_core::{ConstU128, RuntimeDebug};

#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)]
pub enum DepositNamespace {
DipProvider,
}

/// The namespace to use in the [`pallet_deposit_storage::Pallet`] to store
/// all deposits related to DIP commitments.
pub struct DipProviderDepositNamespace;

impl Get<DepositNamespace> for DipProviderDepositNamespace {
fn get() -> DepositNamespace {
DepositNamespace::DipProvider
}
}

/// The various different keys that can be stored in the storage-tracking
/// pallet.
#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)]
pub enum DepositKey {
DipProvider {
identifier: DidIdentifier,
version: IdentityCommitmentVersion,
},
}

impl From<(DidIdentifier, IdentityCommitmentVersion)> for DepositKey {
fn from((identifier, version): (DidIdentifier, IdentityCommitmentVersion)) -> Self {
Self::DipProvider { identifier, version }
}
}

/// The additional logic to execute whenever a deposit is removed by its
/// owner directly via the [`pallet_deposit_storage::Pallet`] pallet.
pub type DepositCollectorHooks =
FixedDepositCollectorViaDepositsPallet<DipProviderDepositNamespace, ConstU128<COMMITMENT_DEPOSIT>, DepositKey>;

pub enum CommitmentDepositRemovalHookError {
DecodeKey,
Internal,
}

impl From<CommitmentDepositRemovalHookError> for u16 {
fn from(value: CommitmentDepositRemovalHookError) -> Self {
match value {
CommitmentDepositRemovalHookError::DecodeKey => 0,
CommitmentDepositRemovalHookError::Internal => u16::MAX,
}
}
}

/// The logic to execute whenever an identity commitment is generated and
/// stored in the [`pallet_dip_provider::Pallet`] pallet.
///
/// Upon storing and removing identity commitments, this hook will reserve
/// or release deposits from the [`pallet_deposit_storage::Pallet`] pallet.
pub struct DepositHooks;

impl DepositStorageHooks<Runtime> for DepositHooks {
type Error = CommitmentDepositRemovalHookError;

fn on_deposit_reclaimed(
_namespace: &<Runtime as pallet_deposit_storage::Config>::Namespace,
key: &DepositKeyOf<Runtime>,
deposit: DepositEntryOf<Runtime>,
) -> Result<(), Self::Error> {
let DepositKey::DipProvider { identifier, version } =
DepositKey::decode(&mut &key[..]).map_err(|_| CommitmentDepositRemovalHookError::DecodeKey)?;
pallet_dip_provider::Pallet::<Runtime>::delete_identity_commitment_storage_entry(
&identifier,
// Deposit owner is the only one authorized to remove the deposit.
&deposit.deposit.owner,
version,
)
.map_err(|_| {
log::error!(
"Should not fail to remove commitment for identifier {:#?} and version {version}",
identifier
);
CommitmentDepositRemovalHookError::Internal
})?;
Ok(())
}
}

#[cfg(feature = "runtime-benchmarks")]
pub struct PalletDepositStorageBenchmarkHooks;

#[cfg(feature = "runtime-benchmarks")]
impl pallet_deposit_storage::traits::BenchmarkHooks<Runtime> for PalletDepositStorageBenchmarkHooks {
fn pre_reclaim_deposit() -> (
<Runtime as frame_system::Config>::AccountId,
<Runtime as pallet_deposit_storage::Config>::Namespace,
sp_runtime::BoundedVec<u8, <Runtime as pallet_deposit_storage::Config>::MaxKeyLength>,
) {
let submitter = runtime_common::AccountId::from([100u8; 32]);
let namespace = DepositNamespace::DipProvider;
let did_identifier = DidIdentifier::from([200u8; 32]);
let commitment_version = 0u16;
let key: DepositKeyOf<Runtime> = (did_identifier.clone(), 0)
.encode()
.try_into()
.expect("Should not fail to create a key for a DIP commitment.");

pallet_dip_provider::IdentityCommitments::<Runtime>::insert(
&did_identifier,
commitment_version,
<Runtime as frame_system::Config>::Hash::default(),
);

assert!(pallet_dip_provider::IdentityCommitments::<Runtime>::get(did_identifier, commitment_version).is_some());

(submitter, namespace, key)
}

fn post_reclaim_deposit() {
let did_identifier = DidIdentifier::from([200u8; 32]);
let commitment_version = 0u16;
assert!(pallet_dip_provider::IdentityCommitments::<Runtime>::get(did_identifier, commitment_version).is_none());
}
}
Loading