Skip to content

Commit

Permalink
[2/x][programmable transactions] Small changes to adapter and types (M…
Browse files Browse the repository at this point in the history
…ystenLabs#8356)

- Small changes needed for programmable transaction runtime
  • Loading branch information
tnowacki authored Feb 17, 2023
1 parent e009238 commit a6387e8
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 51 deletions.
6 changes: 3 additions & 3 deletions crates/sui-adapter/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub fn new_session<
>(
vm: &'v MoveVM,
state_view: &'r S,
input_objects: BTreeMap<ObjectID, (/* by_value */ bool, Owner)>,
input_objects: BTreeMap<ObjectID, Owner>,
is_metered: bool,
protocol_config: &ProtocolConfig,
) -> Session<'r, 'v, S> {
Expand Down Expand Up @@ -221,7 +221,7 @@ fn execute_internal<
) -> Result<Mode::ExecutionResult, ExecutionError> {
let input_objects = object_data
.iter()
.map(|(id, (owner, _))| (*id, (by_value_objects.contains(id), *owner)))
.map(|(id, (owner, _))| (*id, *owner))
.collect();
let mut session = new_session(
vm,
Expand Down Expand Up @@ -307,7 +307,7 @@ fn execute_internal<
deletions,
user_events,
loaded_child_objects,
} = object_runtime.finish()?;
} = object_runtime.finish(by_value_objects)?;
let session = new_session(
vm,
&*state_view,
Expand Down
4 changes: 2 additions & 2 deletions crates/sui-adapter/src/execution_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ fn pay_sui<S>(
let (total_coins, total_amount) = check_total_coins(&coins, &amounts)?;

let mut merged_coin = coins.swap_remove(0);
merged_coin.merge_coins(&mut coins);
merged_coin.merge_coins(&mut coins)?;

let ctx = SingleTxContext::pay_sui(tx_ctx.sender());

Expand Down Expand Up @@ -700,7 +700,7 @@ fn pay_all_sui<S>(
let total_coins = coins.iter().fold(0, |acc, c| acc + c.value());

let mut merged_coin = coins.swap_remove(0);
merged_coin.merge_coins(&mut coins);
merged_coin.merge_coins(&mut coins)?;
let ctx = SingleTxContext::pay_all_sui(sender);
update_input_coins(
&ctx,
Expand Down
14 changes: 10 additions & 4 deletions crates/sui-adapter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

macro_rules! invariant_violation {
($msg:expr) => {{
return Err(sui_types::error::ExecutionError::new_with_source(
sui_types::error::ExecutionErrorKind::InvariantViolation,
$msg,
));
}};
}

macro_rules! assert_invariant {
($cond:expr, $msg:expr) => {
if !$cond {
return Err(sui_types::error::ExecutionError::new_with_source(
sui_types::error::ExecutionErrorKind::InvariantViolation,
$msg,
));
invariant_violation!($msg)
}
};
}
Expand Down
36 changes: 19 additions & 17 deletions crates/sui-core/tests/staged/sui.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,68 +181,70 @@ ExecutionFailureStatus:
15:
CoinTypeMismatch: UNIT
16:
NonEntryFunctionInvoked: UNIT
CoinTooLarge: UNIT
17:
EntryTypeArityMismatch: UNIT
NonEntryFunctionInvoked: UNIT
18:
EntryTypeArityMismatch: UNIT
19:
EntryArgumentError:
NEWTYPE:
TYPENAME: EntryArgumentError
19:
20:
EntryTypeArgumentError:
NEWTYPE:
TYPENAME: EntryTypeArgumentError
20:
21:
CircularObjectOwnership:
NEWTYPE:
TYPENAME: CircularObjectOwnership
21:
22:
InvalidChildObjectArgument:
NEWTYPE:
TYPENAME: InvalidChildObjectArgument
22:
23:
InvalidSharedByValue:
NEWTYPE:
TYPENAME: InvalidSharedByValue
23:
24:
TooManyChildObjects:
STRUCT:
- object:
TYPENAME: ObjectID
24:
25:
InvalidParentDeletion:
STRUCT:
- parent:
TYPENAME: ObjectID
- kind:
OPTION:
TYPENAME: DeleteKind
25:
26:
InvalidParentFreezing:
STRUCT:
- parent:
TYPENAME: ObjectID
26:
PublishErrorEmptyPackage: UNIT
27:
PublishErrorNonZeroAddress: UNIT
PublishErrorEmptyPackage: UNIT
28:
PublishErrorDuplicateModule: UNIT
PublishErrorNonZeroAddress: UNIT
29:
SuiMoveVerificationError: UNIT
PublishErrorDuplicateModule: UNIT
30:
SuiMoveVerificationError: UNIT
31:
MovePrimitiveRuntimeError:
NEWTYPE:
OPTION:
TYPENAME: MoveLocation
31:
32:
MoveAbort:
TUPLE:
- TYPENAME: MoveLocation
- U64
32:
VMVerificationOrDeserializationError: UNIT
33:
VMVerificationOrDeserializationError: UNIT
34:
VMInvariantViolation: UNIT
ExecutionStatus:
ENUM:
Expand Down
23 changes: 12 additions & 11 deletions crates/sui-framework/src/natives/object_runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub struct RuntimeResults {

#[derive(Default)]
pub(crate) struct ObjectRuntimeState {
pub(crate) input_objects: BTreeMap<ObjectID, (/* by_value */ bool, Owner)>,
pub(crate) input_objects: BTreeMap<ObjectID, Owner>,
// new ids from object::new
new_ids: Set<ObjectID>,
// ids passed to object::delete
Expand Down Expand Up @@ -122,7 +122,7 @@ impl TestInventories {
impl<'a> ObjectRuntime<'a> {
pub fn new(
object_resolver: Box<dyn ChildObjectResolver + 'a>,
input_objects: BTreeMap<ObjectID, (/* by_value */ bool, Owner)>,
input_objects: BTreeMap<ObjectID, Owner>,
is_metered: bool,
protocol_config: &ProtocolConfig,
) -> Self {
Expand Down Expand Up @@ -206,7 +206,7 @@ impl<'a> ObjectRuntime<'a> {
let is_framework_obj = [SUI_SYSTEM_STATE_OBJECT_ID, SUI_CLOCK_OBJECT_ID].contains(&id);
let transfer_result = if self.state.new_ids.contains_key(&id) || is_framework_obj {
TransferResult::New
} else if let Some((_, prev_owner)) = self.state.input_objects.get(&id) {
} else if let Some(prev_owner) = self.state.input_objects.get(&id) {
match (&owner, prev_owner) {
// don't use == for dummy values in Shared owner
(Owner::Shared { .. }, Owner::Shared { .. }) => TransferResult::SameOwner,
Expand Down Expand Up @@ -306,9 +306,12 @@ impl<'a> ObjectRuntime<'a> {
std::mem::take(&mut self.state)
}

pub fn finish(mut self) -> Result<RuntimeResults, ExecutionError> {
pub fn finish(
mut self,
by_value_inputs: BTreeSet<ObjectID>,
) -> Result<RuntimeResults, ExecutionError> {
let child_effects = self.object_store.take_effects();
self.state.finish(child_effects)
self.state.finish(by_value_inputs, child_effects)
}

pub(crate) fn all_active_child_objects(
Expand All @@ -329,6 +332,7 @@ impl ObjectRuntimeState {
/// - Passes through user events
pub(crate) fn finish(
mut self,
by_value_inputs: BTreeSet<ObjectID>,
child_object_effects: BTreeMap<ObjectID, ChildObjectEffect>,
) -> Result<RuntimeResults, ExecutionError> {
let mut wrapped_children = BTreeSet::new();
Expand Down Expand Up @@ -388,7 +392,7 @@ impl ObjectRuntimeState {
} = self;
let input_owner_map = input_objects
.iter()
.filter_map(|(id, (_by_value, owner))| match owner {
.filter_map(|(id, owner)| match owner {
Owner::AddressOwner(_) | Owner::Shared { .. } | Owner::Immutable => None,
Owner::ObjectOwner(parent) => Some((*id, (*parent).into())),
})
Expand Down Expand Up @@ -433,12 +437,9 @@ impl ObjectRuntimeState {
})
.collect();
// remaining by value objects must be wrapped
let remaining_by_value_objects = input_objects
let remaining_by_value_objects = by_value_inputs
.into_iter()
.filter(|(id, (by_value, _))| {
*by_value && !writes.contains_key(id) && !deletions.contains_key(id)
})
.map(|(id, _)| id)
.filter(|id| !writes.contains_key(id) && !deletions.contains_key(id))
.collect::<Vec<_>>();
for id in remaining_by_value_objects {
deletions.insert(id, DeleteKind::Wrap);
Expand Down
11 changes: 4 additions & 7 deletions crates/sui-framework/src/natives/test_scenario.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub fn end_transaction(
let object_runtime_state = object_runtime_ref.take_state();
// Determine writes and deletes
// We pass an empty map as we do not expose dynamic field objects in the system
let results = object_runtime_state.finish(BTreeMap::new());
let results = object_runtime_state.finish(BTreeSet::new(), BTreeMap::new());
let RuntimeResults {
writes,
deletions,
Expand Down Expand Up @@ -205,9 +205,7 @@ pub fn end_transaction(
.test_inventories
.taken
.iter()
.map(|(id, owner)| {
(*id, (/* by_value */ false, *owner))
})
.map(|(id, owner)| (*id, *owner))
.collect::<BTreeMap<_, _>>();
// update inventories
// check for bad updates to immutable values
Expand Down Expand Up @@ -517,7 +515,7 @@ fn take_from_inventory(
is_in_inventory: impl FnOnce(&ObjectID) -> bool,
objects: &BTreeMap<ObjectID, Value>,
taken: &mut BTreeMap<ObjectID, Owner>,
input_objects: &mut BTreeMap<ObjectID, (/* by_value */ bool, Owner)>,
input_objects: &mut BTreeMap<ObjectID, Owner>,
id: ObjectID,
owner: Owner,
) -> Result<Value, NativeResult> {
Expand All @@ -530,8 +528,7 @@ fn take_from_inventory(
));
}
taken.insert(id, owner);
// by_value will be set to true later, if wrapped
input_objects.insert(id, (false, owner));
input_objects.insert(id, owner);
let obj = obj_opt.unwrap();
Ok(obj.copy_value().unwrap())
}
Expand Down
20 changes: 17 additions & 3 deletions crates/sui-types/src/coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,27 @@ impl Coin {
// Shift balance of coins_to_merge to this coin.
// Related coin objects need to be updated in temporary_store to persist the changes,
// including deleting the coin objects that have been merged.
pub fn merge_coins(&mut self, coins_to_merge: &mut [Coin]) {
let total_coins = coins_to_merge.iter().fold(0, |acc, c| acc + c.value());
pub fn merge_coins(&mut self, coins_to_merge: &mut [Coin]) -> Result<(), ExecutionError> {
let Some(total_coins) =
coins_to_merge.iter().fold(Some(0u64), |acc, c| acc?.checked_add(c.value())) else {
return Err(ExecutionError::new_with_source(
ExecutionErrorKind::CoinTooLarge,
format!("Coin {} exceeds maximum value", self.id())
))
};

for coin in coins_to_merge.iter_mut() {
// unwrap() is safe because balance value is the same as coin value
coin.balance.withdraw(coin.value()).unwrap();
}
self.balance = Balance::new(self.value() + total_coins);
let Some(new_balance) = self.value().checked_add(total_coins) else {
return Err(ExecutionError::new_with_source(
ExecutionErrorKind::CoinTooLarge,
format!("Coin {} exceeds maximum value", self.id())
))
};
self.balance = Balance::new(new_balance);
Ok(())
}

// Split amount out of this coin to a new coin.
Expand Down
7 changes: 7 additions & 0 deletions crates/sui-types/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,7 @@ pub enum ExecutionFailureStatus {
/// In pay transaction, it means the input coins' types are not the same;
/// In PaySui/PayAllSui, it means some input coins are not SUI coins.
CoinTypeMismatch,
CoinTooLarge,

//
// MoveCall errors
Expand Down Expand Up @@ -2045,6 +2046,12 @@ impl Display for ExecutionFailureStatus {
"Coin type check failed in pay/pay_sui/pay_all_sui transaction"
)
}
ExecutionFailureStatus::CoinTooLarge => {
write!(
f,
"Coin exceeds maximum value for a single coin"
)
}
ExecutionFailureStatus::EmptyInputCoins => {
write!(f, "Expected a non-empty list of input Coin objects")
}
Expand Down
7 changes: 6 additions & 1 deletion crates/sui-types/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use serde_with::Bytes;

use crate::base_types::ObjectIDParseError;
use crate::crypto::{deterministic_random_account_key, sha3_hash};
use crate::error::{ExecutionError, ExecutionErrorKind};
use crate::error::{SuiError, SuiResult};
Expand Down Expand Up @@ -149,8 +150,12 @@ impl MoveObject {
self.has_public_transfer
}
pub fn id(&self) -> ObjectID {
Self::id_opt(&self.contents).unwrap()
}

pub fn id_opt(contents: &[u8]) -> Result<ObjectID, ObjectIDParseError> {
// TODO: Ensure safe index to to parse ObjectID. https://github.com/MystenLabs/sui/issues/6278
ObjectID::try_from(&self.contents[0..ID_END_INDEX]).unwrap()
ObjectID::try_from(&contents[0..ID_END_INDEX])
}

pub fn version(&self) -> SequenceNumber {
Expand Down
13 changes: 10 additions & 3 deletions crates/sui-types/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,10 @@ pub struct SingleTxContext {
}

impl SingleTxContext {
// legacy
pub fn transfer_sui(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("transfer_sui"), sender)
}
pub fn transfer_object(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("transfer_object"), sender)
}
pub fn pay(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("pay"), sender)
}
Expand All @@ -74,12 +72,21 @@ impl SingleTxContext {
pub fn pay_all_sui(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("pay_all_sui"), sender)
}
// programmable transactions
pub fn split_coin(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("split_coin"), sender)
}
// common to legacy and programmable transactions
pub fn transfer_object(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("transfer_object"), sender)
}
pub fn unused_input(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("unused_input_object"), sender)
}
pub fn publish(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("publish"), sender)
}
// system
pub fn gas(sender: SuiAddress) -> Self {
Self::sui_transaction(ident_str!("gas"), sender)
}
Expand Down

0 comments on commit a6387e8

Please sign in to comment.