v1.rs 28.9 KB
Newer Older
asynchronous rob's avatar
asynchronous rob committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.

//! V1 Primitives.

use sp_std::prelude::*;
use parity_scale_codec::{Encode, Decode};
use bitvec::vec::BitVec;

use primitives::RuntimeDebug;
use runtime_primitives::traits::AppVerify;
use inherents::InherentIdentifier;
26
use sp_arithmetic::traits::{BaseArithmetic, Saturating, Zero};
asynchronous rob's avatar
asynchronous rob committed
27

28
pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT};
asynchronous rob's avatar
asynchronous rob committed
29
30
31
32
33

// Export some core primitives.
pub use polkadot_core_primitives::v1::{
	BlockNumber, Moment, Signature, AccountPublic, AccountId, AccountIndex,
	ChainId, Hash, Nonce, Balance, Header, Block, BlockId, UncheckedExtrinsic,
34
	Remark, DownwardMessage, InboundDownwardMessage,
asynchronous rob's avatar
asynchronous rob committed
35
36
37
38
};

// Export some polkadot-parachain primitives
pub use polkadot_parachain::primitives::{
39
	Id, LOWEST_USER_ID, UpwardMessage, HeadData, BlockData, ValidationCode,
asynchronous rob's avatar
asynchronous rob committed
40
41
42
43
44
45
46
47
48
49
50
51
52
};

// Export some basic parachain primitives from v0.
pub use crate::v0::{
	CollatorId, CollatorSignature, PARACHAIN_KEY_TYPE_ID, ValidatorId, ValidatorIndex,
	ValidatorSignature, SigningContext, Signed, ValidityAttestation,
	CompactStatement, SignedStatement, ErasureChunk, EncodeAs,
};

// More exports from v0 for std.
#[cfg(feature = "std")]
pub use crate::v0::{ValidatorPair, CollatorPair};

53
pub use sp_staking::SessionIndex;
54
pub use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
55

asynchronous rob's avatar
asynchronous rob committed
56
57
58
59
60
61
62
/// Unique identifier for the Inclusion Inherent
pub const INCLUSION_INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0";

/// Get a collator signature payload on a relay-parent, block-data combo.
pub fn collator_signature_payload<H: AsRef<[u8]>>(
	relay_parent: &H,
	para_id: &Id,
63
	persisted_validation_data_hash: &Hash,
asynchronous rob's avatar
asynchronous rob committed
64
	pov_hash: &Hash,
65
) -> [u8; 100] {
asynchronous rob's avatar
asynchronous rob committed
66
	// 32-byte hash length is protected in a test below.
67
	let mut payload = [0u8; 100];
asynchronous rob's avatar
asynchronous rob committed
68
69
70

	payload[0..32].copy_from_slice(relay_parent.as_ref());
	u32::from(*para_id).using_encoded(|s| payload[32..32 + s.len()].copy_from_slice(s));
71
	payload[36..68].copy_from_slice(persisted_validation_data_hash.as_ref());
72
	payload[68..100].copy_from_slice(pov_hash.as_ref());
asynchronous rob's avatar
asynchronous rob committed
73
74
75
76
77
78
79

	payload
}

fn check_collator_signature<H: AsRef<[u8]>>(
	relay_parent: &H,
	para_id: &Id,
80
	persisted_validation_data_hash: &Hash,
asynchronous rob's avatar
asynchronous rob committed
81
82
83
84
	pov_hash: &Hash,
	collator: &CollatorId,
	signature: &CollatorSignature,
) -> Result<(),()> {
85
86
87
	let payload = collator_signature_payload(
		relay_parent,
		para_id,
88
		persisted_validation_data_hash,
89
90
91
		pov_hash,
	);

asynchronous rob's avatar
asynchronous rob committed
92
93
94
95
96
97
98
99
100
	if signature.verify(&payload[..], collator) {
		Ok(())
	} else {
		Err(())
	}
}

