Skip to content

Commit

Permalink
[hardening] enable simpler conservation checks
Browse files Browse the repository at this point in the history
Check conservation w.r.t storage rebate when `expensive_checks` is off
  • Loading branch information
sblackshear committed Apr 5, 2023
1 parent e95b596 commit 609caf3
Showing 1 changed file with 19 additions and 50 deletions.
69 changes: 19 additions & 50 deletions crates/sui-types/src/temporary_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,7 @@ impl<S: GetModule + ObjectStore + BackingPackageStore> TemporaryStore<S> {
)
})?
} else {
0
obj.storage_rebate
};
Ok((input_sui, obj.storage_rebate))
} else {
Expand Down Expand Up @@ -1169,7 +1169,7 @@ impl<S: GetModule + ObjectStore + BackingPackageStore> TemporaryStore<S> {
)
})?
} else {
0
obj.storage_rebate
};
Ok((input_sui, obj.storage_rebate))
}
Expand Down Expand Up @@ -1197,17 +1197,13 @@ impl<S: GetModule + ObjectStore + BackingPackageStore> TemporaryStore<S> {
let mut total_input_sui = 0;
// total amount of SUI in output objects, including both coins and storage rebates
let mut total_output_sui = 0;
// total amount of SUI in storage rebate of input objects
let mut total_input_rebate = 0;
// total amount of SUI in storage rebate of output objects
let mut total_output_rebate = 0;
for (id, (output_obj, kind)) in &self.written {
match kind {
WriteKind::Mutate => {
// note: output_obj.version has not yet been increased by the tx, so output_obj.version
// is the object version at tx input
let input_version = output_obj.version();
let (input_sui, input_storage_rebate) =
let (input_sui, _input_storage_rebate) =
self.get_input_sui(id, input_version, do_expensive_checks)?;
total_input_sui += input_sui;
if do_expensive_checks {
Expand All @@ -1216,9 +1212,9 @@ impl<S: GetModule + ObjectStore + BackingPackageStore> TemporaryStore<S> {
"Failed looking up output SUI in SUI conservation checking",
)
})?;
} else {
total_output_sui += output_obj.storage_rebate
}
total_input_rebate += input_storage_rebate;
total_output_rebate += output_obj.storage_rebate;
}
WriteKind::Create => {
// created objects did not exist at input, and thus contribute 0 to input SUI
Expand All @@ -1229,7 +1225,6 @@ impl<S: GetModule + ObjectStore + BackingPackageStore> TemporaryStore<S> {
)
})?;
}
total_output_rebate += output_obj.storage_rebate;
}
WriteKind::Unwrap => {
// an unwrapped object was either:
Expand All @@ -1242,26 +1237,25 @@ impl<S: GetModule + ObjectStore + BackingPackageStore> TemporaryStore<S> {
"Failed looking up output SUI in SUI conservation checking",
)
})?;
} else {
total_output_sui += output_obj.storage_rebate
}
total_output_rebate += output_obj.storage_rebate;
}
}
}
for (id, (input_version, kind)) in &self.deleted {
match kind {
DeleteKind::Normal => {
let (input_sui, input_storage_rebate) =
let (input_sui, _input_storage_rebate) =
self.get_input_sui(id, *input_version, do_expensive_checks)?;
total_input_sui += input_sui;
total_input_rebate += input_storage_rebate;
}
DeleteKind::Wrap => {
// wrapped object was a tx input or dynamic field--need to account for it in input SUI
// note: if an object is created by the tx, then wrapped, it will not appear here
let (input_sui, input_storage_rebate) =
let (input_sui, _input_storage_rebate) =
self.get_input_sui(id, *input_version, do_expensive_checks)?;
total_input_sui += input_sui;
total_input_rebate += input_storage_rebate;
// else, the wrapped object was either:
// 1. freshly created, which means it has 0 contribution to input SUI
// 2. unwrapped from another object A, which means its contribution to input SUI will be captured by looking at A
Expand All @@ -1280,45 +1274,20 @@ impl<S: GetModule + ObjectStore + BackingPackageStore> TemporaryStore<S> {
.map(|(_, summary)| summary.clone())
.unwrap_or_default();

if do_expensive_checks {
// note: storage_cost flows into the storage_rebate field of the output objects, which is why it is not accounted for here.
// similarly, all of the storage_rebate *except* the storage_fund_rebate_inflow gets credited to the gas coin
// both computation costs and storage rebate inflow are
total_output_sui +=
gas_summary.computation_cost + gas_summary.non_refundable_storage_fee;
if let Some((epoch_fees, epoch_rebates)) = advance_epoch_gas_summary {
total_input_sui += epoch_fees;
total_output_sui += epoch_rebates;
}
if total_input_sui != total_output_sui {
return Err(ExecutionError::invariant_violation(
// note: storage_cost flows into the storage_rebate field of the output objects, which is why it is not accounted for here.
// similarly, all of the storage_rebate *except* the storage_fund_rebate_inflow gets credited to the gas coin
// both computation costs and storage rebate inflow are
total_output_sui += gas_summary.computation_cost + gas_summary.non_refundable_storage_fee;
if let Some((epoch_fees, epoch_rebates)) = advance_epoch_gas_summary {
total_input_sui += epoch_fees;
total_output_sui += epoch_rebates;
}
if total_input_sui != total_output_sui {
return Err(ExecutionError::invariant_violation(
format!("SUI conservation failed: input={}, output={}, this transaction either mints or burns SUI",
total_input_sui,
total_output_sui))
);
}
}

// all SUI in storage rebate fields of input objects should flow either to the transaction storage rebate, or the non-refundable
// storage rebate pool
if total_input_rebate != gas_summary.storage_rebate + gas_summary.non_refundable_storage_fee
{
// TODO: re-enable once we fix the edge case with OOG, gas smashing, and storage rebate
/*return Err(ExecutionError::invariant_violation(
format!("SUI conservation failed--{} SUI in storage rebate field of input objects, {} SUI in tx storage rebate or tx non-refundable storage rebate",
total_input_rebate,
gas_summary.non_refundable_storage_fee))
);*/
}

// all SUI charged for storage should flow into the storage rebate field of some output object
if gas_summary.storage_cost != total_output_rebate {
// TODO: re-enable once we fix the edge case with OOG, gas smashing, and storage rebate
/*return Err(ExecutionError::invariant_violation(
format!("SUI conservation failed--{} SUI charged for storage, {} SUI in storage rebate field of output objects",
gas_summary.storage_cost,
total_output_rebate))
);*/
}
Ok(())
}
Expand Down

0 comments on commit 609caf3

Please sign in to comment.