Skip to content

Commit 36adeab

Browse files
fix(dpp): validate group required power to prevent invalid configurations (#2595)
1 parent be85e0d commit 36adeab

File tree

6 files changed

+63
-7
lines changed

6 files changed

+63
-7
lines changed

packages/rs-dpp/src/data_contract/group/v0/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::consensus::basic::data_contract::{
22
GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError,
3-
GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError,
3+
GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupRequiredPowerIsInvalidError,
44
GroupTotalPowerLessThanRequiredError,
55
};
66
use crate::data_contract::group::accessors::v0::{GroupV0Getters, GroupV0Setters};
@@ -151,6 +151,13 @@ impl GroupMethodsV0 for GroupV0 {
151151
));
152152
}
153153

154+
if self.required_power == 0 || self.required_power() > GROUP_POWER_LIMIT {
155+
return Ok(SimpleConsensusValidationResult::new_with_error(
156+
GroupRequiredPowerIsInvalidError::new(self.required_power, GROUP_POWER_LIMIT)
157+
.into(),
158+
));
159+
}
160+
154161
// If all validations pass, return an empty validation result
155162
Ok(SimpleConsensusValidationResult::new())
156163
}

packages/rs-dpp/src/errors/consensus/basic/basic_error.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ use crate::consensus::basic::data_contract::{
1111
DataContractUniqueIndicesChangedError, DecimalsOverLimitError, DuplicateIndexError,
1212
DuplicateIndexNameError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError,
1313
GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError,
14-
GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError,
15-
IncompatibleDataContractSchemaError, IncompatibleDocumentTypeSchemaError,
16-
IncompatibleRe2PatternError, InvalidCompoundIndexError, InvalidDataContractIdError,
17-
InvalidDataContractVersionError, InvalidDocumentTypeNameError,
14+
GroupPositionDoesNotExistError, GroupRequiredPowerIsInvalidError,
15+
GroupTotalPowerLessThanRequiredError, IncompatibleDataContractSchemaError,
16+
IncompatibleDocumentTypeSchemaError, IncompatibleRe2PatternError, InvalidCompoundIndexError,
17+
InvalidDataContractIdError, InvalidDataContractVersionError, InvalidDocumentTypeNameError,
1818
InvalidDocumentTypeRequiredSecurityLevelError, InvalidIndexPropertyTypeError,
1919
InvalidIndexedPropertyConstraintError, InvalidKeywordCharacterError,
2020
InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError,
@@ -557,6 +557,9 @@ pub enum BasicError {
557557

558558
#[error(transparent)]
559559
MainGroupIsNotDefinedError(MainGroupIsNotDefinedError),
560+
561+
#[error(transparent)]
562+
GroupRequiredPowerIsInvalidError(GroupRequiredPowerIsInvalidError),
560563
}
561564

562565
impl From<BasicError> for ConsensusError {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use crate::consensus::basic::BasicError;
2+
use crate::consensus::ConsensusError;
3+
use crate::data_contract::group::GroupRequiredPower;
4+
use crate::errors::ProtocolError;
5+
use bincode::{Decode, Encode};
6+
use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
7+
use thiserror::Error;
8+
9+
#[derive(
10+
Debug, Error, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize,
11+
)]
12+
#[platform_serialize(unversioned)]
13+
#[error("The required group power {required_power} is invalid. It must be > 0 and <= {max_power}.")]
14+
pub struct GroupRequiredPowerIsInvalidError {
15+
required_power: GroupRequiredPower,
16+
max_power: GroupRequiredPower,
17+
}
18+
19+
impl GroupRequiredPowerIsInvalidError {
20+
pub fn new(required_power: GroupRequiredPower, max_power: GroupRequiredPower) -> Self {
21+
Self {
22+
required_power,
23+
max_power,
24+
}
25+
}
26+
27+
pub fn required_power(&self) -> GroupRequiredPower {
28+
self.required_power
29+
}
30+
31+
pub fn max_power(&self) -> GroupRequiredPower {
32+
self.max_power
33+
}
34+
}
35+
36+
impl From<GroupRequiredPowerIsInvalidError> for ConsensusError {
37+
fn from(err: GroupRequiredPowerIsInvalidError) -> Self {
38+
Self::BasicError(BasicError::GroupRequiredPowerIsInvalidError(err))
39+
}
40+
}