/// A unique descriptor of the candidate receipt.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
101
#[cfg_attr(feature = "std", derive(Debug, Default, Hash))]
asynchronous rob's avatar
asynchronous rob committed
102
103
104
105
106
107
108
pub struct CandidateDescriptor<H = Hash> {
	/// The ID of the para this is a candidate for.
	pub para_id: Id,
	/// The hash of the relay-chain block this is executed in the context of.
	pub relay_parent: H,
	/// The collator's sr25519 public key.
	pub collator: CollatorId,
109
	/// The blake2-256 hash of the persisted validation data. This is extra data derived from
110
111
	/// relay-chain state which may vary based on bitfields included before the candidate.
	/// Thus it cannot be derived entirely from the relay-parent.
112
	pub persisted_validation_data_hash: Hash,
asynchronous rob's avatar
asynchronous rob committed
113
114
	/// The blake2-256 hash of the pov.
	pub pov_hash: Hash,
115
116
117
	/// Signature on blake2-256 of components of this receipt:
	/// The parachain index, the relay parent, the validation data hash, and the pov_hash.
	pub signature: CollatorSignature,
asynchronous rob's avatar
asynchronous rob committed
118
119
120
121
122
123
124
125
}

impl<H: AsRef<[u8]>> CandidateDescriptor<H> {
	/// Check the signature of the collator within this descriptor.
	pub fn check_collator_signature(&self) -> Result<(), ()> {
		check_collator_signature(
			&self.relay_parent,
			&self.para_id,
126
			&self.persisted_validation_data_hash,
asynchronous rob's avatar
asynchronous rob committed
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
			&self.pov_hash,
			&self.collator,
			&self.signature,
		)
	}
}

/// A candidate-receipt.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))]
pub struct CandidateReceipt<H = Hash> {
	/// The descriptor of the candidate.
	pub descriptor: CandidateDescriptor<H>,
	/// The hash of the encoded commitments made as a result of candidate execution.
	pub commitments_hash: Hash,
}

impl<H> CandidateReceipt<H> {
	/// Get a reference to the candidate descriptor.
	pub fn descriptor(&self) -> &CandidateDescriptor<H> {
		&self.descriptor
	}

	/// Computes the blake2-256 hash of the receipt.
	pub fn hash(&self) -> Hash where H: Encode {
		BlakeTwo256::hash_of(self)
	}
}

/// All data pertaining to the execution of a para candidate.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))]
159
pub struct FullCandidateReceipt<H = Hash, N = BlockNumber> {
asynchronous rob's avatar
asynchronous rob committed
160
161
	/// The inner candidate receipt.
	pub inner: CandidateReceipt<H>,
162
163
164
165
166
	/// The validation data derived from the relay-chain state at that
	/// point. The hash of the persisted validation data should
	/// match the `persisted_validation_data_hash` in the descriptor
	/// of the receipt.
	pub validation_data: ValidationData<N>,
asynchronous rob's avatar
asynchronous rob committed
167
168
169
170
}

/// A candidate-receipt with commitments directly included.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
171
#[cfg_attr(feature = "std", derive(Debug, Default, Hash))]
asynchronous rob's avatar
asynchronous rob committed
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
pub struct CommittedCandidateReceipt<H = Hash> {
	/// The descriptor of the candidate.
	pub descriptor: CandidateDescriptor<H>,
	/// The commitments of the candidate receipt.
	pub commitments: CandidateCommitments,
}

impl<H> CommittedCandidateReceipt<H> {
	/// Get a reference to the candidate descriptor.
	pub fn descriptor(&self) -> &CandidateDescriptor<H> {
		&self.descriptor
	}
}

impl<H: Clone> CommittedCandidateReceipt<H> {
	/// Transforms this into a plain CandidateReceipt.
	pub fn to_plain(&self) -> CandidateReceipt<H> {
		CandidateReceipt {
			descriptor: self.descriptor.clone(),
			commitments_hash: self.commitments.hash(),
		}
	}

