diff --git a/CHANGELOG.md b/CHANGELOG.md index fa880bab330..1062e043d13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,22 @@ -## [1.8.0-dev.1](https://github.com/dashpay/platform/compare/v1.7.0...v1.8.0-dev.1) (2024-12-16) +### [1.7.1](https://github.com/dashpay/platform/compare/v1.7.0...v1.7.1) (2024-12-19) + +### ⚠ BREAKING CHANGES + +* On epoch 13, masternode vote state transition validation logic will be changed. Nodes which aren't upgraded to this version will halt (#2397) +* Rust 1.83 is required to build the project (#2398) + +### Bug Fixes + +* emergency hard fork to fix masternode voting ([#2397](https://github.com/dashpay/platform/issues/2397)) +### Build System + +* update rust to 1.83 - backport [#2393](https://github.com/dashpay/platform/issues/2393) to v1.7 ([#2398](https://github.com/dashpay/platform/issues/2398)) + + +## [1.8.0-dev.1](https://github.com/dashpay/platform/compare/v1.7.0...v1.8.0-dev.1) (2024-12-16) + ### Continuous Integration * fix artifact upload issue on release build ([#2389](https://github.com/dashpay/platform/issues/2389)) @@ -20,6 +36,7 @@ * **platform:** replace bls library ([#2257](https://github.com/dashpay/platform/issues/2257)) + ### [1.7.0](https://github.com/dashpay/platform/compare/v1.6.2...v1.7.0) (2024-12-13) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/mod.rs index 216c68a1ecb..79818202cde 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/mod.rs @@ -2,6 +2,7 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::execution::types::state_transition_execution_context::StateTransitionExecutionContext; use crate::execution::validation::state_transition::masternode_vote::nonce::v0::MasternodeVoteTransitionIdentityNonceV0; +use crate::execution::validation::state_transition::masternode_vote::nonce::v1::MasternodeVoteTransitionIdentityNonceV1; use crate::execution::validation::state_transition::processor::v0::StateTransitionNonceValidationV0; use crate::platform_types::platform::PlatformStateRef; use dpp::block::block_info::BlockInfo; @@ -11,6 +12,8 @@ use dpp::version::PlatformVersion; use drive::grovedb::TransactionArg; pub(crate) mod v0; +pub(crate) mod v1; + impl StateTransitionNonceValidationV0 for MasternodeVoteTransition { fn validate_nonces( &self, @@ -34,14 +37,21 @@ impl StateTransitionNonceValidationV0 for MasternodeVoteTransition { execution_context, platform_version, ), + Some(1) => self.validate_nonce_v1( + platform, + block_info, + tx, + execution_context, + platform_version, + ), Some(version) => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "masternode vote transition: validate_nonces".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), None => Err(Error::Execution(ExecutionError::VersionNotActive { method: "masternode vote transition: validate_nonces".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], })), } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/v0/mod.rs index bdb92a5a716..fd9ea2cc165 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/v0/mod.rs @@ -14,6 +14,7 @@ use crate::execution::types::execution_operation::ValidationOperation; use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; +use crate::execution::validation::state_transition::masternode_vote::nonce::v1::MasternodeVoteTransitionIdentityNonceV1; use crate::platform_types::platform::PlatformStateRef; use dpp::version::PlatformVersion; use drive::grovedb::TransactionArg; @@ -39,6 +40,17 @@ impl MasternodeVoteTransitionIdentityNonceV0 for MasternodeVoteTransition { execution_context: &mut StateTransitionExecutionContext, platform_version: &PlatformVersion, ) -> Result { + // We are introducing this as an emergency hard fork activating at epoch 13. + if block_info.epoch.index >= 13 { + return self.validate_nonce_v1( + platform, + block_info, + tx, + execution_context, + platform_version, + ); + } + let revision_nonce = self.nonce(); if revision_nonce & MISSING_IDENTITY_REVISIONS_FILTER > 0 { diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/v1/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/v1/mod.rs new file mode 100644 index 00000000000..6fa254f7fbe --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/nonce/v1/mod.rs @@ -0,0 +1,71 @@ +use crate::error::Error; +use dpp::block::block_info::BlockInfo; +use dpp::consensus::basic::document::NonceOutOfBoundsError; +use dpp::consensus::basic::BasicError; +use dpp::identity::identity_nonce::{ + validate_identity_nonce_update, validate_new_identity_nonce, MISSING_IDENTITY_REVISIONS_FILTER, +}; +use dpp::state_transition::masternode_vote_transition::accessors::MasternodeVoteTransitionAccessorsV0; +use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; + +use dpp::validation::SimpleConsensusValidationResult; + +use crate::execution::types::execution_operation::ValidationOperation; +use crate::execution::types::state_transition_execution_context::{ + StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, +}; +use crate::platform_types::platform::PlatformStateRef; +use dpp::version::PlatformVersion; +use drive::grovedb::TransactionArg; + +pub(in crate::execution::validation::state_transition::state_transitions) trait MasternodeVoteTransitionIdentityNonceV1 +{ + fn validate_nonce_v1( + &self, + platform: &PlatformStateRef, + block_info: &BlockInfo, + tx: TransactionArg, + execution_context: &mut StateTransitionExecutionContext, + platform_version: &PlatformVersion, + ) -> Result; +} + +impl MasternodeVoteTransitionIdentityNonceV1 for MasternodeVoteTransition { + fn validate_nonce_v1( + &self, + platform: &PlatformStateRef, + block_info: &BlockInfo, + tx: TransactionArg, + execution_context: &mut StateTransitionExecutionContext, + platform_version: &PlatformVersion, + ) -> Result { + let revision_nonce = self.nonce(); + + if revision_nonce & MISSING_IDENTITY_REVISIONS_FILTER > 0 { + return Ok(SimpleConsensusValidationResult::new_with_error( + BasicError::NonceOutOfBoundsError(NonceOutOfBoundsError::new(revision_nonce)) + .into(), + )); + } + + let voter_identity_id = self.voter_identity_id(); + + let (existing_nonce, fee) = platform.drive.fetch_identity_nonce_with_fees( + voter_identity_id.to_buffer(), + block_info, + true, + tx, + platform_version, + )?; + + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + + let result = if let Some(existing_nonce) = existing_nonce { + validate_identity_nonce_update(existing_nonce, revision_nonce, voter_identity_id) + } else { + validate_new_identity_nonce(revision_nonce, voter_identity_id) + }; + + Ok(result) + } +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs index 4bd5ff6269c..71d54cdb7c1 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs @@ -2,6 +2,7 @@ pub mod v1; pub mod v2; pub mod v3; pub mod v4; +pub mod v5; use versioned_feature_core::{FeatureVersion, OptionalFeatureVersion}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v4.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v4.rs index ff70d44107d..8a1659106de 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v4.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v4.rs @@ -6,6 +6,9 @@ use crate::version::drive_abci_versions::drive_abci_validation_versions::{ DriveAbciValidationVersions, PenaltyAmounts, }; +// We introduced nonce validation for masternode voting in this version, and changed the call +// for nonce validation, however the actual validation for masternode voting was faulty, which is +// why we introduced V5. (We also are making an emergency hard fork). pub const DRIVE_ABCI_VALIDATION_VERSIONS_V4: DriveAbciValidationVersions = DriveAbciValidationVersions { state_transitions: DriveAbciStateTransitionValidationVersions { @@ -131,7 +134,7 @@ pub const DRIVE_ABCI_VALIDATION_VERSIONS_V4: DriveAbciValidationVersions = document_update_price_transition_state_validation: 0, }, }, - has_nonce_validation: 1, + has_nonce_validation: 1, // <---- changed this process_state_transition: 0, state_transition_to_execution_event_for_check_tx: 0, penalties: PenaltyAmounts { diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v5.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v5.rs new file mode 100644 index 00000000000..d48857faba9 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v5.rs @@ -0,0 +1,151 @@ +use crate::version::drive_abci_versions::drive_abci_validation_versions::{ + DriveAbciAssetLockValidationVersions, DriveAbciDocumentsStateTransitionValidationVersions, + DriveAbciStateTransitionCommonValidationVersions, DriveAbciStateTransitionValidationVersion, + DriveAbciStateTransitionValidationVersions, DriveAbciValidationConstants, + DriveAbciValidationDataTriggerAndBindingVersions, DriveAbciValidationDataTriggerVersions, + DriveAbciValidationVersions, PenaltyAmounts, +}; + +// In this version we change the nonce validation of masternode voting. +// There was a bug before this where the nonce validation would validate using the owner identity +// instead of the voting identity. +// This is not the same issue as before when we didn't validate nonces on masternode votes at all. +pub const DRIVE_ABCI_VALIDATION_VERSIONS_V5: DriveAbciValidationVersions = + DriveAbciValidationVersions { + state_transitions: DriveAbciStateTransitionValidationVersions { + common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { + asset_locks: DriveAbciAssetLockValidationVersions { + fetch_asset_lock_transaction_output_sync: 0, + verify_asset_lock_is_not_spent_and_has_enough_balance: 0, + }, + validate_identity_public_key_contract_bounds: 0, + validate_identity_public_key_ids_dont_exist_in_state: 0, + validate_identity_public_key_ids_exist_in_state: 0, + validate_state_transition_identity_signed: 0, + validate_unique_identity_public_key_hashes_in_state: 0, + validate_master_key_uniqueness: 0, + validate_simple_pre_check_balance: 0, + }, + max_asset_lock_usage_attempts: 16, + identity_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition: + DriveAbciStateTransitionValidationVersion { + basic_structure: Some(1), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition_purpose_matches_requirements: 0, + identity_credit_transfer_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: Some(0), + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(1), // <---- Changed this here + state: 0, + transform_into_action: 0, + }, + contract_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + documents_batch_state_transition: DriveAbciDocumentsStateTransitionValidationVersions { + balance_pre_check: 0, + basic_structure: 0, + advanced_structure: 0, + state: 0, + revision: 0, + transform_into_action: 0, + data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { + bindings: 0, + triggers: DriveAbciValidationDataTriggerVersions { + create_contact_request_data_trigger: 0, + create_domain_data_trigger: 0, + create_identity_data_trigger: 0, + create_feature_flag_data_trigger: 0, + create_masternode_reward_shares_data_trigger: 0, + delete_withdrawal_data_trigger: 0, + reject_data_trigger: 0, + }, + }, + is_allowed: 0, + document_create_transition_structure_validation: 0, + document_delete_transition_structure_validation: 0, + document_replace_transition_structure_validation: 0, + document_transfer_transition_structure_validation: 0, + document_purchase_transition_structure_validation: 0, + document_update_price_transition_structure_validation: 0, + document_create_transition_state_validation: 1, + document_delete_transition_state_validation: 0, + document_replace_transition_state_validation: 0, + document_transfer_transition_state_validation: 0, + document_purchase_transition_state_validation: 0, + document_update_price_transition_state_validation: 0, + }, + }, + has_nonce_validation: 1, + process_state_transition: 0, + state_transition_to_execution_event_for_check_tx: 0, + penalties: PenaltyAmounts { + identity_id_not_correct: 50000000, + unique_key_already_present: 10000000, + validation_of_added_keys_structure_failure: 10000000, + validation_of_added_keys_proof_of_possession_failure: 50000000, + }, + event_constants: DriveAbciValidationConstants { + maximum_vote_polls_to_process: 2, + maximum_contenders_to_consider: 100, + }, + }; diff --git a/packages/rs-platform-version/src/version/v7.rs b/packages/rs-platform-version/src/version/v7.rs index ee532689970..0857a94ae90 100644 --- a/packages/rs-platform-version/src/version/v7.rs +++ b/packages/rs-platform-version/src/version/v7.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_method_versions::v4::DRIVE_ABCI_METHOD_VERSIONS_V4; use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; -use crate::version::drive_abci_versions::drive_abci_validation_versions::v4::DRIVE_ABCI_VALIDATION_VERSIONS_V4; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v5::DRIVE_ABCI_VALIDATION_VERSIONS_V5; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; use crate::version::drive_abci_versions::DriveAbciVersion; use crate::version::drive_versions::v2::DRIVE_VERSION_V2; @@ -28,15 +28,14 @@ use crate::version::ProtocolVersion; pub const PROTOCOL_VERSION_7: ProtocolVersion = 7; -/// This version adds token support. -//todo: make changes +/// This version fixes masternode voting nonce issue. pub const PLATFORM_V7: PlatformVersion = PlatformVersion { protocol_version: PROTOCOL_VERSION_7, drive: DRIVE_VERSION_V2, drive_abci: DriveAbciVersion { structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, methods: DRIVE_ABCI_METHOD_VERSIONS_V4, - validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V4, + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V5, // <--- changed to V5 withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, query: DRIVE_ABCI_QUERY_VERSIONS_V1, },