Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/dapi-grpc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
// Derive features for versioned messages
//
// "GetConsensusParamsRequest" is excluded as this message does not support proofs
const VERSIONED_REQUESTS: [&str; 46] = [
const VERSIONED_REQUESTS: [&str; 48] = [
"GetDataContractHistoryRequest",
"GetDataContractRequest",
"GetDataContractsRequest",
Expand Down Expand Up @@ -120,6 +120,8 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
"GetFinalizedEpochInfosRequest",
"GetAddressInfoRequest",
"GetAddressesInfosRequest",
"GetRecentAddressBalanceChangesRequest",
"GetRecentCompactedAddressBalanceChangesRequest",
];

const PROOF_ONLY_VERSIONED_REQUESTS: [&str; 1] = ["GetAddressesTrunkStateRequest"];
Expand All @@ -134,7 +136,7 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
// - "GetIdentityByNonUniquePublicKeyHashResponse"
//
// "GetEvonodesProposedEpochBlocksResponse" is used for 2 Requests
const VERSIONED_RESPONSES: [&str; 44] = [
const VERSIONED_RESPONSES: [&str; 46] = [
"GetDataContractHistoryResponse",
"GetDataContractResponse",
"GetDataContractsResponse",
Expand Down Expand Up @@ -179,6 +181,8 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
"GetFinalizedEpochInfosResponse",
"GetAddressInfoResponse",
"GetAddressesInfosResponse",
"GetRecentAddressBalanceChangesResponse",
"GetRecentCompactedAddressBalanceChangesResponse",
];

const PROOF_ONLY_VERSIONED_RESPONSES: [&str; 1] = ["GetAddressesTrunkStateResponse"];
Expand Down
67 changes: 67 additions & 0 deletions packages/dapi-grpc/protos/platform/v0/platform.proto
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ service Platform {
returns (GetAddressesTrunkStateResponse);
rpc getAddressesBranchState(GetAddressesBranchStateRequest)
returns (GetAddressesBranchStateResponse);
rpc getRecentAddressBalanceChanges(GetRecentAddressBalanceChangesRequest)
returns (GetRecentAddressBalanceChangesResponse);
rpc getRecentCompactedAddressBalanceChanges(GetRecentCompactedAddressBalanceChangesRequest)
returns (GetRecentCompactedAddressBalanceChangesResponse);
}

// Proof message includes cryptographic proofs for validating responses
Expand Down Expand Up @@ -1972,6 +1976,23 @@ message AddressInfoEntries {
repeated AddressInfoEntry address_info_entries = 1;
}

message AddressBalanceChange {
bytes address = 1;
oneof operation {
uint64 set_balance = 2 [ jstype = JS_STRING ];
uint64 add_to_balance = 3 [ jstype = JS_STRING ];
}
}

message BlockAddressBalanceChanges {
uint64 block_height = 1 [ jstype = JS_STRING ];
repeated AddressBalanceChange changes = 2;
}

message AddressBalanceUpdateEntries {
repeated BlockAddressBalanceChanges block_changes = 1;
}

message GetAddressInfoResponse {
message GetAddressInfoResponseV0 {
oneof result {
Expand Down Expand Up @@ -2032,4 +2053,50 @@ message GetAddressesBranchStateResponse {
oneof version { GetAddressesBranchStateResponseV0 v0 = 1; }
}

message GetRecentAddressBalanceChangesRequest {
message GetRecentAddressBalanceChangesRequestV0 {
uint64 start_height = 1 [ jstype = JS_STRING ];
bool prove = 2;
}
oneof version { GetRecentAddressBalanceChangesRequestV0 v0 = 1; }
}

message GetRecentAddressBalanceChangesResponse {
message GetRecentAddressBalanceChangesResponseV0 {
oneof result {
AddressBalanceUpdateEntries address_balance_update_entries = 1;
Proof proof = 2;
}
ResponseMetadata metadata = 3;
}
oneof version { GetRecentAddressBalanceChangesResponseV0 v0 = 1; }
}

message CompactedBlockAddressBalanceChanges {
uint64 start_block_height = 1 [ jstype = JS_STRING ];
uint64 end_block_height = 2 [ jstype = JS_STRING ];
repeated AddressBalanceChange changes = 3;
}

message CompactedAddressBalanceUpdateEntries {
repeated CompactedBlockAddressBalanceChanges compacted_block_changes = 1;
}

message GetRecentCompactedAddressBalanceChangesRequest {
message GetRecentCompactedAddressBalanceChangesRequestV0 {
uint64 start_block_height = 1 [ jstype = JS_STRING ];
bool prove = 2;
}
oneof version { GetRecentCompactedAddressBalanceChangesRequestV0 v0 = 1; }
}

message GetRecentCompactedAddressBalanceChangesResponse {
message GetRecentCompactedAddressBalanceChangesResponseV0 {
oneof result {
CompactedAddressBalanceUpdateEntries compacted_address_balance_update_entries = 1;
Proof proof = 2;
}
ResponseMetadata metadata = 3;
}
oneof version { GetRecentCompactedAddressBalanceChangesResponseV0 v0 = 1; }
}
18 changes: 18 additions & 0 deletions packages/rs-dapi-client/src/transport/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,21 @@ impl_transport_request_grpc!(
RequestSettings::default(),
get_addresses_branch_state
);

// rpc getRecentAddressBalanceChanges(GetRecentAddressBalanceChangesRequest) returns (GetRecentAddressBalanceChangesResponse);
impl_transport_request_grpc!(
platform_proto::GetRecentAddressBalanceChangesRequest,
platform_proto::GetRecentAddressBalanceChangesResponse,
PlatformGrpcClient,
RequestSettings::default(),
get_recent_address_balance_changes
);

// rpc getRecentCompactedAddressBalanceChanges(GetRecentCompactedAddressBalanceChangesRequest) returns (GetRecentCompactedAddressBalanceChangesResponse);
impl_transport_request_grpc!(
platform_proto::GetRecentCompactedAddressBalanceChangesRequest,
platform_proto::GetRecentCompactedAddressBalanceChangesResponse,
PlatformGrpcClient,
RequestSettings::default(),
get_recent_compacted_address_balance_changes
);
12 changes: 12 additions & 0 deletions packages/rs-dapi/src/services/platform_service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,4 +543,16 @@ impl Platform for PlatformServiceImpl {
dapi_grpc::platform::v0::GetAddressesBranchStateRequest,
dapi_grpc::platform::v0::GetAddressesBranchStateResponse
);

drive_method!(
get_recent_address_balance_changes,
dapi_grpc::platform::v0::GetRecentAddressBalanceChangesRequest,
dapi_grpc::platform::v0::GetRecentAddressBalanceChangesResponse
);

drive_method!(
get_recent_compacted_address_balance_changes,
dapi_grpc::platform::v0::GetRecentCompactedAddressBalanceChangesRequest,
dapi_grpc::platform::v0::GetRecentCompactedAddressBalanceChangesResponse
);
}
33 changes: 33 additions & 0 deletions packages/rs-dpp/src/balances/credits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,39 @@ pub const MAX_CREDITS: Credits = 9223372036854775807 as Credits; //i64 Max

pub const CREDITS_PER_DUFF: Credits = 1000;

/// An enum for credit operations
#[derive(Debug, Clone, Copy, PartialEq, Eq, bincode::Encode, bincode::Decode)]
pub enum CreditOperation {
/// We are setting credit amounts
SetCredits(Credits),
/// We are adding to credits
AddToCredits(Credits),
}

impl CreditOperation {
/// Merges two credit operations, where `other` is applied after `self`.
///
/// The merge logic:
/// - SetCredits + SetCredits = SetCredits (take the later value)
/// - SetCredits + AddToCredits = SetCredits (original set value + added amount)
/// - AddToCredits + SetCredits = SetCredits (take the later value)
/// - AddToCredits + AddToCredits = AddToCredits (sum of both)
pub fn merge(&self, other: &CreditOperation) -> CreditOperation {
match (self, other) {
// If other is SetCredits, it overrides (it's the most recent set)
(_, CreditOperation::SetCredits(value)) => CreditOperation::SetCredits(*value),
// If self is SetCredits and other adds, add to the set value
(CreditOperation::SetCredits(set_val), CreditOperation::AddToCredits(add_val)) => {
CreditOperation::SetCredits(set_val.saturating_add(*add_val))
}
// If both are AddToCredits, sum them
(CreditOperation::AddToCredits(val1), CreditOperation::AddToCredits(val2)) => {
CreditOperation::AddToCredits(val1.saturating_add(*val2))
}
}
}
}

/// Trait for signed and unsigned credits
pub trait Creditable {
/// Convert unsigned credit to singed
Expand Down
17 changes: 9 additions & 8 deletions packages/rs-drive-abci/src/abci/app/execution_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@ impl TryIntoPlatformVersioned<Option<ExecTxResult>> for StateTransitionExecution
platform_version: &PlatformVersion,
) -> Result<Option<ExecTxResult>, Self::Error> {
let response = match self {
StateTransitionExecutionResult::SuccessfulExecution(_, actual_fees) => {
Some(ExecTxResult {
code: 0,
gas_used: actual_fees.total_base_fee() as SignedCredits,
..Default::default()
})
}
StateTransitionExecutionResult::SuccessfulExecution {
fee_result: actual_fees,
..
} => Some(ExecTxResult {
code: 0,
gas_used: actual_fees.total_base_fee() as SignedCredits,
..Default::default()
}),
StateTransitionExecutionResult::UnpaidConsensusError(error) => Some(ExecTxResult {
code: HandlerError::from(&error).code(),
info: error.response_info_for_version(platform_version)?,
gas_used: 0,
..Default::default()
}),
StateTransitionExecutionResult::PaidConsensusError(error, actual_fees) => {
StateTransitionExecutionResult::PaidConsensusError { error, actual_fees } => {
Some(ExecTxResult {
code: HandlerError::from(&error).code(),
info: error.response_info_for_version(platform_version)?,
Expand Down
4 changes: 2 additions & 2 deletions packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ where
execution_results.into_iter().zip(request.txs)
{
let tx_action = match &state_transition_execution_result {
StateTransitionExecutionResult::SuccessfulExecution(..) => TxAction::Unmodified,
StateTransitionExecutionResult::SuccessfulExecution { .. } => TxAction::Unmodified,
// We have identity to pay for the state transition, so we keep it in the block
StateTransitionExecutionResult::PaidConsensusError(..) => TxAction::Unmodified,
StateTransitionExecutionResult::PaidConsensusError { .. } => TxAction::Unmodified,
// We don't have any associated identity to pay for the state transition,
// so we remove it from the block to prevent spam attacks.
// Such state transitions must be invalidated by check tx, but they might
Expand Down
4 changes: 2 additions & 2 deletions packages/rs-drive-abci/src/abci/handler/process_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ where
.filter(|execution_result| {
matches!(
execution_result,
StateTransitionExecutionResult::SuccessfulExecution(..)
| StateTransitionExecutionResult::PaidConsensusError(..)
StateTransitionExecutionResult::SuccessfulExecution { .. }
| StateTransitionExecutionResult::PaidConsensusError { .. }
)
})
.filter_map(|execution_result| {
Expand Down
3 changes: 2 additions & 1 deletion packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ where
errors,
state_read_guard.last_block_info(),
transaction,
None, // address_balances_in_update not needed for check_tx
platform_ref.state.current_platform_version()?,
platform_ref.state.previous_fee_versions(),
)
Expand Down Expand Up @@ -3701,7 +3702,7 @@ mod tests {

assert_matches!(
processing_result.execution_results().as_slice(),
[StateTransitionExecutionResult::SuccessfulExecution(_, _)]
[StateTransitionExecutionResult::SuccessfulExecution { .. }]
);

platform
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,14 @@ where
timer,
)?;

// Store the address balances to recent block storage
self.store_address_balances_to_recent_block_storage(
&state_transitions_result.address_balances_updated,
&block_info,
transaction,
platform_version,
)?;

// Pool withdrawals into transactions queue

// Takes queued withdrawals, creates untiled withdrawal transaction payload, saves them to queue
Expand Down Expand Up @@ -359,6 +367,7 @@ where
block_state_info: block_state_info.into(),
epoch_info,
unsigned_withdrawal_transactions: unsigned_withdrawal_transaction_bytes,
block_address_balance_changes: std::collections::BTreeMap::new(),
block_platform_state,
proposer_results: None,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ mod tests {
unsigned_withdrawal_transactions: Default::default(),
block_platform_state,
proposer_results: None,
block_address_balance_changes: Default::default(),
};

let mut batch = vec![];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ mod tests {
unsigned_withdrawal_transactions: Default::default(),
block_platform_state,
proposer_results: None,
block_address_balance_changes: Default::default(),
};

let storage_fee_distribution_outcome = platform
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use drive::drive::identity::withdrawals::paths::{
WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY,
};
use drive::drive::prefunded_specialized_balances::prefunded_specialized_balances_for_voting_path_vec;
use drive::drive::saved_block_transactions::ADDRESS_BALANCES_KEY_U8;
use drive::drive::system::misc_path;
use drive::drive::tokens::paths::{
token_distributions_root_path, token_timed_distributions_path, tokens_root_path,
Expand Down Expand Up @@ -552,6 +553,28 @@ impl<C> Platform<C> {
None,
&platform_version.drive,
)?;

// SavedBlockTransactions for address-based transaction sync
self.drive.grove_insert_if_not_exists(
SubtreePath::empty(),
&[RootTree::SavedBlockTransactions as u8],
Element::empty_tree(),
Some(transaction),
None,
&platform_version.drive,
)?;

// Address balances subtree under SavedBlockTransactions
let saved_block_path = Drive::saved_block_transactions_path();
self.drive.grove_insert_if_not_exists(
saved_block_path.as_slice().into(),
&[ADDRESS_BALANCES_KEY_U8],
Element::empty_tree(),
Some(transaction),
None,
&platform_version.drive,
)?;

Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use crate::error::Error;
use crate::execution::types::execution_event::ExecutionEvent;
use crate::platform_types::event_execution_result::EventExecutionResult;
use crate::platform_types::platform::Platform;
use std::collections::BTreeMap;

use crate::rpc::core::CoreRPCLike;
use dpp::address_funds::PlatformAddress;
use dpp::balances::credits::CreditOperation;
use dpp::block::block_info::BlockInfo;
use dpp::consensus::ConsensusError;
use dpp::fee::default_costs::CachedEpochIndexFeeVersions;
Expand All @@ -24,6 +27,7 @@ where
/// * `event` - The execution event to be processed.
/// * `block_info` - Information about the current block being processed.
/// * `transaction` - The transaction associated with the execution event.
/// * `address_balances_in_update` - Optional map to track address balance changes.
/// * `platform_version` - A `PlatformVersion` reference that dictates which version of
/// the method to call.
///
Expand All @@ -37,12 +41,14 @@ where
///
/// This function may return an `Error` variant if there is a problem with the drive operations or
/// an internal error occurs.
#[allow(clippy::too_many_arguments)]
pub(in crate::execution) fn execute_event(
&self,
event: ExecutionEvent,
consensus_errors: Vec<ConsensusError>,
block_info: &BlockInfo,
transaction: &Transaction,
address_balances_in_update: Option<&mut BTreeMap<PlatformAddress, CreditOperation>>,
platform_version: &PlatformVersion,
previous_fee_versions: &CachedEpochIndexFeeVersions,
) -> Result<EventExecutionResult, Error> {
Expand All @@ -57,6 +63,7 @@ where
consensus_errors,
block_info,
transaction,
address_balances_in_update,
platform_version,
previous_fee_versions,
),
Expand Down
Loading
Loading