	/// Computes the hash of the committed candidate receipt.
	///
	/// This computes the canonical hash, not the hash of the directly encoded data.
	/// Thus this is a shortcut for `candidate.to_plain().hash()`.
	pub fn hash(&self) -> Hash where H: Encode {
		self.to_plain().hash()
	}
}

impl PartialOrd for CommittedCandidateReceipt {
	fn partial_cmp(&self, other: &Self) -> Option<sp_std::cmp::Ordering> {
		Some(self.cmp(other))
	}
}

impl Ord for CommittedCandidateReceipt {
	fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering {
		// TODO: compare signatures or something more sane
		// https://github.com/paritytech/polkadot/issues/222
		self.descriptor().para_id.cmp(&other.descriptor().para_id)
			.then_with(|| self.commitments.head_data.cmp(&other.commitments.head_data))
	}
}

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/// The validation data provide information about how to validate both the inputs and
/// outputs of a candidate.
///
/// There are two types of validation data: persisted and transient.
/// Their respective sections of the guide elaborate on their functionality in more detail.
///
/// This information is derived from the chain state and will vary from para to para,
/// although some of the fields may be the same for every para.
///
/// Persisted validation data are generally derived from some relay-chain state to form inputs
/// to the validation function, and as such need to be persisted by the availability system to
/// avoid dependence on availability of the relay-chain state. The backing phase of the
/// inclusion pipeline ensures that everything that is included in a valid fork of the
/// relay-chain already adheres to the transient constraints.
///
/// The validation data also serve the purpose of giving collators a means of ensuring that
/// their produced candidate and the commitments submitted to the relay-chain alongside it
/// will pass the checks done by the relay-chain when backing, and give validators
/// the same understanding when determining whether to second or attest to a candidate.
///
/// Since the commitments of the validation function are checked by the
/// relay-chain, secondary checkers can rely on the invariant that the relay-chain
/// only includes para-blocks for which these checks have already been done. As such,
/// there is no need for the validation data used to inform validators and collators about
/// the checks the relay-chain will perform to be persisted by the availability system.
/// Nevertheless, we expose it so the backing validators can validate the outputs of a
/// candidate before voting to submit it to the relay-chain and so collators can
/// collate candidates that satisfy the criteria implied these transient validation data.
247
248
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Default))]
249
250
251
252
253
254
255
256
pub struct ValidationData<N = BlockNumber> {
	/// The persisted validation data.
	pub persisted: PersistedValidationData<N>,
	/// The transient validation data.
	pub transient: TransientValidationData<N>,
}

/// Validation data that needs to be persisted for secondary checkers.
asynchronous rob's avatar
asynchronous rob committed
257
258
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))]
259
pub struct PersistedValidationData<N = BlockNumber> {
asynchronous rob's avatar
asynchronous rob committed
260
261
	/// The parent head-data.
	pub parent_head: HeadData,
262
263
264
265
266
267
	/// The relay-chain block number this is in the context of.
	pub block_number: N,
	/// The list of MQC heads for the inbound channels paired with the sender para ids. This
	/// vector is sorted ascending by the para id and doesn't contain multiple entries with the same
	/// sender.
	pub hrmp_mqc_heads: Vec<(Id, Hash)>,
268
269
270
271
272
	/// The MQC head for the DMQ.
	///
	/// The DMQ MQC head will be used by the validation function to authorize the downward messages
	/// passed by the collator.
	pub dmq_mqc_head: Hash,
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
}

impl<N: Encode> PersistedValidationData<N> {
	/// Compute the blake2-256 hash of the persisted validation data.
	pub fn hash(&self) -> Hash {
		BlakeTwo256::hash_of(self)
	}
}

