Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
3844657
start of feature
QuantumExplorer Oct 22, 2025
908ab58
more work on single use keys
QuantumExplorer Oct 25, 2025
8c64bc6
more work on single use keys
QuantumExplorer Oct 27, 2025
bbc31a0
more work
QuantumExplorer Oct 28, 2025
51cb468
more work
QuantumExplorer Nov 17, 2025
6e43207
more work
QuantumExplorer Nov 18, 2025
4f47cb6
a lot more work
QuantumExplorer Nov 21, 2025
d914e6a
a lot more work
QuantumExplorer Nov 21, 2025
0790608
more work
QuantumExplorer Nov 22, 2025
2c3d533
more work
QuantumExplorer Nov 22, 2025
f863cd2
more work
QuantumExplorer Nov 22, 2025
d46fc20
more work
QuantumExplorer Nov 23, 2025
f01e323
start of work on validation
QuantumExplorer Nov 23, 2025
85c9ede
more work
QuantumExplorer Nov 24, 2025
8b487d3
more work
QuantumExplorer Nov 25, 2025
c826814
nonce
QuantumExplorer Nov 27, 2025
79dfde0
more work
QuantumExplorer Nov 27, 2025
4ed3570
fixes
QuantumExplorer Nov 27, 2025
251dd08
more work
QuantumExplorer Nov 29, 2025
0f07209
more work
QuantumExplorer Nov 29, 2025
09a766c
more work
QuantumExplorer Nov 29, 2025
b6d4603
dpp
QuantumExplorer Nov 30, 2025
36cef9e
more work
QuantumExplorer Nov 30, 2025
adc0767
more work
QuantumExplorer Nov 30, 2025
4560e98
more work
QuantumExplorer Nov 30, 2025
781e856
more work
QuantumExplorer Nov 30, 2025
952e448
more work on drive
QuantumExplorer Nov 30, 2025
27d8eab
fix
QuantumExplorer Nov 30, 2025
488ff10
more work on validation
QuantumExplorer Dec 1, 2025
5471e3e
fixes for sdk
QuantumExplorer Dec 1, 2025
bfed03b
fixes for sdk
QuantumExplorer Dec 1, 2025
897e10f
fixes
QuantumExplorer Dec 1, 2025
48a76b0
fix
QuantumExplorer Dec 1, 2025
4339e23
a lot more validation
QuantumExplorer Dec 2, 2025
8c5f786
more work
QuantumExplorer Dec 2, 2025
1ed7242
more work
QuantumExplorer Dec 2, 2025
38bf86f
more work
QuantumExplorer Dec 2, 2025
cae2ef6
fixes
QuantumExplorer Dec 2, 2025
e00a617
more work on validation
QuantumExplorer Dec 2, 2025
06efdc6
more tests
QuantumExplorer Dec 2, 2025
cf1472a
clean up
QuantumExplorer Dec 2, 2025
7b8e541
more work
QuantumExplorer Dec 3, 2025
ad73e4c
more work
QuantumExplorer Dec 3, 2025
aa502ff
fixes
QuantumExplorer Dec 3, 2025
f273249
more work
QuantumExplorer Dec 3, 2025
a542dd8
more work
QuantumExplorer Dec 3, 2025
6edcecd
more work
QuantumExplorer Dec 3, 2025
13f3b7b
more work
QuantumExplorer Dec 4, 2025
b7230ec
fixes
QuantumExplorer Dec 4, 2025
483ef69
more work
QuantumExplorer Dec 5, 2025
b66408e
more work
QuantumExplorer Dec 5, 2025
e6e8f5e
fixes
QuantumExplorer Dec 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
27 changes: 9 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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; 44] = [
const VERSIONED_REQUESTS: [&str; 46] = [
"GetDataContractHistoryRequest",
"GetDataContractRequest",
"GetDataContractsRequest",
Expand Down Expand Up @@ -118,6 +118,8 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
"GetGroupActionsRequest",
"GetGroupActionSignersRequest",
"GetFinalizedEpochInfosRequest",
"GetAddressInfoRequest",
"GetAddressesInfosRequest",
];

// The following responses are excluded as they don't support proofs:
Expand All @@ -128,7 +130,7 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
// - "GetIdentityByNonUniquePublicKeyHashResponse"
//
// "GetEvonodesProposedEpochBlocksResponse" is used for 2 Requests
const VERSIONED_RESPONSES: [&str; 42] = [
const VERSIONED_RESPONSES: [&str; 44] = [
"GetDataContractHistoryResponse",
"GetDataContractResponse",
"GetDataContractsResponse",
Expand Down Expand Up @@ -171,6 +173,8 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig {
"GetGroupActionsResponse",
"GetGroupActionSignersResponse",
"GetFinalizedEpochInfosResponse",
"GetAddressInfoResponse",
"GetAddressesInfosResponse",
];

check_unique(&VERSIONED_REQUESTS).expect("VERSIONED_REQUESTS");
Expand Down
57 changes: 57 additions & 0 deletions packages/dapi-grpc/protos/platform/v0/platform.proto
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ service Platform {
rpc getGroupActions(GetGroupActionsRequest) returns (GetGroupActionsResponse);
rpc getGroupActionSigners(GetGroupActionSignersRequest)
returns (GetGroupActionSignersResponse);
rpc getAddressInfo(GetAddressInfoRequest)
returns (GetAddressInfoResponse);
rpc getAddressesInfos(GetAddressesInfosRequest)
returns (GetAddressesInfosResponse);
}

// Proof message includes cryptographic proofs for validating responses
Expand Down Expand Up @@ -1936,3 +1940,56 @@ message GetGroupActionSignersResponse {

oneof version { GetGroupActionSignersResponseV0 v0 = 1; }
}


message GetAddressInfoRequest {
message GetAddressInfoRequestV0 {
bytes address = 1;
bool prove = 2;
}
oneof version { GetAddressInfoRequestV0 v0 = 1; }
}

message AddressInfoEntry {
bytes address = 1;
optional BalanceAndNonce balance_and_nonce = 2;
}

message BalanceAndNonce {
uint64 balance = 1;
uint32 nonce = 2;
}

message AddressInfoEntries {
repeated AddressInfoEntry address_info_entries = 1;
}

message GetAddressInfoResponse {
message GetAddressInfoResponseV0 {
oneof result {
AddressInfoEntry address_info_entry = 1;
Proof proof = 2;
}
ResponseMetadata metadata = 3;
}
oneof version { GetAddressInfoResponseV0 v0 = 1; }
}

message GetAddressesInfosRequest {
message GetAddressesInfosRequestV0 {
repeated bytes addresses = 1;
bool prove = 2;
}
oneof version { GetAddressesInfosRequestV0 v0 = 1; }
}

message GetAddressesInfosResponse {
message GetAddressesInfosResponseV0 {
oneof result {
AddressInfoEntries address_info_entries = 1;
Proof proof = 2;
}
ResponseMetadata metadata = 3;
}
oneof version { GetAddressesInfosResponseV0 v0 = 1; }
}
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 @@ -519,4 +519,16 @@ impl Platform for PlatformServiceImpl {
dapi_grpc::platform::v0::GetGroupActionSignersRequest,
dapi_grpc::platform::v0::GetGroupActionSignersResponse
);

drive_method!(
get_address_info,
dapi_grpc::platform::v0::GetAddressInfoRequest,
dapi_grpc::platform::v0::GetAddressInfoResponse
);

drive_method!(
get_addresses_infos,
dapi_grpc::platform::v0::GetAddressesInfosRequest,
dapi_grpc::platform::v0::GetAddressesInfosResponse
);
}
1 change: 1 addition & 0 deletions packages/rs-dpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", tag = "v0.40.0",
"rand",
"signer",
"serde",
"eddsa",
], default-features = false }
key-wallet = { git = "https://github.com/dashpay/rust-dashcore", tag = "v0.40.0", optional = true }
key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", tag = "v0.40.0", optional = true }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::address_funds::fee_strategy::deduct_fee_from_inputs_and_outputs::v0::deduct_fee_from_outputs_or_remaining_balance_of_inputs_v0;
use crate::address_funds::{AddressFundsFeeStrategy, PlatformAddress};
use crate::fee::Credits;
use crate::prelude::AddressNonce;
use crate::ProtocolError;
use platform_version::version::PlatformVersion;
use std::collections::BTreeMap;