packages/rs-dpp/src/errors/consensus/basic/data_contract/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mod group_member_has_power_of_zero_error;
1515
mod group_member_has_power_over_limit_error;
1616
mod group_non_unilateral_member_power_has_less_than_required_power_error;
1717
mod group_position_does_not_exist_error;
18+
mod group_required_power_is_invalid_error;
1819
mod group_total_power_has_less_than_required_power_error;
1920
mod incompatible_data_contract_schema_error;
2021
mod incompatible_document_type_schema_error;
@@ -86,6 +87,7 @@ pub use group_member_has_power_of_zero_error::*;
8687
pub use group_member_has_power_over_limit_error::*;
8788
pub use group_non_unilateral_member_power_has_less_than_required_power_error::*;
8889
pub use group_position_does_not_exist_error::*;
90+
pub use group_required_power_is_invalid_error::*;
8991
pub use group_total_power_has_less_than_required_power_error::*;
9092
pub use incompatible_document_type_schema_error::*;
9193
pub use invalid_description_length_error::*;

packages/rs-dpp/src/errors/consensus/codes.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ impl ErrorWithCode for BasicError {
116116
Self::InvalidKeywordCharacterError(_) => 10269,
117117
Self::InvalidKeywordLengthError(_) => 10270,
118118
Self::DecimalsOverLimitError(_) => 10271,
119-
Self::MainGroupIsNotDefinedError(_) => 10272,
120119

121120
// Group Errors: 10350-10399
122121
Self::GroupPositionDoesNotExistError(_) => 10350,
@@ -126,6 +125,8 @@ impl ErrorWithCode for BasicError {
126125
Self::GroupExceedsMaxMembersError(_) => 10354,
127126
Self::GroupMemberHasPowerOfZeroError(_) => 10355,
128127
Self::GroupMemberHasPowerOverLimitError(_) => 10356,
128+
Self::MainGroupIsNotDefinedError(_) => 10357,
129+
Self::GroupRequiredPowerIsInvalidError(_) => 10358,
129130

130131
// Document Errors: 10400-10449
131132
Self::DataContractNotPresentError { .. } => 10400,

packages/wasm-dpp/src/errors/consensus/consensus_error.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{
6161
DataTriggerConditionError, DataTriggerExecutionError, DataTriggerInvalidResultError,
6262
};
6363
use wasm_bindgen::{JsError, JsValue};
64-
use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DecimalsOverLimitError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupTotalPowerLessThanRequiredError, InvalidDescriptionLengthError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidKeywordCharacterError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, InvalidTokenLanguageCodeError, InvalidTokenNameCharacterError, InvalidTokenNameLengthError, MainGroupIsNotDefinedError, NewTokensDestinationIdentityOptionRequiredError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError};
64+
use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, DataContractTokenConfigurationUpdateError, DecimalsOverLimitError, DuplicateKeywordsError, GroupExceedsMaxMembersError, GroupMemberHasPowerOfZeroError, GroupMemberHasPowerOverLimitError, GroupNonUnilateralMemberPowerHasLessThanRequiredPowerError, GroupPositionDoesNotExistError, GroupRequiredPowerIsInvalidError, GroupTotalPowerLessThanRequiredError, InvalidDescriptionLengthError, InvalidDocumentTypeRequiredSecurityLevelError, InvalidKeywordCharacterError, InvalidKeywordLengthError, InvalidTokenBaseSupplyError, InvalidTokenDistributionFunctionDivideByZeroError, InvalidTokenDistributionFunctionIncoherenceError, InvalidTokenDistributionFunctionInvalidParameterError, InvalidTokenDistributionFunctionInvalidParameterTupleError, InvalidTokenLanguageCodeError, InvalidTokenNameCharacterError, InvalidTokenNameLengthError, MainGroupIsNotDefinedError, NewTokensDestinationIdentityOptionRequiredError, NonContiguousContractGroupPositionsError, NonContiguousContractTokenPositionsError, TokenPaymentByBurningOnlyAllowedOnInternalTokenError, TooManyKeywordsError, UnknownDocumentActionTokenEffectError, UnknownDocumentCreationRestrictionModeError, UnknownGasFeesPaidByError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError};
6565
use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError};
6666
use dpp::consensus::basic::group::GroupActionNotAllowedOnTransitionError;
6767
use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError};
@@ -810,6 +810,9 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue {
810810
BasicError::MainGroupIsNotDefinedError(e) => {
811811
generic_consensus_error!(MainGroupIsNotDefinedError, e).into()
812812
}
813+
BasicError::GroupRequiredPowerIsInvalidError(e) => {
814+
generic_consensus_error!(GroupRequiredPowerIsInvalidError, e).into()
815+
}
813816
}
814817
}
815818

0 commit comments

Comments
 (0)