From 05f2e3e1a4a8a27facb9f77a961303b862082a4c Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Thu, 23 Mar 2023 11:27:26 +0100 Subject: [PATCH 01/12] feat: migrate fees from js-dpp v0.24 --- packages/rs-dpp/src/errors/consensus/fee.rs | 4 +- .../abstract_state_transition.rs | 6 +- .../fee/calculate_operation_fees.rs | 45 ++++ .../fee/calculate_state_transition_fee.rs | 59 ------ .../calculate_state_transition_fee_factory.rs | 15 ++ ..._transition_fee_from_operations_factory.rs | 110 ++++++++++ .../src/state_transition/fee/constants.rs | 20 +- .../rs-dpp/src/state_transition/fee/mod.rs | 52 ++--- .../fee/operations/delete_operation.rs | 33 --- .../state_transition/fee/operations/mod.rs | 60 ++---- .../fee/operations/precalculated_operation.rs | 32 ++- .../fee/operations/read_operation.rs | 19 +- .../signature_verification_operation.rs | 13 +- .../fee/operations/write_operation.rs | 33 --- packages/rs-dpp/src/state_transition/mod.rs | 5 + .../state_transition_execution_context.rs | 6 +- .../validate_state_transition_fee.rs | 198 ++++++++++++++---- 17 files changed, 443 insertions(+), 267 deletions(-) create mode 100644 packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs delete mode 100644 packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee.rs create mode 100644 packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs create mode 100644 packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs delete mode 100644 packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs delete mode 100644 packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs diff --git a/packages/rs-dpp/src/errors/consensus/fee.rs b/packages/rs-dpp/src/errors/consensus/fee.rs index 8ac40f0e920..f831e0c3da1 100644 --- a/packages/rs-dpp/src/errors/consensus/fee.rs +++ b/packages/rs-dpp/src/errors/consensus/fee.rs @@ -1,7 +1,9 @@ use thiserror::Error; +use crate::state_transition::fee::Credits; + #[derive(Error, Debug)] pub enum FeeError { #[error("Current credits balance {balance} is not enough to pay {fee} fee")] - BalanceIsNotEnoughError { balance: u64, fee: i64 }, + BalanceIsNotEnoughError { balance: u64, fee: Credits }, } diff --git a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs index 4102c763bf3..c4ea1639f9c 100644 --- a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs +++ b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs @@ -20,8 +20,8 @@ use crate::{ BlsModule, }; +use super::fee::Credits; use super::{ - fee::calculate_state_transition_fee::calculate_state_transition_fee, state_transition_execution_context::StateTransitionExecutionContext, StateTransition, StateTransitionType, }; @@ -56,10 +56,6 @@ pub trait StateTransitionLike: fn get_signature(&self) -> &Vec; /// set a new signature fn set_signature(&mut self, signature: Vec); - /// Calculates the ST fee in credits - fn calculate_fee(&self) -> i64 { - calculate_state_transition_fee(self) - } /// get modified ids list fn get_modified_data_ids(&self) -> Vec; diff --git a/packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs b/packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs new file mode 100644 index 00000000000..d6fe927df83 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs @@ -0,0 +1,45 @@ +use super::{ + operations::{Operation, OperationLike}, + DummyFeesResult, Refunds, +}; + +pub fn calculate_operation_fees(operations: &[Operation]) -> DummyFeesResult { + let mut storage_fee = 0; + let mut processing_fee = 0; + let mut fee_refunds: Vec = Vec::new(); + + for operation in operations { + storage_fee += operation.get_storage_cost(); + processing_fee += operation.get_processing_cost(); + + // Merge refunds + if let Some(operation_refunds) = operation.get_refunds() { + for identity_refunds in operation_refunds { + let mut existing_identity_refunds = fee_refunds + .iter_mut() + .find(|refund| refund.identifier == identity_refunds.identifier); + + if existing_identity_refunds.is_none() { + fee_refunds.push(identity_refunds.clone()); + continue; + } + + for (epoch_index, credits) in identity_refunds.credits_per_epoch.iter() { + if let Some(ref mut refunds) = existing_identity_refunds { + let epoch = refunds + .credits_per_epoch + .entry(epoch_index.to_string()) + .or_default(); + *epoch += credits + } + } + } + } + } + + DummyFeesResult { + storage: storage_fee, + processing: processing_fee, + fee_refunds, + } +} diff --git a/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee.rs deleted file mode 100644 index 28f34992cd6..00000000000 --- a/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::state_transition::StateTransitionLike; - -use super::{calculate_operations_fees, constants::DEFAULT_USER_TIP}; - -pub fn calculate_state_transition_fee(state_transition: &impl StateTransitionLike) -> i64 { - let execution_context = state_transition.get_execution_context(); - let fee = calculate_operations_fees(execution_context.get_operations()); - - // Is not implemented yet - let storage_refund = 0; - - (fee.storage + fee.processing) + DEFAULT_USER_TIP - storage_refund -} - -#[cfg(test)] -mod test { - use crate::{ - identity::{ - state_transition::identity_create_transition::IdentityCreateTransition, KeyType, - }, - state_transition::{ - fee::operations::{ - DeleteOperation, Operation, PreCalculatedOperation, ReadOperation, WriteOperation, - }, - state_transition_execution_context::StateTransitionExecutionContext, - StateTransitionLike, - }, - tests::fixtures::identity_create_transition_fixture_json, - NativeBlsModule, - }; - - use super::calculate_state_transition_fee; - - // TODO: Must be more comprehensive. After we settle all factors and formula. - #[test] - fn should_calculate_fee_based_on_executed_operations() { - let bls = NativeBlsModule::default(); - let private_key = - hex::decode("af432c476f65211f45f48f1d42c9c0b497e56696aa1736b40544ef1a496af837") - .unwrap(); - let mut state_transition = - IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); - state_transition - .sign_by_private_key(&private_key, KeyType::ECDSA_SECP256K1, &bls) - .expect("signing should be successful"); - - let execution_context = StateTransitionExecutionContext::default(); - execution_context.add_operation(Operation::Read(ReadOperation::new(10))); - execution_context.add_operation(Operation::Write(WriteOperation::new(5, 5))); - execution_context.add_operation(Operation::Delete(DeleteOperation::new(6, 6))); - execution_context.add_operation(Operation::PreCalculated(PreCalculatedOperation::new( - 12, 12, - ))); - state_transition.set_execution_context(execution_context); - - let result = calculate_state_transition_fee(&state_transition); - assert_eq!(13616, result) - } -} diff --git a/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs new file mode 100644 index 00000000000..01d0583746c --- /dev/null +++ b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs @@ -0,0 +1,15 @@ +use crate::state_transition::{ + fee::calculate_state_transition_fee_from_operations_factory::calculate_state_transition_fee_from_operations, + StateTransition, StateTransitionLike, +}; + +use super::FeeResult; + +pub fn calculate_state_transition_fee(state_transition: &StateTransition) -> FeeResult { + let execution_context = state_transition.get_execution_context(); + + calculate_state_transition_fee_from_operations( + &execution_context.get_operations(), + state_transition.get_owner_id(), + ) +} diff --git a/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs new file mode 100644 index 00000000000..a5a7adf92f6 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs @@ -0,0 +1,110 @@ +use crate::prelude::Identifier; + +use super::{ + calculate_operation_fees::calculate_operation_fees, constants::DEFAULT_USER_TIP, + operations::Operation, DummyFeesResult, FeeResult, +}; + +pub fn calculate_state_transition_fee_from_operations( + operations: &[Operation], + identity_id: &Identifier, +) -> FeeResult { + calculate_state_transition_fee_from_operations_with_custom_calculator( + operations, + identity_id, + calculate_operation_fees, + ) +} + +fn calculate_state_transition_fee_from_operations_with_custom_calculator( + operations: &[Operation], + identity_id: &Identifier, + calculate_operation_fees_fn: impl FnOnce(&[Operation]) -> DummyFeesResult, +) -> FeeResult { + let calculated_fees = calculate_operation_fees_fn(operations); + + let storage_fee = calculated_fees.storage; + let processing_fee = calculated_fees.processing; + let fee_refunds = calculated_fees.fee_refunds; + + let mut total_refunds = 0; + + let owner_refunds = fee_refunds + .iter() + .find(|refunds| identity_id == &refunds.identifier); + + if let Some(owner_refunds) = owner_refunds { + total_refunds = owner_refunds + .credits_per_epoch + .iter() + .fold(0, |sum, (_, credits)| sum + credits); + } + + let required_amount = (storage_fee - total_refunds) + DEFAULT_USER_TIP; + let desired_amount = (storage_fee + processing_fee - total_refunds) + DEFAULT_USER_TIP; + + FeeResult { + storage_fee, + processing_fee, + fee_refunds, + total_refunds, + required_amount, + desired_amount, + } +} + +#[cfg(test)] +mod test { + use std::collections::HashMap; + + use crate::{ + state_transition::fee::{ + operations::Operation, Credits, DummyFeesResult, FeeResult, Refunds, + }, + tests::utils::generate_random_identifier_struct, + }; + + use super::calculate_state_transition_fee_from_operations_with_custom_calculator; + + #[test] + fn should_calculate_fee_based_on_executed_operations() { + let identifier = generate_random_identifier_struct(); + let storage_fee = 10000; + let processing_fee = 1000; + let total_refunds = 1000 + 500; + let required_amount = storage_fee - total_refunds; + let desired_amount = storage_fee + processing_fee - total_refunds; + + let mut credits_per_epoch: HashMap = Default::default(); + credits_per_epoch.insert("0".to_string(), 1000); + credits_per_epoch.insert("1".to_string(), 500); + + let refunds = Refunds { + identifier, + credits_per_epoch, + }; + + let mock = |_operations: &[Operation]| -> DummyFeesResult { + DummyFeesResult { + storage: storage_fee, + processing: processing_fee, + fee_refunds: vec![refunds.clone()], + } + }; + + let result = calculate_state_transition_fee_from_operations_with_custom_calculator( + &[], + &identifier, + mock, + ); + let expected = FeeResult { + storage_fee, + processing_fee, + desired_amount, + required_amount, + fee_refunds: vec![refunds], + total_refunds: 1500, + }; + assert_eq!(expected, result); + } +} diff --git a/packages/rs-dpp/src/state_transition/fee/constants.rs b/packages/rs-dpp/src/state_transition/fee/constants.rs index 4ee78de7830..6730ac945b4 100644 --- a/packages/rs-dpp/src/state_transition/fee/constants.rs +++ b/packages/rs-dpp/src/state_transition/fee/constants.rs @@ -1,15 +1,17 @@ use crate::identity::KeyType; -pub const BASE_ST_PROCESSING_FEE: i64 = 10000; // 84000 -pub const FEE_MULTIPLIER: i64 = 2; -pub const DEFAULT_USER_TIP: i64 = 0; -pub const STORAGE_CREDIT_PER_BYTE: i64 = 5000; -pub const PROCESSING_CREDIT_PER_BYTE: i64 = 12; -pub const DELETE_BASE_PROCESSING_COST: i64 = 2000; // 20000 -pub const READ_BASE_PROCESSING_COST: i64 = 8400; // 8400 -pub const WRITE_BASE_PROCESSING_COST: i64 = 6000; // 60000 +use super::Credits; -pub const fn signature_verify_cost(key_type: KeyType) -> i64 { +pub const BASE_ST_PROCESSING_FEE: Credits = 10000; // 84000 +pub const FEE_MULTIPLIER: Credits = 2; +pub const DEFAULT_USER_TIP: Credits = 0; +pub const STORAGE_CREDIT_PER_BYTE: Credits = 5000; +pub const PROCESSING_CREDIT_PER_BYTE: Credits = 12; +pub const DELETE_BASE_PROCESSING_COST: Credits = 2000; // 20000 +pub const READ_BASE_PROCESSING_COST: Credits = 8400; // 8400 +pub const WRITE_BASE_PROCESSING_COST: Credits = 6000; // 60000 + +pub const fn signature_verify_cost(key_type: KeyType) -> Credits { match key_type { KeyType::ECDSA_SECP256K1 => 3000, KeyType::BLS12_381 => 6000, diff --git a/packages/rs-dpp/src/state_transition/fee/mod.rs b/packages/rs-dpp/src/state_transition/fee/mod.rs index eac889b595d..0c0c515eb31 100644 --- a/packages/rs-dpp/src/state_transition/fee/mod.rs +++ b/packages/rs-dpp/src/state_transition/fee/mod.rs @@ -1,33 +1,37 @@ -use std::borrow::Borrow; +use std::collections::HashMap; -use self::{ - constants::FEE_MULTIPLIER, - operations::{Operation, OperationLike}, -}; +use serde::{Deserialize, Serialize}; -pub mod calculate_state_transition_fee; +use crate::prelude::Identifier; + +pub mod calculate_operation_fees; +pub mod calculate_state_transition_fee_factory; +pub mod calculate_state_transition_fee_from_operations_factory; pub mod constants; pub mod operations; -#[derive(Default)] -pub struct Fees { - storage: i64, - processing: i64, -} - -pub fn calculate_operations_fees( - operations: impl IntoIterator>, -) -> Fees { - let mut fees = Fees::default(); +pub type Credits = u64; - for operation in operations.into_iter() { - let operation = operation.borrow(); - fees.processing += operation.get_processing_cost(); - fees.storage += operation.get_storage_cost(); - } +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct FeeResult { + pub storage_fee: Credits, + pub processing_fee: Credits, + pub fee_refunds: Vec, + pub total_refunds: Credits, + pub desired_amount: Credits, + pub required_amount: Credits, +} - fees.storage *= FEE_MULTIPLIER; - fees.processing *= FEE_MULTIPLIER; +#[derive(Default)] +pub struct DummyFeesResult { + storage: Credits, + processing: Credits, + fee_refunds: Vec, +} - fees +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename = "camelCase")] +pub struct Refunds { + pub identifier: Identifier, + pub credits_per_epoch: HashMap, } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs deleted file mode 100644 index 214c19dffc5..00000000000 --- a/packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs +++ /dev/null @@ -1,33 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use super::OperationLike; -use crate::state_transition::fee::constants::{ - DELETE_BASE_PROCESSING_COST, PROCESSING_CREDIT_PER_BYTE, STORAGE_CREDIT_PER_BYTE, -}; - -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct DeleteOperation { - pub key_size: usize, - pub value_size: usize, -} - -impl DeleteOperation { - pub fn new(key_size: usize, value_size: usize) -> Self { - Self { - key_size, - value_size, - } - } -} - -impl OperationLike for DeleteOperation { - fn get_processing_cost(&self) -> i64 { - DELETE_BASE_PROCESSING_COST - + ((self.key_size as i64 + self.value_size as i64) * PROCESSING_CREDIT_PER_BYTE) - } - - fn get_storage_cost(&self) -> i64 { - -((self.key_size + self.value_size) as i64 * STORAGE_CREDIT_PER_BYTE) - } -} diff --git a/packages/rs-dpp/src/state_transition/fee/operations/mod.rs b/packages/rs-dpp/src/state_transition/fee/operations/mod.rs index 7085fd22f74..59430db494a 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/mod.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/mod.rs @@ -1,47 +1,42 @@ -mod delete_operation; - -pub use delete_operation::*; - mod precalculated_operation; pub use precalculated_operation::*; mod read_operation; pub use read_operation::*; -mod write_operation; use serde::{Deserialize, Serialize}; use serde_json::Value; -pub use write_operation::*; mod signature_verification_operation; pub use signature_verification_operation::*; +use super::{Credits, Refunds}; + pub const STORAGE_CREDIT_PER_BYTE: i64 = 5000; pub const STORAGE_PROCESSING_CREDIT_PER_BYTE: i64 = 5000; -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "type", rename_all = "camelCase")] pub enum Operation { Read(ReadOperation), - Write(WriteOperation), - Delete(DeleteOperation), PreCalculated(PreCalculatedOperation), SignatureVerification(SignatureVerificationOperation), } pub trait OperationLike { /// Get CPU cost of the operation - fn get_processing_cost(&self) -> i64; + fn get_processing_cost(&self) -> Credits; /// Get storage cost of the operation - fn get_storage_cost(&self) -> i64; + fn get_storage_cost(&self) -> Credits; + + /// Get refunds + fn get_refunds(&self) -> Option<&Vec>; } macro_rules! call_method { ($operation_type:expr, $method:ident ) => { match $operation_type { Operation::Read(op) => op.$method(), - Operation::Write(op) => op.$method(), - Operation::Delete(op) => op.$method(), Operation::PreCalculated(op) => op.$method(), Operation::SignatureVerification(op) => op.$method(), } @@ -49,13 +44,17 @@ macro_rules! call_method { } impl OperationLike for Operation { - fn get_processing_cost(&self) -> i64 { + fn get_processing_cost(&self) -> Credits { call_method!(self, get_processing_cost) } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { call_method!(self, get_storage_cost) } + + fn get_refunds(&self) -> Option<&Vec> { + call_method!(self, get_refunds) + } } impl Operation { @@ -82,11 +81,8 @@ impl Operation { #[cfg(test)] mod test { - use super::{ - DeleteOperation, Operation, PreCalculatedOperation, ReadOperation, - SignatureVerificationOperation, - }; - use crate::{identity::KeyType, state_transition::fee::operations::WriteOperation}; + use super::{Operation, PreCalculatedOperation, ReadOperation, SignatureVerificationOperation}; + use crate::identity::KeyType; use serde_json::json; struct TestCase { @@ -110,37 +106,17 @@ mod test { }), operation: Operation::Read(ReadOperation { value_size: 123 }), }, - TestCase { - json_str: json_string!({ - "type": "write", - "keySize" : 65, - "valueSize" : 321, - }), - operation: Operation::Write(WriteOperation { - key_size: 65, - value_size: 321, - }), - }, - TestCase { - json_str: json_string!({ - "type": "delete", - "keySize" : 65, - "valueSize" : 123, - }), - operation: Operation::Delete(DeleteOperation { - key_size: 65, - value_size: 123, - }), - }, TestCase { json_str: json_string!({ "type": "preCalculated", "storageCost" : 12357, "processingCost" : 468910, + "feeRefunds" : [], }), operation: Operation::PreCalculated(PreCalculatedOperation { storage_cost: 12357, processing_cost: 468910, + fee_refunds: vec![], }), }, TestCase { diff --git a/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs index f3d57fc96f6..b7cdc272502 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs @@ -1,29 +1,49 @@ use serde::{Deserialize, Serialize}; +use crate::state_transition::fee::{Credits, DummyFeesResult, Refunds}; + use super::OperationLike; -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct PreCalculatedOperation { - pub storage_cost: i64, - pub processing_cost: i64, + pub storage_cost: Credits, + pub processing_cost: Credits, + pub fee_refunds: Vec, } impl PreCalculatedOperation { - pub fn new(storage_cost: i64, processing_cost: i64) -> Self { + pub fn from_fee(fee: DummyFeesResult) -> Self { + Self { + fee_refunds: fee.fee_refunds, + processing_cost: fee.processing, + storage_cost: fee.storage, + } + } + + pub fn new( + storage_cost: Credits, + processing_cost: Credits, + fee_refunds: impl IntoIterator, + ) -> Self { Self { storage_cost, processing_cost, + fee_refunds: fee_refunds.into_iter().collect(), } } } impl OperationLike for PreCalculatedOperation { - fn get_processing_cost(&self) -> i64 { + fn get_processing_cost(&self) -> Credits { self.processing_cost } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { self.storage_cost } + + fn get_refunds(&self) -> Option<&Vec> { + Some(&self.fee_refunds) + } } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs index 5f54ad1a681..007be2e941e 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs @@ -2,28 +2,33 @@ use serde::{Deserialize, Serialize}; use super::OperationLike; -use crate::state_transition::fee::constants::{ - PROCESSING_CREDIT_PER_BYTE, READ_BASE_PROCESSING_COST, +use crate::state_transition::fee::{ + constants::{PROCESSING_CREDIT_PER_BYTE, READ_BASE_PROCESSING_COST}, + Credits, Refunds, }; #[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct ReadOperation { - pub value_size: usize, + pub value_size: Credits, } impl ReadOperation { - pub fn new(value_size: usize) -> Self { + pub fn new(value_size: u64) -> Self { Self { value_size } } } impl OperationLike for ReadOperation { - fn get_processing_cost(&self) -> i64 { - READ_BASE_PROCESSING_COST + (self.value_size as i64 * PROCESSING_CREDIT_PER_BYTE) + fn get_processing_cost(&self) -> Credits { + READ_BASE_PROCESSING_COST + (self.value_size * PROCESSING_CREDIT_PER_BYTE) } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { 0 } + + fn get_refunds(&self) -> Option<&Vec> { + None + } } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs index 0211b196b2f..59d43afb249 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs @@ -1,7 +1,10 @@ use serde::{Deserialize, Serialize}; use super::OperationLike; -use crate::{identity::KeyType, state_transition::fee::constants::signature_verify_cost}; +use crate::{ + identity::KeyType, + state_transition::fee::{constants::signature_verify_cost, Credits, Refunds}, +}; #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] @@ -16,11 +19,15 @@ impl SignatureVerificationOperation { } impl OperationLike for SignatureVerificationOperation { - fn get_processing_cost(&self) -> i64 { + fn get_processing_cost(&self) -> Credits { signature_verify_cost(self.signature_type) } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { 0 } + + fn get_refunds(&self) -> Option<&Vec> { + None + } } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs deleted file mode 100644 index 65b2088e576..00000000000 --- a/packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs +++ /dev/null @@ -1,33 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use super::OperationLike; -use crate::state_transition::fee::constants::{ - PROCESSING_CREDIT_PER_BYTE, STORAGE_CREDIT_PER_BYTE, WRITE_BASE_PROCESSING_COST, -}; - -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct WriteOperation { - pub key_size: usize, - pub value_size: usize, -} - -impl WriteOperation { - pub fn new(key_size: usize, value_size: usize) -> Self { - Self { - key_size, - value_size, - } - } -} - -impl OperationLike for WriteOperation { - fn get_processing_cost(&self) -> i64 { - WRITE_BASE_PROCESSING_COST - + ((self.key_size + self.value_size) as i64 * PROCESSING_CREDIT_PER_BYTE) - } - - fn get_storage_cost(&self) -> i64 { - (self.key_size + self.value_size) as i64 * STORAGE_CREDIT_PER_BYTE - } -} diff --git a/packages/rs-dpp/src/state_transition/mod.rs b/packages/rs-dpp/src/state_transition/mod.rs index 2fe8842692a..cf2dfaa2247 100644 --- a/packages/rs-dpp/src/state_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/mod.rs @@ -14,6 +14,7 @@ use crate::identity::state_transition::identity_create_transition::IdentityCreat use crate::identity::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; use crate::identity::state_transition::identity_topup_transition::IdentityTopUpTransition; use crate::identity::state_transition::identity_update_transition::identity_update_transition::IdentityUpdateTransition; +use crate::prelude::Identifier; mod abstract_state_transition; mod abstract_state_transition_identity_signed; @@ -96,6 +97,10 @@ impl StateTransition { fn binary_property_paths(&self) -> Vec<&'static str> { call_static_method!(self, binary_property_paths) } + + fn get_owner_id(&self) -> &Identifier { + call_method!(self, get_owner_id) + } } impl StateTransitionConvert for StateTransition { diff --git a/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs b/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs index 4ac2f18c1c3..2a524aceb75 100644 --- a/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs +++ b/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs @@ -47,8 +47,10 @@ impl StateTransitionExecutionContext { inner .actual_operations .iter() - .copied() - .chain(inner.dry_run_operations.iter().copied()) + // TODO remove cloning + .cloned() + // TODO remove cloning + .chain(inner.dry_run_operations.iter().cloned()) .collect() } diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs index 68452bee026..4f706131f6e 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs @@ -3,6 +3,8 @@ use std::convert::TryInto; use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; use crate::data_contract::errors::IdentityNotPresentError; +use crate::state_transition::fee::calculate_state_transition_fee_factory::calculate_state_transition_fee; +use crate::state_transition::fee::FeeResult; use crate::state_transition::StateTransitionType; use crate::{ consensus::fee::FeeError, @@ -38,11 +40,20 @@ where pub async fn validate( &self, state_transition: &StateTransition, + ) -> Result { + self.validate_with_custom_calculator(state_transition, calculate_state_transition_fee) + .await + } + + async fn validate_with_custom_calculator( + &self, + state_transition: &StateTransition, + calculate_state_transition_fee_fn: impl Fn(&StateTransition) -> FeeResult, ) -> Result { let mut result = SimpleValidationResult::default(); let execution_context = state_transition.get_execution_context(); - let balance = match state_transition { + let balance_with_possible_debt: i128 = match state_transition { StateTransition::IdentityCreate(st) => { let output = self .asset_lock_transition_output_fetcher @@ -54,7 +65,7 @@ where st.get_asset_lock_proof() ) })?; - convert_satoshi_to_credits(output.value) + convert_satoshi_to_credits(output.value) as i128 } StateTransition::IdentityTopUp(st) => { let output = self @@ -69,44 +80,42 @@ where })?; let balance = convert_satoshi_to_credits(output.value); let identity_id = st.get_owner_id(); - let identity = self + let identity_balance = self .state_repository - .fetch_identity(identity_id, st.get_execution_context()) + .fetch_identity_balance_with_debt(identity_id, execution_context) .await? - .map(TryInto::try_into) - .transpose() - .map_err(Into::into)? - .ok_or_else(|| { - ProtocolError::IdentityNotPresentError(IdentityNotPresentError::new( - identity_id.clone(), - )) - })?; + .context(format!( + "balance for given identity {identity_id} not found" + ))?; if execution_context.is_dry_run() { return Ok(result); } - balance + identity.get_balance() + + // TODO fixme: remove i128. what if identity_balance is negative and absolute value is + // TODO greater than balance (which is u64) + balance as i128 + identity_balance as i128 } StateTransition::DataContractCreate(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::DataContractUpdate(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::DocumentsBatch(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::IdentityUpdate(st) => { @@ -114,7 +123,7 @@ where if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::IdentityCreditWithdrawal(_) => { return Err(ProtocolError::InvalidStateTransitionTypeError( @@ -129,10 +138,14 @@ where return Ok(result); } - let fee = state_transition.calculate_fee(); + let fee = calculate_state_transition_fee_fn(state_transition); + // ? make sure Fee cannot be negative and refunds are handled differently - if (balance as i64) < fee { - result.add_error(FeeError::BalanceIsNotEnoughError { balance, fee }) + if (balance_with_possible_debt) < fee.desired_amount as i128 { + result.add_error(FeeError::BalanceIsNotEnoughError { + balance: balance_with_possible_debt as u64, + fee: fee.desired_amount, + }) } Ok(result) @@ -151,9 +164,7 @@ where .transpose() .map_err(Into::into)? .ok_or_else(|| { - ProtocolError::IdentityNotPresentError(IdentityNotPresentError::new( - identity_id.clone(), - )) + ProtocolError::IdentityNotPresentError(IdentityNotPresentError::new(*identity_id)) })?; Ok(identity.get_balance()) @@ -165,9 +176,15 @@ mod test { use std::sync::Arc; use crate::data_contract::state_transition::data_contract_create_transition::DataContractCreateTransition; + use crate::identity::state_transition::asset_lock_proof::AssetLockProof; + use crate::identity::state_transition::identity_create_transition::IdentityCreateTransition; use crate::identity::state_transition::identity_topup_transition::IdentityTopUpTransition; - use crate::state_transition::StateTransitionLike; - use crate::tests::fixtures::identity_topup_transition_fixture_json; + use crate::identity::RATIO; + use crate::state_transition::fee::{Credits, FeeResult}; + use crate::state_transition::StateTransition; + use crate::tests::fixtures::{ + identity_create_transition_fixture_json, identity_topup_transition_fixture_json, + }; use crate::ProtocolError; use crate::{ consensus::fee::FeeError, @@ -190,17 +207,33 @@ mod test { use super::StateTransitionFeeValidator; fn execution_context_with_cost( - storage_cost: i64, - processing_cost: i64, + storage_cost: Credits, + processing_cost: Credits, ) -> StateTransitionExecutionContext { let ctx = StateTransitionExecutionContext::default(); + // TODO fixme ctx.add_operation(Operation::PreCalculated(PreCalculatedOperation::new( storage_cost, processing_cost, + vec![], ))); ctx } + macro_rules! get_output_amount_from_identity_transition { + ($transition:ident) => { + if let AssetLockProof::Instant(lock_proof) = $transition.get_asset_lock_proof() { + let satoshis = lock_proof + .output() + .expect("output must be present in instant lock proof") + .value; + satoshis * RATIO + } else { + panic!("identity must have an instant lock proof") + } + }; + } + #[tokio::test] async fn data_contract_crate_transition_invalid_result_if_balance_is_not_enough() { let mut identity = identity_fixture(); @@ -228,8 +261,7 @@ mod test { let fee_error = get_fee_error_from_result(&result, 0); assert!( matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, fee } if { - *balance == 1 && - *fee == 90 + *balance == 1 }) ); } @@ -239,7 +271,7 @@ mod test { let mut identity = identity_fixture(); let mut state_repository_mock = MockStateRepositoryLike::new(); - identity.balance = 90; + identity.balance = 52; state_repository_mock .expect_fetch_identity() .returning(move |_, _| Ok(Some(identity.clone()))); @@ -289,9 +321,8 @@ mod test { let fee_error = get_fee_error_from_result(&result, 0); assert!( - matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, fee } if { - *balance == 1 && - *fee == 90 + matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, .. } if { + *balance == 1 }) ); } @@ -357,33 +388,114 @@ mod test { assert!(result.is_valid()); } + #[tokio::test] + async fn identity_create_transition_should_return_invalid_result_if_asset_lock_output_amount_is_not_enough( + ) { + let identity_create_transition = + IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); + let state_repository_mock = MockStateRepositoryLike::new(); + let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount + 1, + ..Default::default() + }; + + let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); + let result = validator + .validate_with_custom_calculator( + &identity_create_transition.into(), + calculate_state_transition_fee_mock, + ) + .await + .expect("the validation result should be returned"); + let fee_error = get_fee_error_from_result(&result, 0); + + assert!( + matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, .. } if { + *balance == output_amount + }) + ); + } + + #[tokio::test] + async fn identity_create_transition_should_return_valid_result() { + let identity_create_transition = + IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); + let state_repository_mock = MockStateRepositoryLike::new(); + let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount, + ..Default::default() + }; + let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); + let result = validator + .validate_with_custom_calculator( + &identity_create_transition.into(), + calculate_state_transition_fee_mock, + ) + .await + .expect("the validation result should be returned"); + assert!(result.is_valid()) + } + #[tokio::test] async fn identity_top_up_transition_should_return_invalid_result_if_balance_is_not_enough() { - let mut identity = identity_fixture(); let mut state_repository_mock = MockStateRepositoryLike::new(); - identity.balance = 1; state_repository_mock - .expect_fetch_identity() - .returning(move |_, _| Ok(Some(identity.clone()))); + .expect_fetch_identity_balance_with_debt() + .returning(move |_, _| Ok(Some(1))); - let mut identity_topup_transition = + let identity_topup_transition = IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); - identity_topup_transition.set_execution_context(execution_context_with_cost(45000000, 5)); + let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); + + let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount + 2, + ..Default::default() + }; let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); let result = validator - .validate(&identity_topup_transition.into()) + .validate_with_custom_calculator( + &identity_topup_transition.into(), + calculate_state_transition_fee_mock, + ) .await .expect("the validation result should be returned"); + let fee_error = get_fee_error_from_result(&result, 0); assert!( - matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, fee } if { - *balance == 90000001 && - *fee == 90000010 + matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, .. } if { + *balance == output_amount + 1 }) ); } + #[tokio::test] + async fn identity_top_up_transition_should_return_valid_result() { + let mut state_repository_mock = MockStateRepositoryLike::new(); + state_repository_mock + .expect_fetch_identity_balance_with_debt() + .returning(move |_, _| Ok(Some(41))); + + let identity_topup_transition = + IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); + let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); + + let calculation_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount - 1, + ..Default::default() + }; + + let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); + let result = validator + .validate_with_custom_calculator(&identity_topup_transition.into(), calculation_mock) + .await + .expect("the validation result should be returned"); + + assert!(result.is_valid()) + } + #[tokio::test] async fn should_return_invalid_state_transition_type() { let transition = IdentityCreditWithdrawalTransition::default(); From c0b6abf2511a977c1e399a04491068469acd74d7 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Thu, 23 Mar 2023 11:58:46 +0100 Subject: [PATCH 02/12] fixes after merge --- .../abstract_state_transition.rs | 1 - .../validate_state_transition_fee.rs | 19 ++++++++----------- .../document_batch_transition/mod.rs | 5 ----- .../wasm-dpp/src/errors/consensus_error.rs | 3 ++- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs index b0aeda63842..74c3296c4d6 100644 --- a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs +++ b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs @@ -18,7 +18,6 @@ use crate::{ BlsModule, }; -use super::fee::Credits; use super::{ state_transition_execution_context::StateTransitionExecutionContext, StateTransition, StateTransitionType, diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs index c6689aa5aa5..7fa55ce8397 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs @@ -80,13 +80,10 @@ where })?; let balance = convert_satoshi_to_credits(output.value); let identity_id = st.get_owner_id(); - let identity_balance = self + let identity_balance: i64 = self .state_repository .fetch_identity_balance_with_debt(identity_id, execution_context) .await? - .map(TryInto::try_into) - .transpose() - .map_err(Into::into)? .ok_or_else(|| { ProtocolError::IdentityNotPresentError(IdentityNotPresentError::new( *identity_id, @@ -178,6 +175,9 @@ where #[cfg(test)] mod test { + use crate::tests::fixtures::{ + identity_create_transition_fixture, identity_topup_transition_fixture, + }; use std::sync::Arc; use crate::data_contract::state_transition::data_contract_create_transition::DataContractCreateTransition; @@ -187,9 +187,6 @@ mod test { use crate::identity::RATIO; use crate::state_transition::fee::{Credits, FeeResult}; use crate::state_transition::StateTransition; - use crate::tests::fixtures::{ - identity_create_transition_fixture_json, identity_topup_transition_fixture_json, - }; use crate::ProtocolError; use crate::{ consensus::fee::FeeError, @@ -397,7 +394,7 @@ mod test { async fn identity_create_transition_should_return_invalid_result_if_asset_lock_output_amount_is_not_enough( ) { let identity_create_transition = - IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + IdentityCreateTransition::new(identity_create_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); let state_repository_mock = MockStateRepositoryLike::new(); let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { @@ -425,7 +422,7 @@ mod test { #[tokio::test] async fn identity_create_transition_should_return_valid_result() { let identity_create_transition = - IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + IdentityCreateTransition::new(identity_create_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); let state_repository_mock = MockStateRepositoryLike::new(); let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { @@ -451,7 +448,7 @@ mod test { .returning(move |_, _| Ok(Some(1))); let identity_topup_transition = - IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); + IdentityTopUpTransition::new(identity_topup_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { @@ -484,7 +481,7 @@ mod test { .returning(move |_, _| Ok(Some(41))); let identity_topup_transition = - IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); + IdentityTopUpTransition::new(identity_topup_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); let calculation_mock = |_: &StateTransition| FeeResult { diff --git a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs index 7e15b529050..ddebf0e65cc 100644 --- a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs @@ -329,11 +329,6 @@ impl DocumentsBatchTransitionWasm { self.0.set_signature(BinaryData::new(signature)) } - #[wasm_bindgen(js_name=calculateFee)] - pub fn calculate_fee(&self) -> i64 { - self.0.calculate_fee() - } - #[wasm_bindgen(js_name=isDocumentStateTransition)] pub fn is_document_state_transition(&self) -> bool { self.0.is_document_state_transition() diff --git a/packages/wasm-dpp/src/errors/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus_error.rs index b067c1808e5..7453d0133f9 100644 --- a/packages/wasm-dpp/src/errors/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus_error.rs @@ -185,7 +185,8 @@ pub fn from_consensus_error_ref(e: &DPPConsensusError) -> JsValue { } DPPConsensusError::FeeError(e) => match e { dpp::consensus::fee::FeeError::BalanceIsNotEnoughError { balance, fee } => { - BalanceIsNotEnoughErrorWasm::new(*balance, *fee, code).into() + // TODO decide about type for Fee + BalanceIsNotEnoughErrorWasm::new(*balance, *fee as i64, code).into() } }, DPPConsensusError::SignatureError(e) => from_signature_error(e), From bccb9413af9be198a18aa24a6211bdc5dec4dfae Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Fri, 24 Mar 2023 12:01:23 +0100 Subject: [PATCH 03/12] fix comment --- .../validate_state_transition_fee.rs | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs index 7fa55ce8397..174a337c97c 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs @@ -4,7 +4,7 @@ use std::convert::TryInto; use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; use crate::data_contract::errors::IdentityNotPresentError; use crate::state_transition::fee::calculate_state_transition_fee_factory::calculate_state_transition_fee; -use crate::state_transition::fee::FeeResult; +use crate::state_transition::fee::{Credits, FeeResult}; use crate::state_transition::StateTransitionType; use crate::{ consensus::fee::FeeError, @@ -53,7 +53,9 @@ where let mut result = SimpleValidationResult::default(); let execution_context = state_transition.get_execution_context(); - let balance_with_possible_debt: i128 = match state_transition { + let required_fee = calculate_state_transition_fee_fn(state_transition); + + let balance = match state_transition { StateTransition::IdentityCreate(st) => { let output = self .asset_lock_transition_output_fetcher @@ -65,7 +67,7 @@ where st.get_asset_lock_proof() ) })?; - convert_satoshi_to_credits(output.value) as i128 + convert_satoshi_to_credits(output.value) } StateTransition::IdentityTopUp(st) => { let output = self @@ -94,30 +96,40 @@ where return Ok(result); } - // TODO fixme: remove i128. what if identity_balance is negative and absolute value is - // TODO greater than balance (which is u64) - balance as i128 + identity_balance as i128 + if identity_balance.is_negative() && identity_balance.unsigned_abs() > balance { + result.add_error(FeeError::BalanceIsNotEnoughError { + balance: 0, + fee: required_fee.desired_amount, + }); + return Ok(result); + } + + if identity_balance.is_negative() { + balance - identity_balance.unsigned_abs() + } else { + balance + identity_balance as Credits + } } StateTransition::DataContractCreate(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance as i128 + balance } StateTransition::DataContractUpdate(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance as i128 + balance } StateTransition::DocumentsBatch(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance as i128 + balance } StateTransition::IdentityUpdate(st) => { @@ -125,7 +137,7 @@ where if execution_context.is_dry_run() { return Ok(result); } - balance as i128 + balance } StateTransition::IdentityCreditWithdrawal(_) => { return Err(ProtocolError::InvalidStateTransitionTypeError( @@ -140,13 +152,11 @@ where return Ok(result); } - let fee = calculate_state_transition_fee_fn(state_transition); - // ? make sure Fee cannot be negative and refunds are handled differently - if (balance_with_possible_debt) < fee.desired_amount as i128 { + if balance < required_fee.desired_amount { result.add_error(FeeError::BalanceIsNotEnoughError { - balance: balance_with_possible_debt as u64, - fee: fee.desired_amount, + balance, + fee: required_fee.desired_amount, }) } @@ -213,7 +223,6 @@ mod test { processing_cost: Credits, ) -> StateTransitionExecutionContext { let ctx = StateTransitionExecutionContext::default(); - // TODO fixme ctx.add_operation(Operation::PreCalculated(PreCalculatedOperation::new( storage_cost, processing_cost, From e76c285ee6fdcb24d4abc281dcdda59d1a9c1012 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Fri, 24 Mar 2023 12:23:49 +0100 Subject: [PATCH 04/12] fix entropy generator implementation in rs drive --- packages/rs-drive/src/drive/test_utils.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rs-drive/src/drive/test_utils.rs b/packages/rs-drive/src/drive/test_utils.rs index 61240e3d254..f37c4ccf908 100644 --- a/packages/rs-drive/src/drive/test_utils.rs +++ b/packages/rs-drive/src/drive/test_utils.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; -use dpp::util::entropy_generator::EntropyGenerator; +use dpp::{dashcore::anyhow, util::entropy_generator::EntropyGenerator}; use rand::{rngs::SmallRng, Rng, SeedableRng}; pub(crate) struct TestEntropyGenerator { @@ -16,7 +16,7 @@ impl TestEntropyGenerator { } impl EntropyGenerator for TestEntropyGenerator { - fn generate(&self) -> [u8; 32] { - self.rng.borrow_mut().gen() + fn generate(&self) -> anyhow::Result<[u8; 32]> { + Ok(self.rng.borrow_mut().gen()) } } From a63646f6b06e80e7d237260ac5466d230760454e Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Fri, 24 Mar 2023 12:27:59 +0100 Subject: [PATCH 05/12] fix types in balance fee error --- packages/rs-dpp/src/errors/consensus/fee.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rs-dpp/src/errors/consensus/fee.rs b/packages/rs-dpp/src/errors/consensus/fee.rs index f831e0c3da1..94db1a656c7 100644 --- a/packages/rs-dpp/src/errors/consensus/fee.rs +++ b/packages/rs-dpp/src/errors/consensus/fee.rs @@ -5,5 +5,5 @@ use crate::state_transition::fee::Credits; #[derive(Error, Debug)] pub enum FeeError { #[error("Current credits balance {balance} is not enough to pay {fee} fee")] - BalanceIsNotEnoughError { balance: u64, fee: Credits }, + BalanceIsNotEnoughError { balance: Credits, fee: Credits }, } From 11c130c0033bb83ba90165e794c2075c8be2db35 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Mon, 20 Mar 2023 08:54:51 +0100 Subject: [PATCH 06/12] feat: add fee api wasm bindings --- .../fee/calculate_operation_fees.rs | 20 ++++++ .../fee/calculate_state_transition_fee.rs | 20 ++++++ .../wasm-dpp/src/state_transition/fee/mod.rs | 42 ++++++++++++ .../fee/operations copy/mod.rs | 0 .../fee/operations copy/read_operation.rs | 52 ++++++++++++++ .../state_transition/fee/operations/mod.rs | 9 +++ .../operations/pre_calculated_operation.rs | 67 +++++++++++++++++++ .../fee/operations/read_operation.rs | 52 ++++++++++++++ .../signature_verification_operation.rs | 61 +++++++++++++++++ .../fee/operations/write_operation.rs | 53 +++++++++++++++ packages/wasm-dpp/src/state_transition/mod.rs | 1 + 11 files changed, 377 insertions(+) create mode 100644 packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/mod.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/operations copy/mod.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/operations/mod.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs diff --git a/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs b/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs new file mode 100644 index 00000000000..94167f3a70b --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs @@ -0,0 +1,20 @@ +use dpp::state_transition::fee::{calculate_operations_fees, operations::Operation}; +use wasm_bindgen::prelude::*; + +use crate::{ + fee::FeesWasm, + utils::{Inner, IntoWasm}, +}; + +use super::OperationWasm; + +#[wasm_bindgen(js_name=calculateOperationFees)] +pub fn calculate_operation_fees_wasm(operations: js_sys::Array) -> Result { + let mut inner_operations: Vec = vec![]; + for operation in operations.iter() { + let operation = operation.to_wasm::("Operation")?.to_owned(); + inner_operations.push(operation.into_inner()) + } + + Ok(calculate_operations_fees(inner_operations).into()) +} diff --git a/packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs b/packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs new file mode 100644 index 00000000000..8fe5835a092 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs @@ -0,0 +1,20 @@ +use dpp::{ + consensus::basic::state_transition, + state_transition::{ + fee::calculate_state_transition_fee::calculate_state_transition_fee, StateTransition, + }, +}; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::conversion::create_state_transition_from_wasm_instance; + +#[wasm_bindgen(js_name=calculateStateTransitionFee)] +pub fn calculate_state_transition_fee_wasm( + state_transition_js: &JsValue, +) -> Result { + let state_transition = create_state_transition_from_wasm_instance(state_transition_js)?; + + let fee = calculate_state_transition_fee(&state_transition); + Ok(BigInt::from(fee)) +} diff --git a/packages/wasm-dpp/src/state_transition/fee/mod.rs b/packages/wasm-dpp/src/state_transition/fee/mod.rs new file mode 100644 index 00000000000..19e5f6ac5e4 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/mod.rs @@ -0,0 +1,42 @@ +use dpp::state_transition::fee::{calculate_operations_fees, operations::Operation, Fees}; +use wasm_bindgen::prelude::*; + +use crate::utils::Inner; +mod calculate_operation_fees; +mod calculate_state_transition_fee; +mod operations; + +#[wasm_bindgen(js_name=Fees)] +pub struct FeesWasm(Fees); + +#[wasm_bindgen(js_name=Operation)] +#[derive(Clone)] +pub struct OperationWasm(Operation); + +impl From for OperationWasm { + fn from(value: Operation) -> Self { + OperationWasm(value) + } +} + +impl From for FeesWasm { + fn from(value: Fees) -> Self { + FeesWasm(value) + } +} + +impl Inner for OperationWasm { + type InnerItem = Operation; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/fee/operations copy/mod.rs b/packages/wasm-dpp/src/state_transition/fee/operations copy/mod.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs new file mode 100644 index 00000000000..c2fc3fba991 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs @@ -0,0 +1,52 @@ +use dpp::state_transition::fee::operations::{OperationLike, ReadOperation}; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::utils::{try_to_u64, Inner, WithJsError}; + +#[wasm_bindgen(js_name = "ReadOperation")] +#[derive(Clone)] +pub struct ReadOperationWasm(ReadOperation); + +impl From for ReadOperationWasm { + fn from(value: ReadOperation) -> Self { + ReadOperationWasm(value) + } +} + +#[wasm_bindgen(js_class=ReadOperation)] +impl ReadOperationWasm { + #[wasm_bindgen(constructor)] + pub fn new(value_size: JsValue) -> Result { + let value_size = try_to_u64(value_size).with_js_error()?; + + // TODO remove `as usize` + Ok(ReadOperation::new(value_size as usize).into()) + } + + #[wasm_bindgen(js_name = getProcessingCost)] + pub fn get_processing_cost(&self) -> BigInt { + BigInt::from(self.0.get_processing_cost()) + } + + #[wasm_bindgen(js_name=getStorageCost)] + pub fn get_storage_cost(&self) -> BigInt { + BigInt::from(self.0.get_storage_cost()) + } +} + +impl Inner for ReadOperationWasm { + type InnerItem = ReadOperation; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/mod.rs b/packages/wasm-dpp/src/state_transition/fee/operations/mod.rs new file mode 100644 index 00000000000..d027a631046 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/operations/mod.rs @@ -0,0 +1,9 @@ +mod pre_calculated_operation; +mod read_operation; +mod signature_verification_operation; +mod write_operation; + +pub use pre_calculated_operation::*; +pub use read_operation::*; +pub use signature_verification_operation::*; +pub use write_operation::*; diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs new file mode 100644 index 00000000000..e1741b04281 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs @@ -0,0 +1,67 @@ +use std::convert::TryInto; + +use anyhow::anyhow; +use dpp::state_transition::fee::operations::{OperationLike, PreCalculatedOperation}; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::utils::{try_to_u64, Inner, WithJsError}; + +#[wasm_bindgen(js_name = "PreCalculatedOperation")] +#[derive(Clone)] +pub struct PreCalculatedOperationWasm(PreCalculatedOperation); + +impl From for PreCalculatedOperationWasm { + fn from(value: PreCalculatedOperation) -> Self { + PreCalculatedOperationWasm(value) + } +} + +#[wasm_bindgen(js_class=PreCalculatedOperation)] +impl PreCalculatedOperationWasm { + #[wasm_bindgen(constructor)] + pub fn new( + storage_cost: JsValue, + processing_cost: JsValue, + ) -> Result { + let storage_cost: i64 = try_to_u64(storage_cost) + .with_js_error()? + .try_into() + .map_err(|e| anyhow!("unable convert storage cost to i64: {}", e)) + .with_js_error()?; + + let processing_cost: i64 = try_to_u64(processing_cost) + .with_js_error()? + .try_into() + .map_err(|e| anyhow!("unable convert processing_cost to i64: {}", e)) + .with_js_error()?; + + Ok(PreCalculatedOperation::new(storage_cost, processing_cost).into()) + } + + #[wasm_bindgen(js_name = getProcessingCost)] + pub fn get_processing_cost(&self) -> BigInt { + BigInt::from(self.0.get_processing_cost()) + } + + #[wasm_bindgen(js_name=getStorageCost)] + pub fn get_storage_cost(&self) -> BigInt { + BigInt::from(self.0.get_storage_cost()) + } +} + +impl Inner for PreCalculatedOperationWasm { + type InnerItem = PreCalculatedOperation; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs new file mode 100644 index 00000000000..c2fc3fba991 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs @@ -0,0 +1,52 @@ +use dpp::state_transition::fee::operations::{OperationLike, ReadOperation}; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::utils::{try_to_u64, Inner, WithJsError}; + +#[wasm_bindgen(js_name = "ReadOperation")] +#[derive(Clone)] +pub struct ReadOperationWasm(ReadOperation); + +impl From for ReadOperationWasm { + fn from(value: ReadOperation) -> Self { + ReadOperationWasm(value) + } +} + +#[wasm_bindgen(js_class=ReadOperation)] +impl ReadOperationWasm { + #[wasm_bindgen(constructor)] + pub fn new(value_size: JsValue) -> Result { + let value_size = try_to_u64(value_size).with_js_error()?; + + // TODO remove `as usize` + Ok(ReadOperation::new(value_size as usize).into()) + } + + #[wasm_bindgen(js_name = getProcessingCost)] + pub fn get_processing_cost(&self) -> BigInt { + BigInt::from(self.0.get_processing_cost()) + } + + #[wasm_bindgen(js_name=getStorageCost)] + pub fn get_storage_cost(&self) -> BigInt { + BigInt::from(self.0.get_storage_cost()) + } +} + +impl Inner for ReadOperationWasm { + type InnerItem = ReadOperation; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs new file mode 100644 index 00000000000..22f97eedba6 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs @@ -0,0 +1,61 @@ +use std::convert::TryFrom; + +use anyhow::anyhow; +use dpp::{ + identity::KeyType, + state_transition::fee::operations::{ + OperationLike, SignatureVerificationOperation, + }, +}; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::utils::{Inner, WithJsError}; + +#[wasm_bindgen(js_name = "SignatureVerificationOperation")] +#[derive(Clone)] +pub struct SignatureVerificationOperationWasm(SignatureVerificationOperation); + +impl From for SignatureVerificationOperationWasm { + fn from(value: SignatureVerificationOperation) -> Self { + SignatureVerificationOperationWasm(value) + } +} + +#[wasm_bindgen(js_class=SignatureVerificationOperation)] +impl SignatureVerificationOperationWasm { + #[wasm_bindgen(constructor)] + pub fn new(signature_type: u8) -> Result { + let key_type = KeyType::try_from(signature_type) + .map_err(|e| anyhow!("invalid key type: {}", e)) + .with_js_error()?; + + Ok(SignatureVerificationOperation::new(key_type).into()) + } + + #[wasm_bindgen(js_name = getProcessingCost)] + pub fn get_processing_cost(&self) -> BigInt { + BigInt::from(self.0.get_processing_cost()) + } + + #[wasm_bindgen(js_name=getStorageCost)] + pub fn get_storage_cost(&self) -> BigInt { + BigInt::from(self.0.get_storage_cost()) + } +} + +impl Inner for SignatureVerificationOperationWasm { + type InnerItem = SignatureVerificationOperation; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs new file mode 100644 index 00000000000..1deace02501 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs @@ -0,0 +1,53 @@ +use dpp::state_transition::fee::operations::{OperationLike, WriteOperation}; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::utils::{try_to_u64, Inner, WithJsError}; + +#[wasm_bindgen(js_name = "WriteOperation")] +#[derive(Clone)] +pub struct WriteOperationWasm(WriteOperation); + +impl From for WriteOperationWasm { + fn from(value: WriteOperation) -> Self { + WriteOperationWasm(value) + } +} + +#[wasm_bindgen(js_class=WriteOperation)] +impl WriteOperationWasm { + #[wasm_bindgen(constructor)] + pub fn new(value_size: JsValue, key_size: JsValue) -> Result { + let value_size = try_to_u64(value_size).with_js_error()?; + let key_size = try_to_u64(key_size).with_js_error()?; + + // TODO remove `as usize` + Ok(WriteOperation::new(value_size as usize, key_size as usize).into()) + } + + #[wasm_bindgen(js_name = getProcessingCost)] + pub fn get_processing_cost(&self) -> BigInt { + BigInt::from(self.0.get_processing_cost()) + } + + #[wasm_bindgen(js_name=getStorageCost)] + pub fn get_storage_cost(&self) -> BigInt { + BigInt::from(self.0.get_storage_cost()) + } +} + +impl Inner for WriteOperationWasm { + type InnerItem = WriteOperation; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/mod.rs b/packages/wasm-dpp/src/state_transition/mod.rs index a755f3db21a..2916d16696f 100644 --- a/packages/wasm-dpp/src/state_transition/mod.rs +++ b/packages/wasm-dpp/src/state_transition/mod.rs @@ -6,6 +6,7 @@ pub mod errors; pub mod state_transition_facade; pub mod state_transition_factory; +pub mod fee; pub mod validation; use crate::utils::Inner; pub use validation::*; From dafc316cd6bc977c609daa32dce25e02c7dc9d82 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Thu, 23 Mar 2023 11:27:26 +0100 Subject: [PATCH 07/12] feat: migrate fees from js-dpp v0.24 --- packages/rs-dpp/src/errors/consensus/fee.rs | 4 +- .../abstract_state_transition.rs | 8 +- .../fee/calculate_operation_fees.rs | 45 ++++ .../calculate_state_transition_fee_factory.rs | 15 ++ ..._transition_fee_from_operations_factory.rs | 110 ++++++++++ .../src/state_transition/fee/constants.rs | 20 +- .../rs-dpp/src/state_transition/fee/mod.rs | 52 ++--- .../fee/operations/delete_operation.rs | 33 --- .../state_transition/fee/operations/mod.rs | 60 ++---- .../fee/operations/precalculated_operation.rs | 32 ++- .../fee/operations/read_operation.rs | 19 +- .../signature_verification_operation.rs | 13 +- .../fee/operations/write_operation.rs | 33 --- packages/rs-dpp/src/state_transition/mod.rs | 5 + .../state_transition_execution_context.rs | 6 +- .../validate_state_transition_fee.rs | 196 ++++++++++++++---- 16 files changed, 444 insertions(+), 207 deletions(-) create mode 100644 packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs create mode 100644 packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs create mode 100644 packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs delete mode 100644 packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs delete mode 100644 packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs diff --git a/packages/rs-dpp/src/errors/consensus/fee.rs b/packages/rs-dpp/src/errors/consensus/fee.rs index 8ac40f0e920..f831e0c3da1 100644 --- a/packages/rs-dpp/src/errors/consensus/fee.rs +++ b/packages/rs-dpp/src/errors/consensus/fee.rs @@ -1,7 +1,9 @@ use thiserror::Error; +use crate::state_transition::fee::Credits; + #[derive(Error, Debug)] pub enum FeeError { #[error("Current credits balance {balance} is not enough to pay {fee} fee")] - BalanceIsNotEnoughError { balance: u64, fee: i64 }, + BalanceIsNotEnoughError { balance: u64, fee: Credits }, } diff --git a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs index d17bcbe9219..83a87fe7fc4 100644 --- a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs +++ b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs @@ -18,8 +18,8 @@ use crate::{ BlsModule, }; +use super::fee::Credits; use super::{ - fee::calculate_state_transition_fee::calculate_state_transition_fee, state_transition_execution_context::StateTransitionExecutionContext, StateTransition, StateTransitionType, }; @@ -53,11 +53,7 @@ pub trait StateTransitionLike: /// returns the signature as a byte-array fn get_signature(&self) -> &BinaryData; /// set a new signature - fn set_signature(&mut self, signature: BinaryData); - /// Calculates the ST fee in credits - fn calculate_fee(&self) -> i64 { - calculate_state_transition_fee(self) - } + fn set_signature(&mut self, signature: Vec); /// get modified ids list fn get_modified_data_ids(&self) -> Vec; diff --git a/packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs b/packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs new file mode 100644 index 00000000000..d6fe927df83 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/fee/calculate_operation_fees.rs @@ -0,0 +1,45 @@ +use super::{ + operations::{Operation, OperationLike}, + DummyFeesResult, Refunds, +}; + +pub fn calculate_operation_fees(operations: &[Operation]) -> DummyFeesResult { + let mut storage_fee = 0; + let mut processing_fee = 0; + let mut fee_refunds: Vec = Vec::new(); + + for operation in operations { + storage_fee += operation.get_storage_cost(); + processing_fee += operation.get_processing_cost(); + + // Merge refunds + if let Some(operation_refunds) = operation.get_refunds() { + for identity_refunds in operation_refunds { + let mut existing_identity_refunds = fee_refunds + .iter_mut() + .find(|refund| refund.identifier == identity_refunds.identifier); + + if existing_identity_refunds.is_none() { + fee_refunds.push(identity_refunds.clone()); + continue; + } + + for (epoch_index, credits) in identity_refunds.credits_per_epoch.iter() { + if let Some(ref mut refunds) = existing_identity_refunds { + let epoch = refunds + .credits_per_epoch + .entry(epoch_index.to_string()) + .or_default(); + *epoch += credits + } + } + } + } + } + + DummyFeesResult { + storage: storage_fee, + processing: processing_fee, + fee_refunds, + } +} diff --git a/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs new file mode 100644 index 00000000000..01d0583746c --- /dev/null +++ b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_factory.rs @@ -0,0 +1,15 @@ +use crate::state_transition::{ + fee::calculate_state_transition_fee_from_operations_factory::calculate_state_transition_fee_from_operations, + StateTransition, StateTransitionLike, +}; + +use super::FeeResult; + +pub fn calculate_state_transition_fee(state_transition: &StateTransition) -> FeeResult { + let execution_context = state_transition.get_execution_context(); + + calculate_state_transition_fee_from_operations( + &execution_context.get_operations(), + state_transition.get_owner_id(), + ) +} diff --git a/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs new file mode 100644 index 00000000000..a5a7adf92f6 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/fee/calculate_state_transition_fee_from_operations_factory.rs @@ -0,0 +1,110 @@ +use crate::prelude::Identifier; + +use super::{ + calculate_operation_fees::calculate_operation_fees, constants::DEFAULT_USER_TIP, + operations::Operation, DummyFeesResult, FeeResult, +}; + +pub fn calculate_state_transition_fee_from_operations( + operations: &[Operation], + identity_id: &Identifier, +) -> FeeResult { + calculate_state_transition_fee_from_operations_with_custom_calculator( + operations, + identity_id, + calculate_operation_fees, + ) +} + +fn calculate_state_transition_fee_from_operations_with_custom_calculator( + operations: &[Operation], + identity_id: &Identifier, + calculate_operation_fees_fn: impl FnOnce(&[Operation]) -> DummyFeesResult, +) -> FeeResult { + let calculated_fees = calculate_operation_fees_fn(operations); + + let storage_fee = calculated_fees.storage; + let processing_fee = calculated_fees.processing; + let fee_refunds = calculated_fees.fee_refunds; + + let mut total_refunds = 0; + + let owner_refunds = fee_refunds + .iter() + .find(|refunds| identity_id == &refunds.identifier); + + if let Some(owner_refunds) = owner_refunds { + total_refunds = owner_refunds + .credits_per_epoch + .iter() + .fold(0, |sum, (_, credits)| sum + credits); + } + + let required_amount = (storage_fee - total_refunds) + DEFAULT_USER_TIP; + let desired_amount = (storage_fee + processing_fee - total_refunds) + DEFAULT_USER_TIP; + + FeeResult { + storage_fee, + processing_fee, + fee_refunds, + total_refunds, + required_amount, + desired_amount, + } +} + +#[cfg(test)] +mod test { + use std::collections::HashMap; + + use crate::{ + state_transition::fee::{ + operations::Operation, Credits, DummyFeesResult, FeeResult, Refunds, + }, + tests::utils::generate_random_identifier_struct, + }; + + use super::calculate_state_transition_fee_from_operations_with_custom_calculator; + + #[test] + fn should_calculate_fee_based_on_executed_operations() { + let identifier = generate_random_identifier_struct(); + let storage_fee = 10000; + let processing_fee = 1000; + let total_refunds = 1000 + 500; + let required_amount = storage_fee - total_refunds; + let desired_amount = storage_fee + processing_fee - total_refunds; + + let mut credits_per_epoch: HashMap = Default::default(); + credits_per_epoch.insert("0".to_string(), 1000); + credits_per_epoch.insert("1".to_string(), 500); + + let refunds = Refunds { + identifier, + credits_per_epoch, + }; + + let mock = |_operations: &[Operation]| -> DummyFeesResult { + DummyFeesResult { + storage: storage_fee, + processing: processing_fee, + fee_refunds: vec![refunds.clone()], + } + }; + + let result = calculate_state_transition_fee_from_operations_with_custom_calculator( + &[], + &identifier, + mock, + ); + let expected = FeeResult { + storage_fee, + processing_fee, + desired_amount, + required_amount, + fee_refunds: vec![refunds], + total_refunds: 1500, + }; + assert_eq!(expected, result); + } +} diff --git a/packages/rs-dpp/src/state_transition/fee/constants.rs b/packages/rs-dpp/src/state_transition/fee/constants.rs index 4ee78de7830..6730ac945b4 100644 --- a/packages/rs-dpp/src/state_transition/fee/constants.rs +++ b/packages/rs-dpp/src/state_transition/fee/constants.rs @@ -1,15 +1,17 @@ use crate::identity::KeyType; -pub const BASE_ST_PROCESSING_FEE: i64 = 10000; // 84000 -pub const FEE_MULTIPLIER: i64 = 2; -pub const DEFAULT_USER_TIP: i64 = 0; -pub const STORAGE_CREDIT_PER_BYTE: i64 = 5000; -pub const PROCESSING_CREDIT_PER_BYTE: i64 = 12; -pub const DELETE_BASE_PROCESSING_COST: i64 = 2000; // 20000 -pub const READ_BASE_PROCESSING_COST: i64 = 8400; // 8400 -pub const WRITE_BASE_PROCESSING_COST: i64 = 6000; // 60000 +use super::Credits; -pub const fn signature_verify_cost(key_type: KeyType) -> i64 { +pub const BASE_ST_PROCESSING_FEE: Credits = 10000; // 84000 +pub const FEE_MULTIPLIER: Credits = 2; +pub const DEFAULT_USER_TIP: Credits = 0; +pub const STORAGE_CREDIT_PER_BYTE: Credits = 5000; +pub const PROCESSING_CREDIT_PER_BYTE: Credits = 12; +pub const DELETE_BASE_PROCESSING_COST: Credits = 2000; // 20000 +pub const READ_BASE_PROCESSING_COST: Credits = 8400; // 8400 +pub const WRITE_BASE_PROCESSING_COST: Credits = 6000; // 60000 + +pub const fn signature_verify_cost(key_type: KeyType) -> Credits { match key_type { KeyType::ECDSA_SECP256K1 => 3000, KeyType::BLS12_381 => 6000, diff --git a/packages/rs-dpp/src/state_transition/fee/mod.rs b/packages/rs-dpp/src/state_transition/fee/mod.rs index eac889b595d..0c0c515eb31 100644 --- a/packages/rs-dpp/src/state_transition/fee/mod.rs +++ b/packages/rs-dpp/src/state_transition/fee/mod.rs @@ -1,33 +1,37 @@ -use std::borrow::Borrow; +use std::collections::HashMap; -use self::{ - constants::FEE_MULTIPLIER, - operations::{Operation, OperationLike}, -}; +use serde::{Deserialize, Serialize}; -pub mod calculate_state_transition_fee; +use crate::prelude::Identifier; + +pub mod calculate_operation_fees; +pub mod calculate_state_transition_fee_factory; +pub mod calculate_state_transition_fee_from_operations_factory; pub mod constants; pub mod operations; -#[derive(Default)] -pub struct Fees { - storage: i64, - processing: i64, -} - -pub fn calculate_operations_fees( - operations: impl IntoIterator>, -) -> Fees { - let mut fees = Fees::default(); +pub type Credits = u64; - for operation in operations.into_iter() { - let operation = operation.borrow(); - fees.processing += operation.get_processing_cost(); - fees.storage += operation.get_storage_cost(); - } +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct FeeResult { + pub storage_fee: Credits, + pub processing_fee: Credits, + pub fee_refunds: Vec, + pub total_refunds: Credits, + pub desired_amount: Credits, + pub required_amount: Credits, +} - fees.storage *= FEE_MULTIPLIER; - fees.processing *= FEE_MULTIPLIER; +#[derive(Default)] +pub struct DummyFeesResult { + storage: Credits, + processing: Credits, + fee_refunds: Vec, +} - fees +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename = "camelCase")] +pub struct Refunds { + pub identifier: Identifier, + pub credits_per_epoch: HashMap, } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs deleted file mode 100644 index 214c19dffc5..00000000000 --- a/packages/rs-dpp/src/state_transition/fee/operations/delete_operation.rs +++ /dev/null @@ -1,33 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use super::OperationLike; -use crate::state_transition::fee::constants::{ - DELETE_BASE_PROCESSING_COST, PROCESSING_CREDIT_PER_BYTE, STORAGE_CREDIT_PER_BYTE, -}; - -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct DeleteOperation { - pub key_size: usize, - pub value_size: usize, -} - -impl DeleteOperation { - pub fn new(key_size: usize, value_size: usize) -> Self { - Self { - key_size, - value_size, - } - } -} - -impl OperationLike for DeleteOperation { - fn get_processing_cost(&self) -> i64 { - DELETE_BASE_PROCESSING_COST - + ((self.key_size as i64 + self.value_size as i64) * PROCESSING_CREDIT_PER_BYTE) - } - - fn get_storage_cost(&self) -> i64 { - -((self.key_size + self.value_size) as i64 * STORAGE_CREDIT_PER_BYTE) - } -} diff --git a/packages/rs-dpp/src/state_transition/fee/operations/mod.rs b/packages/rs-dpp/src/state_transition/fee/operations/mod.rs index 7085fd22f74..59430db494a 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/mod.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/mod.rs @@ -1,47 +1,42 @@ -mod delete_operation; - -pub use delete_operation::*; - mod precalculated_operation; pub use precalculated_operation::*; mod read_operation; pub use read_operation::*; -mod write_operation; use serde::{Deserialize, Serialize}; use serde_json::Value; -pub use write_operation::*; mod signature_verification_operation; pub use signature_verification_operation::*; +use super::{Credits, Refunds}; + pub const STORAGE_CREDIT_PER_BYTE: i64 = 5000; pub const STORAGE_PROCESSING_CREDIT_PER_BYTE: i64 = 5000; -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "type", rename_all = "camelCase")] pub enum Operation { Read(ReadOperation), - Write(WriteOperation), - Delete(DeleteOperation), PreCalculated(PreCalculatedOperation), SignatureVerification(SignatureVerificationOperation), } pub trait OperationLike { /// Get CPU cost of the operation - fn get_processing_cost(&self) -> i64; + fn get_processing_cost(&self) -> Credits; /// Get storage cost of the operation - fn get_storage_cost(&self) -> i64; + fn get_storage_cost(&self) -> Credits; + + /// Get refunds + fn get_refunds(&self) -> Option<&Vec>; } macro_rules! call_method { ($operation_type:expr, $method:ident ) => { match $operation_type { Operation::Read(op) => op.$method(), - Operation::Write(op) => op.$method(), - Operation::Delete(op) => op.$method(), Operation::PreCalculated(op) => op.$method(), Operation::SignatureVerification(op) => op.$method(), } @@ -49,13 +44,17 @@ macro_rules! call_method { } impl OperationLike for Operation { - fn get_processing_cost(&self) -> i64 { + fn get_processing_cost(&self) -> Credits { call_method!(self, get_processing_cost) } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { call_method!(self, get_storage_cost) } + + fn get_refunds(&self) -> Option<&Vec> { + call_method!(self, get_refunds) + } } impl Operation { @@ -82,11 +81,8 @@ impl Operation { #[cfg(test)] mod test { - use super::{ - DeleteOperation, Operation, PreCalculatedOperation, ReadOperation, - SignatureVerificationOperation, - }; - use crate::{identity::KeyType, state_transition::fee::operations::WriteOperation}; + use super::{Operation, PreCalculatedOperation, ReadOperation, SignatureVerificationOperation}; + use crate::identity::KeyType; use serde_json::json; struct TestCase { @@ -110,37 +106,17 @@ mod test { }), operation: Operation::Read(ReadOperation { value_size: 123 }), }, - TestCase { - json_str: json_string!({ - "type": "write", - "keySize" : 65, - "valueSize" : 321, - }), - operation: Operation::Write(WriteOperation { - key_size: 65, - value_size: 321, - }), - }, - TestCase { - json_str: json_string!({ - "type": "delete", - "keySize" : 65, - "valueSize" : 123, - }), - operation: Operation::Delete(DeleteOperation { - key_size: 65, - value_size: 123, - }), - }, TestCase { json_str: json_string!({ "type": "preCalculated", "storageCost" : 12357, "processingCost" : 468910, + "feeRefunds" : [], }), operation: Operation::PreCalculated(PreCalculatedOperation { storage_cost: 12357, processing_cost: 468910, + fee_refunds: vec![], }), }, TestCase { diff --git a/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs index f3d57fc96f6..b7cdc272502 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/precalculated_operation.rs @@ -1,29 +1,49 @@ use serde::{Deserialize, Serialize}; +use crate::state_transition::fee::{Credits, DummyFeesResult, Refunds}; + use super::OperationLike; -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct PreCalculatedOperation { - pub storage_cost: i64, - pub processing_cost: i64, + pub storage_cost: Credits, + pub processing_cost: Credits, + pub fee_refunds: Vec, } impl PreCalculatedOperation { - pub fn new(storage_cost: i64, processing_cost: i64) -> Self { + pub fn from_fee(fee: DummyFeesResult) -> Self { + Self { + fee_refunds: fee.fee_refunds, + processing_cost: fee.processing, + storage_cost: fee.storage, + } + } + + pub fn new( + storage_cost: Credits, + processing_cost: Credits, + fee_refunds: impl IntoIterator, + ) -> Self { Self { storage_cost, processing_cost, + fee_refunds: fee_refunds.into_iter().collect(), } } } impl OperationLike for PreCalculatedOperation { - fn get_processing_cost(&self) -> i64 { + fn get_processing_cost(&self) -> Credits { self.processing_cost } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { self.storage_cost } + + fn get_refunds(&self) -> Option<&Vec> { + Some(&self.fee_refunds) + } } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs index 5f54ad1a681..007be2e941e 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/read_operation.rs @@ -2,28 +2,33 @@ use serde::{Deserialize, Serialize}; use super::OperationLike; -use crate::state_transition::fee::constants::{ - PROCESSING_CREDIT_PER_BYTE, READ_BASE_PROCESSING_COST, +use crate::state_transition::fee::{ + constants::{PROCESSING_CREDIT_PER_BYTE, READ_BASE_PROCESSING_COST}, + Credits, Refunds, }; #[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct ReadOperation { - pub value_size: usize, + pub value_size: Credits, } impl ReadOperation { - pub fn new(value_size: usize) -> Self { + pub fn new(value_size: u64) -> Self { Self { value_size } } } impl OperationLike for ReadOperation { - fn get_processing_cost(&self) -> i64 { - READ_BASE_PROCESSING_COST + (self.value_size as i64 * PROCESSING_CREDIT_PER_BYTE) + fn get_processing_cost(&self) -> Credits { + READ_BASE_PROCESSING_COST + (self.value_size * PROCESSING_CREDIT_PER_BYTE) } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { 0 } + + fn get_refunds(&self) -> Option<&Vec> { + None + } } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs index 0211b196b2f..59d43afb249 100644 --- a/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs +++ b/packages/rs-dpp/src/state_transition/fee/operations/signature_verification_operation.rs @@ -1,7 +1,10 @@ use serde::{Deserialize, Serialize}; use super::OperationLike; -use crate::{identity::KeyType, state_transition::fee::constants::signature_verify_cost}; +use crate::{ + identity::KeyType, + state_transition::fee::{constants::signature_verify_cost, Credits, Refunds}, +}; #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] @@ -16,11 +19,15 @@ impl SignatureVerificationOperation { } impl OperationLike for SignatureVerificationOperation { - fn get_processing_cost(&self) -> i64 { + fn get_processing_cost(&self) -> Credits { signature_verify_cost(self.signature_type) } - fn get_storage_cost(&self) -> i64 { + fn get_storage_cost(&self) -> Credits { 0 } + + fn get_refunds(&self) -> Option<&Vec> { + None + } } diff --git a/packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs b/packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs deleted file mode 100644 index 65b2088e576..00000000000 --- a/packages/rs-dpp/src/state_transition/fee/operations/write_operation.rs +++ /dev/null @@ -1,33 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use super::OperationLike; -use crate::state_transition::fee::constants::{ - PROCESSING_CREDIT_PER_BYTE, STORAGE_CREDIT_PER_BYTE, WRITE_BASE_PROCESSING_COST, -}; - -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct WriteOperation { - pub key_size: usize, - pub value_size: usize, -} - -impl WriteOperation { - pub fn new(key_size: usize, value_size: usize) -> Self { - Self { - key_size, - value_size, - } - } -} - -impl OperationLike for WriteOperation { - fn get_processing_cost(&self) -> i64 { - WRITE_BASE_PROCESSING_COST - + ((self.key_size + self.value_size) as i64 * PROCESSING_CREDIT_PER_BYTE) - } - - fn get_storage_cost(&self) -> i64 { - (self.key_size + self.value_size) as i64 * STORAGE_CREDIT_PER_BYTE - } -} diff --git a/packages/rs-dpp/src/state_transition/mod.rs b/packages/rs-dpp/src/state_transition/mod.rs index baf0711e8ec..784a931bf13 100644 --- a/packages/rs-dpp/src/state_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/mod.rs @@ -15,6 +15,7 @@ use crate::identity::state_transition::identity_create_transition::IdentityCreat use crate::identity::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; use crate::identity::state_transition::identity_topup_transition::IdentityTopUpTransition; use crate::identity::state_transition::identity_update_transition::identity_update_transition::IdentityUpdateTransition; +use crate::prelude::Identifier; mod abstract_state_transition; mod abstract_state_transition_identity_signed; @@ -98,6 +99,10 @@ impl StateTransition { fn binary_property_paths(&self) -> Vec<&'static str> { call_static_method!(self, binary_property_paths) } + + fn get_owner_id(&self) -> &Identifier { + call_method!(self, get_owner_id) + } } impl StateTransitionConvert for StateTransition { diff --git a/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs b/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs index 4ac2f18c1c3..2a524aceb75 100644 --- a/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs +++ b/packages/rs-dpp/src/state_transition/state_transition_execution_context.rs @@ -47,8 +47,10 @@ impl StateTransitionExecutionContext { inner .actual_operations .iter() - .copied() - .chain(inner.dry_run_operations.iter().copied()) + // TODO remove cloning + .cloned() + // TODO remove cloning + .chain(inner.dry_run_operations.iter().cloned()) .collect() } diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs index 17c7bd8fcce..ed2f4ee126d 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs @@ -3,6 +3,8 @@ use std::convert::TryInto; use crate::consensus::basic::state_transition::InvalidStateTransitionTypeError; use crate::data_contract::errors::IdentityNotPresentError; +use crate::state_transition::fee::calculate_state_transition_fee_factory::calculate_state_transition_fee; +use crate::state_transition::fee::FeeResult; use crate::state_transition::StateTransitionType; use crate::{ consensus::fee::FeeError, @@ -38,11 +40,20 @@ where pub async fn validate( &self, state_transition: &StateTransition, + ) -> Result { + self.validate_with_custom_calculator(state_transition, calculate_state_transition_fee) + .await + } + + async fn validate_with_custom_calculator( + &self, + state_transition: &StateTransition, + calculate_state_transition_fee_fn: impl Fn(&StateTransition) -> FeeResult, ) -> Result { let mut result = SimpleValidationResult::default(); let execution_context = state_transition.get_execution_context(); - let balance = match state_transition { + let balance_with_possible_debt: i128 = match state_transition { StateTransition::IdentityCreate(st) => { let output = self .asset_lock_transition_output_fetcher @@ -54,7 +65,7 @@ where st.get_asset_lock_proof() ) })?; - convert_satoshi_to_credits(output.value) + convert_satoshi_to_credits(output.value) as i128 } StateTransition::IdentityTopUp(st) => { let output = self @@ -69,44 +80,42 @@ where })?; let balance = convert_satoshi_to_credits(output.value); let identity_id = st.get_owner_id(); - let identity = self + let identity_balance = self .state_repository - .fetch_identity(identity_id, Some(st.get_execution_context())) + .fetch_identity_balance_with_debt(identity_id, Some(execution_context)) .await? - .map(TryInto::try_into) - .transpose() - .map_err(Into::into)? - .ok_or_else(|| { - ProtocolError::IdentityNotPresentError(IdentityNotPresentError::new( - *identity_id, - )) - })?; + .context(format!( + "balance for given identity {identity_id} not found" + ))?; if execution_context.is_dry_run() { return Ok(result); } - balance + identity.get_balance() + + // TODO fixme: remove i128. what if identity_balance is negative and absolute value is + // TODO greater than balance (which is u64) + balance as i128 + identity_balance as i128 } StateTransition::DataContractCreate(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::DataContractUpdate(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::DocumentsBatch(st) => { let balance = self.get_identity_owner_balance(st).await?; if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::IdentityUpdate(st) => { @@ -114,7 +123,7 @@ where if execution_context.is_dry_run() { return Ok(result); } - balance + balance as i128 } StateTransition::IdentityCreditWithdrawal(_) => { return Err(ProtocolError::InvalidStateTransitionTypeError( @@ -129,10 +138,14 @@ where return Ok(result); } - let fee = state_transition.calculate_fee(); + let fee = calculate_state_transition_fee_fn(state_transition); + // ? make sure Fee cannot be negative and refunds are handled differently - if (balance as i64) < fee { - result.add_error(FeeError::BalanceIsNotEnoughError { balance, fee }) + if (balance_with_possible_debt) < fee.desired_amount as i128 { + result.add_error(FeeError::BalanceIsNotEnoughError { + balance: balance_with_possible_debt as u64, + fee: fee.desired_amount, + }) } Ok(result) @@ -163,9 +176,15 @@ mod test { use std::sync::Arc; use crate::data_contract::state_transition::data_contract_create_transition::DataContractCreateTransition; + use crate::identity::state_transition::asset_lock_proof::AssetLockProof; + use crate::identity::state_transition::identity_create_transition::IdentityCreateTransition; use crate::identity::state_transition::identity_topup_transition::IdentityTopUpTransition; - use crate::state_transition::StateTransitionLike; - use crate::tests::fixtures::identity_topup_transition_fixture; + use crate::identity::RATIO; + use crate::state_transition::fee::{Credits, FeeResult}; + use crate::state_transition::StateTransition; + use crate::tests::fixtures::{ + identity_create_transition_fixture_json, identity_topup_transition_fixture_json, + }; use crate::ProtocolError; use crate::{ consensus::fee::FeeError, @@ -188,17 +207,33 @@ mod test { use super::StateTransitionFeeValidator; fn execution_context_with_cost( - storage_cost: i64, - processing_cost: i64, + storage_cost: Credits, + processing_cost: Credits, ) -> StateTransitionExecutionContext { let ctx = StateTransitionExecutionContext::default(); + // TODO fixme ctx.add_operation(Operation::PreCalculated(PreCalculatedOperation::new( storage_cost, processing_cost, + vec![], ))); ctx } + macro_rules! get_output_amount_from_identity_transition { + ($transition:ident) => { + if let AssetLockProof::Instant(lock_proof) = $transition.get_asset_lock_proof() { + let satoshis = lock_proof + .output() + .expect("output must be present in instant lock proof") + .value; + satoshis * RATIO + } else { + panic!("identity must have an instant lock proof") + } + }; + } + #[tokio::test] async fn data_contract_crate_transition_invalid_result_if_balance_is_not_enough() { let mut identity = identity_fixture(); @@ -226,8 +261,7 @@ mod test { let fee_error = get_fee_error_from_result(&result, 0); assert!( matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, fee } if { - *balance == 1 && - *fee == 90 + *balance == 1 }) ); } @@ -237,7 +271,7 @@ mod test { let mut identity = identity_fixture(); let mut state_repository_mock = MockStateRepositoryLike::new(); - identity.balance = 90; + identity.balance = 52; state_repository_mock .expect_fetch_identity() .returning(move |_, _| Ok(Some(identity.clone()))); @@ -287,9 +321,8 @@ mod test { let fee_error = get_fee_error_from_result(&result, 0); assert!( - matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, fee } if { - *balance == 1 && - *fee == 90 + matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, .. } if { + *balance == 1 }) ); } @@ -355,33 +388,114 @@ mod test { assert!(result.is_valid()); } + #[tokio::test] + async fn identity_create_transition_should_return_invalid_result_if_asset_lock_output_amount_is_not_enough( + ) { + let identity_create_transition = + IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); + let state_repository_mock = MockStateRepositoryLike::new(); + let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount + 1, + ..Default::default() + }; + + let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); + let result = validator + .validate_with_custom_calculator( + &identity_create_transition.into(), + calculate_state_transition_fee_mock, + ) + .await + .expect("the validation result should be returned"); + let fee_error = get_fee_error_from_result(&result, 0); + + assert!( + matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, .. } if { + *balance == output_amount + }) + ); + } + + #[tokio::test] + async fn identity_create_transition_should_return_valid_result() { + let identity_create_transition = + IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); + let state_repository_mock = MockStateRepositoryLike::new(); + let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount, + ..Default::default() + }; + let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); + let result = validator + .validate_with_custom_calculator( + &identity_create_transition.into(), + calculate_state_transition_fee_mock, + ) + .await + .expect("the validation result should be returned"); + assert!(result.is_valid()) + } + #[tokio::test] async fn identity_top_up_transition_should_return_invalid_result_if_balance_is_not_enough() { - let mut identity = identity_fixture(); let mut state_repository_mock = MockStateRepositoryLike::new(); - identity.balance = 1; state_repository_mock - .expect_fetch_identity() - .returning(move |_, _| Ok(Some(identity.clone()))); + .expect_fetch_identity_balance_with_debt() + .returning(move |_, _| Ok(Some(1))); - let mut identity_topup_transition = - IdentityTopUpTransition::new(identity_topup_transition_fixture(None)).unwrap(); - identity_topup_transition.set_execution_context(execution_context_with_cost(45000000, 5)); + let identity_topup_transition = + IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); + let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); + + let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount + 2, + ..Default::default() + }; let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); let result = validator - .validate(&identity_topup_transition.into()) + .validate_with_custom_calculator( + &identity_topup_transition.into(), + calculate_state_transition_fee_mock, + ) .await .expect("the validation result should be returned"); + let fee_error = get_fee_error_from_result(&result, 0); assert!( - matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, fee } if { - *balance == 90000001 && - *fee == 90000010 + matches!(fee_error, FeeError::BalanceIsNotEnoughError { balance, .. } if { + *balance == output_amount + 1 }) ); } + #[tokio::test] + async fn identity_top_up_transition_should_return_valid_result() { + let mut state_repository_mock = MockStateRepositoryLike::new(); + state_repository_mock + .expect_fetch_identity_balance_with_debt() + .returning(move |_, _| Ok(Some(41))); + + let identity_topup_transition = + IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); + let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); + + let calculation_mock = |_: &StateTransition| FeeResult { + desired_amount: output_amount - 1, + ..Default::default() + }; + + let validator = StateTransitionFeeValidator::new(Arc::new(state_repository_mock)); + let result = validator + .validate_with_custom_calculator(&identity_topup_transition.into(), calculation_mock) + .await + .expect("the validation result should be returned"); + + assert!(result.is_valid()) + } + #[tokio::test] async fn should_return_invalid_state_transition_type() { let transition = IdentityCreditWithdrawalTransition::default(); From f57495552244911c1fe441174aadf7736955b3fc Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Thu, 23 Mar 2023 11:27:52 +0100 Subject: [PATCH 08/12] fix: adjust wasm-dpp to new fees --- .../state_transition/document_batch_transition/mod.rs | 6 +----- .../consensus/fee/balance_is_not_enough_error.rs | 11 ++++++----- packages/wasm-dpp/src/state_transition/fee/mod.rs | 10 ++++++---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs index 7e15b529050..98ef0820ef9 100644 --- a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs @@ -1,4 +1,5 @@ use dpp::identity::KeyID; +use dpp::state_transition::fee::calculate_state_transition_fee_factory::calculate_state_transition_fee; use dpp::{ document::{ document_transition::document_base_transition, @@ -329,11 +330,6 @@ impl DocumentsBatchTransitionWasm { self.0.set_signature(BinaryData::new(signature)) } - #[wasm_bindgen(js_name=calculateFee)] - pub fn calculate_fee(&self) -> i64 { - self.0.calculate_fee() - } - #[wasm_bindgen(js_name=isDocumentStateTransition)] pub fn is_document_state_transition(&self) -> bool { self.0.is_document_state_transition() diff --git a/packages/wasm-dpp/src/errors/consensus/fee/balance_is_not_enough_error.rs b/packages/wasm-dpp/src/errors/consensus/fee/balance_is_not_enough_error.rs index b516f1b770d..729283a89da 100644 --- a/packages/wasm-dpp/src/errors/consensus/fee/balance_is_not_enough_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/fee/balance_is_not_enough_error.rs @@ -1,14 +1,15 @@ +use dpp::state_transition::fee::Credits; use wasm_bindgen::prelude::*; #[wasm_bindgen(js_name=BalanceIsNotEnoughError)] pub struct BalanceIsNotEnoughErrorWasm { - balance: u64, - fee: i64, + balance: Credits, + fee: Credits, code: u32, } impl BalanceIsNotEnoughErrorWasm { - pub fn new(balance: u64, fee: i64, code: u32) -> Self { + pub fn new(balance: Credits, fee: Credits, code: u32) -> Self { BalanceIsNotEnoughErrorWasm { balance, fee, code } } } @@ -16,12 +17,12 @@ impl BalanceIsNotEnoughErrorWasm { #[wasm_bindgen(js_class=BalanceIsNotEnoughError)] impl BalanceIsNotEnoughErrorWasm { #[wasm_bindgen(js_name=getBalance)] - pub fn get_balance(&self) -> u64 { + pub fn get_balance(&self) -> Credits { self.balance } #[wasm_bindgen(js_name=getFee)] - pub fn get_fee(&self) -> i64 { + pub fn get_fee(&self) -> Credits { self.fee } diff --git a/packages/wasm-dpp/src/state_transition/fee/mod.rs b/packages/wasm-dpp/src/state_transition/fee/mod.rs index 19e5f6ac5e4..3d323a1fe7b 100644 --- a/packages/wasm-dpp/src/state_transition/fee/mod.rs +++ b/packages/wasm-dpp/src/state_transition/fee/mod.rs @@ -1,4 +1,6 @@ -use dpp::state_transition::fee::{calculate_operations_fees, operations::Operation, Fees}; +use dpp::state_transition::fee::{ + calculate_operations_fees, operations::Operation, DummyFeesResult, +}; use wasm_bindgen::prelude::*; use crate::utils::Inner; @@ -7,7 +9,7 @@ mod calculate_state_transition_fee; mod operations; #[wasm_bindgen(js_name=Fees)] -pub struct FeesWasm(Fees); +pub struct FeesWasm(DummyFeesResult); #[wasm_bindgen(js_name=Operation)] #[derive(Clone)] @@ -19,8 +21,8 @@ impl From for OperationWasm { } } -impl From for FeesWasm { - fn from(value: Fees) -> Self { +impl From for FeesWasm { + fn from(value: DummyFeesResult) -> Self { FeesWasm(value) } } From 7eae20b3024e05b822811cd7a9042e89579ffa40 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Mon, 27 Mar 2023 09:38:05 +0200 Subject: [PATCH 09/12] feat: update WASM fee API to v0.24 --- .../abstract_state_transition.rs | 3 +- .../rs-dpp/src/state_transition/fee/mod.rs | 8 +- .../validate_state_transition_fee.rs | 10 +- packages/rs-drive/src/drive/test_utils.rs | 4 +- .../fee/calculate_operation_fees.rs | 13 +- .../fee/calculate_state_transition_fee.rs | 17 +-- .../state_transition/fee/dummy_fee_result.rs | 83 ++++++++++++ .../src/state_transition/fee/fee_result.rs | 125 ++++++++++++++++++ .../wasm-dpp/src/state_transition/fee/mod.rs | 16 +-- .../fee/operations copy/mod.rs | 0 .../fee/operations copy/read_operation.rs | 52 -------- .../state_transition/fee/operations/mod.rs | 2 - .../operations/pre_calculated_operation.rs | 62 ++++++--- .../fee/operations/read_operation.rs | 33 +++-- .../signature_verification_operation.rs | 25 +++- .../fee/operations/write_operation.rs | 53 -------- .../src/state_transition/fee/refunds.rs | 59 +++++++++ packages/wasm-dpp/src/utils.rs | 1 + 18 files changed, 386 insertions(+), 180 deletions(-) create mode 100644 packages/wasm-dpp/src/state_transition/fee/dummy_fee_result.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/fee_result.rs delete mode 100644 packages/wasm-dpp/src/state_transition/fee/operations copy/mod.rs delete mode 100644 packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs delete mode 100644 packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs create mode 100644 packages/wasm-dpp/src/state_transition/fee/refunds.rs diff --git a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs index 83a87fe7fc4..74c3296c4d6 100644 --- a/packages/rs-dpp/src/state_transition/abstract_state_transition.rs +++ b/packages/rs-dpp/src/state_transition/abstract_state_transition.rs @@ -18,7 +18,6 @@ use crate::{ BlsModule, }; -use super::fee::Credits; use super::{ state_transition_execution_context::StateTransitionExecutionContext, StateTransition, StateTransitionType, @@ -53,7 +52,7 @@ pub trait StateTransitionLike: /// returns the signature as a byte-array fn get_signature(&self) -> &BinaryData; /// set a new signature - fn set_signature(&mut self, signature: Vec); + fn set_signature(&mut self, signature: BinaryData); /// get modified ids list fn get_modified_data_ids(&self) -> Vec; diff --git a/packages/rs-dpp/src/state_transition/fee/mod.rs b/packages/rs-dpp/src/state_transition/fee/mod.rs index 0c0c515eb31..14ef6a12712 100644 --- a/packages/rs-dpp/src/state_transition/fee/mod.rs +++ b/packages/rs-dpp/src/state_transition/fee/mod.rs @@ -22,11 +22,11 @@ pub struct FeeResult { pub required_amount: Credits, } -#[derive(Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct DummyFeesResult { - storage: Credits, - processing: Credits, - fee_refunds: Vec, + pub storage: Credits, + pub processing: Credits, + pub fee_refunds: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs index ed2f4ee126d..23c9e9ddfce 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs @@ -183,7 +183,7 @@ mod test { use crate::state_transition::fee::{Credits, FeeResult}; use crate::state_transition::StateTransition; use crate::tests::fixtures::{ - identity_create_transition_fixture_json, identity_topup_transition_fixture_json, + identity_create_transition_fixture, identity_topup_transition_fixture, }; use crate::ProtocolError; use crate::{ @@ -392,7 +392,7 @@ mod test { async fn identity_create_transition_should_return_invalid_result_if_asset_lock_output_amount_is_not_enough( ) { let identity_create_transition = - IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + IdentityCreateTransition::new(identity_create_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); let state_repository_mock = MockStateRepositoryLike::new(); let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { @@ -420,7 +420,7 @@ mod test { #[tokio::test] async fn identity_create_transition_should_return_valid_result() { let identity_create_transition = - IdentityCreateTransition::new(identity_create_transition_fixture_json(None)).unwrap(); + IdentityCreateTransition::new(identity_create_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_create_transition); let state_repository_mock = MockStateRepositoryLike::new(); let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { @@ -446,7 +446,7 @@ mod test { .returning(move |_, _| Ok(Some(1))); let identity_topup_transition = - IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); + IdentityTopUpTransition::new(identity_topup_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); let calculate_state_transition_fee_mock = |_: &StateTransition| FeeResult { @@ -479,7 +479,7 @@ mod test { .returning(move |_, _| Ok(Some(41))); let identity_topup_transition = - IdentityTopUpTransition::new(identity_topup_transition_fixture_json(None)).unwrap(); + IdentityTopUpTransition::new(identity_topup_transition_fixture(None)).unwrap(); let output_amount = get_output_amount_from_identity_transition!(identity_topup_transition); let calculation_mock = |_: &StateTransition| FeeResult { diff --git a/packages/rs-drive/src/drive/test_utils.rs b/packages/rs-drive/src/drive/test_utils.rs index 61240e3d254..e68a5285222 100644 --- a/packages/rs-drive/src/drive/test_utils.rs +++ b/packages/rs-drive/src/drive/test_utils.rs @@ -16,7 +16,7 @@ impl TestEntropyGenerator { } impl EntropyGenerator for TestEntropyGenerator { - fn generate(&self) -> [u8; 32] { - self.rng.borrow_mut().gen() + fn generate(&self) -> Result<[u8; 32], dpp::dashcore::anyhow::Error> { + Ok(self.rng.borrow_mut().gen()) } } diff --git a/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs b/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs index 94167f3a70b..df59ebb50cb 100644 --- a/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs +++ b/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs @@ -1,20 +1,23 @@ -use dpp::state_transition::fee::{calculate_operations_fees, operations::Operation}; +use dpp::state_transition::fee::{ + calculate_operation_fees::calculate_operation_fees, operations::Operation, +}; use wasm_bindgen::prelude::*; use crate::{ - fee::FeesWasm, - utils::{Inner, IntoWasm}, + utils::{Inner, IntoWasm}, fee::dummy_fee_result::DummyFeesResultWasm, }; use super::OperationWasm; #[wasm_bindgen(js_name=calculateOperationFees)] -pub fn calculate_operation_fees_wasm(operations: js_sys::Array) -> Result { +pub fn calculate_operation_fees_wasm( + operations: js_sys::Array, +) -> Result { let mut inner_operations: Vec = vec![]; for operation in operations.iter() { let operation = operation.to_wasm::("Operation")?.to_owned(); inner_operations.push(operation.into_inner()) } - Ok(calculate_operations_fees(inner_operations).into()) + Ok(calculate_operation_fees(&inner_operations).into()) } diff --git a/packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs b/packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs index 8fe5835a092..f6bcddef07d 100644 --- a/packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs +++ b/packages/wasm-dpp/src/state_transition/fee/calculate_state_transition_fee.rs @@ -1,20 +1,15 @@ -use dpp::{ - consensus::basic::state_transition, - state_transition::{ - fee::calculate_state_transition_fee::calculate_state_transition_fee, StateTransition, - }, -}; -use js_sys::BigInt; +use dpp::state_transition::fee::calculate_state_transition_fee_factory::calculate_state_transition_fee; use wasm_bindgen::prelude::*; -use crate::conversion::create_state_transition_from_wasm_instance; +use crate::{ + conversion::create_state_transition_from_wasm_instance, fee::fee_result::FeeResultWasm, +}; #[wasm_bindgen(js_name=calculateStateTransitionFee)] pub fn calculate_state_transition_fee_wasm( state_transition_js: &JsValue, -) -> Result { +) -> Result { let state_transition = create_state_transition_from_wasm_instance(state_transition_js)?; - let fee = calculate_state_transition_fee(&state_transition); - Ok(BigInt::from(fee)) + Ok(calculate_state_transition_fee(&state_transition).into()) } diff --git a/packages/wasm-dpp/src/state_transition/fee/dummy_fee_result.rs b/packages/wasm-dpp/src/state_transition/fee/dummy_fee_result.rs new file mode 100644 index 00000000000..40672c03335 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/dummy_fee_result.rs @@ -0,0 +1,83 @@ +use dpp::state_transition::fee::{DummyFeesResult, Refunds}; +use js_sys::{Array, BigInt}; +use wasm_bindgen::prelude::*; + +use crate::{ + fee::refunds::RefundsWasm, + utils::{try_to_u64, Inner, IntoWasm, WithJsError}, +}; + +#[wasm_bindgen(js_name=DummyFeesResult)] +pub struct DummyFeesResultWasm(DummyFeesResult); + +#[wasm_bindgen(js_class=DummyFeesResult)] +impl DummyFeesResultWasm { + #[wasm_bindgen(getter, js_name = "storageFee")] + pub fn storage_fee(&self) -> BigInt { + BigInt::from(self.0.storage) + } + + #[wasm_bindgen(getter, js_name = "processingFee")] + pub fn processing_fee(&self) -> BigInt { + BigInt::from(self.0.processing) + } + + #[wasm_bindgen(getter, js_name = "feeRefunds")] + pub fn fee_refunds(&self) -> js_sys::Array { + let js_refunds = js_sys::Array::new(); + for refund in self.0.fee_refunds.iter().map(RefundsWasm::from) { + js_refunds.push(&refund.into()); + } + js_refunds + } + + #[wasm_bindgen(setter, js_name = "storageFee")] + pub fn set_storage_fee(&mut self, number: JsValue) -> Result<(), JsValue> { + let number = try_to_u64(number).with_js_error()?; + self.0.storage = number; + Ok(()) + } + + #[wasm_bindgen(setter, js_name = "processingFee")] + pub fn set_processing_fee(&mut self, number: JsValue) -> Result<(), JsValue> { + let number = try_to_u64(number).with_js_error()?; + self.0.processing = number; + Ok(()) + } + + #[wasm_bindgen(setter, js_name = "feeRefunds")] + pub fn set_fee_refunds(&mut self, js_fee_refunds: Array) -> Result<(), JsValue> { + let mut refunds = vec![]; + for refund in js_fee_refunds.iter() { + let transition: Refunds = refund + .to_wasm::("Refunds")? + .to_owned() + .into_inner(); + refunds.push(transition); + } + self.0.fee_refunds = refunds; + Ok(()) + } +} + +impl From for DummyFeesResultWasm { + fn from(value: DummyFeesResult) -> Self { + DummyFeesResultWasm(value) + } +} + +impl Inner for DummyFeesResultWasm { + type InnerItem = DummyFeesResult; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/fee/fee_result.rs b/packages/wasm-dpp/src/state_transition/fee/fee_result.rs new file mode 100644 index 00000000000..ed54a675da8 --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/fee_result.rs @@ -0,0 +1,125 @@ +use dpp::state_transition::fee::{FeeResult, Refunds}; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::{ + fee::refunds::RefundsWasm, + utils::{try_to_u64, Inner, IntoWasm, WithJsError}, +}; + +#[wasm_bindgen(js_name=FeeResult)] +pub struct FeeResultWasm(FeeResult); + +#[wasm_bindgen(js_class=FeeResult)] +impl FeeResultWasm { + #[allow(clippy::new_without_default)] + #[wasm_bindgen(constructor)] + pub fn new() -> FeeResultWasm { + FeeResultWasm(FeeResult::default()) + } + + #[wasm_bindgen(getter, js_name = "storageFee")] + pub fn storage_fee(&self) -> BigInt { + BigInt::from(self.0.storage_fee) + } + + #[wasm_bindgen(getter, js_name = "processingFee")] + pub fn processing_fee(&self) -> BigInt { + BigInt::from(self.0.processing_fee) + } + + #[wasm_bindgen(getter, js_name = "feeRefunds")] + pub fn fee_refunds(&self) -> js_sys::Array { + let js_refunds = js_sys::Array::new(); + for refund in self.0.fee_refunds.iter().map(RefundsWasm::from) { + js_refunds.push(&refund.into()); + } + js_refunds + } + + #[wasm_bindgen(getter, js_name = "totalRefunds")] + pub fn total_refunds(&self) -> BigInt { + BigInt::from(self.0.total_refunds) + } + + #[wasm_bindgen(getter, js_name = "desiredAmount")] + pub fn desired_amount(&self) -> BigInt { + BigInt::from(self.0.desired_amount) + } + + #[wasm_bindgen(getter, js_name = "requiredAmount")] + pub fn required_amount(&self) -> BigInt { + BigInt::from(self.0.required_amount) + } + + #[wasm_bindgen(setter, js_name = "storageFee")] + pub fn set_storage_fee(&mut self, number: JsValue) -> Result<(), JsValue> { + let number = try_to_u64(number).with_js_error()?; + self.0.storage_fee = number; + Ok(()) + } + + #[wasm_bindgen(setter, js_name = "processingFee")] + pub fn set_processing_fee(&mut self, number: JsValue) -> Result<(), JsValue> { + let number = try_to_u64(number).with_js_error()?; + self.0.processing_fee = number; + Ok(()) + } + + #[wasm_bindgen(setter, js_name = "feeRefunds")] + pub fn set_fee_refunds(&mut self, js_fee_refunds: js_sys::Array) -> Result<(), JsValue> { + let mut refunds = vec![]; + for refund in js_fee_refunds.iter() { + let transition: Refunds = refund + .to_wasm::("Refunds")? + .to_owned() + .into_inner(); + refunds.push(transition); + } + self.0.fee_refunds = refunds; + Ok(()) + } + + #[wasm_bindgen(setter, js_name = "desiredAmount")] + pub fn set_desired_amount(&mut self, number: JsValue) -> Result<(), JsValue> { + let number = try_to_u64(number).with_js_error()?; + self.0.desired_amount = number; + Ok(()) + } + + #[wasm_bindgen(setter, js_name = "requiredAmount")] + pub fn set_required_amount(&mut self, number: JsValue) -> Result<(), JsValue> { + let number = try_to_u64(number).with_js_error()?; + self.0.required_amount = number; + Ok(()) + } + + #[wasm_bindgen(setter, js_name = "totalRefunds")] + pub fn set_total_refunds(&mut self, number: JsValue) -> Result<(), JsValue> { + let number = try_to_u64(number).with_js_error()?; + self.0.total_refunds = number; + Ok(()) + } +} + +impl From for FeeResultWasm { + fn from(value: FeeResult) -> Self { + FeeResultWasm(value) + } +} + +impl Inner for FeeResultWasm { + type InnerItem = FeeResult; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} diff --git a/packages/wasm-dpp/src/state_transition/fee/mod.rs b/packages/wasm-dpp/src/state_transition/fee/mod.rs index 3d323a1fe7b..7f787f119d6 100644 --- a/packages/wasm-dpp/src/state_transition/fee/mod.rs +++ b/packages/wasm-dpp/src/state_transition/fee/mod.rs @@ -1,15 +1,13 @@ -use dpp::state_transition::fee::{ - calculate_operations_fees, operations::Operation, DummyFeesResult, -}; +use dpp::state_transition::fee::operations::Operation; use wasm_bindgen::prelude::*; use crate::utils::Inner; mod calculate_operation_fees; mod calculate_state_transition_fee; +mod dummy_fee_result; +mod fee_result; mod operations; - -#[wasm_bindgen(js_name=Fees)] -pub struct FeesWasm(DummyFeesResult); +mod refunds; #[wasm_bindgen(js_name=Operation)] #[derive(Clone)] @@ -21,12 +19,6 @@ impl From for OperationWasm { } } -impl From for FeesWasm { - fn from(value: DummyFeesResult) -> Self { - FeesWasm(value) - } -} - impl Inner for OperationWasm { type InnerItem = Operation; diff --git a/packages/wasm-dpp/src/state_transition/fee/operations copy/mod.rs b/packages/wasm-dpp/src/state_transition/fee/operations copy/mod.rs deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs deleted file mode 100644 index c2fc3fba991..00000000000 --- a/packages/wasm-dpp/src/state_transition/fee/operations copy/read_operation.rs +++ /dev/null @@ -1,52 +0,0 @@ -use dpp::state_transition::fee::operations::{OperationLike, ReadOperation}; -use js_sys::BigInt; -use wasm_bindgen::prelude::*; - -use crate::utils::{try_to_u64, Inner, WithJsError}; - -#[wasm_bindgen(js_name = "ReadOperation")] -#[derive(Clone)] -pub struct ReadOperationWasm(ReadOperation); - -impl From for ReadOperationWasm { - fn from(value: ReadOperation) -> Self { - ReadOperationWasm(value) - } -} - -#[wasm_bindgen(js_class=ReadOperation)] -impl ReadOperationWasm { - #[wasm_bindgen(constructor)] - pub fn new(value_size: JsValue) -> Result { - let value_size = try_to_u64(value_size).with_js_error()?; - - // TODO remove `as usize` - Ok(ReadOperation::new(value_size as usize).into()) - } - - #[wasm_bindgen(js_name = getProcessingCost)] - pub fn get_processing_cost(&self) -> BigInt { - BigInt::from(self.0.get_processing_cost()) - } - - #[wasm_bindgen(js_name=getStorageCost)] - pub fn get_storage_cost(&self) -> BigInt { - BigInt::from(self.0.get_storage_cost()) - } -} - -impl Inner for ReadOperationWasm { - type InnerItem = ReadOperation; - - fn into_inner(self) -> Self::InnerItem { - self.0 - } - - fn inner(&self) -> &Self::InnerItem { - &self.0 - } - - fn inner_mut(&mut self) -> &mut Self::InnerItem { - &mut self.0 - } -} diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/mod.rs b/packages/wasm-dpp/src/state_transition/fee/operations/mod.rs index d027a631046..39f3c998420 100644 --- a/packages/wasm-dpp/src/state_transition/fee/operations/mod.rs +++ b/packages/wasm-dpp/src/state_transition/fee/operations/mod.rs @@ -1,9 +1,7 @@ mod pre_calculated_operation; mod read_operation; mod signature_verification_operation; -mod write_operation; pub use pre_calculated_operation::*; pub use read_operation::*; pub use signature_verification_operation::*; -pub use write_operation::*; diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs index e1741b04281..9c8e81d7e7a 100644 --- a/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs +++ b/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs @@ -1,11 +1,16 @@ -use std::convert::TryInto; -use anyhow::anyhow; -use dpp::state_transition::fee::operations::{OperationLike, PreCalculatedOperation}; -use js_sys::BigInt; +use crate::{fee::dummy_fee_result::DummyFeesResultWasm, utils::Inner}; +use dpp::state_transition::fee::{ + operations::{OperationLike, PreCalculatedOperation}, + Refunds, +}; +use js_sys::{Array, BigInt}; use wasm_bindgen::prelude::*; -use crate::utils::{try_to_u64, Inner, WithJsError}; +use crate::{ + fee::refunds::RefundsWasm, + utils::{try_to_u64, IntoWasm, WithJsError}, +}; #[wasm_bindgen(js_name = "PreCalculatedOperation")] #[derive(Clone)] @@ -23,31 +28,52 @@ impl PreCalculatedOperationWasm { pub fn new( storage_cost: JsValue, processing_cost: JsValue, + js_fee_refunds: Array, ) -> Result { - let storage_cost: i64 = try_to_u64(storage_cost) - .with_js_error()? - .try_into() - .map_err(|e| anyhow!("unable convert storage cost to i64: {}", e)) - .with_js_error()?; + let storage_cost = try_to_u64(storage_cost).with_js_error()?; + let processing_cost = try_to_u64(processing_cost).with_js_error()?; - let processing_cost: i64 = try_to_u64(processing_cost) - .with_js_error()? - .try_into() - .map_err(|e| anyhow!("unable convert processing_cost to i64: {}", e)) - .with_js_error()?; + let mut refunds = vec![]; + for refund in js_fee_refunds.iter() { + let transition: Refunds = refund + .to_wasm::("Refunds")? + .to_owned() + .into_inner(); + refunds.push(transition); + } - Ok(PreCalculatedOperation::new(storage_cost, processing_cost).into()) + Ok(PreCalculatedOperation::new(storage_cost, processing_cost, refunds).into()) + } + + #[wasm_bindgen(js_name=fromFee)] + pub fn from_fee(dummy_fee_result: &DummyFeesResultWasm) -> PreCalculatedOperationWasm { + let operation = PreCalculatedOperation::from_fee(dummy_fee_result.inner().clone()); + PreCalculatedOperationWasm(operation) } #[wasm_bindgen(js_name = getProcessingCost)] - pub fn get_processing_cost(&self) -> BigInt { + pub fn processing_cost(&self) -> BigInt { BigInt::from(self.0.get_processing_cost()) } #[wasm_bindgen(js_name=getStorageCost)] - pub fn get_storage_cost(&self) -> BigInt { + pub fn storage_cost(&self) -> BigInt { BigInt::from(self.0.get_storage_cost()) } + + #[wasm_bindgen(getter)] + pub fn refunds(&self) -> Option { + let array_refunds = Array::new(); + if let Some(refunds) = self.0.get_refunds() { + for refund in refunds { + let refund_wasm: RefundsWasm = refund.into(); + array_refunds.push(&refund_wasm.into()); + } + Some(array_refunds) + } else { + None + } + } } impl Inner for PreCalculatedOperationWasm { diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs index c2fc3fba991..6971d484b0a 100644 --- a/packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs +++ b/packages/wasm-dpp/src/state_transition/fee/operations/read_operation.rs @@ -1,8 +1,11 @@ use dpp::state_transition::fee::operations::{OperationLike, ReadOperation}; -use js_sys::BigInt; +use js_sys::{Array, BigInt}; use wasm_bindgen::prelude::*; -use crate::utils::{try_to_u64, Inner, WithJsError}; +use crate::{ + fee::refunds::RefundsWasm, + utils::{try_to_u64, Inner, WithJsError}, +}; #[wasm_bindgen(js_name = "ReadOperation")] #[derive(Clone)] @@ -19,20 +22,32 @@ impl ReadOperationWasm { #[wasm_bindgen(constructor)] pub fn new(value_size: JsValue) -> Result { let value_size = try_to_u64(value_size).with_js_error()?; - - // TODO remove `as usize` - Ok(ReadOperation::new(value_size as usize).into()) + Ok(ReadOperation::new(value_size).into()) } - #[wasm_bindgen(js_name = getProcessingCost)] - pub fn get_processing_cost(&self) -> BigInt { + #[wasm_bindgen(getter,js_name = processingCost)] + pub fn processing_cost(&self) -> BigInt { BigInt::from(self.0.get_processing_cost()) } - #[wasm_bindgen(js_name=getStorageCost)] - pub fn get_storage_cost(&self) -> BigInt { + #[wasm_bindgen(getter, js_name=storageCost)] + pub fn storage_cost(&self) -> BigInt { BigInt::from(self.0.get_storage_cost()) } + + #[wasm_bindgen(getter)] + pub fn refunds(&self) -> Option { + let array_refunds = Array::new(); + if let Some(refunds) = self.0.get_refunds() { + for refund in refunds { + let refund_wasm: RefundsWasm = refund.into(); + array_refunds.push(&refund_wasm.into()); + } + Some(array_refunds) + } else { + None + } + } } impl Inner for ReadOperationWasm { diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs index 22f97eedba6..b09d6005000 100644 --- a/packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs +++ b/packages/wasm-dpp/src/state_transition/fee/operations/signature_verification_operation.rs @@ -3,14 +3,15 @@ use std::convert::TryFrom; use anyhow::anyhow; use dpp::{ identity::KeyType, - state_transition::fee::operations::{ - OperationLike, SignatureVerificationOperation, - }, + state_transition::fee::operations::{OperationLike, SignatureVerificationOperation}, }; -use js_sys::BigInt; +use js_sys::{Array, BigInt}; use wasm_bindgen::prelude::*; -use crate::utils::{Inner, WithJsError}; +use crate::{ + fee::refunds::RefundsWasm, + utils::{Inner, WithJsError}, +}; #[wasm_bindgen(js_name = "SignatureVerificationOperation")] #[derive(Clone)] @@ -42,6 +43,20 @@ impl SignatureVerificationOperationWasm { pub fn get_storage_cost(&self) -> BigInt { BigInt::from(self.0.get_storage_cost()) } + + #[wasm_bindgen(getter)] + pub fn refunds(&self) -> Option { + let array_refunds = Array::new(); + if let Some(refunds) = self.0.get_refunds() { + for refund in refunds { + let refund_wasm: RefundsWasm = refund.into(); + array_refunds.push(&refund_wasm.into()); + } + Some(array_refunds) + } else { + None + } + } } impl Inner for SignatureVerificationOperationWasm { diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs deleted file mode 100644 index 1deace02501..00000000000 --- a/packages/wasm-dpp/src/state_transition/fee/operations/write_operation.rs +++ /dev/null @@ -1,53 +0,0 @@ -use dpp::state_transition::fee::operations::{OperationLike, WriteOperation}; -use js_sys::BigInt; -use wasm_bindgen::prelude::*; - -use crate::utils::{try_to_u64, Inner, WithJsError}; - -#[wasm_bindgen(js_name = "WriteOperation")] -#[derive(Clone)] -pub struct WriteOperationWasm(WriteOperation); - -impl From for WriteOperationWasm { - fn from(value: WriteOperation) -> Self { - WriteOperationWasm(value) - } -} - -#[wasm_bindgen(js_class=WriteOperation)] -impl WriteOperationWasm { - #[wasm_bindgen(constructor)] - pub fn new(value_size: JsValue, key_size: JsValue) -> Result { - let value_size = try_to_u64(value_size).with_js_error()?; - let key_size = try_to_u64(key_size).with_js_error()?; - - // TODO remove `as usize` - Ok(WriteOperation::new(value_size as usize, key_size as usize).into()) - } - - #[wasm_bindgen(js_name = getProcessingCost)] - pub fn get_processing_cost(&self) -> BigInt { - BigInt::from(self.0.get_processing_cost()) - } - - #[wasm_bindgen(js_name=getStorageCost)] - pub fn get_storage_cost(&self) -> BigInt { - BigInt::from(self.0.get_storage_cost()) - } -} - -impl Inner for WriteOperationWasm { - type InnerItem = WriteOperation; - - fn into_inner(self) -> Self::InnerItem { - self.0 - } - - fn inner(&self) -> &Self::InnerItem { - &self.0 - } - - fn inner_mut(&mut self) -> &mut Self::InnerItem { - &mut self.0 - } -} diff --git a/packages/wasm-dpp/src/state_transition/fee/refunds.rs b/packages/wasm-dpp/src/state_transition/fee/refunds.rs new file mode 100644 index 00000000000..a54bcb46dbd --- /dev/null +++ b/packages/wasm-dpp/src/state_transition/fee/refunds.rs @@ -0,0 +1,59 @@ +use std::collections::HashMap; + +use dpp::state_transition::fee::Refunds; +use js_sys::BigInt; +use wasm_bindgen::prelude::*; + +use crate::{identifier::IdentifierWrapper, utils::Inner}; + +#[derive(Clone)] +#[wasm_bindgen(js_name=Refunds)] +pub struct RefundsWasm(Refunds); + +#[wasm_bindgen(js_class=Refunds)] +impl RefundsWasm { + #[wasm_bindgen(getter)] + pub fn identifier(&self) -> IdentifierWrapper { + self.0.identifier.into() + } + + #[wasm_bindgen(getter)] + pub fn credits_per_epoch(&self) -> js_sys::Map { + convert_hashmap_to_jsmap(&self.0.credits_per_epoch) + } +} + +impl From for RefundsWasm { + fn from(value: Refunds) -> Self { + RefundsWasm(value) + } +} +impl From<&Refunds> for RefundsWasm { + fn from(value: &Refunds) -> Self { + RefundsWasm(value.clone()) + } +} + +impl Inner for RefundsWasm { + type InnerItem = Refunds; + + fn into_inner(self) -> Self::InnerItem { + self.0 + } + + fn inner(&self) -> &Self::InnerItem { + &self.0 + } + + fn inner_mut(&mut self) -> &mut Self::InnerItem { + &mut self.0 + } +} + +pub fn convert_hashmap_to_jsmap(map: &HashMap) -> js_sys::Map { + let mut js_map = js_sys::Map::new(); + for (key, value) in map { + js_map.set(&JsValue::from_str(&key), &BigInt::from(*value)); + } + js_map +} diff --git a/packages/wasm-dpp/src/utils.rs b/packages/wasm-dpp/src/utils.rs index 4a7b90061af..c29fab52e3e 100644 --- a/packages/wasm-dpp/src/utils.rs +++ b/packages/wasm-dpp/src/utils.rs @@ -83,6 +83,7 @@ pub fn to_vec_of_platform_values( .collect() } + pub fn into_vec_of(iter: &[JsValue]) -> Vec where T: for<'de> serde::de::Deserialize<'de>, From fa9fca50d9085befb1f98aaa0f056917d715aae5 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Mon, 27 Mar 2023 09:43:22 +0200 Subject: [PATCH 10/12] cargo fmt --- .../src/state_transition/fee/calculate_operation_fees.rs | 3 ++- .../fee/operations/pre_calculated_operation.rs | 1 - packages/wasm-dpp/src/utils.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs b/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs index df59ebb50cb..91625c269d8 100644 --- a/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs +++ b/packages/wasm-dpp/src/state_transition/fee/calculate_operation_fees.rs @@ -4,7 +4,8 @@ use dpp::state_transition::fee::{ use wasm_bindgen::prelude::*; use crate::{ - utils::{Inner, IntoWasm}, fee::dummy_fee_result::DummyFeesResultWasm, + fee::dummy_fee_result::DummyFeesResultWasm, + utils::{Inner, IntoWasm}, }; use super::OperationWasm; diff --git a/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs b/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs index 9c8e81d7e7a..59bce03f0af 100644 --- a/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs +++ b/packages/wasm-dpp/src/state_transition/fee/operations/pre_calculated_operation.rs @@ -1,4 +1,3 @@ - use crate::{fee::dummy_fee_result::DummyFeesResultWasm, utils::Inner}; use dpp::state_transition::fee::{ operations::{OperationLike, PreCalculatedOperation}, diff --git a/packages/wasm-dpp/src/utils.rs b/packages/wasm-dpp/src/utils.rs index c29fab52e3e..4a7b90061af 100644 --- a/packages/wasm-dpp/src/utils.rs +++ b/packages/wasm-dpp/src/utils.rs @@ -83,7 +83,6 @@ pub fn to_vec_of_platform_values( .collect() } - pub fn into_vec_of(iter: &[JsValue]) -> Vec where T: for<'de> serde::de::Deserialize<'de>, From 276c92a449df06033f1de29c6ce4059fb5369a61 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Mon, 27 Mar 2023 09:50:46 +0200 Subject: [PATCH 11/12] merge fixes --- .../validation/validate_state_transition_fee.rs | 1 - packages/wasm-dpp/src/errors/consensus_error.rs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs index ed103384e28..0b011208653 100644 --- a/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs +++ b/packages/rs-dpp/src/state_transition/validation/validate_state_transition_fee.rs @@ -223,7 +223,6 @@ mod test { processing_cost: Credits, ) -> StateTransitionExecutionContext { let ctx = StateTransitionExecutionContext::default(); - // TODO fixme ctx.add_operation(Operation::PreCalculated(PreCalculatedOperation::new( storage_cost, processing_cost, diff --git a/packages/wasm-dpp/src/errors/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus_error.rs index 7453d0133f9..b067c1808e5 100644 --- a/packages/wasm-dpp/src/errors/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus_error.rs @@ -185,8 +185,7 @@ pub fn from_consensus_error_ref(e: &DPPConsensusError) -> JsValue { } DPPConsensusError::FeeError(e) => match e { dpp::consensus::fee::FeeError::BalanceIsNotEnoughError { balance, fee } => { - // TODO decide about type for Fee - BalanceIsNotEnoughErrorWasm::new(*balance, *fee as i64, code).into() + BalanceIsNotEnoughErrorWasm::new(*balance, *fee, code).into() } }, DPPConsensusError::SignatureError(e) => from_signature_error(e), From 758cd04c0436e18c4253aacd6126214d9abe6fe0 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Tue, 28 Mar 2023 12:50:09 +0200 Subject: [PATCH 12/12] fix merge issuses --- packages/wasm-dpp/src/errors/consensus_error.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/wasm-dpp/src/errors/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus_error.rs index 7453d0133f9..b067c1808e5 100644 --- a/packages/wasm-dpp/src/errors/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus_error.rs @@ -185,8 +185,7 @@ pub fn from_consensus_error_ref(e: &DPPConsensusError) -> JsValue { } DPPConsensusError::FeeError(e) => match e { dpp::consensus::fee::FeeError::BalanceIsNotEnoughError { balance, fee } => { - // TODO decide about type for Fee - BalanceIsNotEnoughErrorWasm::new(*balance, *fee as i64, code).into() + BalanceIsNotEnoughErrorWasm::new(*balance, *fee, code).into() } }, DPPConsensusError::SignatureError(e) => from_signature_error(e),