Skip to content

Commit

Permalink
do not impose limits on unmetered TXes (MystenLabs#8199)
Browse files Browse the repository at this point in the history
Remove object runtime limits for system/unmetered TXes
Increase user object runtime limits to 2048
  • Loading branch information
oxade authored Feb 9, 2023
1 parent d254b16 commit 8cc013d
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ written: object(106)

task 5 'run'. lines 45-47:
Error: Transaction Effects Status: Move Primitive Runtime Error. Location: sui::tx_context::derive_id (function index 0) at offset 0. Arithmetic error, stack overflow, max value depth, etc.
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 1024 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 2048 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }

task 6 'run'. lines 48-48:
Error: Transaction Effects Status: Move Primitive Runtime Error. Location: sui::tx_context::derive_id (function index 0) at offset 0. Arithmetic error, stack overflow, max value depth, etc.
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 1024 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 2048 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ module Test::M1 {
//# run Test::M1::delete_n_ids --args 256

// run at run count limit should succeed
//# run Test::M1::delete_n_ids --args 1024
//# run Test::M1::delete_n_ids --args 2048

// run above run count limit should fail
//# run Test::M1::delete_n_ids --args 1025
//# run Test::M1::delete_n_ids --args 2049

// run above run count limit should fail
//# run Test::M1::delete_n_ids --args 2048
//# run Test::M1::delete_n_ids --args 4096
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ written: object(106)

task 5 'run'. lines 44-46:
Error: Transaction Effects Status: Move Primitive Runtime Error. Location: sui::tx_context::derive_id (function index 0) at offset 0. Arithmetic error, stack overflow, max value depth, etc.
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 1024 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 2048 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }

task 6 'run'. lines 47-47:
Error: Transaction Effects Status: Move Primitive Runtime Error. Location: sui::tx_context::derive_id (function index 0) at offset 0. Arithmetic error, stack overflow, max value depth, etc.
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 1024 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: MovePrimitiveRuntimeError(Some(MoveLocation { module: ModuleId { address: sui, name: Identifier("tx_context") }, function: 0, instruction: 0, function_name: Some("derive_id") })), source: Some(VMError { major_status: MEMORY_LIMIT_EXCEEDED, sub_status: Some(2), message: Some("Creating more than 2048 IDs is not allowed"), exec_state: None, location: Module(ModuleId { address: sui, name: Identifier("tx_context") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 0)] }) } }
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ module Test::M1 {
//# run Test::M1::create_n_ids --args 256

// create at create count limit should succeed
//# run Test::M1::create_n_ids --args 1024
//# run Test::M1::create_n_ids --args 2048

// create above create count limit should fail
//# run Test::M1::create_n_ids --args 1025
//# run Test::M1::create_n_ids --args 2049

// create above create count limit should fail
//# run Test::M1::create_n_ids --args 2048
//# run Test::M1::create_n_ids --args 4096

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ module Test::M1 {
//# run Test::M1::transfer_n_ids --args 256

// run at run count limit should succeed
//# run Test::M1::transfer_n_ids --args 1024
//# run Test::M1::transfer_n_ids --args 2048

// run above run count limit should fail
//# run Test::M1::transfer_n_ids --args 1025
//# run Test::M1::transfer_n_ids --args 2049

// run above run count limit should fail
//# run Test::M1::transfer_n_ids --args 2048
//# run Test::M1::transfer_n_ids --args 4096

13 changes: 9 additions & 4 deletions crates/sui-adapter/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,14 @@ pub fn new_session<
vm: &'v MoveVM,
state_view: &'r S,
input_objects: BTreeMap<ObjectID, (/* by_value */ bool, Owner)>,
is_metered: bool,
) -> Session<'r, 'v, S> {
let mut extensions = NativeContextExtensions::default();
extensions.add(ObjectRuntime::new(Box::new(state_view), input_objects));
extensions.add(ObjectRuntime::new(
Box::new(state_view),
input_objects,
is_metered,
));
vm.new_session_with_extensions(state_view, extensions)
}

Expand Down Expand Up @@ -208,7 +213,7 @@ fn execute_internal<
.iter()
.map(|(id, (owner, _))| (*id, (by_value_objects.contains(id), *owner)))
.collect();
let mut session = new_session(vm, state_view, input_objects);
let mut session = new_session(vm, state_view, input_objects, gas_status.is_metered());
// check type arguments separately for error conversion
for (idx, ty) in type_args.iter().enumerate() {
session
Expand Down Expand Up @@ -287,7 +292,7 @@ fn execute_internal<
user_events,
loaded_child_objects,
} = object_runtime.finish()?;
let session = new_session(vm, &*state_view, BTreeMap::new());
let session = new_session(vm, &*state_view, BTreeMap::new(), gas_status.is_metered());
let writes = writes
.into_iter()
.map(|(id, (write_kind, owner, ty, tag, value))| {
Expand Down Expand Up @@ -481,7 +486,7 @@ pub fn verify_and_link<
// verifier may assume well-formedness conditions enforced by the Move verifier hold
let vm = MoveVM::new(natives)
.expect("VM creation only fails if natives are invalid, and we created the natives");
let mut session = new_session(&vm, state_view, BTreeMap::new());
let mut session = new_session(&vm, state_view, BTreeMap::new(), gas_status.is_metered());
// TODO(https://github.com/MystenLabs/sui/issues/69): avoid this redundant serialization by exposing VM API that allows us to run the linker directly on `Vec<CompiledModule>`
let new_module_bytes: Vec<_> = modules
.iter()
Expand Down
4 changes: 4 additions & 0 deletions crates/sui-cost-tables/src/bytecode_tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ impl<'a> GasStatus<'a> {
}
}

pub fn is_metered(&self) -> bool {
self.charge
}

/// Initialize the gas state with metering disabled.
///
/// It should be used by clients in very specific cases and when executing system
Expand Down
6 changes: 5 additions & 1 deletion crates/sui-framework/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ fn new_testing_object_runtime(ext: &mut NativeContextExtensions) {
InputObjects::new(vec![]),
TransactionDigest::random(),
);
ext.add(ObjectRuntime::new(Box::new(state_view), BTreeMap::new()))
ext.add(ObjectRuntime::new(
Box::new(state_view),
BTreeMap::new(),
false,
))
}

pub fn get_sui_framework() -> Vec<CompiledModule> {
Expand Down
15 changes: 11 additions & 4 deletions crates/sui-framework/src/natives/object_runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub struct ObjectRuntime<'a> {
pub(crate) test_inventories: TestInventories,
// the internal state
pub(crate) state: ObjectRuntimeState,
// whether or not this TX is gas metered
is_metered: bool,
}

pub enum TransferResult {
Expand All @@ -102,6 +104,7 @@ impl<'a> ObjectRuntime<'a> {
pub fn new(
object_resolver: Box<dyn ChildObjectResolver + 'a>,
input_objects: BTreeMap<ObjectID, (/* by_value */ bool, Owner)>,
is_metered: bool,
) -> Self {
Self {
object_store: ObjectStore::new(object_resolver),
Expand All @@ -113,11 +116,13 @@ impl<'a> ObjectRuntime<'a> {
transfers: LinkedHashMap::new(),
events: vec![],
},
is_metered,
}
}

pub fn new_id(&mut self, id: ObjectID) -> PartialVMResult<()> {
if self.state.new_ids.len() == MAX_NUM_NEW_MOVE_OBJECT_IDS {
// Metered transactions don't have limits for now
if self.is_metered && (self.state.new_ids.len() == MAX_NUM_NEW_MOVE_OBJECT_IDS) {
return Err(PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED)
.with_message(format!(
"Creating more than {MAX_NUM_NEW_MOVE_OBJECT_IDS} IDs is not allowed"
Expand All @@ -138,7 +143,8 @@ impl<'a> ObjectRuntime<'a> {
pub fn delete_id(&mut self, id: ObjectID) -> PartialVMResult<()> {
// This is defensive because `self.state.deleted_ids` may not indeed
// be called based on the `was_new` flag
if self.state.deleted_ids.len() == MAX_NUM_DELETED_MOVE_OBJECT_IDS {
// Metered transactions don't have limits for now
if self.is_metered && (self.state.deleted_ids.len() == MAX_NUM_DELETED_MOVE_OBJECT_IDS) {
return Err(PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED)
.with_message(format!(
"Deleting more than {MAX_NUM_DELETED_MOVE_OBJECT_IDS} IDs is not allowed"
Expand Down Expand Up @@ -184,8 +190,9 @@ impl<'a> ObjectRuntime<'a> {
TransferResult::OwnerChanged
};

// Todo: System objects should not be subject to such limits?
if (self.state.transfers.len() == MAX_NUM_TRANSFERED_MOVE_OBJECT_IDS)
// Metered transactions don't have limits for now
if self.is_metered
&& (self.state.transfers.len() == MAX_NUM_TRANSFERED_MOVE_OBJECT_IDS)
&& (id != SUI_SYSTEM_STATE_OBJECT_ID)
{
return Err(PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED)
Expand Down
6 changes: 3 additions & 3 deletions crates/sui-protocol-constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ pub const MAX_DEPENDENCY_DEPTH: usize = 100;
pub const MAX_NUM_EVENT_EMIT: u64 = 256;

/// Maximum number of new IDs that a single transaction can create. Enforced by the VM during execution.
pub const MAX_NUM_NEW_MOVE_OBJECT_IDS: usize = 1024;
pub const MAX_NUM_NEW_MOVE_OBJECT_IDS: usize = 2048;

/// Maximum number of IDs that a single transaction can delete. Enforced by the VM during execution.
pub const MAX_NUM_DELETED_MOVE_OBJECT_IDS: usize = 1024;
pub const MAX_NUM_DELETED_MOVE_OBJECT_IDS: usize = 2048;

/// Maximum number of IDs that a single transaction can transfer. Enforced by the VM during execution.
pub const MAX_NUM_TRANSFERED_MOVE_OBJECT_IDS: usize = 1024;
pub const MAX_NUM_TRANSFERED_MOVE_OBJECT_IDS: usize = 2048;

// === Execution gas costs ====
// note: per-instruction and native function gas costs live in the sui-cost-tables crate
Expand Down

0 comments on commit 8cc013d

Please sign in to comment.