Skip to main content

drive/state_transition_action/batch/v0/
mod.rs

1use crate::state_transition_action::batch::ResolvedContractGroupMemberships;
2use dpp::fee::Credits;
3use std::collections::BTreeMap;
4use crate::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction;
5use dpp::identifier::Identifier;
6use dpp::prelude::UserFeeIncrease;
7use dpp::ProtocolError;
8use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction;
9use crate::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessorsV0;
10use crate::state_transition_action::batch::batched_transition::document_transition::document_purchase_transition_action::DocumentPurchaseTransitionActionAccessorsV0;
11use crate::state_transition_action::batch::batched_transition::token_transition::token_direct_purchase_transition_action::TokenDirectPurchaseTransitionActionAccessorsV0;
12use crate::state_transition_action::batch::batched_transition::token_transition::TokenTransitionAction;
13
14/// action v0
15#[derive(Default, Debug, Clone)]
16pub struct BatchTransitionActionV0 {
17    /// The owner making the transitions
18    pub owner_id: Identifier,
19    /// The inner transitions
20    pub transitions: Vec<BatchedTransitionAction>,
21    /// fee multiplier
22    pub user_fee_increase: UserFeeIncrease,
23    /// The contract group memberships of every contract the batch touches, keyed by contract
24    /// id, as the transformer read them from state (protocol version 14). Resolved only when
25    /// the batch is signed by a key bound to a contract group, so that key can be judged from
26    /// the action alone; empty for every other batch and under earlier transformer versions.
27    pub contract_group_memberships: BTreeMap<Identifier, ResolvedContractGroupMemberships>,
28}
29
30impl BatchTransitionActionV0 {
31    pub(in crate::state_transition_action) fn all_used_balances(
32        &self,
33    ) -> Result<Option<Credits>, ProtocolError> {
34        Ok(match (self.all_purchases_amount()?, self.all_conflicting_index_collateral_voting_funds()?) {
35            (Some(all_purchases_amount), Some(all_conflicting_index_collateral_voting_funds)) => Some(all_purchases_amount.checked_add(all_conflicting_index_collateral_voting_funds).ok_or(ProtocolError::Overflow("overflow between all_purchases_amount and all_conflicting_index_collateral_voting_funds"))?),
36            (Some(all_purchases_amount), None) => Some(all_purchases_amount),
37            (None, Some(all_conflicting_index_collateral_voting_funds)) => Some(all_conflicting_index_collateral_voting_funds),
38            (None, None) => None,
39        })
40    }
41    pub(in crate::state_transition_action) fn all_purchases_amount(
42        &self,
43    ) -> Result<Option<Credits>, ProtocolError> {
44        let (total, any_purchases): (Option<Credits>, bool) = self
45            .transitions
46            .iter()
47            .filter_map(|transition| match transition {
48                BatchedTransitionAction::DocumentAction(
49                    DocumentTransitionAction::PurchaseAction(document_purchase),
50                ) => Some(document_purchase.price()),
51                BatchedTransitionAction::TokenAction(
52                    TokenTransitionAction::DirectPurchaseAction(token_purchase),
53                ) => Some(token_purchase.total_agreed_price()),
54                _ => None,
55            })
56            .fold((None, false), |(acc, _), price| match acc {
57                Some(acc_val) => acc_val
58                    .checked_add(price)
59                    .map_or((None, true), |sum| (Some(sum), true)),
60                None => (Some(price), true),
61            });
62
63        match (total, any_purchases) {
64            (Some(total), _) => Ok(Some(total)),
65            (None, true) => Err(ProtocolError::Overflow("overflow in all purchases amount")), // Overflow occurred
66            _ => Ok(None), // No purchases were found
67        }
68    }
69
70    pub(in crate::state_transition_action) fn all_conflicting_index_collateral_voting_funds(
71        &self,
72    ) -> Result<Option<Credits>, ProtocolError> {
73        let (total, any_voting_funds): (Option<Credits>, bool) = self
74            .transitions
75            .iter()
76            .filter_map(|transition| match transition {
77                BatchedTransitionAction::DocumentAction(
78                    DocumentTransitionAction::CreateAction(document_create_transition_action),
79                ) => document_create_transition_action
80                    .prefunded_voting_balance()
81                    .iter()
82                    .try_fold(0u64, |acc, &(_, val)| acc.checked_add(val)),
83                _ => None,
84            })
85            .fold((None, false), |(acc, _), price| match acc {
86                Some(acc_val) => acc_val
87                    .checked_add(price)
88                    .map_or((None, true), |sum| (Some(sum), true)),
89                None => (Some(price), true),
90            });
91
92        match (total, any_voting_funds) {
93            (Some(total), _) => Ok(Some(total)),
94            (None, true) => Err(ProtocolError::Overflow(
95                "overflow in all voting funds amount",
96            )), // Overflow occurred
97            _ => Ok(None),
98        }
99    }
100}