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
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ authors = ['Joystream']
build = 'build.rs'
edition = '2018'
name = 'joystream-node'
version = '2.1.5'
version = '2.1.6'
default-run = "joystream-node"

[[bin]]
Expand Down
8 changes: 7 additions & 1 deletion runtime-modules/governance/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ std = [
'rstd/std',
'common/std',
'membership/std',
'minting/std',
]

[dependencies.sr-primitives]
Expand Down Expand Up @@ -86,4 +87,9 @@ rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
default_features = false
git = 'https://github.com/paritytech/substrate.git'
package = 'srml-balances'
rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'

[dependencies.minting]
default_features = false
package = 'substrate-token-mint-module'
path = '../token-minting'
44 changes: 41 additions & 3 deletions runtime-modules/governance/src/council.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,22 @@ impl<X: CouncilTermEnded> CouncilTermEnded for (X,) {
}
}

pub trait Trait: system::Trait + GovernanceCurrency {
pub trait Trait: system::Trait + minting::Trait + GovernanceCurrency {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;

type CouncilTermEnded: CouncilTermEnded;
}

decl_storage! {
trait Store for Module<T: Trait> as Council {
ActiveCouncil get(active_council) config(): Seats<T::AccountId, BalanceOf<T>>;
TermEndsAt get(term_ends_at) config() : T::BlockNumber = T::BlockNumber::from(1);
pub ActiveCouncil get(active_council) config(): Seats<T::AccountId, BalanceOf<T>>;

pub TermEndsAt get(term_ends_at) config() : T::BlockNumber = T::BlockNumber::from(1);

/// The mint that funds council member rewards and spending proposals budget. It is an Option
/// because it was introduced in a runtime upgrade. It will be automatically created when
/// a successful call to set_council_mint_capacity() is made.
pub CouncilMint get(council_mint) : Option<<T as minting::Trait>::MintId>;
}
}

Expand Down Expand Up @@ -60,6 +66,15 @@ impl<T: Trait> Module<T> {
pub fn is_councilor(sender: &T::AccountId) -> bool {
Self::active_council().iter().any(|c| c.member == *sender)
}

/// Initializes a new mint, discarding previous mint if it existed.
pub fn create_new_council_mint(
capacity: minting::BalanceOf<T>,
) -> Result<T::MintId, &'static str> {
let mint_id = <minting::Module<T>>::add_mint(capacity, None)?;
CouncilMint::<T>::put(mint_id);
Ok(mint_id)
}
}

decl_module! {
Expand Down Expand Up @@ -118,6 +133,29 @@ decl_module! {
ensure!(ends_at > <system::Module<T>>::block_number(), "must set future block number");
<TermEndsAt<T>>::put(ends_at);
}

/// Sets the capacity of the the council mint, if it doesn't exist, attempts to
/// create a new one.
fn set_council_mint_capacity(origin, capacity: minting::BalanceOf<T>) {
ensure_root(origin)?;

if let Some(mint_id) = Self::council_mint() {
minting::Module::<T>::set_mint_capacity(mint_id, capacity)?;
} else {
Self::create_new_council_mint(capacity)?;
}
}

/// Attempts to mint and transfer amount to destination account
fn spend_from_council_mint(origin, amount: minting::BalanceOf<T>, destination: T::AccountId) {
ensure_root(origin)?;

if let Some(mint_id) = Self::council_mint() {
minting::Module::<T>::transfer_tokens(mint_id, amount, &destination)?;
} else {
return Err("CouncilHashNoMint")
}
}
}
}

Expand Down
19 changes: 11 additions & 8 deletions runtime-modules/governance/src/election.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl<T: Trait> Module<T> {
}

fn can_participate(sender: &T::AccountId) -> bool {
!T::Currency::free_balance(sender).is_zero()
!<T as GovernanceCurrency>::Currency::free_balance(sender).is_zero()
&& <membership::members::Module<T>>::is_member_account(sender)
}

