Origins (Privileged Calls) in FRAME
In Module 5, you created a dispatchable function called register
that defined an extrinsic. The first parameter in that function, OriginFor<T>
, enabled you also to
interpret the call's sender, or origin. There are different types of origins, which can be used
in various ways to filter out where a call should come from.
Origin Overview
A runtime origin defines where a call came from and can be used to check its type. In our
dispatchable code, we used the macro ensure_signed!()
to verify that whoever sent this transaction
signed the payload. Without this check in place, this would mean that anyone could submit a payload,
regardless of whether it is cryptographically signed or not.
This allows us to authenticate the user and gain access to necessary metadata, such as the account address.
Origin Types (Raw Origins)
The above is known as a signed origin, and several types are included by default in Substrate (see: RawOrigin):
- Root - Similar to using "sudo", known as the highest privilege level. The root origin is utilized in scenarios like upgrading the runtime.
- Signed - Some payload is signed by a private/public key pair and provides an
AccountId
. - None - Signed by nobody. Unsigned transactions are rarely used, except in cases like off-chain workers or where charging an account with fees is unreasonable.
Custom Origins
Besides the default RawOrigin
types, custom origins can be defined and used within a pallet.
Custom origins allow a developer to define a stringent set of requirements for what a call should
contain to be valid for that specific use case.
For example, the pallet_collectives
defines custom origins that represent a
Member(AccountId)
of a particular collective. In the pallet's context, a call containing this origin would imply that
a member of that collective condoned that action.