在 Substrate 中,有没有一种方法可以在另一个自定义模块中使用存储和功能?

In Substrate is there a way to use storage and functions from one custom module in another?

我看过关于创建单个 Substrate Runtime 模块包的 Substrate 教程 here 以便重新使用该功能,但我想知道是否有一种方法可以让一个自定义模块访问存储或来自另一个自定义模块的功能?

大致如下:

/// In ModuleA

    pub type IndexType = u64;

    decl_storage! {
        trait Store for Module<T: Trait> as ModuleA {
                pub MyIndexCount get(my_index_count): Option<IndexType>;
        }
    }

然后在 ModuleB 内部 - 我需要做什么才能 use/include ModuleA 的功能,我该如何调用它?

/// In ModuleB

    decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        fn deposit_event<T>() = default;

        pub fn edit_index(origin) -> Result {
            let sender = ensure_signed(origin)?;

            // --->>>> I want to read some storage from ModuleA whilst inside ModuleB
            let c: IndexType = ReadStorageFromModuleA >>> my_index_count().ok_or("Storage Read Error: cannot get index")?;

            // change storage in ModuleA from ModuleB
            WriteToStorageInModuleA <MyIndexCount<T>>::put(&c + 1);

            Ok(())
            }
        }
    }    

如果您构建的模块 (module2) 直接依赖于另一个模块 (module1),则必须在模块 2 的特征定义中继承模块 1 的特征:

pub trait Trait: module1::Trait {
    ...
}

要从模块 2 中的模块 1 访问 public 存储项目,您需要执行以下操作:

  • 导入适当的存储特性以访问存储 API:StorageValueStorageMap 等...
  • 通过模块 1 的存储类型访问 public 存储
    • <module1::Something<T>>::get()
    • <module1::Something<T>>::put()
    • 等...

要在模块 2 中访问模块 1 中的其他 public 函数,您需要使用 Module 类型:

<module1::Module<T>>::public_function();

这是两个模块以这种方式交互的简单示例:

module1.rs

Note that all the things in this module are marked public (pub)

use support::{decl_module, decl_storage, StorageValue};

pub trait Trait: system::Trait {}

decl_storage! {
    trait Store for Module<T: Trait> as TemplateModule {
        pub Something: u32;
    }
}

decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
    }
}

impl<T: Trait> Module<T> {
    pub fn get_value() -> u32 {
        <Something<T>>::get()
    }
}

module2.rs

use support::{decl_module, decl_event, StorageValue, dispatch::Result};
use system::ensure_signed;

use crate::module1;

pub trait Trait: module1::Trait {
    type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}

decl_module! {
    /// The module declaration.
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        fn deposit_event<T>() = default;

        pub fn get_value_directly(origin) -> Result {
            let who = ensure_signed(origin)?;
            let value = <module1::Something<T>>::get();
            Self::deposit_event(RawEvent::ValueIs(value, who));
            Ok(())
        }

        pub fn set_value_directly(origin, value: u32) -> Result {
            let _ = ensure_signed(origin)?;
            <module1::Something<T>>::put(value);
            Ok(())
        }

        pub fn get_value_public_function(origin) -> Result {
            let who = ensure_signed(origin)?;
            let value = <module1::Module<T>>::get_value();
            Self::deposit_event(RawEvent::ValueIs(value, who));
            Ok(())
        }
    }
}

decl_event!(
    pub enum Event<T> where <T as system::Trait>::AccountId {
        ValueIs(u32, AccountId),
    }
);