/// Validation data for checking outputs of the validation-function.
/// As such, they also inform the collator about how to construct the candidate.
///
/// These are transient because they are not necessary beyond the point where the
/// candidate is backed.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Default))]
pub struct TransientValidationData<N = BlockNumber> {
	/// The maximum code size permitted, in bytes.
	pub max_code_size: u32,
	/// The maximum head-data size permitted, in bytes.
	pub max_head_data_size: u32,
asynchronous rob's avatar
asynchronous rob committed
294
295
296
297
298
299
300
301
302
303
304
305
306
	/// The balance of the parachain at the moment of validation.
	pub balance: Balance,
	/// Whether the parachain is allowed to upgrade its validation code.
	///
	/// This is `Some` if so, and contains the number of the minimum relay-chain
	/// height at which the upgrade will be applied, if an upgrade is signaled
	/// now.
	///
	/// A parachain should enact its side of the upgrade at the end of the first
	/// parablock executing in the context of a relay-chain block with at least this
	/// height. This may be equal to the current perceived relay-chain block height, in
	/// which case the code upgrade should be applied at the end of the signaling
	/// block.
307
	pub code_upgrade_allowed: Option<N>,
308
309
	/// The number of messages pending of the downward message queue.
	pub dmq_length: u32,
asynchronous rob's avatar
asynchronous rob committed
310
311
}

312
313
314
315
316
317
318
319
320
321
/// Outputs of validating a candidate.
#[derive(Encode, Decode)]
#[cfg_attr(feature = "std", derive(Clone, Debug, Default))]
pub struct ValidationOutputs {
	/// The head-data produced by validation.
	pub head_data: HeadData,
	/// Upward messages to the relay chain.
	pub upward_messages: Vec<UpwardMessage>,
	/// The new validation code submitted by the execution, if any.
	pub new_validation_code: Option<ValidationCode>,
322
323
	/// The number of messages processed from the DMQ.
	pub processed_downward_messages: u32,
324
325
}

asynchronous rob's avatar
asynchronous rob committed
326
327
/// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
328
#[cfg_attr(feature = "std", derive(Debug, Default, Hash))]
asynchronous rob's avatar
asynchronous rob committed
329
330
331
332
333
334
335
336
337
pub struct CandidateCommitments {
	/// Messages destined to be interpreted by the Relay chain itself.
	pub upward_messages: Vec<UpwardMessage>,
	/// The root of a block's erasure encoding Merkle tree.
	pub erasure_root: Hash,
	/// New validation code.
	pub new_validation_code: Option<ValidationCode>,
	/// The head-data produced as a result of execution.
	pub head_data: HeadData,
338
339
	/// The number of messages processed from the DMQ.
	pub processed_downward_messages: u32,
asynchronous rob's avatar
asynchronous rob committed
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
}

impl CandidateCommitments {
	/// Compute the blake2-256 hash of the commitments.
	pub fn hash(&self) -> Hash {
		BlakeTwo256::hash_of(self)
	}
}

/// A Proof-of-Validity
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct PoV {
	/// The block witness data.
	pub block_data: BlockData,
}

impl PoV {
	/// Get the blake2-256 hash of the PoV.
	#[cfg(feature = "std")]
	pub fn hash(&self) -> Hash {
		BlakeTwo256::hash_of(self)
	}
}

/// A bitfield concerning availability of backed candidates.
Fedor Sakharov's avatar
Fedor Sakharov committed
366
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
asynchronous rob's avatar
asynchronous rob committed
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
pub struct AvailabilityBitfield(pub BitVec<bitvec::order::Lsb0, u8>);

impl From<BitVec<bitvec::order::Lsb0, u8>> for AvailabilityBitfield {
	fn from(inner: BitVec<bitvec::order::Lsb0, u8>) -> Self {
		AvailabilityBitfield(inner)
	}
}

/// A bitfield signed by a particular validator about the availability of pending candidates.
pub type SignedAvailabilityBitfield = Signed<AvailabilityBitfield>;

/// A set of signed availability bitfields. Should be sorted by validator index, ascending.
pub type SignedAvailabilityBitfields = Vec<SignedAvailabilityBitfield>;

