There are few ways to brick a Substrate chain and panic/overweight in mandatory hook execution is one of them. Therefore, we should avoid code execution in mandatory hooks (on_initialize / on_finalize) as much as possible.
While we want to avoid panic/overwieght for extrinsics, it is less bad as collators can blacklist bad one (after a failed attempt to bundle it). It could be a active DoS vector of the chain, but can be mitigated.
There are mainly three category of sources of non extrinsic triggered executions:
- Periodic business logic execution
- Incoming XCM execution
- Delayed execution (e.g. referenda enactment) via pallet-scheduler
Note that #1 and #2 can be refactored to use pallet-scheduler for execution so we really just need to make #3 to be safe.
Pallet scheduler execute the scheduled calls in on_intitalize hook, which means any panic will brick the chain. There will now way to construct a valid block without trigger the panic path and no way to inject other code execution before the panic path to potentially rescue the bad execution.
This property can be useful for some critical logic, but not strictly required by most of the use cases. For example, the enactment of a referendum can usually be delayed for a few blocks without causing issues. Dispatch of an incoming XCM are expected to be queued and delayed anyway.
For those executions that doesn’t have strict execute at a particular block requirements, we may better to offload them to a different pallet. i.e. the safe-scheduler.
I initially came up the idea of safe scheduler pallet at orml#481. The core idea is that instead of execute all the non-extrinsic triggered logic in on_initalize, we simply put them into a queue, and use offchain worker + unsigned tx to trigger them. This means any panic/overweight will only mark such unsigned tx to be unbundlable. It will not impact block production and therefore reduce the impact of the damage.
This wasn’t a such big concern before as it is relatively easy to proof a runtime cannot panic and the compute time of hooks are not unbounded. However for parachains it is now possible to overweight due to storage access, which can be hard to detect and rescue (it is hard to tell the size of the item without reading it, but after read it, it could already be too late).
Related issues: