Skip to content

Commit

Permalink
Handle object locks in WritebackCache (MystenLabs#16949)
Browse files Browse the repository at this point in the history
  • Loading branch information
mystenmark authored Apr 13, 2024
1 parent b8c13cd commit b6b35ed
Show file tree
Hide file tree
Showing 10 changed files with 687 additions and 114 deletions.
2 changes: 1 addition & 1 deletion crates/sui-core/src/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,7 @@ impl AuthorityState {

fn check_owned_locks(&self, owned_object_refs: &[ObjectRef]) -> SuiResult {
self.execution_cache
.check_owned_object_locks_exist(owned_object_refs)
.check_owned_objects_are_live(owned_object_refs)
}

/// This function captures the required state to debug a forked transaction.
Expand Down
9 changes: 3 additions & 6 deletions crates/sui-core/src/authority/authority_per_epoch_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -787,14 +787,12 @@ impl AuthorityEpochTables {
pub fn write_transaction_locks(
&self,
transaction: VerifiedSignedTransaction,
locks_to_write: impl IntoIterator<Item = (ObjectRef, LockDetails)>,
locks_to_write: impl Iterator<Item = (ObjectRef, LockDetails)>,
) -> SuiResult {
let mut batch = self.owned_object_locked_transactions.batch();
batch.insert_batch(
&self.owned_object_locked_transactions,
locks_to_write
.into_iter()
.map(|(obj_ref, lock)| (obj_ref, LockDetailsWrapper::from(lock))),
locks_to_write.map(|(obj_ref, lock)| (obj_ref, LockDetailsWrapper::from(lock))),
)?;
batch.insert_batch(
&self.signed_transactions,
Expand Down Expand Up @@ -1467,8 +1465,7 @@ impl AuthorityPerEpochStore {

pub fn object_lock_split_tables_enabled(&self) -> bool {
self.epoch_start_configuration
.flags()
.contains(&EpochFlag::ObjectLockSplitTables)
.object_lock_split_tables_enabled()
}

// For each id in objects_to_init, return the next version for that id as recorded in the
Expand Down
15 changes: 2 additions & 13 deletions crates/sui-core/src/authority/authority_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -913,17 +913,6 @@ impl AuthorityStore {

write_batch.insert_batch(&self.perpetual_tables.events, events)?;

// NOTE: We just check here that locks exist, not that they are locked to a specific TX. Why?
// 1. Lock existence prevents re-execution of old certs when objects have been upgraded
// 2. Not all validators lock, just 2f+1, so transaction should proceed regardless
// (But the lock should exist which means previous transactions finished)
// 3. Equivocation possible (different TX) but as long as 2f+1 approves current TX its
// fine
// 4. Locks may have existed when we started processing this tx, but could have since
// been deleted by a concurrent tx that finished first. In that case, check if the
// tx effects exist.
self.check_owned_object_locks_exist(locks_to_delete)?;

self.initialize_live_object_markers_impl(&mut write_batch, new_locks_to_init, false)?;

// Note: deletes locks for received objects as well (but not for objects that were in
Expand Down Expand Up @@ -1134,7 +1123,7 @@ impl AuthorityStore {

if !locks_to_write.is_empty() {
trace!(?locks_to_write, "Writing locks");
epoch_tables.write_transaction_locks(transaction, locks_to_write)?;
epoch_tables.write_transaction_locks(transaction, locks_to_write.into_iter())?;
}

Ok(())
Expand Down Expand Up @@ -1255,7 +1244,7 @@ impl AuthorityStore {
/// Returns UserInputError::ObjectNotFound if cannot find lock record for at least one of the objects.
/// Returns UserInputError::ObjectVersionUnavailableForConsumption if at least one object lock is not initialized
/// at the given version.
pub fn check_owned_object_locks_exist(&self, objects: &[ObjectRef]) -> SuiResult {
pub fn check_owned_objects_are_live(&self, objects: &[ObjectRef]) -> SuiResult {
let locks = self
.perpetual_tables
.live_owned_object_markers
Expand Down
4 changes: 4 additions & 0 deletions crates/sui-core/src/authority/epoch_start_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ impl EpochStartConfiguration {
pub fn epoch_start_timestamp_ms(&self) -> CheckpointTimestamp {
self.epoch_start_state().epoch_start_timestamp_ms()
}

pub fn object_lock_split_tables_enabled(&self) -> bool {
self.flags().contains(&EpochFlag::ObjectLockSplitTables)
}
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
Expand Down
13 changes: 8 additions & 5 deletions crates/sui-core/src/execution_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use sui_types::{
use tracing::instrument;

pub(crate) mod cache_types;
mod object_locks;
pub mod passthrough_cache;
pub mod writeback_cache;

Expand Down Expand Up @@ -132,11 +133,11 @@ pub trait ExecutionCacheRead: Send + Sync {
for (object_opt, object_ref) in objects.into_iter().zip(object_refs) {
match object_opt {
None => {
let lock = self._get_latest_lock_for_object_id(object_ref.0)?;
let error = if lock.1 >= object_ref.1 {
let live_objref = self._get_live_objref(object_ref.0)?;
let error = if live_objref.1 >= object_ref.1 {
UserInputError::ObjectVersionUnavailableForConsumption {
provided_obj_ref: *object_ref,
current_version: lock.1,
current_version: live_objref.1,
}
} else {
UserInputError::ObjectNotFound {
Expand Down Expand Up @@ -249,9 +250,11 @@ pub trait ExecutionCacheRead: Send + Sync {
fn get_lock(&self, obj_ref: ObjectRef, epoch_store: &AuthorityPerEpochStore) -> SuiLockResult;

// This method is considered "private" - only used by multi_get_objects_with_more_accurate_error_return
fn _get_latest_lock_for_object_id(&self, object_id: ObjectID) -> SuiResult<ObjectRef>;
fn _get_live_objref(&self, object_id: ObjectID) -> SuiResult<ObjectRef>;

fn check_owned_object_locks_exist(&self, owned_object_refs: &[ObjectRef]) -> SuiResult;
// Check that the given set of objects are live at the given version. This is used as a
// safety check before execution, and could potentially be deleted or changed to a debug_assert
fn check_owned_objects_are_live(&self, owned_object_refs: &[ObjectRef]) -> SuiResult;

fn multi_get_transaction_blocks(
&self,
Expand Down
Loading

0 comments on commit b6b35ed

Please sign in to comment.