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

chore!: do not allow contested documents for the first three epochs #2066

Merged
merged 18 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from 14 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
20 changes: 12 additions & 8 deletions packages/rs-dpp/src/errors/consensus/basic/basic_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ use crate::consensus::basic::decode::{
ProtocolVersionParsingError, SerializedObjectParsingError, VersionError,
};
use crate::consensus::basic::document::{
DataContractNotPresentError, DocumentCreationNotAllowedError,
DocumentFieldMaxSizeExceededError, DocumentTransitionsAreAbsentError,
DuplicateDocumentTransitionsWithIdsError, DuplicateDocumentTransitionsWithIndicesError,
InconsistentCompoundIndexDataError, InvalidDocumentTransitionActionError,
InvalidDocumentTransitionIdError, InvalidDocumentTypeError,
MaxDocumentsTransitionsExceededError, MissingDataContractIdBasicError,
MissingDocumentTransitionActionError, MissingDocumentTransitionTypeError,
MissingDocumentTypeError, MissingPositionsInDocumentTypePropertiesError, NonceOutOfBoundsError,
ContestedDocumentsTemporarilyNotAllowedError, DataContractNotPresentError,
DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError,
DocumentTransitionsAreAbsentError, DuplicateDocumentTransitionsWithIdsError,
DuplicateDocumentTransitionsWithIndicesError, InconsistentCompoundIndexDataError,
InvalidDocumentTransitionActionError, InvalidDocumentTransitionIdError,
InvalidDocumentTypeError, MaxDocumentsTransitionsExceededError,
MissingDataContractIdBasicError, MissingDocumentTransitionActionError,
MissingDocumentTransitionTypeError, MissingDocumentTypeError,
MissingPositionsInDocumentTypePropertiesError, NonceOutOfBoundsError,
};
use crate::consensus::basic::identity::{
DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError,
Expand Down Expand Up @@ -393,6 +394,9 @@ pub enum BasicError {

#[error(transparent)]
UnsupportedFeatureError(UnsupportedFeatureError),

#[error(transparent)]
ContestedDocumentsTemporarilyNotAllowedError(ContestedDocumentsTemporarilyNotAllowedError),
}

impl From<BasicError> for ConsensusError {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::consensus::basic::BasicError;
use crate::consensus::ConsensusError;
use crate::errors::ProtocolError;
use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
use thiserror::Error;

use crate::prelude::Identifier;

Check warning on line 7 in packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs

View workflow job for this annotation

GitHub Actions / Rust packages (dash-sdk) / Linting

unused import: `crate::prelude::Identifier`

warning: unused import: `crate::prelude::Identifier` --> packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs:7:5 | 7 | use crate::prelude::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

Check warning on line 7 in packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs

View workflow job for this annotation

GitHub Actions / Rust packages (dpp) / Linting

unused import: `crate::prelude::Identifier`

warning: unused import: `crate::prelude::Identifier` --> packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs:7:5 | 7 | use crate::prelude::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

Check warning on line 7 in packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs

View workflow job for this annotation

GitHub Actions / Rust packages (drive) / Linting

unused import: `crate::prelude::Identifier`

warning: unused import: `crate::prelude::Identifier` --> packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs:7:5 | 7 | use crate::prelude::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

Check warning on line 7 in packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs

View workflow job for this annotation

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

unused import: `crate::prelude::Identifier`

warning: unused import: `crate::prelude::Identifier` --> packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs:7:5 | 7 | use crate::prelude::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

Check warning on line 7 in packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs

View workflow job for this annotation

GitHub Actions / Rust packages (wasm-dpp) / Linting

unused import: `crate::prelude::Identifier`

warning: unused import: `crate::prelude::Identifier` --> packages/rs-dpp/src/errors/consensus/basic/document/contested_documents_temporarily_not_allowed_error.rs:7:5 | 7 | use crate::prelude::Identifier; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

use crate::block::epoch::EpochIndex;
use bincode::{Decode, Encode};

#[derive(
Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize,
)]
#[error(
"Contested documents are not allowed until epoch {target_epoch}. Current epoch is {current_epoch}"
)]
#[platform_serialize(unversioned)]
pub struct ContestedDocumentsTemporarilyNotAllowedError {
/*

DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION

*/
current_epoch: EpochIndex,
target_epoch: EpochIndex,
}

impl ContestedDocumentsTemporarilyNotAllowedError {
pub fn new(current_epoch: EpochIndex, target_epoch: EpochIndex) -> Self {
Self {
current_epoch,
target_epoch,
}
}
}

