extern crate alloc;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone)]
pub struct LedgerPayload {
pub context_tag: [u8; 32],
pub encrypted_amount: Vec<u8>,
pub encrypted_target: Vec<u8>,
}
#[deprecated(
since = "0.2.0",
note = "renamed to `LedgerPayload` — this is the confidential internal ledger's payload, not an on-chain contract's (SAGP-PG-001 V-7)"
)]
pub type ContractPayload = LedgerPayload;
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm")]
use zeroize::Zeroize;
#[cfg(feature = "wasm")]
#[derive(Zeroize)]
#[zeroize(drop)]
pub struct SecretKeyContainer {
pub raw_key_bytes: Vec<u8>,
}
#[cfg(feature = "wasm")]
#[wasm_bindgen]
pub struct AethelVaultClient {
client_key_bytes: Vec<u8>,
}
#[cfg(feature = "wasm")]
#[wasm_bindgen]
impl AethelVaultClient {
#[wasm_bindgen(constructor)]
pub fn new() -> Result<AethelVaultClient, JsError> {
Ok(AethelVaultClient {
client_key_bytes: Vec::new(),
})
}
pub fn from_key_bytes(key_bytes: &[u8]) -> AethelVaultClient {
AethelVaultClient {
client_key_bytes: key_bytes.to_vec(),
}
}
pub fn build_payload_from_ciphertexts(
&self,
context_tag: &[u8],
encrypted_amount: &[u8],
encrypted_target: &[u8],
) -> Result<Vec<u8>, JsError> {
if context_tag.len() != 32 {
return Err(JsError::new("Context tag must be exactly 32 bytes"));
}
let mut tag_bytes = [0u8; 32];
tag_bytes.copy_from_slice(context_tag);
let payload = LedgerPayload {
context_tag: tag_bytes,
encrypted_amount: encrypted_amount.to_vec(),
encrypted_target: encrypted_target.to_vec(),
};
bincode::serialize(&payload)
.map_err(|e| JsError::new(&alloc::format!("Payload assembly failed: {}", e)))
}
pub fn get_key_bytes(&self) -> Vec<u8> {
self.client_key_bytes.clone()
}
}
#[cfg(all(not(target_arch = "wasm32"), feature = "fhe-state"))]
use tfhe::{generate_keys, prelude::*, ClientKey, ConfigBuilder, FheUint64, PublicKey};
#[cfg(all(not(target_arch = "wasm32"), feature = "fhe-state"))]
pub struct NativeVaultClient {
pub client_key: ClientKey,
pub public_key: PublicKey,
pub server_key: tfhe::ServerKey,
}
#[cfg(all(not(target_arch = "wasm32"), feature = "fhe-state"))]
impl NativeVaultClient {
pub fn new() -> Self {
let config = ConfigBuilder::default().build();
let (client_key, server_key) = generate_keys(config);
let public_key = PublicKey::new(&client_key);
NativeVaultClient {
client_key,
public_key,
server_key,
}
}
pub fn encrypt_u64_balance(&self, amount: u64) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let ct = FheUint64::try_encrypt(amount, &self.client_key)?;
Ok(bincode::serialize(&ct)?)
}
pub fn decrypt_u64_balance(
&self,
encrypted_bytes: &[u8],
) -> Result<u64, Box<dyn std::error::Error>> {
let ct: FheUint64 = bincode::deserialize(encrypted_bytes)?;
Ok(ct.decrypt(&self.client_key))
}
pub fn export_server_key(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
Ok(bincode::serialize(&self.server_key)?)
}
pub fn build_payload(
&self,
context_tag: [u8; 32],
amount: u64,
target_account: u64,
) -> Result<LedgerPayload, Box<dyn std::error::Error>> {
let encrypted_amount = self.encrypt_u64_balance(amount)?;
let encrypted_target = self.encrypt_u64_balance(target_account)?;
Ok(LedgerPayload {
context_tag,
encrypted_amount,
encrypted_target,
})
}
}
#[cfg(all(not(target_arch = "wasm32"), feature = "fhe-state"))]
impl Default for NativeVaultClient {
fn default() -> Self {
Self::new()
}
}