Skip to content

Commit f6fc603

Browse files
committed
feat: improved MoveAuthenticator::validity_check implementation
1 parent 0fd4369 commit f6fc603

File tree

3 files changed

+64
-27
lines changed

3 files changed

+64
-27
lines changed

crates/iota-types/src/move_authenticator.rs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use std::{
88

99
use fastcrypto::{error::FastCryptoError, traits::ToFromBytes};
1010
use iota_protocol_config::ProtocolConfig;
11-
use move_core_types::language_storage::TypeTag;
1211
use once_cell::sync::OnceCell;
1312
use schemars::JsonSchema;
1413
use serde::{Deserialize, Serialize};
@@ -23,6 +22,7 @@ use crate::{
2322
signature::{AuthenticatorTrait, VerifyParams},
2423
signature_verification::VerifiedDigestCache,
2524
transaction::{CallArg, InputObjectKind, ObjectArg, SharedInputObject},
25+
type_input::TypeInput,
2626
};
2727

2828
/// MoveAuthenticator is a GenericSignature variant that enables a new
@@ -35,7 +35,7 @@ pub struct MoveAuthenticator {
3535
call_args: Vec<CallArg>,
3636
/// Type arguments for the Move authenticate function
3737
#[schemars(with = "String")]
38-
type_arguments: Vec<TypeTag>, // TypeInput???
38+
type_arguments: Vec<TypeInput>,
3939
/// The object that is authenticated. Represents the account being the
4040
/// sender of the transaction.
4141
object_to_authenticate: CallArg,
@@ -56,7 +56,7 @@ impl Hash for MoveAuthenticator {
5656
impl MoveAuthenticator {
5757
pub fn new_for_testing(
5858
call_args: Vec<CallArg>,
59-
type_arguments: Vec<TypeTag>,
59+
type_arguments: Vec<TypeInput>,
6060
object_to_authenticate: CallArg,
6161
) -> Self {
6262
Self {
@@ -80,7 +80,7 @@ impl MoveAuthenticator {
8080
&self.call_args
8181
}
8282

83-
pub fn type_arguments(&self) -> &Vec<TypeTag> {
83+
pub fn type_arguments(&self) -> &Vec<TypeInput> {
8484
&self.type_arguments
8585
}
8686

@@ -142,30 +142,51 @@ impl MoveAuthenticator {
142142
.collect()
143143
}
144144

145-
/// Validity check for the MoveAuthenticator.
145+
/// Validity check for MoveAuthenticator.
146146
pub fn validity_check(&self, config: &ProtocolConfig) -> UserInputResult {
147147
// Check that the object to authenticate is valid.
148148
self.object_to_authenticate_components()?;
149149

150150
// Inputs validity check.
151-
151+
//
152152
// `validity_check` is not called for `object_to_authenticate` because it is
153153
// already validated with a dedicated function.
154154

155+
// `ProtocolConfig::max_arguments` is used to check the call arguments because
156+
// MoveAuthenticator is considered as a simple programmable Move call.
157+
fp_ensure!(
158+
self.call_args().len() < (config.max_arguments() as usize),
159+
UserInputError::SizeLimitExceeded {
160+
limit: "maximum arguments in MoveAuthenticator".to_string(),
161+
value: config.max_arguments().to_string()
162+
}
163+
);
164+
165+
// TODO: should we handle duplicate inputs somehow?
166+
155167
self.call_args()
156168
.iter()
157169
.try_for_each(|obj| obj.validity_check(config))?;
158170

159-
if self.receiving_objects().len() > 0 {
160-
return Err(UserInputError::Unsupported(
171+
fp_ensure!(
172+
self.receiving_objects().is_empty(),
173+
UserInputError::Unsupported(
161174
"MoveAuthenticator cannot have receiving objects as input".to_string(),
162175
)
163-
.into());
164-
}
176+
);
165177

166-
// TODO: check max arguments amount.
167-
// TODO: should we handle duplicate inputs somehow?
168-
// TODO: TypeTag -> TypeInput and validate.
178+
// Type arguments validity check.
179+
//
180+
// Each type argument is checked for validity in the same way as it is done for
181+
// `ProgrammableMoveCall`.
182+
let mut type_arguments_count = 0;
183+
self.type_arguments().iter().try_for_each(|type_arg| {
184+
crate::transaction::type_input_validity_check(
185+
type_arg,
186+
config,
187+
&mut type_arguments_count,
188+
)
189+
})?;
169190

170191
Ok(())
171192
}

crates/iota-types/src/transaction.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ pub enum ObjectArg {
123123
Receiving(ObjectRef),
124124
}
125125

126-
fn type_input_validity_check(
126+
pub fn type_input_validity_check(
127127
tag: &TypeInput,
128128
config: &ProtocolConfig,
129129
starting_count: &mut usize,
@@ -2638,32 +2638,35 @@ impl SenderSignedData {
26382638
// Additional checks when `MoveAuthenticators` are present.
26392639
let authenticators_num = self.move_authenticators().len();
26402640
if authenticators_num > 0 {
2641-
if !tx_data.kind().is_programmable_transaction() {
2642-
return Err(UserInputError::Unsupported(
2641+
fp_ensure!(
2642+
tx_data.kind().is_programmable_transaction(),
2643+
UserInputError::Unsupported(
26432644
"SenderSignedData with MoveAuthenticator must be a programmable transaction"
26442645
.to_string(),
26452646
)
2646-
.into());
2647-
}
2647+
.into()
2648+
);
26482649

26492650
// TODO(https://github.com/iotaledger/iota/issues/8966): The following
26502651
// restrictions are temporary added until we implement `MoveAuthenticator`
26512652
// support for sponsors.
26522653

2653-
if authenticators_num > 1 {
2654-
return Err(UserInputError::Unsupported(
2654+
fp_ensure!(
2655+
authenticators_num == 1,
2656+
UserInputError::Unsupported(
26552657
"SenderSignedData with more than one MoveAuthenticator is not supported"
26562658
.to_string(),
26572659
)
2658-
.into());
2659-
}
2660+
.into()
2661+
);
26602662

2661-
if self.sender_move_authenticator().is_none() {
2662-
return Err(UserInputError::Unsupported(
2663+
fp_ensure!(
2664+
self.sender_move_authenticator().is_some(),
2665+
UserInputError::Unsupported(
26632666
"SenderSignedData can have MoveAuthenticator only for the sender".to_string(),
26642667
)
2665-
.into());
2666-
}
2668+
.into()
2669+
);
26672670
}
26682671

26692672
Ok(())

iota-execution/latest/iota-adapter/src/execution_engine.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1890,13 +1890,26 @@ mod checked {
18901890
let mut args = vec![authenticator.object_to_authenticate().to_owned()];
18911891
args.extend(authenticator.call_args().to_owned());
18921892

1893+
let type_arguments = authenticator
1894+
.type_arguments()
1895+
.iter()
1896+
.map(|t| {
1897+
t.as_type_tag().map_err(|err| {
1898+
ExecutionError::new_with_source(
1899+
ExecutionErrorKind::VMInvariantViolation,
1900+
err.to_string(),
1901+
)
1902+
})
1903+
})
1904+
.collect::<Result<Vec<_>, _>>()?;
1905+
18931906
let res = builder.move_call(
18941907
authenticator_info.package,
18951908
Identifier::new(authenticator_info.module.clone())
18961909
.expect("`AuthenticatorInfoV1::module` is expected to be a valid `Identifier`"),
18971910
Identifier::new(authenticator_info.function.clone())
18981911
.expect("`AuthenticatorInfoV1::function` is expected to be a valid `Identifier`"),
1899-
authenticator.type_arguments().to_owned(),
1912+
type_arguments,
19001913
args,
19011914
);
19021915

0 commit comments

Comments
 (0)