/// A backed (or backable, depending on context) candidate.
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
pub struct BackedCandidate<H = Hash> {
	/// The candidate referred to.
	pub candidate: CommittedCandidateReceipt<H>,
	/// The validity votes themselves, expressed as signatures.
	pub validity_votes: Vec<ValidityAttestation>,
	/// The indices of the validators within the group, expressed as a bitfield.
	pub validator_indices: BitVec<bitvec::order::Lsb0, u8>,
}

impl<H> BackedCandidate<H> {
	/// Get a reference to the descriptor of the para.
	pub fn descriptor(&self) -> &CandidateDescriptor<H> {
		&self.candidate.descriptor
	}
}

/// Verify the backing of the given candidate.
///
/// Provide a lookup from the index of a validator within the group assigned to this para,
/// as opposed to the index of the validator within the overall validator set, as well as
/// the number of validators in the group.
///
/// Also provide the signing context.
///
/// Returns either an error, indicating that one of the signatures was invalid or that the index
/// was out-of-bounds, or the number of signatures checked.
pub fn check_candidate_backing<H: AsRef<[u8]> + Clone + Encode>(
	backed: &BackedCandidate<H>,
	signing_context: &SigningContext<H>,
	group_len: usize,
	validator_lookup: impl Fn(usize) -> Option<ValidatorId>,
) -> Result<usize, ()> {
	if backed.validator_indices.len() != group_len {
		return Err(())
	}

	if backed.validity_votes.len() > group_len {
		return Err(())
	}

	// this is known, even in runtime, to be blake2-256.
	let hash: Hash = backed.candidate.hash();

	let mut signed = 0;
	for ((val_in_group_idx, _), attestation) in backed.validator_indices.iter().enumerate()
		.filter(|(_, signed)| **signed)
		.zip(backed.validity_votes.iter())
	{
		let validator_id = validator_lookup(val_in_group_idx).ok_or(())?;
		let payload = attestation.signed_payload(hash.clone(), signing_context);
		let sig = attestation.signature();

		if sig.verify(&payload[..], &validator_id) {
			signed += 1;
		} else {
			return Err(())
		}
	}

	if signed != backed.validity_votes.len() {
		return Err(())
	}

	Ok(signed)
}

/// The unique (during session) index of a core.
#[derive(Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct CoreIndex(pub u32);

impl From<u32> for CoreIndex {
	fn from(i: u32) -> CoreIndex {
		CoreIndex(i)
	}
}

/// The unique (during session) index of a validator group.
#[derive(Encode, Decode, Default, Clone, Copy)]
#[cfg_attr(feature = "std", derive(Eq, Hash, PartialEq, Debug))]
pub struct GroupIndex(pub u32);

impl From<u32> for GroupIndex {
	fn from(i: u32) -> GroupIndex {
		GroupIndex(i)
	}
}

/// A claim on authoring the next block for a given parathread.
#[derive(Clone, Encode, Decode, Default)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct ParathreadClaim(pub Id, pub CollatorId);

/// An entry tracking a claim to ensure it does not pass the maximum number of retries.
#[derive(Clone, Encode, Decode, Default)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct ParathreadEntry {
	/// The claim.
	pub claim: ParathreadClaim,
	/// Number of retries.
	pub retries: u32,
}

/// What is occupying a specific availability core.
#[derive(Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub enum CoreOccupied {
	/// A parathread.
	Parathread(ParathreadEntry),
	/// A parachain.
	Parachain,
}

/// This is the data we keep available for each candidate included in the relay chain.
#[derive(Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct AvailableData {
	/// The Proof-of-Validation of the candidate.
	pub pov: PoV,
502
503
	/// The persisted validation data needed for secondary checks.
	pub validation_data: PersistedValidationData,
asynchronous rob's avatar
asynchronous rob committed
504
}
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

/// A helper data-type for tracking validator-group rotations.
#[derive(Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct GroupRotationInfo<N = BlockNumber> {
	/// The block number where the session started.
	pub session_start_block: N,
	/// How often groups rotate. 0 means never.
	pub group_rotation_frequency: N,
	/// The current block number.
	pub now: N,
}