impl From<ContestedDocumentsTemporarilyNotAllowedError> for ConsensusError {
fn from(err: ContestedDocumentsTemporarilyNotAllowedError) -> Self {
Self::BasicError(BasicError::ContestedDocumentsTemporarilyNotAllowedError(
err,
))
}
}
2 changes: 2 additions & 0 deletions packages/rs-dpp/src/errors/consensus/basic/document/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod contested_documents_temporarily_not_allowed_error;
mod data_contract_not_present_error;
mod document_creation_not_allowed_error;
mod document_field_max_size_exceeded_error;
Expand All @@ -16,6 +17,7 @@ mod missing_document_transition_type_error;
mod missing_document_type_error;
mod missing_positions_in_document_type_properties_error;

pub use contested_documents_temporarily_not_allowed_error::*;
pub use data_contract_not_present_error::*;
pub use document_creation_not_allowed_error::*;
pub use document_field_max_size_exceeded_error::*;
Expand Down
1 change: 1 addition & 0 deletions packages/rs-dpp/src/errors/consensus/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl ErrorWithCode for BasicError {
Self::InvalidDocumentTypeNameError(_) => 10415,
Self::DocumentCreationNotAllowedError(_) => 10416,
Self::DocumentFieldMaxSizeExceededError(_) => 10417,
Self::ContestedDocumentsTemporarilyNotAllowedError(_) => 10418,

// Identity Errors: 10500-10599
Self::DuplicatedIdentityPublicKeyBasicError(_) => 10500,
Expand Down
4 changes: 4 additions & 0 deletions packages/rs-drive-abci/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,8 @@ pub struct PlatformTestConfig {
pub block_commit_signature_verification: bool,
/// Disable instant lock signature verification
pub disable_instant_lock_signature_verification: bool,
/// Disable temporarily disabled contested documents validation
pub disable_contested_documents_allowance_validation: bool,
}

#[cfg(feature = "testing-config")]
Expand All @@ -821,6 +823,7 @@ impl PlatformTestConfig {
store_platform_state: false,
block_commit_signature_verification: false,
disable_instant_lock_signature_verification: true,
disable_contested_documents_allowance_validation: true,
}
}
}
Expand All @@ -833,6 +836,7 @@ impl Default for PlatformTestConfig {
store_platform_state: true,
block_commit_signature_verification: true,
disable_instant_lock_signature_verification: false,
disable_contested_documents_allowance_validation: true,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ use dpp::prelude::ConsensusValidationResult;
use dpp::serialization::Signable;
use dpp::state_transition::signable_bytes_hasher::SignableBytesHasher;
use dpp::ProtocolError;

use dpp::state_transition::StateTransition;
use dpp::version::{DefaultForPlatformVersion, PlatformVersion};
use crate::error::execution::ExecutionError;
use crate::execution::check_tx::CheckTxLevel;
use crate::execution::types::state_transition_execution_context::StateTransitionExecutionContext;
use crate::execution::validation::state_transition::common::asset_lock::proof::verify_is_not_spent::AssetLockProofVerifyIsNotSpent;
use crate::execution::validation::state_transition::processor::v0::{StateTransitionIdentityBalanceValidationV0, StateTransitionBasicStructureValidationV0, StateTransitionNonceValidationV0, StateTransitionIdentityBasedSignatureValidationV0, StateTransitionStructureKnownInStateValidationV0};
use crate::execution::validation::state_transition::processor::v0::{StateTransitionIdentityBalanceValidationV0, StateTransitionBasicStructureValidationV0, StateTransitionNonceValidationV0, StateTransitionIdentityBasedSignatureValidationV0, StateTransitionStructureKnownInStateValidationV0, StateTransitionAllowanceValidationV0};
use crate::execution::validation::state_transition::ValidationMode;

pub(super) fn state_transition_to_execution_event_for_check_tx_v0<'a, C: CoreRPCLike>(
Expand All @@ -29,9 +28,22 @@ pub(super) fn state_transition_to_execution_event_for_check_tx_v0<'a, C: CoreRPC
let mut state_transition_execution_context =
StateTransitionExecutionContext::default_for_platform_version(platform_version)?;

// TODO: There is no point to have it here. There is "_" arm implemented.
#[allow(unreachable_patterns)]
match check_tx_level {
CheckTxLevel::FirstTimeCheck => {
if state_transition.has_allowance_validation(platform_version)? {
let result = state_transition.validate_allowance(platform, platform_version)?;

if !result.is_valid() {
return Ok(
ConsensusValidationResult::<Option<ExecutionEvent>>::new_with_errors(
result.errors,
),
);
}
}

// Only identity top up and identity create do not have nonces validation
if state_transition.has_nonces_validation() {
let result = state_transition.validate_nonces(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>(
let mut state_transition_execution_context =
StateTransitionExecutionContext::default_for_platform_version(platform_version)?;

if state_transition.has_allowance_validation(platform_version)? {
let result = state_transition.validate_allowance(platform, platform_version)?;

if !result.is_valid() {
return Ok(ConsensusValidationResult::<ExecutionEvent>::new_with_errors(result.errors));
}
}

// Only identity create does not use identity in state validation, because it doesn't yet have the identity in state
let mut maybe_identity = if state_transition.uses_identity_in_state() {
// Validating signature for identity based state transitions (all those except identity create and identity top up)
Expand Down Expand Up @@ -250,6 +258,18 @@ pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>(
})
}

/// A trait for validating state transitions within a blockchain.
pub(crate) trait StateTransitionAllowanceValidationV0 {
/// This means we should validate allowance
fn has_allowance_validation(&self, platform_version: &PlatformVersion) -> Result<bool, Error>;
/// Preliminary validation for a state transition
fn validate_allowance<C: CoreRPCLike>(
&self,
platform: &PlatformRef<C>,
platform_version: &PlatformVersion,
) -> Result<ConsensusValidationResult<()>, Error>;
}

/// A trait for validating state transitions within a blockchain.
pub(crate) trait StateTransitionIdentityBasedSignatureValidationV0 {
/// Validates the identity and signatures of a transaction to ensure its authenticity.
Expand Down Expand Up @@ -971,3 +991,34 @@ impl StateTransitionStateValidationV0 for StateTransition {
}
}
}

impl StateTransitionAllowanceValidationV0 for StateTransition {
fn has_allowance_validation(&self, platform_version: &PlatformVersion) -> Result<bool, Error> {
match self {
StateTransition::DocumentsBatch(st) => st.has_allowance_validation(platform_version),
StateTransition::DataContractCreate(_)
| StateTransition::DataContractUpdate(_)
| StateTransition::IdentityCreate(_)
| StateTransition::IdentityTopUp(_)
| StateTransition::IdentityCreditWithdrawal(_)
| StateTransition::IdentityUpdate(_)
| StateTransition::IdentityCreditTransfer(_)
| StateTransition::MasternodeVote(_) => Ok(false),
}
}

fn validate_allowance<C: CoreRPCLike>(
&self,
platform: &PlatformRef<C>,
platform_version: &PlatformVersion,
) -> Result<ConsensusValidationResult<()>, Error> {
match self {
StateTransition::DocumentsBatch(st) => {
st.validate_allowance(platform, platform_version)
}
_ => Err(Error::Execution(ExecutionError::CorruptedCodeExecution(
"validate_allowance is not implemented for this state transition",
))),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use crate::execution::validation::state_transition::state_transitions::documents_batch::action_validation::document_delete_transition_action::DocumentDeleteTransitionActionValidation;
use crate::execution::validation::state_transition::state_transitions::documents_batch::action_validation::document_create_transition_action::DocumentCreateTransitionActionValidation;
use dpp::state_transition::documents_batch_transition::document_create_transition::v0::v0_methods::DocumentCreateTransitionV0Methods;
use drive::state_transition_action::document::documents_batch::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessorsV0;

Check warning on line 26 in packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/advanced_structure/v0/mod.rs

View workflow job for this annotation

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

unused import: `drive::state_transition_action::document::documents_batch::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessorsV0`

warning: unused import: `drive::state_transition_action::document::documents_batch::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessorsV0` --> packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/advanced_structure/v0/mod.rs:26:5 | 26 | use drive::state_transition_action::document::documents_batch::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessors... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
use drive::state_transition_action::StateTransitionAction;
use drive::state_transition_action::system::bump_identity_data_contract_nonce_action::BumpIdentityDataContractNonceAction;
use crate::error::execution::ExecutionError;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use crate::error::execution::ExecutionError;
use crate::error::Error;
use crate::execution::validation::state_transition::processor::v0::StateTransitionAllowanceValidationV0;
use crate::platform_types::platform::PlatformRef;
use crate::rpc::core::CoreRPCLike;

Check warning on line 5 in packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/allowance/mod.rs

View workflow job for this annotation

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

unused import: `crate::rpc::core::CoreRPCLike`

warning: unused import: `crate::rpc::core::CoreRPCLike` --> packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/allowance/mod.rs:5:5 | 5 | use crate::rpc::core::CoreRPCLike; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition;
use dpp::validation::ConsensusValidationResult;
use dpp::version::PlatformVersion;

mod v0;

impl StateTransitionAllowanceValidationV0 for DocumentsBatchTransition {
fn has_allowance_validation(&self, platform_version: &PlatformVersion) -> Result<bool, Error> {
match platform_version
.drive_abci
.validation_and_processing
.state_transitions
.documents_batch_state_transition
.allowance
{
0 => Ok(true),
version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch {
method: "StateTransition::validate_temporary_disabled_contested_documents"
.to_string(),
known_versions: vec![0],
received: version,
})),
}
}

/// Disable contested document create transitions for the first 3 epochs
fn validate_allowance<C>(
&self,
platform: &PlatformRef<C>,
platform_version: &PlatformVersion,
) -> Result<ConsensusValidationResult<()>, Error> {
match platform_version
.drive_abci
.validation_and_processing
.state_transitions
.documents_batch_state_transition
.allowance
{
0 => Ok(v0::validate_allowance_v0(self, platform)),
version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch {
method: "StateTransition::validate_temporary_disabled_contested_documents"
.to_string(),
known_versions: vec![0],
received: version,
})),
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::platform_types::platform::PlatformRef;
use crate::platform_types::platform_state::v0::PlatformStateV0Methods;
use dpp::block::epoch::EpochIndex;
use dpp::consensus::basic::document::ContestedDocumentsTemporarilyNotAllowedError;
use dpp::state_transition::documents_batch_transition::accessors::DocumentsBatchTransitionAccessorsV0;
use dpp::state_transition::documents_batch_transition::document_create_transition::v0::v0_methods::DocumentCreateTransitionV0Methods;
use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition;
use dpp::validation::ConsensusValidationResult;

pub const TARGET_EPOCH_INDEX: EpochIndex = 3;

#[inline(always)]
pub fn validate_allowance_v0<C>(
state_transition: &DocumentsBatchTransition,
platform: &PlatformRef<C>,
) -> ConsensusValidationResult<()> {
#[cfg(feature = "testing-config")]
if platform
.config
.testing_configs
.disable_contested_documents_allowance_validation
{
return ConsensusValidationResult::new();
}

let block_info = platform.state.last_block_info();

if block_info.epoch.index >= TARGET_EPOCH_INDEX {
return ConsensusValidationResult::new();
}

let is_contested = state_transition.transitions().iter().any(|transition| {
transition
.as_transition_create()
.and_then(|create| create.prefunded_voting_balance().as_ref())
.is_some()
});

if is_contested {
return ConsensusValidationResult::new_with_errors(vec![
ContestedDocumentsTemporarilyNotAllowedError::new(
block_info.epoch.index,
TARGET_EPOCH_INDEX,
)
.into(),
]);
}

ConsensusValidationResult::new()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod action_validation;
mod advanced_structure;
mod allowance;
mod balance;
mod data_triggers;
mod identity_contract_nonce;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#[cfg(test)]
mod tests {

use crate::execution::run_chain_for_strategy;
use crate::strategy::CoreHeightIncrease::RandomCoreHeightIncrease;
use crate::strategy::{MasternodeListChangesStrategy, NetworkStrategy};
Expand Down Expand Up @@ -68,12 +67,7 @@ mod tests {
..Default::default()
},
block_spacing_ms: 3000,
testing_configs: PlatformTestConfig {
block_signing: false,
store_platform_state: false,
block_commit_signature_verification: false,
disable_instant_lock_signature_verification: true,
},
testing_configs: PlatformTestConfig::default_minimal_verifications(),
..Default::default()
};
let mut platform = TestPlatformBuilder::new()
Expand Down
3 changes: 2 additions & 1 deletion packages/rs-drive-abci/tests/strategy_tests/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,7 @@ pub(crate) fn start_chain_for_strategy(
current_votes: Default::default(),
start_time_ms: GENESIS_TIME_MS,
current_time_ms: GENESIS_TIME_MS,
current_identities: Vec::new(),
},
strategy,
config,
Expand Down Expand Up @@ -915,14 +916,14 @@ pub(crate) fn continue_chain_for_strategy(
start_time_ms,
mut current_time_ms,
instant_lock_quorums,
mut current_identities,
} = chain_execution_parameters;
let mut rng = match seed {
StrategyRandomness::SeedEntropy(seed) => StdRng::seed_from_u64(seed),
StrategyRandomness::RNGEntropy(rng) => rng,
};
let quorum_size = config.validator_set.quorum_size;
let first_block_time = start_time_ms;
let mut current_identities = vec![];
let mut signer = strategy.strategy.signer.clone().unwrap_or_default();
let mut i = 0;

Expand Down
Loading
Loading