Skip to content

Commit

Permalink
[adapter][verifier] allow option and ID arguments in entry points (My…
Browse files Browse the repository at this point in the history
  • Loading branch information
tnowacki authored May 24, 2022
1 parent 57793fa commit 5c16252
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 47 deletions.
76 changes: 51 additions & 25 deletions crates/sui-adapter/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ use sui_types::{
object::{self, Data, MoveObject, Object, Owner},
storage::{DeleteKind, Storage},
};
use sui_verifier::{entry_points_verifier::INIT_FN_NAME, verifier};
use sui_verifier::{
entry_points_verifier::{INIT_FN_NAME, RESOLVED_STD_OPTION, RESOLVED_SUI_ID},
verifier,
};

use move_core_types::{
account_address::AccountAddress,
Expand Down Expand Up @@ -692,15 +695,15 @@ pub fn resolve_and_type_check(
// Track the mapping from each input object to its Move type.
// This will be needed latter in `check_child_object_of_shared_object`.
let mut object_type_map = BTreeMap::new();

let view = &BinaryIndexedView::Module(module);
let bcs_args = args
.into_iter()
.enumerate()
.map(|(idx, arg)| {
let param_type = &parameters[idx];
let object_kind = match arg {
CallArg::Pure(arg) => {
if !is_primitive(module, type_args, param_type) {
if !is_primitive(view, type_args, param_type) {
return Err(SuiError::TypeError {
error: format!(
"Non-primitive argument at index {}. If it is an object, it must \
Expand Down Expand Up @@ -799,7 +802,7 @@ pub fn resolve_and_type_check(
})
}
};
type_check_struct(module, type_args, &move_object.type_, inner_param_type)?;
type_check_struct(view, type_args, &move_object.type_, inner_param_type)?;
object_type_map.insert(id, move_object.type_.module_id());
Ok(object_arg)
})
Expand Down Expand Up @@ -891,7 +894,7 @@ fn check_child_object_of_shared_object(
}

fn is_primitive(
_module: &CompiledModule,
view: &BinaryIndexedView,
function_type_arguments: &[TypeTag],
t: &SignatureToken,
) -> bool {
Expand All @@ -902,16 +905,27 @@ fn is_primitive(
| SignatureToken::U128
| SignatureToken::Address => true,

SignatureToken::Vector(inner) => is_primitive(_module, function_type_arguments, inner),
SignatureToken::Struct(idx) => {
let resolved_struct = sui_verifier::resolve_struct(view, *idx);
// is ID
resolved_struct == RESOLVED_SUI_ID
}

SignatureToken::StructInstantiation(idx, targs) => {
let resolved_struct = sui_verifier::resolve_struct(view, *idx);
// is option of a primitive
resolved_struct == RESOLVED_STD_OPTION
&& targs.len() == 1
&& is_primitive(view, function_type_arguments, &targs[0])
}
SignatureToken::Vector(inner) => is_primitive(view, function_type_arguments, inner),

SignatureToken::TypeParameter(idx) => function_type_arguments
.get(*idx as usize)
.map(is_primitive_type_tag)
.unwrap_or(false),

SignatureToken::Signer
| SignatureToken::Struct(_)
| SignatureToken::StructInstantiation(_, _)
| SignatureToken::Reference(_)
| SignatureToken::MutableReference(_) => false,
}
Expand All @@ -921,24 +935,37 @@ fn is_primitive_type_tag(t: &TypeTag) -> bool {
match t {
TypeTag::Bool | TypeTag::U8 | TypeTag::U64 | TypeTag::U128 | TypeTag::Address => true,
TypeTag::Vector(inner) => is_primitive_type_tag(inner),
TypeTag::Signer | TypeTag::Struct(_) => false,
TypeTag::Struct(StructTag {
address,
module,
name,
type_params: type_args,
}) => {
let resolved_struct = (address, module.as_ident_str(), name.as_ident_str());
// is id or..
if resolved_struct == RESOLVED_SUI_ID {
return true;
}
// is option of a primitive
resolved_struct == RESOLVED_STD_OPTION
&& type_args.len() == 1
&& is_primitive_type_tag(&type_args[0])
}
TypeTag::Signer => false,
}
}

fn type_check_struct(
module: &CompiledModule,
view: &BinaryIndexedView,
function_type_arguments: &[TypeTag],
arg_type: &StructTag,
param_type: &SignatureToken,
) -> Result<(), SuiError> {
if !struct_tag_equals_sig_token(module, function_type_arguments, arg_type, param_type) {
if !struct_tag_equals_sig_token(view, function_type_arguments, arg_type, param_type) {
Err(SuiError::TypeError {
error: format!(
"Expected argument of type {}, but found type {}",
sui_verifier::format_signature_token(
&BinaryIndexedView::Module(module),
param_type
),
sui_verifier::format_signature_token(view, param_type),
arg_type
),
})
Expand All @@ -948,7 +975,7 @@ fn type_check_struct(
}

fn type_tag_equals_sig_token(
module: &CompiledModule,
view: &BinaryIndexedView,
function_type_arguments: &[TypeTag],
arg_type: &TypeTag,
param_type: &SignatureToken,
Expand All @@ -963,7 +990,7 @@ fn type_tag_equals_sig_token(

(TypeTag::Vector(inner_arg_type), SignatureToken::Vector(inner_param_type)) => {
type_tag_equals_sig_token(
module,
view,
function_type_arguments,
inner_arg_type,
inner_param_type,
Expand All @@ -972,7 +999,7 @@ fn type_tag_equals_sig_token(

(TypeTag::Struct(arg_struct), SignatureToken::Struct(_))
| (TypeTag::Struct(arg_struct), SignatureToken::StructInstantiation(_, _)) => {
struct_tag_equals_sig_token(module, function_type_arguments, arg_struct, param_type)
struct_tag_equals_sig_token(view, function_type_arguments, arg_struct, param_type)
}

(_, SignatureToken::TypeParameter(idx)) => {
Expand All @@ -983,17 +1010,17 @@ fn type_tag_equals_sig_token(
}

fn struct_tag_equals_sig_token(
module: &CompiledModule,
view: &BinaryIndexedView,
function_type_arguments: &[TypeTag],
arg_type: &StructTag,
param_type: &SignatureToken,
) -> bool {
match param_type {
SignatureToken::Struct(idx) => {
struct_tag_equals_struct_inst(module, function_type_arguments, arg_type, *idx, &[])
struct_tag_equals_struct_inst(view, function_type_arguments, arg_type, *idx, &[])
}
SignatureToken::StructInstantiation(idx, args) => {
struct_tag_equals_struct_inst(module, function_type_arguments, arg_type, *idx, args)
struct_tag_equals_struct_inst(view, function_type_arguments, arg_type, *idx, args)
}
SignatureToken::TypeParameter(idx) => match &function_type_arguments[*idx as usize] {
TypeTag::Struct(s) => arg_type == s,
Expand All @@ -1004,14 +1031,13 @@ fn struct_tag_equals_sig_token(
}

fn struct_tag_equals_struct_inst(
module: &CompiledModule,
view: &BinaryIndexedView,
function_type_arguments: &[TypeTag],
arg_type: &StructTag,
param_type: StructHandleIndex,
param_type_arguments: &[SignatureToken],
) -> bool {
let view = BinaryIndexedView::Module(module);
let (address, module_name, struct_name) = sui_verifier::resolve_struct(&view, param_type);
let (address, module_name, struct_name) = sui_verifier::resolve_struct(view, param_type);

// same address, module, name, and type parameters
&arg_type.address == address
Expand All @@ -1021,7 +1047,7 @@ fn struct_tag_equals_struct_inst(
&& arg_type.type_params.iter().zip(param_type_arguments).all(
|(arg_type_arg, param_type_arg)| {
type_tag_equals_sig_token(
module,
view,
function_type_arguments,
arg_type_arg,
param_type_arg,
Expand Down
3 changes: 3 additions & 0 deletions crates/sui-types/src/base_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ pub struct TransactionEffectsDigest(
pub [u8; TRANSACTION_DIGEST_LENGTH],
);

pub const STD_OPTION_MODULE_NAME: &IdentStr = ident_str!("Option");
pub const STD_OPTION_STRUCT_NAME: &IdentStr = STD_OPTION_MODULE_NAME;

pub const TX_CONTEXT_MODULE_NAME: &IdentStr = ident_str!("TxContext");
pub const TX_CONTEXT_STRUCT_NAME: &IdentStr = TX_CONTEXT_MODULE_NAME;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
processed 2 tasks

task 0 'publish'. lines 6-16:
Error: Failed to verify the Move module, reason: "Invalid entry point parameter type. Expected primitive or object type. Got: Std::Option::Option<T0>".

task 1 'publish'. lines 18-28:
Error: Failed to verify the Move module, reason: "Invalid entry point parameter type. Expected primitive or object type. Got: vector<Std::Option::Option<T0>>".
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// invalid, type parameters with key are not valid when nested as no primitive has key

//# publish
module 0x0.M {
import 0x2.TxContext;
import 0x1.Option;

public(script) no<T:key>(l0: Option.Option<T>, ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}

}

//# publish
module 0x0.M {
import 0x2.TxContext;
import 0x1.Option;

public(script) no<T:key>(l0: vector<Option.Option<T>>, ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
processed 1 task

task 0 'publish'. lines 6-16:
created: object(103)
written: object(102)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// valid, type parameters with key are valid as long as they are not nested

//# publish
module 0x0.M {
import 0x2.TxContext;
import 0x1.Option;

public(script) yes<T:key>(l0: T, l1: &T, l2: &mut T, ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
processed 1 task

task 0 'publish'. lines 6-21:
created: object(103)
written: object(102)
21 changes: 21 additions & 0 deletions crates/sui-verifier-transactional-tests/tests/entry_points/id.mvir
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// valid, ID is allowed

//# publish
module 0x0.M {
import 0x2.TxContext;
import 0x2.ID;

public(script) yes<T>(
l0: ID.ID,
l1: vector<ID.ID>,
l2: vector<vector<ID.ID>>,
ctx: &mut TxContext.TxContext,
) {
label l0:
abort 0;
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
processed 1 task

task 0 'publish'. lines 6-16:
Error: Failed to verify the Move module, reason: "Invalid entry point parameter type. Expected primitive or object type. Got: Std::Option::Option<u64>".
task 0 'publish'. lines 6-23:
created: object(103)
written: object(102)
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// invalid, non key structs are not supported
// valid, option of primitives is allowed

//# publish
module 0x0.M {
import 0x2.TxContext;
import 0x1.Option;

public(script) no(s: Option.Option<u64>, ctx: &mut TxContext.TxContext) {
public(script) yes<T>(
l0: Option.Option<u64>,
l1: Option.Option<Option.Option<u64>>,
l2: Option.Option<vector<u64>>,
l3: vector<Option.Option<u64>>,
l4: Option.Option<Option.Option<T>>,
ctx: &mut TxContext.TxContext
) {
label l0:
abort 0;
}
Expand Down
Loading

0 comments on commit 5c16252

Please sign in to comment.