iota_replay/fuzz_mutations/
shuffle_command_inputs.rs1use iota_types::transaction::{Command, TransactionKind};
6use rand::seq::SliceRandom;
7use tracing::info;
8
9use crate::fuzz::TransactionKindMutator;
10
11pub struct ShuffleCommandInputs {
12 pub rng: rand::rngs::StdRng,
13 pub num_mutations_per_base_left: u64,
14}
15
16impl ShuffleCommandInputs {
17 fn shuffle_command(&mut self, command: &mut Command) {
18 match command {
19 Command::MakeMoveVec(_, ref mut args)
20 | Command::MergeCoins(_, ref mut args)
21 | Command::SplitCoins(_, ref mut args)
22 | Command::TransferObjects(ref mut args, _) => {
23 args.shuffle(&mut self.rng);
24 }
25 Command::MoveCall(ref mut pt) => pt.arguments.shuffle(&mut self.rng),
26 Command::Publish(_, _) => (),
27 Command::Upgrade(_, _, _, _) => (),
28 }
29 }
30}
31
32impl TransactionKindMutator for ShuffleCommandInputs {
33 fn mutate(&mut self, transaction_kind: &TransactionKind) -> Option<TransactionKind> {
34 if self.num_mutations_per_base_left == 0 {
35 return None;
37 }
38
39 self.num_mutations_per_base_left -= 1;
40 if let TransactionKind::ProgrammableTransaction(mut p) = transaction_kind.clone() {
41 for command in &mut p.commands {
42 self.shuffle_command(command);
43 }
44 info!("Mutation: Shuffling command inputs");
45 Some(TransactionKind::ProgrammableTransaction(p))
46 } else {
47 None
49 }
50 }
51
52 fn reset(&mut self, mutations_per_base: u64) {
53 self.num_mutations_per_base_left = mutations_per_base;
54 }
55}