mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
Parachain auctions (#239)
* Slots module * Integrate slots * More drafting * Minor updates * Update parachains to use trati * More build fixes * Full code now compiles * Add renew bid function * Implement calculate_winner * Warning remove * Update gitignore * Test framework * Tests * Further testing * More tests, new parameterisation. * Fix and new test * Thread-safe tests * Test off-boarding and a fix. * Test onboarding * Allow late onboarding. * Another test and fix * Avoid println in nostd * Compact representation of paraids * Introduce documentation. * Introduce events. * Additional test and fix * Additional test * Tidy up line lengths. * Remove printlns * Use later substrate utils. * Fix build/test * Make slots work with latest substrate * Update runtime/src/slot_range.rs Co-Authored-By: Robert Habermeier <rphmeier@gmail.com> * Update runtime/src/slots.rs Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com> * Update runtime/src/slots.rs Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com> * Polish logic * Rewind to earlier substrate master * Remove dead code.
This commit is contained in:
@@ -50,6 +50,7 @@ impl EcdsaSignature {
|
||||
r[64] = self.2 as u8;
|
||||
r
|
||||
}
|
||||
#[cfg(test)]
|
||||
pub fn from_blob(blob: &[u8; 65]) -> Self {
|
||||
let mut r = Self([0u8; 32], [0u8; 32], 0);
|
||||
r.0[..].copy_from_slice(&blob[0..32]);
|
||||
@@ -148,7 +149,7 @@ mod tests {
|
||||
use tiny_keccak::keccak256;
|
||||
use super::*;
|
||||
|
||||
use sr_io::{self as runtime_io, with_externalities};
|
||||
use sr_io::with_externalities;
|
||||
use substrate_primitives::{H256, Blake2Hasher};
|
||||
use codec::{Decode, Encode};
|
||||
// The testing primitives are very useful for avoiding having to work with signatures
|
||||
|
||||
@@ -76,6 +76,8 @@ extern crate substrate_trie;
|
||||
mod curated_grandpa;
|
||||
mod parachains;
|
||||
mod claims;
|
||||
mod slot_range;
|
||||
mod slots;
|
||||
|
||||
use rstd::prelude::*;
|
||||
use substrate_primitives::u32_trait::{_2, _4};
|
||||
@@ -252,6 +254,19 @@ impl grandpa::Trait for Runtime {
|
||||
|
||||
impl parachains::Trait for Runtime {}
|
||||
|
||||
parameter_types!{
|
||||
pub const LeasePeriod: BlockNumber = 100000;
|
||||
pub const EndingPeriod: BlockNumber = 1000;
|
||||
}
|
||||
|
||||
impl slots::Trait for Runtime {
|
||||
type Event = Event;
|
||||
type Currency = balances::Module<Self>;
|
||||
type Parachains = parachains::Module<Self>;
|
||||
type LeasePeriod = LeasePeriod;
|
||||
type EndingPeriod = EndingPeriod;
|
||||
}
|
||||
|
||||
impl curated_grandpa::Trait for Runtime { }
|
||||
|
||||
impl sudo::Trait for Runtime {
|
||||
@@ -283,6 +298,7 @@ construct_runtime!(
|
||||
CouncilSeats: council_seats::{Config<T>},
|
||||
Treasury: treasury,
|
||||
Parachains: parachains::{Module, Call, Storage, Config<T>, Inherent},
|
||||
Slots: slots::{Module, Call, Storage, Event<T>},
|
||||
Sudo: sudo,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
//! Main parachains logic. For now this is just the determination of which validators do what.
|
||||
|
||||
use rstd::prelude::*;
|
||||
use codec::Decode;
|
||||
use codec::{Decode, HasCompact};
|
||||
|
||||
use bitvec::BigEndian;
|
||||
use sr_primitives::traits::{Hash as HashT, BlakeTwo256};
|
||||
use primitives::Hash;
|
||||
use primitives::parachain::{Id as ParaId, Chain, DutyRoster, AttestedCandidate, Statement};
|
||||
use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Member};
|
||||
use primitives::{Hash, parachain::{Id as ParaId, Chain, DutyRoster, AttestedCandidate, Statement, AccountIdConversion}};
|
||||
use {system, session};
|
||||
|
||||
use srml_support::{StorageValue, StorageMap, storage::hashed::generator};
|
||||
use srml_support::dispatch::Result;
|
||||
use srml_support::{StorageValue, StorageMap, Parameter, dispatch::Result};
|
||||
#[cfg(feature = "std")]
|
||||
use srml_support::storage::hashed::generator;
|
||||
|
||||
use inherents::{ProvideInherent, InherentData, RuntimeString, MakeFatalError, InherentIdentifier};
|
||||
|
||||
@@ -38,7 +38,64 @@ use rstd::marker::PhantomData;
|
||||
|
||||
use system::ensure_none;
|
||||
|
||||
pub trait Trait: session::Trait {}
|
||||
/// Parachain registration API.
|
||||
pub trait ParachainRegistrar<AccountId> {
|
||||
/// An identifier for a parachain.
|
||||
type ParaId: Member + Parameter + Default + AccountIdConversion<AccountId> + Copy + HasCompact;
|
||||
|
||||
/// Create a new unique parachain identity for later registration.
|
||||
fn new_id() -> Self::ParaId;
|
||||
|
||||
/// Register a parachain with given `code` and `initial_head_data`. `id` must not yet be registered or it will
|
||||
/// result in a error.
|
||||
fn register_parachain(id: Self::ParaId, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result;
|
||||
|
||||
/// Deregister a parachain with given `id`. If `id` is not currently registered, an error is returned.
|
||||
fn deregister_parachain(id: Self::ParaId) -> Result;
|
||||
}
|
||||
|
||||
impl<T: Trait> ParachainRegistrar<T::AccountId> for Module<T> {
|
||||
type ParaId = ParaId;
|
||||
fn new_id() -> ParaId {
|
||||
<NextFreeId<T>>::mutate(|n| { let r = *n; *n = ParaId::from(u32::from(*n) + 1); r })
|
||||
}
|
||||
fn register_parachain(id: ParaId, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result {
|
||||
let mut parachains = Self::active_parachains();
|
||||
match parachains.binary_search(&id) {
|
||||
Ok(_) => fail!("Parachain already exists"),
|
||||
Err(idx) => parachains.insert(idx, id),
|
||||
}
|
||||
|
||||
<Code<T>>::insert(id, code);
|
||||
<Parachains<T>>::put(parachains);
|
||||
<Heads<T>>::insert(id, initial_head_data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn deregister_parachain(id: ParaId) -> Result {
|
||||
let mut parachains = Self::active_parachains();
|
||||
match parachains.binary_search(&id) {
|
||||
Ok(idx) => { parachains.remove(idx); }
|
||||
Err(_) => return Ok(()),
|
||||
}
|
||||
|
||||
<Code<T>>::remove(id);
|
||||
<Heads<T>>::remove(id);
|
||||
|
||||
// clear all routing entries to and from other parachains.
|
||||
for other in parachains.iter().cloned() {
|
||||
<Routing<T>>::remove((id, other));
|
||||
<Routing<T>>::remove((other, id));
|
||||
}
|
||||
|
||||
<Parachains<T>>::put(parachains);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Trait: session::Trait {
|
||||
}
|
||||
|
||||
// result of <NodeCodec<Blake2Hasher> as trie_db::NodeCodec<Blake2Hasher>>::hashed_null_node()
|
||||
const EMPTY_TRIE_ROOT: [u8; 32] = [
|
||||
@@ -59,6 +116,9 @@ decl_storage! {
|
||||
|
||||
// Did the parachain heads get updated in this block?
|
||||
DidUpdate: bool;
|
||||
|
||||
/// The next unused ParaId value.
|
||||
NextFreeId: ParaId;
|
||||
}
|
||||
add_extra_genesis {
|
||||
config(parachains): Vec<(ParaId, Vec<u8>, Vec<u8>)>;
|
||||
@@ -137,39 +197,12 @@ decl_module! {
|
||||
/// Register a parachain with given code.
|
||||
/// Fails if given ID is already used.
|
||||
pub fn register_parachain(id: ParaId, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result {
|
||||
let mut parachains = Self::active_parachains();
|
||||
match parachains.binary_search(&id) {
|
||||
Ok(_) => fail!("Parachain already exists"),
|
||||
Err(idx) => parachains.insert(idx, id),
|
||||
}
|
||||
|
||||
<Code<T>>::insert(id, code);
|
||||
<Parachains<T>>::put(parachains);
|
||||
<Heads<T>>::insert(id, initial_head_data);
|
||||
|
||||
Ok(())
|
||||
<Self as ParachainRegistrar<T::AccountId>>::register_parachain(id, code, initial_head_data)
|
||||
}
|
||||
|
||||
/// Deregister a parachain with given id
|
||||
pub fn deregister_parachain(id: ParaId) -> Result {
|
||||
let mut parachains = Self::active_parachains();
|
||||
match parachains.binary_search(&id) {
|
||||
Ok(idx) => { parachains.remove(idx); }
|
||||
Err(_) => return Ok(()),
|
||||
}
|
||||
|
||||
<Code<T>>::remove(id);
|
||||
<Heads<T>>::remove(id);
|
||||
|
||||
// clear all routing entries to and from other parachains.
|
||||
for other in parachains.iter().cloned() {
|
||||
<Routing<T>>::remove((id, other));
|
||||
<Routing<T>>::remove((other, id));
|
||||
}
|
||||
|
||||
<Parachains<T>>::put(parachains);
|
||||
|
||||
Ok(())
|
||||
<Self as ParachainRegistrar<T::AccountId>>::deregister_parachain(id)
|
||||
}
|
||||
|
||||
fn on_finalize(_n: T::BlockNumber) {
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
// Copyright 2019 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/>.
|
||||
|
||||
//! The SlotRange struct which succinctly handles the ten values that
|
||||
//! represent all sub ranges between 0 and 3 inclusive.
|
||||
|
||||
use rstd::{result, ops::Add, convert::{TryFrom, TryInto}};
|
||||
use sr_primitives::traits::CheckedSub;
|
||||
|
||||
/// Total number of possible sub ranges of slots.
|
||||
pub const SLOT_RANGE_COUNT: usize = 10;
|
||||
|
||||
/// A compactly represented sub-range from the series (0, 1, 2, 3).
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode)]
|
||||
#[repr(u8)]
|
||||
pub enum SlotRange {
|
||||
/// Sub range from index 0 to index 0 inclusive.
|
||||
ZeroZero = 0,
|
||||
/// Sub range from index 0 to index 1 inclusive.
|
||||
ZeroOne = 1,
|
||||
/// Sub range from index 0 to index 2 inclusive.
|
||||
ZeroTwo = 2,
|
||||
/// Sub range from index 0 to index 3 inclusive.
|
||||
ZeroThree = 3,
|
||||
/// Sub range from index 1 to index 1 inclusive.
|
||||
OneOne = 4,
|
||||
/// Sub range from index 1 to index 2 inclusive.
|
||||
OneTwo = 5,
|
||||
/// Sub range from index 1 to index 3 inclusive.
|
||||
OneThree = 6,
|
||||
/// Sub range from index 2 to index 2 inclusive.
|
||||
TwoTwo = 7,
|
||||
/// Sub range from index 2 to index 3 inclusive.
|
||||
TwoThree = 8,
|
||||
/// Sub range from index 3 to index 3 inclusive.
|
||||
ThreeThree = 9, // == SLOT_RANGE_COUNT - 1
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::fmt::Debug for SlotRange {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let p = self.as_pair();
|
||||
write!(fmt, "[{}..{}]", p.0, p.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl SlotRange {
|
||||
pub fn new_bounded<
|
||||
Index: Add<Output=Index> + CheckedSub + Copy + Ord + From<u32> + TryInto<u32>
|
||||
>(
|
||||
initial: Index,
|
||||
first: Index,
|
||||
last: Index
|
||||
) -> result::Result<Self, &'static str> {
|
||||
if first > last || first < initial || last > initial + 3.into() {
|
||||
return Err("Invalid range for this auction")
|
||||
}
|
||||
let count: u32 = last.checked_sub(&first)
|
||||
.ok_or("range ends before it begins")?
|
||||
.try_into()
|
||||
.map_err(|_| "range too big")?;
|
||||
let first: u32 = first.checked_sub(&initial)
|
||||
.ok_or("range begins too early")?
|
||||
.try_into()
|
||||
.map_err(|_| "start too far")?;
|
||||
match first {
|
||||
0 => match count {
|
||||
0 => Some(SlotRange::ZeroZero),
|
||||
1 => Some(SlotRange::ZeroOne),
|
||||
2 => Some(SlotRange::ZeroTwo),
|
||||
3 => Some(SlotRange::ZeroThree),
|
||||
_ => None,
|
||||
},
|
||||
1 => match count {
|
||||
0 => Some(SlotRange::OneOne),
|
||||
1 => Some(SlotRange::OneTwo),
|
||||
2 => Some(SlotRange::OneThree),
|
||||
_ => None
|
||||
},
|
||||
2 => match count { 0 => Some(SlotRange::TwoTwo), 1 => Some(SlotRange::TwoThree), _ => None },
|
||||
3 => match count { 0 => Some(SlotRange::ThreeThree), _ => None },
|
||||
_ => return Err("range begins too late"),
|
||||
}.ok_or("range ends too late")
|
||||
}
|
||||
|
||||
pub fn as_pair(&self) -> (u8, u8) {
|
||||
match self {
|
||||
SlotRange::ZeroZero => (0, 0),
|
||||
SlotRange::ZeroOne => (0, 1),
|
||||
SlotRange::ZeroTwo => (0, 2),
|
||||
SlotRange::ZeroThree => (0, 3),
|
||||
SlotRange::OneOne => (1, 1),
|
||||
SlotRange::OneTwo => (1, 2),
|
||||
SlotRange::OneThree => (1, 3),
|
||||
SlotRange::TwoTwo => (2, 2),
|
||||
SlotRange::TwoThree => (2, 3),
|
||||
SlotRange::ThreeThree => (3, 3),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intersects(&self, other: SlotRange) -> bool {
|
||||
let a = self.as_pair();
|
||||
let b = other.as_pair();
|
||||
b.0 <= a.1 && a.0 <= b.1
|
||||
// == !(b.0 > a.1 || a.0 > b.1)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
SlotRange::ZeroZero => 1,
|
||||
SlotRange::ZeroOne => 2,
|
||||
SlotRange::ZeroTwo => 3,
|
||||
SlotRange::ZeroThree => 4,
|
||||
SlotRange::OneOne => 1,
|
||||
SlotRange::OneTwo => 2,
|
||||
SlotRange::OneThree => 3,
|
||||
SlotRange::TwoTwo => 1,
|
||||
SlotRange::TwoThree => 2,
|
||||
SlotRange::ThreeThree => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<usize> for SlotRange {
|
||||
type Error = ();
|
||||
fn try_from(x: usize) -> Result<SlotRange, ()> {
|
||||
Ok(match x {
|
||||
0 => SlotRange::ZeroZero,
|
||||
1 => SlotRange::ZeroOne,
|
||||
2 => SlotRange::ZeroTwo,
|
||||
3 => SlotRange::ZeroThree,
|
||||
4 => SlotRange::OneOne,
|
||||
5 => SlotRange::OneTwo,
|
||||
6 => SlotRange::OneThree,
|
||||
7 => SlotRange::TwoTwo,
|
||||
8 => SlotRange::TwoThree,
|
||||
9 => SlotRange::ThreeThree,
|
||||
_ => return Err(()),
|
||||
})
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user