Skip to main content
edited tags
Link
jsdw
  • 1.3k
  • 3
  • 12
Source Link
klbrvik
  • 126
  • 5

How to create signed extrinsic in outer node?

What is idiomatic way to submit signed extrinsic in outer node?

Is it using BasicPool and submit_local? Would Rust example at the bottom be be good approach? If it is how to:

  • properly choose period and current args for Era::mortal?
  • obtain nonce for frame_system::CheckNonce?

Also it seems using subxt requires way less boilerplate than example below.

Is there better interface, with less boilerplate than in example below, I could use when submitting signed extrinsics in outer node?

There's always possibility of using subxt but that doesn't seem right since I've got access to runtime, transaction pool and needed types within outer node.

fn submit_signed_extrinsic_example(
    transaction_pool: &dyn sc_transaction_pool_api::LocalTransactionPool<
        Block = Block,
        Hash = Hash,
        Error = sc_transaction_pool::error::Error,
    >,
    keystore: &sc_keystore::LocalKeystore,
    genesis_hash: sp_core::H256,
    block_hash: sp_core::H256,
) -> Result<()> {
    let call = my_pallet::Call::my_call {};

    let keys = keystore.sr25519_public_keys(key_types::ACCOUNT);

    let public = keys.first().ok_or(Error::NoNodeAccountKey)?.clone();

    let extra: runtime::SignedExtra = (
        frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
        frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
        frame_system::CheckTxVersion::<runtime::Runtime>::new(),
        frame_system::CheckGenesis::<runtime::Runtime>::new(),
        frame_system::CheckMortality::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
            0, 0,
        )),
        frame_system::CheckNonce::<runtime::Runtime>::from(0),
        frame_system::CheckWeight::<runtime::Runtime>::new(),
        pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
    );

    let payload = runtime::SignedPayload::from_raw(
        call.clone().into(),
        extra.clone(),
        (
            (),
            runtime::VERSION.spec_version,
            runtime::VERSION.transaction_version,
            genesis_hash,
            genesis_hash,
            (),
            (),
            (),
        ),
    );

    let signature = sp_runtime::MultiSignature::Sr25519(payload.using_encoded(|payload| {
        keystore
            .sr25519_sign(key_types::ACCOUNT, &public, payload)?
            .ok_or(Error::NoNodeAccountKey)
    })?);

    let extrinsic = runtime::UncheckedExtrinsic::new_signed(
        call.clone().into(),
        sp_runtime::AccountId32::from(public).into(),
        signature,
        extra,
    );
    let block_id = sp_runtime::generic::BlockId::Hash(block_hash);

    transaction_pool.submit_local(&block_id, extrinsic.into())?;

    Ok(())
}