From 48a0332670f560092fd7594d046755cbd8b44fa1 Mon Sep 17 00:00:00 2001 From: QuantumExplorer Date: Wed, 18 Sep 2024 18:25:59 +0700 Subject: [PATCH] chore: emergency version upgrade to v1.3 Protocol Version 2. (#2138) --- .../rs-drive-abci/src/abci/handler/info.rs | 8 +-- .../src/abci/handler/prepare_proposal.rs | 11 +++- .../src/abci/handler/process_proposal.rs | 5 +- .../engine/consensus_params_update/mod.rs | 7 ++ .../engine/consensus_params_update/v0/mod.rs | 44 +++++++++++++ .../check_for_desired_protocol_upgrade/mod.rs | 10 +-- .../v0/mod.rs | 26 +++++--- .../v1/mod.rs | 64 +++++++++++++++++++ .../documents_batch/is_allowed/v0/mod.rs | 6 +- .../src/platform_types/epoch_info/mod.rs | 2 +- .../src/platform_types/epoch_info/v0/mod.rs | 2 +- packages/rs-drive/src/config.rs | 1 - .../v1/mod.rs | 2 +- .../src/version/protocol_version.rs | 23 +++++++ .../rs-platform-version/src/version/v3.rs | 8 ++- 15 files changed, 192 insertions(+), 27 deletions(-) create mode 100644 packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v1/mod.rs diff --git a/packages/rs-drive-abci/src/abci/handler/info.rs b/packages/rs-drive-abci/src/abci/handler/info.rs index ea8aad0eec..dbb8501891 100644 --- a/packages/rs-drive-abci/src/abci/handler/info.rs +++ b/packages/rs-drive-abci/src/abci/handler/info.rs @@ -3,7 +3,7 @@ use crate::abci::AbciError; use crate::error::Error; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::rpc::core::CoreRPCLike; -use dpp::version::PlatformVersion; +use dpp::version::DESIRED_PLATFORM_VERSION; use tenderdash_abci::proto::abci as proto; pub fn info(app: &A, request: proto::RequestInfo) -> Result @@ -26,18 +26,18 @@ where .map(|app_hash| app_hash.to_vec()) .unwrap_or_default(); - let latest_supported_protocol_version = PlatformVersion::latest().protocol_version; + let desired_protocol_version = DESIRED_PLATFORM_VERSION.protocol_version; let response = proto::ResponseInfo { data: "".to_string(), - app_version: latest_supported_protocol_version as u64, + app_version: desired_protocol_version as u64, last_block_height: platform_state.last_committed_block_height() as i64, version: env!("CARGO_PKG_VERSION").to_string(), last_block_app_hash: state_app_hash.clone(), }; tracing::debug!( - latest_supported_protocol_version, + desired_protocol_version, software_version = env!("CARGO_PKG_VERSION"), block_version = request.block_version, p2p_version = request.p2p_version, diff --git a/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs b/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs index 7d99cdfc9e..9a59463bea 100644 --- a/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs +++ b/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs @@ -2,10 +2,11 @@ use crate::abci::app::{BlockExecutionApplication, PlatformApplication, Transacti use crate::abci::AbciError; use crate::error::Error; use crate::execution::engine::consensus_params_update::consensus_params_update; -use crate::execution::types::block_execution_context::v0::BlockExecutionContextV0Setters; +use crate::execution::types::block_execution_context::v0::{ + BlockExecutionContextV0Getters, BlockExecutionContextV0Setters, +}; use crate::platform_types::block_execution_outcome; use crate::platform_types::block_proposal::v0::BlockProposal; -use crate::platform_types::platform::Platform; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::platform_types::state_transitions_processing_result::StateTransitionExecutionResult; use crate::rpc::core::CoreRPCLike; @@ -15,7 +16,7 @@ use drive::grovedb_storage::Error::RocksDBError; use tenderdash_abci::proto::abci as proto; use tenderdash_abci::proto::abci::tx_record::TxAction; use tenderdash_abci::proto::abci::{ExecTxResult, TxRecord}; -use tenderdash_abci::proto::types::{ConsensusParams, CoreChainLock}; +use tenderdash_abci::proto::types::CoreChainLock; pub fn prepare_proposal<'a, A, C>( app: &A, @@ -133,6 +134,8 @@ where mut block_execution_context, } = run_result.into_data().map_err(Error::Protocol)?; + let epoch_info = block_execution_context.epoch_info(); + // We need to let Tenderdash know about the transactions we should remove from execution let valid_tx_count = state_transitions_result.valid_count(); let failed_tx_count = state_transitions_result.failed_count(); @@ -204,8 +207,10 @@ where }), validator_set_update, consensus_param_updates: consensus_params_update( + app.platform().config.network, starting_platform_version, platform_version, + epoch_info, )?, app_version: platform_version.protocol_version as u64, }; diff --git a/packages/rs-drive-abci/src/abci/handler/process_proposal.rs b/packages/rs-drive-abci/src/abci/handler/process_proposal.rs index 1d37d1c82a..5bf547e14a 100644 --- a/packages/rs-drive-abci/src/abci/handler/process_proposal.rs +++ b/packages/rs-drive-abci/src/abci/handler/process_proposal.rs @@ -9,7 +9,6 @@ use crate::execution::types::block_state_info::v0::{ BlockStateInfoV0Getters, BlockStateInfoV0Setters, }; use crate::platform_types::block_execution_outcome; -use crate::platform_types::platform::Platform; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::platform_types::state_transitions_processing_result::StateTransitionExecutionResult; use crate::rpc::core::CoreRPCLike; @@ -217,6 +216,8 @@ where block_execution_context, } = run_result.into_data().map_err(Error::Protocol)?; + let epoch_info = *block_execution_context.epoch_info(); + app.block_execution_context() .write() .unwrap() @@ -280,8 +281,10 @@ where status: proto::response_process_proposal::ProposalStatus::Accept.into(), validator_set_update, consensus_param_updates: consensus_params_update( + app.platform().config.network, starting_platform_version, platform_version, + &epoch_info, )?, events: Vec::new(), }; diff --git a/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs index f5c9eb6da4..16319d7746 100644 --- a/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs @@ -1,12 +1,17 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::execution::engine::consensus_params_update::v0::consensus_params_update_v0; +use crate::platform_types::epoch_info::EpochInfo; +use dpp::dashcore::Network; use dpp::version::PlatformVersion; use tenderdash_abci::proto::types::ConsensusParams; + mod v0; pub(crate) fn consensus_params_update( + network: Network, original_platform_version: &PlatformVersion, new_platform_version: &PlatformVersion, + epoch_info: &EpochInfo, ) -> Result, Error> { match new_platform_version .drive_abci @@ -15,8 +20,10 @@ pub(crate) fn consensus_params_update( .consensus_params_update { 0 => Ok(consensus_params_update_v0( + network, original_platform_version, new_platform_version, + epoch_info, )), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "consensus_params_update".to_string(), diff --git a/packages/rs-drive-abci/src/execution/engine/consensus_params_update/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/v0/mod.rs index 3a2d8b71fd..980046b0aa 100644 --- a/packages/rs-drive-abci/src/execution/engine/consensus_params_update/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/v0/mod.rs @@ -1,10 +1,54 @@ +use crate::platform_types::epoch_info::v0::EpochInfoV0Methods; +use crate::platform_types::epoch_info::EpochInfo; +use dpp::dashcore::Network; use dpp::version::PlatformVersion; use tenderdash_abci::proto::types::{ConsensusParams, VersionParams}; + #[inline(always)] pub(super) fn consensus_params_update_v0( + network: Network, original_platform_version: &PlatformVersion, new_platform_version: &PlatformVersion, + epoch_info: &EpochInfo, ) -> Option { + // These are emergency consensus updates + match network { + Network::Dash => { + if epoch_info.is_first_block_of_epoch(3) { + return Some(ConsensusParams { + block: None, + evidence: None, + validator: None, + version: Some(VersionParams { + app_version: new_platform_version.protocol_version as u64, + consensus_version: 1, + }), + synchrony: None, + timeout: None, + abci: None, + }); + } + } + Network::Testnet => { + if epoch_info.is_first_block_of_epoch(1475) { + return Some(ConsensusParams { + block: None, + evidence: None, + validator: None, + version: Some(VersionParams { + app_version: new_platform_version.protocol_version as u64, + consensus_version: 1, + }), + synchrony: None, + timeout: None, + abci: None, + }); + } + } + _ => {} + } + + // These are normal consensus updates if original_platform_version .consensus .tenderdash_consensus_version diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/mod.rs index 33805f3125..be12d1989d 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/mod.rs @@ -5,6 +5,7 @@ use dpp::util::deserializer::ProtocolVersion; use dpp::version::PlatformVersion; mod v0; +mod v1; impl Platform { /// Checks for a network upgrade and resets activation window. @@ -12,7 +13,7 @@ impl Platform { /// /// # Arguments /// - /// * `total_hpmns` - The total number of high priority masternodes. + /// * `active_hpmns` - The total number of evonodes that are not banned. /// /// # Returns /// @@ -29,7 +30,7 @@ impl Platform { /// * More than one version pass the threshold to upgrade. pub fn check_for_desired_protocol_upgrade( &self, - total_hpmns: u32, + active_hpmns: u32, platform_version: &PlatformVersion, ) -> Result, Error> { match platform_version @@ -38,10 +39,11 @@ impl Platform { .protocol_upgrade .check_for_desired_protocol_upgrade { - 0 => self.check_for_desired_protocol_upgrade_v0(total_hpmns, platform_version), + 0 => self.check_for_desired_protocol_upgrade_v0(active_hpmns, platform_version), + 1 => self.check_for_desired_protocol_upgrade_v1(active_hpmns, platform_version), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "check_for_desired_protocol_upgrade".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v0/mod.rs index c7fbd019fe..ba67c149d5 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v0/mod.rs @@ -1,6 +1,7 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::Platform; +use dpp::dashcore::Network; use dpp::version::PlatformVersion; use drive::dpp::util::deserializer::ProtocolVersion; @@ -10,17 +11,26 @@ impl Platform { /// this should only be called on epoch change pub(super) fn check_for_desired_protocol_upgrade_v0( &self, - total_hpmns: u32, + active_hpmns: u32, platform_version: &PlatformVersion, ) -> Result, Error> { - let upgrade_percentage_needed = platform_version - .drive_abci - .methods - .protocol_upgrade - .protocol_version_upgrade_percentage_needed; + let upgrade_percentage_needed = if (self.config.network == Network::Dash + && platform_version.protocol_version == 1) + || (self.config.network == Network::Testnet && platform_version.protocol_version == 2) + { + // This is a solution for the emergency update to version 3 + // We clean this up immediately though as we transition to check_for_desired_protocol_upgrade_v1 + 51 + } else { + platform_version + .drive_abci + .methods + .protocol_upgrade + .protocol_version_upgrade_percentage_needed + }; let required_upgraded_hpmns = 1 - + (total_hpmns as u64) + + (active_hpmns as u64) .checked_mul(upgrade_percentage_needed) .and_then(|product| product.checked_div(100)) .ok_or(Error::Execution(ExecutionError::Overflow( @@ -43,7 +53,7 @@ impl Platform { } tracing::debug!( - total_hpmns, + active_hpmns, required_upgraded_hpmns, all_votes = ?protocol_versions_counter.global_cache, ?versions_passing_threshold, diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v1/mod.rs new file mode 100644 index 0000000000..fd66cc62cd --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/check_for_desired_protocol_upgrade/v1/mod.rs @@ -0,0 +1,64 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::platform_types::platform::Platform; + +use dpp::version::PlatformVersion; +use drive::dpp::util::deserializer::ProtocolVersion; + +impl Platform { + /// checks for a network upgrade and resets activation window + /// this should only be called on epoch change + pub(super) fn check_for_desired_protocol_upgrade_v1( + &self, + active_hpmns: u32, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let upgrade_percentage_needed = platform_version + .drive_abci + .methods + .protocol_upgrade + .protocol_version_upgrade_percentage_needed; + + let required_upgraded_hpmns = 1 + + (active_hpmns as u64) + .checked_mul(upgrade_percentage_needed) + .and_then(|product| product.checked_div(100)) + .ok_or(Error::Execution(ExecutionError::Overflow( + "overflow for required block count", + )))?; + + // if we are at an epoch change, check to see if over 75% of blocks of previous epoch + // were on the future version + let protocol_versions_counter = self.drive.cache.protocol_versions_counter.read(); + + let mut versions_passing_threshold = + protocol_versions_counter.versions_passing_threshold(required_upgraded_hpmns); + + if versions_passing_threshold.len() > 1 { + return Err(Error::Execution( + ExecutionError::ProtocolUpgradeIncoherence( + "only at most 1 version should be able to pass the threshold to upgrade", + ), + )); + } + + tracing::debug!( + active_hpmns, + required_upgraded_hpmns, + all_votes = ?protocol_versions_counter.global_cache, + ?versions_passing_threshold, + "Protocol version voting is finished. we require {} upgraded, {} versions passing the threshold: {:?}", + required_upgraded_hpmns, + versions_passing_threshold.len(), + versions_passing_threshold + ); + + if !versions_passing_threshold.is_empty() { + // same as equals 1 + let next_version = versions_passing_threshold.remove(0); + Ok(Some(next_version)) + } else { + Ok(None) + } + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/is_allowed/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/is_allowed/v0/mod.rs index 4f0681b7ef..a98801ee70 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/is_allowed/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/is_allowed/v0/mod.rs @@ -7,7 +7,11 @@ use dpp::state_transition::documents_batch_transition::document_create_transitio use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition; use dpp::validation::ConsensusValidationResult; -pub const TARGET_EPOCH_INDEX: EpochIndex = 3; +// TARGET_EPOCH_INDEX was introduced without versioning. +// All Evonodes that have not upgraded to version 1.3 by Epoch 3 will chain stall. +// +// This value was previously 3 before version 1.3 +pub const TARGET_EPOCH_INDEX: EpochIndex = 4; #[inline(always)] pub fn validate_is_allowed_v0( diff --git a/packages/rs-drive-abci/src/platform_types/epoch_info/mod.rs b/packages/rs-drive-abci/src/platform_types/epoch_info/mod.rs index 2a62a89c42..8ea7c8a84f 100644 --- a/packages/rs-drive-abci/src/platform_types/epoch_info/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/epoch_info/mod.rs @@ -26,7 +26,7 @@ pub mod v0; /// This means that if we ever want to update EpochInfo, we will need to do so on a release /// where the new fields of epoch info are not being used. Then make another version once /// that one is activated. -#[derive(Clone, Serialize, Deserialize, Debug, From, Eq, PartialEq)] +#[derive(Clone, Copy, Serialize, Deserialize, Debug, From, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub enum EpochInfo { /// Version 0 diff --git a/packages/rs-drive-abci/src/platform_types/epoch_info/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/epoch_info/v0/mod.rs index a7888d5e43..a2e216dc9d 100644 --- a/packages/rs-drive-abci/src/platform_types/epoch_info/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/epoch_info/v0/mod.rs @@ -16,7 +16,7 @@ use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; /// Info pertinent to the current epoch. -#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub struct EpochInfoV0 { /// Current epoch index diff --git a/packages/rs-drive/src/config.rs b/packages/rs-drive/src/config.rs index 960b323f3e..313be06c3c 100644 --- a/packages/rs-drive/src/config.rs +++ b/packages/rs-drive/src/config.rs @@ -5,7 +5,6 @@ use dpp::dashcore::Network; use dpp::fee::epoch::DEFAULT_EPOCHS_PER_ERA; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use std::str::FromStr; /// Boolean if GroveDB batching consistency verification is enabled by default pub const DEFAULT_GROVE_BATCHING_CONSISTENCY_VERIFICATION_ENABLED: bool = false; diff --git a/packages/rs-drive/src/drive/votes/cleanup/remove_contested_resource_vote_poll_end_date_query_operations/v1/mod.rs b/packages/rs-drive/src/drive/votes/cleanup/remove_contested_resource_vote_poll_end_date_query_operations/v1/mod.rs index 8fe6ef3d13..b47e5feb60 100644 --- a/packages/rs-drive/src/drive/votes/cleanup/remove_contested_resource_vote_poll_end_date_query_operations/v1/mod.rs +++ b/packages/rs-drive/src/drive/votes/cleanup/remove_contested_resource_vote_poll_end_date_query_operations/v1/mod.rs @@ -1,6 +1,6 @@ use crate::drive::votes::paths::{ vote_contested_resource_end_date_queries_at_time_tree_path_vec, - vote_end_date_queries_tree_path, vote_end_date_queries_tree_path_vec, + vote_end_date_queries_tree_path_vec, }; use crate::drive::votes::resolved::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePollWithContractInfo; use crate::drive::Drive; diff --git a/packages/rs-platform-version/src/version/protocol_version.rs b/packages/rs-platform-version/src/version/protocol_version.rs index 5af9382972..607a267844 100644 --- a/packages/rs-platform-version/src/version/protocol_version.rs +++ b/packages/rs-platform-version/src/version/protocol_version.rs @@ -51,6 +51,9 @@ const DEFAULT_PLATFORM_TEST_VERSIONS: &[PlatformVersion] = &[TEST_PLATFORM_V2, T pub const LATEST_PLATFORM_VERSION: &PlatformVersion = &PLATFORM_V3; +/// For V3 release we want to do an emergency version upgrade +pub const DESIRED_PLATFORM_VERSION: &PlatformVersion = LATEST_PLATFORM_VERSION; + impl PlatformVersion { pub fn get<'a>(version: ProtocolVersion) -> Result<&'a Self, PlatformVersionError> { if version > 0 { @@ -80,6 +83,26 @@ impl PlatformVersion { } } + pub fn get_optional<'a>(version: ProtocolVersion) -> Option<&'a Self> { + if version > 0 { + #[cfg(feature = "mock-versions")] + { + if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 { + let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES); + + // Init default set of test versions + let versions = PLATFORM_TEST_VERSIONS + .get_or_init(|| vec![TEST_PLATFORM_V2, TEST_PLATFORM_V3]); + + return versions.get(test_version as usize - 2); + } + } + PLATFORM_VERSIONS.get(version as usize - 1) + } else { + None + } + } + pub fn get_version_or_latest<'a>( version: Option, ) -> Result<&'a Self, PlatformVersionError> { diff --git a/packages/rs-platform-version/src/version/v3.rs b/packages/rs-platform-version/src/version/v3.rs index a7277296ec..cb608a3b3c 100644 --- a/packages/rs-platform-version/src/version/v3.rs +++ b/packages/rs-platform-version/src/version/v3.rs @@ -86,6 +86,10 @@ pub const PROTOCOL_VERSION_3: ProtocolVersion = 3; /// This version introduces tenderdash_consensus_version as 1. /// We did this because of the issues in distribution for Evonodes. +/// We are setting the requirement to 51% voting for this upgrade for it to take effect. +/// This was done directly in ABCI. +/// If we get between 51 and 67% we will have a chain stall +/// However the chain will come back up as soon as enough have upgraded. pub const PLATFORM_V3: PlatformVersion = PlatformVersion { protocol_version: 3, @@ -636,9 +640,9 @@ pub const PLATFORM_V3: PlatformVersion = PlatformVersion { }, }, protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { - check_for_desired_protocol_upgrade: 0, + check_for_desired_protocol_upgrade: 1, upgrade_protocol_version_on_epoch_change: 0, - protocol_version_upgrade_percentage_needed: 75, + protocol_version_upgrade_percentage_needed: 67, }, block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { add_process_epoch_change_operations: 0,