From d91af2d8d694e05141eb0b0c965bd6a48d08d1c5 Mon Sep 17 00:00:00 2001 From: David Kazlauskas Date: Thu, 26 Sep 2024 10:31:37 +0300 Subject: [PATCH] feat: add structured logging for coprocessor + remove all panics from tfhe worker to allow graceful error handling --- fhevm-engine/Cargo.lock | 158 ++++++++++++ fhevm-engine/Cargo.toml | 1 + fhevm-engine/coprocessor/Cargo.toml | 2 + fhevm-engine/coprocessor/src/main.rs | 16 +- fhevm-engine/coprocessor/src/metrics.rs | 2 +- fhevm-engine/coprocessor/src/server.rs | 6 +- fhevm-engine/coprocessor/src/tfhe_worker.rs | 17 +- .../fhevm-engine-common/src/tfhe_ops.rs | 232 ++++++++++++++---- fhevm-engine/fhevm-engine-common/src/types.rs | 32 +++ 9 files changed, 407 insertions(+), 59 deletions(-) diff --git a/fhevm-engine/Cargo.lock b/fhevm-engine/Cargo.lock index 2b31c711..cc035fb3 100644 --- a/fhevm-engine/Cargo.lock +++ b/fhevm-engine/Cargo.lock @@ -1768,6 +1768,7 @@ dependencies = [ "fhevm-engine-common", "hex", "lazy_static", + "log", "lru", "prometheus", "prost", @@ -1776,6 +1777,7 @@ dependencies = [ "serde_json", "sha3", "sqlx", + "structured-logger", "strum", "testcontainers", "tfhe", @@ -2156,6 +2158,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + [[package]] name = "errno" version = "0.3.9" @@ -3136,6 +3148,10 @@ name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "serde", + "value-bag", +] [[package]] name = "lru" @@ -4447,6 +4463,15 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "serde_fmt" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" +dependencies = [ + "serde", +] + [[package]] name = "serde_json" version = "1.0.125" @@ -4892,6 +4917,19 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "structured-logger" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16524b1ef57fd2e253216ab20ec44f0dc32b29155a4b3e6bef0a857d8c9f5f08" +dependencies = [ + "log", + "parking_lot", + "serde", + "serde_json", + "tokio", +] + [[package]] name = "strum" version = "0.26.3" @@ -4920,6 +4958,84 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "sval" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf38d1fa2ce984086ea42fb856a9f374d94680a4f796831a7fc868d7f2af1b9" + +[[package]] +name = "sval_buffer" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81682ff859964ca1d7cf3d3d0f9ec7204ea04c2c32acb8cc2cf68ecbd3127354" +dependencies = [ + "sval", + "sval_ref", +] + +[[package]] +name = "sval_dynamic" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a213b93bb4c6f4c9f9b17f2e740e077fd18746bbf7c80c72bbadcac68fa7ee4" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_fmt" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6902c6d3fb52c89206fe0dc93546c0123f7d48b5997fd14e61c9e64ff0b63275" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_json" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a28041ea78cdc394b930ae6b897d36246dc240a29a6edf82d76562487fb0b4" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_nested" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850346e4b0742a7f2fd2697d703ff80084d0b658f0f2e336d71b8a06abf9b68e" +dependencies = [ + "sval", + "sval_buffer", + "sval_ref", +] + +[[package]] +name = "sval_ref" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824afd97a8919f28a35b0fdea979845cc2ae461a8a3aaa129455cb89c88bb77a" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_serde" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ada7520dd719ed672c786c7db7de4f5230f4d504b0821bd8305cd30ca442315" +dependencies = [ + "serde", + "sval", + "sval_nested", +] + [[package]] name = "syn" version = "1.0.109" @@ -5527,6 +5643,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + [[package]] name = "typenum" version = "1.17.0" @@ -5653,6 +5775,42 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +dependencies = [ + "value-bag-serde1", + "value-bag-sval2", +] + +[[package]] +name = "value-bag-serde1" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccacf50c5cb077a9abb723c5bcb5e0754c1a433f1e1de89edc328e2760b6328b" +dependencies = [ + "erased-serde", + "serde", + "serde_fmt", +] + +[[package]] +name = "value-bag-sval2" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1785bae486022dfb9703915d42287dcb284c1ee37bd1080eeba78cc04721285b" +dependencies = [ + "sval", + "sval_buffer", + "sval_dynamic", + "sval_fmt", + "sval_json", + "sval_ref", + "sval_serde", +] + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/fhevm-engine/Cargo.toml b/fhevm-engine/Cargo.toml index c545e78a..b1d40a85 100644 --- a/fhevm-engine/Cargo.toml +++ b/fhevm-engine/Cargo.toml @@ -13,6 +13,7 @@ anyhow = "1.0.86" daggy = "0.8.0" serde = "1.0.210" prometheus = "0.13.4" +log = { version = "0.4.22", features = ["kv"] } [profile.dev.package.tfhe] overflow-checks = false diff --git a/fhevm-engine/coprocessor/Cargo.toml b/fhevm-engine/coprocessor/Cargo.toml index a2fc644c..99fc3a66 100644 --- a/fhevm-engine/coprocessor/Cargo.toml +++ b/fhevm-engine/coprocessor/Cargo.toml @@ -32,6 +32,8 @@ strum = { version = "0.26", features = ["derive"] } bincode.workspace = true sha3.workspace = true prometheus.workspace = true +log.workspace = true +structured-logger = "1.0.3" actix-web = "4.9.0" [dev-dependencies] diff --git a/fhevm-engine/coprocessor/src/main.rs b/fhevm-engine/coprocessor/src/main.rs index 4b1f718b..f262482d 100644 --- a/fhevm-engine/coprocessor/src/main.rs +++ b/fhevm-engine/coprocessor/src/main.rs @@ -42,16 +42,16 @@ pub fn start_runtime( tokio::select! { main = async_main(args) => { if let Err(e) = main { - eprintln!("Runtime error: {:?}", e); + log::error!(target: "main_wchannel", error = e.to_string(); "Runtime error"); } } _ = close_recv.changed() => { - eprintln!("Service stopped voluntarily"); + log::info!(target: "main_wchannel", "Service stopped voluntarily"); } } } else { if let Err(e) = async_main(args).await { - eprintln!("Runtime error: {:?}", e); + log::error!(target: "main", error = e.to_string(); "Runtime error"); } } }) @@ -60,19 +60,23 @@ pub fn start_runtime( async fn async_main( args: crate::cli::Args, ) -> Result<(), Box> { + structured_logger::Builder::new() + .with_default_writer(structured_logger::async_json::new_writer(tokio::io::stdout())) + .init(); + let mut set = JoinSet::new(); if args.run_server { - println!("Initializing api server"); + log::info!(target: "async_main", "Initializing api server"); set.spawn(crate::server::run_server(args.clone())); } if args.run_bg_worker { - println!("Initializing background worker"); + log::info!(target: "async_main", "Initializing background worker"); set.spawn(crate::tfhe_worker::run_tfhe_worker(args.clone())); } if !args.metrics_addr.is_empty() { - println!("Initializing metrics server"); + log::info!(target: "async_main", "Initializing metrics server"); set.spawn(crate::metrics::run_metrics_server(args.clone())); } diff --git a/fhevm-engine/coprocessor/src/metrics.rs b/fhevm-engine/coprocessor/src/metrics.rs index 69d9b917..821d234a 100644 --- a/fhevm-engine/coprocessor/src/metrics.rs +++ b/fhevm-engine/coprocessor/src/metrics.rs @@ -11,7 +11,7 @@ async fn healthcheck() -> impl actix_web::Responder { pub async fn run_metrics_server( args: crate::cli::Args, ) -> Result<(), Box> { - println!("metrics server listening at {}", args.metrics_addr); + log::info!("metrics server listening at {}", args.metrics_addr); let _ = actix_web::HttpServer::new(|| { actix_web::App::new() .route("/metrics", actix_web::web::to(metrics)) diff --git a/fhevm-engine/coprocessor/src/server.rs b/fhevm-engine/coprocessor/src/server.rs index eaeef856..6ffdbde5 100644 --- a/fhevm-engine/coprocessor/src/server.rs +++ b/fhevm-engine/coprocessor/src/server.rs @@ -67,7 +67,7 @@ pub async fn run_server( ) -> Result<(), Box> { loop { if let Err(e) = run_server_iteration(args.clone()).await { - println!("Error running server, retrying shortly: {:?}", e); + log::error!(target: "grpc_server", error = e.to_string(); "Error running server, retrying shortly"); } tokio::time::sleep(tokio::time::Duration::from_millis(5000)).await; @@ -86,9 +86,9 @@ pub async fn run_server_iteration( let coprocessor_key_file = tokio::fs::read_to_string(&args.coprocessor_private_key).await?; let signer = PrivateKeySigner::from_str(coprocessor_key_file.trim())?; - println!("Coprocessor signer address: {}", signer.address()); + log::info!(target: "grpc_server", address = signer.address().to_string(); "Coprocessor signer initiated"); - println!("Coprocessor listening on {}", addr); + log::info!("Coprocessor listening on {}", addr); let pool = sqlx::postgres::PgPoolOptions::new() .max_connections(args.pg_pool_max_connections) .connect(&db_url) diff --git a/fhevm-engine/coprocessor/src/tfhe_worker.rs b/fhevm-engine/coprocessor/src/tfhe_worker.rs index ee4f7884..cfa573a5 100644 --- a/fhevm-engine/coprocessor/src/tfhe_worker.rs +++ b/fhevm-engine/coprocessor/src/tfhe_worker.rs @@ -35,10 +35,7 @@ pub async fn run_tfhe_worker( // here we log the errors and make sure we retry if let Err(cycle_error) = tfhe_worker_cycle(&args).await { WORKER_ERRORS_COUNTER.inc(); - eprintln!( - "Error in background worker, retrying shortly: {:?}", - cycle_error - ); + log::error!(target: "tfhe_worker", error = cycle_error.to_string(); "Error in background worker, retrying shortly"); } tokio::time::sleep(tokio::time::Duration::from_millis(5000)).await; } @@ -68,11 +65,11 @@ async fn tfhe_worker_cycle( tokio::select! { _ = listener.try_recv() => { WORK_ITEMS_NOTIFICATIONS_COUNTER.inc(); - println!("Received work_available notification from postgres"); + log::info!(target: "tfhe_worker", "Received work_available notification from postgres"); }, _ = tokio::time::sleep(tokio::time::Duration::from_millis(5000)) => { WORK_ITEMS_POLL_COUNTER.inc(); - println!("Polling the database for more work on timer"); + log::info!(target: "tfhe_worker", "Polling the database for more work on timer"); }, }; } @@ -114,7 +111,7 @@ async fn tfhe_worker_cycle( } WORK_ITEMS_FOUND_COUNTER.inc_by(the_work.len() as u64); - println!("Processing {} work items", the_work.len()); + log::info!(target: "tfhe_worker", count = the_work.len(); "Processing work items"); // make sure we process each tenant sequentially not to // load different keys in cache by different tenants @@ -273,6 +270,12 @@ async fn tfhe_worker_cycle( } Err((err, tenant_id, output_handle)) => { WORKER_ERRORS_COUNTER.inc(); + log::error!(target: "tfhe_worker", + tenant_id, + output_handle = format!("0x{}", hex::encode(&output_handle)), + error = err.to_string(); + "error while processing work item" + ); let _ = query!( " UPDATE computations diff --git a/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs b/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs index 0245b13f..bd51e307 100644 --- a/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs +++ b/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs @@ -884,7 +884,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a + *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -963,7 +966,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a - *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1042,7 +1048,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a * *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1121,7 +1130,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a / *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1200,7 +1212,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a % *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1279,7 +1294,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a & *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1358,7 +1376,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a | *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1437,7 +1458,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a ^ *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1516,7 +1540,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a << *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1595,7 +1622,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a >> *b)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1674,7 +1704,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a.rotate_left(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1753,7 +1786,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a.rotate_right(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1832,7 +1868,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a.min(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1911,7 +1950,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheUint256(a.max(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -1998,7 +2040,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBool(a.eq(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2085,7 +2130,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBool(a.ne(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2164,7 +2212,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBool(a.ge(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2243,7 +2294,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBool(a.gt(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2322,7 +2376,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBool(a.le(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2401,7 +2458,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBool(a.lt(*b))) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2434,7 +2494,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBytes256(!a)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2466,7 +2529,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBytes256(-a)) } _ => { - panic!("Unsupported fhe types"); + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2474,7 +2540,10 @@ pub fn perform_fhe_operation( assert_eq!(input_operands.len(), 3); let SupportedFheCiphertexts::FheBool(flag) = &input_operands[0] else { - panic!("flag for if-then-else must be boolean") + return Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) }; match (&input_operands[1], &input_operands[2]) { @@ -2545,7 +2614,10 @@ pub fn perform_fhe_operation( Ok(SupportedFheCiphertexts::FheBytes256(res)) } _ => { - panic!("Mismatch between cmux operand types") + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } } } @@ -2602,7 +2674,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -2658,7 +2735,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -2714,7 +2796,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -2770,7 +2857,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -2826,7 +2918,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -2882,7 +2979,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -2938,7 +3040,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -2994,7 +3101,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -3050,7 +3162,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -3106,7 +3223,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -3162,7 +3284,12 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint2048 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheBytes256(out)) } - other => panic!("unexpected type: {other}"), + other => { + Err(FhevmError::UnknownCastType { + fhe_operation: format!("{:?}", fhe_operation), + type_to_cast_to: other, + }) + }, } } } @@ -3223,7 +3350,10 @@ pub fn perform_fhe_operation( } } _ => { - panic!("unknown cast pair") + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } }, SupportedFheOperations::FheTrivialEncrypt => match (&input_operands[0], &input_operands[1]) @@ -3236,15 +3366,24 @@ pub fn perform_fhe_operation( Ok(trivial_encrypt_be_bytes(l, &bytes)) } _ => { - panic!("unknown trivial encrypt operation") + Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) } }, SupportedFheOperations::FheRand => { let SupportedFheCiphertexts::Scalar(rand_counter) = &input_operands[0] else { - panic!("we should have checked we have only scalar operands here") + return Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) }; let SupportedFheCiphertexts::Scalar(to_type) = &input_operands[1] else { - panic!("we should have checked we have only scalar operands here") + return Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) }; let (rand_counter, _) = rand_counter.to_low_high_u128(); let (to_type, _) = to_type.to_low_high_u128(); @@ -3252,13 +3391,22 @@ pub fn perform_fhe_operation( } SupportedFheOperations::FheRandBounded => { let SupportedFheCiphertexts::Scalar(rand_counter) = &input_operands[0] else { - panic!("we should have checked we have only scalar operands here") + return Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) }; let SupportedFheCiphertexts::Scalar(upper_bound) = &input_operands[1] else { - panic!("we should have checked we have only scalar operands here") + return Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) }; let SupportedFheCiphertexts::Scalar(to_type) = &input_operands[2] else { - panic!("we should have checked we have only scalar operands here") + return Err(FhevmError::UnsupportedFheTypes { + fhe_operation: format!("{:?}", fhe_operation), + input_types: input_operands.iter().map(|i| i.type_name()).collect(), + }) }; let (rand_counter, _) = rand_counter.to_low_high_u128(); let (to_type, _) = to_type.to_low_high_u128(); diff --git a/fhevm-engine/fhevm-engine-common/src/types.rs b/fhevm-engine/fhevm-engine-common/src/types.rs index 30d4fca9..e1d581d5 100644 --- a/fhevm-engine/fhevm-engine-common/src/types.rs +++ b/fhevm-engine/fhevm-engine-common/src/types.rs @@ -113,6 +113,14 @@ pub enum FhevmError { BadInputs, MissingTfheRsData, InvalidHandle, + UnsupportedFheTypes { + fhe_operation: String, + input_types: Vec<&'static str>, + }, + UnknownCastType { + fhe_operation: String, + type_to_cast_to: i16, + }, } impl std::error::Error for FhevmError {} @@ -277,6 +285,12 @@ impl std::fmt::Display for FhevmError { Self::InvalidHandle => { write!(f, "Invalid ciphertext handle") } + Self::UnsupportedFheTypes { fhe_operation, input_types } => { + write!(f, "Unsupported type combination for fhe operation {fhe_operation}: {:?}", input_types) + } + Self::UnknownCastType { fhe_operation, type_to_cast_to } => { + write!(f, "Unknown type to cast to for fhe operation {fhe_operation}: {}", type_to_cast_to) + } } } } @@ -381,6 +395,24 @@ impl SupportedFheCiphertexts { } } + pub fn type_name(&self) -> &'static str { + match self { + SupportedFheCiphertexts::FheBool(..) => "FheBool", + SupportedFheCiphertexts::FheUint4(..) => "FheUint4", + SupportedFheCiphertexts::FheUint8(..) => "FheUint8", + SupportedFheCiphertexts::FheUint16(..) => "FheUint16", + SupportedFheCiphertexts::FheUint32(..) => "FheUint32", + SupportedFheCiphertexts::FheUint64(..) => "FheUint64", + SupportedFheCiphertexts::FheUint128(..) => "FheUint128", + SupportedFheCiphertexts::FheUint160(..) => "FheUint160", + SupportedFheCiphertexts::FheUint256(..) => "FheUint256", + SupportedFheCiphertexts::FheBytes64(..) => "FheBytes64", + SupportedFheCiphertexts::FheBytes128(..) => "FheBytes128", + SupportedFheCiphertexts::FheBytes256(..) => "FheBytes256", + SupportedFheCiphertexts::Scalar(..) => "Scalar", + } + } + pub fn decrypt(&self, client_key: &tfhe::ClientKey) -> String { match self { SupportedFheCiphertexts::FheBool(v) => v.decrypt(client_key).to_string(),