sui_replay/fuzz_mutations/
shuffle_command_inputs.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::fuzz::TransactionKindMutator;
5use rand::seq::SliceRandom;
6use sui_types::transaction::{Command, TransactionKind};
7use tracing::info;
8
9pub struct ShuffleCommandInputs {
10    pub rng: rand::rngs::StdRng,
11    pub num_mutations_per_base_left: u64,
12}
13
14impl ShuffleCommandInputs {
15    fn shuffle_command(&mut self, command: &mut Command) {
16        match command {
17            Command::MakeMoveVec(_, args)
18            | Command::MergeCoins(_, args)
19            | Command::SplitCoins(_, args)
20            | Command::TransferObjects(args, _) => {
21                args.shuffle(&mut self.rng);
22            }
23            Command::MoveCall(pt) => pt.arguments.shuffle(&mut self.rng),
24            Command::Publish(_, _) => (),
25            Command::Upgrade(_, _, _, _) => (),
26        }
27    }
28}
29
30impl TransactionKindMutator for ShuffleCommandInputs {
31    fn mutate(&mut self, transaction_kind: &TransactionKind) -> Option<TransactionKind> {
32        if self.num_mutations_per_base_left == 0 {
33            // Nothing else to do
34            return None;
35        }
36
37        self.num_mutations_per_base_left -= 1;
38        if let TransactionKind::ProgrammableTransaction(mut p) = transaction_kind.clone() {
39            for command in &mut p.commands {
40                self.shuffle_command(command);
41            }
42            info!("Mutation: Shuffling command inputs");
43            Some(TransactionKind::ProgrammableTransaction(p))
44        } else {
45            // Other types not supported yet
46            None
47        }
48    }
49
50    fn reset(&mut self, mutations_per_base: u64) {
51        self.num_mutations_per_base_left = mutations_per_base;
52    }
53}