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.