Skip to content

Commit

Permalink
Move balance tracker inside accumulator
Browse files Browse the repository at this point in the history
  • Loading branch information
azarovh committed Feb 2, 2024
1 parent 616df83 commit a9b3951
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 191 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) 2024 RBB S.r.l
// [email protected]
// SPDX-License-Identifier: MIT
// Licensed under the MIT License;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::{btree_map::Entry, BTreeMap};

use common::{
chain::{AccountSpending, AccountType, DelegationId},
primitives::Amount,
};

use crate::Error;

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
enum GenericAccountId {
Delegation(DelegationId),
}

impl From<AccountSpending> for GenericAccountId {
fn from(account: AccountSpending) -> Self {
match account {
AccountSpending::DelegationBalance(id, _) => Self::Delegation(id),
}
}
}

impl From<GenericAccountId> for AccountType {
fn from(value: GenericAccountId) -> Self {
match value {
GenericAccountId::Delegation(id) => AccountType::Delegation(id),
}
}
}

pub struct AccountsBalancesTracker<'a, DelegationBalanceGetterFn> {
balances: BTreeMap<GenericAccountId, Amount>,

delegation_balance_getter: &'a DelegationBalanceGetterFn,
}

impl<'a, DelegationBalanceGetterFn> AccountsBalancesTracker<'a, DelegationBalanceGetterFn>
where
DelegationBalanceGetterFn: Fn(DelegationId) -> Result<Option<Amount>, Error>,
{
pub fn new(delegation_balance_getter: &'a DelegationBalanceGetterFn) -> Self {
Self {
balances: BTreeMap::new(),
delegation_balance_getter,
}
}

pub fn spend_from_account(&mut self, account: AccountSpending) -> Result<(), Error> {
match self.balances.entry(account.clone().into()) {
Entry::Vacant(e) => {
let (balance, spending) = match account {
AccountSpending::DelegationBalance(id, spending) => {
let balance = (self.delegation_balance_getter)(id)?
.ok_or(Error::AccountBalanceNotFound(account.clone().into()))?;
(balance, spending)
}
};
let new_balance = (balance - spending)
.ok_or(Error::NegativeAccountBalance(account.clone().into()))?;
e.insert(new_balance);
}
Entry::Occupied(mut e) => {
let balance = e.get_mut();
let spending = match account {
AccountSpending::DelegationBalance(_, spending) => spending,
};
*balance = (*balance - spending)
.ok_or(Error::NegativeAccountBalance(account.clone().into()))?;
}
};
Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use common::{
};
use utils::ensure;

use crate::accounts_balances_tracker::AccountsBalancesTracker;

use super::{accumulated_fee::AccumulatedFee, insert_or_increase, Error};

/// `ConstrainedValueAccumulator` helps avoiding messy inputs/outputs combinations analysis by
Expand Down Expand Up @@ -73,6 +75,8 @@ impl ConstrainedValueAccumulator {

let mut accumulator = Self::new();
let mut total_fee_deducted = Amount::ZERO;
let mut accounts_balances_tracker =
AccountsBalancesTracker::new(&delegation_balance_getter);

for (input, input_utxo) in inputs.iter().zip(inputs_utxos.iter()) {
match input {
Expand All @@ -92,6 +96,7 @@ impl ConstrainedValueAccumulator {
chain_config,
block_height,
outpoint.account(),
&mut accounts_balances_tracker,
&delegation_balance_getter,
)?;
}
Expand Down Expand Up @@ -195,6 +200,7 @@ impl ConstrainedValueAccumulator {
chain_config: &ChainConfig,
block_height: BlockHeight,
account: &AccountSpending,
accounts_balances_tracker: &mut AccountsBalancesTracker<DelegationBalanceGetterFn>,
delegation_balance_getter: &DelegationBalanceGetterFn,
) -> Result<(), Error>
where
Expand All @@ -216,7 +222,9 @@ impl ConstrainedValueAccumulator {
Error::AttemptToPrintMoney(CoinOrTokenId::Coin)
);
}
AccountsBalancesCheckVersion::V1 => {}
AccountsBalancesCheckVersion::V1 => {
accounts_balances_tracker.spend_from_account(account.clone())?;
}
}

let maturity_distance =
Expand Down
6 changes: 5 additions & 1 deletion chainstate/constraints-value-accumulator/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// limitations under the License.

use common::{
chain::{DelegationId, PoolId, UtxoOutPoint},
chain::{AccountType, DelegationId, PoolId, UtxoOutPoint},
primitives::CoinOrTokenId,
};

Expand Down Expand Up @@ -44,4 +44,8 @@ pub enum Error {
SpendingNonSpendableOutput(UtxoOutPoint),
#[error("Balance not found for delegation `{0}`")]
DelegationBalanceNotFound(DelegationId),
#[error("Account balance not found for `{0:?}`")]
AccountBalanceNotFound(AccountType),
#[error("Negative account balance for `{0:?}`")]
NegativeAccountBalance(AccountType),
}
1 change: 1 addition & 0 deletions chainstate/constraints-value-accumulator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::collections::BTreeMap;

use common::primitives::Amount;

mod accounts_balances_tracker;
mod accumulated_fee;
mod constraints_accumulator;
mod error;
Expand Down
6 changes: 2 additions & 4 deletions chainstate/src/detail/ban_score.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,6 @@ impl BanScore for EpochSealError {
impl BanScore for IOPolicyError {
fn ban_score(&self) -> u32 {
match self {
IOPolicyError::PoSAccountingError(err) => err.ban_score(),
IOPolicyError::InvalidInputTypeInReward => 100,
IOPolicyError::InvalidOutputTypeInReward => 100,
IOPolicyError::InvalidInputTypeInTx => 100,
Expand All @@ -486,9 +485,6 @@ impl BanScore for IOPolicyError {
IOPolicyError::ProduceBlockInTx => 100,
IOPolicyError::MultipleAccountCommands => 100,
IOPolicyError::AttemptToUseAccountInputInReward => 100,
IOPolicyError::AccountBalanceNotFound(_) => 0,
IOPolicyError::NegativeAccountBalance(_) => 100,
IOPolicyError::AccountBalanceOverflow(_) => 100,
}
}
}
Expand All @@ -507,6 +503,8 @@ impl BanScore for constraints_value_accumulator::Error {
constraints_value_accumulator::Error::SpendingNonSpendableOutput(_) => 100,
constraints_value_accumulator::Error::AttemptToViolateFeeRequirements => 100,
constraints_value_accumulator::Error::DelegationBalanceNotFound(_) => 0,
constraints_value_accumulator::Error::AccountBalanceNotFound(_) => 0,
constraints_value_accumulator::Error::NegativeAccountBalance(_) => 100,
}
}
}
Expand Down
58 changes: 44 additions & 14 deletions chainstate/test-suite/src/tests/delegation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,17 @@ fn delegate_and_spend_share_same_tx(
);
}
AccountsBalancesCheckVersion::V1 => {
res.unwrap();
assert_eq!(
res.unwrap_err(),
ChainstateError::ProcessBlockError(BlockError::StateUpdateFailed(
ConnectTransactionError::ConstrainedValueAccumulatorError(
constraints_value_accumulator::Error::NegativeAccountBalance(
AccountType::Delegation(delegation_id)
),
tx_id.into()
)
))
);
}
}
});
Expand Down Expand Up @@ -1114,8 +1124,28 @@ fn delegate_and_spend_share_same_tx_no_overspend_per_input(
))
.add_output(TxOutput::DelegateStaking(change, delegation_id))
.build();
let tx_id = tx.transaction().get_id();

