47 for (
size_t v : values) {
52 double sum = std::accumulate(values.begin(), values.end(), 0.0);
53 stats.
mean =
sum /
static_cast<double>(values.size());
56 std::vector<size_t> sorted = values;
58 size_t n = sorted.size();
60 stats.
median = (
static_cast<double>(sorted[n / 2 - 1]) +
static_cast<double>(sorted[n / 2])) / 2.0;
62 stats.
median =
static_cast<double>(sorted[n / 2]);
68 if (count > max_count) {
115 std::cout <<
"\n=== Opcode Histogram ===\n";
117 if (opcode_counts.empty()) {
123 size_t max_count = 0;
124 size_t total_instructions = 0;
125 for (
const auto& [opcode, count] : opcode_counts) {
126 max_count =
std::max(max_count, count);
127 total_instructions += count;
131 size_t max_name_len = 0;
132 for (
const auto& [opcode, count] : opcode_counts) {
139 sorted_counts.begin(), sorted_counts.end(), [](
const auto&
a,
const auto&
b) { return a.second > b.second; });
141 for (
const auto& [opcode, count] : sorted_counts) {
147 std::cout <<
"\n=== Opcode Statistics ===\n";
148 std::cout <<
"Total instructions: " << total_instructions <<
"\n";
150 size_t total_opcodes =
static_cast<size_t>(WireOpCode::LAST_OPCODE_SENTINEL);
151 std::cout <<
"Unique opcodes used: " << opcode_counts.size() <<
"/" << total_opcodes <<
"\n";
155 for (
size_t i = 0; i < total_opcodes; i++) {
157 if (opcode_counts.find(opcode) == opcode_counts.end()) {
158 missing_opcodes.push_back(opcode);
162 if (!missing_opcodes.empty()) {
163 std::cout <<
"Missing opcodes (" << missing_opcodes.size() <<
"): ";
164 for (
size_t i = 0; i < missing_opcodes.size(); i++) {
173 if (!sorted_counts.empty()) {
174 std::cout <<
"Most common: " <<
opcode_name(sorted_counts.front().first) <<
" (" << sorted_counts.front().second
176 std::cout <<
"Least common: " <<
opcode_name(sorted_counts.back().first) <<
" (" << sorted_counts.back().second
224 std::string corpus_dir =
"corpus/tx";
226 corpus_dir = argv[1];
230 if (!fs::exists(corpus_dir)) {
231 std::cerr <<
"Error: Corpus directory does not exist: " << corpus_dir <<
"\n";
235 if (!fs::is_directory(corpus_dir)) {
236 std::cerr <<
"Error: Not a directory: " << corpus_dir <<
"\n";
240 std::cout <<
"=== AVM Fuzzer Corpus Analysis ===\n";
241 std::cout <<
"Corpus directory: " << corpus_dir <<
"\n";
245 std::vector<size_t> setup_call_counts;
246 std::vector<size_t> app_logic_call_counts;
247 std::vector<size_t> teardown_call_counts;
249 size_t files_processed = 0;
250 size_t files_failed = 0;
251 size_t total_input_programs = 0;
254 for (
const auto& entry : fs::directory_iterator(corpus_dir)) {
255 if (!entry.is_regular_file()) {
259 const auto& path = entry.path();
262 std::ifstream file(path, std::ios::binary);
274 msgpack::unpack(
reinterpret_cast<const char*
>(
buffer.data()),
buffer.size()).get().convert(tx_data);
275 }
catch (
const std::exception& e) {
287 setup_call_counts.push_back(setup_count);
288 app_logic_call_counts.push_back(app_logic_count);
289 teardown_call_counts.push_back(teardown_count);
292 bool has_setup = setup_count > 0;
293 bool has_app_logic = app_logic_count > 0;
294 bool has_teardown = teardown_count > 0;
295 int phases_with_calls = (has_setup ? 1 : 0) + (has_app_logic ? 1 : 0) + (has_teardown ? 1 : 0);
297 if (phases_with_calls >= 2) {
300 if (has_setup && has_app_logic && !has_teardown) {
303 if (has_setup && has_teardown && !has_app_logic) {
306 if (has_app_logic && has_teardown && !has_setup) {
309 if (has_setup && has_app_logic && has_teardown) {
315 total_input_programs++;
320 for (
const auto& cfg_instruction : fuzzer_data.cfg_instructions) {
327 }
catch (
const std::exception&) {
335 std::cout <<
"\nFiles processed: " << files_processed <<
"\n";
336 std::cout <<
"Files failed: " << files_failed <<
"\n";
337 std::cout <<
"Total input programs: " << total_input_programs <<
"\n";