Files
2025-12-31 21:13:02 -08:00

97 lines
4.5 KiB
Solidity

// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity >=0.8.13 <0.9.0;
import { euint32, ebool, FHE } from "@luxfi/contracts/fhe/FHE.sol";
import "./BytesLib.sol";
/// @title Encrypted Address Library
/// @notice Provides methods for creating and managing addresses encrypted with FHE (Fully Homomorphic Encryption)
/// @dev Assumes the existence of an FHE library that implements fully homomorphic encryption functions
/// @dev A representation of an encrypted address using Fully Homomorphic Encryption.
/// It consists of 5 encrypted 32-bit unsigned integers (`euint32`).
struct Eaddress {
euint32[5] values;
}
library ConfAddress {
/// @notice Encrypts a plaintext Ethereum address into its encrypted representation (`eaddress`).
/// @dev Iterates over 5 chunks of the address, applying a bitmask to each, then encrypting with `FHE`.
/// @param addr The plain Ethereum address to encrypt
/// @return eaddr The encrypted representation of the address
function toEaddress(address payable addr) internal returns (Eaddress memory) {
uint160 addrValue = uint160(address(addr));
/// @dev A bitmask constant for selecting specific 32-bit chunks from a 160-bit Ethereum address.
/// It has the first 32 bits set to 1, and the remaining bits set to 0.
uint160 MASK =
uint160(uint256(0x000000000000000000000000FFFFFFFF00000000000000000000000000000000));
Eaddress memory eaddr;
for (uint i = 0; i < 5; i++) {
uint160 currentChunkOffset = uint160(i * 32);
uint160 mask = MASK >> currentChunkOffset; // Mask the correct chunk based on i
uint32 chunk = uint32((addrValue & mask) >> (128 - currentChunkOffset));
eaddr.values[i] = FHE.asEuint32(chunk);
}
return eaddr;
}
/// @notice Placeholder for async decryption of an encrypted address.
/// @dev In production, implement IAsyncFHEReceiver for Gateway callback pattern.
/// This simplified version returns address(0) as decryption requires async flow.
/// @param eaddr The encrypted address (unused in simplified version)
/// @return address(0) - implement Gateway callback for actual decryption
function unsafeToAddress(Eaddress memory eaddr) internal pure returns (address) {
// Suppress unused parameter warning
eaddr;
// Note: Actual decryption requires Gateway async callback pattern
// In production, request decryption and handle result in callback
return address(0);
}
/// @notice Re-encrypts the encrypted values within an `eaddress`.
/// @dev The re-encryption is done to change the encrypted representation without
/// altering the underlying plaintext address, which can be useful for obfuscation purposes in storage.
/// @param eaddr The encrypted address to re-encrypt
/// @param ezero An encrypted zero value that triggers the re-encryption
function resestEaddress(Eaddress memory eaddr, euint32 ezero) internal returns (Eaddress memory) {
for (uint i = 0; i < 5; i++) {
// Adding zero will practically reencrypt the value without it being changed
eaddr.values[i] = FHE.add(eaddr.values[i], ezero);
}
return eaddr;
}
/// @notice Determines if an encrypted address is equal to a given plaintext Ethereum address.
/// @dev This operation encrypts the plaintext address and compares the encrypted representations.
/// @param lhs The encrypted address to compare
/// @param addr The plaintext Ethereum address to compare against
/// @return res A boolean indicating if the encrypted and plaintext addresses are equal
function equals(Eaddress storage lhs, address payable addr) internal returns (ebool) {
Eaddress memory rhs = toEaddress(addr);
ebool res = FHE.eq(lhs.values[0], rhs.values[0]);
for (uint i = 1; i < 5; i++) {
res = FHE.and(res, FHE.eq(lhs.values[i], rhs.values[i]));
}
return res;
}
function conditionalUpdate(
ebool condition,
Eaddress memory eaddr,
Eaddress memory newEaddr
) internal returns (Eaddress memory) {
for (uint i = 0; i < 5; i++) {
// Even if condition is false the ENCRYPTED value of eaddr.values[i] will be changed
// because the encryption is not deterministic
// so no one will know whether the highest bidder was changed or not
eaddr.values[i] = FHE.select(condition, newEaddr.values[i], eaddr.values[i]);
}
return eaddr;
}
}