Feels like a very newbie question but, whilst I've found hints of how to implement this, I can't find the recommended solution.

I have an offchain worker that does some validation of remote data and then calls an onchain function to say the data is either valid or invalid. I'm only using signed transactions.

How do I check, in my onchain function, that the call was made by an offchain worker and not some random individual calling it as an extrinsic?

Feels like I should be using the AuthorityId but I'm not sure how...

2 Answers 2


You can't. There is no cryptographic protocol for telling what software someone used to create a signature for a transaction. Instead, the on-chain logic should be designed such that it doesn't matter how the transaction was submitted but only that it was submitted.


If you're comfortable introducing a layer of permissioning into your design, you could perhaps use the SignedExtension trait.

You'd have to keep an on-chain list of OCW identities that are "authorized" to send the specific extrinsic, and use them in the validate function of your SignedExtention trait implementation.

This list could be updated via sudo or Governance.

Here's a working example of how to use the SignedExtension trait in a RBAC permissioning system. It's not the precise solution to your problem, but could serve as inspiration.

Please note that you also need to design how the signing keys are handled by your OCW. FRAME's OCW example shows how you can do a signed transaction from an OCW. One important line in that example is:

pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"btc!");

The admin of each node will need to inject the keys (ideally matching "authorized" accounts) into the node. That can be done via:

curl --location --request POST 'http://localhost:9933' \
--header 'Content-Type: application/json' \
--data-raw '{
    "jsonrpc": "2.0",
    "method": "author_insertKey",
   "params": ["btc!","bread tongue spell stadium clean grief coin rent spend total practice document","0xb6a8b4b6bf796991065035093d3265e314c3fe89e75ccb623985e57b0c2e0c30"],
    "id": 1

(note that keyType is btc!, matching what has been declared in the OCW pallet).

If the node admin doesn't do this step, the OCW simply won't be able to sign transactions.

Another alternative for the node admin is to use the key insert subcommand on the node's executable, which will write the keys into disc, and will persist in case the node is restarted (author_insertKey will not). See this answer for an example on how to use it.

Then, for every signed transaction, if the signer is in the "authorized" set, the SignedExtension will allow it to enter the transaction pool.

  • Thanks. I'll take a look at that option.
    – jpataylor
    Dec 23, 2022 at 9:03
  • @jpataylor you're welcome... FYI I updated the answer with some extra info Dec 27, 2022 at 18:15

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.