mod v0;

/// Result of deducting fees from outputs or remaining balance of inputs.
///
/// This struct contains the adjusted balances after applying the fee strategy,
/// along with information about whether the fee was fully covered.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FeeDeductionResult {
/// The remaining balance of input addresses after fee deduction.
/// If an address has its balance reduced to zero, it may be removed from this map.
pub remaining_input_balances: BTreeMap<PlatformAddress, (AddressNonce, Credits)>,

/// The adjusted output amounts after fee deduction.
/// If an output has its amount reduced to zero, it may be removed from this map.
pub adjusted_outputs: BTreeMap<PlatformAddress, Credits>,

/// Whether the fee was fully covered by the available funds.
/// If false, the fee strategy steps were exhausted before the full fee could be deducted.
pub fee_fully_covered: bool,
}

pub fn deduct_fee_from_outputs_or_remaining_balance_of_inputs(
inputs: BTreeMap<PlatformAddress, (AddressNonce, Credits)>,
outputs: BTreeMap<PlatformAddress, Credits>,
fee_strategy: &AddressFundsFeeStrategy,
fee: Credits,
platform_version: &PlatformVersion,
) -> Result<FeeDeductionResult, ProtocolError> {
match platform_version
.dpp
.methods
.deduct_fee_from_outputs_or_remaining_balance_of_inputs
{
0 => deduct_fee_from_outputs_or_remaining_balance_of_inputs_v0(
inputs,
outputs,
fee_strategy,
fee,
),
version => Err(ProtocolError::UnknownVersionMismatch {
method: "deduct_fee_from_outputs_or_remaining_balance_of_inputs".to_string(),
known_versions: vec![0],
received: version,
}),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use crate::address_funds::fee_strategy::deduct_fee_from_inputs_and_outputs::FeeDeductionResult;
use crate::address_funds::fee_strategy::AddressFundsFeeStrategyStep;
use crate::address_funds::{AddressFundsFeeStrategy, PlatformAddress};
use crate::fee::Credits;
use crate::prelude::AddressNonce;
use crate::ProtocolError;
use std::collections::BTreeMap;

/// Deducts the fee from outputs or remaining balance of inputs according to the fee strategy.
///
/// The inputs represent the REMAINING BALANCE after the transfer (e.g., if address A had 10
/// and we're sending 3, the input shows A: 7 remaining).
///
/// The fee strategy determines the priority order for deducting the fee:
/// - `DeductFromInput(i)`: Reduce the ith input's remaining balance (address keeps less)
/// - `ReduceOutput(i)`: Reduce the ith output amount (less is sent to that address)
///
/// The strategy steps are applied in order until the fee is fully covered.
pub fn deduct_fee_from_outputs_or_remaining_balance_of_inputs_v0(
mut inputs: BTreeMap<PlatformAddress, (AddressNonce, Credits)>,
mut outputs: BTreeMap<PlatformAddress, Credits>,
fee_strategy: &AddressFundsFeeStrategy,
fee: Credits,
) -> Result<FeeDeductionResult, ProtocolError> {
let mut remaining_fee = fee;

for step in fee_strategy {
if remaining_fee == 0 {
break;
}

match step {
AddressFundsFeeStrategyStep::DeductFromInput(index) => {
// Reduce the remaining balance of the input at the specified index
if let Some((&address, &(nonce, amount))) = inputs.iter().nth(*index as usize) {
let reduction = remaining_fee.min(amount);
let new_amount = amount - reduction;
remaining_fee -= reduction;

if new_amount == 0 {
inputs.remove(&address);
} else {
inputs.insert(address, (nonce, new_amount));
}
}
}
AddressFundsFeeStrategyStep::ReduceOutput(index) => {
// Reduce the output at the specified index
if let Some((&address, &amount)) = outputs.iter().nth(*index as usize) {
let reduction = remaining_fee.min(amount);
let new_amount = amount - reduction;
remaining_fee -= reduction;

if new_amount == 0 {
outputs.remove(&address);
} else {
outputs.insert(address, new_amount);
}
}
}
}
}

Ok(FeeDeductionResult {
remaining_input_balances: inputs,
adjusted_outputs: outputs,
fee_fully_covered: remaining_fee == 0,
})
}
29 changes: 29 additions & 0 deletions packages/rs-dpp/src/address_funds/fee_strategy/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pub mod deduct_fee_from_inputs_and_outputs;

pub use deduct_fee_from_inputs_and_outputs::FeeDeductionResult;

use bincode_derive::{Decode, Encode};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "state-transition-serde-conversion",
derive(Serialize, Deserialize),
serde(rename_all = "camelCase")
)]
pub enum AddressFundsFeeStrategyStep {
/// Deduct fee from a specific input address by index.
/// The input must have remaining balance after its contribution to outputs.
DeductFromInput(u16),
/// Reduce a specific output by the fee amount.
/// The output amount will be reduced to cover the fee.
ReduceOutput(u16),
}

impl Default for AddressFundsFeeStrategyStep {
fn default() -> Self {
AddressFundsFeeStrategyStep::DeductFromInput(0)
}
}

pub type AddressFundsFeeStrategy = Vec<AddressFundsFeeStrategyStep>;
9 changes: 9 additions & 0 deletions packages/rs-dpp/src/address_funds/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod fee_strategy;
mod platform_address;
mod witness;
mod witness_verification_operations;

pub use fee_strategy::*;
pub use platform_address::*;
pub use witness::*;
pub use witness_verification_operations::*;
Loading
Loading