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

feat(platform)!: distribute prefunded specialized balances after vote #2422

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
use crate::error::execution::ExecutionError;
use crate::error::Error;
use crate::platform_types::platform::Platform;
use crate::platform_types::platform_state::v0::PlatformStateV0Methods;
use crate::platform_types::platform_state::PlatformState;
use dpp::block::block_info::BlockInfo;
use dpp::dashcore::hashes::Hash;
use dpp::data_contracts::SystemDataContract;
use dpp::fee::Credits;
use dpp::platform_value::Identifier;
use dpp::serialization::PlatformDeserializable;
use dpp::system_data_contracts::load_system_data_contract;
use dpp::version::PlatformVersion;
use dpp::version::ProtocolVersion;
use dpp::voting::vote_polls::VotePoll;
use drive::drive::identity::key::fetch::{
IdentityKeysRequest, KeyIDIdentityPublicKeyPairBTreeMap, KeyRequestType,
};
use drive::drive::identity::withdrawals::paths::{
get_withdrawal_root_path, WITHDRAWAL_TRANSACTIONS_BROADCASTED_KEY,
WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY,
};
use drive::grovedb::{Element, Transaction};
use drive::drive::prefunded_specialized_balances::{
prefunded_specialized_balances_for_voting_path,

Check warning on line 24 in packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

unused import: `prefunded_specialized_balances_for_voting_path`

warning: unused import: `prefunded_specialized_balances_for_voting_path` --> packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs:24:5 | 24 | prefunded_specialized_balances_for_voting_path, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
prefunded_specialized_balances_for_voting_path_vec,
};
use drive::drive::votes::paths::vote_end_date_queries_tree_path_vec;
use drive::grovedb::{Element, PathQuery, Query, QueryItem, SizedQuery, Transaction};
use drive::query::QueryResultType;
use std::collections::HashSet;
use std::ops::RangeFull;

