Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion packages/platform-test-suite/test/e2e/dpns.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe('DPNS', () => {
identity = await ownerClient.platform.identities.get(dpnsOwnerId);

expect(identity).to.exist();
await ownerClient.platform.identities.topUp(dpnsOwnerId, 500);
await ownerClient.platform.identities.topUp(dpnsOwnerId, 1000);
});

after(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const {
Identifier,
IdentityPublicKey,
InvalidInstantAssetLockProofSignatureError,
InvalidAssetLockProofValueError,
IdentityAssetLockTransactionOutPointAlreadyExistsError,
BasicECDSAError,
IdentityPublicKeyWithWitness,
Expand Down Expand Up @@ -55,6 +56,22 @@ describe('Platform', () => {
expect(identity).to.exist();
});

it('should fail to create an identity if asset lock amount is less than minimal', async () => {
let broadcastError;

try {
await client.platform.identities.register(117000);
} catch (e) {
broadcastError = e;
}

expect(broadcastError).to.be.an.instanceOf(StateTransitionBroadcastError);
expect(broadcastError.getCause().getCode()).to.equal(4028);
expect(broadcastError.getCause()).to.be.an.instanceOf(
InvalidAssetLockProofValueError,
);
});

it('should fail to create an identity if instantLock is not valid', async () => {
await client.platform.initialize();

Expand Down Expand Up @@ -440,7 +457,7 @@ describe('Platform', () => {
transaction,
privateKey,
outputIndex,
} = await client.platform.identities.utils.createAssetLockTransaction(1);
} = await client.platform.identities.utils.createAssetLockTransaction(1000);

const account = await client.getWalletAccount();

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 @@ -177,6 +177,7 @@ impl ErrorWithCode for StateError {
Self::MissingIdentityPublicKeyIdsError { .. } => 4024,
Self::IdentityInsufficientBalanceError(_) => 4026,
Self::IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError(_) => 4027,
Self::InvalidAssetLockProofValueError(_) => 4028,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::errors::ProtocolError;
use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
use thiserror::Error;

use crate::consensus::ConsensusError;

use crate::consensus::state::state_error::StateError;
use bincode::{Decode, Encode};

#[derive(
Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize,
)]
#[error("Asset lock value {value:?} must be higher than minimal value of {min_value:?}")]
#[platform_serialize(unversioned)]
pub struct InvalidAssetLockProofValueError {
/*

DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION

*/
value: u64,
min_value: u64,
}

impl InvalidAssetLockProofValueError {
pub fn new(value: u64, min_value: u64) -> Self {
Self { value, min_value }
}

pub fn value(&self) -> u64 {
self.value
}

pub fn min_value(&self) -> u64 {
self.min_value
}
}

impl From<InvalidAssetLockProofValueError> for ConsensusError {
fn from(err: InvalidAssetLockProofValueError) -> Self {
Self::StateError(StateError::InvalidAssetLockProofValueError(err))
}
}
1 change: 1 addition & 0 deletions packages/rs-dpp/src/errors/consensus/state/identity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod identity_public_key_already_exists_for_unique_contract_bounds_error;
pub mod identity_public_key_disabled_at_window_violation_error;
pub mod identity_public_key_is_disabled_error;
pub mod identity_public_key_is_read_only_error;
pub mod invalid_asset_lock_proof_value;
pub mod invalid_identity_public_key_id_error;
pub mod invalid_identity_revision_error;
pub mod max_identity_public_key_limit_reached_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 @@ -29,6 +29,7 @@ use crate::consensus::state::identity::{
};
use crate::consensus::ConsensusError;
use crate::consensus::state::identity::identity_public_key_already_exists_for_unique_contract_bounds_error::IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError;
use crate::consensus::state::identity::invalid_asset_lock_proof_value::InvalidAssetLockProofValueError;

use super::document::document_timestamps_are_equal_error::DocumentTimestampsAreEqualError;

Expand Down Expand Up @@ -85,6 +86,9 @@ pub enum StateError {
#[error(transparent)]
IdentityPublicKeyIsReadOnlyError(IdentityPublicKeyIsReadOnlyError),

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ impl IdentityCreateTransition {
}),
}
}

pub fn get_minimal_asset_lock_value(
platform_version: &PlatformVersion,
) -> Result<u64, ProtocolError> {
match platform_version
.dpp
.state_transitions
.identities
.asset_locks
.minimal_asset_lock_value
{
0 => Ok(MinimalAssetLockValue::V0 as u64),
v => Err(ProtocolError::UnknownVersionError(format!(
"Unknown IdentityCreateTransition version for minimal_asset_lock_value {v}"
))),
}
}
}

impl StateTransitionFieldTypes for IdentityCreateTransition {
Expand All @@ -83,3 +100,8 @@ impl StateTransitionFieldTypes for IdentityCreateTransition {
vec![]
}
}

