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
Changes from 2 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

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.
@@ -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

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,
@@ -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(())
@@ -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

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)?;

@@ -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

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
Original file line number Diff line number Diff line change
@@ -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,
Original file line number Diff line number Diff line change
@@ -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;
@@ -11,6 +12,7 @@ use drive::grovedb::TransactionArg;
use std::collections::BTreeMap;

mod v0;
mod v1;

impl<C> Platform<C>
where
@@ -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,
@@ -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,
})),
}
Original file line number Diff line number Diff line change
@@ -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;

@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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 })
@@ -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