Skip to content

Commit 2d48b7e

Browse files
committed
Implement object balance withdraw
1 parent e3021a3 commit 2d48b7e

File tree

26 files changed

+964
-206
lines changed

26 files changed

+964
-206
lines changed

crates/sui-core/src/authority.rs

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::execution_cache::ExecutionCacheTraitPointers;
1212
use crate::execution_cache::TransactionCacheRead;
1313
use crate::execution_scheduler::ExecutionScheduler;
1414
use crate::execution_scheduler::SchedulingSource;
15+
use crate::execution_scheduler::balance_withdraw_scheduler::BalanceSettlement;
1516
use crate::jsonrpc_index::CoinIndexKey2;
1617
use crate::rpc_index::RpcIndexStore;
1718
use crate::traffic_controller::TrafficController;
@@ -802,8 +803,9 @@ pub struct ExecutionEnv {
802803
pub expected_effects_digest: Option<TransactionEffectsDigest>,
803804
/// The source of the scheduling of the transaction.
804805
pub scheduling_source: SchedulingSource,
805-
/// Status of the balance withdraw scheduling of the transaction.
806-
pub withdraw_status: BalanceWithdrawStatus,
806+
/// Status of the balance withdraw scheduling of the transaction,
807+
/// including both address and object balance withdraws.
808+
pub balance_withdraw_status: BalanceWithdrawStatus,
807809
/// Transactions that must finish before this transaction can be executed.
808810
/// Used to schedule barrier transactions after non-exclusive writes.
809811
pub barrier_dependencies: Vec<TransactionDigest>,
@@ -815,7 +817,7 @@ impl Default for ExecutionEnv {
815817
assigned_versions: Default::default(),
816818
expected_effects_digest: None,
817819
scheduling_source: SchedulingSource::NonFastPath,
818-
withdraw_status: BalanceWithdrawStatus::NoWithdraw,
820+
balance_withdraw_status: BalanceWithdrawStatus::Unknown,
819821
barrier_dependencies: Default::default(),
820822
}
821823
}
@@ -844,13 +846,8 @@ impl ExecutionEnv {
844846
self
845847
}
846848

847-
pub fn with_sufficient_balance(mut self) -> Self {
848-
self.withdraw_status = BalanceWithdrawStatus::SufficientBalance;
849-
self
850-
}
851-
852849
pub fn with_insufficient_balance(mut self) -> Self {
853-
self.withdraw_status = BalanceWithdrawStatus::InsufficientBalance;
850+
self.balance_withdraw_status = BalanceWithdrawStatus::InsufficientBalance;
854851
self
855852
}
856853

