Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fifth iteration of the Court pallet #233

Merged
merged 1 commit into from
Aug 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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