impl GroupRotationInfo {
	/// Returns the index of the group needed to validate the core at the given index, assuming
	/// the given number of cores.
	///
	/// `core_index` should be less than `cores`, which is capped at u32::max().
	pub fn group_for_core(&self, core_index: CoreIndex, cores: usize) -> GroupIndex {
		if self.group_rotation_frequency == 0 { return GroupIndex(core_index.0) }
		if cores == 0 { return GroupIndex(0) }

		let cores = sp_std::cmp::min(cores, u32::max_value() as usize);
		let blocks_since_start = self.now.saturating_sub(self.session_start_block);
		let rotations = blocks_since_start / self.group_rotation_frequency;

		let idx = (core_index.0 as usize + rotations as usize) % cores;
		GroupIndex(idx as u32)
	}
}

impl<N: Saturating + BaseArithmetic + Copy> GroupRotationInfo<N> {
	/// Returns the block number of the next rotation after the current block. If the current block
	/// is 10 and the rotation frequency is 5, this should return 15.
	///
	/// If the group rotation frequency is 0, returns 0.
	pub fn next_rotation_at(&self) -> N {
		if self.group_rotation_frequency.is_zero() { return Zero::zero() }

		let cycle_once = self.now + self.group_rotation_frequency;
		cycle_once - (
			cycle_once.saturating_sub(self.session_start_block) % self.group_rotation_frequency
		)
	}

	/// Returns the block number of the last rotation before or including the current block. If the
	/// current block is 10 and the rotation frequency is 5, this should return 10.
	///
	/// If the group rotation frequency is 0, returns 0.
	pub fn last_rotation_at(&self) -> N {
		if self.group_rotation_frequency.is_zero() { return Zero::zero() }
		self.now - (
			self.now.saturating_sub(self.session_start_block) % self.group_rotation_frequency
		)
	}
}

/// Information about a core which is currently occupied.
#[derive(Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct OccupiedCore<N = BlockNumber> {
	/// The ID of the para occupying the core.
	pub para_id: Id,
	/// If this core is freed by availability, this is the assignment that is next up on this
	/// core, if any. None if there is nothing queued for this core.
	pub next_up_on_available: Option<ScheduledCore>,
	/// The relay-chain block number this began occupying the core at.
	pub occupied_since: N,
	/// The relay-chain block this will time-out at, if any.
	pub time_out_at: N,
	/// If this core is freed by being timed-out, this is the assignment that is next up on this
	/// core. None if there is nothing queued for this core or there is no possibility of timing
	/// out.
	pub next_up_on_time_out: Option<ScheduledCore>,
	/// A bitfield with 1 bit for each validator in the set. `1` bits mean that the corresponding
	/// validators has attested to availability on-chain. A 2/3+ majority of `1` bits means that
	/// this will be available.
	pub availability: BitVec<bitvec::order::Lsb0, u8>,
	/// The group assigned to distribute availability pieces of this candidate.
	pub group_responsible: GroupIndex,
}

/// Information about a core which is currently occupied.
#[derive(Clone, Encode, Decode)]
589
#[cfg_attr(feature = "std", derive(PartialEq, Debug, Default))]
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
pub struct ScheduledCore {
	/// The ID of a para scheduled.
	pub para_id: Id,
	/// The collator required to author the block, if any.
	pub collator: Option<CollatorId>,
}

/// The state of a particular availability core.
#[derive(Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub enum CoreState<N = BlockNumber> {
	/// The core is currently occupied.
	#[codec(index = "0")]
	Occupied(OccupiedCore<N>),
	/// The core is currently free, with a para scheduled and given the opportunity
	/// to occupy.
	///
	/// If a particular Collator is required to author this block, that is also present in this
	/// variant.
	#[codec(index = "1")]
	Scheduled(ScheduledCore),
	/// The core is currently free and there is nothing scheduled. This can be the case for parathread
	/// cores when there are no parathread blocks queued. Parachain cores will never be left idle.
	#[codec(index = "2")]
	Free,
}

