Skip to content

Commit

Permalink
chore!: do not allow contested documents for the first three epochs (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
shumkov authored Aug 24, 2024
1 parent 06414e8 commit e6c5bdc
Show file tree
Hide file tree
Showing 24 changed files with 813 additions and 414 deletions.
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,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::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
1 change: 0 additions & 1 deletion packages/rs-drive-abci/src/abci/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Configuration of ABCI Application server
use crate::utils::from_opt_str_or_number;
use dpp::prelude::TimestampMillis;
use serde::{Deserialize, Serialize};

// We allow changes in the ABCI configuration, but there should be a social process
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_is_allowed_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_is_allowed_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_is_allowed_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, StateTransitionIsAllowedValidationV0};
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_is_allowed_validation(platform_version)? {
let result = state_transition.validate_is_allowed(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_is_allowed_validation(platform_version)? {
let result = state_transition.validate_is_allowed(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 StateTransitionIsAllowedValidationV0 {
/// This means we should validate is state transition is allowed
fn has_is_allowed_validation(&self, platform_version: &PlatformVersion) -> Result<bool, Error>;
/// Preliminary validation for a state transition
fn validate_is_allowed<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 StateTransitionIsAllowedValidationV0 for StateTransition {
fn has_is_allowed_validation(&self, platform_version: &PlatformVersion) -> Result<bool, Error> {
match self {
StateTransition::DocumentsBatch(st) => st.has_is_allowed_validation(platform_version),
StateTransition::DataContractCreate(_)
| StateTransition::DataContractUpdate(_)
| StateTransition::IdentityCreate(_)
| StateTransition::IdentityTopUp(_)
| StateTransition::IdentityCreditWithdrawal(_)
| StateTransition::IdentityUpdate(_)
| StateTransition::IdentityCreditTransfer(_)
| StateTransition::MasternodeVote(_) => Ok(false),
}
}

fn validate_is_allowed<C: CoreRPCLike>(
&self,
platform: &PlatformRef<C>,
platform_version: &PlatformVersion,
) -> Result<ConsensusValidationResult<()>, Error> {
match self {
StateTransition::DocumentsBatch(st) => {
st.validate_is_allowed(platform, platform_version)
}
_ => Err(Error::Execution(ExecutionError::CorruptedCodeExecution(
"validate_is_allowed is not implemented for this state transition",
))),
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::error::execution::ExecutionError;
use crate::error::Error;
use crate::execution::validation::state_transition::processor::v0::StateTransitionIsAllowedValidationV0;
use crate::platform_types::platform::PlatformRef;
use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition;
use dpp::validation::ConsensusValidationResult;
use dpp::version::PlatformVersion;

mod v0;

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

/// Disable contested document create transitions for the first 3 epochs
fn validate_is_allowed<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
.is_allowed
{
0 => Ok(v0::validate_is_allowed_v0(self, platform)),
version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch {
method: "StateTransition::validate_is_allowed".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_is_allowed_v0<C>(
state_transition: &DocumentsBatchTransition,
platform: &PlatformRef<C>,
) -> ConsensusValidationResult<()> {
#[cfg(feature = "testing-config")]
if platform
.config
.testing_configs
.disable_contested_documents_is_allowed_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
Expand Up @@ -3,6 +3,7 @@ mod advanced_structure;
mod balance;
mod data_triggers;
mod identity_contract_nonce;
mod is_allowed;
mod state;
mod transformer;

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

0 comments on commit e6c5bdc

Please sign in to comment.