impl<C> Platform<C> {
/// Executes protocol-specific events on the first block after a protocol version change.
Expand Down Expand Up @@ -44,7 +57,7 @@
transaction: &Transaction,
previous_protocol_version: ProtocolVersion,
platform_version: &PlatformVersion,
) -> Result<(), Error> {

Check warning on line 60 in packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

the `Err`-variant returned from this function is very large

warning: the `Err`-variant returned from this function is very large --> packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs:60:10 | 60 | ) -> Result<(), Error> { | ^^^^^^^^^^^^^^^^^ | ::: packages/rs-drive-abci/src/error/mod.rs:28:5 | 28 | Abci(#[from] AbciError), | ----------------------- the largest variant contains at least 208 bytes | = help: try reducing the size of `error::Error`, for example by boxing large elements or replacing it with `Box<error::Error>` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err
if previous_protocol_version < 4 && platform_version.protocol_version >= 4 {
self.transition_to_version_4(
platform_state,
Expand All @@ -52,10 +65,10 @@
transaction,
platform_version,
)?;
}

if previous_protocol_version < 6 && platform_version.protocol_version >= 6 {
shumkov marked this conversation as resolved.
Show resolved Hide resolved
} else if previous_protocol_version < 6 && platform_version.protocol_version >= 6 {
self.transition_to_version_6(block_info, transaction, platform_version)?;
} else if previous_protocol_version < 8 && platform_version.protocol_version >= 8 {
self.transition_to_version_8(block_info, transaction, platform_version)?;
}

Ok(())
Expand All @@ -71,7 +84,7 @@
block_info: &BlockInfo,
transaction: &Transaction,
platform_version: &PlatformVersion,
) -> Result<(), Error> {

Check warning on line 87 in packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

the `Err`-variant returned from this function is very large

warning: the `Err`-variant returned from this function is very large --> packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs:87:10 | 87 | ) -> Result<(), Error> { | ^^^^^^^^^^^^^^^^^ | ::: packages/rs-drive-abci/src/error/mod.rs:28:5 | 28 | Abci(#[from] AbciError), | ----------------------- the largest variant contains at least 208 bytes | = help: try reducing the size of `error::Error`, for example by boxing large elements or replacing it with `Box<error::Error>` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err
let contract =
load_system_data_contract(SystemDataContract::WalletUtils, platform_version)?;

Expand All @@ -86,6 +99,136 @@
Ok(())
}

/// When transitioning to version 8 we need to empty some specialized balances
fn transition_to_version_8(
&self,
block_info: &BlockInfo,
transaction: &Transaction,
platform_version: &PlatformVersion,
) -> Result<(), Error> {

Check warning on line 108 in packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive-abci) / Linting

the `Err`-variant returned from this function is very large

warning: the `Err`-variant returned from this function is very large --> packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs:108:10 | 108 | ) -> Result<(), Error> { | ^^^^^^^^^^^^^^^^^ | ::: packages/rs-drive-abci/src/error/mod.rs:28:5 | 28 | Abci(#[from] AbciError), | ----------------------- the largest variant contains at least 208 bytes | = help: try reducing the size of `error::Error`, for example by boxing large elements or replacing it with `Box<error::Error>` = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err
// Let's start by getting all the specialized balances that exist
let path_holding_specialized_balances =
prefunded_specialized_balances_for_voting_path_vec();
let path_query = PathQuery::new_single_query_item(
path_holding_specialized_balances,
QueryItem::RangeFull(RangeFull),
);
let all_specialized_balances_still_around: HashSet<_> = self
.drive
.grove_get_path_query(
&path_query,
Some(transaction),
QueryResultType::QueryKeyElementPairResultType,
&mut vec![],
&platform_version.drive,
)?
.0
.to_keys()
.into_iter()
.map(|key| Identifier::try_from(key))
shumkov marked this conversation as resolved.
Show resolved Hide resolved
.collect::<Result<HashSet<_>, dpp::platform_value::Error>>()?;

let path = vote_end_date_queries_tree_path_vec();
shumkov marked this conversation as resolved.
Show resolved Hide resolved

let mut query = Query::new_with_direction(true);

query.insert_all();

let mut sub_query = Query::new();

sub_query.insert_all();

query.default_subquery_branch.subquery = Some(sub_query.into());

let current_votes_path_query = PathQuery {
path,
query: SizedQuery {
query,
limit: Some(30000), //Just a high number that shouldn't break the system
offset: None,
},
};

let Ok((query_result_elements, _)) = self.drive.grove_get_path_query(
&current_votes_path_query,
Some(transaction),
QueryResultType::QueryElementResultType,
&mut vec![],
&platform_version.drive,
) else {
shumkov marked this conversation as resolved.
Show resolved Hide resolved
tracing::error!(
"Transition to version 8 failed getting active contested resource votes"
);
return Ok(());
};
shumkov marked this conversation as resolved.
Show resolved Hide resolved

let active_specialized_balances = query_result_elements
.to_elements()
.into_iter()
.map(|element| {
let contested_document_resource_vote_poll_bytes = element
.into_item_bytes()
.map_err(drive::error::Error::GroveDB)?;
let vote_poll =
VotePoll::deserialize_from_bytes(&contested_document_resource_vote_poll_bytes)?;
match vote_poll {
VotePoll::ContestedDocumentResourceVotePoll(contested) => {
contested.specialized_balance_id().map_err(Error::Protocol)
}
}
})
.collect::<Result<HashSet<Identifier>, Error>>()?;

// let's get the non-active ones
let non_active_specialized_balances =
all_specialized_balances_still_around.difference(&active_specialized_balances);

let mut total_credits_to_add_to_processing: Credits = 0;

let mut operations = vec![];

for specialized_balance_id in non_active_specialized_balances {
let (credits, mut empty_specialized_balance_operation) =
self.drive.empty_prefunded_specialized_balance_operations(
*specialized_balance_id,
false,
&mut None,
Some(transaction),
platform_version,
)?;
operations.append(&mut empty_specialized_balance_operation);
total_credits_to_add_to_processing = total_credits_to_add_to_processing
.checked_add(credits)
.ok_or(Error::Execution(ExecutionError::Overflow(
"Credits from specialized balances are overflowing",
)))?;
}

if total_credits_to_add_to_processing > 0 {
operations.push(
self.drive
.add_epoch_processing_credits_for_distribution_operation(
&block_info.epoch,
total_credits_to_add_to_processing,
Some(transaction),
platform_version,
)?,
);
}

if !operations.is_empty() {
self.drive.apply_batch_low_level_drive_operations(
None,
Some(transaction),
operations,
&mut vec![],
&platform_version.drive,
)?;
}

Ok(())
}

/// Initializes an empty sum tree for withdrawal transactions required for protocol version 4.
///
/// This function is called during the transition to protocol version 4 to set up
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ where
// This means removing it and also removing all current votes
if !vote_polls_with_info.is_empty() {
self.clean_up_after_vote_polls_end(
block_info,
&vote_polls_with_info,
clean_up_testnet_corrupted_reference_issue,
transaction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::error::execution::ExecutionError;
use crate::error::Error;
use crate::platform_types::platform::Platform;
use crate::rpc::core::CoreRPCLike;
use dpp::block::block_info::BlockInfo;
use dpp::identifier::Identifier;
use dpp::prelude::TimestampMillis;
use dpp::version::PlatformVersion;
Expand All @@ -11,6 +12,7 @@ use drive::grovedb::TransactionArg;
use std::collections::BTreeMap;

mod v0;
mod v1;

impl<C> Platform<C>
where
Expand All @@ -19,6 +21,7 @@ where
/// Checks for ended vote polls
pub(in crate::execution) fn clean_up_after_contested_resources_vote_polls_end(
&self,
block_info: &BlockInfo,
vote_polls: Vec<(
&ContestedDocumentResourceVotePollWithContractInfo,
&TimestampMillis,
Expand All @@ -40,9 +43,16 @@ where
transaction,
platform_version,
),
1 => self.clean_up_after_contested_resources_vote_polls_end_v1(
block_info,
vote_polls,
clean_up_testnet_corrupted_reference_issue,
transaction,
platform_version,
),
version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch {
method: "clean_up_after_contested_resources_vote_polls_end".to_string(),
known_versions: vec![0],
known_versions: vec![0, 1],
received: version,
})),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use dpp::version::PlatformVersion;
use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice;
use dpp::ProtocolError;
use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo;
use drive::fees::op::LowLevelDriveOperation;
use drive::grovedb::TransactionArg;
use std::collections::BTreeMap;

Expand All @@ -28,12 +29,43 @@ where
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<(), Error> {
let operations = self.clean_up_after_contested_resources_vote_polls_end_operations_v0(
vote_polls.as_slice(),
clean_up_testnet_corrupted_reference_issue,
transaction,
platform_version,
)?;
if !operations.is_empty() {
self.drive.apply_batch_low_level_drive_operations(
None,
transaction,
operations,
&mut vec![],
&platform_version.drive,
)?;
}

Ok(())
}
/// Checks for ended vote polls
#[inline(always)]
pub(super) fn clean_up_after_contested_resources_vote_polls_end_operations_v0(
&self,
vote_polls: &[(
&ContestedDocumentResourceVotePollWithContractInfo,
&TimestampMillis,
&BTreeMap<ResourceVoteChoice, Vec<Identifier>>,
)],
clean_up_testnet_corrupted_reference_issue: bool,
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<Vec<LowLevelDriveOperation>, Error> {
let mut operations = vec![];

// We remove the end date query
self.drive
.remove_contested_resource_vote_poll_end_date_query_operations(
vote_polls.as_slice(),
vote_polls,
&mut operations,
transaction,
platform_version,
Expand All @@ -42,7 +74,7 @@ where
// We remove the votes from under the contenders votes received
self.drive
.remove_contested_resource_vote_poll_votes_operations(
vote_polls.as_slice(),
vote_polls,
true,
&mut operations,
transaction,
Expand All @@ -52,7 +84,7 @@ where
// We remove the documents that contenders have
self.drive
.remove_contested_resource_vote_poll_documents_operations(
vote_polls.as_slice(),
vote_polls,
clean_up_testnet_corrupted_reference_issue,
&mut operations,
transaction,
Expand All @@ -62,7 +94,7 @@ where
// We remove the contenders
self.drive
.remove_contested_resource_vote_poll_contenders_operations(
vote_polls.as_slice(),
vote_polls,
&mut operations,
transaction,
platform_version,
Expand All @@ -81,7 +113,7 @@ where

let mut identity_to_vote_ids_map: BTreeMap<&Identifier, Vec<&Identifier>> = BTreeMap::new();

for (vote_poll, _, voters_for_contender) in &vote_polls {
for (vote_poll, _, voters_for_contender) in vote_polls {
let vote_id = vote_poll_ids
.iter()
.find_map(|(vp, vid)| if vp == vote_poll { Some(vid) } else { None })
Expand Down Expand Up @@ -113,31 +145,21 @@ where

if clean_up_testnet_corrupted_reference_issue {
self.drive.remove_contested_resource_info_operations(
vote_polls.as_slice(),
vote_polls,
&mut operations,
transaction,
platform_version,
)?;
// We remove the last index
self.drive
.remove_contested_resource_top_level_index_operations(
vote_polls.as_slice(),
vote_polls,
&mut operations,
transaction,
platform_version,
)?;
}

if !operations.is_empty() {
self.drive.apply_batch_low_level_drive_operations(
None,
transaction,
operations,
&mut vec![],
&platform_version.drive,
)?;
}

Ok(())
Ok(operations)
}
}
Loading
Loading