这节我们继续学习offchain worker的使用,我们将在offchain worker中提交未签名交易。
要在pallet中使用ocw提交未签名交易,我们需要修改几个地方:
#[pallet::config]
pub trait Config: frame_system::Config + SendTransactionTypes<Call<Self>> {
...
}
在Config需要继承trait SendTransactionTypes<Call>才能在ocw提交未签名交易。
具体代码如下:
#[pallet::weight(0)]
pub fn submit_something_unsigned(
origin: OriginFor<T>,
number: u64,
) -> DispatchResultWithPostInfo {
ensure_none(origin)?;
let mut cnt: u64 = 0;
if number > 0 {
cnt = number;
}
log::info!(target:"ocw", "unsigned +++++++++++++++++++ offchain_worker set storage: {:?}, cnt: {:?}", number, cnt);
SomeInfo::<T>::insert(&number, cnt);
Self::deposit_event(Event::UnsignedPutSetSomeInfo(number, cnt));
Ok(().into())
}
具体代码如下:
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn offchain_worker(block_number: T::BlockNumber) {
let number: u64 = block_number.try_into().unwrap_or(0);
//下面为具体的调用未签名交易的方式
let call = Call::submit_something_unsigned { number };
if let Err(e) =
SubmitTransaction::<T, Call<T>>::submit_unsigned_transaction(call.into())
.map_err(|_| <Error<T>>::OffchainUnsignedTxError)
{
log::error!(target:"ocw", "offchain_worker submit unsigned tx error: {:?}", e);
} else {
log::info!(target:"ocw", "offchain_worker submit unsigned tx success");
}
}
}
代码如下:
#[pallet::validate_unsigned]
impl<T: Config> ValidateUnsigned for Pallet<T> {
type Call = Call<T>;
fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
//Call冒号后面就是具体的提交未签名交易的函数,
//需要对此交易进行验证
if let Call::submit_something_unsigned { number: _ } = call {
ValidTransaction::with_tag_prefix("OcwUnsigtx")
.priority(TransactionPriority::max_value())
.longevity(5)
.propagate(false)
.build()
} else {
InvalidTransaction::Call.into()
}
}
}
具体的ValidTransaction使用可以参考文档https://paritytech.github.io/substrate/master/sp_runtime/transaction_validity/struct.ValidTransaction.html
当我们要在ocw中提交未签名交易时,上面的1.1、1.3、1.4都是差不多的写法,1.2为具体的未签名交易函数,根据自己的业务修改就好。当然1.4中的ValidTransaction根据自己的情况进行修改。
接下来就是在runtime中添加代码,本节需要添加的代码比较简单,如下:
impl pallet_ocw_unsigtx::Config for Runtime {
type Event = Event;
}
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system,
...
OcwUnSigtx: pallet_ocw_unsigtx,
}