#state #module #system #key #sovereign #value #cache

sov-state

定义了Sovereign SDK模块系统中状态存储的特性和类型

3个版本 (重大更新)

0.3.0 2023年10月20日
0.2.0 2023年9月14日
0.1.0 2023年5月31日

#50 in #sovereign

Download history 33/week @ 2024-04-20 29/week @ 2024-04-27 24/week @ 2024-05-04 30/week @ 2024-05-11 26/week @ 2024-05-18 36/week @ 2024-05-25 30/week @ 2024-06-01 18/week @ 2024-06-08 18/week @ 2024-06-15 33/week @ 2024-06-22 7/week @ 2024-06-29 8/week @ 2024-07-06 39/week @ 2024-07-13 20/week @ 2024-07-20 44/week @ 2024-07-27 21/week @ 2024-08-03

每月 124 次下载
11 crate 中使用 (10 直接)

MIT/Apache

185KB
3.5K SLoC

sov-state

此crate提供特定于从永久存储中存储和检索数据的抽象,适用于在模块系统中使用。

高级说明

从高层次来看,该crate提供了两个主要抽象,模块开发者可以利用这些抽象来访问数据

  1. StateValue:用于在状态中存储单个值。它提供设置值和稍后检索值的方法。
  2. StateMap:用于在状态中存储映射。它允许模块开发者将键与值相关联,并相应地检索它们。

未来,此crate旨在引入其他抽象,如StateVec,以进一步增强模块系统中的数据存储功能。

以下是一个展示StateValue API一部分的代码片段

impl StateValue<V> {

    /// Sets a value in the StateValue.
    pub fn set<S: Storage>(&self, value: V, working_set: &mut WorkingSet<S>) {
        // Implementation details
    }

    /// Gets a value from the StateValue or None if the value is absent.
    pub fn get<S: Storage>(&self, working_set: &mut WorkingSet<S>) -> Option<V> {
       // Implementation details
    }

    // Additional methods
    // ...
}

getset 方法都需要一个 WorkingSet 参数,它是一个包装在具有附加缓存层的 键值存储 上的封装器。

模块开发者可以与 WorkingSetStateValueStateMap 交互,无需担心这些组件的内部工作原理。相反,他们可以将它们视为处理数据存储和检索的“黑盒”。

以上API的使用方式如下

state.value.set(&some_value, working_set);
let maybe_value = state.value.get(working_set);

低级说明

需要注意的是,理解本节内容对于高效使用sov-state并非必需。

Native & Zkp 执行

Native 执行过程中,数据存储在 键值 存储中,通过 WorkingSet 访问。值得一提的是,实际的存储机制,如 RocksDB,仅在完整节点执行事务并更新状态的这个阶段才能访问。

相比之下,在 Zkp 阶段,当生成正确执行的加密证明时,模块系统无法直接访问底层数据库。相反,它依赖于 Native 执行期间产生的“见证”。系统通过使用梅克尔树(Merkle trees)等变体进行加密检查,以验证状态是否正确更新。尽管访问存储机制的方式不同,但两种场景都可以通过相同的接口进行抽象。

Storage 抽象定义为以下内容

pub trait Storage: Clone {
    type Witness: Witness;
    /// The runtime config for this storage instance.
    type RuntimeConfig;

    fn with_config(config: Self::RuntimeConfig) -> Result<Self, anyhow::Error>;

    /// Returns the value corresponding to the key or None if key is absent.
    fn get(&self, key: StorageKey, witness: &Self::Witness) -> Option<StorageValue>;

    /// Validate all of the storage accesses in a particular cache log,
    /// returning the new state root after applying all writes
    fn validate_and_commit(
        &self,
        state_accesses: OrderedReadsAndWrites,
        witness: &Self::Witness,
    ) -> Result<[u8; 32], anyhow::Error>;
}

sov-state 包提供了 Storage 特性的两种实现:ZkStorageProverStorage。这些实现分别处理 ZkpNative 执行模式下的数据存储和检索。为了在 zk-proof 生成不是问题的情况下提高性能,可以添加一个额外的实现,该实现不包括生成见证。这些实现封装了所需的逻辑和与存储系统的交互,使得模块开发者可以在不同的执行模式下使用一致的接口。

WorkingSet:

执行状态更新和生成见证是一个耗时的过程。因此,引入缓存层以减轻这些问题是合理的。《WorkingSet》将数据写入内存映射,仅在数据不在映射中时才从后端存储读取。有关我们缓存的信息,请参阅 sov-first-read-last-write-cache 包。此外,缓存简化了状态回滚的实现过程。如果在特定事务需要回滚的情况下,我们只需简单地丢弃相关缓存中进行的所有写入即可。

依赖项

~6–22MB
~319K SLoC