Expand Down Expand Up @@ -374,7 +374,10 @@ impl<T: Trait> Module<T> {
for stakeholder in Self::existing_stake_holders().iter() {
let stake = Self::transferable_stakes(stakeholder);
if !stake.seat.is_zero() || !stake.backing.is_zero() {
T::Currency::unreserve(stakeholder, stake.seat + stake.backing);
<T as GovernanceCurrency>::Currency::unreserve(
stakeholder,
stake.seat + stake.backing,
);
}
}
}
Expand All @@ -399,7 +402,7 @@ impl<T: Trait> Module<T> {

// return new stake to account's free balance
if !stake.new.is_zero() {
T::Currency::unreserve(applicant, stake.new);
<T as GovernanceCurrency>::Currency::unreserve(applicant, stake.new);
}

// return unused transferable stake
Expand Down Expand Up @@ -453,7 +456,7 @@ impl<T: Trait> Module<T> {
// return new stake to account's free balance
let SealedVote { voter, stake, .. } = sealed_vote;
if !stake.new.is_zero() {
T::Currency::unreserve(voter, stake.new);
<T as GovernanceCurrency>::Currency::unreserve(voter, stake.new);
}

// return unused transferable stake
Expand Down Expand Up @@ -644,12 +647,12 @@ impl<T: Trait> Module<T> {
let new_stake = Self::new_stake_reusing_transferable(&mut transferable_stake.seat, stake);

ensure!(
T::Currency::can_reserve(&applicant, new_stake.new),
<T as GovernanceCurrency>::Currency::can_reserve(&applicant, new_stake.new),
"not enough free balance to reserve"
);

ensure!(
T::Currency::reserve(&applicant, new_stake.new).is_ok(),
<T as GovernanceCurrency>::Currency::reserve(&applicant, new_stake.new).is_ok(),
"failed to reserve applicant stake!"
);

Expand Down Expand Up @@ -680,12 +683,12 @@ impl<T: Trait> Module<T> {
Self::new_stake_reusing_transferable(&mut transferable_stake.backing, stake);

ensure!(
T::Currency::can_reserve(&voter, vote_stake.new),
<T as GovernanceCurrency>::Currency::can_reserve(&voter, vote_stake.new),
"not enough free balance to reserve"
);

ensure!(
T::Currency::reserve(&voter, vote_stake.new).is_ok(),
<T as GovernanceCurrency>::Currency::reserve(&voter, vote_stake.new).is_ok(),
"failed to reserve voting stake!"
);

Expand Down
5 changes: 4 additions & 1 deletion runtime-modules/governance/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ impl membership::members::Trait for Test {
type ActorId = u32;
type InitialMembersBalance = InitialMembersBalance;
}

impl minting::Trait for Test {
type Currency = Balances;
type MintId = u64;
}
parameter_types! {
pub const ExistentialDeposit: u32 = 0;
pub const TransferFee: u32 = 0;
Expand Down
24 changes: 15 additions & 9 deletions runtime-modules/governance/src/proposals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ decl_module! {
ensure!(wasm_code.len() as u32 <= Self::wasm_code_max_len(), MSG_TOO_LONG_WASM_CODE);

// Lock proposer's stake:
T::Currency::reserve(&proposer, stake)
<T as GovernanceCurrency>::Currency::reserve(&proposer, stake)
.map_err(|_| MSG_STAKE_IS_GREATER_THAN_BALANCE)?;

let proposal_id = Self::proposal_count() + 1;
Expand Down Expand Up @@ -312,11 +312,11 @@ decl_module! {

// Spend some minimum fee on proposer's balance for canceling a proposal
let fee = Self::cancellation_fee();
let _ = T::Currency::slash_reserved(&proposer, fee);
let _ = <T as GovernanceCurrency>::Currency::slash_reserved(&proposer, fee);

// Return unspent part of remaining staked deposit (after taking some fee)
let left_stake = proposal.stake - fee;
let _ = T::Currency::unreserve(&proposer, left_stake);
let _ = <T as GovernanceCurrency>::Currency::unreserve(&proposer, left_stake);

Self::_update_proposal_status(proposal_id, Cancelled)?;
Self::deposit_event(RawEvent::ProposalCanceled(proposer, proposal_id));
Expand All @@ -336,7 +336,7 @@ decl_module! {
let proposal = Self::proposals(proposal_id);
ensure!(proposal.status == Active, MSG_PROPOSAL_FINALIZED);

let _ = T::Currency::unreserve(&proposal.proposer, proposal.stake);
let _ = <T as GovernanceCurrency>::Currency::unreserve(&proposal.proposer, proposal.stake);

Self::_update_proposal_status(proposal_id, Cancelled)?;

Expand All @@ -357,7 +357,7 @@ impl<T: Trait> Module<T> {
}

fn can_participate(sender: &T::AccountId) -> bool {
!T::Currency::free_balance(sender).is_zero()
!<T as GovernanceCurrency>::Currency::free_balance(sender).is_zero()
&& <membership::members::Module<T>>::is_member_account(sender)
}

Expand Down Expand Up @@ -513,7 +513,8 @@ impl<T: Trait> Module<T> {
let proposal = Self::proposals(proposal_id);

// Slash proposer's stake:
let _ = T::Currency::slash_reserved(&proposal.proposer, proposal.stake);
let _ =
<T as GovernanceCurrency>::Currency::slash_reserved(&proposal.proposer, proposal.stake);

Ok(())
}
Expand All @@ -525,11 +526,11 @@ impl<T: Trait> Module<T> {

// Spend some minimum fee on proposer's balance to prevent spamming attacks:
let fee = Self::rejection_fee();
let _ = T::Currency::slash_reserved(&proposer, fee);
let _ = <T as GovernanceCurrency>::Currency::slash_reserved(&proposer, fee);

// Return unspent part of remaining staked deposit (after taking some fee):
let left_stake = proposal.stake - fee;
let _ = T::Currency::unreserve(&proposer, left_stake);
let _ = <T as GovernanceCurrency>::Currency::unreserve(&proposer, left_stake);

Ok(())
}
Expand All @@ -540,7 +541,7 @@ impl<T: Trait> Module<T> {
let wasm_code = Self::wasm_code_by_hash(proposal.wasm_hash);

// Return staked deposit to proposer:
let _ = T::Currency::unreserve(&proposal.proposer, proposal.stake);
let _ = <T as GovernanceCurrency>::Currency::unreserve(&proposal.proposer, proposal.stake);

// Update wasm code of node's runtime:
<system::Module<T>>::set_code(system::RawOrigin::Root.into(), wasm_code)?;
Expand Down Expand Up @@ -649,6 +650,11 @@ mod tests {
type InitialMembersBalance = InitialMembersBalance;
}

impl minting::Trait for Test {
type Currency = balances::Module<Self>;
type MintId = u64;
}

impl Trait for Test {
type Event = ();
}
Expand Down
9 changes: 9 additions & 0 deletions runtime-modules/token-minting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ impl From<GeneralError> for &'static str {
}
}

impl From<TransferError> for &'static str {
fn from(err: TransferError) -> &'static str {
match err {
TransferError::MintNotFound => "MintNotFound",
TransferError::NotEnoughCapacity => "NotEnoughCapacity",
}
}
}

#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
pub enum Adjustment<Balance: Zero, BlockNumber> {
// First adjustment will be after AdjustOnInterval.block_interval
Expand Down
2 changes: 1 addition & 1 deletion runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = '2018'
name = 'joystream-node-runtime'
# Follow convention: https://github.com/Joystream/substrate-runtime-joystream/issues/1
# {Authoring}.{Spec}.{Impl} of the RuntimeVersion
version = '6.11.0'
version = '6.12.0'

[features]
default = ['std']
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("joystream-node"),
impl_name: create_runtime_str!("joystream-node"),
authoring_version: 6,
spec_version: 11,
spec_version: 12,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
};
Expand Down
29 changes: 13 additions & 16 deletions runtime/src/migration.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
use crate::VERSION;
use sr_primitives::print;
use sr_primitives::{print, traits::Zero};
use srml_support::{decl_event, decl_module, decl_storage};
use sudo;
use system;

// When preparing a new major runtime release version bump this value to match it and update
// the initialization code in runtime_initialization(). Because of the way substrate runs runtime code
// the runtime doesn't need to maintain any logic for old migrations. All knowledge about state of the chain and runtime
// prior to the new runtime taking over is implicit in the migration code implementation. If assumptions are incorrect
// behaviour is undefined.
const MIGRATION_FOR_SPEC_VERSION: u32 = 0;

impl<T: Trait> Module<T> {
fn runtime_initialization() {
if VERSION.spec_version != MIGRATION_FOR_SPEC_VERSION {
return;
}

print("running runtime initializers");
fn runtime_upgraded() {
print("running runtime initializers...");

// ...
// add initialization of other modules introduced in this runtime
// add initialization of modules introduced in new runtime release. This
// would be any new storage values that need an initial value which would not
// have been initialized with config() or build() mechanism.
// ...

// Create the Council mint. If it fails, we can't do anything about it here.
let _ = governance::council::Module::<T>::create_new_council_mint(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We agreed to print an error message in such cases. Don't we?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in a6148b9

minting::BalanceOf::<T>::zero(),
);

Self::deposit_event(RawEvent::Migrated(
<system::Module<T>>::block_number(),
VERSION.spec_version,
Expand All @@ -36,6 +32,7 @@ pub trait Trait:
+ storage::data_object_storage_registry::Trait
+ forum::Trait
+ sudo::Trait
+ governance::council::Trait
{
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
Expand Down Expand Up @@ -64,7 +61,7 @@ decl_module! {
SpecVersion::put(VERSION.spec_version);

// run migrations and store initializers
Self::runtime_initialization();
Self::runtime_upgraded();
}
}
}
Expand Down