diff --git a/node/src/service.rs b/node/src/service.rs index a403a0d2..138ac420 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -253,7 +253,7 @@ async fn start_node_impl( config: parachain_config, keystore: params.keystore_container.keystore(), backend, - network: network.clone(), + network, sync_service: sync_service.clone(), system_rpc_tx, tx_handler_controller, @@ -318,7 +318,7 @@ async fn start_node_impl( &task_manager, relay_chain_interface.clone(), transaction_pool, - sync_service.clone(), + sync_service, params.keystore_container.keystore(), relay_chain_slot_duration, para_id, @@ -395,7 +395,7 @@ fn start_consensus( client.clone(), transaction_pool, prometheus_registry, - telemetry.clone(), + telemetry, ); let proposer = Proposer::new(proposer_factory); diff --git a/pallets/disputes/src/lib.rs b/pallets/disputes/src/lib.rs index f5eb3566..1fc8ccb9 100644 --- a/pallets/disputes/src/lib.rs +++ b/pallets/disputes/src/lib.rs @@ -442,6 +442,11 @@ pub mod pallet { } } + #[derive(Clone, Copy, PartialEq, Debug, Encode, Decode, TypeInfo)] + pub struct DisputeVotes { + pub votes: T, + } + #[derive(Clone, Copy, PartialEq, Debug, Encode, Decode, TypeInfo)] pub enum DisputeResult { Success = 0, diff --git a/pallets/grants/src/lib.rs b/pallets/grants/src/lib.rs index 27f5cf3c..38cce62d 100644 --- a/pallets/grants/src/lib.rs +++ b/pallets/grants/src/lib.rs @@ -131,7 +131,7 @@ pub mod pallet { ); let mut contributions = BTreeMap::new(); - let _ = assigned_approvers.iter().for_each(|approver_id| { + assigned_approvers.iter().for_each(|approver_id| { contributions.insert( approver_id.clone(), Contribution { diff --git a/pallets/grants/src/mock.rs b/pallets/grants/src/mock.rs index 9b295952..277c76b9 100644 --- a/pallets/grants/src/mock.rs +++ b/pallets/grants/src/mock.rs @@ -247,10 +247,10 @@ impl pallet_disputes::traits::DisputeRaiser for MockDisputeRaiser { type MaxJurySize = MaxJuryMembers; type MaxSpecifics = MaxMilestonesPerProject; fn raise_dispute( - dispute_key: Self::DisputeKey, - raised_by: AccountId, - jury: BoundedVec, - specific_ids: BoundedVec, + _dispute_key: Self::DisputeKey, + _raised_by: AccountId, + _jury: BoundedVec, + _specific_ids: BoundedVec, ) -> Result<(), DispatchError> { Ok(()) } diff --git a/pallets/proposals/rpc/runtime-api/src/lib.rs b/pallets/proposals/rpc/runtime-api/src/lib.rs index e3643b21..2c25bbc5 100644 --- a/pallets/proposals/rpc/runtime-api/src/lib.rs +++ b/pallets/proposals/rpc/runtime-api/src/lib.rs @@ -7,6 +7,6 @@ sp_api::decl_runtime_apis! { where AccountId: codec::Codec + Ord, { fn get_project_account_by_id(project_id: u32) -> AccountId; - fn get_all_project_data(project_id: u32) -> Option<(Vec, Vec)>; + fn get_all_project_data(project_id: u32) -> (Option>, Option>, Option>, Vec); } } diff --git a/pallets/proposals/rpc/src/lib.rs b/pallets/proposals/rpc/src/lib.rs index c8bd2a25..7e09262a 100644 --- a/pallets/proposals/rpc/src/lib.rs +++ b/pallets/proposals/rpc/src/lib.rs @@ -24,7 +24,10 @@ where #[method(name = "proposals_getProjectKitty")] fn project_account_id(&self, project_id: u32) -> RpcResult; #[method(name = "proposals_getAllProjectData")] - fn all_project_data(&self, project_id: u32) -> RpcResult, Vec)>>; + fn all_project_data( + &self, + project_id: u32, + ) -> RpcResult<(Option>, Option>, Option>, Vec)>; } pub struct Proposals { @@ -76,7 +79,10 @@ where api.get_project_account_by_id(at, project_id) .map_err(runtime_error_into_rpc_err) } - fn all_project_data(&self, project_id: u32) -> RpcResult, Vec)>> { + fn all_project_data( + &self, + project_id: u32, + ) -> RpcResult<(Option>, Option>, Option>, Vec)> { let api = self.client.runtime_api(); let at = self.client.info().best_hash; diff --git a/pallets/proposals/src/impls/pallet_impls.rs b/pallets/proposals/src/impls/pallet_impls.rs index a2f26a27..8685fda8 100644 --- a/pallets/proposals/src/impls/pallet_impls.rs +++ b/pallets/proposals/src/impls/pallet_impls.rs @@ -57,6 +57,8 @@ impl Pallet { Ok::<(), DispatchError>(()) })?; + ProjectInVoting::::insert(project_key, milestone_key, ()); + Self::deposit_event(Event::MilestoneSubmitted(who, project_key, milestone_key)); Self::deposit_event(Event::VotingRoundCreated(project_key)); Ok(().into()) @@ -306,25 +308,25 @@ impl Pallet { } pub(crate) fn close_voting_round( - project_key: ProjectKey, + _project_key: ProjectKey, user_has_voted_key: (ProjectKey, RoundType, MilestoneKey), ) -> Result<(), DispatchError> { + let (project_key, _round_type, milestone_key) = user_has_voted_key; // Prevent further voting. - let exp_block = - Rounds::::take((project_key, user_has_voted_key.2), RoundType::VotingRound) - .ok_or(Error::::VotingRoundNotStarted)?; + let exp_block = Rounds::::take((project_key, milestone_key), RoundType::VotingRound) + .ok_or(Error::::VotingRoundNotStarted)?; // Prevent hook from calling. RoundsExpiring::::remove(exp_block); // Allow future votes to occur on this milestone IndividualVoteStore::::try_mutate(project_key, |maybe_individual_votes| { if let Some(individual_votes) = maybe_individual_votes { - individual_votes.clear_milestone_votes(user_has_voted_key.2); + individual_votes.clear_milestone_votes(milestone_key); } else { return Err(Error::::IndividualVoteNotFound.into()); } Ok::<(), DispatchError>(()) })?; - + ProjectInVoting::::remove(project_key, milestone_key); Ok(()) } } diff --git a/pallets/proposals/src/lib.rs b/pallets/proposals/src/lib.rs index 55c74c99..3d25cb29 100644 --- a/pallets/proposals/src/lib.rs +++ b/pallets/proposals/src/lib.rs @@ -210,6 +210,8 @@ pub mod pallet { ValueQuery, >; + // TODO: Check if this is in use. + /// A helper to find what projects / milestones are in a dispute. #[pallet::storage] pub type ProjectsInDispute = StorageMap< _, @@ -219,6 +221,19 @@ pub mod pallet { ValueQuery, >; + /// Projects in Voting round. + /// A helper for the runtime api so we dont have to iterate over the Rounds Double map. + #[pallet::storage] + pub type ProjectInVoting = StorageDoubleMap< + _, + Blake2_128Concat, + ProjectKey, + Blake2_128Concat, + MilestoneKey, + (), + ValueQuery, + >; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { @@ -369,6 +384,8 @@ pub mod pallet { individual_votes.clear_milestone_votes(*milestone_key); } }); + + ProjectInVoting::::remove(project_key, milestone_key); } // Votes of no confidence do not finaliese automatically RoundType::VoteOfNoConfidence => { diff --git a/pallets/proposals/src/test_utils.rs b/pallets/proposals/src/test_utils.rs index 4362be81..f669b915 100644 --- a/pallets/proposals/src/test_utils.rs +++ b/pallets/proposals/src/test_utils.rs @@ -1,8 +1,8 @@ use crate::*; use common_types::CurrencyId; -use frame_support::{assert_ok, BoundedVec}; +use frame_support::BoundedVec; use frame_system::EventRecord; -use orml_traits::{MultiCurrency, MultiReservableCurrency}; +use orml_traits::MultiReservableCurrency; use pallet_disputes::traits::DisputeHooks; use sp_arithmetic::per_things::Percent; @@ -13,6 +13,7 @@ use sp_std::convert::TryInto; #[cfg(feature = "runtime-benchmarks")] use frame_benchmarking::account; +use frame_support::assert_ok; #[cfg(feature = "runtime-benchmarks")] use sp_std::vec::Vec; diff --git a/pallets/proposals/src/tests/pallet.rs b/pallets/proposals/src/tests/pallet.rs index ce730cec..d7b85006 100644 --- a/pallets/proposals/src/tests/pallet.rs +++ b/pallets/proposals/src/tests/pallet.rs @@ -690,8 +690,7 @@ fn withdraw_only_transfers_approved_milestones() { let alice_after = ::MultiCurrency::free_balance(CurrencyId::Native, &ALICE); let expected_fee = ::ImbueFee::get().mul_floor(per_contribution * 2 / 10); // total_contribution / number of milestones - fee - let alice_expected_balance = - alice_before + ((per_contribution * 2 / 10) as u128) - expected_fee as u128; + let alice_expected_balance = alice_before + (per_contribution * 2 / 10) - expected_fee; assert_eq!( alice_after, alice_expected_balance, "Alice account is not the expected balance" @@ -1074,3 +1073,79 @@ fn close_voting_round_works() { .is_empty()); }) } + +#[test] +fn project_in_voting_is_saved_on_submission() { + build_test_externality().execute_with(|| { + let cont = get_contributions::(vec![BOB], 100_000); + let prop_milestones = get_milestones(10); + let project_key = + create_and_fund_project::(ALICE, cont, prop_milestones, CurrencyId::Native) + .unwrap(); + + assert_ok!(Proposals::submit_milestone( + RuntimeOrigin::signed(ALICE), + project_key, + 0 + )); + assert_ok!(Proposals::submit_milestone( + RuntimeOrigin::signed(ALICE), + project_key, + 1 + )); + + assert!(ProjectInVoting::::contains_key(project_key, 0)); + assert!(ProjectInVoting::::contains_key(project_key, 1)); + }) +} + +#[test] +fn project_in_voting_is_removed_on_init_hook() { + build_test_externality().execute_with(|| { + let cont = get_contributions::(vec![BOB], 100_000); + let prop_milestones = get_milestones(10); + let project_key = + create_and_fund_project::(ALICE, cont, prop_milestones, CurrencyId::Native) + .unwrap(); + + assert_ok!(Proposals::submit_milestone( + RuntimeOrigin::signed(ALICE), + project_key, + 0 + )); + + assert!(ProjectInVoting::::contains_key(project_key, 0)); + + run_to_block( + frame_system::Pallet::::block_number() + + ::MilestoneVotingWindow::get(), + ); + + assert!(!ProjectInVoting::::contains_key(project_key, 0)); + }) +} + +#[test] +fn project_in_voting_is_removed_on_milestone_autofinalisation() { + build_test_externality().execute_with(|| { + let cont = get_contributions::(vec![BOB], 100_000); + let prop_milestones = get_milestones(10); + let project_key = + create_and_fund_project::(ALICE, cont, prop_milestones, CurrencyId::Native) + .unwrap(); + + assert_ok!(Proposals::submit_milestone( + RuntimeOrigin::signed(ALICE), + project_key, + 0 + )); + assert!(ProjectInVoting::::contains_key(project_key, 0)); + assert_ok!(Proposals::vote_on_milestone( + RuntimeOrigin::signed(BOB), + project_key, + 0, + true + )); + assert!(!ProjectInVoting::::contains_key(project_key, 0)); + }) +} diff --git a/pallets/proposals/src/tests/refunds.rs b/pallets/proposals/src/tests/refunds.rs index 3b739f25..c61c6dab 100644 --- a/pallets/proposals/src/tests/refunds.rs +++ b/pallets/proposals/src/tests/refunds.rs @@ -273,7 +273,7 @@ fn refund_check_refund_amount() { let charlie_pre_creation = ::MultiCurrency::free_balance(CurrencyId::Native, &CHARLIE); let per_contribution = 100000u128; - let contributions = get_contributions::(vec![BOB, CHARLIE], per_contribution as u128); + let contributions = get_contributions::(vec![BOB, CHARLIE], per_contribution); let milestones = get_milestones(10); let project_key = create_and_fund_project::( ALICE, @@ -331,7 +331,7 @@ fn refund_takes_imbue_fee() { ); let per_contribution = 500000u128; - let contributions = get_contributions::(vec![BOB, CHARLIE], per_contribution as u128); + let contributions = get_contributions::(vec![BOB, CHARLIE], per_contribution); let milestones = get_milestones(10); let project_key = create_and_fund_project::( ALICE, diff --git a/pallets/proposals/src/todo b/pallets/proposals/src/todo deleted file mode 100644 index 23cbd917..00000000 --- a/pallets/proposals/src/todo +++ /dev/null @@ -1,29 +0,0 @@ -raise-dispute extrinsic. - done -tests for above implementation. - done?? check code cov -benchmark for raise dispute extrinsic -done -ALLOW VOTING ON SUBMITTED MILESTONE - done -make sure when raising a dispute you cannot raise it on approved milestones. - done -OnDisputeCompleteHooks. -tests for above implementation. - done check code cov -update change withdraw to uses can_withdraw - done -benchmark for hooks to return weight. - done didnt need, we can do it directly in the method. -removal of old no confidence logic. - done - -fix all tests - done -get jury in each pallet (briefs, grants, crowdfunding.) -update the function call in each pallet (jury, TreasuryOrigin, ) -code cov check - - -initiate refund extrinsic - done -benchmark refund - done -tests! - done -add total_refunded to withdraw extrinsic - done -tests for these - done - -Migration for removing NoConfidenceLogic -Migration removing NoConfidenceRound, - - - - diff --git a/runtime/imbue-kusama/src/lib.rs b/runtime/imbue-kusama/src/lib.rs index 8e364359..7d202698 100644 --- a/runtime/imbue-kusama/src/lib.rs +++ b/runtime/imbue-kusama/src/lib.rs @@ -1208,15 +1208,31 @@ impl_runtime_apis! { ImbueProposals::project_account_id(project_id) } - /// (Project, ImmutableindividualVotes) - fn get_all_project_data(project_key: u32) -> Option<(Vec, Vec)> { - use pallet_proposals::{Project, Projects, ImmutableIndividualVotes, IndividualVoteStore}; - - if let Some(project) = Projects::::get(project_key) { - IndividualVoteStore::::get(project_key).map(|individual_votes| ( as Encode>::encode(&project), as Encode>::encode(&individual_votes))) - } else { - None - } + /// (Project, ImmutableindividualVotes, DisputeVotes, MilestonesInVotingRound) + fn get_all_project_data(project_key: u32) -> (Option>, Option>, Option>, Vec) { + use pallet_proposals::{Project, Projects, ImmutableIndividualVotes, IndividualVoteStore, ProjectInVoting, MilestoneKey}; + use pallet_disputes::{Disputes, DisputeVotes, BoundedVotes}; + + let project_encoded = Projects::::get(project_key).map(|p| as Encode>::encode(&p)); + + let project_votes_encoded = IndividualVoteStore::::get(project_key).map(|i| as Encode>::encode(&i)); + + let dispute_votes_encoded = match Disputes::::get(project_key) { + Some(d) => { + let dispute_votes: DisputeVotes> = DisputeVotes { + votes: d.votes + }; + Some(> as Encode>::encode(&dispute_votes)) + }, + None => {None} + }; + + let milestones_in_voting = ProjectInVoting::::iter_prefix(project_key).map(|(milestone_key, _)|{ + milestone_key + }).collect::>(); + + + (project_encoded, project_votes_encoded, dispute_votes_encoded, milestones_in_voting) } } @@ -1325,7 +1341,7 @@ impl pallet_fellowship::traits::SelectJury