Skip to content

Commit

Permalink
Calculate correct start slot for skipped epoch transition (#1015)
Browse files Browse the repository at this point in the history
* Calculate correct start slot for skipped epoch transition

* Changelog
  • Loading branch information
skunert authored Aug 10, 2023
1 parent 902280d commit 726dd51
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 45 deletions.
85 changes: 40 additions & 45 deletions lib/src/verify/babe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,19 +276,11 @@ pub fn verify_header(config: VerifyConfig) -> Result<VerifySuccess, VerifyError>

// Verify consistency of the configuration.
if let Some(curr) = &config.parent_block_epoch {
assert_eq!(
curr.epoch_index.checked_add(1).unwrap(),
config.parent_block_next_epoch.epoch_index
);
assert!(curr.start_slot_number.is_some());
assert!(curr.start_slot_number <= parent_slot_number);
} else {
assert_eq!(config.parent_block_next_epoch.epoch_index, 0);
}
assert!(config
.parent_block_next_epoch
.start_slot_number
.map_or(true, |n| n > parent_slot_number.unwrap()));
assert_eq!(
config.parent_block_next_epoch.epoch_index == 0,
config.parent_block_next_epoch.start_slot_number.is_none()
Expand Down Expand Up @@ -322,16 +314,18 @@ pub fn verify_header(config: VerifyConfig) -> Result<VerifySuccess, VerifyError>
}
};

// Check if the current slot number indicates that entire epochs have been skipped.
let skipped_epochs = block_epoch_info
.start_slot_number
.map_or(0, |start_slot_number| {
(slot_number - start_slot_number) / config.slots_per_epoch
});

// Calculate the epoch index of the epoch of the block.
// This is the vast majority of the time equal to `block_epoch_info.epoch_index`. However,
// if no block has been produced for an entire epoch, the value needs to be increased by the
// number of skipped epochs.
let block_epoch_index = block_epoch_info.epoch_index
+ block_epoch_info
.start_slot_number
.map_or(0, |start_slot_number| {
(slot_number - start_slot_number) / config.slots_per_epoch
});
let block_epoch_index = block_epoch_info.epoch_index + skipped_epochs;

// TODO: in case of epoch change, should also check the randomness value; while the runtime
// checks that the randomness value is correct, light clients in particular do not
Expand Down Expand Up @@ -360,37 +354,38 @@ pub fn verify_header(config: VerifyConfig) -> Result<VerifySuccess, VerifyError>

// If the block contains an epoch transition, build the information about the new epoch.
// This is done now, as the header is consumed below.
let epoch_transition_target = match config.header.digest.babe_epoch_information() {
None => None,
Some((info, None)) => Some(chain_information::BabeEpochInformation {
epoch_index: block_epoch_index.checked_add(1).unwrap(),
start_slot_number: Some(
block_epoch_info
.start_slot_number
.unwrap_or(slot_number)
.checked_add(config.slots_per_epoch.get())
.unwrap(),
),
authorities: info.authorities.map(Into::into).collect(),
randomness: *info.randomness,
c: block_epoch_info.c,
allowed_slots: block_epoch_info.allowed_slots,
}),
Some((info, Some(epoch_cfg))) => Some(chain_information::BabeEpochInformation {
epoch_index: block_epoch_index.checked_add(1).unwrap(),
start_slot_number: Some(
block_epoch_info
.start_slot_number
.unwrap_or(slot_number)
.checked_add(config.slots_per_epoch.get())
.unwrap(),
),
authorities: info.authorities.map(Into::into).collect(),
randomness: *info.randomness,
c: epoch_cfg.c,
allowed_slots: epoch_cfg.allowed_slots,
}),
};
let epoch_transition_target =
config
.header
.digest
.babe_epoch_information()
.map(|(info, maybe_config)| {
let start_slot_number = Some(
block_epoch_info
.start_slot_number
.unwrap_or(slot_number)
.checked_add(config.slots_per_epoch.get())
.unwrap()
// If some epochs have been skipped, we need to adjust the starting slot of
// the next epoch.
.checked_add(
skipped_epochs
.checked_mul(config.slots_per_epoch.get())
.unwrap(),
)
.unwrap(),
);
chain_information::BabeEpochInformation {
epoch_index: block_epoch_index.checked_add(1).unwrap(),
start_slot_number,
authorities: info.authorities.map(Into::into).collect(),
randomness: *info.randomness,
c: maybe_config.map_or(block_epoch_info.c, |config| config.c),
allowed_slots: maybe_config.map_or(block_epoch_info.allowed_slots, |config| {
config.allowed_slots
}),
}
});

// Make sure that the header wouldn't put Babe in a non-sensical state.
if let Some(epoch_transition_target) = &epoch_transition_target {
Expand Down
1 change: 1 addition & 0 deletions wasm-node/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Fixed

- Fix panic when removing a chain while a networking connection is being opened. ([#1011](https://github.com/smol-dot/smoldot/pull/1011))
- Fix epoch start slot calculation when epochs have been skipped. ([#1015](https://github.com/smol-dot/smoldot/pull/1015))

## 1.0.15 - 2023-08-08

Expand Down

0 comments on commit 726dd51

Please sign in to comment.