# Slot duration migration Slot duration up to now is more a constant variable that should not be changed after genesis. However, there are requests to change this, because it was for example configured incorrectly or the chain wants to build blocks faster or slower. To achieve this, we will need to write some custom migration to support this. At time of writing this "guide", it will assume we are talking about a Parachain that uses AURA as block authoring implementation. ## Problem description When migrating the slot duration we change the way the slot is calculated. A slot is basically caculated by taking the current time and dividing it by the slot duration. Let's assume the time is `10` and our slot duration is `5`, so we are at slot `2`. If you change the slot duration to `2` (aka decreasing the time between) blocks, the slot is `5`. When increasing the slot duration to `10`, the slot will be `1`. When a node imports blocks, it checks that the slot in the header to import block is not too far in the future. This is simply done by checking that `current_slot + 1 <= header_slot`. As long as the node can handle the switch between two different slot durations transparently, the client side shouldn't be any problem. On the runtime side there are also checks that ensure that the slots are always increasing. If we take our example from above with switching from `5s` to `10s`, the slot would actually not be increased (`2` -> `1`). This would lead to the runtime rejecting blocks that are being build with the new slot duration. ## Solution To make the migration possible, it will require some changes on the node side and some on the runtime side. Let's start with the node side. These changes should be fairly straight forward. In the service instantiation there is somewhere the following relative similar code: ```rust create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( *timestamp, raw_slot_duration, ); Ok((timestamp, slot)) } ``` Here we have this `raw_slot_duration`. We would need to change this when we enact the change of the slot duration. This can be achieved by checking the `spec_version` for example of the block we will be building on to see if this is the block that enacted the change of the slot duration. This should look similar to: ```rust create_inherent_data_providers: move |parent, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let raw_slot_duration = if client.runtime_version(parent).spec_version >= expected { correct_slot_duration } else { old_slot_duration }; let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( ,*timestamp, raw_slot_duration, ); Ok((timestamp, slot)) }, ``` This should ensure that we use the correct slot duration, depending on `spec_version`. On the runtime side we are checking that the slot are increasing, so we need to ensure that when we switch the slot duration and the slot decreases, we still can build blocks. This check can be found here: https://github.com/paritytech/substrate/blob/22ed351d86b3b04ca1df82fb0036c6376bf1fea0/frame/aura/src/lib.rs#L92 So, we would need a migration on the runtime that sets `CurrentSlot` to the correct value. The migration could look like: ```rust let current_slot = CurrentSlot::get(); let timestamp = old_slot_duration * current_slot; let new_slot = timestamp / new_slot_duration; CurrentSlot::put(new_slot); ``` As runtime migrations are executed before any other logic is executed, we can ensure that the moment we hit the mentioned check above the slot is already corrected.