pallet进阶(8)-offchain storage

链下存储
顾名思义,链下存储不保存在链上,而是保存在节点本地的。

1. 案例1-链下存储基本操作

在ocw中使用StorageValueRef
pallet的lib.rs中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

use sp_runtime::offchain::storage::{
MutateStorageError, StorageRetrievalError, StorageValueRef,
};

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config {}

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn offchain_worker(block_number: T::BlockNumber) {
if Self::should_print() {
log::info!(target:"offchain-storage", "1. Block number: {:?}, should print +++++++++++++++++++++++++++ ", block_number);
} else {
log::info!(target:"offchain-storage", "2. Block number: {:?}, Should not print +++++++++++++++++++++++++++ ", block_number);
}
}
}

//内部方法
impl<T: Config> Pallet<T> {
fn should_print() -> bool {
const LAST_VALUE: () = ();
//重点看这里
let val = StorageValueRef::persistent(b"ocw-demo::last_value");
let res = val.mutate(
|last_flag: Result<Option<bool>, StorageRetrievalError>| match last_flag {
Ok(Some(flag)) => Ok(!flag),
_ => Ok(true),
},
);

match res {
Ok(flag) => flag,
Err(MutateStorageError::ValueFunctionFailed(LAST_VALUE)) => false,
Err(MutateStorageError::ConcurrentModification(_)) => false,
}
}
}
}

相关引入和编译后,即可正常运行

2. 在ocw中使用local_storage_set/get

手动通过rpc对storage demo::flag设置为true,然后在代码中查看此存储的值,然后再将此值写到另外一个存储demo::result中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

extern crate alloc;
use alloc::string::{String, ToString};

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config {}

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn offchain_worker(block_number: T::BlockNumber) {
let flag = Self::should_print();

if flag {
log::info!(target:"offchain-storage2222", "1. Offchain-storage2, block number: {:?}, should print +++++++++++ ", block_number);
} else {
log::info!(target:"offchain-storage2222", "2. Offchain-storage2, block number: {:?}, Should not print +++++++++++ ", block_number);
}

Self::set_result(flag);
}
}

impl<T: Config> Pallet<T> {
fn should_print() -> bool {
let kind = sp_core::offchain::StorageKind::PERSISTENT;
if let Some(flag) = sp_io::offchain::local_storage_get(kind, b"demo::flag") {
let ret = match String::from_utf8(flag) {
Ok(v) => v.eq(&"true"),
Err(_) => false,
};
ret
} else {
false
}
}

fn set_result(flag: bool) {
let kind = sp_core::offchain::StorageKind::PERSISTENT;
let value = match flag {
true => "true".to_string(),
false => "false".to_string(),
};
sp_io::offchain::local_storage_set(kind, b"demo::result", value.as_bytes());
}
}
}

总结

本文编辑完毕

  • Copyrights © 2017-2023 Jason
  • Visitors: | Views:

谢谢打赏~

微信