2

Imagine there is an unsigned extrinsic call.

#[pallet::call]
fn call(something, ..) -> DispatchResult {
    ensure_none()?;

    // verify(something)?;

    Ok(())
}

#[pallet::validate_unsigned]
impl .. {
    fn validate_unsigned(call, ..) {
        match call {
            call(something, ..) => verify(something),
            _ => return Err
        }

        return Ok
    }
}

We already do the verification in the validate_unsigned.

  1. Should we? To my understanding, we should. If any validator/collator modifies their node to remove the validate_unsigned part. Then he could skip that.
  2. Why? How will the extrinsic be executed and broadcast in the network in this case?

I found the Polkadot did the first verification here https://github.com/paritytech/polkadot/blob/d57049f1e4e5b00309cdd0297235a8de821f601d/runtime/common/src/claims.rs#L475.

And second here https://github.com/paritytech/polkadot/blob/d57049f1e4e5b00309cdd0297235a8de821f601d/runtime/common/src/claims.rs#L317.

Why the second one is necessary?

If we remove the second one. What would happen? How does the attacker make a successful attack in this case?

1 Answer 1

2

Yes, you need to do the same checks while applying the unsigned extrinsic as in validate_block.

As you need to implement ValidateUnsigned for your pallet, it will already do the verification while applying the unsigned extrinsic. This assumes that you don't change the default implementation of pre_dispatch. If you implement the method on your own, you need to ensure that pre_dispatch and validate_unsigned are doing exactly the same checks! I mean they can do different kind of checks, but validity should be checked in both implementations in the same way.

Why the second one is necessary?

In the example you gave above the signer is extracted in validate_unsigned to check that it exists in Claims. This is done to prevent spam. As unsigned transaction are not paying any fees, you want to ensure that no one is spamming you with these transactions. So, your validate_unsigned logic should contain some code to reject these transactions early aka before they can enter the pool. However, as always in the context of validate_transaction (the context in that we call validate_unsigned) you should ensure that your checks are lightweight as otherwise you may make these checks a dos vector to your network.

Another point on why we need to call eth_recover in the implementation of the call again is that we can not pass data from pre_dispatch to the actual call dispatch.

10
  • If I don't perform the verification in the #[pallet::call]. I only do the verification in #[pallet::validate_unsigned]. What will happen? When the invalid extrinsic broadcast to other nodes' transaction pool, they will reject it I think. How does the attacker make a successful attack?
    – aurexav
    Commented Dec 7, 2022 at 13:39
  • 1
    What attacker? What kind of attack? I don't get it. Did you read what I have written above? That the same checks as in validate_unsigned are also done in pre_dispatch as this calls to validate_unsigned in the default implementation.
    – bkchr
    Commented Dec 7, 2022 at 13:47
  • Skip the transaction pool level verification. And make the invalid extrinsic successful. Because I don't verify it in runtime call. IIUC validate_unsigned only works for transaction pool verification which is off-chain.
    – aurexav
    Commented Dec 7, 2022 at 13:50
  • 1
    > IIUC validate_unsigned only works for transaction pool verification which is off-chain. You did not read on what I have written above from the beginning. > As you need to implement ValidateUnsigned for your pallet, it will already do the verification while applying the unsigned extrinsic. This works by having pre_dispatch call validate_unsigned in the default implementation of pre_dispatch.
    – bkchr
    Commented Dec 7, 2022 at 13:54
  • 1
    No the answer is not really "no". The answer is that you should do the same checks while applying as in validation. Point being where you do these checks, if you just use pre_validate then you don't need to do it in your call again. However, you could also implement pre_validate omitting all checks.
    – bkchr
    Commented Dec 7, 2022 at 14:31

Your Answer

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

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