1

Reading the documentation about off-chain workers in Substrate recipes, it is stated that we can generally make three types of transactions to include non-deterministic data from outside the chain into the blockchain. The three types being:

  1. Signed transactions
  2. Unsigned transactions
  3. Unsigned transactions with signed payload

The common feature between the 1st and the 3rd type is that in both cases we can know the identity of the signer. The difference mentioned in the documentation is that the signer will need to pay a fee for the 1st type, but not for the 3rd type. It is also stated that for the 3rd type we need extra validation logic in order to mitigate any kind of attack on our chain since there are no fees. From my understanding of how signed transactions work is that you can also allow signed transactions with 0 fees using the Pays::No option as answered here. You can also put more validation logic in this case as well for protecting your chain from any form of attacks.

So my question is, in both cases if we can achieve the same desired result that is knowing the caller, no fees, validation logic, is there still a difference b/w the two types of transactions? Is there a way of knowing which type to use when?

Jdawg287
  • 117
  • 5

1 Answers1

4

Indeed, there is a very important difference between signed transactions that return Pays::No and unsigned transactions.

The former will only refund the fee at the end of the execution, almost certainly if the transaction succeeded, while the latter is always free. This is why, as you mentioned, you really really need to have custom validation logic for your unsigned transactions, otherwise they are open to DoS attacks.


Let's look at more examples:

  • A signed transaction will do some cleanup for the chain that is actually beneficial for the chain and is worth the computation. If you want to incentivize random users to call this transaction more, you can leave it as a signed transaction, and return Pays::No only if the execution was successful and the chain benefited. Otherwise, if the transaction was not beneficial, the signer will have to pay full fees, preventing any attacks. This the case in submitting the pre-image of a proposal in the democracy pallet. If the pre-image was submitted successfully, the fee is refunded.
  • A transaction can only be submitted by a fixed set of hard-coded accounts (either stored on chain, or the validator set etc.), and you want to exempt them from paying any fee. In this case you make this an unsigned transaction, which pays no fee, and sign (a part of) the payload with the sender account. This can later be checked on-chain, which is similar to what ensure_signed is doing.
  • Finally, in cases like the claims pallet of Polkadot, you might want to allow for accounts that do not have any funds to send a transaction. This is the most risky variant, and it is up to you to make sure you have good weights and a validate_unsigned that prevents any DoS attack.
kianenigma
  • 1,365
  • 12
  • 20