617
618
619
620
621
622
623
624
625
626
627
impl<N> CoreState<N> {
	/// If this core state has a `para_id`, return it.
	pub fn para_id(&self) -> Option<Id> {
		match self {
			Self::Occupied(OccupiedCore { para_id, ..}) => Some(*para_id),
			Self::Scheduled(ScheduledCore { para_id, .. }) => Some(*para_id),
			Self::Free => None,
		}
	}
}

628
/// An assumption being made about the state of an occupied core.
629
#[derive(Clone, Copy, Encode, Decode)]
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub enum OccupiedCoreAssumption {
	/// The candidate occupying the core was made available and included to free the core.
	#[codec(index = "0")]
	Included,
	/// The candidate occupying the core timed out and freed the core without advancing the para.
	#[codec(index = "1")]
	TimedOut,
	/// The core was not occupied to begin with.
	#[codec(index = "2")]
	Free,
}

/// An even concerning a candidate.
#[derive(Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub enum CandidateEvent<H = Hash> {
	/// This candidate receipt was backed in the most recent block.
	#[codec(index = "0")]
	CandidateBacked(CandidateReceipt<H>, HeadData),
	/// This candidate receipt was included and became a parablock at the most recent block.
	#[codec(index = "1")]
	CandidateIncluded(CandidateReceipt<H>, HeadData),
	/// This candidate receipt was not made available in time and timed out.
	#[codec(index = "2")]
	CandidateTimedOut(CandidateReceipt<H>, HeadData),
}

658
659
660
661
662
663
/// Errors that can happen when checking the validation outputs of a parachain candidate.
#[derive(Clone, Encode, Decode, Copy)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug, displaydoc::Display))]
pub enum CheckValidationOutputsError {
	/// The head data is too large.
	HeadDataTooLarge,
Bastian Köcher's avatar
Bastian Köcher committed
664
	/// The parachain tried to upgrade its code too early.
665
666
667
668
669
670
671
672
673
	PrematureCodeUpgrade,
	/// The new parachain code is too large.
	NewCodeTooLarge,
	/// The parachain didn't handled the downward messages correctly.
	IncorrectDownwardMessageHandling,
	/// The parachain returned invalid upward messages.
	InvalidUpwardMessages,
}

