2

The transaction pool regularly calls the validate_unsigned function of the SignedExtension trait to check transaction validity against current state. This trait then gets used to implement custom extensions in frame_system, which get passed into the runtime as a single type, for example in a typical runtime/src/lib.rs file we have:

pub type SignedExtra = (
    frame_system::CheckNonZeroSender<Runtime>,
    frame_system::CheckSpecVersion<Runtime>,
    frame_system::CheckTxVersion<Runtime>,
    frame_system::CheckGenesis<Runtime>,
    frame_system::CheckEra<Runtime>,
    frame_system::CheckNonce<Runtime>,
    frame_system::CheckWeight<Runtime>,
    pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
);

So, IIUC this then is used to construct all parts of extra data that a signed call submitted to the runtime expects:

/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;

Then, the TaggedTransactionQueue runtime API provides a way to check that a submitted signed transaction is valid, giving the pool to order transaction by priority etc.

From what I understand, this runtime API verifies all the data in SignedExtra. My question is how?

How does this extra data gets passed into the signed extension and how does the transaction pool know what and where to check in the encoded call?

1 Answer 1

2

Per my understanding,

The transaction pool doesn't know much about the extrinsics, pretty much they are opaque for the pool. But the runtime comes to save the day. TaggedTransactionQueue runtime API will end up calling to pallet_executive, which will take care of orchestrating the whole validation. - impl of TaggedTransactionQueue for a runtime.

Extra is part of the extrinsic itself already, from the beginning - UncheckedExtrinsic.

As you very well mention the node will call into the runtime to to perform the necessary checks and validations for the extrinsics. Being one of the first operations checking the extrinsic - impl for UncheckedExtrinsic.

After that the relevant dispatch_info will be retrieved and eventually the, now CheckedExtrinsic, will be validated - impl for CheckedExtrinsic, and here is where those SignedExtensions from Extra are validated.

The source of the steps I have described can be found here. And, for reference, you can see here how an Extrinsic is built, embedding Extra in it - build()

I don't know if this will actually solve your questions or maybe it was to broad.

EDIT: Adding a clarification

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.