Skip to content
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: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ joystream_runtime.wasm

# Vim
.*.sw*

/modules/**/*.lock
103 changes: 103 additions & 0 deletions modules/proposals/codex/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
[package]
name = 'substrate-proposals-codex-module'
version = '2.0.0'
authors = ['Joystream contributors']
edition = '2018'

[features]
default = ['std']
no_std = []
std = [
'sr-staking-primitives/std',
'staking/std',
'codec/std',
'rstd/std',
'srml-support/std',
'balances/std',
'primitives/std',
'runtime-primitives/std',
'system/std',
'timestamp/std',
'serde',
]


[dependencies.num_enum]
default_features = false
version = "0.4.2"

[dependencies.serde]
features = ['derive']
optional = true
version = '1.0.101'

[dependencies.codec]
default-features = false
features = ['derive']
package = 'parity-scale-codec'
version = '1.0.0'

[dependencies.primitives]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'substrate-primitives'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.rstd]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'sr-std'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.runtime-primitives]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'sr-primitives'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.sr-staking-primitives]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'sr-staking-primitives'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.srml-support]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'srml-support'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.system]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'srml-system'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.timestamp]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'srml-timestamp'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.staking]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'srml-staking'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.balances]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'srml-balances'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'

[dependencies.proposal_engine]
default_features = false
package = 'substrate-proposals-engine-module'
path = '../engine'

[dev-dependencies.runtime-io]
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'sr-io'
rev = '0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3'
55 changes: 55 additions & 0 deletions modules/proposals/codex/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! Proposals codex module for the Joystream platform. Version 2.
//! Contains preset proposal types
//!
//! Supported extrinsics (proposal type):
//! - create_text_proposal
//!

// Ensure we're `no_std` when compiling for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]

// Do not delete! Cannot be uncommented by default, because of Parity decl_module! issue.
//#![warn(missing_docs)]

pub use proposal_types::{ProposalType, TextProposalExecutable};

mod proposal_types;
#[cfg(test)]
mod tests;

use codec::Encode;
use proposal_engine::*;
use rstd::clone::Clone;
use rstd::vec::Vec;
use srml_support::decl_module;

/// 'Proposals codex' substrate module Trait
pub trait Trait: system::Trait + proposal_engine::Trait {}

decl_module! {
/// 'Proposal codex' substrate module
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
/// Create text (signal) proposal type. On approval prints its content.
pub fn create_text_proposal(origin, title: Vec<u8>, body: Vec<u8>) {
let parameters = crate::ProposalParameters {
voting_period: T::BlockNumber::from(3u32),
approval_quorum_percentage: 49,
};

let text_proposal = TextProposalExecutable{
title: title.clone(),
body: body.clone()
};
let proposal_code = text_proposal.encode();

<proposal_engine::Module<T>>::create_proposal(
origin,
parameters,
title,
body,
text_proposal.proposal_type(),
proposal_code
)?;
}
}
}
69 changes: 69 additions & 0 deletions modules/proposals/codex/src/proposal_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use codec::{Decode, Encode};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use rstd::convert::TryFrom;
use rstd::prelude::*;

use rstd::str::from_utf8;
use srml_support::{dispatch, print};

use crate::{ProposalCodeDecoder, ProposalExecutable};

/// Defines allowed proposals types. Integer value serves as proposal_type_id.
#[derive(Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
#[repr(u32)]
pub enum ProposalType {
/// Text(signal) proposal type
Text = 1,
}

impl ProposalType {
fn compose_executable(
&self,
proposal_data: Vec<u8>,
) -> Result<Box<dyn ProposalExecutable>, &'static str> {
match self {
ProposalType::Text => TextProposalExecutable::decode(&mut &proposal_data[..])
.map_err(|err| err.what())
.map(|obj| Box::new(obj) as Box<dyn ProposalExecutable>),
}
}
}

impl ProposalCodeDecoder for ProposalType {
fn decode_proposal(
proposal_type: u32,
proposal_code: Vec<u8>,
) -> Result<Box<dyn ProposalExecutable>, &'static str> {
Self::try_from(proposal_type)
.map_err(|_| "Unsupported proposal type")?
.compose_executable(proposal_code)
}
}

