From ceceeac6c3ebb0cc0b590d83ebe277f658d8dd71 Mon Sep 17 00:00:00 2001 From: Nicolas Racchi Date: Tue, 14 Mar 2023 00:04:19 +0100 Subject: [PATCH 1/6] feat: added huff_cli flag to print jump label indices --- huff_cli/src/huffc.rs | 74 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/huff_cli/src/huffc.rs b/huff_cli/src/huffc.rs index c8fc8b76..8fb74328 100644 --- a/huff_cli/src/huffc.rs +++ b/huff_cli/src/huffc.rs @@ -18,8 +18,8 @@ use huff_tests::{ use huff_utils::{ file_provider::FileSystemFileProvider, prelude::{ - export_interfaces, gen_sol_interfaces, str_to_bytes32, unpack_files, AstSpan, CodegenError, - CodegenErrorKind, CompilerError, FileSource, Literal, OutputLocation, Span, + export_interfaces, gen_sol_interfaces, str_to_bytes32, unpack_files, AstSpan, BytecodeRes, + CodegenError, CodegenErrorKind, CompilerError, FileSource, Literal, OutputLocation, Span, }, }; use isatty::stdout_isatty; @@ -82,6 +82,10 @@ struct Huff { #[clap(short = 'v', long = "verbose")] verbose: bool, + /// Prints out the jump label PC indices for the specified contract. + #[clap(short = 'x', long = "label-indices")] + label_indices: bool, + /// Override / set constants for the compilation environment. #[clap(short = 'c', long = "constants", multiple_values = true)] constants: Option>, @@ -156,12 +160,12 @@ fn main() { // Check that constant override argument is valid // Key rule: Alphabetic chars + underscore // Value rule: Valid literal string (0x...) - if parts.len() != 2 || - parts[0].chars().any(|c| !(c.is_alphabetic() || c == '_')) || - !parts[1].starts_with("0x") || - parts[1][2..].chars().any(|c| { - !(c.is_numeric() || - matches!(c, '\u{0041}'..='\u{0046}' | '\u{0061}'..='\u{0066}')) + if parts.len() != 2 + || parts[0].chars().any(|c| !(c.is_alphabetic() || c == '_')) + || !parts[1].starts_with("0x") + || parts[1][2..].chars().any(|c| { + !(c.is_numeric() + || matches!(c, '\u{0041}'..='\u{0046}' | '\u{0061}'..='\u{0066}')) }) { eprintln!("Invalid constant override argument: {}", Paint::red(c.to_string())); @@ -204,6 +208,58 @@ fn main() { file_provider: Arc::new(FileSystemFileProvider {}), }; + if cli.label_indices { + match compiler.grab_contracts() { + Ok(contracts) => { + if contracts.len() > 1 { + eprintln!( + "{}", + Paint::red("Multiple contracts found. Please specify a single contract and try again.") + ); + std::process::exit(1); + } + + if let Some(contract) = contracts.first() { + let m_macro = contract.find_macro_by_name("MAIN").unwrap(); + + // Recurse through the macro and generate bytecode + let bytecode_res: BytecodeRes = Codegen::macro_to_bytecode( + m_macro.clone(), + contract, + &mut vec![m_macro], + 0, + &mut Vec::default(), + false, + None, + ) + .unwrap(); + + // Format the label indices nicely + let label_indices = bytecode_res + .label_indices + .iter() + .map(|(label, index)| format!("{}: 0x{:04x}", label, index)) + .collect::>() + .join("\n"); + + println!("Label indices:\n{}", label_indices); + } else { + eprintln!( + "{}", + Paint::red("No contract found. Please specify a contract and try again.") + ); + std::process::exit(1); + } + } + Err(e) => { + tracing::error!(target: "cli", "PARSER ERRORED!"); + eprintln!("{}", Paint::red(e)); + std::process::exit(1); + } + } + return; + } + if let Some(TestCommands::Test { format, match_ }) = cli.test { match compiler.grab_contracts() { Ok(contracts) => { @@ -230,7 +286,7 @@ fn main() { std::process::exit(1); } } - return + return; } // Create compiling spinner From 2cd3c8043dc5ffb41f33efc97877e76f88361378 Mon Sep 17 00:00:00 2001 From: Nicolas Racchi Date: Tue, 14 Mar 2023 00:05:25 +0100 Subject: [PATCH 2/6] chore: hex formatting --- huff_cli/src/huffc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/huff_cli/src/huffc.rs b/huff_cli/src/huffc.rs index 8fb74328..b8530eb7 100644 --- a/huff_cli/src/huffc.rs +++ b/huff_cli/src/huffc.rs @@ -238,7 +238,7 @@ fn main() { let label_indices = bytecode_res .label_indices .iter() - .map(|(label, index)| format!("{}: 0x{:04x}", label, index)) + .map(|(label, index)| format!("{}: {:#04x}", label, index)) .collect::>() .join("\n"); From 6cd93dd02732f165f3fcdea8ed909dd819941326 Mon Sep 17 00:00:00 2001 From: Nicolas Racchi Date: Tue, 14 Mar 2023 00:12:27 +0100 Subject: [PATCH 3/6] chore: fmt --- huff_cli/src/huffc.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/huff_cli/src/huffc.rs b/huff_cli/src/huffc.rs index b8530eb7..67b5afd7 100644 --- a/huff_cli/src/huffc.rs +++ b/huff_cli/src/huffc.rs @@ -160,12 +160,12 @@ fn main() { // Check that constant override argument is valid // Key rule: Alphabetic chars + underscore // Value rule: Valid literal string (0x...) - if parts.len() != 2 - || parts[0].chars().any(|c| !(c.is_alphabetic() || c == '_')) - || !parts[1].starts_with("0x") - || parts[1][2..].chars().any(|c| { - !(c.is_numeric() - || matches!(c, '\u{0041}'..='\u{0046}' | '\u{0061}'..='\u{0066}')) + if parts.len() != 2 || + parts[0].chars().any(|c| !(c.is_alphabetic() || c == '_')) || + !parts[1].starts_with("0x") || + parts[1][2..].chars().any(|c| { + !(c.is_numeric() || + matches!(c, '\u{0041}'..='\u{0046}' | '\u{0061}'..='\u{0066}')) }) { eprintln!("Invalid constant override argument: {}", Paint::red(c.to_string())); @@ -257,7 +257,7 @@ fn main() { std::process::exit(1); } } - return; + return } if let Some(TestCommands::Test { format, match_ }) = cli.test { @@ -286,7 +286,7 @@ fn main() { std::process::exit(1); } } - return; + return } // Create compiling spinner From 46dfe99f00df45eec038919d07aed92150da6140 Mon Sep 17 00:00:00 2001 From: merklefruit Date: Fri, 14 Apr 2023 09:39:27 +0200 Subject: [PATCH 4/6] feat: better formatting --- huff_cli/src/huffc.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/huff_cli/src/huffc.rs b/huff_cli/src/huffc.rs index 67b5afd7..5a55031c 100644 --- a/huff_cli/src/huffc.rs +++ b/huff_cli/src/huffc.rs @@ -240,9 +240,11 @@ fn main() { .iter() .map(|(label, index)| format!("{}: {:#04x}", label, index)) .collect::>() - .join("\n"); + .join("\n "); - println!("Label indices:\n{}", label_indices); + println!("\n------ JUMP LABEL INDICES ------"); + println!("{}", format!(" {}", label_indices).to_string()); + println!("--------------------------------\n") } else { eprintln!( "{}", From 6793097415bd2e43abf2725324290867e53788d6 Mon Sep 17 00:00:00 2001 From: merklefruit Date: Fri, 14 Apr 2023 09:57:57 +0200 Subject: [PATCH 5/6] chore: removed unnecessary format --- huff_cli/src/huffc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/huff_cli/src/huffc.rs b/huff_cli/src/huffc.rs index 5a55031c..e00ca89e 100644 --- a/huff_cli/src/huffc.rs +++ b/huff_cli/src/huffc.rs @@ -243,7 +243,7 @@ fn main() { .join("\n "); println!("\n------ JUMP LABEL INDICES ------"); - println!("{}", format!(" {}", label_indices).to_string()); + println!(" {}", label_indices); println!("--------------------------------\n") } else { eprintln!( From 29d2e043ec462797c9a0c611aa9132999439a8a7 Mon Sep 17 00:00:00 2001 From: merklefruit Date: Sun, 16 Apr 2023 01:07:12 +0200 Subject: [PATCH 6/6] chore: adapted code to review --- Cargo.lock | 1 + huff_cli/Cargo.toml | 1 + huff_cli/src/huffc.rs | 61 +++++++++++++++++++++++++++++++------------ 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 423f7cb0..2273cb0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,6 +699,7 @@ name = "huff_cli" version = "0.3.1" dependencies = [ "clap 3.2.23", + "comfy-table", "ethers-core", "huff_codegen", "huff_core", diff --git a/huff_cli/Cargo.toml b/huff_cli/Cargo.toml index d45d7659..b5ac3aa0 100644 --- a/huff_cli/Cargo.toml +++ b/huff_cli/Cargo.toml @@ -17,6 +17,7 @@ huff_core = { path = "../huff_core", version = "0.x.x" } huff_codegen = { path = "../huff_codegen", version = "0.x.x" } huff_utils = { path = "../huff_utils", version = "0.x.x" } huff_tests = { path = "../huff_tests", version = "0.x.x" } +comfy-table = "6.0.0" tracing = "0.1.34" ethers-core = "1.0.2" yansi = "0.5.1" diff --git a/huff_cli/src/huffc.rs b/huff_cli/src/huffc.rs index e00ca89e..93bc0299 100644 --- a/huff_cli/src/huffc.rs +++ b/huff_cli/src/huffc.rs @@ -8,6 +8,7 @@ #![allow(deprecated)] use clap::{App, CommandFactory, Parser as ClapParser, Subcommand}; +use comfy_table::{modifiers::UTF8_ROUND_CORNERS, presets::UTF8_FULL, Cell, Color, Row, Table}; use ethers_core::utils::hex; use huff_codegen::Codegen; use huff_core::Compiler; @@ -83,7 +84,7 @@ struct Huff { verbose: bool, /// Prints out the jump label PC indices for the specified contract. - #[clap(short = 'x', long = "label-indices")] + #[clap(short = 'l', long = "label-indices")] label_indices: bool, /// Override / set constants for the compilation environment. @@ -95,7 +96,7 @@ struct Huff { alternative_main: Option, /// Compile a specific constructor macro - #[clap(short = 'l', long = "alt-constructor")] + #[clap(short = 't', long = "alt-constructor")] alternative_constructor: Option, /// Test subcommand @@ -198,7 +199,7 @@ fn main() { let compiler: Compiler = Compiler { sources: Arc::clone(&sources), output, - alternative_main: cli.alternative_main, + alternative_main: cli.alternative_main.clone(), alternative_constructor: cli.alternative_constructor, construct_args: cli.inputs, constant_overrides: constants, @@ -220,13 +221,25 @@ fn main() { } if let Some(contract) = contracts.first() { - let m_macro = contract.find_macro_by_name("MAIN").unwrap(); + let macro_def = contract + .find_macro_by_name( + &cli.alternative_main.unwrap_or_else(|| "MAIN".to_string()), + ) + .unwrap_or_else(|| { + eprintln!( + "{}", + Paint::red( + "Macro not found. Please specify a valid macro and try again." + ) + ); + std::process::exit(1); + }); // Recurse through the macro and generate bytecode let bytecode_res: BytecodeRes = Codegen::macro_to_bytecode( - m_macro.clone(), + macro_def.clone(), contract, - &mut vec![m_macro], + &mut vec![macro_def.clone()], 0, &mut Vec::default(), false, @@ -234,17 +247,31 @@ fn main() { ) .unwrap(); - // Format the label indices nicely - let label_indices = bytecode_res - .label_indices - .iter() - .map(|(label, index)| format!("{}: {:#04x}", label, index)) - .collect::>() - .join("\n "); - - println!("\n------ JUMP LABEL INDICES ------"); - println!(" {}", label_indices); - println!("--------------------------------\n") + if !bytecode_res.label_indices.is_empty() { + // Format the label indices nicely in a table + let mut table = Table::new(); + table.load_preset(UTF8_FULL).apply_modifier(UTF8_ROUND_CORNERS); + table + .set_header(vec![ + Cell::new("Jump Label").fg(Color::Cyan), + Cell::new("Program counter offset (in hex)").fg(Color::Cyan), + ]) + .add_rows(bytecode_res.label_indices.iter().map(|(label, index)| { + Row::from(vec![ + Cell::new(label), + Cell::new(&format!("{:#04x}", index)), + ]) + })); + println!("{table}"); + } else { + eprintln!( + "{}", + Paint::red( + "No jump labels found. Please try again.\nHint: you can run this command on a specific macro by adding the `-m ` flag.\n" + ) + ); + std::process::exit(1); + } } else { eprintln!( "{}",