From fd1cec850e4b5b295b4f2cd8eb8ec9ae73c26ae8 Mon Sep 17 00:00:00 2001
From: Gavin Wood <gavin@parity.io>
Date: Sun, 1 Dec 2019 10:13:09 +0100
Subject: [PATCH] Economic fixes for democracy module (#4256)

* Fix up `end_block` mess; add free preimage noting for imminents.

* Fixes

* Bump runtime

* Update frame/democracy/src/lib.rs

Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com>

* Handle grumble

* Update frame/democracy/src/lib.rs

Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com>
---
 substrate/bin/node/runtime/src/lib.rs         |   8 +-
 .../src/communication/gossip.rs               |   4 +-
 substrate/frame/democracy/src/lib.rs          | 586 ++++++++++++------
 3 files changed, 415 insertions(+), 183 deletions(-)

diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index c1ae0510205..366f8847354 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -78,8 +78,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
 	// and set impl_version to equal spec_version. If only runtime
 	// implementation changes and behavior does not, then leave spec_version as
 	// is and increment impl_version.
-	spec_version: 196,
-	impl_version: 196,
+	spec_version: 197,
+	impl_version: 197,
 	apis: RUNTIME_API_VERSIONS,
 };
 
@@ -278,6 +278,8 @@ parameter_types! {
 	pub const MinimumDeposit: Balance = 100 * DOLLARS;
 	pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES;
 	pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES;
+	// One cent: $10,000 / MB
+	pub const PreimageByteDeposit: Balance = 1 * CENTS;
 }
 
 impl democracy::Trait for Runtime {
@@ -305,6 +307,8 @@ impl democracy::Trait for Runtime {
 	// only do it once and it lasts only for the cooloff period.
 	type VetoOrigin = collective::EnsureMember<AccountId, TechnicalCollective>;
 	type CooloffPeriod = CooloffPeriod;
+	type PreimageByteDeposit = PreimageByteDeposit;
+	type Slash = Treasury;
 }
 
 type CouncilCollective = collective::Instance1;
diff --git a/substrate/client/finality-grandpa/src/communication/gossip.rs b/substrate/client/finality-grandpa/src/communication/gossip.rs
index 3e0f2a7ac4f..bd1b6197eaa 100644
--- a/substrate/client/finality-grandpa/src/communication/gossip.rs
+++ b/substrate/client/finality-grandpa/src/communication/gossip.rs
@@ -517,7 +517,7 @@ impl<N: Ord> Peers<N> {
 	}
 
 	fn reshuffle(&mut self) {
-		let mut lucky_peers : Vec<_> = self.inner
+		let mut lucky_peers: Vec<_> = self.inner
 			.iter()
 			.filter_map(|(id, info)| if !info.roles.is_authority() { Some(id.clone()) } else { None })
 			.collect();
@@ -670,7 +670,7 @@ impl<Block: BlockT> Inner<Block> {
 			let set_id = local_view.set_id;
 
 			debug!(target: "afg", "Voter {} noting beginning of round {:?} to network.",
-				self.config.name(), (round,set_id));
+				self.config.name(), (round, set_id));
 
 			local_view.round = round;
 
diff --git a/substrate/frame/democracy/src/lib.rs b/substrate/frame/democracy/src/lib.rs
index 98420444610..988f82734c4 100644
--- a/substrate/frame/democracy/src/lib.rs
+++ b/substrate/frame/democracy/src/lib.rs
@@ -22,7 +22,7 @@ use rstd::prelude::*;
 use rstd::{result, convert::TryFrom};
 use sr_primitives::{
 	RuntimeDebug,
-	traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash, Dispatchable},
+	traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash, Dispatchable, Saturating},
 };
 use codec::{Ref, Encode, Decode, Input, Output, Error};
 use support::{
@@ -31,7 +31,7 @@ use support::{
 	weights::SimpleDispatchInfo,
 	traits::{
 		Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get,
-		OnFreeBalanceZero
+		OnFreeBalanceZero, OnUnbalanced
 	}
 };
 use support::dispatch::Result;
@@ -174,6 +174,8 @@ impl Decode for Vote {
 }
 
 type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
+type NegativeImbalanceOf<T> =
+<<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::NegativeImbalance;
 
 pub trait Trait: system::Trait + Sized {
 	type Proposal: Parameter + Dispatchable<Origin=Self::Origin>;
@@ -227,30 +229,36 @@ pub trait Trait: system::Trait + Sized {
 
 	/// Period in blocks where an external proposal may not be re-submitted after being vetoed.
 	type CooloffPeriod: Get<Self::BlockNumber>;
+
+	/// The amount of balance that must be deposited per byte of preimage stored.
+	type PreimageByteDeposit: Get<BalanceOf<Self>>;
+
+	/// Handler for the unbalanced reduction when slashing a preimage deposit.
+	type Slash: OnUnbalanced<NegativeImbalanceOf<Self>>;
 }
 
 /// Info regarding an ongoing referendum.
 #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
-pub struct ReferendumInfo<BlockNumber: Parameter, Proposal: Parameter> {
+pub struct ReferendumInfo<BlockNumber: Parameter, Hash: Parameter> {
 	/// When voting on this referendum will end.
 	end: BlockNumber,
-	/// The proposal being voted on.
-	proposal: Proposal,
+	/// The hash of the proposal being voted on.
+	proposal_hash: Hash,
 	/// The thresholding mechanism to determine whether it passed.
 	threshold: VoteThreshold,
 	/// The delay (in blocks) to wait after a successful referendum before deploying.
 	delay: BlockNumber,
 }
 
-impl<BlockNumber: Parameter, Proposal: Parameter> ReferendumInfo<BlockNumber, Proposal> {
+impl<BlockNumber: Parameter, Hash: Parameter> ReferendumInfo<BlockNumber, Hash> {
 	/// Create a new instance.
 	pub fn new(
 		end: BlockNumber,
-		proposal: Proposal,
+		proposal_hash: Hash,
 		threshold: VoteThreshold,
 		delay: BlockNumber
 	) -> Self {
-		ReferendumInfo { end, proposal, threshold, delay }
+		ReferendumInfo { end, proposal_hash, threshold, delay }
 	}
 }
 
@@ -258,8 +266,11 @@ decl_storage! {
 	trait Store for Module<T: Trait> as Democracy {
 		/// The number of (public) proposals that have been made so far.
 		pub PublicPropCount get(fn public_prop_count) build(|_| 0 as PropIndex) : PropIndex;
-		/// The public proposals. Unsorted.
-		pub PublicProps get(fn public_props): Vec<(PropIndex, T::Proposal, T::AccountId)>;
+		/// The public proposals. Unsorted. The second item is the proposal's hash.
+		pub PublicProps get(fn public_props): Vec<(PropIndex, T::Hash, T::AccountId)>;
+		/// Map of hashes to the proposal preimage, along with who registered it and their deposit.
+		/// The block number is the block at which it was deposited.
+		pub Preimages: map T::Hash => Option<(Vec<u8>, T::AccountId, BalanceOf<T>, T::BlockNumber)>;
 		/// Those who have locked a deposit.
 		pub DepositOf get(fn deposit_of): map PropIndex => Option<(BalanceOf<T>, Vec<T::AccountId>)>;
 
@@ -269,10 +280,10 @@ decl_storage! {
 		pub NextTally get(fn next_tally) build(|_| 0 as ReferendumIndex): ReferendumIndex;
 		/// Information concerning any given referendum.
 		pub ReferendumInfoOf get(fn referendum_info):
-			map ReferendumIndex => Option<(ReferendumInfo<T::BlockNumber, T::Proposal>)>;
+			map ReferendumIndex => Option<(ReferendumInfo<T::BlockNumber, T::Hash>)>;
 		/// Queue of successful referenda to be dispatched.
 		pub DispatchQueue get(fn dispatch_queue):
-			map T::BlockNumber => Vec<Option<(T::Proposal, ReferendumIndex)>>;
+			map T::BlockNumber => Vec<Option<(T::Hash, ReferendumIndex)>>;
 
 		/// Get the voters for the current proposal.
 		pub VotersFor get(fn voters_for): map ReferendumIndex => Vec<T::AccountId>;
@@ -298,7 +309,7 @@ decl_storage! {
 		/// This happens when a referendum needs to be tabled and one of two conditions are met:
 		/// - `LastTabledWasExternal` is `false`; or
 		/// - `PublicProps` is empty.
-		pub NextExternal: Option<(T::Proposal, VoteThreshold)>;
+		pub NextExternal: Option<(T::Hash, VoteThreshold)>;
 
 		/// A record of who vetoed what. Maps proposal hash to a possible existent block number
 		/// (until when it may not be resubmitted) and who vetoed it.
@@ -316,17 +327,38 @@ decl_event!(
 		<T as system::Trait>::Hash,
 		<T as system::Trait>::BlockNumber,
 	{
+		/// A motion has been proposed by a public account.
 		Proposed(PropIndex, Balance),
+		/// A public proposal has been tabled for referendum vote.
 		Tabled(PropIndex, Balance, Vec<AccountId>),
+		/// An external proposal has been tabled.
 		ExternalTabled,
+		/// A referendum has begun.
 		Started(ReferendumIndex, VoteThreshold),
+		/// A proposal has been approved by referendum.
 		Passed(ReferendumIndex),
+		/// A proposal has been rejected by referendum.
 		NotPassed(ReferendumIndex),
+		/// A referendum has been cancelled.
 		Cancelled(ReferendumIndex),
+		/// A proposal has been enacted.
 		Executed(ReferendumIndex, bool),
+		/// An account has delegated their vote to another account.
 		Delegated(AccountId, AccountId),
+		/// An account has cancelled a previous delegation operation.
 		Undelegated(AccountId),
+		/// An external proposal has been vetoed.
 		Vetoed(AccountId, Hash, BlockNumber),
+		/// A proposal's preimage was noted, and the deposit taken.
+		PreimageNoted(Hash, AccountId, Balance),
+		/// A proposal preimage was removed and used (the deposit was returned).
+		PreimageUsed(Hash, AccountId, Balance),
+		/// A proposal could not be executed because its preimage was invalid.
+		PreimageInvalid(Hash, ReferendumIndex),
+		/// A proposal could not be executed because its preimage was missing.
+		PreimageMissing(Hash, ReferendumIndex),
+		/// A registered preimage was removed and the deposit collected by the reaper (last item).
+		PreimageReaped(Hash, AccountId, Balance, AccountId),
 	}
 );
 
@@ -354,6 +386,9 @@ decl_module! {
 		/// Period in blocks where an external proposal may not be re-submitted after being vetoed.
 		const CooloffPeriod: T::BlockNumber = T::CooloffPeriod::get();
 
+		/// The amount of balance that must be deposited per byte of preimage stored.
+		const PreimageByteDeposit: BalanceOf<T> = T::PreimageByteDeposit::get();
+
 		fn deposit_event() = default;
 
 		/// Propose a sensitive action to be taken.
@@ -364,11 +399,10 @@ decl_module! {
 		/// # </weight>
 		#[weight = SimpleDispatchInfo::FixedNormal(5_000_000)]
 		fn propose(origin,
-			proposal: Box<T::Proposal>,
+			proposal_hash: T::Hash,
 			#[compact] value: BalanceOf<T>
 		) {
 			let who = ensure_signed(origin)?;
-
 			ensure!(value >= T::MinimumDeposit::get(), "value too low");
 			T::Currency::reserve(&who, value)
 				.map_err(|_| "proposer's balance too low")?;
@@ -377,7 +411,7 @@ decl_module! {
 			PublicPropCount::put(index + 1);
 			<DepositOf<T>>::insert(index, (value, &[&who][..]));
 
-			let new_prop = (index, proposal, who);
+			let new_prop = (index, proposal_hash, who);
 			<PublicProps<T>>::append_or_put(&[Ref::from(&new_prop)][..]);
 
 			Self::deposit_event(RawEvent::Proposed(index, value));
@@ -439,7 +473,7 @@ decl_module! {
 			T::CancellationOrigin::ensure_origin(origin)?;
 
 			let info = Self::referendum_info(ref_index).ok_or("unknown index")?;
-			let h = T::Hashing::hash_of(&info.proposal);
+			let h = info.proposal_hash;
 			ensure!(!<Cancellations<T>>::exists(h), "cannot cancel the same proposal twice");
 
 			<Cancellations<T>>::insert(h, true);
@@ -449,14 +483,13 @@ decl_module! {
 		/// Schedule a referendum to be tabled once it is legal to schedule an external
 		/// referendum.
 		#[weight = SimpleDispatchInfo::FixedNormal(5_000_000)]
-		fn external_propose(origin, proposal: Box<T::Proposal>) {
+		fn external_propose(origin, proposal_hash: T::Hash) {
 			T::ExternalOrigin::ensure_origin(origin)?;
 			ensure!(!<NextExternal<T>>::exists(), "proposal already made");
-			let proposal_hash = T::Hashing::hash_of(&proposal);
 			if let Some((until, _)) = <Blacklist<T>>::get(proposal_hash) {
 				ensure!(<system::Module<T>>::block_number() >= until, "proposal still blacklisted");
 			}
-			<NextExternal<T>>::put((*proposal, VoteThreshold::SuperMajorityApprove));
+			<NextExternal<T>>::put((proposal_hash, VoteThreshold::SuperMajorityApprove));
 		}
 
 		/// Schedule a majority-carries referendum to be tabled next once it is legal to schedule
@@ -465,9 +498,9 @@ decl_module! {
 		/// Unlike `external_propose`, blacklisting has no effect on this and it may replace a
 		/// pre-scheduled `external_propose` call.
 		#[weight = SimpleDispatchInfo::FixedNormal(5_000_000)]
-		fn external_propose_majority(origin, proposal: Box<T::Proposal>) {
+		fn external_propose_majority(origin, proposal_hash: T::Hash) {
 			T::ExternalMajorityOrigin::ensure_origin(origin)?;
-			<NextExternal<T>>::put((*proposal, VoteThreshold::SimpleMajority));
+			<NextExternal<T>>::put((proposal_hash, VoteThreshold::SimpleMajority));
 		}
 
 		/// Schedule a negative-turnout-bias referendum to be tabled next once it is legal to
@@ -476,9 +509,9 @@ decl_module! {
 		/// Unlike `external_propose`, blacklisting has no effect on this and it may replace a
 		/// pre-scheduled `external_propose` call.
 		#[weight = SimpleDispatchInfo::FixedNormal(5_000_000)]
-		fn external_propose_default(origin, proposal: Box<T::Proposal>) {
+		fn external_propose_default(origin, proposal_hash: T::Hash) {
 			T::ExternalDefaultOrigin::ensure_origin(origin)?;
-			<NextExternal<T>>::put((*proposal, VoteThreshold::SuperMajorityAgainst));
+			<NextExternal<T>>::put((proposal_hash, VoteThreshold::SuperMajorityAgainst));
 		}
 
 		/// Schedule the currently externally-proposed majority-carries referendum to be tabled
@@ -497,15 +530,18 @@ decl_module! {
 			delay: T::BlockNumber
 		) {
 			T::FastTrackOrigin::ensure_origin(origin)?;
-			let (proposal, threshold) = <NextExternal<T>>::get().ok_or("no proposal made")?;
-			ensure!(threshold != VoteThreshold::SuperMajorityApprove, "next external proposal not simple majority");
-			ensure!(proposal_hash == T::Hashing::hash_of(&proposal), "invalid hash");
+			let (e_proposal_hash, threshold) = <NextExternal<T>>::get().ok_or("no proposal made")?;
+			ensure!(
+				threshold != VoteThreshold::SuperMajorityApprove,
+				"next external proposal not simple majority"
+			);
+			ensure!(proposal_hash == e_proposal_hash, "invalid hash");
 
 			<NextExternal<T>>::kill();
 			let now = <system::Module<T>>::block_number();
 			// We don't consider it an error if `vote_period` is too low, like `emergency_propose`.
 			let period = voting_period.max(T::EmergencyVotingPeriod::get());
-			Self::inject_referendum(now + period, proposal, threshold, delay).map(|_| ())?;
+			Self::inject_referendum(now + period, proposal_hash, threshold, delay).map(|_| ())?;
 		}
 
 		/// Veto and blacklist the external proposal hash.
@@ -513,8 +549,8 @@ decl_module! {
 		fn veto_external(origin, proposal_hash: T::Hash) {
 			let who = T::VetoOrigin::ensure_origin(origin)?;
 
-			if let Some((proposal, _)) = <NextExternal<T>>::get() {
-				ensure!(proposal_hash == T::Hashing::hash_of(&proposal), "unknown proposal");
+			if let Some((e_proposal_hash, _)) = <NextExternal<T>>::get() {
+				ensure!(proposal_hash == e_proposal_hash, "unknown proposal");
 			} else {
 				Err("no external proposal")?;
 			}
@@ -560,7 +596,7 @@ decl_module! {
 		}
 
 		fn on_initialize(n: T::BlockNumber) {
-			if let Err(e) = Self::end_block(n) {
+			if let Err(e) = Self::begin_block(n) {
 				sr_primitives::print(e);
 			}
 		}
@@ -642,6 +678,70 @@ decl_module! {
 			);
 			Self::deposit_event(RawEvent::Undelegated(who));
 		}
+
+		/// Veto and blacklist the proposal hash. Must be from Root origin.
+		#[weight = SimpleDispatchInfo::FixedNormal(10_000)]
+		fn clear_public_proposals(origin) {
+			ensure_root(origin)?;
+
+			<PublicProps<T>>::kill();
+		}
+
+		/// Register the preimage for an upcoming proposal. This doesn't require the proposal to be
+		/// in the dispatch queue but does require a deposit, returned once enacted.
+		#[weight = SimpleDispatchInfo::FixedNormal(100_000)]
+		fn note_preimage(origin, encoded_proposal: Vec<u8>) {
+			let who = ensure_signed(origin)?;
+			let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
+			ensure!(!<Preimages<T>>::exists(&proposal_hash), "preimage already noted");
+
+			let deposit = <BalanceOf<T>>::from(encoded_proposal.len() as u32)
+				.saturating_mul(T::PreimageByteDeposit::get());
+			T::Currency::reserve(&who, deposit)?;
+
+			let now = <system::Module<T>>::block_number();
+			<Preimages<T>>::insert(proposal_hash, (encoded_proposal, who.clone(), deposit, now));
+
+			Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, deposit));
+		}
+
+		/// Register the preimage for an upcoming proposal. This requires the proposal to be
+		/// in the dispatch queue. No deposit is needed.
+		#[weight = SimpleDispatchInfo::FixedNormal(100_000)]
+		fn note_imminent_preimage(origin,
+			encoded_proposal: Vec<u8>,
+			when: T::BlockNumber,
+			which: u32
+		) {
+			let who = ensure_signed(origin)?;
+			let proposal_hash = T::Hashing::hash(&encoded_proposal[..]);
+			ensure!(!<Preimages<T>>::exists(&proposal_hash), "preimage already noted");
+			let queue = <DispatchQueue<T>>::get(when);
+			let item = queue.get(which as usize).and_then(|x| x.as_ref())
+				.ok_or("dispatch queue entry not found")?;
+			ensure!(item.0 == proposal_hash, "dispatch queue entry invalid");
+
+			let now = <system::Module<T>>::block_number();
+			<Preimages<T>>::insert(proposal_hash, (encoded_proposal, who.clone(), <BalanceOf<T>>::zero(), now));
+
+			Self::deposit_event(RawEvent::PreimageNoted(proposal_hash, who, Zero::zero()));
+		}
+
+		/// Remove an expired proposal preimage and collect the deposit.
+		#[weight = SimpleDispatchInfo::FixedNormal(10_000)]
+		fn reap_preimage(origin, proposal_hash: T::Hash) {
+			let who = ensure_signed(origin)?;
+
+			if let Some((_, old, deposit, then)) = <Preimages<T>>::get(&proposal_hash) {
+				let now = <system::Module<T>>::block_number();
+				if now >= then + T::EnactmentPeriod::get() + T::VotingPeriod::get() {
+					// allowed to claim the deposit.
+					let _ = T::Currency::repatriate_reserved(&old, &who, deposit);
+					<Preimages<T>>::remove(&proposal_hash);
+					Self::deposit_event(RawEvent::PreimageReaped(proposal_hash, old, deposit, who));
+				}
+			}
+		}
 	}
 }
 
@@ -661,7 +761,7 @@ impl<T: Trait> Module<T> {
 
 	/// Get all referenda currently active.
 	pub fn active_referenda()
-		-> Vec<(ReferendumIndex, ReferendumInfo<T::BlockNumber, T::Proposal>)>
+		-> Vec<(ReferendumIndex, ReferendumInfo<T::BlockNumber, T::Hash>)>
 	{
 		let next = Self::next_tally();
 		let last = Self::referendum_count();
@@ -673,7 +773,7 @@ impl<T: Trait> Module<T> {
 	/// Get all referenda ready for tally at block `n`.
 	pub fn maturing_referenda_at(
 		n: T::BlockNumber
-	) -> Vec<(ReferendumIndex, ReferendumInfo<T::BlockNumber, T::Proposal>)> {
+	) -> Vec<(ReferendumIndex, ReferendumInfo<T::BlockNumber, T::Hash>)> {
 		let next = Self::next_tally();
 		let last = Self::referendum_count();
 		(next..last).into_iter()
@@ -764,13 +864,13 @@ impl<T: Trait> Module<T> {
 
 	/// Start a referendum.
 	pub fn internal_start_referendum(
-		proposal: T::Proposal,
+		proposal_hash: T::Hash,
 		threshold: VoteThreshold,
 		delay: T::BlockNumber
 	) -> result::Result<ReferendumIndex, &'static str> {
 		<Module<T>>::inject_referendum(
 			<system::Module<T>>::block_number() + T::VotingPeriod::get(),
-			proposal,
+			proposal_hash,
 			threshold,
 			delay
 		)
@@ -797,7 +897,7 @@ impl<T: Trait> Module<T> {
 	/// Start a referendum
 	fn inject_referendum(
 		end: T::BlockNumber,
-		proposal: T::Proposal,
+		proposal_hash: T::Hash,
 		threshold: VoteThreshold,
 		delay: T::BlockNumber,
 	) -> result::Result<ReferendumIndex, &'static str> {
@@ -811,7 +911,7 @@ impl<T: Trait> Module<T> {
 		}
 
 		ReferendumCount::put(ref_index + 1);
-		let item = ReferendumInfo { end, proposal, threshold, delay };
+		let item = ReferendumInfo { end, proposal_hash, threshold, delay };
 		<ReferendumInfoOf<T>>::insert(ref_index, item);
 		Self::deposit_event(RawEvent::Started(ref_index, threshold));
 		Ok(ref_index)
@@ -827,9 +927,25 @@ impl<T: Trait> Module<T> {
 	}
 
 	/// Enact a proposal from a referendum.
-	fn enact_proposal(proposal: T::Proposal, index: ReferendumIndex) {
-		let ok = proposal.dispatch(system::RawOrigin::Root.into()).is_ok();
-		Self::deposit_event(RawEvent::Executed(index, ok));
+	fn enact_proposal(proposal_hash: T::Hash, index: ReferendumIndex) -> Result {
+		if let Some((encoded_proposal, who, amount, _)) = <Preimages<T>>::take(&proposal_hash) {
+			if let Ok(proposal) = T::Proposal::decode(&mut &encoded_proposal[..]) {
+				let _ = T::Currency::unreserve(&who, amount);
+				Self::deposit_event(RawEvent::PreimageUsed(proposal_hash, who, amount));
+
+				let ok = proposal.dispatch(system::RawOrigin::Root.into()).is_ok();
+				Self::deposit_event(RawEvent::Executed(index, ok));
+
+				Ok(())
+			} else {
+				T::Slash::on_unbalanced(T::Currency::slash_reserved(&who, amount).0);
+				Self::deposit_event(RawEvent::PreimageInvalid(proposal_hash, index));
+				Err("invalid preimage")
+			}
+		} else {
+			Self::deposit_event(RawEvent::PreimageMissing(proposal_hash, index));
+			Err("missing preimage")
+		}
 	}
 
 	/// Table the next waiting proposal for a vote.
@@ -892,7 +1008,7 @@ impl<T: Trait> Module<T> {
 	fn bake_referendum(
 		now: T::BlockNumber,
 		index: ReferendumIndex,
-		info: ReferendumInfo<T::BlockNumber, T::Proposal>
+		info: ReferendumInfo<T::BlockNumber, T::Hash>
 	) -> Result {
 		let (approve, against, capital) = Self::tally(index);
 		let total_issuance = T::Currency::total_issuance();
@@ -924,11 +1040,11 @@ impl<T: Trait> Module<T> {
 		if approved {
 			Self::deposit_event(RawEvent::Passed(index));
 			if info.delay.is_zero() {
-				Self::enact_proposal(info.proposal, index);
+				let _ = Self::enact_proposal(info.proposal_hash, index);
 			} else {
 				<DispatchQueue<T>>::append_or_insert(
 					now + info.delay,
-					&[Some((info.proposal, index))][..]
+					&[Some((info.proposal_hash, index))][..]
 				);
 			}
 		} else {
@@ -940,8 +1056,7 @@ impl<T: Trait> Module<T> {
 	}
 
 	/// Current era is ending; we should finish up any proposals.
-	// TODO: move to initialize_block #2779
-	fn end_block(now: T::BlockNumber) -> Result {
+	fn begin_block(now: T::BlockNumber) -> Result {
 		// pick out another public referendum if it's time.
 		if (now % T::LaunchPeriod::get()).is_zero() {
 			// Errors come from the queue being empty. we don't really care about that, and even if
@@ -954,8 +1069,8 @@ impl<T: Trait> Module<T> {
 			Self::bake_referendum(now, index, info)?;
 		}
 
-		for (proposal, index) in <DispatchQueue<T>>::take(now).into_iter().filter_map(|x| x) {
-			Self::enact_proposal(proposal, index);
+		for (proposal_hash, index) in <DispatchQueue<T>>::take(now).into_iter().filter_map(|x| x) {
+			let _ = Self::enact_proposal(proposal_hash, index);
 		}
 		Ok(())
 	}
@@ -970,6 +1085,7 @@ impl<T: Trait> OnFreeBalanceZero<T::AccountId> for Module<T> {
 #[cfg(test)]
 mod tests {
 	use super::*;
+	use std::cell::RefCell;
 	use support::{
 		impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types,
 		traits::Contains,
@@ -1057,6 +1173,13 @@ mod tests {
 			*n >= 1 && *n <= 5
 		}
 	}
+	thread_local! {
+		static PREIMAGE_BYTE_DEPOSIT: RefCell<u64> = RefCell::new(0);
+	}
+	pub struct PreimageByteDeposit;
+	impl Get<u64> for PreimageByteDeposit {
+		fn get() -> u64 { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow()) }
+	}
 	impl super::Trait for Test {
 		type Proposal = Call;
 		type Event = ();
@@ -1073,6 +1196,8 @@ mod tests {
 		type CancellationOrigin = EnsureSignedBy<Four, u64>;
 		type VetoOrigin = EnsureSignedBy<OneToFive, u64>;
 		type CooloffPeriod = CooloffPeriod;
+		type PreimageByteDeposit = PreimageByteDeposit;
+		type Slash = ();
 	}
 
 	fn new_test_ext() -> runtime_io::TestExternalities {
@@ -1098,21 +1223,43 @@ mod tests {
 		});
 	}
 
-	fn set_balance_proposal(value: u64) -> Call {
-		Call::Balances(balances::Call::set_balance(42, value, 0))
+	fn set_balance_proposal(value: u64) -> Vec<u8> {
+		Call::Balances(balances::Call::set_balance(42, value, 0)).encode()
+	}
+
+	fn set_balance_proposal_hash(value: u64) -> H256 {
+		BlakeTwo256::hash(&set_balance_proposal(value)[..])
+	}
+
+	fn set_balance_proposal_hash_and_note(value: u64) -> H256 {
+		let p = set_balance_proposal(value);
+		let h = BlakeTwo256::hash(&p[..]);
+		match Democracy::note_preimage(Origin::signed(6), p) {
+			Ok(_) | Err("preimage already noted") => (),
+			Err(x) => panic!(x),
+		}
+		h
 	}
 
 	fn propose_set_balance(who: u64, value: u64, delay: u64) -> super::Result {
 		Democracy::propose(
 			Origin::signed(who),
-			Box::new(set_balance_proposal(value)),
+			set_balance_proposal_hash(value),
+			delay
+		)
+	}
+
+	fn propose_set_balance_and_note(who: u64, value: u64, delay: u64) -> super::Result {
+		Democracy::propose(
+			Origin::signed(who),
+			set_balance_proposal_hash_and_note(value),
 			delay
 		)
 	}
 
 	fn next_block() {
-		assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
 		System::set_block_number(System::block_number() + 1);
+		assert_eq!(Democracy::begin_block(System::block_number()), Ok(()));
 	}
 
 	fn fast_forward_to(n: u64) {
@@ -1121,24 +1268,104 @@ mod tests {
 		}
 	}
 
+	#[test]
+	fn missing_preimage_should_fail() {
+		new_test_ext().execute_with(|| {
+			System::set_block_number(1);
+			let r = Democracy::inject_referendum(
+				2,
+				set_balance_proposal_hash(2),
+				VoteThreshold::SuperMajorityApprove,
+				0
+			).unwrap();
+			assert_ok!(Democracy::vote(Origin::signed(1), r, AYE));
+
+			next_block();
+			next_block();
+
+			assert_eq!(Balances::free_balance(&42), 0);
+		});
+	}
+
+	#[test]
+	fn preimage_deposit_should_be_required_and_returned() {
+		new_test_ext().execute_with(|| {
+			System::set_block_number(1);
+			// fee of 100 is too much.
+			PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 100);
+			assert_noop!(
+				Democracy::note_preimage(Origin::signed(6), vec![0; 500]),
+				"not enough free funds"
+			);
+			// fee of 1 is reasonable.
+			PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1);
+			let r = Democracy::inject_referendum(
+				2,
+				set_balance_proposal_hash_and_note(2),
+				VoteThreshold::SuperMajorityApprove,
+				0
+			).unwrap();
+			assert_ok!(Democracy::vote(Origin::signed(1), r, AYE));
+
+			assert_eq!(Balances::reserved_balance(6), 12);
+
+			next_block();
+			next_block();
+
+			assert_eq!(Balances::reserved_balance(6), 0);
+			assert_eq!(Balances::free_balance(6), 60);
+			assert_eq!(Balances::free_balance(42), 2);
+		});
+	}
+
+	#[test]
+	fn noting_imminent_preimage_for_free_should_work() {
+		new_test_ext().execute_with(|| {
+			System::set_block_number(1);
+			PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow_mut() = 1);
+
+			let r = Democracy::inject_referendum(
+				2,
+				set_balance_proposal_hash(2),
+				VoteThreshold::SuperMajorityApprove,
+				1
+			).unwrap();
+			assert_ok!(Democracy::vote(Origin::signed(1), r, AYE));
+
+			assert_noop!(
+				Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2), 3, 0),
+				"dispatch queue entry not found"
+			);
+
+			next_block();
+
+			// Now we're in the dispatch queue it's all good.
+			assert_ok!(Democracy::note_imminent_preimage(Origin::signed(7), set_balance_proposal(2), 3, 0));
+
+			next_block();
+
+			assert_eq!(Balances::free_balance(42), 2);
+		});
+	}
+
 	#[test]
 	fn external_and_public_interleaving_works() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(1)),
+				set_balance_proposal_hash_and_note(1),
 			));
-			assert_ok!(propose_set_balance(6, 2, 2));
+			assert_ok!(propose_set_balance_and_note(6, 2, 2));
 
-			fast_forward_to(1);
+			fast_forward_to(2);
 
 			// both waiting: external goes first.
 			assert_eq!(
 				Democracy::referendum_info(0),
 				Some(ReferendumInfo {
-					end: 2,
-					proposal: set_balance_proposal(1),
+					end: 4,
+					proposal_hash: set_balance_proposal_hash_and_note(1),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
@@ -1146,31 +1373,31 @@ mod tests {
 			// replenish external
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(3)),
+				set_balance_proposal_hash_and_note(3),
 			));
 
-			fast_forward_to(3);
+			fast_forward_to(4);
 
 			// both waiting: public goes next.
 			assert_eq!(
 				Democracy::referendum_info(1),
 				Some(ReferendumInfo {
-					end: 4,
-					proposal: set_balance_proposal(2),
+					end: 6,
+					proposal_hash: set_balance_proposal_hash_and_note(2),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
 			);
 			// don't replenish public
 
-			fast_forward_to(5);
+			fast_forward_to(6);
 
 			// it's external "turn" again, though since public is empty that doesn't really matter
 			assert_eq!(
 				Democracy::referendum_info(2),
 				Some(ReferendumInfo {
-					end: 6,
-					proposal: set_balance_proposal(3),
+					end: 8,
+					proposal_hash: set_balance_proposal_hash_and_note(3),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
@@ -1178,17 +1405,17 @@ mod tests {
 			// replenish external
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(5)),
+				set_balance_proposal_hash_and_note(5),
 			));
 
-			fast_forward_to(7);
+			fast_forward_to(8);
 
 			// external goes again because there's no public waiting.
 			assert_eq!(
 				Democracy::referendum_info(3),
 				Some(ReferendumInfo {
-					end: 8,
-					proposal: set_balance_proposal(5),
+					end: 10,
+					proposal_hash: set_balance_proposal_hash_and_note(5),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
@@ -1196,36 +1423,36 @@ mod tests {
 			// replenish both
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(7)),
+				set_balance_proposal_hash_and_note(7),
 			));
-			assert_ok!(propose_set_balance(6, 4, 2));
+			assert_ok!(propose_set_balance_and_note(6, 4, 2));
 
-			fast_forward_to(9);
+			fast_forward_to(10);
 
 			// public goes now since external went last time.
 			assert_eq!(
 				Democracy::referendum_info(4),
 				Some(ReferendumInfo {
-					end: 10,
-					proposal: set_balance_proposal(4),
+					end: 12,
+					proposal_hash: set_balance_proposal_hash_and_note(4),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
 			);
 			// replenish public again
-			assert_ok!(propose_set_balance(6, 6, 2));
+			assert_ok!(propose_set_balance_and_note(6, 6, 2));
 			// cancel external
-			let h = BlakeTwo256::hash_of(&set_balance_proposal(7));
+			let h = set_balance_proposal_hash_and_note(7);
 			assert_ok!(Democracy::veto_external(Origin::signed(3), h));
 
-			fast_forward_to(11);
+			fast_forward_to(12);
 
 			// public goes again now since there's no external waiting.
 			assert_eq!(
 				Democracy::referendum_info(5),
 				Some(ReferendumInfo {
-					end: 12,
-					proposal: set_balance_proposal(6),
+					end: 14,
+					proposal_hash: set_balance_proposal_hash_and_note(6),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
@@ -1240,7 +1467,7 @@ mod tests {
 			System::set_block_number(0);
 			let r = Democracy::inject_referendum(
 				2,
-				set_balance_proposal(2),
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				2
 			).unwrap();
@@ -1254,7 +1481,7 @@ mod tests {
 
 			let r = Democracy::inject_referendum(
 				2,
-				set_balance_proposal(2),
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				2
 			).unwrap();
@@ -1269,32 +1496,32 @@ mod tests {
 			System::set_block_number(0);
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(2)),
+				set_balance_proposal_hash_and_note(2),
 			));
 			assert!(<NextExternal<Test>>::exists());
 
-			let h = BlakeTwo256::hash_of(&set_balance_proposal(2));
+			let h = set_balance_proposal_hash_and_note(2);
 			assert_ok!(Democracy::veto_external(Origin::signed(3), h.clone()));
 			// cancelled.
 			assert!(!<NextExternal<Test>>::exists());
 			// fails - same proposal can't be resubmitted.
 			assert_noop!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(2)),
+				set_balance_proposal_hash(2),
 			), "proposal still blacklisted");
 
 			fast_forward_to(1);
 			// fails as we're still in cooloff period.
 			assert_noop!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(2)),
+				set_balance_proposal_hash(2),
 			), "proposal still blacklisted");
 
 			fast_forward_to(2);
 			// works; as we're out of the cooloff period.
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(2)),
+				set_balance_proposal_hash_and_note(2),
 			));
 			assert!(<NextExternal<Test>>::exists());
 
@@ -1313,12 +1540,12 @@ mod tests {
 			// same proposal fails as we're still in cooloff
 			assert_noop!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(2)),
+				set_balance_proposal_hash(2),
 			), "proposal still blacklisted");
 			// different proposal works fine.
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(3)),
+				set_balance_proposal_hash_and_note(3),
 			));
 		});
 	}
@@ -1329,22 +1556,22 @@ mod tests {
 			System::set_block_number(0);
 			assert_noop!(Democracy::external_propose(
 				Origin::signed(1),
-				Box::new(set_balance_proposal(2)),
+				set_balance_proposal_hash(2),
 			), "Invalid origin");
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(2)),
+				set_balance_proposal_hash_and_note(2),
 			));
 			assert_noop!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(1)),
+				set_balance_proposal_hash(1),
 			), "proposal already made");
-			fast_forward_to(1);
+			fast_forward_to(2);
 			assert_eq!(
 				Democracy::referendum_info(0),
 				Some(ReferendumInfo {
-					end: 2,
-					proposal: set_balance_proposal(2),
+					end: 4,
+					proposal_hash: set_balance_proposal_hash(2),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
@@ -1358,18 +1585,18 @@ mod tests {
 			System::set_block_number(0);
 			assert_noop!(Democracy::external_propose_majority(
 				Origin::signed(1),
-				Box::new(set_balance_proposal(2))
+				set_balance_proposal_hash(2)
 			), "Invalid origin");
 			assert_ok!(Democracy::external_propose_majority(
 				Origin::signed(3),
-				Box::new(set_balance_proposal(2))
+				set_balance_proposal_hash_and_note(2)
 			));
-			fast_forward_to(1);
+			fast_forward_to(2);
 			assert_eq!(
 				Democracy::referendum_info(0),
 				Some(ReferendumInfo {
-					end: 2,
-					proposal: set_balance_proposal(2),
+					end: 4,
+					proposal_hash: set_balance_proposal_hash(2),
 					threshold: VoteThreshold::SimpleMajority,
 					delay: 2,
 				})
@@ -1383,18 +1610,18 @@ mod tests {
 			System::set_block_number(0);
 			assert_noop!(Democracy::external_propose_default(
 				Origin::signed(3),
-				Box::new(set_balance_proposal(2))
+				set_balance_proposal_hash(2)
 			), "Invalid origin");
 			assert_ok!(Democracy::external_propose_default(
 				Origin::signed(1),
-				Box::new(set_balance_proposal(2))
+				set_balance_proposal_hash_and_note(2)
 			));
-			fast_forward_to(1);
+			fast_forward_to(2);
 			assert_eq!(
 				Democracy::referendum_info(0),
 				Some(ReferendumInfo {
-					end: 2,
-					proposal: set_balance_proposal(2),
+					end: 4,
+					proposal_hash: set_balance_proposal_hash(2),
 					threshold: VoteThreshold::SuperMajorityAgainst,
 					delay: 2,
 				})
@@ -1406,11 +1633,11 @@ mod tests {
 	fn fast_track_referendum_works() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
-			let h = BlakeTwo256::hash_of(&set_balance_proposal(2));
+			let h = set_balance_proposal_hash_and_note(2);
 			assert_noop!(Democracy::fast_track(Origin::signed(5), h, 3, 2), "no proposal made");
 			assert_ok!(Democracy::external_propose_majority(
 				Origin::signed(3),
-				Box::new(set_balance_proposal(2))
+				set_balance_proposal_hash_and_note(2)
 			));
 			assert_noop!(Democracy::fast_track(Origin::signed(1), h, 3, 2), "Invalid origin");
 			assert_ok!(Democracy::fast_track(Origin::signed(5), h, 0, 0));
@@ -1418,7 +1645,7 @@ mod tests {
 				Democracy::referendum_info(0),
 				Some(ReferendumInfo {
 					end: 1,
-					proposal: set_balance_proposal(2),
+					proposal_hash: set_balance_proposal_hash_and_note(2),
 					threshold: VoteThreshold::SimpleMajority,
 					delay: 0,
 				})
@@ -1430,10 +1657,10 @@ mod tests {
 	fn fast_track_referendum_fails_when_no_simple_majority() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
-			let h = BlakeTwo256::hash_of(&set_balance_proposal(2));
+			let h = set_balance_proposal_hash_and_note(2);
 			assert_ok!(Democracy::external_propose(
 				Origin::signed(2),
-				Box::new(set_balance_proposal(2))
+				set_balance_proposal_hash_and_note(2)
 			));
 			assert_noop!(
 				Democracy::fast_track(Origin::signed(5), h, 3, 2),
@@ -1446,9 +1673,9 @@ mod tests {
 	fn locked_for_should_work() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
-			assert_ok!(propose_set_balance(1, 2, 2));
-			assert_ok!(propose_set_balance(1, 4, 4));
-			assert_ok!(propose_set_balance(1, 3, 3));
+			assert_ok!(propose_set_balance_and_note(1, 2, 2));
+			assert_ok!(propose_set_balance_and_note(1, 4, 4));
+			assert_ok!(propose_set_balance_and_note(1, 3, 3));
 			assert_eq!(Democracy::locked_for(0), Some(2));
 			assert_eq!(Democracy::locked_for(1), Some(4));
 			assert_eq!(Democracy::locked_for(2), Some(3));
@@ -1459,11 +1686,11 @@ mod tests {
 	fn single_proposal_should_work() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 			assert!(Democracy::referendum_info(0).is_none());
 
-			// end of 0 => next referendum scheduled.
-			fast_forward_to(1);
+			// start of 2 => next referendum scheduled.
+			fast_forward_to(2);
 
 			let r = 0;
 			assert_ok!(Democracy::vote(Origin::signed(1), r, AYE));
@@ -1472,8 +1699,8 @@ mod tests {
 			assert_eq!(
 				Democracy::referendum_info(0),
 				Some(ReferendumInfo {
-					end: 2,
-					proposal: set_balance_proposal(2),
+					end: 4,
+					proposal_hash: set_balance_proposal_hash_and_note(2),
 					threshold: VoteThreshold::SuperMajorityApprove,
 					delay: 2
 				})
@@ -1482,21 +1709,21 @@ mod tests {
 			assert_eq!(Democracy::vote_of((r, 1)), AYE);
 			assert_eq!(Democracy::tally(r), (1, 0, 1));
 
-			fast_forward_to(2);
+			fast_forward_to(3);
 
 			// referendum still running
 			assert!(Democracy::referendum_info(0).is_some());
 
-			// referendum runs during 1 and 2, ends @ end of 2.
-			fast_forward_to(3);
+			// referendum runs during 2 and 3, ends @ start of 4.
+			fast_forward_to(4);
 
 			assert!(Democracy::referendum_info(0).is_none());
-			assert_eq!(Democracy::dispatch_queue(4), vec![
-				Some((set_balance_proposal(2), 0))
+			assert_eq!(Democracy::dispatch_queue(6), vec![
+				Some((set_balance_proposal_hash_and_note(2), 0))
 			]);
 
 			// referendum passes and wait another two blocks for enactment.
-			fast_forward_to(5);
+			fast_forward_to(6);
 
 			assert_eq!(Balances::free_balance(&42), 2);
 		});
@@ -1506,23 +1733,23 @@ mod tests {
 	fn cancel_queued_should_work() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 
-			// end of 0 => next referendum scheduled.
-			fast_forward_to(1);
+			// start of 2 => next referendum scheduled.
+			fast_forward_to(2);
 
 			assert_ok!(Democracy::vote(Origin::signed(1), 0, AYE));
 
-			fast_forward_to(3);
+			fast_forward_to(4);
 
-			assert_eq!(Democracy::dispatch_queue(4), vec![
-				Some((set_balance_proposal(2), 0))
+			assert_eq!(Democracy::dispatch_queue(6), vec![
+				Some((set_balance_proposal_hash_and_note(2), 0))
 			]);
 
-			assert_noop!(Democracy::cancel_queued(Origin::ROOT, 3, 0, 0), "proposal not found");
-			assert_noop!(Democracy::cancel_queued(Origin::ROOT, 4, 1, 0), "proposal not found");
-			assert_ok!(Democracy::cancel_queued(Origin::ROOT, 4, 0, 0));
-			assert_eq!(Democracy::dispatch_queue(4), vec![None]);
+			assert_noop!(Democracy::cancel_queued(Origin::ROOT, 5, 0, 0), "proposal not found");
+			assert_noop!(Democracy::cancel_queued(Origin::ROOT, 6, 1, 0), "proposal not found");
+			assert_ok!(Democracy::cancel_queued(Origin::ROOT, 6, 0, 0));
+			assert_eq!(Democracy::dispatch_queue(6), vec![None]);
 		});
 	}
 
@@ -1560,9 +1787,9 @@ mod tests {
 	fn single_proposal_should_work_with_proxy() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 
-			fast_forward_to(1);
+			fast_forward_to(2);
 			let r = 0;
 			assert_ok!(Democracy::set_proxy(Origin::signed(1), 10));
 			assert_ok!(Democracy::proxy_vote(Origin::signed(10), r, AYE));
@@ -1571,7 +1798,7 @@ mod tests {
 			assert_eq!(Democracy::vote_of((r, 1)), AYE);
 			assert_eq!(Democracy::tally(r), (1, 0, 1));
 
-			fast_forward_to(5);
+			fast_forward_to(6);
 			assert_eq!(Balances::free_balance(&42), 2);
 		});
 	}
@@ -1581,9 +1808,9 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
 
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 
-			fast_forward_to(1);
+			fast_forward_to(2);
 
 			// Delegate vote.
 			assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value()));
@@ -1595,7 +1822,7 @@ mod tests {
 			// Delegated vote is counted.
 			assert_eq!(Democracy::tally(r), (3, 0, 3));
 
-			fast_forward_to(5);
+			fast_forward_to(6);
 
 			assert_eq!(Balances::free_balance(&42), 2);
 		});
@@ -1606,9 +1833,9 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
 
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 
-			fast_forward_to(1);
+			fast_forward_to(2);
 
 			// Check behavior with cycle.
 			assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value()));
@@ -1621,7 +1848,7 @@ mod tests {
 			// Delegated vote is counted.
 			assert_eq!(Democracy::tally(r), (6, 0, 6));
 
-			fast_forward_to(5);
+			fast_forward_to(6);
 
 			assert_eq!(Balances::free_balance(&42), 2);
 		});
@@ -1633,9 +1860,9 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
 
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 
-			fast_forward_to(1);
+			fast_forward_to(2);
 
 			let r = 0;
 			assert_ok!(Democracy::vote(Origin::signed(1), r, AYE));
@@ -1648,7 +1875,7 @@ mod tests {
 			// Delegated vote is not counted.
 			assert_eq!(Democracy::tally(r), (3, 0, 3));
 
-			fast_forward_to(5);
+			fast_forward_to(6);
 
 			assert_eq!(Balances::free_balance(&42), 2);
 		});
@@ -1659,13 +1886,13 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
 
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 
 			// Delegate and undelegate vote.
 			assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::max_value()));
 			assert_ok!(Democracy::undelegate(Origin::signed(2)));
 
-			fast_forward_to(1);
+			fast_forward_to(2);
 			let r = 0;
 			assert_ok!(Democracy::vote(Origin::signed(1), r, AYE));
 
@@ -1676,7 +1903,7 @@ mod tests {
 			// Delegated vote is not counted.
 			assert_eq!(Democracy::tally(r), (1, 0, 1));
 
-			fast_forward_to(5);
+			fast_forward_to(6);
 
 			assert_eq!(Balances::free_balance(&42), 2);
 		});
@@ -1688,9 +1915,9 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
 
-			assert_ok!(propose_set_balance(1, 2, 1));
+			assert_ok!(propose_set_balance_and_note(1, 2, 1));
 
-			fast_forward_to(1);
+			fast_forward_to(2);
 			let r = 0;
 
 			assert_ok!(Democracy::vote(Origin::signed(1), r, AYE));
@@ -1708,7 +1935,7 @@ mod tests {
 			// Delegated vote is not counted.
 			assert_eq!(Democracy::tally(r), (3, 0, 3));
 
-			fast_forward_to(5);
+			fast_forward_to(6);
 
 			assert_eq!(Balances::free_balance(&42), 2);
 		});
@@ -1718,7 +1945,7 @@ mod tests {
 	fn deposit_for_proposals_should_be_taken() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
-			assert_ok!(propose_set_balance(1, 2, 5));
+			assert_ok!(propose_set_balance_and_note(1, 2, 5));
 			assert_ok!(Democracy::second(Origin::signed(2), 0));
 			assert_ok!(Democracy::second(Origin::signed(5), 0));
 			assert_ok!(Democracy::second(Origin::signed(5), 0));
@@ -1733,7 +1960,7 @@ mod tests {
 	fn deposit_for_proposals_should_be_returned() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
-			assert_ok!(propose_set_balance(1, 2, 5));
+			assert_ok!(propose_set_balance_and_note(1, 2, 5));
 			assert_ok!(Democracy::second(Origin::signed(2), 0));
 			assert_ok!(Democracy::second(Origin::signed(5), 0));
 			assert_ok!(Democracy::second(Origin::signed(5), 0));
@@ -1765,7 +1992,7 @@ mod tests {
 	fn poor_seconder_should_not_work() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
-			assert_ok!(propose_set_balance(2, 2, 11));
+			assert_ok!(propose_set_balance_and_note(2, 2, 11));
 			assert_noop!(Democracy::second(Origin::signed(1), 0), "seconder\'s balance too low");
 		});
 	}
@@ -1774,14 +2001,14 @@ mod tests {
 	fn runners_up_should_come_after() {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
-			assert_ok!(propose_set_balance(1, 2, 2));
-			assert_ok!(propose_set_balance(1, 4, 4));
-			assert_ok!(propose_set_balance(1, 3, 3));
-			fast_forward_to(1);
+			assert_ok!(propose_set_balance_and_note(1, 2, 2));
+			assert_ok!(propose_set_balance_and_note(1, 4, 4));
+			assert_ok!(propose_set_balance_and_note(1, 3, 3));
+			fast_forward_to(2);
 			assert_ok!(Democracy::vote(Origin::signed(1), 0, AYE));
-			fast_forward_to(3);
+			fast_forward_to(4);
 			assert_ok!(Democracy::vote(Origin::signed(1), 1, AYE));
-			fast_forward_to(5);
+			fast_forward_to(6);
 			assert_ok!(Democracy::vote(Origin::signed(1), 2, AYE));
 		});
 	}
@@ -1791,8 +2018,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
@@ -1814,8 +2041,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
@@ -1834,8 +2061,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
@@ -1857,11 +2084,12 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
+
 			assert_ok!(Democracy::vote(Origin::signed(1), r, BIG_AYE));
 			assert_ok!(Democracy::vote(Origin::signed(2), r, BIG_NAY));
 			assert_ok!(Democracy::vote(Origin::signed(3), r, BIG_NAY));
@@ -1883,8 +2111,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				1
 			).unwrap();
@@ -1911,8 +2139,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
@@ -1936,8 +2164,8 @@ mod tests {
 
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
@@ -1959,8 +2187,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(0);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
@@ -1993,19 +2221,19 @@ mod tests {
 			assert_eq!(Balances::locks(2), vec![BalanceLock {
 				id: DEMOCRACY_ID,
 				amount: u64::max_value(),
-				until: 17,
+				until: 18,
 				reasons: WithdrawReason::Transfer.into()
 			}]);
 			assert_eq!(Balances::locks(3), vec![BalanceLock {
 				id: DEMOCRACY_ID,
 				amount: u64::max_value(),
-				until: 9,
+				until: 10,
 				reasons: WithdrawReason::Transfer.into()
 			}]);
 			assert_eq!(Balances::locks(4), vec![BalanceLock {
 				id: DEMOCRACY_ID,
 				amount: u64::max_value(),
-				until: 5,
+				until: 6,
 				reasons: WithdrawReason::Transfer.into()
 			}]);
 			assert_eq!(Balances::locks(5), vec![]);
@@ -2019,8 +2247,8 @@ mod tests {
 		new_test_ext().execute_with(|| {
 			System::set_block_number(1);
 			let r = Democracy::inject_referendum(
-				1,
-				set_balance_proposal(2),
+				2,
+				set_balance_proposal_hash_and_note(2),
 				VoteThreshold::SuperMajorityApprove,
 				0
 			).unwrap();
-- 
GitLab