You mention the relay chain block number isn’t available in inherent and
on_initialize, but couldn’t you look at the last block and just add one to it?
Or is there some deeper problem here I am missing?
I have always recommended to other blockchain developers that they should prefer writing code which relies on a block number rather than the timestamp since the block number is a native part of the blockchain, and the timestamp is an externally reported, potentially inaccurate (to some limit) value.
Indeed, block number is inferior to many of the “user experience” things that want to be designed, like “execute some transaction exactly in one year”, since delays to block production may mean that a block number representation of that time period is not perfect, but to me this is also fine, and could be repaired with upgrades / governance.
Are there scenarios where it is strictly better for a developer to design a system around the timestamp?
In this case, having parachains rely on the relay chain block number seems like the best choice to me. In the current design of Polkadot, it has a pretty consistent block time of 6 seconds. This stuff is reported to the parachains, and all logic could stem from this as a universal marker of time.
When designing on-demand parachain logic, developers need to remove all assumptions around a fixed block production time, and instead write logic which incentivizes blocks to be pushed to the relay chain at certain relay chain blocks, or to look at the current relay chain block for the truth about the current time.
Example: an on-demand parachain for vesting DOT balances.
Polkadot already has a pallet for managing vesting DOT directly on the relay chain. Most of the time, the logic in this pallet is inactive. Users can initiate transactions to the pallet, and based on the current relay chain block number, some DOT balance will be unlocked.
If we were to design this as an on-demand parachain, there would be no need for a local timestamp or consistent block time. Instead, users will have their balances vesting based on the relay chain block number. A block is only created when a user wants to unlock their DOT (which could be months apart), and simply checking the latest relay chain block number would allow the logic to unlock the correct amount.
I think you could think of a very similar pattern for a Domain Name Service On-Demand Parachain, where most of the time, the DNS logic is inactive, and only when users buy / trade / renew / re-claim their domain, blocks will need to be made. We should not require that this chain produce consistent empty blocks just to keep track of time, instead we again rely on the block number of the relay chain.