Skip to content

Commit

Permalink
chore: add some extra unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
QuantumExplorer committed Oct 12, 2024
1 parent e406d63 commit 66dd35e
Show file tree
Hide file tree
Showing 15 changed files with 758 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@ use crate::data_contract::document_type::v0::DocumentTypeV0;
use crate::document::{Document, DocumentV0Getters};
use crate::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll;
use crate::voting::vote_polls::VotePoll;
use platform_value::btreemap_extensions::BTreeValueMapPathHelper;
use platform_value::Value;
use std::collections::BTreeMap;

impl DocumentTypeV0 {
/// Figures out the prefunded voting balance (v0) for a document in a document type
pub(in crate::data_contract::document_type) fn contested_vote_poll_for_document_v0(
&self,
document: &Document,
) -> Option<VotePoll> {
self.contested_vote_poll_for_document_properties_v0(document.properties())
}

pub(in crate::data_contract::document_type) fn contested_vote_poll_for_document_properties_v0(
&self,
document_properties: &BTreeMap<String, Value>,
) -> Option<VotePoll> {
self.indexes()
.values()
Expand All @@ -18,7 +28,11 @@ impl DocumentTypeV0 {
.field_matches
.iter()
.all(|(field, field_match)| {
if let Some(value) = document.get(field) {
if let Some(value) = document_properties
.get_optional_at_path(field)
.ok()
.flatten()
{
field_match.matches(value)
} else {
false
Expand All @@ -29,7 +43,7 @@ impl DocumentTypeV0 {
}
})
.map(|index| {
let index_values = index.extract_values(document.properties());
let index_values = index.extract_values(document_properties);
VotePoll::ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll {
contract_id: self.data_contract_id,
document_type_name: self.name.clone(),
Expand Down
28 changes: 28 additions & 0 deletions packages/rs-dpp/src/data_contract/document_type/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ pub trait DocumentTypeV0Methods {
document: &Document,
platform_version: &PlatformVersion,
) -> Result<Option<VotePoll>, ProtocolError>;
/// Gets the vote poll associated with a document
fn contested_vote_poll_for_document_properties(
&self,
document_properties: &BTreeMap<String, Value>,
platform_version: &PlatformVersion,
) -> Result<Option<VotePoll>, ProtocolError>;
}

impl DocumentTypeV0Methods for DocumentTypeV0 {
Expand Down Expand Up @@ -399,4 +405,26 @@ impl DocumentTypeV0Methods for DocumentTypeV0 {
}),
}
}

/// Gets the vote poll associated with a document
fn contested_vote_poll_for_document_properties(
&self,
document_properties: &BTreeMap<String, Value>,
platform_version: &PlatformVersion,
) -> Result<Option<VotePoll>, ProtocolError> {
match platform_version
.dpp
.contract_versions
.document_type_versions
.methods
.contested_vote_poll_for_document
{
0 => Ok(self.contested_vote_poll_for_document_properties_v0(document_properties)),
version => Err(ProtocolError::UnknownVersionMismatch {
method: "contested_vote_poll_for_document_properties".to_string(),
known_versions: vec![0],
received: version,
}),
}
}
}
10 changes: 10 additions & 0 deletions packages/rs-dpp/src/data_contract/document_type/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,14 @@ impl<'a> DocumentTypeV0Methods for DocumentTypeRef<'a> {
}
}
}
fn contested_vote_poll_for_document_properties(
&self,
document_properties: &BTreeMap<String, Value>,
platform_version: &PlatformVersion,
) -> Result<Option<VotePoll>, ProtocolError> {
match self {
DocumentTypeRef::V0(v0) => v0
.contested_vote_poll_for_document_properties(document_properties, platform_version),
}
}
}
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 @@ -216,6 +216,7 @@ impl ErrorWithCode for StateError {
Self::DocumentContestNotJoinableError(_) => 40111,
Self::DocumentContestIdentityAlreadyContestantError(_) => 40112,
Self::DocumentContestDocumentWithSameIdAlreadyPresentError(_) => 40113,
Self::DocumentContestNotPaidForError(_) => 40114,

// Identity Errors: 40200-40299
Self::IdentityAlreadyExistsError(_) => 40200,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::consensus::state::state_error::StateError;
use crate::consensus::ConsensusError;
use crate::errors::ProtocolError;
use crate::fee::Credits;
use bincode::{Decode, Encode};
use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
use platform_value::Identifier;
use thiserror::Error;

#[derive(
Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize,
)]
#[error("Contest for document {document_id} was not paid for, needs payment of {expected_amount} Credits")]
#[platform_serialize(unversioned)]
pub struct DocumentContestNotPaidForError {
/*
DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION
*/
document_id: Identifier,

expected_amount: Credits,

paid_amount: Credits,
}

