1use move_core_types::language_storage::StructTag;
5use move_core_types::{account_address::AccountAddress, identifier::Identifier};
6use proptest::arbitrary::*;
7use proptest::prelude::*;
8
9use sui_core::authority::authority_test_utils::submit_and_execute;
10use sui_types::base_types::ObjectID;
11use sui_types::effects::{TransactionEffects, TransactionEffectsAPI};
12use sui_types::error::SuiError;
13use sui_types::programmable_transaction_builder::ProgrammableTransactionBuilder;
14use sui_types::transaction::{ProgrammableTransaction, TransactionData, TransactionKind};
15use sui_types::utils::to_sender_signed_transaction;
16use sui_types::{SUI_FRAMEWORK_PACKAGE_ID, TypeTag};
17
18use crate::account_universe::AccountCurrent;
19use crate::executor::{Executor, assert_is_acceptable_result};
20
21const GAS_PRICE: u64 = 700;
22const GAS: u64 = 1_000_000 * GAS_PRICE;
23
24pub fn gen_type_tag() -> impl Strategy<Value = TypeTag> {
25 prop_oneof![
26 2 => any::<TypeTag>(),
27 1 => gen_nested_type_tag()
28 ]
29}
30
31pub fn gen_nested_type_tag() -> impl Strategy<Value = TypeTag> {
33 let leaf = prop_oneof![
34 Just(TypeTag::Bool),
35 Just(TypeTag::U8),
36 Just(TypeTag::U16),
37 Just(TypeTag::U32),
38 Just(TypeTag::U64),
39 Just(TypeTag::U128),
40 Just(TypeTag::U256),
41 Just(TypeTag::Address),
42 Just(TypeTag::Signer),
43 ];
44 leaf.prop_recursive(8, 6, 10, |inner| {
45 prop_oneof![
46 inner.prop_map(|x| TypeTag::Vector(Box::new(x))),
47 gen_struct_tag().prop_map(|x| TypeTag::Struct(Box::new(x))),
48 ]
49 })
50}
51
52pub fn gen_struct_tag() -> impl Strategy<Value = StructTag> {
53 (
54 any::<AccountAddress>(),
55 any::<Identifier>(),
56 any::<Identifier>(),
57 any::<Vec<TypeTag>>(),
58 )
59 .prop_map(|(address, module, name, type_params)| StructTag {
60 address,
61 module,
62 name,
63 type_params,
64 })
65}
66
67pub fn generate_valid_type_factory_tags(
68 type_factory_addr: ObjectID,
69) -> impl Strategy<Value = TypeTag> {
70 let leaf = prop_oneof![
71 base_type_factory_tag_gen(type_factory_addr),
72 nested_type_factory_tag_gen(type_factory_addr),
73 ];
74
75 leaf.prop_recursive(8, 6, 10, move |inner| {
76 prop_oneof![inner.prop_map(|x| TypeTag::Vector(Box::new(x))),]
77 })
78}
79
80pub fn generate_valid_and_invalid_type_factory_tags(
81 type_factory_addr: ObjectID,
82) -> impl Strategy<Value = TypeTag> {
83 let leaf = prop_oneof![
84 any::<TypeTag>(),
85 base_type_factory_tag_gen(type_factory_addr),
86 nested_type_factory_tag_gen(type_factory_addr),
87 ];
88
89 leaf.prop_recursive(8, 6, 10, move |inner| {
90 prop_oneof![inner.prop_map(|x| TypeTag::Vector(Box::new(x))),]
91 })
92}
93
94pub fn base_type_factory_tag_gen(addr: ObjectID) -> impl Strategy<Value = TypeTag> {
95 "[A-Z]".prop_map(move |name| {
96 TypeTag::Struct(Box::new(StructTag {
97 address: AccountAddress::from(addr),
98 module: Identifier::new("type_factory").unwrap(),
99 name: Identifier::new(name).unwrap(),
100 type_params: vec![],
101 }))
102 })
103}
104
105pub fn nested_type_factory_tag_gen(addr: ObjectID) -> impl Strategy<Value = TypeTag> {
106 base_type_factory_tag_gen(addr).prop_recursive(20, 256, 10, move |inner| {
107 (inner, "[A-Z]").prop_map(move |(instantiation, name)| {
108 TypeTag::Struct(Box::new(StructTag {
109 address: AccountAddress::from(addr),
110 module: Identifier::new("type_factory").unwrap(),
111 name: Identifier::new(name.to_string() + &name).unwrap(),
112 type_params: vec![instantiation],
113 }))
114 })
115 })
116}
117
118pub fn type_factory_pt_for_tags(
119 package_id: ObjectID,
120 type_tags: Vec<TypeTag>,
121 len: usize,
122) -> ProgrammableTransaction {
123 let mut builder = ProgrammableTransactionBuilder::new();
124 builder
125 .move_call(
126 package_id,
127 Identifier::new("type_factory").unwrap(),
128 Identifier::new(format!("type_tags{}", len)).unwrap(),
129 type_tags,
130 vec![],
131 )
132 .unwrap();
133 builder.finish()
134}
135
136pub fn pt_for_tags(type_tags: Vec<TypeTag>) -> ProgrammableTransaction {
137 let mut builder = ProgrammableTransactionBuilder::new();
138 builder
139 .move_call(
140 SUI_FRAMEWORK_PACKAGE_ID,
141 Identifier::new("random_type_tag_fuzzing").unwrap(),
142 Identifier::new("random_type_tag_fuzzing_fn").unwrap(),
143 type_tags,
144 vec![],
145 )
146 .unwrap();
147 builder.finish()
148}
149
150pub fn run_pt(account: &mut AccountCurrent, exec: &mut Executor, pt: ProgrammableTransaction) {
151 let result = run_pt_effects(account, exec, pt);
152 let status = result.map(|effects| effects.status().clone());
153 assert_is_acceptable_result(&status);
154}
155
156pub fn run_pt_effects(
157 account: &mut AccountCurrent,
158 exec: &mut Executor,
159 pt: ProgrammableTransaction,
160) -> Result<TransactionEffects, SuiError> {
161 let gas_object = account.new_gas_object(exec);
162 let gas_object_ref = gas_object.compute_object_reference();
163 let kind = TransactionKind::ProgrammableTransaction(pt);
164 let tx_data = TransactionData::new(
165 kind,
166 account.initial_data.account.address,
167 gas_object_ref,
168 GAS,
169 GAS_PRICE,
170 );
171 let signed_txn = to_sender_signed_transaction(tx_data, &account.initial_data.account.key);
172 exec.rt
173 .block_on(submit_and_execute(&exec.state, signed_txn))
174 .map(|(_, effects)| effects.into_data())
175}