#[repr(u64)]
pub enum MinimalAssetLockValue {
V0 = 120000,
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,23 @@ impl IdentityTopUpTransition {
}),
}
}

pub fn get_minimal_asset_lock_value(
platform_version: &PlatformVersion,
) -> Result<u64, ProtocolError> {
match platform_version
.dpp
.state_transitions
.identities
.asset_locks
.minimal_asset_lock_value
{
0 => Ok(MinimalAssetLockValue::V0 as u64),
v => Err(ProtocolError::UnknownVersionError(format!(
"Unknown IdentityTopUpTransition version for minimal_asset_lock_value {v}"
))),
}
}
}

impl StateTransitionFieldTypes for IdentityTopUpTransition {
Expand All @@ -82,3 +99,8 @@ impl StateTransitionFieldTypes for IdentityTopUpTransition {
vec![]
}
}

#[repr(u64)]
enum MinimalAssetLockValue {
V0 = 1000,
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ pub fn fetch_asset_lock_transaction_output_sync_v0<C: CoreRPCLike>(
// We are dealing with old Rust edition so we can't use optional remove
if payload.credit_outputs.get(output_index as usize).is_some() {
let output = payload.credit_outputs.remove(output_index as usize);

return Ok(ValidationResult::new_with_data(output));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::platform_types::platform::PlatformRef;
use crate::rpc::core::CoreRPCLike;
use dpp::consensus::signature::{BasicECDSAError, SignatureError};

use dpp::consensus::state::identity::invalid_asset_lock_proof_value::InvalidAssetLockProofValueError;
use dpp::consensus::state::identity::IdentityAlreadyExistsError;
use dpp::dashcore::signer;
use dpp::dashcore::signer::double_sha;
Expand All @@ -12,6 +13,7 @@ use dpp::identity::state_transition::AssetLockProved;
use dpp::prelude::ConsensusValidationResult;
use dpp::serialization::Signable;
use dpp::state_transition::identity_create_transition::accessors::IdentityCreateTransitionAccessorsV0;
use dpp::state_transition::identity_create_transition::methods::IdentityCreateTransitionMethodsV0;
use dpp::state_transition::identity_create_transition::IdentityCreateTransition;
use dpp::state_transition::{StateTransition, StateTransitionLike};

Expand Down Expand Up @@ -125,6 +127,12 @@ impl IdentityCreateStateTransitionStateValidationV0 for IdentityCreateTransition
}

let tx_out = tx_out_validation.into_data()?;
let min_value = IdentityCreateTransition::get_minimal_asset_lock_value(platform_version)?;
if tx_out.value < min_value {
return Ok(ConsensusValidationResult::new_with_error(
InvalidAssetLockProofValueError::new(tx_out.value, min_value).into(),
));
}

// Verify one time signature

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ use crate::platform_types::platform::PlatformRef;
use crate::rpc::core::CoreRPCLike;

use dpp::consensus::signature::{BasicECDSAError, SignatureError};
use dpp::consensus::state::identity::invalid_asset_lock_proof_value::InvalidAssetLockProofValueError;
use dpp::dashcore::signer;
use dpp::dashcore::signer::double_sha;
use dpp::identity::state_transition::AssetLockProved;
use dpp::identity::KeyType;

use dpp::prelude::ConsensusValidationResult;
use dpp::serialization::Signable;
use dpp::state_transition::identity_topup_transition::methods::IdentityTopUpTransitionMethodsV0;
use dpp::state_transition::identity_topup_transition::IdentityTopUpTransition;
use dpp::state_transition::{StateTransition, StateTransitionLike};

Expand Down Expand Up @@ -88,6 +90,12 @@ impl IdentityTopUpStateTransitionStateValidationV0 for IdentityTopUpTransition {
}

let tx_out = tx_out_validation.into_data()?;
let min_value = IdentityTopUpTransition::get_minimal_asset_lock_value(platform_version)?;
if tx_out.value < min_value {
return Ok(ConsensusValidationResult::new_with_error(
InvalidAssetLockProofValueError::new(tx_out.value, min_value).into(),
));
}

// Verify one time signature

Expand Down
1 change: 1 addition & 0 deletions packages/rs-platform-version/src/version/dpp_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct IdentityTransitionVersions {
pub struct IdentityTransitionAssetLockVersions {
pub validate_asset_lock_transaction_structure: FeatureVersion,
pub validate_instant_asset_lock_proof_structure: FeatureVersion,
pub minimal_asset_lock_value: FeatureVersion,
}

#[derive(Clone, Debug, Default)]
Expand Down
1 change: 1 addition & 0 deletions packages/rs-platform-version/src/version/mocks/v2_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,7 @@ pub(crate) const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion {
asset_locks: IdentityTransitionAssetLockVersions {
validate_asset_lock_transaction_structure: 0,
validate_instant_asset_lock_proof_structure: 0,
minimal_asset_lock_value: 0,
},
},
},
Expand Down
1 change: 1 addition & 0 deletions packages/rs-platform-version/src/version/mocks/v3_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,7 @@ pub(crate) const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion {
asset_locks: IdentityTransitionAssetLockVersions {
validate_asset_lock_transaction_structure: 0,
validate_instant_asset_lock_proof_structure: 0,
minimal_asset_lock_value: 0,
},
},
},
Expand Down
1 change: 1 addition & 0 deletions packages/rs-platform-version/src/version/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,7 @@ pub(super) const PLATFORM_V1: PlatformVersion = PlatformVersion {
asset_locks: IdentityTransitionAssetLockVersions {
validate_asset_lock_transaction_structure: 0,
validate_instant_asset_lock_proof_structure: 0,
minimal_asset_lock_value: 0,
},
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use dpp::consensus::codes::ErrorWithCode;
use dpp::consensus::ConsensusError;

use dpp::consensus::state::identity::invalid_asset_lock_proof_value::InvalidAssetLockProofValueError;
use wasm_bindgen::prelude::*;

#[wasm_bindgen(js_name=InvalidAssetLockProofValueError)]
pub struct InvalidAssetLockProofValueErrorWasm {
inner: InvalidAssetLockProofValueError,
}

impl From<&InvalidAssetLockProofValueError> for InvalidAssetLockProofValueErrorWasm {
fn from(e: &InvalidAssetLockProofValueError) -> Self {
Self { inner: e.clone() }
}
}

#[wasm_bindgen(js_class=InvalidAssetLockProofValueError)]
impl InvalidAssetLockProofValueErrorWasm {
#[wasm_bindgen(js_name=getValue)]
pub fn value(&self) -> u64 {
self.inner.value()
}

#[wasm_bindgen(js_name=getMinValue)]
pub fn min_value(&self) -> u64 {
self.inner.min_value()
}

#[wasm_bindgen(js_name=getCode)]
pub fn get_code(&self) -> u32 {
ConsensusError::from(self.inner.clone()).code()
}

#[wasm_bindgen(getter)]
pub fn message(&self) -> String {
self.inner.to_string()
}
}
2 changes: 2 additions & 0 deletions packages/wasm-dpp/src/errors/consensus/basic/identity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod identity_credit_transfer_to_self_error;
mod identity_insufficient_balance_error;
mod invalid_asset_lock_proof_core_chain_height_error;
mod invalid_asset_lock_proof_transaction_height_error;
mod invalid_asset_lock_proof_value_error;
mod invalid_asset_lock_transaction_output_return_size_error;
mod invalid_identity_asset_lock_proof_chain_lock_validation_error;
mod invalid_identity_asset_lock_transaction_error;
Expand All @@ -34,6 +35,7 @@ pub use identity_credit_transfer_to_self_error::*;
pub use identity_insufficient_balance_error::*;
pub use invalid_asset_lock_proof_core_chain_height_error::*;
pub use invalid_asset_lock_proof_transaction_height_error::*;
pub use invalid_asset_lock_proof_value_error::*;
pub use invalid_asset_lock_transaction_output_return_size_error::*;
pub use invalid_identity_asset_lock_proof_chain_lock_validation_error::*;
pub use invalid_identity_asset_lock_transaction_error::*;
Expand Down
5 changes: 4 additions & 1 deletion packages/wasm-dpp/src/errors/consensus/consensus_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::errors::consensus::basic::identity::{
IdentityAssetLockTransactionOutPointAlreadyExistsErrorWasm,
IdentityAssetLockTransactionOutputNotFoundErrorWasm, IdentityCreditTransferToSelfErrorWasm,
IdentityInsufficientBalanceErrorWasm, InvalidAssetLockProofCoreChainHeightErrorWasm,
InvalidAssetLockProofTransactionHeightErrorWasm,
InvalidAssetLockProofTransactionHeightErrorWasm, InvalidAssetLockProofValueErrorWasm,
InvalidAssetLockTransactionOutputReturnSizeErrorWasm,
InvalidIdentityAssetLockProofChainLockValidationErrorWasm,
InvalidIdentityAssetLockTransactionErrorWasm,
Expand Down Expand Up @@ -215,6 +215,9 @@ pub fn from_state_error(state_error: &StateError) -> JsValue {
StateError::DataContractConfigUpdateError(e) => {
DataContractConfigUpdateErrorWasm::from(e).into()
}
StateError::InvalidAssetLockProofValueError(e) => {
InvalidAssetLockProofValueErrorWasm::from(e).into()
}
// TODO(versioning): restore
_ => todo!(),
}
Expand Down