sui_replay/
fuzz_mutations.rs1use rand::{SeedableRng, seq::SliceRandom};
5use sui_types::transaction::TransactionKind;
6
7use crate::fuzz::TransactionKindMutator;
8
9pub mod drop_random_command_suffix;
10pub mod drop_random_commands;
11pub mod shuffle_command_inputs;
12pub mod shuffle_commands;
13pub mod shuffle_transaction_inputs;
14pub mod shuffle_types;
15
16const NUM_TRIES: u64 = 5;
19
20pub struct RandomMutator {
25 pub rng: rand::rngs::StdRng,
26 pub mutators: Vec<Box<dyn TransactionKindMutator + Send + Sync>>,
27 pub num_tries: u64,
28}
29
30pub struct ChainedMutator {
31 pub mutators: Vec<Box<dyn TransactionKindMutator>>,
32}
33
34impl RandomMutator {
35 pub fn new() -> Self {
36 Self {
37 rng: rand::rngs::StdRng::from_seed([0u8; 32]),
38 mutators: vec![],
39 num_tries: NUM_TRIES,
40 }
41 }
42
43 pub fn add_mutator(&mut self, mutator: Box<dyn TransactionKindMutator + Send + Sync>) {
44 self.mutators.push(mutator);
45 }
46
47 pub fn select_mutator(&mut self) -> Option<&mut Box<dyn TransactionKindMutator + Send + Sync>> {
48 self.mutators.choose_mut(&mut self.rng)
49 }
50}
51
52impl Default for RandomMutator {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58impl TransactionKindMutator for RandomMutator {
59 fn mutate(&mut self, transaction_kind: &TransactionKind) -> Option<TransactionKind> {
60 for _ in 0..self.num_tries {
61 if let Some(mutator) = self.select_mutator() {
62 return mutator.mutate(transaction_kind);
63 }
64 }
65 None
66 }
67
68 fn reset(&mut self, mutations_per_base: u64) {
69 for mutator in self.mutators.iter_mut() {
70 mutator.reset(mutations_per_base);
71 }
72 }
73}
74
75impl ChainedMutator {
76 pub fn new() -> Self {
77 Self { mutators: vec![] }
78 }
79
80 pub fn add_mutator(&mut self, mutator: Box<dyn TransactionKindMutator>) {
81 self.mutators.push(mutator);
82 }
83}
84
85impl Default for ChainedMutator {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl TransactionKindMutator for ChainedMutator {
92 fn mutate(&mut self, transaction_kind: &TransactionKind) -> Option<TransactionKind> {
93 let mut mutated = transaction_kind.clone();
94 let mut num_mutations = 0;
95
96 for mutator in self.mutators.iter_mut() {
97 if let Some(new_mutated) = mutator.mutate(&mutated) {
98 num_mutations += 1;
99 mutated = new_mutated;
100 }
101 }
102
103 if num_mutations == 0 {
104 None
105 } else {
106 Some(mutated)
107 }
108 }
109
110 fn reset(&mut self, mutations_per_base: u64) {
111 for mutator in self.mutators.iter_mut() {
112 mutator.reset(mutations_per_base);
113 }
114 }
115}
116
117pub fn base_fuzzers(num_mutations: u64) -> RandomMutator {
118 let mut mutator = RandomMutator::new();
119 mutator.add_mutator(Box::new(shuffle_commands::ShuffleCommands {
120 rng: rand::rngs::StdRng::from_seed([0u8; 32]),
121 num_mutations_per_base_left: num_mutations,
122 }));
123 mutator.add_mutator(Box::new(shuffle_types::ShuffleTypes {
124 rng: rand::rngs::StdRng::from_seed([0u8; 32]),
125 num_mutations_per_base_left: num_mutations,
126 }));
127 mutator.add_mutator(Box::new(shuffle_command_inputs::ShuffleCommandInputs {
128 rng: rand::rngs::StdRng::from_seed([0u8; 32]),
129 num_mutations_per_base_left: num_mutations,
130 }));
131 mutator.add_mutator(Box::new(
132 shuffle_transaction_inputs::ShuffleTransactionInputs {
133 rng: rand::rngs::StdRng::from_seed([0u8; 32]),
134 num_mutations_per_base_left: num_mutations,
135 },
136 ));
137 mutator.add_mutator(Box::new(drop_random_commands::DropRandomCommands {
138 rng: rand::rngs::StdRng::from_seed([0u8; 32]),
139 num_mutations_per_base_left: num_mutations,
140 }));
141 mutator.add_mutator(Box::new(drop_random_command_suffix::DropCommandSuffix {
142 rng: rand::rngs::StdRng::from_seed([0u8; 32]),
143 num_mutations_per_base_left: num_mutations,
144 }));
145 mutator
146}