@@ -1763,7 +1760,7 @@ impl AuthorityState {
17631760
&self,
17641761
tx_lock: &CertLockGuard,
17651762
certificate: &VerifiedExecutableTransaction,
1766-
assigned_shared_object_versions: AssignedVersions,
1763+
assigned_shared_object_versions: &AssignedVersions,
17671764
epoch_store: &Arc<AuthorityPerEpochStore>,
17681765
) -> SuiResult<InputObjects> {
17691766
let _scope = monitored_scope("Execution::load_input_objects");
@@ -1776,7 +1773,7 @@ impl AuthorityState {
17761773
&certificate.key(),
17771774
tx_lock,
17781775
input_objects,
1779-
&assigned_shared_object_versions,
1776+
assigned_shared_object_versions,
17801777
epoch_store.epoch(),
17811778
)
17821779
}
@@ -1871,7 +1868,7 @@ impl AuthorityState {
18711868
let input_objects = match self.read_objects_for_execution(
18721869
tx_guard.as_lock_guard(),
18731870
certificate,
1874-
execution_env.assigned_versions,
1871+
&execution_env.assigned_versions,
18751872
epoch_store,
18761873
) {
18771874
Ok(objects) => objects,
@@ -1907,7 +1904,7 @@ impl AuthorityState {
19071904
certificate,
19081905
input_objects,
19091906
expected_effects_digest,
1910-
execution_env.withdraw_status,
1907+
execution_env,
19111908
epoch_store,
19121909
)
19131910
}
@@ -2020,7 +2017,7 @@ impl AuthorityState {
20202017
certificate: &VerifiedExecutableTransaction,
20212018
input_objects: InputObjects,
20222019
expected_effects_digest: Option<TransactionEffectsDigest>,
2023-
withdraw_status: BalanceWithdrawStatus,
2020+
execution_env: ExecutionEnv,
20242021
epoch_store: &Arc<AuthorityPerEpochStore>,
20252022
) -> ExecutionOutput<(
20262023
TransactionOutputs,
@@ -2062,7 +2059,7 @@ impl AuthorityState {
20622059
&tx_digest,
20632060
&input_objects,
20642061
self.config.certificate_deny_config.certificate_deny_set(),
2065-
&withdraw_status,
2062+
&execution_env.balance_withdraw_status,
20662063
);
20672064
let execution_params = match early_execution_error {
20682065
Some(error) => ExecutionOrEarlyError::Err(error),
@@ -2097,6 +2094,13 @@ impl AuthorityState {
20972094
&mut None,
20982095
);
20992096

2097+
if !self
2098+
.execution_scheduler
2099+
.should_commit_object_balance_withdraws(certificate, &effects, &execution_env)
2100+
{
2101+
return ExecutionOutput::RetryLater;
2102+
}
2103+
21002104
if let Some(expected_effects_digest) = expected_effects_digest
21012105
&& effects.digest() != expected_effects_digest
21022106
{
@@ -2232,7 +2236,7 @@ impl AuthorityState {
22322236
certificate,
22332237
input_objects,
22342238
None,
2235-
BalanceWithdrawStatus::NoWithdraw,
2239+
ExecutionEnv::default(),
22362240
epoch_store,
22372241
)
22382242
.unwrap();
@@ -2376,7 +2380,7 @@ impl AuthorityState {
23762380
&checked_input_objects,
23772381
self.config.certificate_deny_config.certificate_deny_set(),
23782382
// TODO(address-balances): Mimic withdraw scheduling and pass the result.
2379-
&BalanceWithdrawStatus::NoWithdraw,
2383+
&BalanceWithdrawStatus::Unknown,
23802384
);
23812385
let execution_params = match early_execution_error {
23822386
Some(error) => ExecutionOrEarlyError::Err(error),
@@ -2584,7 +2588,7 @@ impl AuthorityState {
25842588
&checked_input_objects,
25852589
self.config.certificate_deny_config.certificate_deny_set(),
25862590
// TODO(address-balances): Mimic withdraw scheduling and pass the result.
2587-
&BalanceWithdrawStatus::NoWithdraw,
2591+
&BalanceWithdrawStatus::Unknown,
25882592
);
25892593
let execution_params = match early_execution_error {
25902594
Some(error) => ExecutionOrEarlyError::Err(error),
@@ -2829,7 +2833,7 @@ impl AuthorityState {
28292833
&checked_input_objects,
28302834
self.config.certificate_deny_config.certificate_deny_set(),
28312835
// TODO(address-balances): Mimic withdraw scheduling and pass the result.
2832-
&BalanceWithdrawStatus::NoWithdraw,
2836+
&BalanceWithdrawStatus::Unknown,
28332837
);
28342838
let execution_params = match early_execution_error {
28352839
Some(error) => ExecutionOrEarlyError::Err(error),
@@ -3910,7 +3914,7 @@ impl AuthorityState {
39103914
Ok(new_epoch_store)
39113915
}
39123916

3913-
pub async fn settle_transactions_for_testing(
3917+
pub async fn settle_accumulator_for_testing(
39143918
&self,
39153919
ckpt_seq: CheckpointSequenceNumber,
39163920
effects: &[TransactionEffects],
@@ -3921,6 +3925,7 @@ impl AuthorityState {
39213925
ckpt_seq,
39223926
0,
39233927
);
3928+
let balance_changes = builder.collect_accumulator_changes();
39243929
let epoch_store = self.epoch_store_for_testing();
39253930
let epoch = epoch_store.epoch();
39263931
let (settlements, barrier) = builder.build_tx(
@@ -3978,12 +3983,17 @@ impl AuthorityState {
39783983
.next()
39793984
.unwrap()
39803985
.1;
3986+
let next_accumulator_version = assigned_versions.accumulator_version.unwrap().next();
39813987
let env = ExecutionEnv::new().with_assigned_versions(assigned_versions);
39823988
let (effects, _) = self
39833989
.try_execute_immediately(&barrier, env, &epoch_store)
39843990
.await
39853991
.unwrap();
39863992
assert!(effects.status().is_ok());
3993+
self.execution_scheduler.settle_balances(BalanceSettlement {
3994+
balance_changes,
3995+
next_accumulator_version,
3996+
});
39873997
}
39883998

39893999
/// Advance the epoch store to the next epoch for testing only.
@@ -6045,7 +6055,7 @@ impl AuthorityState {
60456055
let input_objects = self.read_objects_for_execution(
60466056
&tx_lock,
60476057
&executable_tx,
6048-
assigned_versions,
6058+
&assigned_versions,
60496059
epoch_store,
60506060
)?;
60516061

@@ -6055,7 +6065,7 @@ impl AuthorityState {
60556065
&executable_tx,
60566066
input_objects,
60576067
None,
6058-
BalanceWithdrawStatus::NoWithdraw,
6068+
ExecutionEnv::default(),
60596069
epoch_store,
60606070
)
60616071
.unwrap();

crates/sui-core/src/checkpoints/checkpoint_executor/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,8 +876,8 @@ impl CheckpointExecutor {
876876
.with_barrier_dependencies(barrier_deps);
877877

878878
// Check if the expected effects indicate insufficient balance
879-
if let ExecutionStatus::Failure {
880-
error: ExecutionFailureStatus::InsufficientBalanceForWithdraw,
879+
if let &ExecutionStatus::Failure {
880+
error: ExecutionFailureStatus::InsufficientFunds,
881881
..
882882
} = effects.status()
883883
{

crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/e2e_tests.rs renamed to crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/address_balance/e2e_tests.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use sui_types::{
2828
use tokio::sync::mpsc::{self, unbounded_channel};
2929
use tokio::time::timeout;
3030

31-
use crate::execution_scheduler::balance_withdraw_scheduler::BalanceSettlement;
31+
use super::BalanceSettlement;
3232
use crate::{
3333
authority::{
3434
AuthorityState, ExecutionEnv, shared_object_version_manager::Schedulable,
@@ -158,7 +158,7 @@ impl TestEnv {
158158
let cert = self.receive_certificate().await.unwrap();
159159
results.insert(
160160
*cert.certificate.digest(),
161-
cert.execution_env.withdraw_status,
161+
cert.execution_env.balance_withdraw_status,
162162
);
163163
}
164164
assert_eq!(results, expected_results);
@@ -212,14 +212,8 @@ async fn test_withdraw_schedule_e2e() {
212212
test_env.enqueue_transactions(transactions.clone());
213213
test_env
214214
.expect_withdraw_results(BTreeMap::from([
215-
(
216-
*transactions[0].digest(),
217-
BalanceWithdrawStatus::SufficientBalance,
218-
),
219-
(
220-
*transactions[1].digest(),
221-
BalanceWithdrawStatus::SufficientBalance,
222-
),
215+
(*transactions[0].digest(), BalanceWithdrawStatus::Unknown),
216+
(*transactions[1].digest(), BalanceWithdrawStatus::Unknown),
223217
(
224218
*transactions[2].digest(),
225219
BalanceWithdrawStatus::InsufficientBalance,
@@ -235,10 +229,7 @@ async fn test_withdraw_schedule_e2e() {
235229
test_env.settle_balances(BTreeMap::from([(test_env.account_objects[0], -500)]));
236230
test_env
237231
.expect_withdraw_results(BTreeMap::from([
238-
(
239-
*transactions[0].digest(),
240-
BalanceWithdrawStatus::SufficientBalance,
241-
),
232+
(*transactions[0].digest(), BalanceWithdrawStatus::Unknown),
242233
(
243234
*transactions[1].digest(),
244235
BalanceWithdrawStatus::InsufficientBalance,

crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/eager_scheduler.rs renamed to crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/address_balance/eager_scheduler.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@ use sui_types::{
1414
use tokio::sync::oneshot::Sender;
1515
use tracing::{debug, instrument};
1616

17-
use crate::{
18-
accumulators::balance_read::AccountBalanceRead,
19-
execution_scheduler::balance_withdraw_scheduler::{
20-
BalanceSettlement, ScheduleResult, ScheduleStatus, TxBalanceWithdraw,
21-
scheduler::{BalanceWithdrawSchedulerTrait, WithdrawReservations},
22-
},
17+
use super::{
18+
BalanceSettlement, ScheduleResult, ScheduleStatus, TxBalanceWithdraw,
19+
scheduler::{BalanceWithdrawSchedulerTrait, WithdrawReservations},
2320
};
21+
use crate::accumulators::balance_read::AccountBalanceRead;
2422

2523
pub(crate) struct EagerBalanceWithdrawScheduler {
2624
balance_read: Arc<dyn AccountBalanceRead>,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Mysten Labs, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::collections::BTreeMap;
5+
6+
use sui_types::{
7+
accumulator_root::AccumulatorObjId, base_types::SequenceNumber, digests::TransactionDigest,
8+
};
9+
10+
mod eager_scheduler;
11+
mod naive_scheduler;
12+
pub(crate) mod scheduler;
13+
#[cfg(test)]
14+
mod tests;
15+
16+
#[cfg(test)]
17+
mod e2e_tests;
18+
19+
/// The status of scheduling the withdraw reservations for a transaction.
20+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
21+
pub(crate) enum ScheduleStatus {
22+
/// We know for sure that the withdraw reservations in this transactions all have enough balance.
23+
/// This transaction can be executed normally as soon as its object dependencies are ready.
24+
SufficientBalance,
25+
/// We know for sure that the withdraw reservations in this transactions do not all have enough balance.
26+
/// This transaction should result in an execution failure without actually executing it, similar to
27+
/// how transaction cancellation works.
28+
InsufficientBalance,
29+
/// We can skip scheduling this transaction, due to one of the following reasons:
30+
/// 1. The accumulator version for this transaction has already been settled.
31+
/// 2. We are observing some account objects bumping to the next version, indicating
32+
/// that the withdraw transactions in this commit have already been executed and are
33+
/// being settled.
34+
SkipSchedule,
35+
}
36+
37+
/// The result of scheduling the withdraw reservations for a transaction.
38+
#[derive(Debug, Clone, Eq, PartialEq)]
39+
pub(crate) struct ScheduleResult {
40+
pub tx_digest: TransactionDigest,
41+
pub status: ScheduleStatus,
42+
}
43+
44+
/// Details regarding a balance settlement, generated when a settlement transaction has been executed
45+
/// and committed to the writeback cache.
46+
#[derive(Debug, Clone)]
47+
pub struct BalanceSettlement {
48+
// After this settlement, the accumulator object will be at this version.
49+
// This means that all transactions that read `next_accumulator_version - 1`
50+
// are settled as part of this settlement.
51+
pub next_accumulator_version: SequenceNumber,
52+
/// The balance changes for each account object ID.
53+
pub balance_changes: BTreeMap<AccumulatorObjId, i128>,
54+
}
55+
56+
/// Details regarding all balance withdraw reservations in a transaction.
57+
#[derive(Clone, Debug)]
58+
pub(crate) struct TxBalanceWithdraw {
59+
pub tx_digest: TransactionDigest,
60+
pub reservations: BTreeMap<AccumulatorObjId, u64>,
61+
}

crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/naive_scheduler.rs renamed to crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/address_balance/naive_scheduler.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ use sui_types::base_types::SequenceNumber;
77
use tokio::sync::watch;
88
use tracing::{debug, instrument};
99

10-
use crate::{
11-
accumulators::balance_read::AccountBalanceRead,
12-
execution_scheduler::balance_withdraw_scheduler::{
13-
BalanceSettlement, ScheduleResult, ScheduleStatus,
14-
scheduler::{BalanceWithdrawSchedulerTrait, WithdrawReservations},
15-
},
10+
use super::{
11+
BalanceSettlement, ScheduleResult, ScheduleStatus,
12+
scheduler::{BalanceWithdrawSchedulerTrait, WithdrawReservations},
1613
};
14+
use crate::accumulators::balance_read::AccountBalanceRead;
1715

1816
/// A naive implementation of the balance withdraw scheduler that does not attempt to optimize the scheduling.
1917
/// For each withdraw reservation, it will always wait until the dependent accumulator object is available,

crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/scheduler.rs renamed to crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/address_balance/scheduler.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@
33

44
use std::{collections::BTreeMap, sync::Arc};
55

6-
use crate::{
7-
accumulators::balance_read::AccountBalanceRead,
8-
execution_scheduler::balance_withdraw_scheduler::{
9-
BalanceSettlement, ScheduleResult, ScheduleStatus, TxBalanceWithdraw,
10-
eager_scheduler::EagerBalanceWithdrawScheduler,
11-
naive_scheduler::NaiveBalanceWithdrawScheduler,
12-
},
6+
use super::{
7+
BalanceSettlement, ScheduleResult, ScheduleStatus, TxBalanceWithdraw,
8+
eager_scheduler::EagerBalanceWithdrawScheduler, naive_scheduler::NaiveBalanceWithdrawScheduler,
139
};
10+
use crate::accumulators::balance_read::AccountBalanceRead;
1411
use futures::stream::FuturesUnordered;
1512
use mysten_metrics::monitored_mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel};
1613
use sui_types::base_types::SequenceNumber;

crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/tests.rs renamed to crates/sui-core/src/execution_scheduler/balance_withdraw_scheduler/address_balance/tests.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Copyright (c) Mysten Labs, Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use crate::execution_scheduler::balance_withdraw_scheduler::ScheduleResult;
5-
use crate::execution_scheduler::balance_withdraw_scheduler::{
6-
BalanceSettlement, ScheduleStatus, TxBalanceWithdraw, mock_balance_read::MockBalanceRead,
4+
use crate::execution_scheduler::balance_withdraw_scheduler::mock_balance_read::MockBalanceRead;
5+
6+
use super::{
7+
BalanceSettlement, ScheduleResult, ScheduleStatus, TxBalanceWithdraw,
78
scheduler::BalanceWithdrawScheduler,
89
};
910
use futures::StreamExt;

0 commit comments

Comments
 (0)