# 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.