674
675
sp_api::decl_runtime_apis! {
	/// The API for querying the state of parachains on-chain.
676
	pub trait ParachainHost<H: Decode = Hash, N: Encode + Decode = BlockNumber> {
677
678
679
680
681
682
683
684
685
686
687
688
		/// Get the current validators.
		fn validators() -> Vec<ValidatorId>;

		/// Returns the validator groups and rotation info localized based on the block whose state
		/// this is invoked on. Note that `now` in the `GroupRotationInfo` should be the successor of
		/// the number of the block.
		fn validator_groups() -> (Vec<Vec<ValidatorIndex>>, GroupRotationInfo<N>);

		/// Yields information on all availability cores. Cores are either free or occupied. Free
		/// cores can have paras assigned to them.
		fn availability_cores() -> Vec<CoreState<N>>;

689
690
691
692
693
694
695
		/// Yields the full validation data for the given ParaId along with an assumption that
		/// should be used if the para currently occupieds a core.
		///
		/// Returns `None` if either the para is not registered or the assumption is `Freed`
		/// and the para already occupies a core.
		fn full_validation_data(para_id: Id, assumption: OccupiedCoreAssumption)
			-> Option<ValidationData<N>>;
696

697
		/// Yields the persisted validation data for the given ParaId along with an assumption that
698
699
700
701
		/// should be used if the para currently occupies a core.
		///
		/// Returns `None` if either the para is not registered or the assumption is `Freed`
		/// and the para already occupies a core.
702
703
		fn persisted_validation_data(para_id: Id, assumption: OccupiedCoreAssumption)
			-> Option<PersistedValidationData<N>>;
704

705
		/// Checks if the given validation outputs pass the acceptance criteria.
706
		fn check_validation_outputs(para_id: Id, outputs: ValidationOutputs) -> Result<(), CheckValidationOutputsError>;
707

708
709
710
711
712
713
714
715
716
717
718
719
		/// Returns the session index expected at a child of the block.
		///
		/// This can be used to instantiate a `SigningContext`.
		fn session_index_for_child() -> SessionIndex;

		/// Fetch the validation code used by a para, making the given `OccupiedCoreAssumption`.
		///
		/// Returns `None` if either the para is not registered or the assumption is `Freed`
		/// and the para already occupies a core.
		fn validation_code(para_id: Id, assumption: OccupiedCoreAssumption)
			-> Option<ValidationCode>;

720
721
722
723
724
725
726
727
		/// Fetch the historical validation code used by a para for candidates executed in the
		/// context of a given block height in the current chain.
		///
		/// `context_height` may be no greater than the height of the block in whose
		/// state the runtime API is executed.
		fn historical_validation_code(para_id: Id, context_height: N)
			-> Option<ValidationCode>;

728
729
730
731
732
733
734
735
736
		/// Get the receipt of a candidate pending availability. This returns `Some` for any paras
		/// assigned to occupied cores in `availability_cores` and `None` otherwise.
		fn candidate_pending_availability(para_id: Id) -> Option<CommittedCandidateReceipt<H>>;

		/// Get a vector of events concerning candidates that occurred within a block.
		// NOTE: this needs to skip block initialization as events are wiped within block
		// initialization.
		#[skip_initialize_block]
		fn candidate_events() -> Vec<CandidateEvent<H>>;
737
738

		/// Get the `AuthorityDiscoveryId`s corresponding to the given `ValidatorId`s.
739
		/// Currently this request is limited to validators in the current session.
740
741
742
743
		///
		/// We assume that every validator runs authority discovery,
		/// which would allow us to establish point-to-point connection to given validators.
		fn validator_discovery(validators: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>>;
744
745
746
747
748

		/// Get all the pending inbound messages in the downward message queue for a para.
		fn dmq_contents(
			recipient: Id,
		) -> Vec<InboundDownwardMessage<N>>;
749
750
751
	}
}

752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
/// Custom validity errors used in Polkadot while validating transactions.
#[repr(u8)]
pub enum ValidityError {
	/// The Ethereum signature is invalid.
	InvalidEthereumSignature = 0,
	/// The signer has no claim.
	SignerHasNoClaim = 1,
	/// No permission to execute the call.
	NoPermission = 2,
	/// An invalid statement was made for a claim.
	InvalidStatement = 3,
}

impl From<ValidityError> for u8 {
	fn from(err: ValidityError) -> Self {
		err as u8
	}
}

771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn group_rotation_info_calculations() {
		let info = GroupRotationInfo {
			session_start_block: 10u32,
			now: 15,
			group_rotation_frequency: 5,
		};

		assert_eq!(info.next_rotation_at(), 20);
		assert_eq!(info.last_rotation_at(), 15);

		let info = GroupRotationInfo {
			session_start_block: 10u32,
			now: 11,
			group_rotation_frequency: 0,
		};

		assert_eq!(info.next_rotation_at(), 0);
		assert_eq!(info.last_rotation_at(), 0);
	}
795
796
797
798
799
800
801
802
803
804
805
806
807
808

	#[test]
	fn collator_signature_payload_is_valid() {
		// if this fails, collator signature verification code has to be updated.
		let h = Hash::default();
		assert_eq!(h.as_ref().len(), 32);

		let _payload = collator_signature_payload(
			&Hash::from([1; 32]),
			&5u32.into(),
			&Hash::from([2; 32]),
			&Hash::from([3; 32]),
		);
	}
809
}