|
@@ -1,188 +0,0 @@
|
|
-//! # Service discovery module
|
|
|
|
-//! Service discovery module for the Joystream platform supports the storage providers.
|
|
|
|
-//! It registers their 'pings' in the system with the expiration time, and stores the bootstrap
|
|
|
|
-//! nodes for the Colossus.
|
|
|
|
-//!
|
|
|
|
-//! ## Comments
|
|
|
|
-//!
|
|
|
|
-//! Service discovery module uses working group module to authorize actions. It is generally used by
|
|
|
|
-//! the Colossus service.
|
|
|
|
-//!
|
|
|
|
-//! ## Supported extrinsics
|
|
|
|
-//!
|
|
|
|
-//! - [set_ipns_id](./struct.Module.html#method.set_ipns_id) - Creates the ServiceProviderRecord to save an IPNS identity for the storage provider.
|
|
|
|
-//! - [unset_ipns_id](./struct.Module.html#method.unset_ipns_id) - Deletes the ServiceProviderRecord with the IPNS identity for the storage provider.
|
|
|
|
-//! - [set_default_lifetime](./struct.Module.html#method.set_default_lifetime) - Sets default lifetime for storage providers accounts info.
|
|
|
|
-//! - [set_bootstrap_endpoints](./struct.Module.html#method.set_bootstrap_endpoints) - Sets bootstrap endpoints for the Colossus.
|
|
|
|
-//!
|
|
|
|
-
|
|
|
|
-// Ensure we're `no_std` when compiling for Wasm.
|
|
|
|
-#![cfg_attr(not(feature = "std"), no_std)]
|
|
|
|
-
|
|
|
|
-mod mock;
|
|
|
|
-mod tests;
|
|
|
|
-
|
|
|
|
-use codec::{Decode, Encode};
|
|
|
|
-use common::Url;
|
|
|
|
-
|
|
|
|
-#[cfg(feature = "std")]
|
|
|
|
-use serde::{Deserialize, Serialize};
|
|
|
|
-
|
|
|
|
-use frame_support::{decl_event, decl_module, decl_storage, ensure};
|
|
|
|
-use sp_std::vec::Vec;
|
|
|
|
-use system::ensure_root;
|
|
|
|
-/*
|
|
|
|
- Although there is support for ed25519 keys as the IPNS identity key and we could potentially
|
|
|
|
- reuse the same key for the role account and ipns (and make this discovery module obselete)
|
|
|
|
- it is probably better to separate concerns.
|
|
|
|
- Why not to use a fixed size 32byte -> SHA256 hash of public key: because we would have to force
|
|
|
|
- specific key type on ipfs side.
|
|
|
|
- pub struct IPNSIdentity(pub [u8; 32]); // we loose the key type!
|
|
|
|
- pub type IPNSIdentity(pub u8, pub [u8; 32]); // we could add the keytype?
|
|
|
|
- can we use rust library in wasm runtime?
|
|
|
|
- https://github.com/multiformats/rust-multihash
|
|
|
|
- https://github.com/multiformats/multicodec/
|
|
|
|
- https://github.com/multiformats/multihash/
|
|
|
|
-*/
|
|
|
|
-/// base58 encoded IPNS identity multihash codec
|
|
|
|
-pub type IPNSIdentity = Vec<u8>;
|
|
|
|
-
|
|
|
|
-// The storage working group instance alias.
|
|
|
|
-pub(crate) type StorageWorkingGroupInstance = working_group::Instance2;
|
|
|
|
-
|
|
|
|
-// Alias for storage working group.
|
|
|
|
-pub(crate) type StorageWorkingGroup<T> = working_group::Module<T, StorageWorkingGroupInstance>;
|
|
|
|
-
|
|
|
|
-/// Storage provider is a worker from the working_group module.
|
|
|
|
-pub type StorageProviderId<T> = working_group::WorkerId<T>;
|
|
|
|
-
|
|
|
|
-pub(crate) const MINIMUM_LIFETIME: u32 = 600; // 1hr assuming 6s block times
|
|
|
|
-pub(crate) const DEFAULT_LIFETIME: u32 = MINIMUM_LIFETIME * 24; // 24hr
|
|
|
|
-
|
|
|
|
-/// Defines the expiration date for the storage provider.
|
|
|
|
-#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
|
|
|
|
-#[derive(Encode, Decode, Default, Clone, PartialEq, Eq)]
|
|
|
|
-pub struct ServiceProviderRecord<BlockNumber> {
|
|
|
|
- /// IPNS Identity.
|
|
|
|
- pub identity: IPNSIdentity,
|
|
|
|
- /// Block at which information expires.
|
|
|
|
- pub expires_at: BlockNumber,
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/// The _Service discovery_ main _Trait_.
|
|
|
|
-pub trait Trait: system::Trait + working_group::Trait<StorageWorkingGroupInstance> {
|
|
|
|
- /// _Service discovery_ event type.
|
|
|
|
- type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-decl_storage! {
|
|
|
|
- trait Store for Module<T: Trait> as Discovery {
|
|
|
|
- /// Bootstrap endpoints maintained by root
|
|
|
|
- pub BootstrapEndpoints get(fn bootstrap_endpoints): Vec<Url>;
|
|
|
|
-
|
|
|
|
- /// Mapping of service providers' storage provider id to their ServiceProviderRecord
|
|
|
|
- pub AccountInfoByStorageProviderId get(fn account_info_by_storage_provider_id):
|
|
|
|
- map hasher(blake2_128_concat) StorageProviderId<T> => ServiceProviderRecord<T::BlockNumber>;
|
|
|
|
-
|
|
|
|
- /// Lifetime of an ServiceProviderRecord record in AccountInfoByAccountId map
|
|
|
|
- pub DefaultLifetime get(fn default_lifetime) config():
|
|
|
|
- T::BlockNumber = T::BlockNumber::from(DEFAULT_LIFETIME);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-decl_event! {
|
|
|
|
- /// _Service discovery_ events
|
|
|
|
- pub enum Event<T> where
|
|
|
|
- StorageProviderId = StorageProviderId<T>
|
|
|
|
- {
|
|
|
|
- /// Emits on updating of the account info.
|
|
|
|
- /// Params:
|
|
|
|
- /// - Id of the storage provider.
|
|
|
|
- /// - Id of the IPNS.
|
|
|
|
- AccountInfoUpdated(StorageProviderId, IPNSIdentity),
|
|
|
|
-
|
|
|
|
- /// Emits on removing of the account info.
|
|
|
|
- /// Params:
|
|
|
|
- /// - Id of the storage provider.
|
|
|
|
- AccountInfoRemoved(StorageProviderId),
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-decl_module! {
|
|
|
|
- /// _Service discovery_ substrate module.
|
|
|
|
- pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
|
|
|
- /// Default deposit_event() handler
|
|
|
|
- fn deposit_event() = default;
|
|
|
|
-
|
|
|
|
- /// Creates the ServiceProviderRecord to save an IPNS identity for the storage provider.
|
|
|
|
- /// Requires signed storage provider credentials.
|
|
|
|
- #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
- pub fn set_ipns_id(
|
|
|
|
- origin,
|
|
|
|
- storage_provider_id: StorageProviderId<T>,
|
|
|
|
- id: Vec<u8>,
|
|
|
|
- ) {
|
|
|
|
- <StorageWorkingGroup<T>>::ensure_worker_signed(origin, &storage_provider_id)?;
|
|
|
|
-
|
|
|
|
- // TODO: ensure id is a valid base58 encoded IPNS identity
|
|
|
|
-
|
|
|
|
- //
|
|
|
|
- // == MUTATION SAFE ==
|
|
|
|
- //
|
|
|
|
-
|
|
|
|
- <AccountInfoByStorageProviderId<T>>::insert(storage_provider_id, ServiceProviderRecord {
|
|
|
|
- identity: id.clone(),
|
|
|
|
- expires_at: <system::Module<T>>::block_number() + Self::default_lifetime(),
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
- Self::deposit_event(RawEvent::AccountInfoUpdated(storage_provider_id, id));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Deletes the ServiceProviderRecord with the IPNS identity for the storage provider.
|
|
|
|
- /// Requires signed storage provider credentials.
|
|
|
|
- #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
- pub fn unset_ipns_id(origin, storage_provider_id: StorageProviderId<T>) {
|
|
|
|
- <StorageWorkingGroup<T>>::ensure_worker_signed(origin, &storage_provider_id)?;
|
|
|
|
-
|
|
|
|
- // == MUTATION SAFE ==
|
|
|
|
-
|
|
|
|
- if <AccountInfoByStorageProviderId<T>>::contains_key(storage_provider_id) {
|
|
|
|
- <AccountInfoByStorageProviderId<T>>::remove(storage_provider_id);
|
|
|
|
- Self::deposit_event(RawEvent::AccountInfoRemoved(storage_provider_id));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Privileged methods
|
|
|
|
-
|
|
|
|
- /// Sets default lifetime for storage providers accounts info. Requires root privileges.
|
|
|
|
- #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
- pub fn set_default_lifetime(origin, lifetime: T::BlockNumber) {
|
|
|
|
- ensure_root(origin)?;
|
|
|
|
- ensure!(lifetime >= T::BlockNumber::from(MINIMUM_LIFETIME),
|
|
|
|
- "discovery: default lifetime must be gte minimum lifetime");
|
|
|
|
-
|
|
|
|
- // == MUTATION SAFE ==
|
|
|
|
-
|
|
|
|
- <DefaultLifetime<T>>::put(lifetime);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /// Sets bootstrap endpoints for the Colossus. Requires root privileges.
|
|
|
|
- #[weight = 10_000_000] // TODO: adjust weight
|
|
|
|
- pub fn set_bootstrap_endpoints(origin, endpoints: Vec<Url>) {
|
|
|
|
- ensure_root(origin)?;
|
|
|
|
-
|
|
|
|
- // == MUTATION SAFE ==
|
|
|
|
-
|
|
|
|
- BootstrapEndpoints::put(endpoints);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-impl<T: Trait> Module<T> {
|
|
|
|
- /// Verifies that account info for the storage provider is still valid.
|
|
|
|
- pub fn is_account_info_expired(storage_provider_id: &StorageProviderId<T>) -> bool {
|
|
|
|
- !<AccountInfoByStorageProviderId<T>>::contains_key(storage_provider_id)
|
|
|
|
- || <system::Module<T>>::block_number()
|
|
|
|
- > <AccountInfoByStorageProviderId<T>>::get(storage_provider_id).expires_at
|
|
|
|
- }
|
|
|
|
-}
|
|
|