/// Text (signal) proposal executable code wrapper. Prints its content on execution.
#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, Default)]
pub struct TextProposalExecutable {
/// Text proposal title
pub title: Vec<u8>,

/// Text proposal body
pub body: Vec<u8>,
}

impl TextProposalExecutable {
/// Converts text proposal type to proposal_type_id
pub fn proposal_type(&self) -> u32 {
ProposalType::Text.into()
}
}

impl ProposalExecutable for TextProposalExecutable {
fn execute(&self) -> dispatch::Result {
print("Proposal: ");
print(from_utf8(self.title.as_slice()).unwrap());
print("Description:");
print(from_utf8(self.body.as_slice()).unwrap());

Ok(())
}
}
128 changes: 128 additions & 0 deletions modules/proposals/codex/src/tests/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#![cfg(test)]

pub use system;

pub use primitives::{Blake2Hasher, H256};
pub use runtime_primitives::{
testing::{Digest, DigestItem, Header, UintAuthorityId},
traits::{BlakeTwo256, Convert, IdentityLookup, OnFinalize},
weights::Weight,
BuildStorage, Perbill,
};

use proposal_engine::VotersParameters;
use srml_support::{impl_outer_dispatch, impl_outer_origin, parameter_types};

impl_outer_origin! {
pub enum Origin for Test {}
}

// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Test;
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: u32 = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
pub const MinimumPeriod: u64 = 5;
}

impl_outer_dispatch! {
pub enum Call for Test where origin: Origin {
codex::ProposalCodex,
proposals::ProposalsEngine,
}
}

impl proposal_engine::Trait for Test {
type Event = ();

type ProposalOrigin = system::EnsureSigned<Self::AccountId>;

type VoteOrigin = system::EnsureSigned<Self::AccountId>;

type TotalVotersCounter = MockVotersParameters;

type ProposalCodeDecoder = crate::ProposalType;

type ProposalId = u32;

type ProposerId = u64;

type VoterId = u64;
}

pub struct MockVotersParameters;
impl VotersParameters for MockVotersParameters {
fn total_voters_count() -> u32 {
4
}
}

impl crate::Trait for Test {}

impl system::Trait for Test {
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Call = ();
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
}

impl timestamp::Trait for Test {
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
}

parameter_types! {
pub const ExistentialDeposit: u32 = 0;
pub const TransferFee: u32 = 0;
pub const CreationFee: u32 = 0;
pub const TransactionBaseFee: u32 = 1;
pub const TransactionByteFee: u32 = 0;
pub const InitialMembersBalance: u32 = 0;
}

impl balances::Trait for Test {
/// The type for recording an account's balance.
type Balance = u64;
/// What to do if an account's free balance gets zeroed.
type OnFreeBalanceZero = ();
/// What to do if a new account is created.
type OnNewAccount = ();
/// The ubiquitous event type.
type Event = ();

type DustRemoval = ();
type TransferPayment = ();
type ExistentialDeposit = ExistentialDeposit;
type TransferFee = TransferFee;
type CreationFee = CreationFee;
}

// TODO add a Hook type to capture TriggerElection and CouncilElected hooks

// This function basically just builds a genesis storage key/value store according to
// our desired mockup.
pub fn initial_test_ext() -> runtime_io::TestExternalities {
let t = system::GenesisConfig::default()
.build_storage::<Test>()
.unwrap();

t.into()
}

pub type ProposalCodex = crate::Module<Test>;
pub type ProposalsEngine = proposal_engine::Module<Test>;
28 changes: 28 additions & 0 deletions modules/proposals/codex/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
mod mock;

use mock::*;
use system::RawOrigin;

#[test]
fn create_text_proposal_codex_call_succeeds() {
initial_test_ext().execute_with(|| {
let origin = RawOrigin::Signed(1).into();

assert!(
ProposalCodex::create_text_proposal(origin, b"title".to_vec(), b"body".to_vec(),)
.is_ok()
);
});
}

#[test]
fn create_text_proposal_codex_call_fails_with_insufficient_rights() {
initial_test_ext().execute_with(|| {
let origin = RawOrigin::None.into();

assert!(
ProposalCodex::create_text_proposal(origin, b"title".to_vec(), b"body".to_vec(),)
.is_err()
);
});
}
Loading