tf.make_block_builder().add_transaction(tx).build_and_process().unwrap();
let res = tf.make_block_builder().add_transaction(tx).build_and_process();

match accumulator_version {
AccountsBalancesCheckVersion::V0 => {
res.unwrap();
}
AccountsBalancesCheckVersion::V1 => {
assert_eq!(
res.unwrap_err(),
ChainstateError::ProcessBlockError(BlockError::StateUpdateFailed(
ConnectTransactionError::ConstrainedValueAccumulatorError(
constraints_value_accumulator::Error::NegativeAccountBalance(
AccountType::Delegation(delegation_id)
),
tx_id.into()
)
))
);
}
}
});
}

Expand Down Expand Up @@ -1234,10 +1264,10 @@ fn delegate_and_spend_share_same_block(
assert_eq!(
res.unwrap_err(),
ChainstateError::ProcessBlockError(BlockError::StateUpdateFailed(
ConnectTransactionError::IOPolicyError(
IOPolicyError::NegativeAccountBalance(AccountType::Delegation(
delegation_id
)),
ConnectTransactionError::ConstrainedValueAccumulatorError(
constraints_value_accumulator::Error::NegativeAccountBalance(
AccountType::Delegation(delegation_id)
),
tx1_id.into()
)
))
Expand Down Expand Up @@ -1363,10 +1393,10 @@ fn try_overspend_delegation(
assert_eq!(
res.unwrap_err(),
ChainstateError::ProcessBlockError(BlockError::StateUpdateFailed(
ConnectTransactionError::IOPolicyError(
IOPolicyError::NegativeAccountBalance(AccountType::Delegation(
delegation_id
)),
ConnectTransactionError::ConstrainedValueAccumulatorError(
constraints_value_accumulator::Error::NegativeAccountBalance(
AccountType::Delegation(delegation_id)
),
tx_id.into()
)
))
Expand Down Expand Up @@ -1531,10 +1561,10 @@ fn delegate_and_spend_share_same_block_multiple_delegations(
assert_eq!(
res.unwrap_err(),
ChainstateError::ProcessBlockError(BlockError::StateUpdateFailed(
ConnectTransactionError::IOPolicyError(
IOPolicyError::NegativeAccountBalance(AccountType::Delegation(
delegation_id_1
)),
ConnectTransactionError::ConstrainedValueAccumulatorError(
constraints_value_accumulator::Error::NegativeAccountBalance(
AccountType::Delegation(delegation_id_1)
),
tx_id_1.into()
)
))
Expand Down
4 changes: 2 additions & 2 deletions chainstate/test-suite/src/tests/pos_processing_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1891,8 +1891,8 @@ fn spend_from_delegation_with_reward(#[case] seed: Seed) {
assert_eq!(
res,
ChainstateError::ProcessBlockError(BlockError::StateUpdateFailed(
ConnectTransactionError::IOPolicyError(
chainstate::IOPolicyError::NegativeAccountBalance(
ConnectTransactionError::ConstrainedValueAccumulatorError(
constraints_value_accumulator::Error::NegativeAccountBalance(
common::chain::AccountType::Delegation(delegation_id)
),
tx_id.into()
Expand Down
Loading

0 comments on commit a9b3951

Please sign in to comment.