Skip to content

Commit 2ea3364

Browse files
authored
change: Remove slot dependency from selection inherents (#1071)
1 parent 4fb701c commit 2ea3364

File tree

6 files changed

+59
-66
lines changed

6 files changed

+59
-66
lines changed

Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ Pallet Session new parameters should be: `type KeyDeposit = ();` and `type Curre
1212
* Updated partner-chains-smart-contracts (raw-scripts) dependency to v8.2.0. Not breaking.
1313
* `SessionManager` and `ShouldEndSession` implementations of `pallet-session-validator-management` rotate one additional
1414
session in order to make `pallet_session` use authorities with less delay.
15+
* Removed use of slots in `authority-selection-inherents`. `AriadneInherentDataProvider::new` now uses current timestamp
16+
and epoch duration to calculate current epoch.
17+
Since the block timestamp is not passed to the inherent data provider creation logic by Aura, the exact timestamp is not
18+
available during block verification, but it can be approximated based on the slot number. See the example impelementation
19+
in the demo node crate.
1520

1621
## Removed
1722

demo/node/src/inherent_data.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ where
105105

106106
let ariadne_data_provider = AriadneIDP::new(
107107
client.as_ref(),
108-
sc_slot_config,
108+
sc_slot_config.epoch_duration().as_millis() as u64,
109109
mc_epoch_config,
110110
parent_hash,
111-
*slot,
111+
(*timestamp).as_millis(),
112112
authority_selection_data_source.as_ref(),
113113
mc_hash.mc_epoch(),
114114
)
@@ -211,9 +211,11 @@ where
211211
governed_map_data_source,
212212
bridge_data_source,
213213
} = self;
214-
let CreateInherentDataConfig { mc_epoch_config, sc_slot_config, time_source, .. } = config;
214+
let CreateInherentDataConfig { mc_epoch_config, sc_slot_config, .. } = config;
215215

216-
let timestamp = TimestampIDP::new(Timestamp::new(time_source.get_current_time_millis()));
216+
let timestamp = TimestampIDP::new(Timestamp::new(
217+
sc_slot_config.slot_start_time(verified_block_slot).unix_millis(),
218+
));
217219
let parent_header = client.expect_header(parent_hash)?;
218220
let parent_slot = slot_from_predigest(&parent_header)?;
219221
let mc_state_reference = McHashIDP::new_verification(
@@ -228,10 +230,10 @@ where
228230

229231
let ariadne_data_provider = AriadneIDP::new(
230232
client.as_ref(),
231-
sc_slot_config,
233+
sc_slot_config.epoch_duration().as_millis() as u64,
232234
mc_epoch_config,
233235
parent_hash,
234-
verified_block_slot,
236+
(*timestamp).as_millis(),
235237
authority_selection_data_source.as_ref(),
236238
mc_state_reference.epoch,
237239
)

toolkit/committee-selection/authority-selection-inherents/Cargo.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@ plutus-datum-derive = { workspace = true }
2424
scale-info = { workspace = true }
2525
selection = { workspace = true }
2626
sidechain-domain = { workspace = true }
27-
sidechain-slots = { workspace = true, optional = true }
2827
sp-api = { workspace = true }
2928
sp-core = { workspace = true }
3029
sp-inherents = { workspace = true }
3130
sp-runtime = { workspace = true }
3231
sp-std = { workspace = true }
3332
thiserror = { workspace = true, optional = true }
3433
serde = { workspace = true }
35-
sp-consensus-slots = { workspace = true }
3634

3735
[dev-dependencies]
3836
hex = { workspace = true }
@@ -49,9 +47,6 @@ std = [
4947
"sidechain-domain/std",
5048
"parity-scale-codec/std",
5149
"serde/std",
52-
"sidechain-slots",
53-
"sidechain-slots/std",
54-
"sidechain-slots/serde",
5550
"sp-api/std",
5651
"sp-session-validator-management/std",
5752
"sp-session-validator-management/serde",

toolkit/committee-selection/authority-selection-inherents/src/ariadne_inherent_data_provider.rs

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use {
99
sidechain_domain::mainchain_epoch::MainchainEpochDerivation,
1010
sidechain_domain::*,
1111
sp_api::ProvideRuntimeApi,
12-
sp_consensus_slots::Slot,
1312
sp_inherents::{InherentData, InherentIdentifier},
1413
sp_runtime::traits::Block as BlockT,
1514
sp_session_validator_management::CommitteeMember as CommitteeMemberT,
@@ -19,7 +18,7 @@ use {
1918
};
2019

2120
#[cfg(feature = "std")]
22-
pub use {sidechain_domain::mainchain_epoch::MainchainEpochConfig, sidechain_slots::ScSlotConfig};
21+
pub use sidechain_domain::mainchain_epoch::MainchainEpochConfig;
2322

2423
#[derive(Clone, Debug, Encode, Decode)]
2524
/// Inherent data provider providing inputs for authority selection.
@@ -34,18 +33,18 @@ impl AriadneInherentDataProvider {
3433
///
3534
/// Parameters:
3635
/// - `client`: runtime client capable of providing [SessionValidatorManagementApi] runtime API
37-
/// - `sc_slot_config`: partner chain slot configuration
36+
/// - `sc_epoch_duration_millis`: duration of the Partner Chain epoch in milliseconds
3837
/// - `mc_epoch_config`: main chain epoch configuration
3938
/// - `parent_hash`: parent hash of the current block
40-
/// - `slot`: slot of the current block
39+
/// - `timestamp_millis`: timestamp of current block in milliseconds
4140
/// - `data_source`: data source implementing [AuthoritySelectionDataSource]
4241
/// - `mc_reference_epoch`: latest stable mainchain epoch
4342
pub async fn new<Block, CommitteeMember, T>(
4443
client: &T,
45-
sc_slot_config: &ScSlotConfig,
44+
sc_epoch_duration_millis: u64,
4645
mc_epoch_config: &MainchainEpochConfig,
4746
parent_hash: <Block as BlockT>::Hash,
48-
slot: Slot,
47+
timestamp_millis: u64,
4948
data_source: &(dyn AuthoritySelectionDataSource + Send + Sync),
5049
mc_reference_epoch: McEpochNumber,
5150
) -> Result<Self, InherentProviderCreationError>
@@ -64,10 +63,10 @@ impl AriadneInherentDataProvider {
6463
{
6564
let for_mc_epoch = mc_epoch_for_next_ariadne_cidp(
6665
client,
67-
sc_slot_config,
66+
sc_epoch_duration_millis,
6867
mc_epoch_config,
6968
parent_hash,
70-
slot,
69+
timestamp_millis,
7170
)?;
7271

7372
let data_epoch = data_source.data_epoch(for_mc_epoch).await?;
@@ -100,9 +99,6 @@ impl AriadneInherentDataProvider {
10099
#[derive(Debug, thiserror::Error)]
101100
/// Error type returned when creation of [AriadneInherentDataProvider] fails.
102101
pub enum InherentProviderCreationError {
103-
/// Slot represents a timestamp bigger than of [u64::MAX].
104-
#[error("Slot represents a timestamp bigger than of u64::MAX")]
105-
SlotTooBig,
106102
/// Couldn't convert timestamp to main chain epoch.
107103
#[error("Couldn't convert timestamp to main chain epoch: {0}")]
108104
McEpochDerivationError(#[from] sidechain_domain::mainchain_epoch::EpochDerivationError),
@@ -120,10 +116,10 @@ pub enum InherentProviderCreationError {
120116
#[cfg(feature = "std")]
121117
fn mc_epoch_for_next_ariadne_cidp<Block, CommitteeMember, T>(
122118
client: &T,
123-
sc_slot_config: &ScSlotConfig,
119+
sc_epoch_duration_millis: u64,
124120
epoch_config: &MainchainEpochConfig,
125121
parent_hash: <Block as BlockT>::Hash,
126-
slot: Slot,
122+
timestamp_millis: u64,
127123
) -> Result<McEpochNumber, InherentProviderCreationError>
128124
where
129125
Block: BlockT,
@@ -138,34 +134,27 @@ where
138134
ScEpochNumber,
139135
>,
140136
{
137+
use sp_core::offchain::Timestamp;
138+
141139
let next_unset_epoch = client.runtime_api().get_next_unset_epoch_number(parent_hash)?;
142140

143-
let for_sc_epoch_number = {
141+
let for_timestamp = {
144142
// A special case for the genesis committee (current epoch 0, next unset epoch 1).
145143
// The genesis committee epoch is initialized with 0, so in the very first block we need to provide
146-
// the epoch number based on the current slot number
144+
// the epoch number based on the current timestamp
147145
if next_unset_epoch == ScEpochNumber(1) {
148-
sc_slot_config.epoch_number(slot)
146+
// We first convert the timestamp to PC epoch number and then use the starting time of this
147+
// to ensure that all timestamps within a PC epoch produce the same candidates. This is
148+
// necessary in case the boundaries of PC epochs and MC epochs do not align.
149+
let current_pc_epoch = timestamp_millis / sc_epoch_duration_millis;
150+
current_pc_epoch * sc_epoch_duration_millis
149151
} else {
150-
next_unset_epoch
152+
next_unset_epoch.0 * sc_epoch_duration_millis
151153
}
152154
};
153155

154-
sc_epoch_to_mc_epoch(for_sc_epoch_number, sc_slot_config, epoch_config)
155-
}
156-
157-
#[cfg(feature = "std")]
158-
fn sc_epoch_to_mc_epoch(
159-
sc_epoch: ScEpochNumber,
160-
sc_slot_config: &ScSlotConfig,
161-
epoch_config: &MainchainEpochConfig,
162-
) -> Result<McEpochNumber, InherentProviderCreationError> {
163-
let timestamp = sc_slot_config
164-
.epoch_start_time(sc_epoch)
165-
.ok_or(InherentProviderCreationError::SlotTooBig)?;
166-
167156
epoch_config
168-
.timestamp_to_mainchain_epoch(timestamp)
157+
.timestamp_to_mainchain_epoch(Timestamp::from_unix_millis(for_timestamp))
169158
.map_err(InherentProviderCreationError::McEpochDerivationError)
170159
}
171160

@@ -205,24 +194,24 @@ mod tests {
205194
use crate::ariadne_inherent_data_provider::AriadneInherentDataProvider;
206195
use crate::mock::MockAuthoritySelectionDataSource;
207196
use crate::runtime_api_mock::*;
208-
use SlotDuration;
209197
use sidechain_domain::mainchain_epoch::*;
210-
use sidechain_slots::*;
211198
use sp_core::H256;
212199
use sp_core::offchain::Timestamp;
213200

201+
const TIMESTAMP: u64 = 400_000;
202+
214203
#[tokio::test]
215204
async fn return_empty_ariadne_cidp_if_runtime_requests_too_new_epoch() {
216205
// This is the epoch number that is too new
217206
let next_unset_epoch_number = ScEpochNumber(42);
218207
let mc_reference_epoch = McEpochNumber(1);
219208
let empty_ariadne_idp = AriadneInherentDataProvider::new(
220209
&client(next_unset_epoch_number),
221-
&sc_slot_config(),
210+
sc_epoch_duration_millis(),
222211
&epoch_config(),
223212
H256::zero(),
224-
// This is the slot that will be used to calculate current_epoch_number
225-
Slot::from(400u64),
213+
// This is the timestamp that will be used to calculate current_epoch_number
214+
TIMESTAMP,
226215
&MockAuthoritySelectionDataSource::default(),
227216
mc_reference_epoch,
228217
)
@@ -241,11 +230,11 @@ mod tests {
241230
let mc_reference_epoch = McEpochNumber(5);
242231
let ariadne_idp = AriadneInherentDataProvider::new(
243232
&client(next_unset_epoch_number),
244-
&sc_slot_config(),
233+
sc_epoch_duration_millis(),
245234
&epoch_config(),
246235
H256::zero(),
247-
// This is the slot that will be used to calculate current_epoch_number
248-
Slot::from(400u64),
236+
// This is the timestamp that will be used to calculate current_epoch_number
237+
TIMESTAMP,
249238
&MockAuthoritySelectionDataSource::default()
250239
.with_permissioned_candidates(vec![None, None, None, None, None])
251240
.with_num_permissioned_candidates(3),
@@ -266,11 +255,11 @@ mod tests {
266255
let mc_reference_epoch = McEpochNumber(5);
267256
let ariadne_idp = AriadneInherentDataProvider::new(
268257
&client(next_unset_epoch_number),
269-
&sc_slot_config(),
258+
sc_epoch_duration_millis(),
270259
&epoch_config(),
271260
H256::zero(),
272-
// This is the slot that will be used to calculate current_epoch_number
273-
Slot::from(400u64),
261+
// This is the timestamp that will be used to calculate current_epoch_number
262+
TIMESTAMP,
274263
&MockAuthoritySelectionDataSource::default()
275264
.with_permissioned_candidates(vec![None, None, None, None, None])
276265
.with_num_permissioned_candidates(0),
@@ -282,11 +271,8 @@ mod tests {
282271
assert!(ariadne_idp.unwrap().data.is_some());
283272
}
284273

285-
fn sc_slot_config() -> ScSlotConfig {
286-
ScSlotConfig {
287-
slots_per_epoch: SlotsPerEpoch(10),
288-
slot_duration: SlotDuration::from_millis(1000),
289-
}
274+
fn sc_epoch_duration_millis() -> u64 {
275+
60 * 60 * 1000
290276
}
291277

292278
fn client(next_unset_epoch_number: ScEpochNumber) -> TestApi {
@@ -297,11 +283,7 @@ mod tests {
297283
MainchainEpochConfig {
298284
first_epoch_timestamp_millis: Timestamp::from_unix_millis(0),
299285
first_epoch_number: 0,
300-
epoch_duration_millis: Duration::from_millis(
301-
u64::from(sc_slot_config().slots_per_epoch.0)
302-
* sc_slot_config().slot_duration.as_millis()
303-
* 10,
304-
),
286+
epoch_duration_millis: Duration::from_millis(10 * sc_epoch_duration_millis()),
305287
first_slot_number: 0,
306288
slot_duration_millis: Duration::from_millis(1000),
307289
}

toolkit/sidechain/sidechain-slots/src/lib.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#[cfg(feature = "std")]
88
pub mod runtime_api_client;
99

10-
use core::ops::Rem;
10+
use core::{ops::Rem, time::Duration};
1111
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
1212
use scale_info::TypeInfo;
1313
#[cfg(feature = "serde")]
@@ -86,6 +86,12 @@ pub struct ScSlotConfig {
8686
}
8787

8888
impl ScSlotConfig {
89+
#[cfg(feature = "std")]
90+
/// Returns epoch duration
91+
pub fn epoch_duration(&self) -> Duration {
92+
self.slot_duration.as_duration() * self.slots_per_epoch.0
93+
}
94+
8995
/// Returns the epoch number of `slot`
9096
pub fn epoch_number(&self, slot: Slot) -> ScEpochNumber {
9197
self.slots_per_epoch.epoch_number(slot)
@@ -101,6 +107,11 @@ impl ScSlotConfig {
101107
Slot::from_timestamp(timestamp.into(), self.slot_duration)
102108
}
103109

110+
/// Returns the start timestamp of `slot`
111+
pub fn slot_start_time(&self, slot: Slot) -> Timestamp {
112+
Timestamp::from_unix_millis(self.slot_duration.as_millis() * u64::from(slot))
113+
}
114+
104115
/// Returns the start timestamp of `epoch`
105116
pub fn epoch_start_time(&self, epoch: ScEpochNumber) -> Option<Timestamp> {
106117
self.first_slot_number(epoch)

0 commit comments

Comments
 (0)