Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
}
}
}
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.
pub fn next_rotation_at(&self) -> N {
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.
pub fn last_rotation_at(&self) -> N {
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, TypeInfo, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(PartialEq))]
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
pub struct OccupiedCore<H = Hash, N = BlockNumber> {
// NOTE: this has no ParaId as it can be deduced from the candidate descriptor.
/// 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<u8, bitvec::order::Lsb0>,
/// The group assigned to distribute availability pieces of this candidate.
pub group_responsible: GroupIndex,
/// The hash of the candidate occupying the core.
pub candidate_hash: CandidateHash,
/// The descriptor of the candidate occupying the core.
pub candidate_descriptor: CandidateDescriptor<H>,
}
impl<H, N> OccupiedCore<H, N> {
/// Get the Para currently occupying this core.
pub fn para_id(&self) -> Id {
self.candidate_descriptor.para_id
}
}
/// Information about a core which is currently occupied.
#[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(PartialEq))]
pub struct ScheduledCore {
/// The ID of a para scheduled.
pub para_id: Id,
/// DEPRECATED: see: <https://github.com/paritytech/polkadot/issues/7575>
///
/// Will be removed in a future version.
pub collator: Option<CollatorId>,
}
/// The state of a particular availability core.
#[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(PartialEq))]
pub enum CoreState<H = Hash, N = BlockNumber> {
/// The core is currently occupied.
#[codec(index = 0)]
Occupied(OccupiedCore<H, 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,
}
impl<N> CoreState<N> {
/// Returns the scheduled `ParaId` for the core or `None` if nothing is scheduled.
///
/// This function is deprecated. `ClaimQueue` should be used to obtain the scheduled `ParaId`s
/// for each core.
#[deprecated(
note = "`para_id` will be removed. Use `ClaimQueue` to query the scheduled `para_id` instead."
)]
pub fn para_id(&self) -> Option<Id> {
match self {
Self::Occupied(ref core) => core.next_up_on_available.as_ref().map(|n| n.para_id),
Self::Scheduled(core) => Some(core.para_id),
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
Self::Free => None,
}
}
/// Is this core state `Self::Occupied`?
pub fn is_occupied(&self) -> bool {
matches!(self, Self::Occupied(_))
}
}
/// An assumption being made about the state of an occupied core.
#[derive(Clone, Copy, Encode, Decode, TypeInfo, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash))]
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, TypeInfo, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(PartialEq))]
pub enum CandidateEvent<H = Hash> {
/// This candidate receipt was backed in the most recent block.
/// This includes the core index the candidate is now occupying.
#[codec(index = 0)]
CandidateBacked(CandidateReceipt<H>, HeadData, CoreIndex, GroupIndex),
/// This candidate receipt was included and became a parablock at the most recent block.
/// This includes the core index the candidate was occupying as well as the group responsible
/// for backing the candidate.
#[codec(index = 1)]
CandidateIncluded(CandidateReceipt<H>, HeadData, CoreIndex, GroupIndex),
/// This candidate receipt was not made available in time and timed out.
/// This includes the core index the candidate was occupying.
#[codec(index = 2)]
CandidateTimedOut(CandidateReceipt<H>, HeadData, CoreIndex),
}
/// Scraped runtime backing votes and resolved disputes.
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(PartialEq))]
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
pub struct ScrapedOnChainVotes<H: Encode + Decode = Hash> {
/// The session in which the block was included.
pub session: SessionIndex,
/// Set of backing validators for each candidate, represented by its candidate
/// receipt.
pub backing_validators_per_candidate:
Vec<(CandidateReceipt<H>, Vec<(ValidatorIndex, ValidityAttestation)>)>,
/// On-chain-recorded set of disputes.
/// Note that the above `backing_validators` are
/// unrelated to the backers of the disputes candidates.
pub disputes: MultiDisputeStatementSet,
}
/// A vote of approval on a candidate.
#[derive(Clone, RuntimeDebug)]
pub struct ApprovalVote(pub CandidateHash);
impl ApprovalVote {
/// Yields the signing payload for this approval vote.
pub fn signing_payload(&self, session_index: SessionIndex) -> Vec<u8> {
const MAGIC: [u8; 4] = *b"APPR";
(MAGIC, &self.0, session_index).encode()
}
}
/// A vote of approval for multiple candidates.
#[derive(Clone, RuntimeDebug)]
pub struct ApprovalVoteMultipleCandidates<'a>(pub &'a [CandidateHash]);
impl<'a> ApprovalVoteMultipleCandidates<'a> {
/// Yields the signing payload for this approval vote.
pub fn signing_payload(&self, session_index: SessionIndex) -> Vec<u8> {
const MAGIC: [u8; 4] = *b"APPR";
// Make this backwards compatible with `ApprovalVote` so if we have just on candidate the
// signature will look the same.
// This gives us the nice benefit that old nodes can still check signatures when len is 1
// and the new node can check the signature coming from old nodes.
if self.0.len() == 1 {
(MAGIC, self.0.first().expect("QED: we just checked"), session_index).encode()
} else {
(MAGIC, &self.0, session_index).encode()
}
}
}
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
/// Approval voting configuration parameters
#[derive(
RuntimeDebug,
Copy,
Clone,
PartialEq,
Encode,
Decode,
TypeInfo,
serde::Serialize,
serde::Deserialize,
)]
pub struct ApprovalVotingParams {
/// The maximum number of candidates `approval-voting` can vote for with
/// a single signatures.
///
/// Setting it to 1, means we send the approval as soon as we have it available.
pub max_approval_coalesce_count: u32,
}
impl Default for ApprovalVotingParams {
fn default() -> Self {
Self { max_approval_coalesce_count: 1 }
}
}
/// 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
}
}
/// Abridged version of `HostConfiguration` (from the `Configuration` parachains host runtime
/// module) meant to be used by a parachain or PDK such as cumulus.
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(PartialEq))]
pub struct AbridgedHostConfiguration {
/// The maximum validation code size, in bytes.
pub max_code_size: u32,
/// The maximum head-data size, in bytes.
pub max_head_data_size: u32,
/// Total number of individual messages allowed in the parachain -> relay-chain message queue.
pub max_upward_queue_count: u32,
/// Total size of messages allowed in the parachain -> relay-chain message queue before which
/// no further messages may be added to it. If it exceeds this then the queue may contain only
/// a single message.
pub max_upward_queue_size: u32,
/// The maximum size of an upward message that can be sent by a candidate.
///
/// This parameter affects the size upper bound of the `CandidateCommitments`.
pub max_upward_message_size: u32,
/// The maximum number of messages that a candidate can contain.
///
/// This parameter affects the size upper bound of the `CandidateCommitments`.
pub max_upward_message_num_per_candidate: u32,
/// The maximum number of outbound HRMP messages can be sent by a candidate.
///
/// This parameter affects the upper bound of size of `CandidateCommitments`.
pub hrmp_max_message_num_per_candidate: u32,
/// The minimum period, in blocks, between which parachains can update their validation code.
pub validation_upgrade_cooldown: BlockNumber,
/// The delay, in blocks, before a validation upgrade is applied.
pub validation_upgrade_delay: BlockNumber,
/// Asynchronous backing parameters.
pub async_backing_params: AsyncBackingParams,
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
}
/// Abridged version of `HrmpChannel` (from the `Hrmp` parachains host runtime module) meant to be
/// used by a parachain or PDK such as cumulus.
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(PartialEq))]
pub struct AbridgedHrmpChannel {
/// The maximum number of messages that can be pending in the channel at once.
pub max_capacity: u32,
/// The maximum total size of the messages that can be pending in the channel at once.
pub max_total_size: u32,
/// The maximum message size that could be put into the channel.
pub max_message_size: u32,
/// The current number of messages pending in the channel.
/// Invariant: should be less or equal to `max_capacity`.s`.
pub msg_count: u32,
/// The total size in bytes of all message payloads in the channel.
/// Invariant: should be less or equal to `max_total_size`.
pub total_size: u32,
/// A head of the Message Queue Chain for this channel. Each link in this chain has a form:
/// `(prev_head, B, H(M))`, where
/// - `prev_head`: is the previous value of `mqc_head` or zero if none.
/// - `B`: is the [relay-chain] block number in which a message was appended
/// - `H(M)`: is the hash of the message being appended.
/// This value is initialized to a special value that consists of all zeroes which indicates
/// that no messages were previously added.
pub mqc_head: Option<Hash>,
}
/// A possible upgrade restriction that prevents a parachain from performing an upgrade.
#[derive(Copy, Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
pub enum UpgradeRestriction {
/// There is an upgrade restriction and there are no details about its specifics nor how long
/// it could last.
#[codec(index = 0)]
Present,
}
/// A struct that the relay-chain communicates to a parachain indicating what course of action the
/// parachain should take in the coordinated parachain validation code upgrade process.
///
/// This data type appears in the last step of the upgrade process. After the parachain observes it
/// and reacts to it the upgrade process concludes.
#[derive(Copy, Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
pub enum UpgradeGoAhead {
/// Abort the upgrade process. There is something wrong with the validation code previously
/// submitted by the parachain. This variant can also be used to prevent upgrades by the
/// governance should an emergency emerge.
///
/// The expected reaction on this variant is that the parachain will admit this message and
/// remove all the data about the pending upgrade. Depending on the nature of the problem (to
/// be examined offchain for now), it can try to send another validation code or just retry
/// later.
#[codec(index = 0)]
Abort,
/// Apply the pending code change. The parablock that is built on a relay-parent that is
/// descendant of the relay-parent where the parachain observed this signal must use the
/// upgraded validation code.
#[codec(index = 1)]
GoAhead,
}
/// Consensus engine id for polkadot v1 consensus engine.
pub const POLKADOT_ENGINE_ID: runtime_primitives::ConsensusEngineId = *b"POL1";
/// A consensus log item for polkadot validation. To be used with [`POLKADOT_ENGINE_ID`].
#[derive(Decode, Encode, Clone, PartialEq, Eq)]
pub enum ConsensusLog {
/// A parachain upgraded its code.
#[codec(index = 1)]
ParaUpgradeCode(Id, ValidationCodeHash),
/// A parachain scheduled a code upgrade.
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
#[codec(index = 2)]
ParaScheduleUpgradeCode(Id, ValidationCodeHash, BlockNumber),
/// Governance requests to auto-approve every candidate included up to the given block
/// number in the current chain, inclusive.
#[codec(index = 3)]
ForceApprove(BlockNumber),
/// A signal to revert the block number in the same chain as the
/// header this digest is part of and all of its descendants.
///
/// It is a no-op for a block to contain a revert digest targeting
/// its own number or a higher number.
///
/// In practice, these are issued when on-chain logic has detected an
/// invalid parachain block within its own chain, due to a dispute.
#[codec(index = 4)]
Revert(BlockNumber),
}
impl ConsensusLog {
/// Attempt to convert a reference to a generic digest item into a consensus log.
pub fn from_digest_item(
digest_item: &runtime_primitives::DigestItem,
) -> Result<Option<Self>, parity_scale_codec::Error> {
match digest_item {
runtime_primitives::DigestItem::Consensus(id, encoded) if id == &POLKADOT_ENGINE_ID =>
Ok(Some(Self::decode(&mut &encoded[..])?)),
_ => Ok(None),
}
}
}
impl From<ConsensusLog> for runtime_primitives::DigestItem {
fn from(c: ConsensusLog) -> runtime_primitives::DigestItem {
Self::Consensus(POLKADOT_ENGINE_ID, c.encode())
}
}
/// A statement about a candidate, to be used within the dispute resolution process.
///
/// Statements are either in favor of the candidate's validity or against it.
#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
pub enum DisputeStatement {
/// A valid statement, of the given kind.
#[codec(index = 0)]
Valid(ValidDisputeStatementKind),
/// An invalid statement, of the given kind.
#[codec(index = 1)]
Invalid(InvalidDisputeStatementKind),
}
impl DisputeStatement {
/// Get the payload data for this type of dispute statement.
///
/// Returns Error if the candidate_hash is not included in the list of signed
/// candidate from ApprovalCheckingMultipleCandidate.
pub fn payload_data(
&self,
candidate_hash: CandidateHash,
session: SessionIndex,
) -> Result<Vec<u8>, ()> {
match self {
DisputeStatement::Valid(ValidDisputeStatementKind::Explicit) =>
Ok(ExplicitDisputeStatement { valid: true, candidate_hash, session }
.signing_payload()),
DisputeStatement::Valid(ValidDisputeStatementKind::BackingSeconded(
inclusion_parent,
)) => Ok(CompactStatement::Seconded(candidate_hash).signing_payload(&SigningContext {
parent_hash: *inclusion_parent,
})),
DisputeStatement::Valid(ValidDisputeStatementKind::BackingValid(inclusion_parent)) =>
Ok(CompactStatement::Valid(candidate_hash).signing_payload(&SigningContext {
parent_hash: *inclusion_parent,
})),
DisputeStatement::Valid(ValidDisputeStatementKind::ApprovalChecking) =>
Ok(ApprovalVote(candidate_hash).signing_payload(session)),
DisputeStatement::Valid(
ValidDisputeStatementKind::ApprovalCheckingMultipleCandidates(candidate_hashes),
) =>
if candidate_hashes.contains(&candidate_hash) {
Ok(ApprovalVoteMultipleCandidates(candidate_hashes).signing_payload(session))
} else {
Err(())
},
DisputeStatement::Invalid(InvalidDisputeStatementKind::Explicit) =>
Ok(ExplicitDisputeStatement { valid: false, candidate_hash, session }
.signing_payload()),
}
}
/// Check the signature on a dispute statement.
pub fn check_signature(
&self,
validator_public: &ValidatorId,
candidate_hash: CandidateHash,
session: SessionIndex,
validator_signature: &ValidatorSignature,
) -> Result<(), ()> {
let payload = self.payload_data(candidate_hash, session)?;
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
if validator_signature.verify(&payload[..], &validator_public) {
Ok(())
} else {
Err(())
}
}
/// Whether the statement indicates validity.
pub fn indicates_validity(&self) -> bool {
match *self {
DisputeStatement::Valid(_) => true,
DisputeStatement::Invalid(_) => false,
}
}
/// Whether the statement indicates invalidity.
pub fn indicates_invalidity(&self) -> bool {
match *self {
DisputeStatement::Valid(_) => false,
DisputeStatement::Invalid(_) => true,
}
}
/// Statement is backing statement.
pub fn is_backing(&self) -> bool {
match self {
Self::Valid(s) => s.is_backing(),
Self::Invalid(_) => false,
}
}
}
/// Different kinds of statements of validity on a candidate.
#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
pub enum ValidDisputeStatementKind {
/// An explicit statement issued as part of a dispute.
#[codec(index = 0)]
Explicit,
/// A seconded statement on a candidate from the backing phase.
#[codec(index = 1)]
BackingSeconded(Hash),
/// A valid statement on a candidate from the backing phase.
#[codec(index = 2)]
BackingValid(Hash),
/// An approval vote from the approval checking phase.
#[codec(index = 3)]
ApprovalChecking,
/// An approval vote from the new version.
/// We can't create this version until all nodes
/// have been updated to support it and max_approval_coalesce_count
/// is set to more than 1.
#[codec(index = 4)]
ApprovalCheckingMultipleCandidates(Vec<CandidateHash>),
impl ValidDisputeStatementKind {
/// Whether the statement is from the backing phase.
pub fn is_backing(&self) -> bool {
match self {
ValidDisputeStatementKind::BackingSeconded(_) |
ValidDisputeStatementKind::BackingValid(_) => true,
ValidDisputeStatementKind::Explicit |
ValidDisputeStatementKind::ApprovalChecking |
ValidDisputeStatementKind::ApprovalCheckingMultipleCandidates(_) => false,
}
}
}
/// Different kinds of statements of invalidity on a candidate.
#[derive(Encode, Decode, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)]
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
pub enum InvalidDisputeStatementKind {
/// An explicit statement issued as part of a dispute.
#[codec(index = 0)]
Explicit,
}
/// An explicit statement on a candidate issued as part of a dispute.
#[derive(Clone, PartialEq, RuntimeDebug)]
pub struct ExplicitDisputeStatement {
/// Whether the candidate is valid
pub valid: bool,
/// The candidate hash.
pub candidate_hash: CandidateHash,
/// The session index of the candidate.
pub session: SessionIndex,
}
impl ExplicitDisputeStatement {
/// Produce the payload used for signing this type of statement.
pub fn signing_payload(&self) -> Vec<u8> {
const MAGIC: [u8; 4] = *b"DISP";
(MAGIC, self.valid, self.candidate_hash, self.session).encode()
}
}
/// A set of statements about a specific candidate.
#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
pub struct DisputeStatementSet {
/// The candidate referenced by this set.
pub candidate_hash: CandidateHash,
/// The session index of the candidate.
pub session: SessionIndex,
/// Statements about the candidate.
pub statements: Vec<(DisputeStatement, ValidatorIndex, ValidatorSignature)>,
}
impl From<CheckedDisputeStatementSet> for DisputeStatementSet {
fn from(other: CheckedDisputeStatementSet) -> Self {
other.0
}
}
impl AsRef<DisputeStatementSet> for DisputeStatementSet {
fn as_ref(&self) -> &DisputeStatementSet {
&self
}
}
/// A set of dispute statements.
pub type MultiDisputeStatementSet = Vec<DisputeStatementSet>;
/// A _checked_ set of dispute statements.
#[derive(Clone, PartialEq, RuntimeDebug, Encode)]
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
pub struct CheckedDisputeStatementSet(DisputeStatementSet);
impl AsRef<DisputeStatementSet> for CheckedDisputeStatementSet {
fn as_ref(&self) -> &DisputeStatementSet {
&self.0
}
}
impl core::cmp::PartialEq<DisputeStatementSet> for CheckedDisputeStatementSet {
fn eq(&self, other: &DisputeStatementSet) -> bool {
self.0.eq(other)
}
}
impl CheckedDisputeStatementSet {
/// Convert from an unchecked, the verification of correctness of the `unchecked` statement set
/// _must_ be done before calling this function!
pub fn unchecked_from_unchecked(unchecked: DisputeStatementSet) -> Self {
Self(unchecked)
}
}
/// A set of _checked_ dispute statements.
pub type CheckedMultiDisputeStatementSet = Vec<CheckedDisputeStatementSet>;
/// The entire state of a dispute.
#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, TypeInfo)]
pub struct DisputeState<N = BlockNumber> {
/// A bitfield indicating all validators for the candidate.
pub validators_for: BitVec<u8, bitvec::order::Lsb0>, // one bit per validator.
/// A bitfield indicating all validators against the candidate.
pub validators_against: BitVec<u8, bitvec::order::Lsb0>, // one bit per validator.
/// The block number at which the dispute started on-chain.
pub start: N,
/// The block number at which the dispute concluded on-chain.
pub concluded_at: Option<N>,
}
/// Parachains inherent-data passed into the runtime by a block author
#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
pub struct InherentData<HDR: HeaderT = Header> {
/// Signed bitfields by validators about availability.
pub bitfields: UncheckedSignedAvailabilityBitfields,
/// Backed candidates for inclusion in the block.
pub backed_candidates: Vec<BackedCandidate<HDR::Hash>>,
/// Sets of dispute votes for inclusion,
pub disputes: MultiDisputeStatementSet,
/// The parent block header. Used for checking state proofs.
pub parent_header: HDR,
}
/// An either implicit or explicit attestation to the validity of a parachain
/// candidate.
#[derive(Clone, Eq, PartialEq, Decode, Encode, RuntimeDebug, TypeInfo)]
pub enum ValidityAttestation {
/// Implicit validity attestation by issuing.
/// This corresponds to issuance of a `Candidate` statement.
#[codec(index = 1)]
Implicit(ValidatorSignature),
/// An explicit attestation. This corresponds to issuance of a
/// `Valid` statement.
#[codec(index = 2)]
Explicit(ValidatorSignature),
}
impl ValidityAttestation {
/// Produce the underlying signed payload of the attestation, given the hash of the candidate,
/// which should be known in context.
pub fn to_compact_statement(&self, candidate_hash: CandidateHash) -> CompactStatement {
// Explicit and implicit map directly from
// `ValidityVote::Valid` and `ValidityVote::Issued`, and hence there is a
// `1:1` relationship which enables the conversion.
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
match *self {
ValidityAttestation::Implicit(_) => CompactStatement::Seconded(candidate_hash),
ValidityAttestation::Explicit(_) => CompactStatement::Valid(candidate_hash),
}
}
/// Get a reference to the signature.
pub fn signature(&self) -> &ValidatorSignature {
match *self {
ValidityAttestation::Implicit(ref sig) => sig,
ValidityAttestation::Explicit(ref sig) => sig,
}
}
/// Produce the underlying signed payload of the attestation, given the hash of the candidate,
/// which should be known in context.
pub fn signed_payload<H: Encode>(
&self,
candidate_hash: CandidateHash,
signing_context: &SigningContext<H>,
) -> Vec<u8> {
match *self {
ValidityAttestation::Implicit(_) =>
(CompactStatement::Seconded(candidate_hash), signing_context).encode(),
ValidityAttestation::Explicit(_) =>
(CompactStatement::Valid(candidate_hash), signing_context).encode(),
}
}
}
/// A type returned by runtime with current session index and a parent hash.
#[derive(Clone, Eq, PartialEq, Default, Decode, Encode, RuntimeDebug)]
pub struct SigningContext<H = Hash> {
/// Current session index.
pub session_index: sp_staking::SessionIndex,
/// Hash of the parent.
pub parent_hash: H,
}
const BACKING_STATEMENT_MAGIC: [u8; 4] = *b"BKNG";
/// Statements that can be made about parachain candidates. These are the
/// actual values that are signed.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Hash))]
pub enum CompactStatement {
/// Proposal of a parachain candidate.
Seconded(CandidateHash),
/// State that a parachain candidate is valid.
Valid(CandidateHash),
}
impl CompactStatement {
/// Yields the payload used for validator signatures on this kind
/// of statement.
pub fn signing_payload(&self, context: &SigningContext) -> Vec<u8> {
(self, context).encode()
}
/// Get the underlying candidate hash this references.
pub fn candidate_hash(&self) -> &CandidateHash {
match *self {
CompactStatement::Seconded(ref h) | CompactStatement::Valid(ref h) => h,
}
}
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
}
// Inner helper for codec on `CompactStatement`.
#[derive(Encode, Decode, TypeInfo)]
enum CompactStatementInner {
#[codec(index = 1)]
Seconded(CandidateHash),
#[codec(index = 2)]
Valid(CandidateHash),
}
impl From<CompactStatement> for CompactStatementInner {
fn from(s: CompactStatement) -> Self {
match s {
CompactStatement::Seconded(h) => CompactStatementInner::Seconded(h),
CompactStatement::Valid(h) => CompactStatementInner::Valid(h),
}
}
}
impl parity_scale_codec::Encode for CompactStatement {
fn size_hint(&self) -> usize {
// magic + discriminant + payload
4 + 1 + 32
}
fn encode_to<T: parity_scale_codec::Output + ?Sized>(&self, dest: &mut T) {
dest.write(&BACKING_STATEMENT_MAGIC);
CompactStatementInner::from(self.clone()).encode_to(dest)
}
}
impl parity_scale_codec::Decode for CompactStatement {
fn decode<I: parity_scale_codec::Input>(
input: &mut I,
) -> Result<Self, parity_scale_codec::Error> {
let maybe_magic = <[u8; 4]>::decode(input)?;
if maybe_magic != BACKING_STATEMENT_MAGIC {
return Err(parity_scale_codec::Error::from("invalid magic string"))
}
Ok(match CompactStatementInner::decode(input)? {
CompactStatementInner::Seconded(h) => CompactStatement::Seconded(h),
CompactStatementInner::Valid(h) => CompactStatement::Valid(h),
})
}
}
/// `IndexedVec` struct indexed by type specific indices.
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(PartialEq))]
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
pub struct IndexedVec<K, V>(Vec<V>, PhantomData<fn(K) -> K>);
impl<K, V> Default for IndexedVec<K, V> {
fn default() -> Self {
Self(vec![], PhantomData)
}
}
impl<K, V> From<Vec<V>> for IndexedVec<K, V> {
fn from(validators: Vec<V>) -> Self {
Self(validators, PhantomData)
}
}
impl<K, V> FromIterator<V> for IndexedVec<K, V> {
fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
Self(Vec::from_iter(iter), PhantomData)
}
}
impl<K, V> IndexedVec<K, V>
where
V: Clone,
{
/// Returns a reference to an element indexed using `K`.
pub fn get(&self, index: K) -> Option<&V>
where
K: TypeIndex,
{
self.0.get(index.type_index())
}
/// Returns number of elements in vector.
pub fn len(&self) -> usize {
self.0.len()
}
/// Returns contained vector.
pub fn to_vec(&self) -> Vec<V> {
self.0.clone()
}
/// Returns an iterator over the underlying vector.
pub fn iter(&self) -> Iter<'_, V> {
self.0.iter()
}
/// Returns a mutable iterator over the underlying vector.
pub fn iter_mut(&mut self) -> IterMut<'_, V> {
self.0.iter_mut()
}
/// Creates a consuming iterator.
pub fn into_iter(self) -> IntoIter<V> {
self.0.into_iter()
}
/// Returns true if the underlying container is empty.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
/// The maximum number of validators `f` which may safely be faulty.
///
/// The total number of validators is `n = 3f + e` where `e in { 1, 2, 3 }`.
pub const fn byzantine_threshold(n: usize) -> usize {
n.saturating_sub(1) / 3
}
/// The supermajority threshold of validators which represents a subset
/// guaranteed to have at least f+1 honest validators.
pub const fn supermajority_threshold(n: usize) -> usize {
n - byzantine_threshold(n)
}
/// Adjust the configured needed backing votes with the size of the backing group.
pub fn effective_minimum_backing_votes(
group_len: usize,
configured_minimum_backing_votes: u32,
) -> usize {
sp_std::cmp::min(group_len, configured_minimum_backing_votes as usize)
}
/// Information about validator sets of a session.
///
/// NOTE: `SessionInfo` is frozen. Do not include new fields, consider creating a separate runtime
/// API. Reasoning and further outlook [here](https://github.com/paritytech/polkadot/issues/6586).
#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(PartialEq))]
/****** New in v2 ****** */
/// All the validators actively participating in parachain consensus.
/// Indices are into the broader validator set.
pub active_validator_indices: Vec<ValidatorIndex>,
/// A secure random seed for the session, gathered from BABE.
pub random_seed: [u8; 32],
/// The amount of sessions to keep for disputes.
pub dispute_period: SessionIndex,
/****** Old fields ***** */
/// Validators in canonical ordering.
///
/// NOTE: There might be more authorities in the current session, than `validators`
/// participating in parachain consensus. See
/// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148).
///
/// `SessionInfo::validators` will be limited to to `max_validators` when set.
pub validators: IndexedVec<ValidatorIndex, ValidatorId>,
/// Validators' authority discovery keys for the session in canonical ordering.
///
/// NOTE: The first `validators.len()` entries will match the corresponding validators in
/// `validators`, afterwards any remaining authorities can be found. This is any authorities
/// not participating in parachain consensus - see
/// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148)
pub discovery_keys: Vec<AuthorityDiscoveryId>,
/// The assignment keys for validators.
///
/// NOTE: There might be more authorities in the current session, than validators participating
/// in parachain consensus. See
/// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148).
///
/// Therefore:
/// ```ignore
/// assignment_keys.len() == validators.len() && validators.len() <= discovery_keys.len()
/// ```
pub assignment_keys: Vec<AssignmentId>,
/// Validators in shuffled ordering - these are the validator groups as produced
/// by the `Scheduler` module for the session and are typically referred to by
/// `GroupIndex`.
pub validator_groups: IndexedVec<GroupIndex, Vec<ValidatorIndex>>,
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
/// The number of availability cores used by the protocol during this session.
pub n_cores: u32,
/// The zeroth delay tranche width.
pub zeroth_delay_tranche_width: u32,
/// The number of samples we do of `relay_vrf_modulo`.
pub relay_vrf_modulo_samples: u32,
/// The number of delay tranches in total.
pub n_delay_tranches: u32,
/// How many slots (BABE / SASSAFRAS) must pass before an assignment is considered a
/// no-show.
pub no_show_slots: u32,
/// The number of validators needed to approve a block.
pub needed_approvals: u32,
}
/// A statement from the specified validator whether the given validation code passes PVF
/// pre-checking or not anchored to the given session index.
#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)]
pub struct PvfCheckStatement {
/// `true` if the subject passed pre-checking and `false` otherwise.
pub accept: bool,
/// The validation code hash that was checked.
pub subject: ValidationCodeHash,
/// The index of a session during which this statement is considered valid.
pub session_index: SessionIndex,
/// The index of the validator from which this statement originates.
pub validator_index: ValidatorIndex,
}
impl PvfCheckStatement {
/// Produce the payload used for signing this type of statement.
///
/// It is expected that it will be signed by the validator at `validator_index` in the
/// `session_index`.
pub fn signing_payload(&self) -> Vec<u8> {
const MAGIC: [u8; 4] = *b"VCPC"; // for "validation code pre-checking"
(MAGIC, self.accept, self.subject, self.session_index, self.validator_index).encode()
}
}
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
/// A well-known and typed storage key.
///
/// Allows for type-safe access to raw well-known storage keys.
pub struct WellKnownKey<T> {
/// The raw storage key.
pub key: Vec<u8>,
_p: sp_std::marker::PhantomData<T>,
}
impl<T> From<Vec<u8>> for WellKnownKey<T> {
fn from(key: Vec<u8>) -> Self {
Self { key, _p: Default::default() }
}
}
impl<T> AsRef<[u8]> for WellKnownKey<T> {
fn as_ref(&self) -> &[u8] {
self.key.as_ref()
}
}
impl<T: Decode> WellKnownKey<T> {
/// Gets the value or `None` if it does not exist or decoding failed.
pub fn get(&self) -> Option<T> {
sp_io::storage::get(&self.key)
.and_then(|raw| parity_scale_codec::DecodeAll::decode_all(&mut raw.as_ref()).ok())
}
}
impl<T: Encode> WellKnownKey<T> {
/// Sets the value.
pub fn set(&self, value: T) {
sp_io::storage::set(&self.key, &value.encode());
}
}
/// Type discriminator for PVF preparation.
Michal Kucharczyk
committed
#[derive(Encode, Decode, TypeInfo, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PvfPrepKind {
/// For prechecking requests.
Precheck,
/// For execution and heads-up requests.
Prepare,
/// Type discriminator for PVF execution.
Michal Kucharczyk
committed
#[derive(Encode, Decode, TypeInfo, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PvfExecKind {
/// For backing requests.
Backing,
/// For approval and dispute request.
Approval,
}
/// Bit indices in the `HostConfiguration.node_features` that correspond to different node features.
pub type NodeFeatures = BitVec<u8, bitvec::order::Lsb0>;
/// Module containing feature-specific bit indices into the `NodeFeatures` bitvec.
pub mod node_features {
/// A feature index used to identify a bit into the node_features array stored
/// in the HostConfiguration.
#[repr(u8)]
pub enum FeatureIndex {
/// Tells if tranch0 assignments could be sent in a single certificate.
/// Reserved for: `<https://github.com/paritytech/polkadot-sdk/issues/628>`
EnableAssignmentsV2 = 0,
/// This feature enables the extension of `BackedCandidate::validator_indices` by 8 bits.
/// The value stored there represents the assumed core index where the candidates
/// are backed. This is needed for the elastic scaling MVP.
ElasticScalingMVP = 1,
/// First unassigned feature bit.