Skip to content

Commit

Permalink
Fifth iteration of the Court pallet (zeitgeistpm#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
c410-f3r committed Sep 14, 2021
1 parent 3aed86c commit 980555d
Show file tree
Hide file tree
Showing 33 changed files with 279 additions and 247 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
with:
override: true
profile: minimal
toolchain: nightly-2021-03-10
toolchain: nightly-2021-08-09

- name: Cache dependencies
uses: Swatinem/rust-cache@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/migration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ jobs:
with:
override: true
profile: minimal
toolchain: nightly-2021-03-10
toolchain: nightly-2021-08-09

- run: ./scripts/runtime-upgrade/test_runtime_upgrade.sh ${{ github.event.inputs.block }}
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
components: clippy, rustfmt
override: true
profile: minimal
toolchain: nightly-2021-03-10
toolchain: nightly-2021-08-09

- name: Cache Dependencies
uses: Swatinem/rust-cache@v1
Expand All @@ -52,7 +52,7 @@ jobs:
with:
override: true
profile: minimal
toolchain: nightly-2021-03-10
toolchain: nightly-2021-08-09

- uses: actions-rs/install@v0.1
with:
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ RUN apt-get update && \

RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \
export PATH="$PATH:$HOME/.cargo/bin" && \
rustup toolchain install nightly-2021-03-10 && \
rustup target add wasm32-unknown-unknown --toolchain nightly-2021-03-10 && \
rustup toolchain install nightly-2021-08-09 && \
rustup target add wasm32-unknown-unknown --toolchain nightly-2021-08-09 && \
rustup default stable && \
cargo build "--$PROFILE" --features "$FEATURES"

Expand Down
2 changes: 1 addition & 1 deletion node/src/service/service_parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn new_partial(

let (client, backend, keystore_container, task_manager) =
sc_service::new_full_parts::<Block, RuntimeApi, Executor>(
&config,
config,
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
)?;

Expand Down
10 changes: 6 additions & 4 deletions primitives/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ pub mod ztg;
use crate::types::{Balance, BlockNumber};
use frame_support::{parameter_types, PalletId};

// General
pub const BLOCK_HASH_COUNT: BlockNumber = 250;

// Definitions for time
pub const BLOCKS_PER_DAY: BlockNumber = BLOCKS_PER_HOUR * 24;
pub const MILLISECS_PER_BLOCK: u64 = 6000;
Expand All @@ -27,10 +24,15 @@ parameter_types! {

// Court
parameter_types! {
pub const CourtCaseDuration: u64 = 2 * BLOCKS_PER_DAY;
pub const CourtCaseDuration: u64 = BLOCKS_PER_DAY;
pub const StakeWeight: u128 = 2 * BASE;
}

// General
parameter_types! {
pub const BlockHashCount: u64 = 250;
}

// Liquidity Mining parameters
parameter_types! {
pub const LiquidityMiningPalletId: PalletId = PalletId(*b"zrml/lmg");
Expand Down
13 changes: 6 additions & 7 deletions primitives/src/traits/dispute_api.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::types::{Market, OutcomeReport, ResolutionCounters};
use frame_support::dispatch::{DispatchError, DispatchResult};
use crate::{market::MarketDispute, types::Market};
use frame_support::dispatch::DispatchResult;

/// Dispute Api
pub trait DisputeApi {
Expand All @@ -12,16 +12,15 @@ pub trait DisputeApi {
/// Disputes a reported outcome.
fn on_dispute<D>(
dispute_bond: D,
disputes: &[MarketDispute<Self::AccountId, Self::BlockNumber>],
market_id: Self::MarketId,
outcome: OutcomeReport,
who: Self::AccountId,
) -> Result<(), DispatchError>
) -> DispatchResult
where
D: Fn(usize) -> Self::Balance;

/// Manages markets resolutions moving all reported markets to resolved.
fn on_resolution<D, F>(dispute_bound: &D, now: Self::BlockNumber, cb: F) -> DispatchResult
fn on_resolution<F>(now: Self::BlockNumber, cb: F) -> DispatchResult
where
D: Fn(usize) -> Self::Balance,
F: FnMut(&Market<Self::AccountId, Self::BlockNumber>, ResolutionCounters);
F: FnMut(&Self::MarketId, &Market<Self::AccountId, Self::BlockNumber>) -> DispatchResult;
}
4 changes: 2 additions & 2 deletions primitives/src/traits/swaps.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::types::{Asset, MarketType, OutcomeReport, Pool, PoolId};
use alloc::vec::Vec;
use frame_support::dispatch::DispatchError;
use frame_support::dispatch::{DispatchError, DispatchResult};

pub trait Swaps<AccountId> {
type Balance;
Expand Down Expand Up @@ -34,5 +34,5 @@ pub trait Swaps<AccountId> {
market_type: &MarketType,
pool_id: PoolId,
outcome_report: &OutcomeReport,
) -> Result<(), DispatchError>;
) -> DispatchResult;
}
3 changes: 1 addition & 2 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ pub type SignedExtra = (
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;

parameter_types! {
pub const BlockHashCount: BlockNumber = BLOCK_HASH_COUNT;
pub const BondDuration: u32 = BLOCKS_PER_DAY as u32;
pub const CollatorDeposit: Balance = 2 * BASE;
pub const DefaultCollatorCommission: Perbill = Perbill::from_percent(20);
Expand Down Expand Up @@ -740,7 +739,7 @@ impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
.create_inherent_data()
.expect("Could not create the timestamp inherent data");

inherent_data.check_extrinsics(&block)
inherent_data.check_extrinsics(block)
}
}

Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = "nightly-2021-03-10"
channel = "nightly-2021-08-09"
components = ["clippy", "rustfmt"]
profile = "minimal"
targets = ["wasm32-unknown-unknown"]
4 changes: 2 additions & 2 deletions scripts/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ set -e
echo "*** Initializing WASM build environment"

if [ -z $CI_PROJECT_NAME ] ; then
rustup update nightly-2021-03-10
rustup update nightly-2021-08-09
rustup update stable
fi

rustup target add wasm32-unknown-unknown --toolchain nightly-2021-03-10
rustup target add wasm32-unknown-unknown --toolchain nightly-2021-08-09
101 changes: 83 additions & 18 deletions zrml/court/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod pallet {
use core::marker::PhantomData;
use frame_support::{
dispatch::DispatchResult,
pallet_prelude::{StorageMap, StorageValue, ValueQuery},
pallet_prelude::{StorageDoubleMap, StorageMap, StorageValue, ValueQuery},
traits::{Currency, Get, Hooks, IsType, Randomness, ReservableCurrency},
Blake2_128Concat,
};
Expand All @@ -29,11 +29,16 @@ mod pallet {
use sp_runtime::{traits::Saturating, ArithmeticError, DispatchError, SaturatedConversion};
use zeitgeist_primitives::{
traits::DisputeApi,
types::{Market, OutcomeReport, ResolutionCounters},
types::{Market, MarketDispute, OutcomeReport},
};
use zrml_market_commons::MarketCommonsPalletApi;

// Number of jurors for an initial market dispute
const INITIAL_JURORS_NUM: usize = 3;
const MAX_RANDOM_JURORS: usize = 13;
// Weight used to increase the number of jurors for subsequent disputes
// of the same market
const SUBSEQUENT_JURORS_FACTOR: usize = 2;

pub(crate) type BalanceOf<T> =
<CurrencyOf<T> as Currency<<T as frame_system::Config>::AccountId>>::Balance;
Expand All @@ -46,25 +51,46 @@ mod pallet {
impl<T: Config> Pallet<T> {
#[pallet::weight(0)]
pub fn exit_court(origin: OriginFor<T>) -> DispatchResult {
let account_id = ensure_signed(origin)?;
let juror = Self::juror(&account_id)?;
Jurors::<T>::remove(&account_id);
CurrencyOf::<T>::unreserve(&account_id, juror.staked);
let who = ensure_signed(origin)?;
let juror = Self::juror(&who)?;
Jurors::<T>::remove(&who);
CurrencyOf::<T>::unreserve(&who, juror.staked);
Ok(())
}

#[frame_support::transactional]
// `transactional` attribute is not used here because once `reserve` is successful, `insert`
// won't fail.
#[pallet::weight(0)]
pub fn join_court(origin: OriginFor<T>) -> DispatchResult {
let account_id = ensure_signed(origin)?;
if Jurors::<T>::get(&account_id).is_some() {
let who = ensure_signed(origin)?;
if Jurors::<T>::get(&who).is_some() {
return Err(Error::<T>::JurorAlreadyExists.into());
}
let jurors_num = Jurors::<T>::iter().count();
let jurors_num_plus_one = jurors_num.checked_add(1).ok_or(ArithmeticError::Overflow)?;
let stake = Self::current_required_stake(jurors_num_plus_one);
Jurors::<T>::insert(&account_id, Juror { staked: stake, status: JurorStatus::Ok });
CurrencyOf::<T>::reserve(&account_id, stake)?;
CurrencyOf::<T>::reserve(&who, stake)?;
Jurors::<T>::insert(&who, Juror { staked: stake, status: JurorStatus::Ok });
Ok(())
}

// `transactional` attribute is not used here because no fallible storage operation
// is performed
#[pallet::weight(0)]
pub fn vote(
origin: OriginFor<T>,
market_id: MarketIdOf<T>,
outcome: OutcomeReport,
) -> DispatchResult {
let who = ensure_signed(origin)?;
if Jurors::<T>::get(&who).is_none() {
return Err(Error::<T>::OnlyJurorsCanVote.into());
}
Votes::<T>::insert(
who,
market_id,
(<frame_system::Pallet<T>>::block_number(), outcome),
);
Ok(())
}
}
Expand Down Expand Up @@ -96,6 +122,8 @@ mod pallet {
JurorAlreadyExists,
/// An account id does not exist on the jurors storage.
JurorDoesNotExists,
/// Forbids voting of unknown accounts
OnlyJurorsCanVote,
}

#[pallet::event]
Expand Down Expand Up @@ -152,6 +180,15 @@ mod pallet {
T::StakeWeight::get().saturating_mul(jurors_len)
}

// Calculates the necessary number of jurors depending on the number of market disputes.
//
// Result is capped to `usize::MAX` or in other words, capped to a very, very, very
// high number of jurors.
fn necessary_jurors_num(disputes: &[MarketDispute<T::AccountId, T::BlockNumber>]) -> usize {
let len = disputes.len();
INITIAL_JURORS_NUM.saturating_add(SUBSEQUENT_JURORS_FACTOR.saturating_mul(len))
}

// Retrieves a juror from the storage
fn juror(account_id: &T::AccountId) -> Result<Juror<BalanceOf<T>>, DispatchError> {
Jurors::<T>::get(account_id).ok_or_else(|| Error::<T>::JurorDoesNotExists.into())
Expand All @@ -170,24 +207,30 @@ mod pallet {

fn on_dispute<D>(
dispute_bond: D,
_market_id: Self::MarketId,
_outcome: OutcomeReport,
disputes: &[MarketDispute<Self::AccountId, Self::BlockNumber>],
market_id: Self::MarketId,
who: Self::AccountId,
) -> DispatchResult
where
D: Fn(usize) -> Self::Balance,
{
CurrencyOf::<T>::reserve(&who, dispute_bond(1))?;
CurrencyOf::<T>::reserve(&who, dispute_bond(disputes.len()))?;
let jurors: Vec<_> = Jurors::<T>::iter().collect();
let necessary_jurors_num = Self::necessary_jurors_num(disputes);
let mut rng = Self::rng();
let _ = Self::random_jurors(&jurors, 3, &mut rng);
let random_jurors = Self::random_jurors(&jurors, necessary_jurors_num, &mut rng);
for (ai, _) in random_jurors {
RequestedJurors::<T>::insert(ai, market_id, T::CourtCaseDuration::get());
}
Ok(())
}

fn on_resolution<D, F>(_dispute_bond: &D, _now: Self::BlockNumber, _cb: F) -> DispatchResult
fn on_resolution<F>(_now: Self::BlockNumber, _cb: F) -> DispatchResult
where
D: Fn(usize) -> Self::Balance,
F: FnMut(&Market<Self::AccountId, Self::BlockNumber>, ResolutionCounters),
F: FnMut(
&Self::MarketId,
&Market<Self::AccountId, Self::BlockNumber>,
) -> DispatchResult,
{
Ok(())
}
Expand All @@ -200,4 +243,26 @@ mod pallet {
/// An extra layer of pseudo randomness.
#[pallet::storage]
pub type JurorsSelectionNonce<T: Config> = StorageValue<_, u64, ValueQuery>;

/// Selected jurors that should vote a market outcome until a certain block number
#[pallet::storage]
pub type RequestedJurors<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
T::AccountId,
Blake2_128Concat,
MarketIdOf<T>,
T::BlockNumber,
>;

/// Votes of market outcomes for disputes
#[pallet::storage]
pub type Votes<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
T::AccountId,
Blake2_128Concat,
MarketIdOf<T>,
(T::BlockNumber, OutcomeReport),
>;
}
4 changes: 1 addition & 3 deletions zrml/court/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
};
use zeitgeist_primitives::{
constants::{CourtCaseDuration, MaxReserves, BASE, BLOCK_HASH_COUNT},
constants::{BlockHashCount, CourtCaseDuration, MaxReserves, StakeWeight, BASE},
types::{
AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, MarketId,
UncheckedExtrinsicTest,
Expand All @@ -21,9 +21,7 @@ type Block = BlockTest<Runtime>;
type UncheckedExtrinsic = UncheckedExtrinsicTest<Runtime>;

parameter_types! {
pub const BlockHashCount: u64 = BLOCK_HASH_COUNT;
pub const LmPalletId: PalletId = PalletId(*b"test/lmg");
pub const StakeWeight: u128 = 2 * BASE;
}

construct_runtime!(
Expand Down
Loading

0 comments on commit 980555d

Please sign in to comment.