如何使用 PalletS 从 Pallet 中保存记录,而 Pallet 对基材和锈蚀保存的内部结构一无所知

How to use PalletB to save record from PalletA without PalletA knowing anything about internals of the saving in substrate and rust

我想通过简单地传递原始数据并等待 return.

将 PalletA 中的记录保存到 PalletB 中

我试过以下方法:

// ./PalletB/lib.rs

pub trait PutInStorage {
    fn put_rule_in_storage(value: u32);
}

impl<T: Trait> PutInStorage for Module<T> {
    fn put_rule_in_storage(value: u32) {
        SimpleCounter::put(value);
    }
}

然后在

// ./PalletA/lib.rs
use palletB::{PutInStorage, Trait as PalletBTrait};

///The pallet's configuration trait.
pub trait Trait: system::Trait + PalletBTrait {
    /// The overarching event type.
    type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
    type ExternalStorage: PutInStorage;
}

然后我像这样将定义添加到运行时:

// ./runtime/lib.rs
// near the construct_runtime macro

impl palletA::Trait for Runtime {
    type Event = Event;
    type ExternalStorage = palletB::Module<Runtime>;
}

到目前为止,这通过了检查,但没有通过测试。 trait 的测试配置是这样的:

use palletB::{PutInStorage, Trait as PalletBTrait};

impl Trait for Test {
    type Event = ();
    type ExternalStorage = PutInStorage;
}

这失败了:

 type ExternalRulesStorage = PutInStorage;
                                         ^^^^^^^^^^^^ help: use `dyn`: `dyn PutInStorage`

 impl Trait for Test 
     ------------------- in this `impl` item
     type Event = ();
     type ExternalRulesStorage = PutInStorage;
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    
 type ExternalRulesStorage = PutInStorage;
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `pallet_rules::PutInStorage` cannot be made into an object

我尝试了 Rust 编译器给我的所有建议,但没有任何运气。在有人问为什么我的测试中需要这个之前,这是因为 decl_module! 中的可调度 fn 检查在开始处理和保存自己的记录之前是否存在某个记录。它依赖于记录存在。

为了让编译器满意,您的测试配置还必须有一个 PalletB 实例,或任何其他实现 PutInStorage.

的实例

与您在 ./runtime/lib.rs 中所做的类似:

impl Trait for Test {
    type Event = ();
    type ExternalStorage =  palletB::Module<Test>;
}

请注意,现在struct Test是扮演Runtime的角色。我认为这是您唯一缺少的东西。


话虽如此,你似乎在整体设计上走错了路。

PalletA 已经依赖于 PalletB。鉴于您还具有 link 这两个 PutInStorage 的特征,这不是一个好的设计。通常,您应该尝试并始终选择以下选项之一:

  1. 两个托盘将相互依赖。在这种情况下,您不需要特征。如果一个需要将某些东西放入另一个的存储中,您只需直接即可。在您的示例中,我假设 PalletBdecl_storage 中有一个名为 pub Foo: u32 的存储项,并且 PutInStorage 写入该项。如果是这种情况,则不需要特征。从 PalletA 你可以说:palletB::Foo::put(value).

请注意,应谨慎选择这种方法,否则最终可能会出现大量托盘相互依赖的情况,这并不好。

  1. 你决定你的 pallet 不相互依赖,在这种情况下你使用了一些特性,比如 PutInStorage。您的代码似乎与这种方法保持一致,除了您将 PalletA 的特征定义为 pub trait Trait: system::Trait。这里不用依赖PalletB,当然你也可以从Cargo.toml里抹掉