impl DocumentContestNotPaidForError {
pub fn new(document_id: Identifier, expected_amount: Credits, paid_amount: Credits) -> Self {
Self {
document_id,
expected_amount,
paid_amount,
}
}

pub fn document_id(&self) -> &Identifier {
&self.document_id
}

pub fn expected_amount(&self) -> Credits {
self.expected_amount
}

pub fn paid_amount(&self) -> Credits {
self.paid_amount
}
}

impl From<DocumentContestNotPaidForError> for ConsensusError {
fn from(err: DocumentContestNotPaidForError) -> Self {
Self::StateError(StateError::DocumentContestNotPaidForError(err))
}
}
1 change: 1 addition & 0 deletions packages/rs-dpp/src/errors/consensus/state/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod document_contest_currently_locked_error;
pub mod document_contest_document_with_same_id_already_present_error;
pub mod document_contest_identity_already_contestant;
pub mod document_contest_not_joinable_error;
pub mod document_contest_not_paid_for_error;
pub mod document_incorrect_purchase_price_error;
pub mod document_not_for_sale_error;
pub mod document_not_found_error;
Expand Down
4 changes: 4 additions & 0 deletions packages/rs-dpp/src/errors/consensus/state/state_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use crate::consensus::state::document::document_contest_currently_locked_error::
use crate::consensus::state::document::document_contest_document_with_same_id_already_present_error::DocumentContestDocumentWithSameIdAlreadyPresentError;
use crate::consensus::state::document::document_contest_identity_already_contestant::DocumentContestIdentityAlreadyContestantError;
use crate::consensus::state::document::document_contest_not_joinable_error::DocumentContestNotJoinableError;
use crate::consensus::state::document::document_contest_not_paid_for_error::DocumentContestNotPaidForError;
use crate::consensus::state::document::document_incorrect_purchase_price_error::DocumentIncorrectPurchasePriceError;
use crate::consensus::state::document::document_not_for_sale_error::DocumentNotForSaleError;
use crate::consensus::state::identity::identity_public_key_already_exists_for_unique_contract_bounds_error::IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError;
Expand Down Expand Up @@ -81,6 +82,9 @@ pub enum StateError {
#[error(transparent)]
DocumentContestIdentityAlreadyContestantError(DocumentContestIdentityAlreadyContestantError),

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

#[error(transparent)]
DocumentContestDocumentWithSameIdAlreadyPresentError(
DocumentContestDocumentWithSameIdAlreadyPresentError,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ pub(super) fn state_transition_to_execution_event_for_check_tx_v0<'a, C: CoreRPC

// Validating structure
let result = state_transition.validate_advanced_structure_from_state(
platform.state.last_block_info(),
platform.config.network,
&action,
maybe_identity.as_ref(),
&mut state_transition_execution_context,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
use crate::error::execution::ExecutionError;
use crate::error::Error;
use crate::execution::types::execution_event::ExecutionEvent;
use crate::execution::validation::state_transition::transformer::StateTransitionActionTransformerV0;
use crate::platform_types::platform::{PlatformRef, PlatformStateRef};
use crate::platform_types::platform_state::v0::PlatformStateV0Methods;
use crate::rpc::core::CoreRPCLike;
use dpp::block::block_info::BlockInfo;
use dpp::dashcore::Network;
use dpp::fee::Credits;
use dpp::identity::PartialIdentity;
use dpp::prefunded_specialized_balance::PrefundedSpecializedBalanceIdentifier;
use dpp::prelude::ConsensusValidationResult;
use dpp::ProtocolError;
use std::collections::BTreeMap;

use crate::error::execution::ExecutionError;
use dpp::serialization::Signable;
use dpp::state_transition::StateTransition;
use dpp::validation::SimpleConsensusValidationResult;
use dpp::version::{DefaultForPlatformVersion, PlatformVersion};
use dpp::ProtocolError;
use drive::drive::Drive;
use drive::grovedb::TransactionArg;
use drive::state_transition_action::StateTransitionAction;
use std::collections::BTreeMap;

use crate::execution::types::state_transition_execution_context::{StateTransitionExecutionContext};
use crate::execution::validation::state_transition::common::validate_simple_pre_check_balance::ValidateSimplePreCheckBalance;
Expand Down Expand Up @@ -215,6 +215,8 @@ pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>(

// Validating structure
let result = state_transition.validate_advanced_structure_from_state(
block_info,
platform.config.network,
&action,
maybe_identity.as_ref(),
&mut state_transition_execution_context,
Expand Down Expand Up @@ -403,6 +405,8 @@ pub(crate) trait StateTransitionStructureKnownInStateValidationV0 {
/// * `Result<SimpleConsensusValidationResult, Error>` - A result with either a SimpleConsensusValidationResult or an Error.
fn validate_advanced_structure_from_state(
&self,
block_info: &BlockInfo,
network: Network,
action: &StateTransitionAction,
maybe_identity: Option<&PartialIdentity>,
execution_context: &mut StateTransitionExecutionContext,
Expand Down Expand Up @@ -746,13 +750,17 @@ impl StateTransitionAdvancedStructureValidationV0 for StateTransition {
impl StateTransitionStructureKnownInStateValidationV0 for StateTransition {
fn validate_advanced_structure_from_state(
&self,
block_info: &BlockInfo,
network: Network,
action: &StateTransitionAction,
maybe_identity: Option<&PartialIdentity>,
execution_context: &mut StateTransitionExecutionContext,
platform_version: &PlatformVersion,
) -> Result<ConsensusValidationResult<StateTransitionAction>, Error> {
match self {
StateTransition::DocumentsBatch(st) => st.validate_advanced_structure_from_state(
block_info,
network,
action,
maybe_identity,
execution_context,
Expand All @@ -774,6 +782,8 @@ impl StateTransitionStructureKnownInStateValidationV0 for StateTransition {
)
}
StateTransition::MasternodeVote(st) => st.validate_advanced_structure_from_state(
block_info,
network,
action,
maybe_identity,
execution_context,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use dashcore_rpc::dashcore::Network;
use dpp::block::block_info::BlockInfo;
use dpp::identifier::Identifier;
use dpp::validation::SimpleConsensusValidationResult;
Expand All @@ -20,6 +21,8 @@ pub trait DocumentCreateTransitionActionValidation {
fn validate_structure(
&self,
owner_id: Identifier,
block_info: &BlockInfo,
network: Network,
platform_version: &PlatformVersion,
) -> Result<SimpleConsensusValidationResult, Error>;

Expand All @@ -38,6 +41,8 @@ impl DocumentCreateTransitionActionValidation for DocumentCreateTransitionAction
fn validate_structure(
&self,
owner_id: Identifier,
block_info: &BlockInfo,
network: Network,
platform_version: &PlatformVersion,
) -> Result<SimpleConsensusValidationResult, Error> {
match platform_version
Expand All @@ -47,7 +52,7 @@ impl DocumentCreateTransitionActionValidation for DocumentCreateTransitionAction
.documents_batch_state_transition
.document_create_transition_structure_validation
{
0 => self.validate_structure_v0(owner_id, platform_version),
0 => self.validate_structure_v0(owner_id, block_info, network, platform_version),
version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch {
method: "DocumentCreateTransitionAction::validate_structure".to_string(),
known_versions: vec![0],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use dpp::block::block_info::BlockInfo;
use dpp::consensus::basic::document::{DocumentCreationNotAllowedError, InvalidDocumentTypeError};
use dpp::consensus::state::document::document_contest_not_paid_for_error::DocumentContestNotPaidForError;
use dpp::dashcore::Network;
use dpp::data_contract::accessors::v0::DataContractV0Getters;
use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters;
use dpp::data_contract::document_type::methods::DocumentTypeV0Methods;
use dpp::data_contract::document_type::restricted_creation::CreationRestrictionMode;
use dpp::data_contract::validate_document::DataContractDocumentValidationMethodsV0;
use dpp::identifier::Identifier;
Expand All @@ -14,13 +18,17 @@ pub(super) trait DocumentCreateTransitionActionStructureValidationV0 {
fn validate_structure_v0(
&self,
owner_id: Identifier,
block_info: &BlockInfo,
network: Network,
platform_version: &PlatformVersion,
) -> Result<SimpleConsensusValidationResult, Error>;
}
impl DocumentCreateTransitionActionStructureValidationV0 for DocumentCreateTransitionAction {
fn validate_structure_v0(
&self,
owner_id: Identifier,
block_info: &BlockInfo,
network: Network,
platform_version: &PlatformVersion,
) -> Result<SimpleConsensusValidationResult, Error> {
let contract_fetch_info = self.base().data_contract_fetch_info();
Expand All @@ -36,6 +44,37 @@ impl DocumentCreateTransitionActionStructureValidationV0 for DocumentCreateTrans
));
};

// Don't do the following validation on testnet before epoch 2080
// As state transitions already happened that would break this validation
if !(network == Network::Testnet && block_info.epoch.index < 2080) {
if document_type
.contested_vote_poll_for_document_properties(self.data(), platform_version)?
.is_some()
{
let expected_amount = platform_version
.fee_version
.vote_resolution_fund_fees
.contested_document_vote_resolution_fund_required_amount;
if let Some((_, paid_amount)) = self.prefunded_voting_balance() {
if expected_amount != *paid_amount {
return Ok(SimpleConsensusValidationResult::new_with_error(
DocumentContestNotPaidForError::new(
self.base().id(),
expected_amount,
*paid_amount,
)
.into(),
));
}
} else {
return Ok(SimpleConsensusValidationResult::new_with_error(
DocumentContestNotPaidForError::new(self.base().id(), expected_amount, 0)
.into(),
));
}
}
}

match document_type.creation_restriction_mode() {
CreationRestrictionMode::NoRestrictions => {}
CreationRestrictionMode::OwnerOnly => {
Expand Down
Loading

0 comments on commit 66dd35e

Please sign in to comment.