diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 946949f..fc6de36 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,6 +37,19 @@ jobs: - name: run rust tests run: make rust_test + cpp_tests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: true + - name: Install deps + run: | + sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10 + make deps + - run: make cpp_test + clippy: runs-on: ubuntu-latest container: diff --git a/CMakeLists.txt b/CMakeLists.txt index 187a447..ba62bf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ #* limitations under the License. #******************************************************************************** cmake_minimum_required(VERSION 3.28) +set(CMAKE_VERBOSE_MAKEFILE ON) include("cmake/HunterGate.cmake") HunterGate( URL "https://github.com/cpp-pm/hunter/archive/v0.25.5.tar.gz" @@ -22,7 +23,7 @@ HunterGate( ) if(CMAKE_GENERATOR MATCHES "Ninja") - message(FATAL_ERROR "This project does not support the Ninja generator. " + message(FATAL_ERROR "This project does not support the Ninja generator. " "Please use Unix Makefiles or another supported generator. " "This error is typical in CLion. In this case, switch to generator Unix Makefiles.") endif() @@ -177,6 +178,8 @@ target_include_directories(app_lib PUBLIC ############################################################## ## Rust library for CPP tests set(RUST_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/app/rust") +message(STATUS "Rust library path: ${RUST_LIB}") +message(STATUS "Rust library path2: ${RUST_LIB_DIR}") # Determine the Rust target triple based on the host system if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") @@ -200,7 +203,7 @@ else() endif() # Use debug mode for debugging tests -set(RUST_TARGET_DIR "${RUST_LIB_DIR}/target/${RUST_TARGET_TRIPLE}/debug") +set(RUST_TARGET_DIR "${RUST_LIB_DIR}/target/${RUST_TARGET_TRIPLE}/release") # Custom target for the Rust library add_custom_target(RustLibClean @@ -208,7 +211,7 @@ add_custom_target(RustLibClean WORKING_DIRECTORY ${RUST_LIB_DIR} ) add_custom_target(RustLibBuild - COMMAND cargo build --target ${RUST_TARGET_TRIPLE} + COMMAND cargo build --release --target ${RUST_TARGET_TRIPLE} --features cpp_tests WORKING_DIRECTORY ${RUST_LIB_DIR} DEPENDS RustLibClean ) @@ -239,13 +242,13 @@ if(ENABLE_FUZZING) target_link_options(fuzz-${target} PRIVATE "-fsanitize=fuzzer") endforeach() else() -############################################################## -# Tests -file(GLOB_RECURSE TESTS_SRC + ############################################################## + # Tests + file(GLOB_RECURSE TESTS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp) -add_executable(unittests ${TESTS_SRC}) -target_include_directories(unittests PRIVATE + add_executable(unittests ${TESTS_SRC}) + target_include_directories(unittests PRIVATE ${gtest_SOURCE_DIR}/include ${gmock_SOURCE_DIR}/include ${CONAN_INCLUDE_DIRS_FMT} @@ -256,11 +259,17 @@ target_include_directories(unittests PRIVATE ) target_link_libraries(unittests PRIVATE - rslib - app_lib - GTest::gtest_main - fmt::fmt - JsonCpp::JsonCpp) + app_lib + rslib + GTest::gtest_main + fmt::fmt + JsonCpp::JsonCpp) + # target_link_libraries(unittests PRIVATE + # rslib + # app_lib + # GTest::gtest_main + # fmt::fmt + # JsonCpp::JsonCpp) add_compile_definitions(TESTVECTORS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/") add_test(NAME unittests COMMAND unittests) diff --git a/app/rust/.cargo/config.toml b/app/rust/.cargo/config.toml index c136e93..f2777bf 100644 --- a/app/rust/.cargo/config.toml +++ b/app/rust/.cargo/config.toml @@ -19,6 +19,8 @@ rustflags = [ "link-arg=-Tlink.ld", "-C", "inline-threshold=0", + "-C", + "panic=abort", # Add this line to disable unwinding ] @@ -28,4 +30,6 @@ rustflags = [ "link-arg=-Wl,--gc-sections", "-C", "link-arg=-Wl,--as-needed", + "-C", + "panic=abort", # Add this line to disable unwinding ] diff --git a/app/rust/Cargo.lock b/app/rust/Cargo.lock index c75a3b3..31adbd8 100644 --- a/app/rust/Cargo.lock +++ b/app/rust/Cargo.lock @@ -257,12 +257,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - [[package]] name = "inout" version = "0.1.3" @@ -444,7 +438,6 @@ dependencies = [ "f4jumble", "getrandom 0.1.16", "hex", - "hex-literal", "no-std-compat", "nom", "panic-halt", diff --git a/app/rust/Cargo.toml b/app/rust/Cargo.toml index 8189ade..baea20d 100644 --- a/app/rust/Cargo.toml +++ b/app/rust/Cargo.toml @@ -33,7 +33,6 @@ bech32 = { version = "0.11.0", default-features = false } chacha20poly1305 = { version = "0.10.1", default-features = false } [dev-dependencies] -hex-literal = "0.4.1" hex = "0.4.2" no-std-compat = { version = "0.4.1", features = ["std"] } blake2b_simd = { version = "1.0.2", default-features = false } @@ -57,8 +56,11 @@ overflow-checks = false strip = true [profile.dev] +lto = false panic = "abort" [features] clippy = [] derive-debug = [] +# use when compiling this crate as a lib for the cpp_tests suite +cpp_tests = [] diff --git a/app/rust/src/ffi/c_api.rs b/app/rust/src/ffi/c_api.rs index e6203e0..170aae2 100644 --- a/app/rust/src/ffi/c_api.rs +++ b/app/rust/src/ffi/c_api.rs @@ -1,26 +1,62 @@ -use crate::constants::FVK_LEN; -use crate::keys::{fvk::FullViewingKey, nk::NullifierKey}; +use crate::keys::fvk::FullViewingKey; use crate::zxerror::ZxErr; -use decaf377::Fq; -use decaf377_rdsa::{SpendAuth, VerificationKey}; + +#[cfg(all( + not(test), + not(feature = "clippy"), + not(feature = "fuzzing"), + not(feature = "cpp_tests") +))] extern "C" { pub fn crypto_getFvkBytes(fvk: *mut u8, len: u16) -> ZxErr; } +#[cfg(all( + not(test), + not(feature = "clippy"), + not(feature = "fuzzing"), + not(feature = "cpp_tests") +))] pub fn c_fvk_bytes() -> Result { + use crate::constants::FVK_LEN; + use crate::keys::nk::NullifierKey; + use decaf377::Fq; + use decaf377_rdsa::{SpendAuth, VerificationKey}; + unsafe { let mut fvk_bytes = [0u8; FVK_LEN]; let err = crypto_getFvkBytes(fvk_bytes.as_mut_ptr(), fvk_bytes.len() as u16); - let ak_bytes: [u8; 32] = fvk_bytes[0..32].try_into().unwrap(); - let nk_bytes: [u8; 32] = fvk_bytes[32..64].try_into().unwrap(); - let ak = VerificationKey::::try_from(ak_bytes.as_ref()).unwrap(); + let ak_bytes: [u8; 32] = fvk_bytes[0..32] + .try_into() + .map_err(|_| ZxErr::InvalidCryptoSettings)?; + let nk_bytes: [u8; 32] = fvk_bytes[32..64] + .try_into() + .map_err(|_| ZxErr::InvalidCryptoSettings)?; + let ak = VerificationKey::::try_from(ak_bytes.as_ref()) + .map_err(|_| ZxErr::InvalidCryptoSettings)?; let nk = NullifierKey(Fq::from_le_bytes_mod_order(nk_bytes.as_ref())); - let fvk = FullViewingKey::from_components(ak, nk).unwrap(); + let fvk = + FullViewingKey::from_components(ak, nk).map_err(|_| ZxErr::InvalidCryptoSettings)?; match err { - ZxErr::Ok => Ok(FullViewingKey::from(fvk)), + ZxErr::Ok => Ok(fvk), _ => Err(err), } } } + +#[cfg(any(test, feature = "clippy", feature = "fuzzing", feature = "cpp_tests"))] +pub fn c_fvk_bytes() -> Result { + use crate::keys::spend_key::SpendKeyBytes; + + const SK_BYTES_RAW: [u8; 32] = [ + 0xa1, 0xff, 0xba, 0x0c, 0x37, 0x93, 0x1f, 0x0a, 0x62, 0x61, 0x37, 0x52, 0x0d, 0xa6, 0x50, + 0x63, 0x2d, 0x35, 0x85, 0x3b, 0xf5, 0x91, 0xb3, 0x6b, 0xb4, 0x28, 0x63, 0x0a, 0x4d, 0x87, + 0xc4, 0xdc, + ]; + + let sk = SpendKeyBytes::from(SK_BYTES_RAW); + + FullViewingKey::derive_from(&sk).map_err(|_| ZxErr::InvalidCryptoSettings) +} diff --git a/app/rust/src/keys/fvk.rs b/app/rust/src/keys/fvk.rs index 0e27aad..005ca0a 100644 --- a/app/rust/src/keys/fvk.rs +++ b/app/rust/src/keys/fvk.rs @@ -24,7 +24,7 @@ pub struct FullViewingKey { impl FullViewingKey { pub const ACCOUNT_ID_DOMAIN_SEP: &'static [u8] = b"Penumbra_HashFVK"; - fn derive_from(spk: &SpendKeyBytes) -> Result { + pub(crate) fn derive_from(spk: &SpendKeyBytes) -> Result { crate::zlog("FullViewingKey::derive_from\x00"); let ak = spk.verification_key()?; let nk = spk.nullifier_key()?; diff --git a/app/rust/src/lib.rs b/app/rust/src/lib.rs index 0d7e4ee..27a1a3d 100644 --- a/app/rust/src/lib.rs +++ b/app/rust/src/lib.rs @@ -20,9 +20,6 @@ extern crate no_std_compat as std; -#[cfg(test)] -extern crate hex_literal; - use arrayref as _; use educe as _; use poseidon377 as _; @@ -43,15 +40,24 @@ pub(crate) use utils::prf::{expand_fq, expand_fr}; fn debug(_msg: &str) {} -#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))] +// for cpp_tests we need to define the panic handler +// the remaining features does not need as dev-dependencies +// are used and their include a handler from std +#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing"),))] use core::panic::PanicInfo; -#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing")))] +#[cfg(all(not(test), not(feature = "clippy"), not(feature = "fuzzing"),))] #[panic_handler] fn panic(_info: &PanicInfo) -> ! { loop {} } +#[cfg(all( + not(test), + not(feature = "clippy"), + not(feature = "fuzzing"), + not(feature = "cpp_tests") +))] extern "C" { fn check_app_canary(); fn pic(link_address: u32) -> u32; @@ -60,24 +66,39 @@ extern "C" { } pub(crate) fn canary() { - #[cfg(not(any(test, fuzzing)))] + #[cfg(all( + not(test), + not(feature = "clippy"), + not(feature = "fuzzing"), + not(feature = "cpp_tests") + ))] unsafe { check_app_canary(); } } -#[cfg(not(any(test, fuzzing)))] +#[cfg(all( + not(test), + not(feature = "clippy"), + not(feature = "fuzzing"), + not(feature = "cpp_tests") +))] pub fn is_expert_mode() -> bool { unsafe { app_mode_expert() > 0 } } -#[cfg(any(test, feature = "fuzzing"))] +#[cfg(any(test, feature = "clippy", feature = "fuzzing", feature = "cpp_tests"))] pub fn is_expert_mode() -> bool { true } pub fn zlog(_msg: &str) { - #[cfg(not(any(test, fuzzing)))] + #[cfg(all( + not(test), + not(feature = "clippy"), + not(feature = "fuzzing"), + not(feature = "cpp_tests") + ))] unsafe { zemu_log_stack(_msg.as_bytes().as_ptr()); }