Files
fhe/examples/content-provenance/contracts/ContentProvenance.sol
T
Zach Kelling 961c42e204 feat: add FHE example apps for all Pars PIPs
- data-seal: Verifiable Data Integrity Seal (PIP-0010/LP-0535)
  FHE-encrypted tamper-proof sealing with Public/ZK/Private modes,
  batch sealing, homomorphic verification

- content-provenance: AI & Media Content Provenance (PIP-0011/LP-7110)
  Model manifests, output attestation via homomorphic comparison,
  media derivation DAGs

- encrypted-crdt: Encrypted CRDT (PIP-0013/LP-6500)
  LWW-Register with FHE values, OR-Set with tag-based add/remove,
  Lamport timestamp conflict resolution, deterministic merge

- shadow-governance: Shadow Government Protocol (PIP-7010)
  Anonymous ministries, encrypted voting with homomorphic tallying,
  nullifier-based anti-fraud, quorum enforcement

Each example includes Solidity contracts, Hardhat tests, CLI tasks,
and README linking to corresponding PIP and LP specifications.
2026-02-13 14:16:46 -08:00

187 lines
7.0 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
import "@luxfhe/luxfhe-contracts/FHE.sol";
/// @title ContentProvenance - AI & Media Content Provenance
/// @notice Tracks provenance of AI models, outputs, and media with FHE privacy
/// @dev Implements PIP-0011 / LP-7110: Model sealing, output attestation, media auth
contract ContentProvenance {
/// @notice Content types
enum ContentType {
AIModel, // Neural network model weights/architecture
AIOutput, // Generated content from a model
MediaCapture, // Point-of-capture media (photo, video, audio)
MediaEdit, // Edited derivative of existing media
Document // Text document
}
/// @notice A registered content item
struct ContentRecord {
bytes32 contentHash; // SHA-256 of content
ContentType contentType; // Type of content
address creator; // Who registered it
uint256 timestamp; // When registered
uint256 parentId; // 0 if original, else parent record ID
euint32 encryptedModelId; // FHE-encrypted model identifier (for AI outputs)
bool exists;
}
/// @notice Model manifest for AI provenance
struct ModelManifest {
bytes32 weightsHash; // Hash of model weights
bytes32 architectureHash; // Hash of architecture spec
bytes32 trainingDataHash; // Hash of training dataset description
address registrant; // Who registered the model
uint256 timestamp;
euint32 encryptedVersion; // FHE-encrypted version (IP protection)
}
/// @notice All content records
mapping(uint256 => ContentRecord) public records;
uint256 public recordCount;
/// @notice Model manifests
mapping(uint256 => ModelManifest) public models;
uint256 public modelCount;
/// @notice Provenance chain: contentId => child IDs
mapping(uint256 => uint256[]) public derivations;
/// @notice Attestation results
mapping(uint256 => euint32) private attestationResults;
event ContentRegistered(uint256 indexed id, ContentType contentType, address indexed creator, bytes32 contentHash);
event ModelRegistered(uint256 indexed modelId, address indexed registrant, bytes32 weightsHash);
event OutputAttested(uint256 indexed outputId, uint256 indexed modelId);
event DerivationRecorded(uint256 indexed parentId, uint256 indexed childId);
/// @notice Register an AI model manifest
/// @param weightsHash Hash of model weights
/// @param architectureHash Hash of architecture
/// @param trainingDataHash Hash of training data description
/// @param encryptedVersion FHE-encrypted version number (protects IP)
/// @return modelId The registered model ID
function registerModel(
bytes32 weightsHash,
bytes32 architectureHash,
bytes32 trainingDataHash,
inEuint32 calldata encryptedVersion
) external returns (uint256 modelId) {
modelId = modelCount++;
euint32 version = FHE.asEuint32(encryptedVersion);
FHE.allowThis(version);
FHE.allow(version, msg.sender);
models[modelId] = ModelManifest({
weightsHash: weightsHash,
architectureHash: architectureHash,
trainingDataHash: trainingDataHash,
registrant: msg.sender,
timestamp: block.timestamp,
encryptedVersion: version
});
emit ModelRegistered(modelId, msg.sender, weightsHash);
}
/// @notice Register content (media, document, or AI output)
/// @param contentHash Hash of the content
/// @param contentType Type of content being registered
/// @param parentId Parent content ID (0 for originals)
/// @param encryptedModelId FHE-encrypted model ID (for AI outputs)
/// @return contentId The registered content ID
function registerContent(
bytes32 contentHash,
ContentType contentType,
uint256 parentId,
inEuint32 calldata encryptedModelId
) external returns (uint256 contentId) {
contentId = recordCount++;
euint32 modelId = FHE.asEuint32(encryptedModelId);
FHE.allowThis(modelId);
FHE.allow(modelId, msg.sender);
records[contentId] = ContentRecord({
contentHash: contentHash,
contentType: contentType,
creator: msg.sender,
timestamp: block.timestamp,
parentId: parentId,
encryptedModelId: modelId,
exists: true
});
// Track derivation chain
if (parentId > 0 && records[parentId].exists) {
derivations[parentId].push(contentId);
emit DerivationRecorded(parentId, contentId);
}
emit ContentRegistered(contentId, contentType, msg.sender, contentHash);
}
/// @notice Attest that an AI output was produced by a specific model
/// @dev Homomorphic comparison of encrypted model IDs
/// @param outputId The content record to attest
/// @param claimedModelId FHE-encrypted model ID to verify against
function attestOutput(
uint256 outputId,
inEuint32 calldata claimedModelId
) external {
require(records[outputId].exists, "Content not found");
euint32 claimed = FHE.asEuint32(claimedModelId);
// Homomorphic equality check
ebool isMatch = FHE.eq(records[outputId].encryptedModelId, claimed);
euint32 result = FHE.select(isMatch, FHE.asEuint32(1), FHE.asEuint32(0));
FHE.allowThis(result);
FHE.allow(result, msg.sender);
attestationResults[outputId] = result;
FHE.decrypt(result);
emit OutputAttested(outputId, outputId);
}
/// @notice Get attestation result
function getAttestationResult(uint256 outputId) external view returns (bool attested, bool ready) {
euint32 result = attestationResults[outputId];
(uint256 value, bool decrypted) = FHE.getDecryptResultSafe(result);
return (value == 1, decrypted);
}
/// @notice Get content record metadata
function getRecord(uint256 contentId) external view returns (
bytes32 contentHash,
ContentType contentType,
address creator,
uint256 timestamp,
uint256 parentId
) {
ContentRecord storage r = records[contentId];
require(r.exists, "Not found");
return (r.contentHash, r.contentType, r.creator, r.timestamp, r.parentId);
}
/// @notice Get the full derivation chain for content
function getDerivations(uint256 contentId) external view returns (uint256[] memory) {
return derivations[contentId];
}
/// @notice Get model manifest metadata
function getModel(uint256 modelId) external view returns (
bytes32 weightsHash,
bytes32 architectureHash,
bytes32 trainingDataHash,
address registrant,
uint256 timestamp
) {
ModelManifest storage m = models[modelId];
return (m.weightsHash, m.architectureHash, m.trainingDataHash, m.registrant, m.timestamp);
}
}