#![allow(unsafe_code, clippy::missing_safety_doc)]
use i2pd_sys::*;
use std::ffi::CString;
const SIG_TYPE_EDDSA_ED25519: i32 = 7;
const CRYPTO_TYPE_ECIES_X25519_AEAD: i32 = 4;
#[test]
fn local_destination_and_key_lifecycle() {
unsafe {
let app_name = CString::new("tachyon-i2pd-local-lifecycle-test").unwrap();
i2pd_init(app_name.as_ptr());
i2pd_start();
let transient = i2pd_create_transient_destination();
assert!(!transient.is_null(), "failed to create transient destination");
let transient_addr = i2pd_destination_b32_address(transient);
assert!(!transient_addr.is_null());
let transient_addr_str = std::ffi::CStr::from_ptr(transient_addr).to_str().unwrap().to_owned();
assert!(
transient_addr_str.ends_with(".b32.i2p"),
"unexpected address format: {transient_addr_str}"
);
assert_eq!(
transient_addr_str.len(),
52 + ".b32.i2p".len(),
"b32 address has unexpected length: {transient_addr_str}"
);
i2pd_free_string(transient_addr);
let mut transient_hash = [0u8; 32];
assert_eq!(i2pd_destination_ident_hash(transient, transient_hash.as_mut_ptr()), 1);
assert_ne!(transient_hash, [0u8; 32], "ident hash should not be all-zero");
i2pd_destroy_destination(transient);
let mut keys_buf: *mut u8 = std::ptr::null_mut();
let mut keys_len: usize = 0;
assert_eq!(
i2pd_generate_keys(
SIG_TYPE_EDDSA_ED25519,
CRYPTO_TYPE_ECIES_X25519_AEAD,
&mut keys_buf,
&mut keys_len,
),
1,
"key generation failed"
);
assert!(!keys_buf.is_null());
assert!(keys_len > 0);
let keys_bytes = std::slice::from_raw_parts(keys_buf, keys_len).to_vec();
let dest_a = i2pd_create_persistent_destination(keys_bytes.as_ptr(), keys_bytes.len(), 1, std::ptr::null());
assert!(!dest_a.is_null(), "failed to create persistent destination from generated keys");
let addr_a_ptr = i2pd_destination_b32_address(dest_a);
assert!(!addr_a_ptr.is_null());
let addr_a = std::ffi::CStr::from_ptr(addr_a_ptr).to_str().unwrap().to_owned();
i2pd_free_string(addr_a_ptr);
i2pd_destroy_destination(dest_a);
let dest_b = i2pd_create_persistent_destination(keys_bytes.as_ptr(), keys_bytes.len(), 1, std::ptr::null());
assert!(!dest_b.is_null());
let addr_b_ptr = i2pd_destination_b32_address(dest_b);
let addr_b = std::ffi::CStr::from_ptr(addr_b_ptr).to_str().unwrap().to_owned();
i2pd_free_string(addr_b_ptr);
i2pd_destroy_destination(dest_b);
assert_eq!(addr_a, addr_b, "same keys must produce the same b32 address");
i2pd_free_buffer(keys_buf);
let mut buf2: *mut u8 = std::ptr::null_mut();
let mut len2: usize = 0;
assert_eq!(
i2pd_generate_keys(SIG_TYPE_EDDSA_ED25519, CRYPTO_TYPE_ECIES_X25519_AEAD, &mut buf2, &mut len2),
1
);
let keys2_bytes = std::slice::from_raw_parts(buf2, len2).to_vec();
i2pd_free_buffer(buf2);
assert_ne!(keys_bytes, keys2_bytes, "two independent key generations produced identical keys");
i2pd_stop();
i2pd_terminate();
}
}