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 1 commit
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,
ContestedDocumentsTemporaryNotAllowedError, 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)]
ContestedDocumentsTemporaryNotAllowedError(ContestedDocumentsTemporaryNotAllowedError),
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
}

impl From<BasicError> for ConsensusError {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
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;

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 ContestedDocumentsTemporaryNotAllowedError {
/*

DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION

*/
current_epoch: EpochIndex,
target_epoch: EpochIndex,
}

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

impl From<ContestedDocumentsTemporaryNotAllowedError> for ConsensusError {
fn from(err: ContestedDocumentsTemporaryNotAllowedError) -> Self {
Self::BasicError(BasicError::ContestedDocumentsTemporaryNotAllowedError(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_temporary_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_temporary_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::ContestedDocumentsTemporaryNotAllowedError(_) => 10418,

// Identity Errors: 10500-10599
Self::DuplicatedIdentityPublicKeyBasicError(_) => 10500,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ 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;
Expand Down Expand Up @@ -65,6 +64,32 @@ pub(super) fn state_transition_to_execution_event_for_check_tx_v0<'a, C: CoreRPC
}
}

// Disable contested document create transitions for the first 2 epochs
// We doing it very top of state transition validation logic to avoid any unnecessary expenses
// for a state transition owner.
let result = state_transition.validate_temporary_disabled_contested_documents(
platform.state.last_block_info(),
platform_version,
)?;
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved

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

let result = state_transition.validate_basic_structure(platform_version)?;
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved

if !result.is_valid() {
return Ok(
ConsensusValidationResult::<Option<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
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ pub mod validate_identity_public_key_ids_exist_in_state;
pub mod validate_not_disabling_last_master_key;
pub mod validate_simple_pre_check_balance;
pub mod validate_state_transition_identity_signed;
mod validate_temporary_disabled_contested_documents;
pub mod validate_unique_identity_public_key_hashes_in_state;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::error::execution::ExecutionError;
use crate::error::Error;
use dpp::block::block_info::BlockInfo;
use dpp::block::epoch::EpochIndex;
use dpp::state_transition::StateTransition;
use dpp::validation::ConsensusValidationResult;
use dpp::version::PlatformVersion;

mod v0;

pub trait ValidateTemporaryDisabledContestedDocuments {
fn validate_temporary_disabled_contested_documents(
&self,
block_info: &BlockInfo,
platform_version: &PlatformVersion,
) -> Result<ConsensusValidationResult<()>, Error>;
}

impl ValidateTemporaryDisabledContestedDocuments for StateTransition {
/// Disable contested document create transitions for the first 2 epochs
fn validate_temporary_disabled_contested_documents(
&self,
block_info: &BlockInfo,
platform_version: &PlatformVersion,
) -> Result<ConsensusValidationResult<()>, Error> {
match platform_version
.drive_abci
.validation_and_processing
.validate_temporary_disabled_contested_documents
{
0 => Ok(v0::validate_temporary_disabled_contested_documents(
self, block_info,
)),
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,41 @@
use dpp::block::block_info::BlockInfo;
use dpp::block::epoch::EpochIndex;
use dpp::consensus::basic::document::ContestedDocumentsTemporaryNotAllowedError;
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::document_transition::DocumentTransition;
use dpp::state_transition::StateTransition;
use dpp::validation::ConsensusValidationResult;

pub const TARGET_EPOCH_INDEX: EpochIndex = 2;

pub fn validate_temporary_disabled_contested_documents(
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
state_transition: &StateTransition,
block_info: &BlockInfo,
) -> ConsensusValidationResult<()> {
if block_info.epoch.index >= TARGET_EPOCH_INDEX {
return ConsensusValidationResult::new();
}

if let StateTransition::DocumentsBatch(transition) = state_transition {
let is_contested = transition.transitions().iter().any(|transition| {
if let DocumentTransition::Create(create) = transition {
create.prefunded_voting_balance().is_some()
} else {
false
}
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
});

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

ConsensusValidationResult::new()
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>(
let mut state_transition_execution_context =
StateTransitionExecutionContext::default_for_platform_version(platform_version)?;

// Disable contested document create transitions for the first 2 epochs
// We doing it very top of state transition validation logic to avoid any unnecessary expenses
// for a state transition owner.
let result = state_transition.validate_temporary_disabled_contested_documents(
platform.state.last_block_info(),
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 @@ -459,7 +471,7 @@ pub(crate) trait StateTransitionPrefundedSpecializedBalanceValidationV0 {

/// A trait for validating state transitions within a blockchain.
pub(crate) trait StateTransitionStateValidationV0:
StateTransitionActionTransformerV0
StateTransitionActionTransformerV0
{
/// Validates the state transition by analyzing the changes in the platform state after applying the transaction.
///
Expand Down
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
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;
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 Expand Up @@ -119,6 +120,21 @@ impl DocumentsBatchStateTransitionStructureValidationV0 for DocumentsBatchTransi
for transition in action.transitions() {
match transition {
DocumentTransitionAction::CreateAction(create_action) => {
if create_action.prefunded_voting_balance().is_some() && block {
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved
let result =
create_action.validate_structure(identity.id, platform_version)?;
if !result.is_valid() {
let bump_action = StateTransitionAction::BumpIdentityDataContractNonceAction(
BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition_action(transition.base().expect("there is always a base for the create action"), self.owner_id(), self.user_fee_increase()),
);

return Ok(ConsensusValidationResult::new_with_data_and_errors(
bump_action,
result.errors,
));
}
}
QuantumExplorer marked this conversation as resolved.
Show resolved Hide resolved

let result = create_action.validate_structure(identity.id, platform_version)?;
if !result.is_valid() {
let bump_action = StateTransitionAction::BumpIdentityDataContractNonceAction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub struct DriveAbciMethodVersions {

#[derive(Clone, Debug, Default)]
pub struct DriveAbciValidationVersions {
pub validate_temporary_disabled_contested_documents: FeatureVersion,
pub state_transitions: DriveAbciStateTransitionValidationVersions,
pub process_state_transition: FeatureVersion,
pub state_transition_to_execution_event_for_check_tx: FeatureVersion,
Expand Down